From 0979ae6a4172dec06c74d4588f61e64bc48d78f3 Mon Sep 17 00:00:00 2001 From: ncpfs archive import Date: Tue, 28 Apr 2026 20:39:59 +0200 Subject: [PATCH] Import ncpfs 2.2.0 --- .downloads/ncpfs-2.2.0.tgz | Bin 0 -> 190475 bytes BUGS | 19 +- Changes | 127 +- FAQ | 19 +- Makefile | 33 +- Makeinit | 79 + README | 35 +- README.NDS | 18 + contrib/tknwmsg/nwmsg.c | 62 +- include/glibstub.h | 22 + include/ipxlib.h | 58 +- include/kernel/fs.h | 11 + include/kernel/if.h | 11 + include/kernel/ipx.h | 15 + include/kernel/ncp.h | 213 ++ include/kernel/ncp_fs.h | 110 + include/kernel/route.h | 12 + include/kernel/types.h | 40 + include/ncp.h | 9 +- include/ncplib.h | 262 +- include/ncpsign.h | 18 + include/ndslib.h | 35 + ipx-1.0/Makefile | 6 +- ipx-1.0/Samples/ipxrcv.c | 12 +- ipx-1.0/Samples/ipxsend.c | 12 +- ipx-1.0/Samples/rip.c | 21 +- ipx-1.0/Samples/sap.c | 24 +- {man => ipx-1.0}/ipx_configure.8 | 0 ipx-1.0/ipx_configure.c | 49 +- {man => ipx-1.0}/ipx_interface.8 | 0 ipx-1.0/ipx_interface.c | 136 +- {man => ipx-1.0}/ipx_internal_net.8 | 0 ipx-1.0/ipx_internal_net.c | 82 +- {man => ipx-1.0}/ipx_route.8 | 0 ipx-1.0/ipx_route.c | 83 +- ipxdump/Makefile | 2 +- ipxdump/ipxdump.c | 109 +- ipxdump/ipxparse.c | 272 +- ipxdump/ipxutil.c | 45 +- ipxdump/ipxutil.h | 2 +- lib-shared/Makefile | 28 + lib-static-su/Makefile | 17 + lib-static/Makefile | 17 + lib/Makefile | 57 +- lib/Makelib | 61 + lib/com_err/Makefile | 7 +- lib/com_err/com_err.c | 33 +- lib/com_err/compile_et | 2 +- lib/com_err/error_message.c | 25 +- lib/com_err/error_table.h | 6 +- lib/com_err/et_name.c | 5 +- lib/com_err/init_et.c | 9 +- lib/mpilib.c | 1881 ++++++++++ lib/mpilib.h | 468 +++ lib/ncplib.c | 3022 +++++++++++---- lib/ncplib_err.et | 14 +- lib/ncpsign.c | 103 + lib/ndscrypt.c | 297 ++ lib/ndscrypt.h | 47 + lib/ndslib.c | 1253 +++++++ lib/nwcrypt.c | 94 +- lib/platform.h | 218 ++ lib/usuals.h | 39 + man/Makefile | 18 +- man/nwmsg.8 | 33 + man/nwpurge.1 | 65 + man/pqrm.1 | 105 + man/pqstat.1 | 107 + man/pserver.1 | 3 + ncpfs-2.1.1.lsm => ncpfs-2.2.0.lsm | 18 +- ncpfs-nds-0.06.CHANGES | 96 + ncpfs-nds-0.06.README | 42 + patches/README | 13 +- patches/linux-2.1.26.diff | 35 - patches/linux-2.1.29.diff | 5281 --------------------------- patches/lockup-2.0.28.diff | 44 - patches/lockup-2.0.30.diff | 12 + sutil/Makefile | 26 +- sutil/ipxlib.h | 93 - sutil/ncplib.c | 1668 --------- sutil/ncplib.h | 280 -- sutil/ncpmount.c | 982 ++++- sutil/ncpmount.h | 76 + sutil/ncpumount.c | 70 +- sutil/nwcrypt.c | 198 - sutil/nwsfind.c | 68 +- util/Makefile | 40 +- util/ipx_probe | Bin 27138 -> 0 bytes util/ipx_probe.c | 653 ++-- util/ncopy.c | 308 +- util/ncptest.c | 98 +- util/nprint.c | 116 +- util/nsend.c | 34 +- util/nwauth.c | 40 +- util/nwbocreate.c | 54 +- util/nwbols.c | 33 +- util/nwboprops.c | 33 +- util/nwborm.c | 30 +- util/nwbpadd.c | 86 +- util/nwbpcreate.c | 60 +- util/nwbprm.c | 36 +- util/nwbpset.c | 95 +- util/nwbpvalues.c | 210 +- util/nwfsinfo.c | 38 +- util/nwfstime.c | 30 +- util/nwgrant.c | 36 +- util/nwmsg.c | 215 ++ util/nwpasswd.c | 57 +- util/nwpurge.c | 127 + util/nwrevoke.c | 33 +- util/nwrights.c | 55 +- util/nwtrustee.c | 48 +- util/nwuserlist.c | 49 +- util/nwvolinfo.c | 35 +- util/pqlist.c | 24 +- util/pqrm.c | 71 + util/pqstat.c | 188 + util/pserver.c | 176 +- util/slist.c | 30 +- 119 files changed, 12194 insertions(+), 10043 deletions(-) create mode 100644 .downloads/ncpfs-2.2.0.tgz create mode 100644 Makeinit create mode 100644 README.NDS create mode 100644 include/glibstub.h create mode 100644 include/kernel/fs.h create mode 100644 include/kernel/if.h create mode 100644 include/kernel/ipx.h create mode 100644 include/kernel/ncp.h create mode 100644 include/kernel/ncp_fs.h create mode 100644 include/kernel/route.h create mode 100644 include/kernel/types.h create mode 100644 include/ncpsign.h create mode 100644 include/ndslib.h rename {man => ipx-1.0}/ipx_configure.8 (100%) rename {man => ipx-1.0}/ipx_interface.8 (100%) rename {man => ipx-1.0}/ipx_internal_net.8 (100%) rename {man => ipx-1.0}/ipx_route.8 (100%) create mode 100644 lib-shared/Makefile create mode 100644 lib-static-su/Makefile create mode 100644 lib-static/Makefile create mode 100644 lib/Makelib create mode 100644 lib/mpilib.c create mode 100644 lib/mpilib.h create mode 100644 lib/ncpsign.c create mode 100644 lib/ndscrypt.c create mode 100644 lib/ndscrypt.h create mode 100644 lib/ndslib.c create mode 100644 lib/platform.h create mode 100644 lib/usuals.h create mode 100644 man/nwmsg.8 create mode 100644 man/nwpurge.1 create mode 100644 man/pqrm.1 create mode 100644 man/pqstat.1 rename ncpfs-2.1.1.lsm => ncpfs-2.2.0.lsm (50%) create mode 100644 ncpfs-nds-0.06.CHANGES create mode 100644 ncpfs-nds-0.06.README delete mode 100644 patches/linux-2.1.26.diff delete mode 100644 patches/linux-2.1.29.diff delete mode 100644 patches/lockup-2.0.28.diff create mode 100644 patches/lockup-2.0.30.diff delete mode 100644 sutil/ipxlib.h delete mode 100644 sutil/ncplib.c delete mode 100644 sutil/ncplib.h create mode 100644 sutil/ncpmount.h delete mode 100644 sutil/nwcrypt.c delete mode 100755 util/ipx_probe create mode 100644 util/nwmsg.c create mode 100644 util/nwpurge.c create mode 100644 util/pqrm.c create mode 100644 util/pqstat.c diff --git a/.downloads/ncpfs-2.2.0.tgz b/.downloads/ncpfs-2.2.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..5974da3beba8ddc37f3694d09ed8ee3dc309d80f GIT binary patch literal 190475 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%0D_wjDGeQ@0A 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 M0KXQC_W&Rb0H>yA9smFU literal 0 HcmV?d00001 diff --git a/BUGS b/BUGS index c0d8116..662fc84 100644 --- a/BUGS +++ b/BUGS @@ -13,9 +13,8 @@ down the complete ipx subsystem by deleting all ipx interfaces, unmounting all ncpfs volumes (in this order!) and restarting all again. -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! +This problem has been solved by Martin Stover (THANKS!!) +See patches/lockup-2.0.30.diff for the fix. ------------------------------------------------------------------------------- @@ -34,3 +33,17 @@ like Nov 25 16:09:08 lx01 kernel: alloc_skb called nonatomically from interrupt 0000002e These are a bit annoying, but completely harmless. + +------------------------------------------------------------------------------- + +Known bugs: + +- It returns error 255 during bindery login on one site... I do not know why. +- If GetNearsetServer returns invalid (nonexistant, downed) server, all + utilities gives up. VLM/Client32 in this situation tries randomly choosen + server after 30 secs timeout. You have to fix your routers at this time. + Sorry. +- NFS namespace does not work on Netware Storage Services volume... Sorry, + it is not my fault and I did not found any workaround (maybe that I have + workaround for NSS from NW5Beta3) + diff --git a/Changes b/Changes index 0fe1c47..8acb1fb 100644 --- a/Changes +++ b/Changes @@ -1,9 +1,130 @@ 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.10 -> ncpfs-2.1.1 -- Restructured the kernel part a bit, moved watchdog and message support - out of the kernel into ncpmount. +[Versions ncpfs-2.0.12.x are available at ftp://platan.vc.cvut.cz/pub/linux/ncpfs] + +ncpfs-2.0.12.10 -> ncpfs-2.2.0 +- VANA: minor cleanup + +ncpfs-2.0.12.9 -> ncpfs-2.0.12.10 +- VANA: you can now access NDS server without replica of its conteiner + (TODO: access to server if server has R/W replica of your account but + does not have replica of itself) +- VANA: Alpha still no go :-( + +ncpfs-2.0.12.8 -> ncpfs-2.0.12.9 +- Eloy A. Paris: Fixes in library code + +ncpfs-2.0.12.7 -> ncpfs-2.0.12.8 +- VANA: bugfix, now it works again without ipxripd +- VANA: still cleaning up, ncp_open() and NDS byte ordering + +ncpfs-2.0.12.6 -> ncpfs-2.0.12.7 +- VANA: bugfixes, nwpurge + +ncpfs-2.0.12.5 -> ncpfs-2.0.12.6 +- VANA: ncpmount supports NCP over IP (no incoming broadcast at this time) + +ncpfs-2.0.12.4 -> ncpfs-2.0.12.5 +- Eloy A. Paris: Makefile bugfix + +ncpfs-2.0.12.3 -> ncpfs-2.0.12.4 +- VANA: Bugfixes +- VANA: Alpha stage of native NCP over IP support (no kernel at this time) + +ncpfs-2.0.12.2 -> ncpfs-2.0.12.3 +- VANA: Major makefile changes, compile warning cleanup + +ncpfs-2.0.12.1 -> ncpfs-2.0.12.2 +- Eloy A. Paris : Makefile cleanup +- VANA: More merging sutil/ncplib.c and lib/ncplib.c, not fully functional yet + +ncpfs-2.0.12 -> ncpfs-2.0.12.1 +- Dave, VANA: Bindery logins for all utilities (-b) +- VANA: Specify signature level for ncpmount (-i number) +- VANA: Start of merging sutil/*lib* with lib/*lib* + +ncpfs-2.0.11.19 -> ncpfs-2.0.12 +- Polished for release 2.0.12 +- Dave: pserver fixes, including addition of %d flag. + +ncpfs-2.0.11.18 -> ncpfs-2.0.11.19 +- Dave, VANA: new userspace utilities - pqstat and pqrm + +ncpfs-2.0.11.17 -> ncpfs-2.0.11.18 (no userspace change) +- Dave: getwd() did not work on 2.1.x +- VANA: Volumes are now always listed lowercased on 2.1.x + +ncpfs-2.0.11.16 -> ncpfs-2.0.11.17 +- David Woodhouse : Patch to pserver, + ncp_get_broadcast_message +- VANA & Dave: Cleanup for glibc, I hope that complete (xcpt. few warnings + about long int vs. u_int32_t) + +ncpfs-2.0.11.15 -> ncpfs-2.0.11.16 +- VANA: Removed symlink latest from archive :-) +- VANA: Added ncp_send_broadcast2 + +ncpfs-2.0.11.14 -> ncpfs-2.0.11.15 +- VANA: Fixed bug: wrong completion code returned when login to server without + r/w replica of logged-in user +- VANA: It is possible to disable NFS and/or OS2 namespace support in mount + +ncpfs-2.0.11.13 -> ncpfs-2.0.11.14 +- VANA: One source for 2.0 and 2.1 kernels +- Chirstian Groessler : Added strong mounts + +ncpfs-2.0.11.12 -> ncpfs-2.0.11.13 +- Arne: Signatures added to ncpfs-nds-0.06 +- VANA: Synchronized sources with Arne + +ncpfs-2.0.11.11 -> ncpfs-2.0.11.12 +- VANA: Fixed compilation error if compiled against kernel without signatures + even if SIGNATURES = 0 set + +ncpfs-2.0.11.10 -> ncpfs-2.0.11.11 +- VANA: Fixed segfault on invalid user name in NDS mode +- VANA: Added locking features (through ncpfs-specific ioctl(2)) + +ncpfs-2.0.11.9 -> ncpfs-2.0.11.10 +- VANA: Synchronized with nds-patches-0.05 from Arne de Bruijn + +ncpfs-2.0.11.8 -> ncpfs-2.0.11.9 +- VANA: Added call to lock connection (dropped in 2.0.11.7, sorry) + +ncpfs-2.0.11.7 -> ncpfs-2.0.11.8 +- VANA: Can be correctly compiled without signatures support in kernel (I hope) +- VANA: Fix in kernel in setting task number + +ncpfs-2.0.11.6 -> ncpfs-2.0.11.7 +- VANA: Codebase synchronized with Arne de Bruijn +- ARNE: Gracelogins on NDS +- VANA: Removed some (one) compilation warnings + +ncpfs-2.0.11.5 -> ncpfs-2.0.11.6 +- VANA: Support for NDS login accross servers + +ncpfs-2.0.11.4 -> ncpfs-2.0.11.5 +- VANA: Cleanup in ndscrypt +- VANA: Bugfix: empty password for NDS login is now allowed & works + +ncpfs-2.0.11.3 -> ncpfs-2.0.11.4 +- Enabled some buffer cleaning +- Added parameter "-b" to ncpmount for bindery login to NDS server + +ncpfs-2.0.11.2 -> ncpfs-2.0.11.3 +- Added NDS support by Arne de Bruijn ; small fixes in code; + moved sections to do same things as DOS login does. + +ncpfs-2.0.11.1 -> ncpfs-2.0.11.2 +- VANA: Fixed that some error conditions in LOGIN should start packet signatures + +ncpfs-2.0.11 -> ncpfs-2.0.11.1 +- VANA: Added packet signatures by Arne de Bruijn + +ncpfs-2.0.10 -> ncpfs-2.0.11 +- Added Martin's patch to Linux 2.0.30 to get rid of the lockups. + MANY thanks to Martin Stover! ncpfs-2.0.9 -> ncpfs-2.0.10 - Made nwtrustee hopefully work ;-) diff --git a/FAQ b/FAQ index 8a3d947..f08ec41 100644 --- a/FAQ +++ b/FAQ @@ -35,6 +35,9 @@ 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. +Note: ncpfs, as of 2.0.12, and kernel 2.1.89, does now support packet +signatures. + ------------------------------------------------------------------------------- Q: When I re-export ncpfs-mounted directories via nfs, I get messages like @@ -54,14 +57,10 @@ When you want to export a directory via NFS, you have to do two things: ------------------------------------------------------------------------------- -Q: When I compile ncpfs, I get a message like the following: +Q: I cannot login into server with these utilities. It was possible with an +older version. -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. +A: You are probably connecting into Netware 4.x or IntraNetware. If you want a +temporary workaround, add the option "-b" to the ncpmount commandline. +For the future you should determine your Directory Services user name and +use that instead of your bindery name. diff --git a/Makefile b/Makefile index 3aad401..38410a0 100644 --- a/Makefile +++ b/Makefile @@ -2,12 +2,6 @@ # Makefile for the linux ncp-filesystem routines. # -VERSION = 2.1.1 - -# If you are using kerneld to autoload ncp support, -# uncomment this (kerneld is in linux since about 1.3.57): -KERNELD = -DHAVE_KERNELD - # If your system is ELF, either also do a 'make install', or append the util/ # directory where the dynamic library resides to the environment # variable LD_LIBRARY_PATH @@ -15,22 +9,23 @@ HAVE_ELF=$(shell file `whereis gcc|cut -d ' ' -f 2`| \ grep ELF >/dev/null && echo -n yes ) TOPDIR = $(shell pwd) -BINDIR = /usr/bin -SBINDIR = /sbin -SUBDIRS = lib sutil util ipx-1.0 man +include ./Makeinit -KVERSION=$(shell uname -r | cut -b1-3) +EXECSUBDIRS = lib-static-su sutil util ipx-1.0 +SUBDIRS := $(EXECSUBDIRS) lib-shared lib-static man +INSTALL_SUBDIRS := util sutil man ipx-1.0 +ifeq ($(HAVE_ELF),yes) +EXECSUBDIRS := lib-shared $(EXECSUBDIRS) +INSTALL_SUBDIRS := lib-shared $(INSTALL_SUBDIRS) +else +EXECSUBDIRS := lib-static $(EXECSUBDIRS) +INSTALL_SUBDIRS := lib-static $(INSTALL_SUBDIRS) +endif -INCLUDES=-I$(TOPDIR)/include - -COPT = -O2 -COPT += -g -CFLAGS = $(COPT) -Wall $(INCLUDES) $(KERNELD) -DNCPFS_VERSION=\"$(VERSION)\" - -export INCLUDES BINDIR SBINDIR KERNELD VERSION HAVE_ELF CFLAGS +export INCLUDES VERSION HAVE_ELF CFLAGS all: - for i in $(SUBDIRS); do make -C $$i all; done + set -e; for i in $(EXECSUBDIRS); do make -C $$i all; done @if [ "$(HAVE_ELF)" = yes ] ;\ then \ echo ; echo ; echo ;\ @@ -47,7 +42,7 @@ dep: for i in $(SUBDIRS); do make -C $$i dep; done install: - for i in $(SUBDIRS); do make -C $$i install; done + for i in $(INSTALL_SUBDIRS); do make -C $$i install; done clean_me: rm -f `find -name '*.out'` diff --git a/Makeinit b/Makeinit new file mode 100644 index 0000000..3f80e10 --- /dev/null +++ b/Makeinit @@ -0,0 +1,79 @@ +VERSION = 2.2.0 + +# If you want to include NDS support for ncpmount uncomment this: +# WARNING! NDS support is very beta, uncomment only if you are testing +# because anything can happen (like crashing the linux box or nw server). +NDS_SUPPORT = 1 + +# If you want to include packet signature support uncomment this: +# WARNING! packet signature support is in beta stage, uncomment only when you +# know what you are doing, anything can happen (like crashing the linux box or +# netware server). +# When enabling, make sure you have applied the kernel patches too, +# otherwise the packet signatures won't work. +SIGNATURES = 1 + +# If you want to eat only one NDS connection. Does not work at this time. +# (waiting for Novell...) +NDS_PRIVATEKEY = 1 + +# If you want native IP support, uncomment CONFIG_NATIVEIP +# Do not forget that it is VERY ALPHA code, with almost no support +# Enable only if you are interested in NCP over IP and you want help +# me. -A ip.address is your friend. At this time you have to silently +# ignore Login to server XXXX as YYYY - think that XXXX is ip.address and +# not one taken from .nwclient. Also, if you have not .nwclient, you have +# to add -S DUMMY on commandline. +CONFIG_NATIVE_IP = 1 + +# Include code for Linux2.0.x +MOUNT2 = 1 +# Include code for Linux2.1.x +MOUNT3 = 1 + +# ######################################################## +BINDIR = /usr/bin +SBINDIR = /sbin +LIBSODIR = /lib +LIBADIR = /usr/lib +MANDIR = /usr/local/man + +CC = gcc + +COPT = -O2 +CWARN = -Wall +# CWARN = -Wall -Wstrict-prototypes -Wpointer-arith -Wcast-qual -Waggregate-return -Wnested-externs -Winline -Wbad-function-cast -W #-Werror #-Wwrite-strings -Wtraditional -Wshadow +# ######################################################## + +ifdef SIGNATURES +CFLAGS_DEFINES += -DSIGNATURES +endif +ifdef NDS_SUPPORT +CFLAGS_DEFINES += -DNDS_SUPPORT +endif +ifdef CONFIG_NATIVE_IP +CFLAGS_DEFINES += -DCONFIG_NATIVE_IP +endif +ifdef MOUNT2 +CFLAGS_DEFINES += -DMOUNT2 +endif +ifdef MOUNT3 +CFLAGS_DEFINES += -DMOUNT3 +endif +CFLAGS_DEFINES += -DNCPFS_VERSION=\"$(VERSION)\" +CFLAGS_OPTIONS += $(COPT) +CFLAGS_OPTIONS += $(CWARN) + +CCFLAGS = $(CFLAGS_DEFINES) $(CFLAGS_OPTIONS) -I../include + +# If your system is ELF, either also do a 'make install', or append the util/ +# 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 ) +#HAVE_ELF=yes + +TOPDIR = $(shell pwd) + +INCLUDES=-I$(TOPDIR)/include + diff --git a/README b/README index 47f5ab0..54d0cbf 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ -This is ncpfs, the user utilities that are needed to use the NCP kernel support -present in Linux since version 1.3.71. This version of ncpfs is only usable -with Linux 2.1.29 and later. To use it, please apply the patch contained in the -patches/ directory. +This is ncpfs, a free NetWare client filesystem for Linux. Besides +some little utilities it also contains nprint, which enables you to +print on NetWare print queues. The opposite side, pserver, is also +provided. ncpfs works with NetWare versions 3.x and following. It does NOT work with NetWare version 2.x. Some of the NetWare look-alikes, such as @@ -24,11 +24,25 @@ information. INSTALLATION -Before you start the installation of the user utilities, please make sure that -your kernel is 2.1.29 or later. If you are using 2.1.29, please apply the patch -contained in patches/linux-2.1.29.diff. You have to compile your kernel with -IPX and NCP support compiled in. But as you are using a development kernel, you -probably know what you're doing :-). +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. + +If you are not using 2.0.x kernels, you can comment out MOUNT2=1 line +in the Makeinit. +If you are not using 2.1.x kernels, you can comment out MOUNT3=1 line +in the Makeinit. + +If you are not using NDS access, you can comment out NDS_SUPPORT=1 in +the Makeinit. +If you are not using packet signatures, you can comment out SIGNATURES=1 +in the Makeinit. + +After you adapted your Makeinit, type 'make' and, as root, 'make install'. HELP @@ -110,9 +124,6 @@ limitation is the lack of uid, gid and permission information per file. You have to assign those values once for a complete mounted directory. -You will not be able to access servers that require packet -signatures. This seems to be one of Novell's bigger secrets :-(. - Have fun with ncpfs! Volker diff --git a/README.NDS b/README.NDS new file mode 100644 index 0000000..6ba5590 --- /dev/null +++ b/README.NDS @@ -0,0 +1,18 @@ +The NDS login code uses the RSA public key cryptosystem. Because of a patent +right on this algorithm (U.S. patent #4,405,829, issued 20 Sep 1983), you +are probably not allowed to use this code in the U.S.A. and Canada, and +possibly neither in other countries. Check this before you use NDS logins! + +The mpilib.c, mpilib.h, platform.h, and usuals.h in the lib/ directory are +taken from the PGP 2.3 source distribution (Copyright 1986-92 by Philip +Zimmermann), which is distributed under the GPL, as stated below. + +Excerpt from pgpdoc2.txt (contained in pgp23src.zip): +"All the source code for PGP is available for free under the "Copyleft" +General Public License from the Free Software Foundation (FSF)." + +For more details on the RSA patent see the pgp23src archive, or more recent +PGP packages. + +Arne de Bruijn +arne@knoware.nl diff --git a/contrib/tknwmsg/nwmsg.c b/contrib/tknwmsg/nwmsg.c index 51c8df9..6f0c200 100644 --- a/contrib/tknwmsg/nwmsg.c +++ b/contrib/tknwmsg/nwmsg.c @@ -27,7 +27,8 @@ static int search_utmp(char *user, char *tty); static char *progname; -void main(int argc, char *argv[]) +void +main(int argc, char *argv[]) { struct ncp_conn *conn; char message[256]; @@ -50,23 +51,27 @@ void main(int argc, char *argv[]) openlog("nwmsg", LOG_PID, LOG_LPR); - if (argc != 2) { + if (argc != 2) + { fprintf(stderr, "usage: %s mount-point\n", progname); exit(1); } mount_point = argv[1]; - if ((conn = ncp_open_mount(mount_point, &err)) == NULL) { + if ((conn = ncp_open_mount(mount_point, &err)) == NULL) + { com_err(progname, err, "in ncp_open_mount"); exit(1); } - if (ncp_get_broadcast_message(conn, message) != 0) { + if (ncp_get_broadcast_message(conn, message) != 0) + { fprintf(stderr, "%s: could not get broadcast message\n", progname); ncp_close(conn); exit(1); } - if (strlen(message) == 0) { + if (strlen(message) == 0) + { syslog(LOG_DEBUG, "no message"); exit(0); } @@ -75,7 +80,8 @@ void main(int argc, char *argv[]) #endif info.version = NCP_GET_FS_INFO_VERSION; - if (ioctl(conn->mount_fid, NCP_IOC_GET_FS_INFO, &info) < 0) { + if (ioctl(conn->mount_fid, NCP_IOC_GET_FS_INFO, &info) < 0) + { fprintf(stderr, "%s: could not ioctl on connection: %s\n", progname, strerror(errno)); ncp_close(conn); @@ -83,30 +89,37 @@ void main(int argc, char *argv[]) } ncp_close(conn); - if ((pwd = getpwuid(info.mounted_uid)) == NULL) { + if ((pwd = getpwuid(info.mounted_uid)) == NULL) + { fprintf(stderr, "%s: user %d not known\n", progname, info.mounted_uid); exit(1); } - if ((mtab = fopen(MOUNTED, "r")) == NULL) { + if ((mtab = fopen(MOUNTED, "r")) == NULL) + { fprintf(stderr, "%s: can't open %s\n", progname, MOUNTED); exit(1); } - while ((mnt = getmntent(mtab)) != NULL) { - if (strcmp(mnt->mnt_dir, mount_point) == 0) { + while ((mnt = getmntent(mtab)) != NULL) + { + if (strcmp(mnt->mnt_dir, mount_point) == 0) + { break; } } - if (mnt == NULL) { + if (mnt == NULL) + { syslog(LOG_DEBUG, "cannot find mtab entry\n"); } - if (search_utmp(pwd->pw_name, tty) != 0) { + if (search_utmp(pwd->pw_name, tty) != 0) + { exit(1); } sprintf(tty_path, "/dev/%s", tty); - if ((tty_file = fopen(tty_path, "w")) == NULL) { + if ((tty_file = fopen(tty_path, "w")) == NULL) + { fprintf(stderr, "%s: cannot open %s: %s\n", progname, tty_path, strerror(errno)); exit(1); @@ -139,16 +152,18 @@ void main(int argc, char *argv[]) * term_chk - check that a terminal exists, and get the message bit * and the access time */ -static int term_chk(char *tty, int *msgsokP, time_t * atimeP, int *showerror) +static int +term_chk(char *tty, int *msgsokP, time_t * atimeP, int *showerror) { struct stat s; char path[MAXPATHLEN]; (void) sprintf(path, "/dev/%s", tty); - if (stat(path, &s) < 0) { + if (stat(path, &s) < 0) + { if (showerror) (void) fprintf(stderr, - "write: %s: %s\n", path, strerror(errno)); + "write: %s: %s\n", path, strerror(errno)); return (1); } *msgsokP = (s.st_mode & (S_IWRITE >> 3)) != 0; /* group write bit */ @@ -167,7 +182,8 @@ static int term_chk(char *tty, int *msgsokP, time_t * atimeP, int *showerror) * Special case for writing to yourself - ignore the terminal you're * writing from, unless that's the only terminal with messages enabled. */ -static int search_utmp(char *user, char *tty) +static int +search_utmp(char *user, char *tty) { struct utmp u; time_t bestatime, atime; @@ -175,7 +191,8 @@ static int search_utmp(char *user, char *tty) char atty[sizeof(u.ut_line) + 1]; - if ((ufd = open(_PATH_UTMP, O_RDONLY)) < 0) { + if ((ufd = open(_PATH_UTMP, O_RDONLY)) < 0) + { perror("utmp"); return -1; } @@ -183,7 +200,8 @@ static int search_utmp(char *user, char *tty) bestatime = 0; user_is_me = 0; while (read(ufd, (char *) &u, sizeof(u)) == sizeof(u)) - if (strncmp(user, u.ut_name, sizeof(u.ut_name)) == 0) { + if (strncmp(user, u.ut_name, sizeof(u.ut_name)) == 0) + { ++nloggedttys; (void) strncpy(atty, u.ut_line, sizeof(u.ut_line)); @@ -198,13 +216,15 @@ static int search_utmp(char *user, char *tty) continue; /* it's not a valid entry */ ++nttys; - if (atime > bestatime) { + if (atime > bestatime) + { bestatime = atime; (void) strcpy(tty, atty); } } (void) close(ufd); - if (nloggedttys == 0) { + if (nloggedttys == 0) + { (void) fprintf(stderr, "write: %s is not logged in\n", user); return -1; } diff --git a/include/glibstub.h b/include/glibstub.h new file mode 100644 index 0000000..89b0332 --- /dev/null +++ b/include/glibstub.h @@ -0,0 +1,22 @@ +#ifndef __GLIBSTUB_H__ +#define __GLIBSTUB_H__ + +#undef GLIBCHDR +#ifdef __GLIBC__ +#if __GLIBC__ >= 2 +#define GLIBCHDR +#endif +#endif +#ifdef GLIBCHDR +#define HAVE_NETIPX_IPX_H +#define HAVE_SYS_MOUNT_H +#define HAVE_NET_ROUTE_H +#define HAVE_NET_IF_H +#else +#undef HAVE_NETIPX_IPX_H +#undef HAVE_SYS_MOUNT_H +#undef HAVE_NET_ROUTE_H +#undef HAVE_NET_IF_H +#endif +#endif /* __GLIBSTUB_H__ */ + diff --git a/include/ipxlib.h b/include/ipxlib.h index 048d7dd..2bcb976 100644 --- a/include/ipxlib.h +++ b/include/ipxlib.h @@ -8,15 +8,14 @@ #ifndef _IPXLIB_H #define _IPXLIB_H - -#include +#include "kernel/types.h" #include "ncp.h" -#include -#include +#include "kernel/ipx.h" -typedef unsigned long IPXNet; -typedef unsigned short IPXPort; -typedef unsigned char IPXNode[IPX_NODE_LEN]; +typedef u_int32_t IPXNet; +typedef u_int16_t IPXPort; +typedef u_int8_t IPXNode[IPX_NODE_LEN]; +typedef const u_int8_t CIPXNode[IPX_NODE_LEN]; #define IPX_USER_PTYPE (0x00) #define IPX_RIP_PTYPE (0x01) @@ -32,30 +31,35 @@ typedef unsigned char IPXNode[IPX_NODE_LEN]; #define IPX_SAP_FILE_SERVER (0x0004) -struct sap_query { - unsigned short query_type; /* net order */ - unsigned short server_type; /* net order */ +struct sap_query +{ + u_int16_t query_type; /* net order */ + u_int16_t 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)); +struct sap_server_ident +{ + u_int16_t 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)); + u_int16_t 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)); +struct ipx_rip_packet +{ + u_int16_t operation __attribute__((packed)); + struct ipx_rt_def + { + u_int32_t network __attribute__((packed)); + u_int16_t hops __attribute__((packed)); + u_int16_t ticks __attribute__((packed)); + } + rt[1] __attribute__((packed)); }; #define IPX_BROADCAST_NODE ("\xff\xff\xff\xff\xff\xff") @@ -85,8 +89,10 @@ void int ipx_sscanf_node(char *buf, unsigned char node[IPX_NODE_LEN]); void - ipx_assign_node(IPXNode dest, IPXNode src); + ipx_assign_node(IPXNode dest, CIPXNode src); int - ipx_node_equal(IPXNode n1, IPXNode n2); + ipx_node_equal(CIPXNode n1, CIPXNode n2); +int +ipx_sscanf_saddr(char* buf, struct sockaddr_ipx* sipx); #endif /* _IPXLIB_H */ diff --git a/include/kernel/fs.h b/include/kernel/fs.h new file mode 100644 index 0000000..ae00f2f --- /dev/null +++ b/include/kernel/fs.h @@ -0,0 +1,11 @@ +#ifndef _KERNEL_FS_H +#define _KERNEL_FS_H + +#include "glibstub.h" +#ifdef HAVE_SYS_MOUNT_H +#include +#else +#include +#endif + +#endif diff --git a/include/kernel/if.h b/include/kernel/if.h new file mode 100644 index 0000000..14dee6d --- /dev/null +++ b/include/kernel/if.h @@ -0,0 +1,11 @@ +#ifndef _KERNEL_IF_H +#define _KERNEL_IF_H + +#include "glibstub.h" +#ifdef HAVE_NET_IF_H +#include +#else +#include +#endif + +#endif diff --git a/include/kernel/ipx.h b/include/kernel/ipx.h new file mode 100644 index 0000000..ff4f153 --- /dev/null +++ b/include/kernel/ipx.h @@ -0,0 +1,15 @@ +#ifndef _KERNEL_IPX_H +#define _KERNEL_IPX_H + +#include "glibstub.h" +#ifdef HAVE_NETIPX_IPX_H +#include +#else +#include +#endif + +#ifndef IPXPROTO_IPX +#define IPXPROTO_IPX (PF_IPX) +#endif + +#endif diff --git a/include/kernel/ncp.h b/include/kernel/ncp.h new file mode 100644 index 0000000..cd02499 --- /dev/null +++ b/include/kernel/ncp.h @@ -0,0 +1,213 @@ +/* + * ncp.h + * + * Copyright (C) 1995 by Volker Lendecke + * Modified for sparc by J.F. Chadima + * + */ + +#ifndef _LINUX_NCP_H +#define _LINUX_NCP_H + +#include "kernel/types.h" +#include "kernel/ipx.h" + +#define NCP_PTYPE (0x11) +#define NCP_PORT (0x0451) + +#define NCP_ALLOC_SLOT_REQUEST (0x1111) +#define NCP_REQUEST (0x2222) +#define NCP_DEALLOC_SLOT_REQUEST (0x5555) + +struct ncp_request_header { + u_int16_t type __attribute__((packed)); + u_int8_t sequence __attribute__((packed)); + u_int8_t conn_low __attribute__((packed)); + u_int8_t task __attribute__((packed)); + u_int8_t conn_high __attribute__((packed)); + u_int8_t function __attribute__((packed)); + u_int8_t data[0] __attribute__((packed)); +}; + +#define NCP_REPLY (0x3333) +#define NCP_POSITIVE_ACK (0x9999) + +struct ncp_reply_header { + __u16 type __attribute__((packed)); + __u8 sequence __attribute__((packed)); + __u8 conn_low __attribute__((packed)); + __u8 task __attribute__((packed)); + __u8 conn_high __attribute__((packed)); + __u8 completion_code __attribute__((packed)); + __u8 connection_state __attribute__((packed)); + __u8 data[0] __attribute__((packed)); +}; + +#define NCP_VOLNAME_LEN (16) +#define NCP_NUMBER_OF_VOLUMES (64) +struct ncp_volume_info { + __u32 total_blocks; + __u32 free_blocks; + __u32 purgeable_blocks; + __u32 not_yet_purgeable_blocks; + __u32 total_dir_entries; + __u32 available_dir_entries; + __u8 sectors_per_block; + char volume_name[NCP_VOLNAME_LEN + 1]; +}; + +/* these define the attribute byte as seen by NCP */ +#define aRONLY (ntohl(0x01000000)) +#define aHIDDEN (ntohl(0x02000000)) +#define aSYSTEM (ntohl(0x04000000)) +#define aEXECUTE (ntohl(0x08000000)) +#define aDIR (ntohl(0x10000000)) +#define aARCH (ntohl(0x20000000)) + +#define AR_READ (ntohs(0x0100)) +#define AR_WRITE (ntohs(0x0200)) +#define AR_EXCLUSIVE (ntohs(0x2000)) + +#define NCP_FILE_ID_LEN 6 + +/* 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 + +#if 0 /* Sorry, I do not think so... VANA */ +/* Defines for ReturnInformationMask */ +#define RIM_NAME (ntohl(0x01000000L)) +#define RIM_SPACE_ALLOCATED (ntohl(0x02000000L)) +#define RIM_ATTRIBUTES (ntohl(0x04000000L)) +#define RIM_DATA_SIZE (ntohl(0x08000000L)) +#define RIM_TOTAL_SIZE (ntohl(0x10000000L)) +#define RIM_EXT_ATTR_INFO (ntohl(0x20000000L)) +#define RIM_ARCHIVE (ntohl(0x40000000L)) +#define RIM_MODIFY (ntohl(0x80000000L)) +#define RIM_CREATION (ntohl(0x00010000L)) +#define RIM_OWNING_NAMESPACE (ntohl(0x00020000L)) +#define RIM_DIRECTORY (ntohl(0x00040000L)) +#define RIM_RIGHTS (ntohl(0x00080000L)) +#define RIM_ALL (ntohl(0xFF0F0000L)) +#define RIM_COMPRESSED_INFO (ntohl(0x00000080L)) +#else +#define RIM_NAME 0x00000001 +#define RIM_SPACE_ALLOCATED 0x00000002 +#define RIM_ATTRIBUTES 0x00000004 +#define RIM_DATA_SIZE 0x00000008 +#define RIM_TOTAL_SIZE 0x00000010 +#define RIM_EXT_ATTR_INFO 0x00000020 +#define RIM_ARCHIVE 0x00000040 +#define RIM_MODIFY 0x00000080 +#define RIM_CREATION 0x00000100 +#define RIM_OWNING_NAMESPACE 0x00000200 +#define RIM_DIRECTORY 0x00000400 +#define RIM_RIGHTS 0x00000800 +#define RIM_ALL 0x00000FFF +#define RIM_COMPRESSED_INFO 0x80000000UL +#endif + +/* open/create modes */ +#define OC_MODE_OPEN 0x01 +#define OC_MODE_TRUNCATE 0x02 +#define OC_MODE_REPLACE 0x02 +#define OC_MODE_CREATE 0x08 + +/* open/create results */ +#define OC_ACTION_NONE 0x00 +#define OC_ACTION_OPEN 0x01 +#define OC_ACTION_CREATE 0x02 +#define OC_ACTION_TRUNCATE 0x04 +#define OC_ACTION_REPLACE 0x04 + +/* access rights attributes */ +#ifndef AR_READ_ONLY +#define AR_READ_ONLY 0x0001 +#define AR_WRITE_ONLY 0x0002 +#define AR_DENY_READ 0x0004 +#define AR_DENY_WRITE 0x0008 +#define AR_COMPATIBILITY 0x0010 +#define AR_WRITE_THROUGH 0x0040 +#define AR_OPEN_COMPRESSED 0x0100 +#endif + +struct nw_info_struct { + __u32 spaceAlloc __attribute__((packed)); + __u32 attributes __attribute__((packed)); + __u16 flags __attribute__((packed)); + __u32 dataStreamSize __attribute__((packed)); + __u32 totalStreamSize __attribute__((packed)); + __u16 numberOfStreams __attribute__((packed)); + __u16 creationTime __attribute__((packed)); + __u16 creationDate __attribute__((packed)); + __u32 creatorID __attribute__((packed)); + __u16 modifyTime __attribute__((packed)); + __u16 modifyDate __attribute__((packed)); + __u32 modifierID __attribute__((packed)); + __u16 lastAccessDate __attribute__((packed)); + __u16 archiveTime __attribute__((packed)); + __u16 archiveDate __attribute__((packed)); + __u32 archiverID __attribute__((packed)); + __u16 inheritedRightsMask __attribute__((packed)); + __u32 dirEntNum __attribute__((packed)); + __u32 DosDirNum __attribute__((packed)); + __u32 volNumber __attribute__((packed)); + __u32 EADataSize __attribute__((packed)); + __u32 EAKeyCount __attribute__((packed)); + __u32 EAKeySize __attribute__((packed)); + __u32 NSCreator __attribute__((packed)); + __u8 nameLen __attribute__((packed)); + __u8 entryName[256] __attribute__((packed)); +}; + +/* modify mask - use with MODIFY_DOS_INFO structure */ +#define DM_ATTRIBUTES (ntohl(0x02000000L)) +#define DM_CREATE_DATE (ntohl(0x04000000L)) +#define DM_CREATE_TIME (ntohl(0x08000000L)) +#define DM_CREATOR_ID (ntohl(0x10000000L)) +#define DM_ARCHIVE_DATE (ntohl(0x20000000L)) +#define DM_ARCHIVE_TIME (ntohl(0x40000000L)) +#define DM_ARCHIVER_ID (ntohl(0x80000000L)) +#define DM_MODIFY_DATE (ntohl(0x00010000L)) +#define DM_MODIFY_TIME (ntohl(0x00020000L)) +#define DM_MODIFIER_ID (ntohl(0x00040000L)) +#define DM_LAST_ACCESS_DATE (ntohl(0x00080000L)) +#define DM_INHERITED_RIGHTS_MASK (ntohl(0x00100000L)) +#define DM_MAXIMUM_SPACE (ntohl(0x00200000L)) + +struct nw_modify_dos_info { + __u32 attributes __attribute__((packed)); + __u16 creationDate __attribute__((packed)); + __u16 creationTime __attribute__((packed)); + __u32 creatorID __attribute__((packed)); + __u16 modifyDate __attribute__((packed)); + __u16 modifyTime __attribute__((packed)); + __u32 modifierID __attribute__((packed)); + __u16 archiveDate __attribute__((packed)); + __u16 archiveTime __attribute__((packed)); + __u32 archiverID __attribute__((packed)); + __u16 lastAccessDate __attribute__((packed)); + __u16 inheritanceGrantMask __attribute__((packed)); + __u16 inheritanceRevokeMask __attribute__((packed)); + __u32 maximumSpace __attribute__((packed)); +}; + +struct nw_file_info { + struct nw_info_struct i; + int opened; + int access; + __u32 server_file_handle __attribute__((packed)); + __u8 open_create_action __attribute__((packed)); + __u8 file_handle[6] __attribute__((packed)); +}; + +struct nw_search_sequence { + __u8 volNumber __attribute__((packed)); + __u32 dirBase __attribute__((packed)); + __u32 sequence __attribute__((packed)); +}; + +#endif /* _LINUX_NCP_H */ diff --git a/include/kernel/ncp_fs.h b/include/kernel/ncp_fs.h new file mode 100644 index 0000000..3abdff6 --- /dev/null +++ b/include/kernel/ncp_fs.h @@ -0,0 +1,110 @@ +/* + * ncp_fs.h + * + * Copyright (C) 1995, 1996 by Volker Lendecke + * + */ + +#ifndef _KERNEL_NCP_FS_H +#define _KERNEL_NCP_FS_H + +#include "kernel/fs.h" +#include +#include + +/* + * ioctl commands + */ + +struct ncp_ioctl_request { + unsigned int function; + unsigned int size; + char *data; +}; + +struct ncp_fs_info { + int version; + struct sockaddr_ipx addr; + __kerXX_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; +}; + +struct ncp_sign_init +{ + char sign_root[8]; + char sign_last[16]; +}; + +struct ncp_lock_ioctl +{ +#define NCP_LOCK_LOG 0 +#define NCP_LOCK_SH 1 +#define NCP_LOCK_EX 2 +#define NCP_LOCK_CLEAR 256 + int cmd; + int origin; + unsigned int offset; + unsigned int length; +#define NCP_LOCK_DEFAULT_TIMEOUT 18 +#define NCP_LOCK_MAX_TIMEOUT 180 + int timeout; +}; + +struct ncp_setroot_ioctl +{ + int volNumber; + int namespace; + __u32 dirEntNum; +}; + +struct ncp_objectname_ioctl +{ +#define NCP_AUTH_NONE 0x00 +#define NCP_AUTH_BIND 0x31 +#define NCP_AUTH_NDS 0x32 + int auth_type; + size_t object_name_len; + void* object_name; +}; + +struct ncp_privatedata_ioctl +{ + size_t len; + void* data; /* ~1000 for NDS */ +}; + +#define NCP_IOC_NCPREQUEST _IOR('n', 1, struct ncp_ioctl_request) +#define NCP_IOC_GETMOUNTUID _IOW('n', 2, __kernel_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) + +#define NCP_IOC_SIGN_INIT _IOR('n', 5, struct ncp_sign_init) +#define NCP_IOC_SIGN_WANTED _IOR('n', 6, int) +#define NCP_IOC_SET_SIGN_WANTED _IOW('n', 6, int) + +#define NCP_IOC_LOCKUNLOCK _IOR('n', 7, struct ncp_lock_ioctl) + +#define NCP_IOC_GETROOT _IOW('n', 8, struct ncp_setroot_ioctl) +#define NCP_IOC_SETROOT _IOR('n', 8, struct ncp_setroot_ioctl) + +#define NCP_IOC_GETOBJECTNAME _IOWR('n', 9, struct ncp_objectname_ioctl) +#define NCP_IOC_SETOBJECTNAME _IOR('n', 9, struct ncp_objectname_ioctl) +#define NCP_IOC_GETPRIVATEDATA _IOWR('n', 10, struct ncp_privatedata_ioctl) +#define NCP_IOC_SETPRIVATEDATA _IOR('n', 10, struct ncp_privatedata_ioctl) + +/* + * The packet size to allocate. One page should be enough. + */ +#define NCP_PACKET_SIZE 4070 + +#define NCP_MAXPATHLEN 255 +#define NCP_MAXNAMELEN 14 + +#endif /* _LINUX_NCP_FS_H */ diff --git a/include/kernel/route.h b/include/kernel/route.h new file mode 100644 index 0000000..f5c0b83 --- /dev/null +++ b/include/kernel/route.h @@ -0,0 +1,12 @@ +#ifndef __KERNEL_ROUTE_H__ +#define __KERNEL_ROUTE_H__ + +#include "glibstub.h" +#ifdef HAVE_NET_ROUTE_H +#include +#else +#include +#endif + +#endif /* __KERNEL_ROUTE_H__ */ + diff --git a/include/kernel/types.h b/include/kernel/types.h new file mode 100644 index 0000000..c2286ca --- /dev/null +++ b/include/kernel/types.h @@ -0,0 +1,40 @@ +#ifndef __KERNEL_TYPES_H__ +#define __KERNEL_TYPES_H__ + +#include + +#undef __u8 +#undef __u16 +#undef __u32 +#define __u8 u_int8_t +#define __u16 u_int16_t +#define __u32 u_int32_t + +typedef u_int16_t __kerXX_uid_t; + +#include + +typedef __kernel_pid_t __ker20_pid_t; +typedef __kernel_uid_t __ker20_uid_t; +typedef __kernel_gid_t __ker20_gid_t; +typedef __kernel_mode_t __ker20_mode_t; + +typedef __kernel_pid_t __ker21_pid_t; +typedef __kernel_uid_t __ker21_uid_t; +typedef __kernel_gid_t __ker21_gid_t; +typedef __kernel_mode_t __ker21_mode_t; + +#ifdef __GLIBC__ +/* why is this defined in posix_types ???? dirty hack... */ +#undef __FD_CLR +#undef __FD_SET +#undef __FD_ISSET +#undef __FD_ZERO +#ifdef _SELECTBITS_H +#undef _SELECTBITS_H +#include +#endif +#endif + +#endif /* __KERNEL_TYPES_H__ */ + diff --git a/include/ncp.h b/include/ncp.h index dc117a9..29361ba 100644 --- a/include/ncp.h +++ b/include/ncp.h @@ -9,10 +9,10 @@ #ifndef _NCP_H #define _NCP_H -#include -#include -#include -#include +#include "kernel/types.h" +#include "kernel/ipx.h" +#include "kernel/ncp.h" +#include "kernel/ncp_fs.h" #define NCP_BINDERY_USER (0x0001) #define NCP_BINDERY_UGROUP (0x0002) @@ -119,5 +119,4 @@ struct print_job_record { char Path[80] __attribute__((packed)); }; - #endif /* _NCP_H */ diff --git a/include/ncplib.h b/include/ncplib.h index 141d16b..634d0c8 100644 --- a/include/ncplib.h +++ b/include/ncplib.h @@ -8,13 +8,17 @@ #ifndef _NCPLIB_H #define _NCPLIB_H -#include #include "ncp.h" -#include #include #include #include +#ifdef SIGNATURES +#ifndef NCP_IOC_SIGN_INIT +#undef SIGNATURES +#endif /* NCP_IOC_SIGN_INIT */ +#endif /* SIGNATURES */ + #include "ipxlib.h" #include "com_err.h" @@ -22,31 +26,36 @@ typedef __u8 byte; typedef __u16 word; typedef __u32 dword; +typedef int NWCCODE; + #ifndef memzero #include #define memzero(object) memset(&(object), 0, sizeof(object)) #endif -#define BVAL(buf,pos) (((__u8 *)(buf))[pos]) +#define BVAL(buf,pos) (((const __u8 *)(buf))[pos]) +#define BWVAL(buf,pos) (((__u8*)(buf))[pos]) #define PVAL(buf,pos) ((unsigned)BVAL(buf,pos)) -#define BSET(buf,pos,val) (BVAL(buf,pos) = (val)) +#define BSET(buf,pos,val) (BWVAL(buf,pos) = (val)) static inline word - WVAL_HL(__u8 * buf, int pos) +WVAL_HL(const __u8 * buf, int pos) { return PVAL(buf, pos) << 8 | PVAL(buf, pos + 1); } static inline dword - DVAL_HL(__u8 * buf, int pos) +DVAL_HL(const __u8 * buf, int pos) { return WVAL_HL(buf, pos) << 16 | WVAL_HL(buf, pos + 2); } -static inline void WSET_HL(__u8 * buf, int pos, word val) +static inline void +WSET_HL(__u8 * buf, int pos, word val) { BSET(buf, pos, val >> 8); BSET(buf, pos + 1, val & 0xff); } -static inline void DSET_HL(__u8 * buf, int pos, dword val) +static inline void +DSET_HL(__u8 * buf, int pos, dword val) { WSET_HL(buf, pos, val >> 16); WSET_HL(buf, pos + 2, val & 0xffff); @@ -58,20 +67,22 @@ static inline void DSET_HL(__u8 * buf, int pos, dword val) #if defined(__i386__) static inline word - WVAL_LH(__u8 * buf, int pos) +WVAL_LH(const __u8 * buf, int pos) { - return *((word *) (buf + pos)); + return *((const word *) (buf + pos)); } static inline dword - DVAL_LH(__u8 * buf, int pos) +DVAL_LH(const __u8 * buf, int pos) { - return *((dword *) (buf + pos)); + return *((const dword *) (buf + pos)); } -static inline void WSET_LH(__u8 * buf, int pos, word val) +static inline void +WSET_LH(__u8 * buf, int pos, word val) { *((word *) (buf + pos)) = val; } -static inline void DSET_LH(__u8 * buf, int pos, dword val) +static inline void +DSET_LH(__u8 * buf, int pos, dword val) { *((dword *) (buf + pos)) = val; } @@ -79,21 +90,23 @@ static inline void DSET_LH(__u8 * buf, int pos, dword val) #else static inline word - WVAL_LH(__u8 * buf, int pos) +WVAL_LH(const __u8 * buf, int pos) { return PVAL(buf, pos) | PVAL(buf, pos + 1) << 8; } static inline dword - DVAL_LH(__u8 * buf, int pos) +DVAL_LH(const __u8 * buf, int pos) { return WVAL_LH(buf, pos) | WVAL_LH(buf, pos + 2) << 16; } -static inline void WSET_LH(__u8 * buf, int pos, word val) +static inline void +WSET_LH(__u8 * buf, int pos, word val) { BSET(buf, pos, val & 0xff); BSET(buf, pos + 1, val >> 8); } -static inline void DSET_LH(__u8 * buf, int pos, dword val) +static inline void +DSET_LH(__u8 * buf, int pos, dword val) { WSET_LH(buf, pos, val & 0xffff); WSET_LH(buf, pos + 2, val >> 16); @@ -101,19 +114,18 @@ static inline void DSET_LH(__u8 * buf, int pos, dword val) #endif - - - void str_upper(char *name); -enum connect_state { +enum connect_state +{ NOT_CONNECTED = 0, CONN_PERMANENT, CONN_TEMPORARY }; -struct ncp_conn { +struct ncp_conn +{ enum connect_state is_connected; @@ -139,14 +151,22 @@ struct ncp_conn { int current_size; int has_subfunction; int verbose; - int ncp_reply_size; + size_t ncp_reply_size; int lock; char packet[NCP_PACKET_SIZE]; +#ifdef SIGNATURES + /* Field used to make packet signatures */ + int sign_wanted; + int sign_active; + char sign_root[8]; + char sign_last[16]; +#endif }; -struct ncp_conn_spec { +struct ncp_conn_spec +{ char server[NCP_BINDERY_NAME_LEN]; char user[NCP_BINDERY_NAME_LEN]; uid_t uid; @@ -154,12 +174,16 @@ struct ncp_conn_spec { char password[NCP_BINDERY_NAME_LEN]; }; -struct ncp_search_seq { +#ifndef __MAKE_SULIB__ +struct ncp_search_seq +{ struct nw_search_sequence s; int namespace; }; +#endif /* not __MAKE_SULIB__ */ -struct ncp_property_info { +struct ncp_property_info +{ __u8 property_name[16]; __u8 property_flags; __u8 property_security; @@ -186,34 +210,35 @@ struct ncp_conn * /* Open a connection */ struct ncp_conn * - ncp_open(const struct ncp_conn_spec *spec, long *err); +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); +int +ncp_open_mount(const char *mount_point, struct ncp_conn** conn); /* Find a permanent connection that fits the spec, return NULL if * there is none. */ char * - ncp_find_permanent(const struct ncp_conn_spec *spec); +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); +long +ncp_find_fileserver(const char *server_name, struct sockaddr* addr, size_t addrlen); /* Find the address of a server */ -struct sockaddr_ipx * - ncp_find_server(const char **server_name, int type, long *err); +long +ncp_find_server(const char **server_name, int type, struct sockaddr* addr, size_t addrlen); /* Detach from a permanent connection or destroy a temporary connection */ long - ncp_close(struct ncp_conn *conn); +ncp_close(struct ncp_conn *conn); /* like getmntent, get_ncp_conn_ent scans /etc/mtab for usable connections */ -struct ncp_conn_ent { +struct ncp_conn_ent +{ char server[NCP_BINDERY_NAME_LEN]; char user[NCP_BINDERY_NAME_LEN]; uid_t uid; @@ -221,7 +246,7 @@ struct ncp_conn_ent { }; struct ncp_conn_ent * - ncp_get_conn_ent(FILE * filep); +ncp_get_conn_ent(FILE * filep); #define NWCLIENT (".nwclient") #define NWC_NOPASSWORD ("-") @@ -232,6 +257,12 @@ 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); +#ifdef __MAKE_SULIB__ +struct ncp_conn_spec * + ncp_find_conn_spec2(const char *server, const char *user, const char *password, + int login_necessary, uid_t uid, int allow_multiple_conns, + long *err); +#else /* __MAKE_SULIB__ */ long ncp_get_file_server_description_strings(struct ncp_conn *conn, char target[512]); @@ -241,7 +272,8 @@ long long ncp_set_file_server_time(struct ncp_conn *conn, time_t * source); -struct ncp_file_server_info { +struct ncp_file_server_info +{ __u8 ServerName[48] __attribute__((packed)); __u8 FileServiceVersion __attribute__((packed)); __u8 FileServiceSubVersion __attribute__((packed)); @@ -288,9 +320,16 @@ long __u8 no_conn, const __u8 * connections, const char *message); +long + ncp_send_broadcast2(struct ncp_conn *conn, + unsigned int conns, const unsigned int* connlist, + const char* message); +#endif /* not __MAKE_SULIB__ */ + long ncp_get_encryption_key(struct ncp_conn *conn, char *target); +#ifndef __MAKE_SULIB__ long ncp_get_bindery_object_id(struct ncp_conn *conn, __u16 object_type, @@ -302,7 +341,7 @@ long struct ncp_bindery_object *target); long ncp_scan_bindery_object(struct ncp_conn *conn, - __u32 last_id, __u16 object_type, char *search_string, + __u32 last_id, __u16 object_type, char *search_string, struct ncp_bindery_object *target); long ncp_create_bindery_object(struct ncp_conn *conn, @@ -320,14 +359,17 @@ long __u16 object_type, const char *object_name, __u8 security); +#endif /* not __MAKE_SULIB__ */ -struct ncp_station_addr { +struct ncp_station_addr +{ __u32 NetWork __attribute__((packed)); __u8 Node[6] __attribute__((packed)); __u16 Socket __attribute__((packed)); }; -struct ncp_prop_login_control { +struct ncp_prop_login_control +{ __u8 AccountExpireDate[3] __attribute__((packed)); __u8 Disabled __attribute__((packed)); __u8 PasswordExpireDate[3] __attribute__((packed)); @@ -351,10 +393,11 @@ long int object_type, const char *object_name, int segment, const char *prop_name, struct nw_property *target); +#ifndef __MAKE_SULIB__ long ncp_scan_property(struct ncp_conn *conn, __u16 object_type, const char *object_name, - __u32 last_id, char *search_string, + __u32 last_id, const char *search_string, struct ncp_property_info *property_info); long ncp_add_object_to_set(struct ncp_conn *conn, @@ -387,7 +430,7 @@ long __u16 object_type, const char *object_name, const char *property_name, __u8 segment, - struct nw_property *property_value); + const struct nw_property *property_value); /* Bit masks for security flag */ #define NCP_SEC_CHECKSUMMING_REQUESTED (1) @@ -421,13 +464,24 @@ long const unsigned char *key, const unsigned char *oldpasswd, const unsigned char *newpasswd); +#endif /* not __MAKE_SULIB__ */ +#define NWE_SIGNATURE_LEVEL_CONFLICT (0x8861) #define NCP_GRACE_PERIOD (0xdf) +#ifndef __MAKE_SULIB__ +long + ncp_get_bindery_object_id(struct ncp_conn *conn, + __u16 object_type, + const char *object_name, + struct ncp_bindery_object *target); +#endif /* not __MAKE_SULIB__ */ + long ncp_login_user(struct ncp_conn *conn, const unsigned char *username, const unsigned char *password); +#ifndef __MAKE_SULIB__ long ncp_get_volume_info_with_number(struct ncp_conn *conn, int n, struct ncp_volume_info *target); @@ -528,6 +582,15 @@ long __u32 count, __u32 * copied_count); +#define SA_NORMAL (0x0000) +#define SA_HIDDEN (0x0002) +#define SA_SYSTEM (0x0004) +#define SA_SUBDIR_ONLY (0x0010) +#define SA_SUBDIR_FILES (0x8000) +#define SA_ALL (SA_SUBDIR_FILES | SA_SYSTEM | SA_HIDDEN) +#define SA_SUBDIR_ALL (SA_SUBDIR_ONLY | SA_SYSTEM | SA_HIDDEN) +#define SA_FILES_ALL (SA_NORMAL | SA_SYSTEM | SA_HIDDEN) + long ncp_obtain_file_or_subdir_info(struct ncp_conn *conn, __u8 source_ns, __u8 target_ns, @@ -555,7 +618,7 @@ long long ncp_do_lookup(struct ncp_conn *conn, struct nw_info_struct *dir, - char *path, /* may only be one component */ + const char *path, /* may only be one component */ struct nw_info_struct *target); long @@ -583,6 +646,13 @@ long int namespace, struct ncp_search_seq *target); +long +ncp_search_for_file_or_subdir2(struct ncp_conn *conn, + int search_attributes, + u_int32_t RIM, + struct ncp_search_seq *seq, + struct nw_info_struct *target); + long ncp_search_for_file_or_subdir(struct ncp_conn *conn, struct ncp_search_seq *seq, @@ -590,14 +660,35 @@ long 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); + 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_get_queue_length(struct ncp_conn *conn, + __u32 queue_id, + __u32 *queue_length); + +long + ncp_get_queue_job_ids(struct ncp_conn *conn, + __u32 queue_id, + __u32 queue_section, + __u32 *length1, + __u32 *length2, + __u32 ids[]); +long + ncp_get_queue_job_info(struct ncp_conn *conn, + __u32 queue_id, + __u32 job_id, + struct nw_queue_job_entry *jobdata); + +long +NWRemoveJobFromQueue2(struct ncp_conn* conn, __u32 queue_id, __u32 job_id); + long ncp_close_file_and_start_job(struct ncp_conn *conn, __u32 queue_id, @@ -622,10 +713,12 @@ long long ncp_abort_servicing_job(struct ncp_conn *conn, __u32 queue_id, __u32 job_number); +#endif /* not __MAKE_SULIB__ */ long ncp_get_broadcast_message(struct ncp_conn *conn, char message[256]); +#ifndef __MAKE_SULIB__ long ncp_dealloc_dir_handle(struct ncp_conn *conn, __u8 dir_handle); @@ -644,7 +737,8 @@ long struct nw_info_struct *file, __u16 * target); -struct ncp_trustee_struct { +struct ncp_trustee_struct +{ __u32 object_id; __u16 rights; }; @@ -655,5 +749,75 @@ long __u16 rights_mask, int object_count, struct ncp_trustee_struct *rights); +struct ncp_deleted_file +{ + int32_t seq; + __u32 vol; + __u32 base; +}; -#endif /* _NCPLIB_H */ +long +ncp_ns_scan_salvageable_file(struct ncp_conn* conn, __u8 src_ns, + int dirstyle, __u8 vol_num, + __u32 dir_base, + const unsigned char* encpath, int pathlen, + struct ncp_deleted_file* finfo, + char* name, int maxnamelen); + +long +ncp_ns_purge_file(struct ncp_conn* conn, const struct ncp_deleted_file* finfo); + +long +ncp_ns_get_full_name(struct ncp_conn* conn, __u8 src_ns, __u8 dst_ns, + int dirstyle, __u8 vol_num, __u32 dir_base, + const unsigned char* encpath, size_t pathlen, + char* name, size_t maxnamelen); + +#endif /* not __MAKE_SULIB__ */ + +#ifdef SIGNATURES +long +ncp_sign_start(struct ncp_conn *conn, const char *sign_root); +#endif /* SIGNATURES */ + +#ifdef NDS_SUPPORT +long +ncp_send_nds_frag(struct ncp_conn *conn, + int ndsverb, + const char *inbuf, size_t inbuflen, + char *outbuf, size_t outbufsize, size_t *outbuflen); + +long +ncp_send_nds(struct ncp_conn *conn, int fn, + const char *data_in, size_t data_in_len, + char *data_out, size_t data_out_max, size_t *data_out_len); + +long +ncp_change_conn_state(struct ncp_conn *conn, int new_state); +#endif + +struct ncp_conn * +ncp_open_addr(struct sockaddr *target, long *err); + +#ifdef __MAKE_SULIB__ +int +ncp_path_to_NW_format(const char* path, unsigned char* buff, int buffsize); + +long +ncp_obtain_file_or_subdir_info2(struct ncp_conn* conn, __u8 source_ns, + __u8 target_ns, __u16 search_attribs, __u32 rim, + int dir_style, __u8 vol, __u32 dirent, + const unsigned char* path, int pathlen, + struct nw_info_struct* target); + +#endif /* __MAKE_SULIB__ */ + +int +ncp_get_mount_uid(int fid, uid_t* uid); + +#ifdef __MAKE_SULIB__ +long +ncp_renegotiate_connparam(struct ncp_conn* conn, int buffsize, int options); +#endif /* __MAKE_SULIB__ */ + +#endif /* _NCPLIB_H */ diff --git a/include/ncpsign.h b/include/ncpsign.h new file mode 100644 index 0000000..72d8f8e --- /dev/null +++ b/include/ncpsign.h @@ -0,0 +1,18 @@ +#ifdef SIGNATURES +/* + * ncpsign.h + * + * Arne de Bruijn (arne@knoware.nl), 1997 + * + */ + +#ifndef _NCPSIGN_H +#define _NCPSIGN_H + +#include "ncplib.h" + +void sign_init(const char *logindata, char *sign_root); +void sign_packet(struct ncp_conn *conn, int *size); + +#endif +#endif diff --git a/include/ndslib.h b/include/ndslib.h new file mode 100644 index 0000000..89a4813 --- /dev/null +++ b/include/ndslib.h @@ -0,0 +1,35 @@ +/* + NDS client for ncpfs + Copyright (C) 1997 Arne de Bruijn + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _NDSLIB_H_ +#define _NDSLIB_H_ + +#include "ncplib.h" +typedef unsigned short uni_char; + +#define NDS_GRACE_PERIOD -223 + +int strlen_u(const uni_char *s); +void strcpy_uc(char *d, const uni_char *s); +void strcpy_cu(uni_char *d, const char *s); +long nds_get_server_name(struct ncp_conn *conn, uni_char **server_name); +long nds_get_tree_name(struct ncp_conn *conn, char *name, int name_buf_len); +long nds_login_auth(struct ncp_conn *conn, const char *user, const char *pwd); + +#endif /* ifndef _NDSLIB_H_ */ diff --git a/ipx-1.0/Makefile b/ipx-1.0/Makefile index c12bf8d..5a29d7d 100644 --- a/ipx-1.0/Makefile +++ b/ipx-1.0/Makefile @@ -1,5 +1,8 @@ -CFLAGS = -O2 -Wall +include ../Makeinit +# CFLAGS = -O2 -Wall -I../include UTILS = ipx_configure ipx_interface ipx_internal_net ipx_route +MAN8 := $(UTILS) +CFLAGS := $(CCFLAGS) all: $(UTILS) @@ -17,3 +20,4 @@ install: $(UTILS) do \ install $$i $(BINDIR); \ done + for i in $(MAN8); do install $$i.8 -m 644 $(MANDIR)/man8; done diff --git a/ipx-1.0/Samples/ipxrcv.c b/ipx-1.0/Samples/ipxrcv.c index c01a0f8..d076506 100644 --- a/ipx-1.0/Samples/ipxrcv.c +++ b/ipx-1.0/Samples/ipxrcv.c @@ -5,7 +5,8 @@ #include #include -int main(int argc, char **argv) +int +main(int argc, char **argv) { struct sockaddr_ipx sipx; int s; @@ -14,7 +15,8 @@ int main(int argc, char **argv) int len; s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); - if (s < 0) { + if (s < 0) + { perror("IPX: socket: "); exit(-1); } @@ -24,14 +26,16 @@ int main(int argc, char **argv) sipx.sipx_type = 17; len = sizeof(sipx); result = bind(s, (struct sockaddr *) &sipx, sizeof(sipx)); - if (result < 0) { + 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) { + if (result < 0) + { perror("IPX: recvfrom: "); } printf("From %08lX:%02X%02X%02X%02X%02X%02X:%04X\n", diff --git a/ipx-1.0/Samples/ipxsend.c b/ipx-1.0/Samples/ipxsend.c index ad92629..e8b519d 100644 --- a/ipx-1.0/Samples/ipxsend.c +++ b/ipx-1.0/Samples/ipxsend.c @@ -9,7 +9,8 @@ #include #include -int main(int argc, char **argv) +int +main(int argc, char **argv) { struct sockaddr_ipx sipx; int s; @@ -18,7 +19,8 @@ int main(int argc, char **argv) int len = sizeof(sipx); s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); - if (s < 0) { + if (s < 0) + { perror("IPX: socket: "); exit(-1); } @@ -28,7 +30,8 @@ int main(int argc, char **argv) sipx.sipx_type = 17; result = bind(s, (struct sockaddr *) &sipx, sizeof(sipx)); - if (result < 0) { + if (result < 0) + { perror("IPX: bind: "); exit(-1); } @@ -36,7 +39,8 @@ int main(int argc, char **argv) sipx.sipx_port = htons(0x5000); result = sendto(s, msg, sizeof(msg), 0, (struct sockaddr *) &sipx, sizeof(sipx)); - if (result < 0) { + if (result < 0) + { perror("IPX: send: "); exit(-1); } diff --git a/ipx-1.0/Samples/rip.c b/ipx-1.0/Samples/rip.c index 38f4419..67f660e 100644 --- a/ipx-1.0/Samples/rip.c +++ b/ipx-1.0/Samples/rip.c @@ -9,13 +9,15 @@ #include #include -struct rip_data { +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) +int +main(int argc, char **argv) { struct sockaddr_ipx sipx; int result; @@ -26,7 +28,8 @@ int main(int argc, char **argv) struct rip_data *rp; s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); - if (s < 0) { + if (s < 0) + { perror("IPX: socket: "); exit(-1); } @@ -35,15 +38,18 @@ int main(int argc, char **argv) sipx.sipx_port = htons(0x453); sipx.sipx_type = 17; result = bind(s, (struct sockaddr *) &sipx, sizeof(sipx)); - if (result < 0) { + if (result < 0) + { perror("IPX: bind: "); exit(-1); } - while (1) { + while (1) + { len = sizeof(sipx); result = recvfrom(s, msg, sizeof(msg), 0, (struct sockaddr *) &sipx, &len); - if (result < 0) { + if (result < 0) + { perror("IPX: recvfrom"); exit(-1); } @@ -56,7 +62,8 @@ int main(int argc, char **argv) sipx.sipx_node[6], sipx.sipx_node[5]); bptr += 2; rp = (struct rip_data *) bptr; - while (result >= sizeof(struct rip_data)) { + 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); diff --git a/ipx-1.0/Samples/sap.c b/ipx-1.0/Samples/sap.c index 5bf696b..cfb3a6b 100644 --- a/ipx-1.0/Samples/sap.c +++ b/ipx-1.0/Samples/sap.c @@ -10,7 +10,8 @@ #include -struct sap_data { +struct sap_data +{ unsigned short sap_type __attribute__((packed)); char sap_name[48] __attribute__((packed)); unsigned long sap_net __attribute__((packed)); @@ -19,7 +20,8 @@ struct sap_data { unsigned short sap_hops __attribute__((packed)); }; -int main(int argc, char **argv) +int +main(int argc, char **argv) { int s; int result; @@ -31,12 +33,14 @@ int main(int argc, char **argv) struct sap_data *sp; s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); - if (s < 0) { + if (s < 0) + { perror("IPX: socket: "); exit(-1); } result = setsockopt(s, SOL_SOCKET, SO_DEBUG, &val, 4); - if (result < 0) { + if (result < 0) + { perror("IPX: setsockopt: "); exit(-1); } @@ -46,15 +50,18 @@ int main(int argc, char **argv) sipx.sipx_type = 17; result = bind(s, (struct sockaddr *) &sipx, sizeof(sipx)); - if (result < 0) { + if (result < 0) + { perror("IPX: bind: "); exit(-1); } - while (1) { + while (1) + { len = 1024; result = recvfrom(s, msg, sizeof(msg), 0, (struct sockaddr *) &sipx, &len); - if (result < 0) { + if (result < 0) + { perror("IPX: recvfrom: "); exit(-1); } @@ -67,7 +74,8 @@ int main(int argc, char **argv) bptr += 2; sp = (struct sap_data *) bptr; - while (result >= sizeof(struct sap_data)) { + while (result >= sizeof(struct sap_data)) + { int i; sp->sap_name[32] = '\0'; diff --git a/man/ipx_configure.8 b/ipx-1.0/ipx_configure.8 similarity index 100% rename from man/ipx_configure.8 rename to ipx-1.0/ipx_configure.8 diff --git a/ipx-1.0/ipx_configure.c b/ipx-1.0/ipx_configure.c index 92e98bb..37ce88e 100644 --- a/ipx-1.0/ipx_configure.c +++ b/ipx-1.0/ipx_configure.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include "kernel/ipx.h" #include #include #include @@ -24,7 +24,8 @@ struct option options[] = char *progname; -void usage(void) +void +usage(void) { fprintf(stderr, "Usage: %s --auto_primary=[on|off]\n\ @@ -33,23 +34,27 @@ Usage: %s --help\n\ Usage: %s\n", progname, progname, progname, progname); } -int map_string_to_bool(char *optarg) +int +map_string_to_bool(char *optarg) { if ((strcasecmp(optarg, "ON") == 0) || (strcasecmp(optarg, "TRUE") == 0) || (strcasecmp(optarg, "SET") == 0) || - (strcasecmp(optarg, "YES") == 0)) { + (strcasecmp(optarg, "YES") == 0)) + { return 1; } else if ((strcasecmp(optarg, "OFF") == 0) || (strcasecmp(optarg, "FALSE") == 0) || (strcasecmp(optarg, "CLEAR") == 0) || - (strcasecmp(optarg, "NO") == 0)) { + (strcasecmp(optarg, "NO") == 0)) + { return 0; } return -1; } -int main(int argc, char **argv) +int +main(int argc, char **argv) { int s; int result; @@ -63,11 +68,13 @@ int main(int argc, char **argv) progname = argv[0]; s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); - if (s < 0) { + if (s < 0) + { int old_errno = errno; sprintf(errmsg, "%s: socket", progname); perror(errmsg); - if (old_errno == -EINVAL) { + if (old_errno == -EINVAL) + { fprintf(stderr, "Probably you have no IPX support in " "your kernel\n"); } @@ -75,20 +82,24 @@ int main(int argc, char **argv) } sprintf(errmsg, "%s: ioctl", progname); while ((result = getopt_long(argc, argv, "", options, - &option_index)) != -1) { - switch (result) { + &option_index)) != -1) + { + switch (result) + { case 1: if (got_auto_pri) break; got_auto_pri++; val = map_string_to_bool(optarg); - if (val < 0) { + if (val < 0) + { usage(); exit(-1); } result = ioctl(s, SIOCAIPXPRISLT, &val); - if (result < 0) { + if (result < 0) + { perror(errmsg); exit(-1); } @@ -99,12 +110,14 @@ int main(int argc, char **argv) got_auto_itf++; val = map_string_to_bool(optarg); - if (val < 0) { + if (val < 0) + { usage(); exit(-1); } result = ioctl(s, SIOCAIPXITFCRT, &val); - if (result < 0) { + if (result < 0) + { perror(errmsg); exit(-1); } @@ -115,15 +128,17 @@ int main(int argc, char **argv) } } result = ioctl(s, SIOCIPXCFGDATA, &data); - if (result < 0) { + if (result < 0) + { perror(errmsg); exit(-1); } - if (argc == 1) { + if (argc == 1) + { fprintf(stdout, "Auto Primary Select is %s\n\ Auto Interface Create is %s\n", (data.ipxcfg_auto_select_primary) ? "ON" : "OFF", - (data.ipxcfg_auto_create_interfaces) ? "ON" : "OFF"); + (data.ipxcfg_auto_create_interfaces) ? "ON" : "OFF"); } exit(0); } diff --git a/man/ipx_interface.8 b/ipx-1.0/ipx_interface.8 similarity index 100% rename from man/ipx_interface.8 rename to ipx-1.0/ipx_interface.8 diff --git a/ipx-1.0/ipx_interface.c b/ipx-1.0/ipx_interface.c index 0ba3da5..7a73a84 100644 --- a/ipx-1.0/ipx_interface.c +++ b/ipx-1.0/ipx_interface.c @@ -11,8 +11,8 @@ #include #include #include -#include -#include +#include "kernel/ipx.h" +#include "kernel/if.h" #include #include #include @@ -21,7 +21,8 @@ static struct ifreq id; static char *progname; -void usage(void) +void +usage(void) { fprintf(stderr, "Usage: %s add [-p] device frame_type [net_number]\n\ Usage: %s del device frame_type\n\ @@ -30,11 +31,12 @@ Usage: %s check device frame_type\n", progname, progname, progname, progname); exit(-1); } -struct frame_type { +struct frame_type +{ char *ft_name; unsigned char ft_val; -} frame_types[] = - +} +frame_types[] = { { "802.2", IPX_FRAME_8022 @@ -61,19 +63,22 @@ struct frame_type { #define NFTYPES (sizeof(frame_types)/sizeof(struct frame_type)) -int lookup_frame_type(char *frame) +int +lookup_frame_type(char *frame) { - int j; + size_t j; for (j = 0; (j < NFTYPES) && (strcasecmp(frame_types[j].ft_name, frame)); - j++); + j++) + ; if (j != NFTYPES) return j; fprintf(stderr, "%s: Frame type must be", progname); - for (j = 0; j < NFTYPES; j++) { + for (j = 0; j < NFTYPES; j++) + { fprintf(stderr, "%s%s", (j == NFTYPES - 1) ? " or " : " ", frame_types[j].ft_name); @@ -82,7 +87,8 @@ int lookup_frame_type(char *frame) return -1; } -int ipx_add_interface(int argc, char **argv) +int +ipx_add_interface(int argc, char **argv) { struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &id.ifr_addr; int s; @@ -95,19 +101,24 @@ int ipx_add_interface(int argc, char **argv) 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) { + while ((c = getopt(argc, argv, "p")) > 0) + { + switch (c) + { case 'p': sipx->sipx_special = IPX_PRIMARY; break; } } - if (((i = (argc - optind)) < 2) || (i > 3)) { + if (((i = (argc - optind)) < 2) || (i > 3)) + { usage(); } - for (i = optind; i < argc; i++) { - switch (i - optind) { + for (i = optind; i < argc; i++) + { + switch (i - optind) + { case 0: /* Physical Device - Required */ strcpy(id.ifr_name, argv[i]); break; @@ -120,9 +131,10 @@ int ipx_add_interface(int argc, char **argv) case 2: /* Network Number - Optional */ netnum = strtoul(argv[i], (char **) NULL, 16); - if (netnum == 0xffffffffL) { + if (netnum == 0xffffffffL) + { fprintf(stderr, - "%s: Inappropriate network number %08lX\n", + "%s: Inappropriate network number %08lX\n", progname, netnum); exit(-1); } @@ -132,11 +144,13 @@ int ipx_add_interface(int argc, char **argv) } s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); - if (s < 0) { + if (s < 0) + { int old_errno = errno; sprintf(errmsg, "%s: socket", progname); perror(errmsg); - if (old_errno == -EINVAL) { + if (old_errno == -EINVAL) + { fprintf(stderr, "Probably you have no IPX support in " "your kernel\n"); } @@ -145,7 +159,8 @@ int ipx_add_interface(int argc, char **argv) i = 0; sipx->sipx_family = AF_IPX; sipx->sipx_action = IPX_CRTITF; - do { + do + { result = ioctl(s, SIOCSIFADDR, &id); i++; } @@ -154,14 +169,15 @@ int ipx_add_interface(int argc, char **argv) if (result == 0) exit(0); - switch (errno) { + 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)); + fprintf(stderr, "%s: Network number (%08X) already in use.\n", + progname, (u_int32_t)htonl(sipx->sipx_network)); break; case EPROTONOSUPPORT: fprintf(stderr, "%s: Invalid frame type (%s).\n", @@ -192,7 +208,8 @@ int ipx_add_interface(int argc, char **argv) exit(-1); } -int ipx_delall_interface(int argc, char **argv) +int +ipx_delall_interface(int argc, char **argv) { struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &id.ifr_addr; int s; @@ -205,26 +222,31 @@ int ipx_delall_interface(int argc, char **argv) FILE *fp; s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); - if (s < 0) { + if (s < 0) + { sprintf(errmsg, "%s: socket", progname); perror(errmsg); exit(-1); } fp = fopen("/proc/net/ipx_interface", "r"); - if (fp == NULL) { + if (fp == NULL) + { fprintf(stderr, - "%s: Unable to open \"/proc/net/ipx_interface.\"\n", + "%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) { + device, frame_type) == 5) + { sipx->sipx_network = 0L; - if (strcasecmp(device, "Internal") == 0) { + if (strcasecmp(device, "Internal") == 0) + { sipx->sipx_special = IPX_INTERNAL; - } else { + } else + { sipx->sipx_special = IPX_SPECIAL_NONE; strcpy(id.ifr_name, device); fti = lookup_frame_type(frame_type); @@ -238,7 +260,8 @@ int ipx_delall_interface(int argc, char **argv) result = ioctl(s, SIOCSIFADDR, &id); if (result == 0) continue; - switch (errno) { + switch (errno) + { case EPROTONOSUPPORT: fprintf(stderr, "%s: Invalid frame type (%s).\n", progname, frame_type); @@ -261,7 +284,8 @@ int ipx_delall_interface(int argc, char **argv) exit(0); } -int ipx_del_interface(int argc, char **argv) +int +ipx_del_interface(int argc, char **argv) { struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &id.ifr_addr; int s; @@ -269,7 +293,8 @@ int ipx_del_interface(int argc, char **argv) char errmsg[80]; int fti; - if (argc != 3) { + if (argc != 3) + { usage(); } sipx->sipx_network = 0L; @@ -281,7 +306,8 @@ int ipx_del_interface(int argc, char **argv) sipx->sipx_type = frame_types[fti].ft_val; s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); - if (s < 0) { + if (s < 0) + { sprintf(errmsg, "%s: socket", progname); perror(errmsg); exit(-1); @@ -292,7 +318,8 @@ int ipx_del_interface(int argc, char **argv) if (result == 0) exit(0); - switch (errno) { + switch (errno) + { case EPROTONOSUPPORT: fprintf(stderr, "%s: Invalid frame type (%s).\n", progname, frame_types[fti].ft_name); @@ -313,7 +340,8 @@ int ipx_del_interface(int argc, char **argv) exit(-1); } -int ipx_check_interface(int argc, char **argv) +int +ipx_check_interface(int argc, char **argv) { struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &id.ifr_addr; int s; @@ -321,7 +349,8 @@ int ipx_check_interface(int argc, char **argv) char errmsg[80]; int fti; - if (argc != 3) { + if (argc != 3) + { usage(); } sipx->sipx_network = 0L; @@ -332,24 +361,27 @@ int ipx_check_interface(int argc, char **argv) sipx->sipx_type = frame_types[fti].ft_val; s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); - if (s < 0) { + 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) { + if (result == 0) + { printf( - "IPX Address for (%s, %s) is %08lX:%02X%02X%02X%02X%02X%02X.\n", + "IPX Address for (%s, %s) is %08X:%02X%02X%02X%02X%02X%02X.\n", argv[1], frame_types[fti].ft_name, - htonl(sipx->sipx_network), sipx->sipx_node[0], + (u_int32_t)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) { + switch (errno) + { case EPROTONOSUPPORT: fprintf(stderr, "%s: Invalid frame type (%s).\n", progname, frame_types[fti].ft_name); @@ -370,28 +402,34 @@ int ipx_check_interface(int argc, char **argv) exit(-1); } -int main(int argc, char **argv) +int +main(int argc, char **argv) { int i; progname = argv[0]; - if (argc < 2) { + if (argc < 2) + { usage(); exit(-1); } - if (strncasecmp(argv[1], "add", 3) == 0) { + 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) { + } else if (strncasecmp(argv[1], "delall", 6) == 0) + { for (i = 1; i < (argc - 1); i++) argv[i] = argv[i + 1]; ipx_delall_interface(argc - 1, argv); - } else if (strncasecmp(argv[1], "del", 3) == 0) { + } else if (strncasecmp(argv[1], "del", 3) == 0) + { for (i = 1; i < (argc - 1); i++) argv[i] = argv[i + 1]; ipx_del_interface(argc - 1, argv); - } else if (strncasecmp(argv[1], "check", 5) == 0) { + } 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); diff --git a/man/ipx_internal_net.8 b/ipx-1.0/ipx_internal_net.8 similarity index 100% rename from man/ipx_internal_net.8 rename to ipx-1.0/ipx_internal_net.8 diff --git a/ipx-1.0/ipx_internal_net.c b/ipx-1.0/ipx_internal_net.c index 121007e..004a8c7 100644 --- a/ipx-1.0/ipx_internal_net.c +++ b/ipx-1.0/ipx_internal_net.c @@ -9,8 +9,8 @@ #include #include #include -#include -#include +#include "kernel/ipx.h" +#include "kernel/if.h" #include #include #include @@ -18,26 +18,32 @@ static struct ifreq id; static char *progname; -void usage(void) +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) +int +map_char_to_val(char dig) { char digit = tolower(dig); - if ((digit >= '0') && (digit <= '9')) { + if ((digit >= '0') && (digit <= '9')) + { return digit - '0'; - } else if ((digit >= 'a') && (digit <= 'f')) { + } else if ((digit >= 'a') && (digit <= 'f')) + { return (10 + (digit - 'a')); - } else { + } else + { return 0; } } -int ipx_add_internal_net(int argc, char **argv) +int +ipx_add_internal_net(int argc, char **argv) { struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &id.ifr_addr; int s; @@ -51,38 +57,45 @@ int ipx_add_internal_net(int argc, char **argv) char *tin; int i; - if (argc != 3) { + if (argc != 3) + { usage(); } netnum = strtoul(argv[1], (char **) NULL, 16); - if ((netnum == 0L) || (netnum == 0xffffffffL)) { + 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) { + 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++); + for (i = 0; (i < nodelen) && isxdigit(node[i]); i++) + ; - if (i < nodelen) { + 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++) { + 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)) { + (memcmp(sipx->sipx_node, "\377\377\377\377\377\377", IPX_NODE_LEN) == 0)) + { fprintf(stderr, "%s: Node is invalid.\n", progname); exit(-1); } @@ -90,7 +103,8 @@ int ipx_add_internal_net(int argc, char **argv) sipx->sipx_type = IPX_FRAME_NONE; sipx->sipx_special = IPX_INTERNAL; s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); - if (s < 0) { + if (s < 0) + { sprintf(errmsg, "%s: socket", progname); perror(errmsg); exit(-1); @@ -98,7 +112,8 @@ int ipx_add_internal_net(int argc, char **argv) sipx->sipx_family = AF_IPX; sipx->sipx_action = IPX_CRTITF; i = 0; - do { + do + { result = ioctl(s, SIOCSIFADDR, &id); i++; } @@ -107,18 +122,19 @@ int ipx_add_internal_net(int argc, char **argv) if (result == 0) exit(0); - switch (errno) { + 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)); + fprintf(stderr, "%s: Network number (%08X) already in use.\n", + progname, (u_int32_t)htonl(sipx->sipx_network)); break; case EAGAIN: fprintf(stderr, - "%s: Insufficient memory to create internal net.\n", + "%s: Insufficient memory to create internal net.\n", progname); break; default: @@ -129,20 +145,23 @@ int ipx_add_internal_net(int argc, char **argv) exit(-1); } -int ipx_del_internal_net(int argc, char **argv) +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) { + if (argc != 1) + { usage(); } sipx->sipx_network = 0L; sipx->sipx_special = IPX_INTERNAL; s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); - if (s < 0) { + if (s < 0) + { sprintf(errmsg, "%s: socket", progname); perror(errmsg); exit(-1); @@ -153,7 +172,8 @@ int ipx_del_internal_net(int argc, char **argv) if (result == 0) exit(0); - switch (errno) { + switch (errno) + { case ENOENT: fprintf(stderr, "%s: No internal network configured.\n", progname); break; @@ -165,20 +185,24 @@ int ipx_del_internal_net(int argc, char **argv) exit(-1); } -int main(int argc, char **argv) +int +main(int argc, char **argv) { int i; progname = argv[0]; - if (argc < 2) { + if (argc < 2) + { usage(); exit(-1); } - if (strncasecmp(argv[1], "add", 3) == 0) { + 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) { + } 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); diff --git a/man/ipx_route.8 b/ipx-1.0/ipx_route.8 similarity index 100% rename from man/ipx_route.8 rename to ipx-1.0/ipx_route.8 diff --git a/ipx-1.0/ipx_route.c b/ipx-1.0/ipx_route.c index bdb4381..47df63b 100644 --- a/ipx-1.0/ipx_route.c +++ b/ipx-1.0/ipx_route.c @@ -11,28 +11,33 @@ #include #include #include -#include +#include "kernel/ipx.h" #include #include #include -#include +#include "kernel/route.h" static struct rtentry rd; static char *progname; -int map_char_to_val(char dig) +int +map_char_to_val(char dig) { char digit = tolower(dig); - if ((digit >= '0') && (digit <= '9')) { + if ((digit >= '0') && (digit <= '9')) + { return digit - '0'; - } else if ((digit >= 'a') && (digit <= 'f')) { + } else if ((digit >= 'a') && (digit <= 'f')) + { return (10 + (digit - 'a')); - } else { + } else + { return 0; } } -void usage(void) +void +usage(void) { fprintf(stderr, "Usage: %s add network(hex) router_network(hex) router_node(hex)\n\ @@ -40,7 +45,8 @@ Usage: %s del network(hex)\n", progname, progname); exit(-1); } -int ipx_add_route(int argc, char **argv) +int +ipx_add_route(int argc, char **argv) { /* Router */ struct sockaddr_ipx *sr = (struct sockaddr_ipx *) &rd.rt_gateway; @@ -62,7 +68,8 @@ int ipx_add_route(int argc, char **argv) /* Network Number */ netnum = strtoul(argv[1], (char **) NULL, 16); - if ((netnum == 0xffffffffL) || (netnum == 0L)) { + if ((netnum == 0xffffffffL) || (netnum == 0L)) + { fprintf(stderr, "%s: Inappropriate network number %08lX\n", progname, netnum); exit(-1); @@ -72,7 +79,8 @@ int ipx_add_route(int argc, char **argv) /* Router Network Number */ netnum = strtoul(argv[2], (char **) NULL, 16); - if ((netnum == 0xffffffffL) || (netnum == 0L)) { + if ((netnum == 0xffffffffL) || (netnum == 0L)) + { fprintf(stderr, "%s: Inappropriate network number %08lX\n", progname, netnum); exit(-1); @@ -82,40 +90,47 @@ int ipx_add_route(int argc, char **argv) /* Router Node */ node = argv[3]; nodelen = strlen(node); - if (nodelen > 12) { + 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++); + for (i = 0; (i < nodelen) && isxdigit(node[i]); i++) + ; - if (i < nodelen) { + 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++) { + 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)) { + (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) { + if (s < 0) + { sprintf(errmsg, "%s: socket", progname); perror(errmsg); exit(-1); } sr->sipx_family = st->sipx_family = AF_IPX; i = 0; - do { + do + { result = ioctl(s, SIOCADDRT, &rd); i++; } @@ -124,10 +139,11 @@ int ipx_add_route(int argc, char **argv) if (result == 0) exit(0); - switch (errno) { + switch (errno) + { case ENETUNREACH: - fprintf(stderr, "%s: Router network (%08lX) not reachable.\n", - progname, htonl(sr->sipx_network)); + fprintf(stderr, "%s: Router network (%08X) not reachable.\n", + progname, (u_int32_t)htonl(sr->sipx_network)); break; default: sprintf(errmsg, "%s: ioctl", progname); @@ -137,7 +153,8 @@ int ipx_add_route(int argc, char **argv) exit(-1); } -int ipx_del_route(int argc, char **argv) +int +ipx_del_route(int argc, char **argv) { /* Router */ struct sockaddr_ipx *sr = (struct sockaddr_ipx *) &rd.rt_gateway; @@ -148,13 +165,15 @@ int ipx_del_route(int argc, char **argv) unsigned long netnum; char errmsg[80]; - if (argc != 2) { + if (argc != 2) + { usage(); } rd.rt_flags = RTF_GATEWAY; /* Network Number */ netnum = strtoul(argv[1], (char **) NULL, 16); - if ((netnum == 0xffffffffL) || (netnum == 0L)) { + if ((netnum == 0xffffffffL) || (netnum == 0L)) + { fprintf(stderr, "%s: Inappropriate network number %08lX.\n", progname, netnum); exit(-1); @@ -163,7 +182,8 @@ int ipx_del_route(int argc, char **argv) st->sipx_family = sr->sipx_family = AF_IPX; s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); - if (s < 0) { + if (s < 0) + { sprintf(errmsg, "%s: socket", progname); perror(errmsg); exit(-1); @@ -172,7 +192,8 @@ int ipx_del_route(int argc, char **argv) if (result == 0) exit(0); - switch (errno) { + switch (errno) + { case ENOENT: fprintf(stderr, "%s: Route not found for network %08lX.\n", progname, netnum); @@ -189,20 +210,24 @@ int ipx_del_route(int argc, char **argv) exit(-1); } -int main(int argc, char **argv) +int +main(int argc, char **argv) { int i; progname = argv[0]; - if (argc < 2) { + if (argc < 2) + { usage(); exit(-1); } - if (strncasecmp(argv[1], "add", 3) == 0) { + 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) { + } 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); diff --git a/ipxdump/Makefile b/ipxdump/Makefile index b67fab8..08372dd 100644 --- a/ipxdump/Makefile +++ b/ipxdump/Makefile @@ -1,6 +1,6 @@ EXEC= ipxdump ipxparse -CFLAGS= -Wall -O2 +CFLAGS= -Wall -O2 -I../include OBJECTS= ipxutil.o all: $(EXEC) diff --git a/ipxdump/ipxdump.c b/ipxdump/ipxdump.c index 4844865..69744fe 100644 --- a/ipxdump/ipxdump.c +++ b/ipxdump/ipxdump.c @@ -21,26 +21,27 @@ #include #include #include -#include +#include #include #include -#include +#include #include -#include -#include -#include +#include +#include #include #include #include #include "ipxutil.h" -struct ipx_address { +struct ipx_address +{ unsigned long net; unsigned char node[IPX_NODE_LEN]; unsigned short sock; }; -struct ipx_packet { +struct ipx_packet +{ unsigned short ipx_checksum; #define IPX_NO_CHECKSUM 0xFFFF unsigned short ipx_pktsize; @@ -61,15 +62,18 @@ void handle_frame(unsigned char *buf, int length, struct sockaddr *saddr); void handle_ipx(char *frame, unsigned char *buf); static int filter = 0; +static int allframes = 0; static IPXNode filter_node; static int exit_request = 0; -static void int_handler() +static void +int_handler() { exit_request = 1; } -void main(int argc, char *argv[]) +void +main(int argc, char *argv[]) { int sd; struct ifreq ifr, oldifr; @@ -81,14 +85,30 @@ void main(int argc, char *argv[]) signal(SIGINT, int_handler); - if (argc > 1) { - if (ipx_sscanf_node(argv[1], filter_node) != 0) { - fprintf(stderr, "usage: %s [node]\n", argv[0]); + while (1) { + int opt; + + opt = getopt(argc, argv, "r"); + if (opt == -1) break; + switch (opt) { + case 'r':allframes = 1; break; + case ':':; + case '?':break; + default: printf("?? unknown option returned by getopt\n"); + break; + } + } + if (optind < argc) + { + if (ipx_sscanf_node(argv[optind], filter_node) != 0) + { + fprintf(stderr, "usage: %s [-a] [node]\n", argv[0]); exit(1); } filter = 1; } - if ((sd = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL))) < 0) { + 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); @@ -96,7 +116,8 @@ void main(int argc, char *argv[]) /* SET PROMISC */ strcpy(oldifr.ifr_name, device); - if (ioctl(sd, SIOCGIFFLAGS, &oldifr) < 0) { + if (ioctl(sd, SIOCGIFFLAGS, &oldifr) < 0) + { close(sd); perror("Can't get flags"); exit(2); @@ -105,12 +126,14 @@ void main(int argc, char *argv[]) ifr = oldifr; ifr.ifr_flags |= IFF_PROMISC; - if (ioctl(sd, SIOCSIFFLAGS, &ifr) < 0) { + if (ioctl(sd, SIOCSIFFLAGS, &ifr) < 0) + { close(sd); perror("Can't set flags"); exit(3); } - while (exit_request == 0) { + while (exit_request == 0) + { /* This is the main data-gathering loop; keep it small and fast */ sizeaddr = sizeof(saddr); @@ -118,11 +141,23 @@ void main(int argc, char *argv[]) &saddr, &sizeaddr); if (length < 0) continue; - handle_frame(buf, length, &saddr); + if (allframes) { + unsigned char* ptr = buf; + if (filter) { + if (memcmp(filter_node, buf, 6)&&memcmp(filter_node, buf+6, 6)) + continue; + } + printf("raweth "); + while (length--) printf("%02X", *ptr++); + printf("\n"); + } else { + handle_frame(buf, length, &saddr); + } } /* This should be rewritten to cooperate with other net tools */ - if (ioctl(sd, SIOCSIFFLAGS, &oldifr) < 0) { + if (ioctl(sd, SIOCSIFFLAGS, &oldifr) < 0) + { close(sd); perror("Can't set flags"); exit(4); @@ -131,7 +166,8 @@ void main(int argc, char *argv[]) exit(0); } -void handle_ipx(char *frame, unsigned char *buf) +void +handle_ipx(char *frame, unsigned char *buf) { int i; struct ipx_packet *h = (struct ipx_packet *) buf; @@ -151,32 +187,38 @@ void handle_ipx(char *frame, unsigned char *buf) d_addr.sipx_port = h->ipx_dest.sock; d_addr.sipx_network = h->ipx_dest.net; - if (filter != 0) { + 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)) { + sizeof(filter_node)) != 0)) + { /* Not for us */ return; } } printf("%s ", frame); - for (i = 0; i < length; i++) { + for (i = 0; i < length; i++) + { printf("%2.2X", buf[i]); } printf("\n"); - if (!isatty(STDOUT_FILENO)) { + if (!isatty(STDOUT_FILENO)) + { fflush(stdout); } } -void handle_other(unsigned char *buf, int length, struct sockaddr *saddr) +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) { + 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 @@ -184,28 +226,33 @@ void handle_other(unsigned char *buf, int length, struct sockaddr *saddr) * for fault tolerant netware but does for the rest. */ - if (*(unsigned short *) p == 0xffff) { + if (*(unsigned short *) p == 0xffff) + { handle_ipx("802.3", p); return; } if ((*(unsigned short *) p == htons(0xe0e0)) - && (p[2] == 0x03)) { + && (p[2] == 0x03)) + { handle_ipx("802.2", p + 3); return; } - if (memcmp(p, "\252\252\003\000\000\000\201\067", 8) == 0) { + 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) +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): + switch (htons(packet_type)) + { + case ETH_P_IPX: handle_ipx("EtherII", &(buf[sizeof(struct ethhdr)])); break; default: diff --git a/ipxdump/ipxparse.c b/ipxdump/ipxparse.c index 6f3562f..04a828a 100644 --- a/ipxdump/ipxparse.c +++ b/ipxdump/ipxparse.c @@ -21,29 +21,34 @@ #include #include #include -#include +#include #include #include -#include +#include #include -#include -#include -#include +#include +#include #include #include #include #include #include "ipxutil.h" +#define __u8 u_int8_t +#define __u16 u_int16_t +#define __u32 u_int32_t + #define DUMPALLSAPS /* #define if you want to dump all SAP's */ -struct ipx_address { +struct ipx_address +{ unsigned long net; unsigned char node[IPX_NODE_LEN]; unsigned short sock; }; -struct ipx_packet { +struct ipx_packet +{ unsigned short ipx_checksum; #define IPX_NO_CHECKSUM 0xFFFF unsigned short ipx_pktsize; @@ -63,7 +68,8 @@ struct ipx_packet { #define NCP_REQUEST (0x2222) #define NCP_DEALLOC_SLOT_REQUEST (0x5555) -struct ncp_request_header { +struct ncp_request_header +{ __u16 type __attribute__((packed)); __u8 sequence __attribute__((packed)); __u8 conn_low __attribute__((packed)); @@ -76,7 +82,8 @@ struct ncp_request_header { #define NCP_REPLY (0x3333) #define NCP_POSITIVE_ACK (0x9999) -struct ncp_reply_header { +struct ncp_reply_header +{ __u16 type __attribute__((packed)); __u8 sequence __attribute__((packed)); __u8 conn_low __attribute__((packed)); @@ -89,7 +96,8 @@ struct ncp_reply_header { #define NCP_BURST_PACKET (0x7777) -struct ncp_burst_header { +struct ncp_burst_header +{ __u16 type __attribute__((packed)); __u8 system_flags __attribute__((packed)); __u8 stream_type __attribute__((packed)); @@ -120,29 +128,37 @@ int handle_burst(struct sockaddr_ipx *source, /* SAP Query structure (returned in sap_packet as an array) * NBO == Network Byte Order) */ -typedef struct saps { +typedef struct saps +{ __u16 serverType __attribute__((packed)); /* NBO */ __u8 serverName[SAP_MAX_SERVER_NAME_LENGTH] __attribute__((packed)); struct ipx_address serverAddress __attribute__((packed)); __u16 serverHops __attribute__((packed)); /* NBO */ -} SAPS; +} +SAPS; /* General Service/Nearest Server Response SAP packet */ -union sap_packet { +union sap_packet +{ unsigned short sapOperation; - struct sap_query { + struct sap_query + { __u16 sapOperation __attribute__((packed)); __u16 serverType __attribute__((packed)); - } query; - struct sap_response { + } + query; + struct sap_response + { __u16 sapOperation __attribute__((packed)); /* each SAP can has a max of SAP_MAX_SAPS_PER_PACKET packets */ SAPS sap[SAP_MAX_SAPS_PER_PACKET] __attribute__((packed)); - } response; + } + response; }; /* print out one SAP record */ -static void print_sap(FILE * file, SAPS * sapp) +static void +print_sap(FILE * file, SAPS * sapp) { fprintf(file, " Name:%s, serverType 0x%x, ", sapp->serverName, @@ -155,7 +171,8 @@ static void print_sap(FILE * file, SAPS * sapp) fprintf(file, " (Hops %d)\n", ntohs(sapp->serverHops)); } -void handle_ipx(unsigned char *buf, int length, char *frame, int no) +void +handle_ipx(unsigned char *buf, int length, char *frame, int no) { struct ipx_packet *h = (struct ipx_packet *) buf; struct sockaddr_ipx s_addr; @@ -183,11 +200,13 @@ void handle_ipx(unsigned char *buf, int length, char *frame, int no) printf("\n"); if (handle_burst(&s_addr, &d_addr, buf + sizeof(struct ipx_packet), - length - sizeof(struct ipx_packet), no) != 0) { + length - sizeof(struct ipx_packet), no) != 0) + { return; } if ((ntohs(s_addr.sipx_port) == 0x451) - || (ntohs(d_addr.sipx_port) == 0x451)) { + || (ntohs(d_addr.sipx_port) == 0x451)) + { handle_ncp(&s_addr, &d_addr, buf + sizeof(struct ipx_packet), length - sizeof(struct ipx_packet), no); } else @@ -198,21 +217,25 @@ void handle_ipx(unsigned char *buf, int length, char *frame, int no) printf(" type 0x05 (SPX sequenced packet)\n"); else if (h->ipx_type == 0x14) printf(" type 0x14 (propogated Client-NetBios)\n"); - else { + else + { hbo_dsock = ntohs(d_addr.sipx_port); - if (hbo_dsock == 0x452) { /* SAP */ + if (hbo_dsock == 0x452) /* SAP */ + { sappacket = (union sap_packet *) (buf + sizeof(struct ipx_packet)); hbo_sapop = ntohs(sappacket->sapOperation); - if ((hbo_sapop == 0x01) || (hbo_sapop == 0x03)) { + if ((hbo_sapop == 0x01) || (hbo_sapop == 0x03)) + { printf(" type 0x%x, SAP op:0x%x %s Query, " "serverType 0x%x wanted\n", h->ipx_type, hbo_sapop, - (hbo_sapop == 0x01) ? "General Service" : - (hbo_sapop == 0x03) ? "Nearest Server" : + (hbo_sapop == 0x01) ? "General Service" : + (hbo_sapop == 0x03) ? "Nearest Server" : "Error", - ntohs(sappacket->query.serverType)); - } else { + ntohs(sappacket->query.serverType)); + } else + { int hops; hops = ntohs(sappacket-> @@ -228,18 +251,20 @@ void handle_ipx(unsigned char *buf, int length, char *frame, int no) ? "[Shutdown]" : ""); /* Service ending */ - if (hops >= SAP_SHUTDOWN) { + if (hops >= SAP_SHUTDOWN) + { print_sap(stdout, - sappacket->response.sap); + sappacket->response.sap); } #ifdef DUMPALLSAPS /* If you want to dump all SAP's */ - else { + else + { int num_saps; SAPS *sapp; num_saps = (length - - sizeof(struct ipx_packet) + - sizeof(struct ipx_packet) - 2) / sizeof(SAPS); sapp = sappacket->response.sap; @@ -263,13 +288,15 @@ void handle_ipx(unsigned char *buf, int length, char *frame, int no) } -int handle_burst(struct sockaddr_ipx *source, - struct sockaddr_ipx *target, - unsigned char *buf, int length, int no) +int +handle_burst(struct sockaddr_ipx *source, + struct sockaddr_ipx *target, + unsigned char *buf, int length, int no) { struct ncp_burst_header *rq = (struct ncp_burst_header *) buf; - if (rq->type != NCP_BURST_PACKET) { + if (rq->type != NCP_BURST_PACKET) + { return 0; } printf("Burst Packet\n"); @@ -279,22 +306,25 @@ int handle_burst(struct sockaddr_ipx *source, rq->source_conn, rq->dest_conn, (unsigned int) ntohl(rq->packet_sequence)); printf("Send Delay: %08X, Burst Seq: %04X, Ack Seq: %04X\n", - (unsigned int) ntohl(rq->send_delay), ntohs(rq->burst_sequence), + (unsigned int) ntohl(rq->send_delay), ntohs(rq->burst_sequence), ntohs(rq->ack_sequence)); printf("Burst Length: %08X\n", (unsigned int) ntohl(rq->burst_length)); printf("Data Offset: %08X, Data Bytes: %04X, Missing Frags: %04X\n", - (unsigned int) ntohl(rq->data_offset), ntohs(rq->data_bytes), + (unsigned int) ntohl(rq->data_offset), ntohs(rq->data_bytes), ntohs(rq->missing_frags)); - if (ntohs(rq->data_bytes) == 24) { - struct ncp_burst_request { + if (ntohs(rq->data_bytes) == 24) + { + struct ncp_burst_request + { struct ncp_burst_header h __attribute__((packed)); __u32 function __attribute__((packed)); __u32 file_handle __attribute__((packed)); __u8 reserved[8] __attribute__((packed)); __u32 file_offset __attribute__((packed)); __u32 number_of_bytes __attribute__((packed)); - } *brq = (struct ncp_burst_request *) rq; + } + *brq = (struct ncp_burst_request *) rq; printf("Assuming Burst Request:\n"); printf("%s: Handle %08X, Offset %08X, Bytes %08X\n", @@ -307,9 +337,10 @@ int handle_burst(struct sockaddr_ipx *source, return 1; } -void handle_ncp(struct sockaddr_ipx *source, - struct sockaddr_ipx *target, - unsigned char *buf, int length, int no) +void +handle_ncp(struct sockaddr_ipx *source, + struct sockaddr_ipx *target, + unsigned char *buf, int length, int no) { struct ncp_request_header *rq = (struct ncp_request_header *) buf; struct ncp_reply_header *rs = (struct ncp_reply_header *) buf; @@ -321,7 +352,8 @@ void handle_ncp(struct sockaddr_ipx *source, static struct ncp_request_header request_header; static char request_data[5]; - if (ntohs(rq->type) == NCP_REQUEST) { + if (ntohs(rq->type) == NCP_REQUEST) + { /* Request */ printf("NCP request: conn: %-5d, seq: %-3d, task: %-3d, ", rq->conn_low + 256 * rq->conn_high, @@ -334,7 +366,8 @@ void handle_ncp(struct sockaddr_ipx *source, data = buf + sizeof(struct ncp_request_header); data_length = length - sizeof(struct ncp_request_header); - switch (rq->function) { + switch (rq->function) + { case 18: printf("fn: %-3d\n", rq->function); printf("Get Volume Info with Number\n"); @@ -346,7 +379,8 @@ void handle_ncp(struct sockaddr_ipx *source, case 21: printf("fn: %-3d, subfn: %-3d\n", rq->function, data[2]); - switch (data[2]) { + switch (data[2]) + { case 0: printf("Send Broadcast Message\n"); break; @@ -360,7 +394,8 @@ void handle_ncp(struct sockaddr_ipx *source, case 22: printf("fn: %-3d, subfn: %-3d\n", rq->function, data[2]); - switch (data[2]) { + switch (data[2]) + { case 00: printf("Set Directory Handle\n"); break; @@ -404,7 +439,8 @@ void handle_ncp(struct sockaddr_ipx *source, case 23: printf("fn: %-3d, subfn: %-3d\n", rq->function, data[2]); - switch (data[2]) { + switch (data[2]) + { case 17: printf("Get Fileserver Information\n"); break; @@ -527,7 +563,8 @@ void handle_ncp(struct sockaddr_ipx *source, case 87: printf("fn: %-3d, subfn: %-3d\n", rq->function, data[0]); - switch (data[0]) { + switch (data[0]) + { case 1: { unsigned char *p = &(data[0]); @@ -537,7 +574,7 @@ void handle_ncp(struct sockaddr_ipx *source, printf("Search Attributes: %x\n", *(__u16 *) & (p[3])); printf("Return Information Mask: %x\n", - (unsigned int) (*(__u32 *) & (p[5]))); + (unsigned int) (*(__u32 *) & (p[5]))); printf("Desired Access Rights: %x\n", *(__u16 *) & (p[9])); break; @@ -564,10 +601,12 @@ void handle_ncp(struct sockaddr_ipx *source, break; case 97: { - struct INPUT { + struct INPUT + { __u16 proposed_max_size; __u8 security_flag; - } *i = (struct INPUT *) data; + } + *i = (struct INPUT *) data; printf("fn: %-3d\n", rq->function); printf("Get Big Packet NCP Max Packet Size\n"); @@ -579,26 +618,28 @@ void handle_ncp(struct sockaddr_ipx *source, } case 101: { - struct INPUT { + struct INPUT + { __u32 local_conn_id; __u32 local_max_packet_size; __u16 local_target_socket; __u32 local_max_send_size; __u32 local_max_recv_size; - } *i = (struct INPUT *) data; + } + *i = (struct INPUT *) data; printf("fn: %-3d\n", rq->function); printf("Packet Burst Connection Request\n"); - printf("local_conn_id: %lx\n", - ntohl(i->local_conn_id)); - printf("local_max_packet_size: %lx\n", - ntohl(i->local_max_packet_size)); - printf("local_target_socket: %lx\n", - ntohl(i->local_target_socket)); - printf("local_max_send_size: %lx\n", - ntohl(i->local_max_send_size)); - printf("local_max_recv_size: %lx\n", - ntohl(i->local_max_recv_size)); + printf("local_conn_id: %x\n", + (u_int32_t)ntohl(i->local_conn_id)); + printf("local_max_packet_size: %x\n", + (u_int32_t)ntohl(i->local_max_packet_size)); + printf("local_target_socket: %x\n", + (u_int32_t)ntohl(i->local_target_socket)); + printf("local_max_send_size: %x\n", + (u_int32_t)ntohl(i->local_max_send_size)); + printf("local_max_recv_size: %x\n", + (u_int32_t)ntohl(i->local_max_recv_size)); } break; case 104: @@ -617,20 +658,23 @@ void handle_ncp(struct sockaddr_ipx *source, workstation, and tell me whether anything of this makes sense at all. */ - switch (data[0]) { + switch (data[0]) + { case 1: printf("Ping for NDS\n"); break; case 2: { - struct INPUT { + struct INPUT + { __u8 subfunction_code; __u32 fragger_handle; __u32 max_fragment_size; __u32 message_size; __u32 fragment_flag; __u32 verb; - } *i = (struct INPUT *) data; + } + *i = (struct INPUT *) data; printf("Send NDS Fragment Request/Reply\n"); printf("fragger_handle: %lx\n", (unsigned long) i->fragger_handle); @@ -642,7 +686,8 @@ void handle_ncp(struct sockaddr_ipx *source, (unsigned long) i->fragment_flag); printf("verb: %d\n", i->verb); - switch (i->verb) { + switch (i->verb) + { case 1: printf("Resolve Name\n"); break; @@ -899,7 +944,8 @@ void handle_ncp(struct sockaddr_ipx *source, printf("fn: %-3d\n", rq->function); } } - if (ntohs(rs->type) == NCP_REPLY) { + if (ntohs(rs->type) == NCP_REPLY) + { printf("NCP respons: conn: %-5d, seq: %-3d, task: %-3d, ", rs->conn_low + 256 * rs->conn_high, rs->sequence, rs->task); @@ -911,20 +957,25 @@ void handle_ncp(struct sockaddr_ipx *source, if ((memcmp(&request_source, target, sizeof(request_source)) == 0) - && (request_header.sequence == rs->sequence)) { - switch (request_header.function) { + && (request_header.sequence == rs->sequence)) + { + switch (request_header.function) + { case 22: - switch (request_data[2]) { + switch (request_data[2]) + { case 18: { - struct XDATA { + struct XDATA + { __u8 new_directory_handle; __u8 access_rights_mask; - } *x = (struct XDATA *) data; + } + *x = (struct XDATA *) data; printf("new_directory_handle: %x\n", - x->new_directory_handle); + x->new_directory_handle); printf("access_rights_mask: %x\n", - x->access_rights_mask); + x->access_rights_mask); } break; } @@ -935,13 +986,15 @@ void handle_ncp(struct sockaddr_ipx *source, break; case 97: { - struct XDATA { + struct XDATA + { __u16 accepted_max_size; __u16 echo_socket; __u8 security_flag; - } *x = (struct XDATA *) data; + } + *x = (struct XDATA *) data; printf("accepted_max_size: %x\n", - ntohs(x->accepted_max_size)); + ntohs(x->accepted_max_size)); printf("echo_socket: %x\n", ntohs(x->echo_socket)); printf("security_flag: %x\n", @@ -950,44 +1003,55 @@ void handle_ncp(struct sockaddr_ipx *source, break; case 101: { - struct XDATA { + struct XDATA + { __u8 completion_code; __u32 remote_target_id; __u32 remote_max_packet_size; - } *x = (struct XDATA *) data; + } + *x = (struct XDATA *) data; printf("completion_code: %x\n", x->completion_code); - printf("remote_target_id: %lx\n", - ntohl(x->remote_target_id)); - printf("remote_max_packet_size: %lx\n", - ntohl(x->remote_max_packet_size)); + printf("remote_target_id: %x\n", + (u_int32_t)ntohl(x->remote_target_id)); + printf("remote_max_packet_size: %x\n", + (u_int32_t)ntohl(x->remote_max_packet_size)); } break; } } } - if (data == NULL) { + if (data == NULL) + { data = buf; data_length = length; } i = 0; - while (i < data_length) { + while (i < data_length) + { int j; - for (j = i; j < i + 16; j++) { - if (j >= data_length) { + for (j = i; j < i + 16; j++) + { + if (j >= data_length) + { printf(" "); - } else { + } else + { printf("%-2.2X", data[j]); } } printf(" "); - for (j = i; j < i + 16; j++) { - if (j >= data_length) { + for (j = i; j < i + 16; j++) + { + if (j >= data_length) + { break; } - if (isprint(data[j])) { + if (isprint(data[j])) + { printf("%c", data[j]); - } else { + } else + { printf("."); } } @@ -998,7 +1062,8 @@ void handle_ncp(struct sockaddr_ipx *source, } -void main(int argc, char *argv[]) +void +main(int argc, char *argv[]) { unsigned char buf[16384]; unsigned char packet[8192]; @@ -1006,13 +1071,16 @@ void main(int argc, char *argv[]) int len; int i = 1; - while (fgets(buf, sizeof(buf), stdin) != NULL) { - if (strlen(buf) == sizeof(buf) - 1) { + while (fgets(buf, sizeof(buf), stdin) != NULL) + { + if (strlen(buf) == sizeof(buf) - 1) + { fprintf(stderr, "line too long\n"); exit(1); } b = strchr(buf, ' '); - if (b == NULL) { + if (b == NULL) + { fprintf(stderr, "illegal line format\n"); exit(1); } @@ -1020,9 +1088,11 @@ void main(int argc, char *argv[]) b += 1; len = 0; - while ((b[0] != '\0') && (b[1] != '\0')) { + while ((b[0] != '\0') && (b[1] != '\0')) + { unsigned int value; - if (sscanf(b, "%2x", &value) != 1) { + if (sscanf(b, "%2x", &value) != 1) + { fprintf(stderr, "illegal packet\n"); exit(1); } diff --git a/ipxdump/ipxutil.c b/ipxdump/ipxutil.c index d3fba8b..7fe5c4c 100644 --- a/ipxdump/ipxutil.c +++ b/ipxdump/ipxutil.c @@ -27,7 +27,8 @@ #include #include "ipxutil.h" -void ipx_fprint_node(FILE * file, IPXNode node) +void +ipx_fprint_node(FILE * file, IPXNode node) { fprintf(file, "%02X%02X%02X%02X%02X%02X", (unsigned char) node[0], @@ -39,17 +40,20 @@ void ipx_fprint_node(FILE * file, IPXNode node) ); } -void ipx_fprint_network(FILE * file, IPXNet net) +void +ipx_fprint_network(FILE * file, IPXNet net) { fprintf(file, "%08lX", net); } -void ipx_fprint_port(FILE * file, IPXPort port) +void +ipx_fprint_port(FILE * file, IPXPort port) { fprintf(file, "%04X", port); } -void ipx_fprint_saddr(FILE * file, struct sockaddr_ipx *sipx) +void +ipx_fprint_saddr(FILE * file, struct sockaddr_ipx *sipx) { ipx_fprint_network(file, ntohl(sipx->sipx_network)); fprintf(file, ":"); @@ -58,55 +62,66 @@ void ipx_fprint_saddr(FILE * file, struct sockaddr_ipx *sipx) ipx_fprint_port(file, ntohs(sipx->sipx_port)); } -void ipx_print_node(IPXNode node) +void +ipx_print_node(IPXNode node) { ipx_fprint_node(stdout, node); } -void ipx_print_network(IPXNet net) +void +ipx_print_network(IPXNet net) { ipx_fprint_network(stdout, net); } -void ipx_print_port(IPXPort port) +void +ipx_print_port(IPXPort port) { ipx_fprint_port(stdout, port); } -void ipx_print_saddr(struct sockaddr_ipx *sipx) +void +ipx_print_saddr(struct sockaddr_ipx *sipx) { ipx_fprint_saddr(stdout, sipx); } -void ipx_assign_node(IPXNode dest, IPXNode src) +void +ipx_assign_node(IPXNode dest, IPXNode src) { memcpy(dest, src, sizeof(IPXNode)); } -int ipx_node_equal(IPXNode n1, IPXNode n2) +int +ipx_node_equal(IPXNode n1, IPXNode n2) { return memcmp(n1, n2, sizeof(IPXNode)) == 0; } -int ipx_sscanf_node(char *buf, IPXNode node) +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) { + &(n[3]), &(n[4]), &(n[5]))) != 6) + { return -1; } - for (i = 0; i < 6; i++) { + for (i = 0; i < 6; i++) + { node[i] = n[i]; } return 0; } -int ipx_sscanf_net(char *buf, IPXNet * target) +int +ipx_sscanf_net(char *buf, IPXNet * target) { - if (sscanf(buf, "%8lX", target) == 1) { + if (sscanf(buf, "%8lX", target) == 1) + { return 0; } return -1; diff --git a/ipxdump/ipxutil.h b/ipxdump/ipxutil.h index e259a58..3c7a78d 100644 --- a/ipxdump/ipxutil.h +++ b/ipxdump/ipxutil.h @@ -25,7 +25,7 @@ #define __IPXUTIL_H__ #include -#include +#include "kernel/ipx.h" #define IPX_MAX_ERROR (255) #define IPX_THIS_NET (0) diff --git a/lib-shared/Makefile b/lib-shared/Makefile new file mode 100644 index 0000000..f964e20 --- /dev/null +++ b/lib-shared/Makefile @@ -0,0 +1,28 @@ +include ../Makeinit +NCPLIB = libncp.so +NCPLIB_BIN = $(NCPLIB).1.0 +NCPLIB_SONAME = $(NCPLIB).1 +CCFLAGS += -I../include -I. +PIC_FLAG = -fPIC +export PIC_FLAG +CCFLAGS += $(PIC_FLAG) + +vpath %.c ../lib +vpath %.et ../lib + +include ../lib/Makelib + +install: all + rm -f $(LIBSODIR)/$(NCPLIB) + install $(NCPLIB_BIN) $(LIBSODIR) + ldconfig + ln -sf $(NCPLIB_SONAME) $(LIBSODIR)/$(NCPLIB) + +$(NCPLIB): $(NCPLIB_BIN) + rm -f $@ + ln -sf $< $@ + +$(NCPLIB_BIN): $(O_OBJ) $(O_LIB) + $(CC) -shared -o $@ -Wl,-soname=$(NCPLIB_SONAME) $(O_OBJ) -lc + + diff --git a/lib-static-su/Makefile b/lib-static-su/Makefile new file mode 100644 index 0000000..e4cc037 --- /dev/null +++ b/lib-static-su/Makefile @@ -0,0 +1,17 @@ +include ../Makeinit +NCPLIB = libncp.a +NCPLIB_BIN := $(NCPLIB) +CCFLAGS += -I../include -I. +CCFLAGS += -D__MAKE_SULIB__ + +vpath %.c ../lib +vpath %.et ../lib + +include ../lib/Makelib + +install: + +$(NCPLIB_BIN): $(O_OBJ) + ar r $@ $(O_OBJ) + + diff --git a/lib-static/Makefile b/lib-static/Makefile new file mode 100644 index 0000000..fb3b38f --- /dev/null +++ b/lib-static/Makefile @@ -0,0 +1,17 @@ +include ../Makeinit +NCPLIB = libncp.a +NCPLIB_BIN = $(NCPLIB) +CCFLAGS += -I../include -I. + +vpath %.c ../lib +vpath %.et ../lib + +include ../lib/Makelib + +install: all + install $(NCPLIB_BIN) $(LIBADIR) + +$(NCPLIB_BIN): $(O_OBJ) + ar r $@ $(O_OBJ) + + diff --git a/lib/Makefile b/lib/Makefile index 5e73e9f..151fedd 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -2,70 +2,19 @@ # 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) +all: install: - $(INSTALL_LIB) - -ncplib.o: ncplib.c ncplib_err.h - $(CC) $(CFLAGS) -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 + make -C com_err install clean: make -C com_err clean - rm -f *.o *~ ncplib_err.[ch] ../include/ncplib_err.h - rm -f libncp.* -mrproper: clean +mrproper: make -C com_err mrproper - rm -f $(UTILS) .depend $(DISTFILE) # # include a dependency file if one exists diff --git a/lib/Makelib b/lib/Makelib new file mode 100644 index 0000000..2d545c0 --- /dev/null +++ b/lib/Makelib @@ -0,0 +1,61 @@ +# +# Makefile for the linux ncp-filesystem routines. +# + +BASE_OBJ = ncplib.o +ifdef NDS_SUPPORT +NDS_OBJ = ndslib.o mpilib.o +BASE_OBJ += ndscrypt.o +endif +ifdef SIGNATURES +BASE_OBJ += ncpsign.o +endif + +O_OBJ := $(BASE_OBJ) $(NDS_OBJ) ncplib_err.o + +all: $(NCPLIB) + +$(NDS_OBJ): %.o: %.c ncplib_err.h + $(CC) $(CFLAGS) $(CCFLAGS) -DPORTABLE -DSMITH -DUNIT32 -DMUNIT16 -o $@ -c $< + +$(BASE_OBJ): %.o: %.c ncplib_err.h + $(CC) $(CFLAGS) $(CCFLAGS) -o $@ -c $< + +COM_ERR = ../lib/com_err + +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 + +O_OBJ += $(COM_ERR_OFILES) + +$(COM_ERR_OFILES): %.o: %.c + make -C $(COM_ERR) + +ncplib_err.o: ncplib_err.h ncplib_err.c + $(CC) $(CFLAGS) $(CCFLAGS) -c ncplib_err.c + +ncplib_err.h ncplib_err.c: ncplib_err.et + $(COM_ERR)/compile_et ../lib/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.* libcom_err.a + +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 + diff --git a/lib/com_err/Makefile b/lib/com_err/Makefile index eeafb15..9a415bd 100644 --- a/lib/com_err/Makefile +++ b/lib/com_err/Makefile @@ -5,14 +5,13 @@ 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) +all: $(OBJECTS) dep: $(CPP) -M $(INCLUDES) *.c > .depend +install: + clean: rm -f *.o ../libcom_err.a diff --git a/lib/com_err/com_err.c b/lib/com_err/com_err.c index f5ab310..e1a0158 100644 --- a/lib/com_err/com_err.c +++ b/lib/com_err/com_err.c @@ -17,25 +17,28 @@ static void #ifdef __STDC__ - default_com_err_proc(const char *whoami, errcode_t code, const - char *fmt, va_list args) +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) +default_com_err_proc(whoami, code, fmt, args) const char *whoami; errcode_t code; const char *fmt; va_list args; #endif { - if (whoami) { + if (whoami) + { fputs(whoami, stderr); fputs(": ", stderr); } - if (code) { + if (code) + { fputs(error_message(code), stderr); fputs(" ", stderr); } - if (fmt) { + if (fmt) + { vfprintf(stderr, fmt, args); } /* should do this only on a tty in raw mode */ @@ -53,10 +56,12 @@ typedef void (*errf) (); 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) +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) +void +com_err_va(whoami, code, fmt, args) const char *whoami; errcode_t code; const char *fmt; @@ -67,12 +72,14 @@ va_list args; } #ifndef VARARGS -void com_err(const char *whoami, - errcode_t code, - const char *fmt,...) +void +com_err(const char *whoami, + errcode_t code, + const char *fmt,...) { #else -void com_err(va_alist) +void +com_err(va_alist) va_dcl { const char *whoami, *fmt; diff --git a/lib/com_err/compile_et b/lib/com_err/compile_et index 872e147..b361717 100755 --- a/lib/com_err/compile_et +++ b/lib/com_err/compile_et @@ -2,7 +2,7 @@ # # AWK=/usr/bin/awk -DIR=com_err/ +DIR=../lib/com_err ROOT=`echo $1 | sed -e s/.et$//` BASE=`basename $ROOT` diff --git a/lib/com_err/error_message.c b/lib/com_err/error_message.c index d3e0c55..ee2f049 100644 --- a/lib/com_err/error_message.c +++ b/lib/com_err/error_message.c @@ -24,10 +24,10 @@ struct et_list *_et_list = (struct et_list *) NULL; #ifdef __STDC__ const char * - error_message(errcode_t code) +error_message(errcode_t code) #else const char * - error_message(code) +error_message(code) errcode_t code; #endif { @@ -39,7 +39,8 @@ errcode_t code; offset = code & ((1 << ERRCODE_RANGE) - 1); table_num = code - offset; - if (!table_num) { + if (!table_num) + { #ifdef HAS_SYS_ERRLIST if (offset < sys_nerr) return (sys_errlist[offset]); @@ -53,8 +54,10 @@ errcode_t code; goto oops; #endif } - for (et = _et_list; et; et = et->next) { - if (et->table->base == table_num) { + 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; @@ -63,17 +66,21 @@ errcode_t code; } oops: strcpy(buffer, "Unknown code "); - if (table_num) { + if (table_num) + { strcat(buffer, error_table_name(table_num)); strcat(buffer, " "); } - for (cp = buffer; *cp; cp++); - if (offset >= 100) { + for (cp = buffer; *cp; cp++) + ; + if (offset >= 100) + { *cp++ = '0' + offset / 100; offset %= 100; started++; } - if (started || offset >= 10) { + if (started || offset >= 10) + { *cp++ = '0' + offset / 10; offset %= 10; } diff --git a/lib/com_err/error_table.h b/lib/com_err/error_table.h index 06c410a..ab498fa 100644 --- a/lib/com_err/error_table.h +++ b/lib/com_err/error_table.h @@ -11,12 +11,14 @@ #define const #endif -struct error_table { +struct error_table +{ char const *const *msgs; long base; int n_msgs; }; -struct et_list { +struct et_list +{ struct et_list *next; const struct error_table *table; }; diff --git a/lib/com_err/et_name.c b/lib/com_err/et_name.c index c1f225b..75617d7 100644 --- a/lib/com_err/et_name.c +++ b/lib/com_err/et_name.c @@ -14,7 +14,7 @@ static const char char_set[] = static char buf[6]; const char * - error_table_name(num) +error_table_name(num) int num; { int ch; @@ -27,7 +27,8 @@ int num; /* 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--) { + 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]; diff --git a/lib/com_err/init_et.c b/lib/com_err/init_et.c index 1ac3675..8978434 100644 --- a/lib/com_err/init_et.c +++ b/lib/com_err/init_et.c @@ -23,7 +23,8 @@ #define const #endif -struct foobar { +struct foobar +{ struct et_list etl; struct error_table et; }; @@ -31,9 +32,11 @@ struct foobar { extern struct et_list *_et_list; #ifdef __STDC__ -int init_error_table(const char *const *msgs, int base, int count) +int +init_error_table(const char *const *msgs, int base, int count) #else -int init_error_table(msgs, base, count) +int +init_error_table(msgs, base, count) const char *const *msgs; int base; int count; diff --git a/lib/mpilib.c b/lib/mpilib.c new file mode 100644 index 0000000..0ac29ce --- /dev/null +++ b/lib/mpilib.c @@ -0,0 +1,1881 @@ +/* C source code for multiprecision arithmetic library routines. + Implemented Nov 86 by Philip Zimmermann + Last revised 27 Nov 91 by PRZ + + Boulder Software Engineering + 3021 Eleventh Street + Boulder, CO 80304 + (303) 541-0140 + + (c) Copyright 1986-92 by Philip Zimmermann. All rights reserved. + The author assumes no liability for damages resulting from the use + of this software, even if the damage results from defects in this + software. No warranty is expressed or implied. The use of this + cryptographic software for developing weapon systems is expressly + forbidden. + + These routines implement all of the multiprecision arithmetic + necessary for number-theoretic cryptographic algorithms such as + ElGamal, Diffie-Hellman, Rabin, or factoring studies for large + composite numbers, as well as Rivest-Shamir-Adleman (RSA) public + key cryptography. + + Although originally developed in Microsoft C for the IBM PC, this code + contains few machine dependencies. It assumes 2's complement + arithmetic. It can be adapted to 8-bit, 16-bit, or 32-bit machines, + lowbyte-highbyte order or highbyte-lowbyte order. This version + has been converted to ANSI C. + + + The internal representation for these extended precision integer + "registers" is an array of "units". A unit is a machine word, which + is either an 8-bit byte, a 16-bit unsigned integer, or a 32-bit + unsigned integer, depending on the machine's word size. For example, + an IBM PC or AT uses a unit size of 16 bits. To perform arithmetic + on these huge precision integers, we pass pointers to these unit + arrays to various subroutines. A pointer to an array of units is of + type unitptr. This is a pointer to a huge integer "register". + + When calling a subroutine, we always pass a pointer to the BEGINNING + of the array of units, regardless of the byte order of the machine. + On a lowbyte-first machine, such as the Intel 80x86, this unitptr + points to the LEAST significant unit, and the array of units increases + significance to the right. On a highbyte-first machine, such as the + Motorola 680x0, this unitptr points to the MOST significant unit, and + the array of units decreases significance to the right. + + Modified 8 Apr 92 - HAJK + Implement new VAX/VMS primitive support. + + Modified 30 Sep 92 -Castor Fu + Upgraded PORTABLE support to allow sizeof(unit) == sizeof(long) + + Modified 28 Nov 92 - Thad Smith + Added Smith modmult, generalized non-portable support. +*/ + +/* #define COUNTMULTS */ /* count modmults for performance studies */ + +#ifdef DEBUG +#ifdef MSDOS +#ifdef __GO32__ /* DJGPP */ +#include +#else +#include +#endif /* __GO32__ */ +#define poll_for_break() {while (kbhit()) getch();} +#endif /* MSDOS */ +#endif /* DEBUG */ + +#ifndef poll_for_break +#define poll_for_break() /* stub */ +#endif + +#include "mpilib.h" + +#ifdef mp_smula +#ifdef mp_smul + Error: Both mp_smula and mp_smul cannot be defined. +#else +#define mp_smul mp_smula +#endif +#endif + +/* set macros for MULTUNIT */ +#ifdef MUNIT8 +#define MULTUNITSIZE 8 +typedef unsigned char MULTUNIT; +#ifdef UNIT8 +#define MULTUNIT_SIZE_SAME +#endif +#else /* not MUNIT8 */ +#ifdef MUNIT32 +#define MULTUNITSIZE 32 +typedef unsigned long MULTUNIT; +#ifdef UNIT32 +#define MULTUNIT_SIZE_SAME +#else +/* #error is not portable, this has the same effect */ +#include "UNITSIZE cannot be smaller than MULTUNITSIZE" +#endif +#else /* assume MUNIT16 */ +#define MULTUNITSIZE 16 +typedef unsigned short MULTUNIT; +#ifdef UNIT16 +#define MULTUNIT_SIZE_SAME +#endif /* UNIT16 */ +#ifdef UNIT8 +#include "UNITSIZE cannot be smaller than MULTUNITSIZE" +#endif /* UNIT8 */ +#endif /* MUNIT32 */ +#endif /* MUNIT8 */ + +#define MULTUNIT_msb ((MULTUNIT)1 << (MULTUNITSIZE-1)) /* msb of MULTUNIT */ +#define DMULTUNIT_msb (1L << (2*MULTUNITSIZE-1)) +#define MULTUNIT_mask ((MULTUNIT)((1L << MULTUNITSIZE)-1)) +#define MULTUNITs_perunit (UNITSIZE/MULTUNITSIZE) + + +void mp_smul (MULTUNIT *prod, MULTUNIT *multiplicand, MULTUNIT multiplier); +void mp_dmul (unitptr prod, unitptr multiplicand, unitptr multiplier); + +short global_precision = 0; /* units of precision for all routines */ +/* global_precision is the unit precision last set by set_precision. + Initially, set_precision() should be called to define global_precision + before using any of these other multiprecision library routines. + i.e.: set_precision(MAX_UNIT_PRECISION); +*/ + +/*************** multiprecision library primitives ****************/ +/* The following portable C primitives should be recoded in assembly. + The entry point name should be defined, in "mpilib.h" to the external + entry point name. If undefined, the C version will be used. +*/ + +typedef unsigned long int ulint; + +#ifndef mp_addc +boolean mp_addc + (register unitptr r1,register unitptr r2,register boolean carry) + /* multiprecision add with carry r2 to r1, result in r1 */ + /* carry is incoming carry flag-- value should be 0 or 1 */ +{ register unit x; + short precision; /* number of units to add */ + precision = global_precision; + make_lsbptr(r1,precision); + make_lsbptr(r2,precision); + while (precision--) + { + if (carry) + { x = *r1 + *r2 + 1; + carry = (*r2 >= (unit)(~ *r1)); + } else + { x = *r1 + *r2; + carry = (x < *r1) ; + } + post_higherunit(r2); + *post_higherunit(r1) = x; + } + return(carry); /* return the final carry flag bit */ +} /* mp_addc */ +#endif /* mp_addc */ + +#ifndef mp_subb +boolean mp_subb + (register unitptr r1,register unitptr r2,register boolean borrow) + /* multiprecision subtract with borrow, r2 from r1, result in r1 */ + /* borrow is incoming borrow flag-- value should be 0 or 1 */ +{ register unit x; + short precision; /* number of units to subtract */ + precision = global_precision; + make_lsbptr(r1,precision); + make_lsbptr(r2,precision); + while (precision--) + { if (borrow) + { x = *r1 - *r2 - 1; + borrow = (*r1 <= *r2); + } else + { x = *r1 - *r2; + borrow = (*r1 < *r2); + } + post_higherunit(r2); + *post_higherunit(r1) = x; + } + return(borrow); /* return the final carry/borrow flag bit */ +} /* mp_subb */ +#endif /* mp_subb */ + +#ifndef mp_rotate_left +boolean mp_rotate_left(register unitptr r1,register boolean carry) + /* multiprecision rotate left 1 bit with carry, result in r1. */ + /* carry is incoming carry flag-- value should be 0 or 1 */ +{ register int precision; /* number of units to rotate */ + unsigned int mcarry = carry, nextcarry=0; /* int is supposed to be + * the efficient size for ops*/ + precision = global_precision; + make_lsbptr(r1,precision); + while (precision--) + { + nextcarry = (((signedunit) *r1) < 0); + *r1 = (*r1 << 1) | mcarry; + mcarry = nextcarry; + pre_higherunit(r1); + } + return(nextcarry); /* return the final carry flag bit */ +} /* mp_rotate_left */ +#endif /* mp_rotate_left */ + +/************** end of primitives that should be in assembly *************/ + + +/* The mp_shift_right_bits function is not called in any time-critical + situations in public-key cryptographic functions, so it doesn't + need to be coded in assembly language. +*/ +void mp_shift_right_bits(register unitptr r1,register short bits) + /* multiprecision shift right bits, result in r1. + bits is how many bits to shift, must be <= UNITSIZE. + */ +{ register short precision; /* number of units to shift */ + register unit carry,nextcarry,bitmask; + register short unbits; + if (bits==0) return; /* shift zero bits is a no-op */ + carry = 0; + bitmask = power_of_2(bits)-1; + unbits = UNITSIZE-bits; /* shift bits must be <= UNITSIZE */ + precision = global_precision; + make_msbptr(r1,precision); + if (bits == UNITSIZE) { + while (precision--) { + nextcarry = *r1; + *r1 = carry; + carry = nextcarry; + pre_lowerunit(r1); + } + } else { + while (precision--) + { nextcarry = *r1 & bitmask; + *r1 >>= bits; + *r1 |= carry << unbits; + carry = nextcarry; + pre_lowerunit(r1); + } + } +} /* mp_shift_right_bits */ + + +#ifndef mp_compare +short mp_compare(register unitptr r1,register unitptr r2) +/* Compares multiprecision integers *r1, *r2, and returns: + -1 iff *r1 < *r2 + 0 iff *r1 == *r2 + +1 iff *r1 > *r2 +*/ +{ register short precision; /* number of units to compare */ + + precision = global_precision; + make_msbptr(r1,precision); + make_msbptr(r2,precision); + do + { if (*r1 < *r2) + return(-1); + if (*post_lowerunit(r1) > *post_lowerunit(r2)) + return(1); + } while (--precision); + return(0); /* *r1 == *r2 */ +} /* mp_compare */ +#endif /* mp_compare */ + + +boolean mp_inc(register unitptr r) + /* Increment multiprecision integer r. */ +{ register short precision; + precision = global_precision; + make_lsbptr(r,precision); + do + { if ( ++(*r) ) return(0); /* no carry */ + post_higherunit(r); + } while (--precision); + return(1); /* return carry set */ +} /* mp_inc */ + + +boolean mp_dec(register unitptr r) + /* Decrement multiprecision integer r. */ +{ register short precision; + precision = global_precision; + make_lsbptr(r,precision); + do + { if ( (signedunit) (--(*r)) != (signedunit) -1 ) + return(0); /* no borrow */ + post_higherunit(r); + } while (--precision); + return(1); /* return borrow set */ +} /* mp_dec */ + + +void mp_neg(register unitptr r) + /* Compute 2's complement, the arithmetic negative, of r */ +{ register short precision; /* number of units to negate */ + precision = global_precision; + mp_dec(r); /* 2's complement is 1's complement plus 1 */ + do /* now do 1's complement */ + { *r = ~(*r); + r++; + } while (--precision); +} /* mp_neg */ + +#ifndef mp_move +void mp_move(register unitptr dst,register unitptr src) +{ register short precision; /* number of units to move */ + precision = global_precision; + do { *dst++ = *src++; } while (--precision); +} /* mp_move */ +#endif /* mp_move */ + +void mp_init(register unitptr r, word16 value) + /* Init multiprecision register r with short value. */ +{ /* Note that mp_init doesn't extend sign bit for >32767 */ + + unitfill0( r, global_precision); + make_lsbptr(r,global_precision); + *post_higherunit(r) = value; +#ifdef UNIT8 + *post_higherunit(r) = value >> UNITSIZE; +#endif +} /* mp_init */ + + +short significance(register unitptr r) + /* Returns number of significant units in r */ +{ register short precision; + precision = global_precision; + make_msbptr(r,precision); + do + { if (*post_lowerunit(r)) + return(precision); + } while (--precision); + return(precision); +} /* significance */ + + +#ifndef unitfill0 +void unitfill0(unitptr r,word16 unitcount) + /* Zero-fill the unit buffer r. */ +{ while (unitcount--) *r++ = 0; +} /* unitfill0 */ +#endif /* unitfill0 */ + + +int mp_udiv(register unitptr remainder,register unitptr quotient, + register unitptr dividend,register unitptr divisor) + /* Unsigned divide, treats both operands as positive. */ +{ int bits; + short dprec; + register unit bitmask; + if (testeq(divisor,0)) + return(-1); /* zero divisor means divide error */ + mp_init0(remainder); + mp_init0(quotient); + /* normalize and compute number of bits in dividend first */ + init_bitsniffer(dividend,bitmask,dprec,bits); + /* rescale quotient to same precision (dprec) as dividend */ + rescale(quotient,global_precision,dprec); + make_msbptr(quotient,dprec); + + while (bits--) + { mp_rotate_left(remainder,(boolean)(sniff_bit(dividend,bitmask)!=0)); + if (mp_compare(remainder,divisor) >= 0) + { mp_sub(remainder,divisor); + stuff_bit(quotient,bitmask); + } + bump_2bitsniffers(dividend,quotient,bitmask); + } + return(0); +} /* mp_udiv */ + + +#ifdef UPTON_OR_SMITH +#define RECIPMARGIN 0 /* extra margin bits used by mp_recip() */ + +int mp_recip(register unitptr quotient,register unitptr divisor) + /* Compute reciprocal (quotient) as 1/divisor. Used by faster modmult. */ +{ int bits; + short qprec; + register unit bitmask; + unit remainder[MAX_UNIT_PRECISION]; + if (testeq(divisor,0)) + return(-1); /* zero divisor means divide error */ + mp_init0(remainder); + mp_init0(quotient); + + /* normalize and compute number of bits in quotient first */ + bits = countbits(divisor) + RECIPMARGIN; + bitmask = bitmsk(bits); /* bitmask within a single unit */ + qprec = bits2units(bits+1); + mp_setbit(remainder,(bits-RECIPMARGIN)-1); + /* rescale quotient to precision of divisor + RECIPMARGIN bits */ + rescale(quotient,global_precision,qprec); + make_msbptr(quotient,qprec); + + while (bits--) + { mp_shift_left(remainder); + if (mp_compare(remainder,divisor) >= 0) + { mp_sub(remainder,divisor); + stuff_bit(quotient,bitmask); + } + bump_bitsniffer(quotient,bitmask); + } + mp_init0(remainder); /* burn sensitive data left on stack */ + return(0); +} /* mp_recip */ +#endif /* UPTON_OR_SMITH */ + + +int mp_div(register unitptr remainder,register unitptr quotient, + register unitptr dividend,register unitptr divisor) + /* Signed divide, either or both operands may be negative. */ +{ boolean dvdsign,dsign; + int status; + dvdsign = (boolean)(mp_tstminus(dividend)!=0); + dsign = (boolean)(mp_tstminus(divisor)!=0); + if (dvdsign) mp_neg(dividend); + if (dsign) mp_neg(divisor); + status = mp_udiv(remainder,quotient,dividend,divisor); + if (dvdsign) mp_neg(dividend); /* repair caller's dividend */ + if (dsign) mp_neg(divisor); /* repair caller's divisor */ + if (status<0) return(status); /* divide error? */ + if (dvdsign) mp_neg(remainder); + if (dvdsign ^ dsign) mp_neg(quotient); + return(status); +} /* mp_div */ + + +word16 mp_shortdiv(register unitptr quotient, + register unitptr dividend,register word16 divisor) +/* This function does a fast divide and mod on a multiprecision dividend + using a short integer divisor returning a short integer remainder. + This is an unsigned divide. It treats both operands as positive. + It is used mainly for faster printing of large numbers in base 10. +*/ +{ int bits; + short dprec; + register unit bitmask; + register word16 remainder; + if (!divisor) /* if divisor == 0 */ + return(-1); /* zero divisor means divide error */ + remainder=0; + mp_init0(quotient); + /* normalize and compute number of bits in dividend first */ + init_bitsniffer(dividend,bitmask,dprec,bits); + /* rescale quotient to same precision (dprec) as dividend */ + rescale(quotient,global_precision,dprec); + make_msbptr(quotient,dprec); + + while (bits--) + { remainder <<= 1; + if (sniff_bit(dividend,bitmask)) + remainder++; + if (remainder >= divisor) + { remainder -= divisor; + stuff_bit(quotient,bitmask); + } + bump_2bitsniffers(dividend,quotient,bitmask); + } + return(remainder); +} /* mp_shortdiv */ + + +int mp_mod(register unitptr remainder, + register unitptr dividend,register unitptr divisor) + /* Unsigned divide, treats both operands as positive. */ +{ int bits; + short dprec; + register unit bitmask; + if (testeq(divisor,0)) + return(-1); /* zero divisor means divide error */ + mp_init0(remainder); + /* normalize and compute number of bits in dividend first */ + init_bitsniffer(dividend,bitmask,dprec,bits); + + while (bits--) + { mp_rotate_left(remainder,(boolean)(sniff_bit(dividend,bitmask)!=0)); + msub(remainder,divisor); + bump_bitsniffer(dividend,bitmask); + } + return(0); +} /* mp_mod */ + + +word16 mp_shortmod(register unitptr dividend,register word16 divisor) +/* This function does a fast mod operation on a multiprecision dividend + using a short integer modulus returning a short integer remainder. + This is an unsigned divide. It treats both operands as positive. + It is used mainly for fast sieve searches for large primes. +*/ +{ int bits; + short dprec; + register unit bitmask; + register word16 remainder; + if (!divisor) /* if divisor == 0 */ + return(-1); /* zero divisor means divide error */ + remainder=0; + /* normalize and compute number of bits in dividend first */ + init_bitsniffer(dividend,bitmask,dprec,bits); + + while (bits--) + { remainder <<= 1; + if (sniff_bit(dividend,bitmask)) + remainder++; + if (remainder >= divisor) remainder -= divisor; + bump_bitsniffer(dividend,bitmask); + } + return(remainder); +} /* mp_shortmod */ + + + +#ifdef COMB_MULT /* use faster "comb" multiply algorithm */ + /* We are skipping this code because it has a bug... */ + +int mp_mult(register unitptr prod, + register unitptr multiplicand, register unitptr multiplier) + /* Computes multiprecision prod = multiplicand * multiplier */ +{ /* Uses interleaved comb multiply algorithm. + This improved multiply more than twice as fast as a Russian + peasant multiply, because it does a lot fewer shifts. + Must have global_precision set to the size of the multiplicand + plus UNITSIZE-1 SLOP_BITS. Produces a product that is the sum + of the lengths of the multiplier and multiplicand. + + BUG ALERT: Unfortunately, this code has a bug. It fails for + some numbers. One such example: + x= 59DE 60CE 2345 8091 A02B 2A1C DBC3 8BE5 + x*x= 59DE 60CE 2345 26B3 993B 67A5 2499 0B7D + 52C8 CDC7 AFB3 61C8 243C 741B + --which is obviously wrong. The answer should be: + x*x= 1F8C 607B 5EA6 C061 2714 04A9 A0C6 A17A + C9AB 6095 C62F 3756 3843 E4D0 3950 7AD9 + We'll have to fix this some day. In the meantime, we'll + just have the compiler skip over this code. + + BUG NOTE: Possibly fixed. Needs testing. + */ + int bits; + register unit bitmask; + unitptr product, mplier, temp; + short mprec,mprec2; + unit mplicand[MAX_UNIT_PRECISION]; + + /* better clear full width--double precision */ + mp_init(prod+tohigher(global_precision),0); + + if (testeq(multiplicand,0)) + return(0); /* zero multiplicand means zero product */ + + mp_move(mplicand,multiplicand); /* save it from damage */ + + normalize(multiplier,mprec); + if (!mprec) + return(0); + + make_lsbptr(multiplier,mprec); + bitmask = 1; /* start scan at LSB of multiplier */ + + do /* UNITSIZE times */ + { /* do for bits 0-15 */ + product = prod; + mplier = multiplier; + mprec2 = mprec; + while (mprec2--) /* do for each word in multiplier */ + { + if (sniff_bit(mplier,bitmask)) + { if (mp_addc(product,multiplicand,0)) /* ripple carry */ + { /* After 1st time thru, this is rarely encountered. */ + temp = msbptr(product,global_precision); + pre_higherunit(temp); + /* temp now points to LSU of carry region. */ + unmake_lsbptr(temp,global_precision); + mp_inc(temp); + } /* ripple carry */ + } + pre_higherunit(mplier); + pre_higherunit(product); + } + if (!(bitmask <<= 1)) + break; + mp_shift_left(multiplicand); + + } while (TRUE); + + mp_move(multiplicand,mplicand); /* recover */ + + return(0); /* normal return */ +} /* mp_mult */ + +#endif /* COMB_MULT */ + + +/* Because the "comb" multiply has a bug, we will use the slower + Russian peasant multiply instead. Fortunately, the mp_mult + function is not called from any time-critical code. +*/ + +int mp_mult(register unitptr prod, + register unitptr multiplicand,register unitptr multiplier) + /* Computes multiprecision prod = multiplicand * multiplier */ +{ /* Uses "Russian peasant" multiply algorithm. */ + int bits; + register unit bitmask; + short mprec; + mp_init(prod,0); + if (testeq(multiplicand,0)) + return(0); /* zero multiplicand means zero product */ + /* normalize and compute number of bits in multiplier first */ + init_bitsniffer(multiplier,bitmask,mprec,bits); + + while (bits--) + { mp_shift_left(prod); + if (sniff_bit(multiplier,bitmask)) + mp_add(prod,multiplicand); + bump_bitsniffer(multiplier,bitmask); + } + return(0); +} /* mp_mult */ + + + +/* mp_modmult computes a multiprecision multiply combined with a + modulo operation. This is the most time-critical function in + this multiprecision arithmetic library for performing modulo + exponentiation. We experimented with different versions of modmult, + depending on the machine architecture and performance requirements. + We will either use a Russian Peasant modmult (peasant_modmult), + Charlie Merritt's modmult (merritt_modmult), Jimmy Upton's + modmult (upton_modmult), or Thad Smith's modmult (smith_modmult). + On machines with a hardware atomic multiply instruction, + Smith's modmult is fastest. It can utilize assembly subroutines to + speed up the hardware multiply logic and trial quotient calculation. + If the machine lacks a fast hardware multiply, Merritt's modmult + is preferred, which doesn't call any assembly multiply routine. + We use the alias names mp_modmult, stage_modulus, and modmult_burn + for the corresponding true names, which depend on what flavor of + modmult we are using. + + Before making the first call to mp_modmult, you must set up the + modulus-dependant precomputated tables by calling stage_modulus. + After making all the calls to mp_modmult, you call modmult_burn to + erase the tables created by stage_modulus that were left in memory. +*/ + +#ifdef COUNTMULTS +/* "number of modmults" counters, used for performance studies. */ +static unsigned int tally_modmults = 0; +static unsigned int tally_modsquares = 0; +#endif /* COUNTMULTS */ + + +#ifdef PEASANT +/* Conventional Russian peasant multiply with modulo algorithm. */ + +static unitptr pmodulus = 0; /* used only by mp_modmult */ + +int stage_peasant_modulus(unitptr n) +/* Must pass modulus to stage_modulus before calling modmult. + Assumes that global_precision has already been adjusted to the + size of the modulus, plus SLOP_BITS. +*/ +{ /* For this simple version of modmult, just copy unit pointer. */ + pmodulus = n; + return(0); /* normal return */ +} /* stage_peasant_modulus */ + + +int peasant_modmult(register unitptr prod, + unitptr multiplicand,register unitptr multiplier) +{ /* "Russian peasant" multiply algorithm, combined with a modulo + operation. This is a simple naive replacement for Merritt's + faster modmult algorithm. References global unitptr "modulus". + Computes: prod = (multiplicand*multiplier) mod modulus + WARNING: All the arguments must be less than the modulus! + */ + int bits; + register unit bitmask; + short mprec; + mp_init(prod,0); +/* if (testeq(multiplicand,0)) + return(0); */ /* zero multiplicand means zero product */ + /* normalize and compute number of bits in multiplier first */ + init_bitsniffer(multiplier,bitmask,mprec,bits); + + while (bits--) + { mp_shift_left(prod); + msub(prod,pmodulus); /* turns mult into modmult */ + if (sniff_bit(multiplier,bitmask)) + { mp_add(prod,multiplicand); + msub(prod,pmodulus); /* turns mult into modmult */ + } + bump_bitsniffer(multiplier,bitmask); + } + return(0); +} /* peasant_modmult */ + + +/* If we are using a version of mp_modmult that uses internal tables + in memory, we have to call modmult_burn() at the end of mp_modexp. + This is so that no sensitive data is left in memory after the program + exits. The Russian peasant method doesn't use any such tables. +*/ +void peasant_burn(void) +/* Alias for modmult_burn, called only from mp_modexp(). Destroys + internal modmult tables. This version does nothing because no + tables are used by the Russian peasant modmult. */ +{ } /* peasant_burn */ + +#endif /* PEASANT */ + + +#ifdef MERRITT +/*=========================================================================*/ +/* + This is Charlie Merritt's MODMULT algorithm, implemented in C by PRZ. + Also refined by Zhahai Stewart to reduce the number of subtracts. + Modified by Raymond Brand to reduce the number of SLOP_BITS by 1. + It performs a multiply combined with a modulo operation, without + going into "double precision". It is faster than the Russian peasant + method, and still works well on machines that lack a fast hardware + multiply instruction. +*/ + +/* The following support functions, macros, and data structures + are used only by Merritt's modmult algorithm... */ + +static void mp_lshift_unit(register unitptr r1) +/* Shift r1 1 whole unit to the left. Used only by modmult function. */ +{ register short precision; + register unitptr r2; + precision = global_precision; + make_msbptr(r1,precision); + r2 = r1; + while (--precision) + *post_lowerunit(r1) = *pre_lowerunit(r2); + *r1 = 0; +} /* mp_lshift_unit */ + + +/* moduli_buf contains shifted images of the modulus, set by stage_modulus */ +static unit moduli_buf[UNITSIZE-1][MAX_UNIT_PRECISION] = {0}; +static unitptr moduli[UNITSIZE] = /* contains pointers into moduli_buf */ +{ 0 + ,&moduli_buf[ 0][0], &moduli_buf[ 1][0], &moduli_buf[ 2][0], &moduli_buf[ 3][0], + &moduli_buf[ 4][0], &moduli_buf[ 5][0], &moduli_buf[ 6][0] +#ifndef UNIT8 + ,&moduli_buf[ 7][0] + ,&moduli_buf[ 8][0], &moduli_buf[ 9][0], &moduli_buf[10][0], &moduli_buf[11][0], + &moduli_buf[12][0], &moduli_buf[13][0], &moduli_buf[14][0] +#ifndef UNIT16 /* and not UNIT8 */ + ,&moduli_buf[15][0] + ,&moduli_buf[16][0], &moduli_buf[17][0], &moduli_buf[18][0], &moduli_buf[19][0], + &moduli_buf[20][0], &moduli_buf[21][0], &moduli_buf[22][0], &moduli_buf[23][0], + &moduli_buf[24][0], &moduli_buf[25][0], &moduli_buf[26][0], &moduli_buf[27][0], + &moduli_buf[28][0], &moduli_buf[29][0], &moduli_buf[30][0] +#endif /* UNIT16 and UNIT8 not defined */ +#endif /* UNIT8 not defined */ +}; + +/* To optimize msubs, need following 2 unit arrays, each filled + with the most significant unit and next-to-most significant unit + of the preshifted images of the modulus. */ +static unit msu_moduli[UNITSIZE] = {0}; /* most signif. unit */ +static unit nmsu_moduli[UNITSIZE] = {0}; /* next-most signif. unit */ + +/* mpdbuf contains preshifted images of the multiplicand, mod n. + It is used only by mp_modmult. It could be staticly declared + inside of mp_modmult, but we put it outside mp_modmult so that + it can be wiped clean by modmult_burn(), which is called at the + end of mp_modexp. This is so that no sensitive data is left in + memory after the program exits. +*/ +static unit mpdbuf[UNITSIZE-1][MAX_UNIT_PRECISION] = {0}; + + +static void stage_mp_images(unitptr images[UNITSIZE],unitptr r) +/* Computes UNITSIZE images of r, each shifted left 1 more bit. + Used only by modmult function. +*/ +{ short int i; + images[0] = r; /* no need to move the first image, just copy ptr */ + for (i=1; i= 0) && \ + (p_m || (mp_compare(prod,moduli[i]) >= 0) ) \ + ) mp_sub(prod,moduli[i]) +*/ + +/* Fully-optimized msubs macro (msubs2) follows... */ +#define msubs(i) if (((p_m = *msu_prod-msu_moduli[i])>0) || ( \ + (p_m==0) && ( (*nmsu_prod>nmsu_moduli[i]) || ( \ + (*nmsu_prod==nmsu_moduli[i]) && ((mp_compare(prod,moduli[i]) >= 0)) ))) ) \ + mp_sub(prod,moduli[i]) + + +int merritt_modmult(register unitptr prod, + unitptr multiplicand,register unitptr multiplier) + /* Performs combined multiply/modulo operation. + Computes: prod = (multiplicand*multiplier) mod modulus + WARNING: All the arguments must be less than the modulus! + Assumes the modulus has been predefined by first calling + stage_modulus. + */ +{ + /* p_m, msu_prod, and nmsu_prod are used by the optimized msubs macro...*/ + register signedunit p_m; + register unitptr msu_prod; /* ptr to most significant unit of product */ + register unitptr nmsu_prod; /* next-most signif. unit of product */ + short mprec; /* precision of multiplier, in units */ + /* Array mpd contains a list of pointers to preshifted images of + the multiplicand: */ + static unitptr mpd[UNITSIZE] = + { 0, &mpdbuf[ 0][0], &mpdbuf[ 1][0], &mpdbuf[ 2][0], + &mpdbuf[ 3][0], &mpdbuf[ 4][0], &mpdbuf[ 5][0], &mpdbuf[ 6][0] +#ifndef UNIT8 + ,&mpdbuf[ 7][0], &mpdbuf[ 8][0], &mpdbuf[ 9][0], &mpdbuf[10][0], + &mpdbuf[11][0], &mpdbuf[12][0], &mpdbuf[13][0], &mpdbuf[14][0] +#ifndef UNIT16 /* and not UNIT8 */ + ,&mpdbuf[15][0], &mpdbuf[16][0], &mpdbuf[17][0], &mpdbuf[18][0], + &mpdbuf[19][0], &mpdbuf[20][0], &mpdbuf[21][0], &mpdbuf[22][0], + &mpdbuf[23][0], &mpdbuf[24][0], &mpdbuf[25][0], &mpdbuf[26][0], + &mpdbuf[27][0], &mpdbuf[28][0], &mpdbuf[29][0], &mpdbuf[30][0] +#endif /* UNIT16 and UNIT8 not defined */ +#endif /* UNIT8 not defined */ + }; + + /* Compute preshifted images of multiplicand, mod n: */ + stage_mp_images(mpd,multiplicand); + + /* To optimize msubs, set up msu_prod and nmsu_prod: */ + msu_prod = msbptr(prod,global_precision); /* Get ptr to MSU of prod */ + nmsu_prod = msu_prod; + post_lowerunit(nmsu_prod); /* Get next-MSU of prod */ + + /* To understand this algorithm, it would be helpful to first + study the conventional Russian peasant modmult algorithm. + This one does about the same thing as Russian peasant, but + is organized differently to save some steps. It loops + through the multiplier a word (unit) at a time, instead of + a bit at a time. It word-shifts the product instead of + bit-shifting it, so it should be faster. It also does about + half as many subtracts as Russian peasant. + */ + + mp_init(prod,0); /* Initialize product to 0. */ + + /* The way mp_modmult is actually used in cryptographic + applications, there will NEVER be a zero multiplier or + multiplicand. So there is no need to optimize for that + condition. + */ +/* if (testeq(multiplicand,0)) + return(0); */ /* zero multiplicand means zero product */ + /* Normalize and compute number of units in multiplier first: */ + normalize(multiplier,mprec); + if (mprec==0) /* if precision of multiplier is 0 */ + return(0); /* zero multiplier means zero product */ + make_msbptr(multiplier,mprec); /* start at MSU of multiplier */ + + while (mprec--) /* Loop for the number of units in the multiplier */ + { + /* Shift the product one whole unit to the left. + This is part of the multiply phase of modmult. + */ + + mp_lshift_unit(prod); + + /* The product may have grown by as many as UNITSIZE + bits. That's why we have global_precision set to the + size of the modulus plus UNITSIZE slop bits. + Now reduce the product back down by conditionally + subtracting the preshifted images of the modulus. + This is part of the modulo reduction phase of modmult. + The following loop is unrolled for speed, using macros... + + for (i=UNITSIZE-1; i>=LOG_UNITSIZE; i--) + if (mp_compare(prod,moduli[i]) >= 0) + mp_sub(prod,moduli[i]); + */ + +#ifndef UNIT8 +#ifndef UNIT16 /* and not UNIT8 */ + msubs(31); + msubs(30); + msubs(29); + msubs(28); + msubs(27); + msubs(26); + msubs(25); + msubs(24); + msubs(23); + msubs(22); + msubs(21); + msubs(20); + msubs(19); + msubs(18); + msubs(17); + msubs(16); +#endif /* not UNIT16 and not UNIT8 */ + msubs(15); + msubs(14); + msubs(13); + msubs(12); + msubs(11); + msubs(10); + msubs(9); + msubs(8); +#endif /* not UNIT8 */ + msubs(7); + msubs(6); + msubs(5); +#ifndef UNIT32 + msubs(4); +#ifndef UNIT16 + msubs(3); +#endif +#endif + + /* Sniff each bit in the current unit of the multiplier, + and conditionally add the corresponding preshifted + image of the multiplicand to the product. + This is also part of the multiply phase of modmult. + + The following loop is unrolled for speed, using macros... + + for (i=UNITSIZE-1; i>=0; i--) + if (*multiplier & power_of_2(i)) + mp_add(prod,mpd[i]); + */ +#ifndef UNIT8 +#ifndef UNIT16 /* and not UNIT8 */ + sniffadd(31); + sniffadd(30); + sniffadd(29); + sniffadd(28); + sniffadd(27); + sniffadd(26); + sniffadd(25); + sniffadd(24); + sniffadd(23); + sniffadd(22); + sniffadd(21); + sniffadd(20); + sniffadd(19); + sniffadd(18); + sniffadd(17); + sniffadd(16); +#endif /* not UNIT16 and not UNIT8 */ + sniffadd(15); + sniffadd(14); + sniffadd(13); + sniffadd(12); + sniffadd(11); + sniffadd(10); + sniffadd(9); + sniffadd(8); +#endif /* not UNIT8 */ + sniffadd(7); + sniffadd(6); + sniffadd(5); + sniffadd(4); + sniffadd(3); + sniffadd(2); + sniffadd(1); + sniffadd(0); + + /* The product may have grown by as many as LOG_UNITSIZE+1 + bits. + Now reduce the product back down by conditionally + subtracting LOG_UNITSIZE+1 preshifted images of the + modulus. This is the modulo reduction phase of modmult. + + The following loop is unrolled for speed, using macros... + + for (i=LOG_UNITSIZE; i>=0; i--) + if (mp_compare(prod,moduli[i]) >= 0) + mp_sub(prod,moduli[i]); + */ + +#ifndef UNIT8 +#ifndef UNIT16 + msubs(5); +#endif + msubs(4); +#endif + msubs(3); + msubs(2); + msubs(1); + msubs(0); + + /* Bump pointer to next lower unit of multiplier: */ + post_lowerunit(multiplier); + + } /* Loop for the number of units in the multiplier */ + + return(0); /* normal return */ + +} /* merritt_modmult */ + + +#undef msubs +#undef sniffadd + + +/* Merritt's mp_modmult function leaves some internal tables in memory, + so we have to call modmult_burn() at the end of mp_modexp. + This is so that no cryptographically sensitive data is left in memory + after the program exits. +*/ +void merritt_burn(void) +/* Alias for modmult_burn, merritt_burn() is called only by mp_modexp. */ +{ unitfill0(&(mpdbuf[0][0]),(UNITSIZE-1)*MAX_UNIT_PRECISION); + unitfill0(&(moduli_buf[0][0]),(UNITSIZE-1)*MAX_UNIT_PRECISION); + unitfill0(msu_moduli,UNITSIZE); + unitfill0(nmsu_moduli,UNITSIZE); +} /* merritt_burn() */ + +/******* end of Merritt's MODMULT stuff. *******/ +/*=========================================================================*/ +#endif /* MERRITT */ + + +#ifdef UPTON_OR_SMITH /* Used by Upton's and Smith's modmult algorithms */ + +/* Jimmy Upton's multiprecision modmult algorithm in C. + Performs a multiply combined with a modulo operation. + + The following support functions and data structures + are used only by Upton's modmult algorithm... +*/ + +short munit_prec; /* global_precision expressed in MULTUNITs */ + +/* Note that since the SPARC CPU has no hardware integer multiply + instruction, there is not that much advantage in having an + assembly version of mp_smul on that machine. It might be faster + to use Merritt's modmult instead of Upton's modmult on the SPARC. +*/ + +/* + Multiply the single-word multiplier times the multiprecision integer + in multiplicand, accumulating result in prod. The resulting + multiprecision prod will be 1 word longer than the multiplicand. + multiplicand is munit_prec words long. We add into prod, so caller + should zero it out first. For best results, this time-critical + function should be implemented in assembly. + NOTE: Unlike other functions in the multiprecision arithmetic + library, both multiplicand and prod are pointing at the LSB, + regardless of byte order of the machine. On an 80x86, this makes + no difference. But if this assembly function is implemented + on a 680x0, it becomes important. +*/ +/* Note that this has been modified from the previous version to allow + better support for Smith's modmult: + The final carry bit is added to the existing product + array, rather than simply stored. +*/ + +#ifndef mp_smul +void mp_smul (MULTUNIT *prod, MULTUNIT *multiplicand, MULTUNIT multiplier) +{ + short i; + unsigned long p, carry; + + carry = 0; + for (i=0; i> MULTUNITSIZE; + } + /* Add carry to the next higher word of product / dividend */ + *prod += (MULTUNIT)carry; +} /* mp_smul */ +#endif + +/* mp_dmul is a double-precision multiply multiplicand times multiplier, + result into prod. prod must be pointing at a "double precision" + buffer. E.g. If global_precision is 10 words, prod must be + pointing at a 20-word buffer. +*/ +#ifndef mp_dmul +void mp_dmul (unitptr prod, unitptr multiplicand, unitptr multiplier) +{ + register int i; + register MULTUNIT *p_multiplicand, *p_multiplier; + register MULTUNIT *prodp; + + + unitfill0(prod,global_precision*2); /* Pre-zero prod */ + /* Calculate precision in units of MULTUNIT */ + munit_prec = global_precision * UNITSIZE / MULTUNITSIZE; + p_multiplicand = (MULTUNIT *)multiplicand; + p_multiplier = (MULTUNIT *)multiplier; + prodp = (MULTUNIT *)prod; + make_lsbptr(p_multiplicand,munit_prec); + make_lsbptr(p_multiplier,munit_prec); + make_lsbptr(prodp,munit_prec*2); + /* Multiply multiplicand by each word in multiplier, accumulating prod: */ + for (i=0; i 0) + mp_sub (d,modulus); + + mp_move(prod,d); + return(0); /* normal return */ +} /* upton_modmult */ + + +/* Upton's mp_modmult function leaves some internal arrays in memory, + so we have to call modmult_burn() at the end of mp_modexp. + This is so that no cryptographically sensitive data is left in memory + after the program exits. + upton_burn() is aliased to modmult_burn(). +*/ +void upton_burn(void) +{ + unitfill0(modulus,MAX_UNIT_PRECISION); + unitfill0(reciprocal,MAX_UNIT_PRECISION); + unitfill0(dhi,MAX_UNIT_PRECISION); + unitfill0(d_data,MAX_UNIT_PRECISION*2); + unitfill0(e_data,MAX_UNIT_PRECISION*2); + unitfill0(f_data,MAX_UNIT_PRECISION*2); + nbits = nbitsDivUNITSIZE = nbitsModUNITSIZE = 0; +} /* upton_burn */ + +/******* end of Upton's MODMULT stuff. *******/ +/*=========================================================================*/ +#endif /* UPTON */ + +#ifdef SMITH /* using Thad Smith's modmult algorithm */ + +/* Thad Smith's implementation of multiprecision modmult algorithm in C. + Performs a multiply combined with a modulo operation. + The multiplication is done with mp_dmul, the same as for Upton's + modmult. The modulus reduction is done by long division, in + which a trial quotient "digit" is determined, then the product of + that digit and the divisor are subtracted from the dividend. + + In this case, the digit is MULTUNIT in size and the subtraction + is done by adding the product to the one's complement of the + dividend, which allows use of the existing mp_smul routine. + + The following support functions and data structures + are used only by Smith's modmult algorithm... +*/ + +/* These scratchpad arrays are used only by smith_modmult (mp_modmult). + Some of them could be statically declared inside of mp_modmult, but we + put them outside mp_modmult so that they can be wiped clean by + modmult_burn(), which is called at the end of mp_modexp. This is + so that no sensitive data is left in memory after the program exits. +*/ + +static unit ALIGN ds_data[MAX_UNIT_PRECISION*2+2]; + +static unit mod_quotient [4]; +static unit mod_divisor [4]; /* 2 most signif. MULTUNITs of modulus */ + +static MULTUNIT *modmpl; /* ptr to modulus least significant + ** MULTUNIT */ +static int mshift; /* number of bits for + ** recip scaling */ +static MULTUNIT reciph; /* MSunit of scaled recip */ +static MULTUNIT recipl; /* LSunit of scaled recip */ + +static short modlenMULTUNITS; /* length of modulus in MULTUNITs */ +static MULTUNIT mutemp; /* temporary */ + +/* The routines mp_smul and mp_dmul are the same as for UPTON and + should be coded in assembly. Note, however, that the previous + Upton's mp_smul version has been modified to compatible with + Smith's modmult. The new version also still works for Upton's + modmult. +*/ + +#ifndef mp_set_recip +#define mp_set_recip(rh,rl,m) /* null */ +#else +/* setup routine for external mp_quo_digit */ +void mp_set_recip(MULTUNIT rh, MULTUNIT rl, int m); +#endif +MULTUNIT mp_quo_digit (MULTUNIT *dividend); + +#ifdef MULTUNIT_SIZE_SAME +#define mp_musubb mp_subb /* use existing routine */ +#else /* ! MULTUNIT_SIZE_SAME */ + +/* This performs the same function as mp_subb, but with MULTUNITs. + Note: Processors without alignment requirements may be able to use + mp_subb, even though MULTUNITs are smaller than units. In that case, + use mp_subb, since it would be faster if coded in assembly. Note that + this implementation won't work for MULTUNITs which are long -- use + mp_subb in that case. +*/ +#ifndef mp_musubb +boolean mp_musubb + (register MULTUNIT* r1,register MULTUNIT* r2,register boolean borrow) + /* multiprecision subtract of MULTUNITs with borrow, r2 from r1, + ** result in r1 */ + /* borrow is incoming borrow flag-- value should be 0 or 1 */ +{ register ulint x; /* won't work if sizeof(MULTUNIT)== + sizeof(long) */ + short precision; /* number of MULTUNITs to subtract */ + precision = global_precision * MULTUNITs_perunit; + make_lsbptr(r1,precision); + make_lsbptr(r2,precision); + while (precision--) + { x = (ulint) *r1 - (ulint) *post_higherunit(r2) - (ulint) borrow; + *post_higherunit(r1) = x; + borrow = (((1L << MULTUNITSIZE) & x) != 0L); + } + return (borrow); +} /* mp_musubb */ +#endif /* mp_musubb */ +#endif /* MULTUNIT_SIZE_SAME */ + +/* The function mp_quo_digit is the heart of Smith's modulo reduction, + which uses a form of long division. It computes a trial quotient + "digit" (MULTUNIT-sized digit) by multiplying the three most + significant MULTUNITs of the dividend by the two most significant + MULTUNITs of the reciprocal of the modulus. Note that this function + requires that MULTUNITSIZE * 2 <= sizeof(unsigned long). + + An important part of this technique is that the quotient never be + too small, although it may occasionally be too large. This was + done to eliminate the need to check and correct for a remainder + exceeding the divisor. It is easier to check for a negative + remainder. The following technique rarely needs correction for + MULTUNITs of at least 16 bits. + + The following routine has two implementations: + + ASM_PROTOTYPE defined: written to be an executable prototype for + an efficient assembly language implementation. Note that several + of the following masks and shifts can be done by directly + manipulating single precision registers on some architectures. + + ASM_PROTOTYPE undefined: a slightly more efficient implementation + in C. Although this version returns a result larger than the + optimum (which is corrected in smith_modmult) more often than the + prototype version, the faster execution in C more than makes up + for the difference. + + Parameter: dividend - points to the most significant MULTUNIT + of the dividend. Note that dividend actually contains the + one's complement of the actual dividend value (see comments for + smith_modmult). + + Return: the trial quotient digit resulting from dividing the first + three MULTUNITs at dividend by the upper two MULTUNITs of the + modulus. +*/ + +/* #define ASM_PROTOTYPE */ /* undefined: use C-optimized version */ + +#ifndef mp_quo_digit +MULTUNIT mp_quo_digit (MULTUNIT *dividend) { + unsigned long q, q0, q1, q2; + unsigned short lsb_factor; + +/* Compute the least significant product group. + The last terms of q1 and q2 perform upward rounding, which is + needed to guarantee that the result not be too small. +*/ + q1 = (dividend[tohigher(-2)] ^ MULTUNIT_mask) * (unsigned long)reciph + + reciph; + q2 = (dividend[tohigher(-1)] ^ MULTUNIT_mask) * (unsigned long)recipl + + (1L << MULTUNITSIZE) ; +#ifdef ASM_PROTOTYPE + lsb_factor = 1 & (q1>>MULTUNITSIZE) & (q2>>MULTUNITSIZE); + q = q1 + q2; + + /* The following statement is equivalent to shifting the sum right + one bit while shifting in the carry bit. + */ + q0 = (q1 > ~q2 ? DMULTUNIT_msb : 0) | (q >> 1); +#else /* optimized C version */ + q0 = (q1>>1) + (q2>>1) + 1; +#endif + +/* Compute the middle significant product group. */ + + q1 = (dividend[tohigher(-1)] ^ MULTUNIT_mask) * (unsigned long)reciph; + q2 = (dividend[ 0] ^ MULTUNIT_mask) * (unsigned long)recipl; +#ifdef ASM_PROTOTYPE + q = q1 + q2; + q = (q1 > ~q2 ? DMULTUNIT_msb : 0) | (q >> 1); + +/* Add in the most significant word of the first group. + The last term takes care of the carry from adding the lsb's + that were shifted out prior to addition. +*/ + q = (q0 >> MULTUNITSIZE)+ q + (lsb_factor & (q1 ^ q2)); +#else /* optimized C version */ + q = (q0 >> MULTUNITSIZE)+ (q1>>1) + (q2>>1) + 1; +#endif + +/* Compute the most significant term and add in the others */ + + q = (q >> (MULTUNITSIZE-2)) + + (((dividend[0] ^ MULTUNIT_mask) * (unsigned long)reciph) << 1); + q >>= mshift; + +/* Prevent overflow and then wipe out the intermediate results. */ + + mutemp = (MULTUNIT)min(q, (1L << MULTUNITSIZE) -1); + q= q0 = q1 = q2 = 0; lsb_factor = 0; (void)lsb_factor; + return mutemp; +} +#endif /* mp_quo_digit */ + +/* stage_smith_modulus() - Prepare for a Smith modmult. + + Calculate the reciprocal of modulus with a precision of two MULTUNITs. + Assumes that global_precision has already been adjusted to the + size of the modulus, plus SLOP_BITS. + + Note: This routine was designed to work with large values and + doesn't have the necessary testing or handling to work with a + modulus having less than three significant units. For such cases, + the separate multiply and modulus routines can be used. + + stage_smith_modulus() is aliased to stage_modulus(). +*/ + +int stage_smith_modulus(unitptr n_modulus) +{ + int original_precision; + int sigmod; /* significant units in modulus */ + unitptr mp; /* modulus most significant pointer */ + MULTUNIT *mpm; /* reciprocal pointer */ + int prec; /* precision of reciprocal calc in units */ + + mp_move(modulus, n_modulus); + modmpl = (MULTUNIT*) modulus; + modmpl = lsbptr (modmpl, global_precision * MULTUNITs_perunit); + nbits = countbits(modulus); + modlenMULTUNITS = (nbits+ MULTUNITSIZE-1) / MULTUNITSIZE; + + original_precision = global_precision; + + /* The following code copies the three most significant units of + * modulus to mod_divisor. + */ + mp = modulus; + sigmod = significance (modulus); + rescale (mp, original_precision, sigmod); +/* prec is the unit precision required for 3 MULTUNITs */ + prec = (3 +(MULTUNITs_perunit-1)) / MULTUNITs_perunit; + set_precision (prec); + + /* set mp = ptr to most significant units of modulus, then move + * the most significant units to mp_divisor + */ + mp = msbptr(mp,sigmod) -tohigher(prec-1); + unmake_lsbptr (mp, prec); + mp_move (mod_divisor, mp); + + /* Keep 2*MULTUNITSIZE bits in mod_divisor. + * This will (normally) result in a reciprocal of 2*MULTUNITSIZE+1 bits. + */ + mshift = countbits (mod_divisor) - 2*MULTUNITSIZE; + mp_shift_right_bits (mod_divisor, mshift); + mp_recip(mod_quotient,mod_divisor); + mp_shift_right_bits (mod_quotient,1); + + /* Reduce to: 0 < mshift <= MULTUNITSIZE */ + mshift = ((mshift + (MULTUNITSIZE-1)) % MULTUNITSIZE) +1; + /* round up, rescaling if necessary */ + mp_inc (mod_quotient); + if (countbits (mod_quotient) > 2*MULTUNITSIZE) { + mp_shift_right_bits (mod_quotient,1); + mshift--; /* now 0 <= mshift <= MULTUNITSIZE */ + } + mpm = lsbptr ((MULTUNIT*)mod_quotient, prec*MULTUNITs_perunit); + recipl = *post_higherunit (mpm); + reciph = *mpm; + mp_set_recip (reciph, recipl, mshift); + set_precision (original_precision); + return(0); /* normal return */ +} /* stage_smith_modulus */ + +/* Smith's algorithm performs a multiply combined with a modulo operation. + Computes: prod = (multiplicand*multiplier) mod modulus + The modulus must first be set by stage_smith_modulus(). + smith_modmult() is aliased to mp_modmult(). +*/ + +int +smith_modmult(unitptr prod, unitptr multiplicand, unitptr multiplier) +{ + unitptr d; /* ptr to product */ + MULTUNIT *dmph, *dmpl, *dmp; /* ptrs to dividend (high, low, first) + * aligned for subtraction */ +/* Note that dmph points one MULTUNIT higher than indicated by + global precision. This allows us to zero out a word one higher than + the normal precision. +*/ + short orig_precision; + short nqd; /* number of quotient digits remaining to + * be generated */ + short dmi; /* number of significant MULTUNITs in product */ + + d = ds_data + 1; /* room for leading MSB if HIGHFIRST */ + orig_precision = global_precision; + mp_dmul(d, multiplicand, multiplier); + + rescale(d, orig_precision * 2, orig_precision * 2 + 1); + set_precision(orig_precision * 2 + 1); + *msbptr(d, global_precision) = 0; /* leading 0 unit */ + +/* We now start working with MULTUNITs. + Determine the most significant MULTUNIT of the product so we don't + have to process leading zeros in our divide loop. +*/ + dmi = significance(d) * MULTUNITs_perunit; + if (dmi >= modlenMULTUNITS) + { /* Make dividend negative. This allows the use of mp_smul to + * "subtract" the product of the modulus and the trial divisor + * by actually adding to a negative dividend. + * The one's complement of the dividend is used, since it causes + * a zero value to be represented as all ones. This facilitates + * testing the result for possible overflow, since a sign bit + * indicates that no adjustment is necessary, and we should not + * attempt to adjust if the result of the addition is zero. + */ + mp_inc(d); + mp_neg(d); + set_precision(orig_precision); + munit_prec = global_precision * UNITSIZE / MULTUNITSIZE; + + /* Set msb, lsb, and normal ptrs of dividend */ + dmph = lsbptr((MULTUNIT *) d, (orig_precision * 2 + 1) * + MULTUNITs_perunit) + tohigher(dmi); + nqd = dmi + 1 - modlenMULTUNITS; + dmpl = dmph - tohigher(modlenMULTUNITS); + +/* Divide loop. + Each iteration computes the next quotient MULTUNIT digit, then + multiplies the divisor (modulus) by the quotient digit and adds + it to the one's complement of the dividend (equivalent to + subtracting). If the product was greater than the remaining dividend, + we get a non-negative result, in which case we subtract off the + modulus to get the proper negative remainder. +*/ + for (; nqd; nqd--) + { MULTUNIT q; /* quotient trial digit */ + + q = mp_quo_digit(dmph); + if (q > 0) + { mp_smul(dmpl, modmpl, q); + + /* Perform correction if q too large. + * This rarely occurs. + */ + if (!(*dmph & MULTUNIT_msb)) + { dmp = dmpl; + unmake_lsbptr(dmp, orig_precision * + MULTUNITs_perunit); + if (mp_musubb(dmp, + (MULTUNIT *) modulus, 0)) + (*dmph) --; + } + } + pre_lowerunit(dmph); + pre_lowerunit(dmpl); + } + /* d contains the one's complement of the remainder. */ + rescale(d, orig_precision * 2 + 1, orig_precision); + set_precision(orig_precision); + mp_neg(d); + mp_dec(d); + } else + { /* Product was less than modulus. Return it. */ + rescale(d, orig_precision * 2 + 1, orig_precision); + set_precision(orig_precision); + } + mp_move(prod, d); + return (0); /* normal return */ +} /* smith_modmult */ + + +/* Smith's mp_modmult function leaves some internal arrays in memory, + so we have to call modmult_burn() at the end of mp_modexp. + This is so that no cryptographically sensitive data is left in memory + after the program exits. + smith_burn() is aliased to modmult_burn(). +*/ +void smith_burn(void) +{ + empty_array (modulus); + empty_array (ds_data); + empty_array (mod_quotient); + empty_array (mod_divisor); + modmpl = 0; + mshift =nbits = 0; + reciph = recipl = 0; + modlenMULTUNITS = mutemp = 0; + mp_set_recip (0,0,0); +} /* smith_burn */ + +/* End of Thad Smith's implementation of modmult. */ + +#endif /* SMITH */ + + +int countbits(unitptr r) + /* Returns number of significant bits in r */ +{ int bits; + short prec; + register unit bitmask; + init_bitsniffer(r,bitmask,prec,bits); + return(bits); +} /* countbits */ + + +const char *copyright_notice(void) +/* force linker to include copyright notice in the executable object image. */ +{ return ("(c)1986 Philip Zimmermann"); } /* copyright_notice */ + + +int mp_modexp(register unitptr expout,register unitptr expin, + register unitptr exponent,register unitptr modulus) +{ /* Russian peasant combined exponentiation/modulo algorithm. + Calls modmult instead of mult. + Computes: expout = (expin**exponent) mod modulus + WARNING: All the arguments must be less than the modulus! + */ + int bits; + short oldprecision; + register unit bitmask; + unit product[MAX_UNIT_PRECISION]; + short eprec; + +#ifdef COUNTMULTS + tally_modmults = 0; /* clear "number of modmults" counter */ + tally_modsquares = 0; /* clear "number of modsquares" counter */ +#endif /* COUNTMULTS */ + mp_init(expout,1); + if (testeq(exponent,0)) + { if (testeq(expin,0)) + return(-1); /* 0 to the 0th power means return error */ + return(0); /* otherwise, zero exponent means expout is 1 */ + } + if (testeq(modulus,0)) + return(-2); /* zero modulus means error */ +#if SLOP_BITS > 0 /* if there's room for sign bits */ + if (mp_tstminus(modulus)) + return(-2); /* negative modulus means error */ +#endif /* SLOP_BITS > 0 */ + if (mp_compare(expin,modulus) >= 0) + return(-3); /* if expin >= modulus, return error */ + if (mp_compare(exponent,modulus) >= 0) + return(-4); /* if exponent >= modulus, return error */ + + oldprecision = global_precision; /* save global_precision */ + /* set smallest optimum precision for this modulus */ + set_precision(bits2units(countbits(modulus)+SLOP_BITS)); + /* rescale all these registers to global_precision we just defined */ + rescale(modulus,oldprecision,global_precision); + rescale(expin,oldprecision,global_precision); + rescale(exponent,oldprecision,global_precision); + rescale(expout,oldprecision,global_precision); + + if (stage_modulus(modulus)) + { set_precision(oldprecision); /* restore original precision */ + return(-5); /* unstageable modulus (STEWART algorithm) */ + } + + /* normalize and compute number of bits in exponent first */ + init_bitsniffer(exponent,bitmask,eprec,bits); + + /* We can "optimize out" the first modsquare and modmult: */ + bits--; /* We know for sure at this point that bits>0 */ + mp_move(expout,expin); /* expout = (1*1)*expin; */ + bump_bitsniffer(exponent,bitmask); + + while (bits--) + { + poll_for_break(); /* polls keyboard, allows ctrl-C to abort program */ +#ifdef COUNTMULTS + tally_modsquares++; /* bump "number of modsquares" counter */ +#endif /* COUNTMULTS */ + mp_modsquare(product,expout); + if (sniff_bit(exponent,bitmask)) + { mp_modmult(expout,product,expin); +#ifdef COUNTMULTS + tally_modmults++; /* bump "number of modmults" counter */ +#endif /* COUNTMULTS */ + } else + { + mp_move(expout,product); + } + bump_bitsniffer(exponent,bitmask); + } /* while bits-- */ + mp_burn(product); /* burn the evidence on the stack */ + modmult_burn(); /* ask mp_modmult to also burn its own evidence */ + +#ifdef COUNTMULTS /* diagnostic analysis */ + { long atomic_mults; + unsigned int unitcount,totalmults; + unitcount = bits2units(countbits(modulus)); + /* calculation assumes modsquare takes as long as a modmult: */ + atomic_mults = (long) tally_modmults * (unitcount * unitcount); + atomic_mults += (long) tally_modsquares * (unitcount * unitcount); + printf("%ld atomic mults for ",atomic_mults); + printf("%d+%d = %d modsqr+modmlt, at %d bits, %d words.\n", + tally_modsquares,tally_modmults, + tally_modsquares+tally_modmults, + countbits(modulus), unitcount); + } +#endif /* COUNTMULTS */ + + set_precision(oldprecision); /* restore original precision */ + + /* Do an explicit reference to the copyright notice so that the linker + will be forced to include it in the executable object image... */ + copyright_notice(); /* has no real effect at run time */ + + return(0); /* normal return */ +} /* mp_modexp */ + +int mp_modexp_crt(unitptr expout, unitptr expin, + unitptr p, unitptr q, unitptr ep, unitptr eq, unitptr u) + /* This is a faster modexp for moduli with a known + factorisation into two relatively prime factors p and q, + and an input relatively prime to the modulus, + the Chinese Remainder Theorem to do the computation + mod p and mod q, and then combine the results. This + relies on a number of precomputed values, but does not + actually require the modulus n or the exponent e. + + expout = expin ^ e mod (p*q). + We form this by evaluating + p2 = (expin ^ e) mod p and + q2 = (expin ^ e) mod q + and then combining the two by the CRT. + + Two optimisations of this are possible. First, we can + reduce expin modulo p and q before starting. + + Second, since we know the factorisation of p and q + (trivially derived from the factorisation of n = p*q), + and expin is relatively prime to both p and q, + we can use Euler's theorem, expin^phi(m) = 1 (mod m), + to throw away multiples of phi(p) or phi(q) in e. + Letting ep = e mod phi(p) and + eq = e mod phi(q) + then combining these two speedups, we only need to evaluate + p2 = ((expin mod p) ^ ep) mod p and + q2 = ((expin mod q) ^ eq) mod q. + + Now we need to apply the CRT. Starting with + expout = p2 (mod p) and + expout = q2 (mod q) + we can say that expout = p2 + p * k, and if we assume that + 0 <= p2 < p, then 0 <= expout < p*q for some 0 <= k < q. + Since we want expout = q2 (mod q), then + p*k = q2-p2 (mod q). Since p and q are relatively + prime, p has a multiplicative inverse u mod q. In other + words, + u = 1/p (mod q). + Multiplying by u on both sides gives k = u*(q2-p2) (mod q). + Since we want 0 <= k < q, we can thus find k as + k = (u * (q2-p2)) mod q. + + Once we have k, evaluating p2 + p * k is easy, and + that gives us the result. + + In the detailed implementation, there is a temporary, temp, + used to hold intermediate results, p2 is held in expout, + and q2 is used as a temporary in the final step when it is + no longer needed. With that, you should be able to + understand the code below. + */ +{ + unit q2[MAX_UNIT_PRECISION]; + unit temp[MAX_UNIT_PRECISION]; + int status; + +/* First, compiute p2 (physically held in M) */ + +/* p2 = [ (expin mod p) ^ ep ] mod p */ + mp_mod(temp,expin,p); /* temp = expin mod p */ + status = mp_modexp(expout,temp,ep,p); + if (status < 0) /* mp_modexp returned an error. */ + { mp_init(expout,1); + return(status); /* error return */ + } + +/* And the same thing for q2 */ + +/* q2 = [ (expin mod q) ^ eq ] mod q */ + mp_mod(temp,expin,q); /* temp = expin mod q */ + status = mp_modexp(q2,temp,eq,q); + if (status < 0) /* mp_modexp returned an error. */ + { mp_init(expout,1); + return(status); /* error return */ + } + +/* Now use the multiplicative inverse u to glue together the + two halves. +*/ +#if 0 +/* This optimisation is useful if you commonly get small results, + but for random results and large q, the odds of (1/q) of it + being useful do not warrant the test. +*/ + if (mp_compare(expout,q2) != 0) + { +#endif + /* Find q2-p2 mod q */ + if (mp_sub(q2,expout)) /* if the result went negative */ + mp_add(q2,q); /* add q to q2 */ + + /* expout = p2 + ( p * [(q2*u) mod q] ) */ + mp_mult(temp,q2,u); /* q2*u */ + mp_mod(q2,temp,q); /* (q2*u) mod q */ + mp_mult(temp,p,q2); /* p * [(q2*u) mod q] */ + mp_add(expout,temp); /* expout = p2 + p * [...] */ +#if 0 + } +#endif + + mp_burn(q2); /* burn the evidence on the stack...*/ + mp_burn(temp); + return(0); /* normal return */ +} /* mp_modexp_crt */ + + +/****************** end of MPI library ****************************/ diff --git a/lib/mpilib.h b/lib/mpilib.h new file mode 100644 index 0000000..0227105 --- /dev/null +++ b/lib/mpilib.h @@ -0,0 +1,468 @@ +/* C include file for MPI multiprecision integer math routines. + + Boulder Software Engineering + 3021 Eleventh Street + Boulder, CO 80304 + (303) 541-0140 + + (c) Copyright 1986-92 by Philip Zimmermann. All rights reserved. + The author assumes no liability for damages resulting from the use + of this software, even if the damage results from defects in this + software. No warranty is expressed or implied. + + These routines implement all of the multiprecision arithmetic necessary + for Rivest-Shamir-Adleman (RSA) public key cryptography, as well as + other number-theoretic algorithms such as ElGamal, Diffie-Hellman, + or Rabin. + + Although originally developed in Microsoft C for the IBM PC, this code + contains few machine dependencies. It assumes 2's complement + arithmetic. It can be adapted to 8-bit, 16-bit, or 32-bit machines, + lowbyte-highbyte order or highbyte-lowbyte order. This version + has been converted to ANSI C. + + Modified 8 Apr 92 - HAJK - Implement new VAX/VMS primitive support. + Modified 29 Nov 92 - Thad Smith +*/ + +#include +#include "usuals.h" /* typedefs for byte, word16, boolean, etc. */ +#include "platform.h" /* customization for different environments */ + +/* Platform customization: + * A version which runs on almost any computer can be implemented by + * defining PORTABLE and MPORTABLE, preferably as a command line + * parameter. Faster versions can be generated by specifying specific + * parameters, such as size of unit and MULTUNIT, and by supplying some + * of the critical in assembly. See the file platform.h for more + * details on customization. + * + * The symbol HIGHFIRST, designating that integers and longs are stored + * with the most significant bit in the lowest address, should be defined + * on the command line for compiling all files, since it is used by files + * other than the mpilib routines. + */ + +#ifndef ALIGN +#define ALIGN +#endif + +#ifndef PEASANT /* if not Russian peasant modulo multiply algorithm */ +#ifndef MERRITT /* if not Merritt's modmult */ +#ifndef UPTON /* if not Upton's modmult */ +#ifndef SMITH +#define SMITH /* default: use Smith's modmult algorithm */ +#endif +#endif +#endif +#endif + +#ifdef SMITH +#define UPTON_OR_SMITH /* enable common code */ +#endif +#ifdef UPTON +#define UPTON_OR_SMITH /* enable common code */ +#endif + +#ifndef UNIT32 +#ifndef UNIT8 +#define UNIT16 /* default--use 16-bit units */ +#endif +#endif + +/*** CAUTION: If your machine has an unusual word size that is not a + power of 2 (8, 16, 32, or 64) bits wide, then the macros here that + use the symbol "LOG_UNITSIZE" must be changed. +***/ + +#ifdef UNIT8 +typedef unsigned char unit; +typedef signed char signedunit; +#define UNITSIZE 8 /* number of bits in a unit */ +#define LOG_UNITSIZE 3 +#define uppermostbit ((unit) 0x80) +#define BYTES_PER_UNIT 1 /* number of bytes in a unit */ +#define units2bits(n) ((n) << 3) /* fast multiply by UNITSIZE */ +#define units2bytes(n) (n) +#define bits2units(n) (((n)+7) >> 3) +#define bytes2units(n) (n) +#endif + +#ifdef UNIT16 +typedef word16 unit; +typedef short signedunit; +#define UNITSIZE 16 /* number of bits in a unit */ +#define LOG_UNITSIZE 4 +#define uppermostbit ((unit) 0x8000) +#define BYTES_PER_UNIT 2 /* number of bytes in a unit */ +#define units2bits(n) ((n) << 4) /* fast multiply by UNITSIZE */ +#define units2bytes(n) ((n) << 1) +#define bits2units(n) (((n)+15) >> 4) +#define bytes2units(n) (((n)+1) >> 1) +#endif + +#ifdef UNIT32 +typedef word32 unit; +typedef long signedunit; +#define UNITSIZE 32 /* number of bits in a unit */ +#define LOG_UNITSIZE 5 +#define uppermostbit ((unit) 0x80000000L) +#define BYTES_PER_UNIT 4 /* number of bytes in a unit */ +#define units2bits(n) ((n) << 5) /* fast multiply by UNITSIZE */ +#define units2bytes(n) ((n) << 2) +#define bits2units(n) (((n)+31) >> 5) +#define bytes2units(n) (((n)+3) >> 2) +#endif + +#define power_of_2(b) ((unit) 1 << (b)) /* computes power-of-2 bit masks */ +#define bits2bytes(n) (((n)+7) >> 3) +/* Some C compilers (like the ADSP2101) will not always collapse constant + expressions at compile time if the expressions contain shift operators. */ +/* #define uppermostbit power_of_2(UNITSIZE-1) */ +/* #define UNITSIZE units2bits(1) */ /* number of bits in a unit */ +/* #define bytes2units(n) bits2units((n)<<3) */ +/* #define BYTES_PER_UNIT (UNITSIZE >> 3) */ +/* LOG_UNITSIZE is the log base 2 of UNITSIZE, ie: 4 for 16-bit units */ +/* #define units2bits(n) ((n) << LOG_UNITSIZE) */ /* fast multiply by UNITSIZE */ +/* #define units2bytes(n) ((n) << (LOG_UNITSIZE-3)) */ +/* #define bits2units(n) (((n)+(UNITSIZE-1)) >> LOG_UNITSIZE) */ +/* #define bytes2units(n) (((n)+(BYTES_PER_UNIT-1)) >> (LOG_UNITSIZE-3)) */ + +typedef unit *unitptr; + + +/*--------------------- Byte ordering stuff -------------------*/ +#ifdef HIGHFIRST + +/* these definitions assume MSB comes first */ +#define tohigher(n) (-(n)) /* offset towards higher unit */ +#define pre_higherunit(r) (--(r)) +#define pre_lowerunit(r) (++(r)) +#define post_higherunit(r) ((r)--) +#define post_lowerunit(r) ((r)++) +#define bit_index(n) (global_precision-bits2units((n)+1)) +#define lsbptr(r,prec) ((r)+(prec)-1) +#define make_lsbptr(r,prec) (r) = lsbptr(r,prec) +#define unmake_lsbptr(r,prec) (r) = ((r)-(prec)+1) +#define msbptr(r,prec) (r) +#define make_msbptr(r,prec) /* (r) = msbptr(r,prec) */ + +/* The macro rescale(r,current_precision,new_precision) rescales + a multiprecision integer by adjusting r and its precision to new values. + It can be used to reverse the effects of the normalize + routine given above. See the comments in normalize concerning + Intel vs. Motorola LSB/MSB conventions. + WARNING: You can only safely call rescale on registers that + you have previously normalized with the above normalize routine, + or are known to be big enough for the new precision. You may + specify a new precision that is smaller than the current precision. + You must be careful not to specify a new_precision value that is + too big, or which adjusts the r pointer out of range. +*/ +#define rescale(r,currentp,newp) r -= ((newp) - (currentp)) + +/* The macro normalize(r,precision) "normalizes" a multiprecision integer + by adjusting r and precision to new values. For Motorola-style processors + (MSB-first), r is a pointer to the MSB of the register, and must + be adjusted to point to the first nonzero unit. For Intel/VAX-style + (LSB-first) processors, r is a pointer to the LSB of the register, + and must be left unchanged. The precision counter is always adjusted, + regardless of processor type. In the case of precision = 0, + r becomes undefined. +*/ +#define normalize(r,prec) \ + { prec = significance(r); r += (global_precision-(prec)); } + +#else /* LOWFIRST byte order */ + +/* these definitions assume LSB comes first */ +#define tohigher(n) (n) /* offset towards higher unit */ +#define pre_higherunit(r) (++(r)) +#define pre_lowerunit(r) (--(r)) +#define post_higherunit(r) ((r)++) +#define post_lowerunit(r) ((r)--) +#define bit_index(n) (bits2units((n)+1)-1) +#define lsbptr(r,prec) (r) +#define make_lsbptr(r,prec) /* (r) = lsbptr(r,prec) */ +#define unmake_lsbptr(r,prec) /* (r) = (r) */ +#define msbptr(r,prec) ((r)+(prec)-1) +#define make_msbptr(r,prec) (r) = msbptr(r,prec) + +#define rescale(r,currentp,newp) /* nil statement */ +#define normalize(r,prec) prec = significance(r) + +#endif /* LOWFIRST byte order */ +/*------------------ End byte ordering stuff -------------------*/ + +/* Note that the address calculations require that lsbptr, msbptr, + make_lsbptr, make_msbptr, mp_tstbit, mp_setbit, mp_clrbit, + and bitptr all have unitptr arguments, not byte pointer arguments. */ +#define bitptr(r,n) &((r)[bit_index(n)]) +#define bitmsk(n) power_of_2((n) & (UNITSIZE-1)) + /* bitmsk() assumes UNITSIZE is a power of 2 */ +#define mp_tstbit(r,n) (*bitptr(r,n) & bitmsk(n)) +#define mp_setbit(r,n) (*bitptr(r,n) |= bitmsk(n)) +#define mp_clrbit(r,n) (*bitptr(r,n) &= ~bitmsk(n)) +#define msunit(r) (*msbptr(r,global_precision)) +#define lsunit(r) (*lsbptr(r,global_precision)) +/* #define mp_tstminus(r) ((msunit(r) & uppermostbit)!=0) */ +#define mp_tstminus(r) ((signedunit) msunit(r) < 0) + + + /* set working precision to specified number of bits. */ +#ifdef mp_setp +void mp_setp(short nbits); +#define set_precision(prec) mp_setp(units2bits(global_precision=(prec))) +#else +#define set_precision(prec) (global_precision = (prec)) +#endif + + +#ifdef PEASANT + +/* Define C names for Russian peasant modmult primitives. */ +#define stage_modulus stage_peasant_modulus +#define mp_modmult peasant_modmult +#define modmult_burn peasant_burn +#define SLOP_BITS PEASANT_SLOP_BITS + +#else /* not PEASANT */ +#ifdef MERRITT +/* Define C names for Merritt's modmult primitives. */ +#define stage_modulus stage_merritt_modulus +#define mp_modmult merritt_modmult +#define modmult_burn merritt_burn +#define SLOP_BITS MERRITT_SLOP_BITS + +#else /* not PEASANT, MERRITT */ +#ifdef UPTON +/* Define C names for Upton's modmult primitives. */ +#define stage_modulus stage_upton_modulus +#define mp_modmult upton_modmult +#define modmult_burn upton_burn +#define SLOP_BITS UPTON_SLOP_BITS + +#else /* not PEASANT, MERRITT, UPTON */ +#ifdef SMITH +/* Define C names for Smith's modmult primitives. */ +#define stage_modulus stage_smith_modulus +#define mp_modmult smith_modmult +#define modmult_burn smith_burn +#define SLOP_BITS SMITH_SLOP_BITS + +#endif /* SMITH */ +#endif /* UPTON */ +#endif /* MERRITT */ +#endif /* PEASANT */ + + +#define mp_shift_left(r1) mp_rotate_left(r1,(boolean)0) + /* multiprecision shift left 1 bit */ + +#define mp_add(r1,r2) mp_addc(r1,r2,(boolean)0) + /* multiprecision add with no carry */ + +#define mp_sub(r1,r2) mp_subb(r1,r2,(boolean)0) + /* multiprecision subtract with no borrow */ + +#define mp_abs(r) (mp_tstminus(r) ? (mp_neg(r),TRUE) : FALSE) + +#define msub(r,m) if (mp_compare(r,m) >= 0) mp_sub(r,m) + /* Prevents r from getting bigger than modulus m */ + +#define testeq(r,i) \ + ( (lsunit(r)==(i)) && (significance(r)<=1) ) + +#define testne(r,i) \ + ( (lsunit(r)!=(i)) || (significance(r)>1) ) + +#define testge(r,i) \ + ( (lsunit(r)>=(i)) || (significance(r)>1) ) + +#define testle(r,i) \ + ( (lsunit(r)<=(i)) && (significance(r)<=1) ) + +#define mp_square(r1,r2) mp_mult(r1,r2,r2) + /* Square r2, returning product in r1 */ + +#define mp_modsquare(r1,r2) mp_modmult(r1,r2,r2) + /* Square r2, returning modulo'ed product in r1 */ + +#define countbytes(r) ((countbits(r)+7)>>3) + +/* SLOP_BITS is how many "carry bits" to allow for intermediate + calculation results to exceed the size of the modulus. + It is used by modexp to give some overflow elbow room for + modmult to use to perform modulo operations with the modulus. + The number of slop bits required is determined by the modmult + algorithm. The Russian peasant modmult algorithm only requires + 1 slop bit, for example. Note that if we use an external assembly + modmult routine, SLOP_BITS may be meaningless or may be defined in a + non-constant manner. +*/ +#define PEASANT_SLOP_BITS 1 +#define MERRITT_SLOP_BITS UNITSIZE +#define UPTON_SLOP_BITS (UNITSIZE/2) +#ifdef mp_smul /* old version requires MS word = 0 */ +#define SMITH_SLOP_BITS UNITSIZE +#else /* mp_smula or C version of mp_smul */ +#define SMITH_SLOP_BITS 0 +#endif /* mp_smul */ + +/* MAX_BIT_PRECISION is upper limit that assembly primitives can handle. + It must be less than 32704 bits, or 4088 bytes. It should be an + integer multiple of UNITSIZE*2. +*/ +#if (SLOP_BITS > 0) +#define MAX_BIT_PRECISION (1280+(2*UNITSIZE)) +#else +#define MAX_BIT_PRECISION 1280 +#endif +#define MAX_BYTE_PRECISION (MAX_BIT_PRECISION/8) +#define MAX_UNIT_PRECISION (MAX_BIT_PRECISION/UNITSIZE) + + +/* global_precision is the unit precision last set by set_precision */ +extern short global_precision; + + +/* The "bit sniffer" macros all begin sniffing at the MSB. + They are used internally by all the various multiply, divide, + modulo, exponentiation, and square root functions. +*/ +#define sniff_bit(bptr,bitmask) (*(bptr) & bitmask) + +#define init_bitsniffer(bptr,bitmask,prec,bits) \ +{ normalize(bptr,prec); \ + if (!prec) \ + return(0); \ + bits = units2bits(prec); \ + make_msbptr(bptr,prec); bitmask = uppermostbit; \ + while (!sniff_bit(bptr,bitmask)) \ + { bitmask >>= 1; bits--; \ + } \ +} + +#define bump_bitsniffer(bptr,bitmask) \ +{ if (!(bitmask >>= 1)) \ + { bitmask = uppermostbit; \ + post_lowerunit(bptr); \ + } \ +} + +/* bump_2bitsniffers is used internally by mp_udiv. */ +#define bump_2bitsniffers(bptr,bptr2,bitmask) \ +{ if (!(bitmask >>= 1)) \ + { bitmask = uppermostbit; \ + post_lowerunit(bptr); \ + post_lowerunit(bptr2); \ + } \ +} + +/* stuff_bit is used internally by mp_udiv and mp_sqrt. */ +#define stuff_bit(bptr,bitmask) *(bptr) |= bitmask + + +boolean mp_addc + (register unitptr r1,register unitptr r2,register boolean carry); + /* multiprecision add with carry r2 to r1, result in r1 */ + +boolean mp_subb + (register unitptr r1,register unitptr r2,register boolean borrow); + /* multiprecision subtract with borrow, r2 from r1, result in r1 */ + +boolean mp_rotate_left(register unitptr r1,register boolean carry); + /* multiprecision rotate left 1 bit with carry, result in r1. */ + +void mp_shift_right_bits(register unitptr r1,register short bits); + /* multiprecision shift right bits, result in r1. */ + +short mp_compare(register unitptr r1,register unitptr r2); + /* Compares registers *r1, *r2, and returns -1, 0, or 1 */ + +boolean mp_inc(register unitptr r); + /* Increment multiprecision integer r. */ + +boolean mp_dec(register unitptr r); + /* Decrement multiprecision integer r. */ + +void mp_neg(register unitptr r); + /* Compute 2's complement, the arithmetic negative, of r */ + +#ifndef mp_move +#define mp_move(d,s) memcpy((void*)(d), (void*)(s), \ + units2bytes(global_precision)) +#endif +#ifndef unitfill0 +#define unitfill0(r,ct) memset((void*)(r), 0, units2bytes(ct)) +#endif + +#ifndef mp_burn +#define mp_burn(r) mp_init(r,0) /* for burning the evidence */ +#define mp_init0(r) mp_init(r,0) +#endif + +#define empty_array(r) unitfill0(r, sizeof(r)/sizeof(r[0])/sizeof(unit)) + +void mp_init(register unitptr r, word16 value); + /* Init multiprecision register r with short value. */ + +short significance(register unitptr r); + /* Returns number of significant units in r */ + +int mp_udiv(register unitptr remainder,register unitptr quotient, + register unitptr dividend,register unitptr divisor); + /* Unsigned divide, treats both operands as positive. */ + +int mp_recip(register unitptr quotient,register unitptr divisor); + /* Compute reciprocal as 1/divisor. Used by faster modmult. */ + +int mp_div(register unitptr remainder,register unitptr quotient, + register unitptr dividend,register unitptr divisor); + /* Signed divide, either or both operands may be negative. */ + +word16 mp_shortdiv(register unitptr quotient, + register unitptr dividend,register word16 divisor); + /* Returns short remainder of unsigned divide. */ + +int mp_mod(register unitptr remainder, + register unitptr dividend,register unitptr divisor); + /* Unsigned divide, treats both operands as positive. */ + +word16 mp_shortmod(register unitptr dividend,register word16 divisor); + /* Just returns short remainder of unsigned divide. */ + +int mp_mult(register unitptr prod, + register unitptr multiplicand,register unitptr multiplier); + /* Computes multiprecision prod = multiplicand * multiplier */ + +int countbits(unitptr r); + /* Returns number of significant bits in r. */ + +int stage_peasant_modulus(unitptr n); +int stage_merritt_modulus(unitptr n); +int stage_upton_modulus(unitptr n); +int stage_smith_modulus(unitptr n); + /* Must pass modulus to stage_modulus before calling modmult. */ + +int peasant_modmult(register unitptr prod, + unitptr multiplicand,register unitptr multiplier); +int merritt_modmult(register unitptr prod, + unitptr multiplicand,register unitptr multiplier); +int upton_modmult(register unitptr prod, + unitptr multiplicand,register unitptr multiplier); +int smith_modmult(register unitptr prod, + unitptr multiplicand,register unitptr multiplier); + /* Performs combined multiply/modulo operation, with global modulus */ + + + +int mp_modexp(register unitptr expout,register unitptr expin, + register unitptr exponent,register unitptr modulus); + /* Combined exponentiation/modulo algorithm. */ + +int mp_modexp_crt(unitptr expout, unitptr expin, + unitptr p, unitptr q, unitptr ep, unitptr eq, unitptr u); + /* exponentiation and modulo using Chinese Remainder Theorem */ + +/****************** end of MPI library ****************************/ diff --git a/lib/ncplib.c b/lib/ncplib.c index 8fc7af2..4fceafb 100644 --- a/lib/ncplib.c +++ b/lib/ncplib.c @@ -5,8 +5,20 @@ * */ +#if 0 +#define ncp_dprintf(X...) printf(X) +#else +#define ncp_dprintf(X...) +#endif #include "ncplib.h" #include "ncplib_err.h" +#ifdef SIGNATURES +#include "ncpsign.h" +#endif +#ifdef NDS_SUPPORT +extern int bindery_only; +#include "ndslib.h" +#endif #include extern pid_t wait(int *); @@ -20,17 +32,35 @@ extern pid_t wait(int *); #include #include #include -#include +#include "kernel/route.h" #include #include #include #include #include #include +#ifdef CONFIG_NATIVE_IP +#include +#endif + +#define NCP_DEFAULT_BUFSIZE 1024 +#define NCP_MAX_BUFSIZE 1024 +#ifdef SIGNATURES +#define NCP_DEFAULT_OPTIONS 2 +int in_options = NCP_DEFAULT_OPTIONS; +#endif static long ncp_negotiate_buffersize(struct ncp_conn *conn, int size, int *target); + +#ifdef SIGNATURES +static long + ncp_negotiate_size_and_options(struct ncp_conn *conn, + int size, int options, + int *ret_size, int *ret_options); +#endif + static long ncp_login_object(struct ncp_conn *conn, const unsigned char *username, @@ -38,11 +68,16 @@ static long const unsigned char *password); static long - ncp_do_close(struct ncp_conn *conn); +ncp_do_close(struct ncp_conn *conn); -void str_upper(char *name) +static long +ncp_find_server_ipx(const char **server_name, int type, struct sockaddr_ipx* addr); + +void +str_upper(char *name) { - while (*name) { + while (*name) + { *name = toupper(*name); name = name + 1; } @@ -53,11 +88,13 @@ void str_upper(char *name) static int debug_level = 5; static FILE *logfile = stderr; -static void dprintf(int level, char *p,...) +static void +dprintf(int level, char *p,...) { va_list ap; - if (level > debug_level) { + if (level > debug_level) + { return; } va_start(ap, p); @@ -73,7 +110,8 @@ static void dprintf(int level, char *p,...) the file nwcrypt.c intact and separate for copyright reasons */ #include "nwcrypt.c" -void ipx_fprint_node(FILE * file, IPXNode node) +void +ipx_fprint_node(FILE * file, IPXNode node) { fprintf(file, "%02X%02X%02X%02X%02X%02X", (unsigned char) node[0], @@ -85,17 +123,20 @@ void ipx_fprint_node(FILE * file, IPXNode node) ); } -void ipx_fprint_network(FILE * file, IPXNet net) +void +ipx_fprint_network(FILE * file, IPXNet net) { - fprintf(file, "%08lX", ntohl(net)); + fprintf(file, "%08X", (u_int32_t)ntohl(net)); } -void ipx_fprint_port(FILE * file, IPXPort port) +void +ipx_fprint_port(FILE * file, IPXPort port) { fprintf(file, "%04X", ntohs(port)); } -void ipx_fprint_saddr(FILE * file, struct sockaddr_ipx *sipx) +void +ipx_fprint_saddr(FILE * file, struct sockaddr_ipx *sipx) { ipx_fprint_network(file, sipx->sipx_network); fprintf(file, ":"); @@ -104,66 +145,80 @@ void ipx_fprint_saddr(FILE * file, struct sockaddr_ipx *sipx) ipx_fprint_port(file, sipx->sipx_port); } -void ipx_print_node(IPXNode node) +void +ipx_print_node(IPXNode node) { ipx_fprint_node(stdout, node); } -void ipx_print_network(IPXNet net) +void +ipx_print_network(IPXNet net) { ipx_fprint_network(stdout, net); } -void ipx_print_port(IPXPort port) +void +ipx_print_port(IPXPort port) { ipx_fprint_port(stdout, port); } -void ipx_print_saddr(struct sockaddr_ipx *sipx) +void +ipx_print_saddr(struct sockaddr_ipx *sipx) { ipx_fprint_saddr(stdout, sipx); } -int ipx_sscanf_node(char *buf, unsigned char node[6]) +int +ipx_sscanf_node(char *buf, unsigned char node[6]) { 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) { + &(n[3]), &(n[4]), &(n[5]))) != 6) + { return i; } - for (i = 0; i < 6; i++) { + for (i = 0; i < 6; i++) + { node[i] = n[i]; } return 6; } -static int ipx_sscanf_saddr(char *buf, struct sockaddr_ipx *target) +int +ipx_sscanf_saddr(char *buf, struct sockaddr_ipx *target) { char *p; struct sockaddr_ipx addr; + unsigned long sipx_network; addr.sipx_family = AF_IPX; addr.sipx_type = NCP_PTYPE; - if (sscanf(buf, "%lx", (unsigned long int *) &addr.sipx_network) != 1) { + if (sscanf(buf, "%lx", &sipx_network) != 1) + { return 1; } - addr.sipx_network = htonl(addr.sipx_network); - if ((p = strchr(buf, ':')) == NULL) { + addr.sipx_network = htonl(sipx_network); + if ((p = strchr(buf, ':')) == NULL) + { return 1; } p += 1; - if (ipx_sscanf_node(p, addr.sipx_node) != 6) { + if (ipx_sscanf_node(p, addr.sipx_node) != 6) + { return 1; } - if ((p = strchr(p, ':')) == NULL) { + if ((p = strchr(p, ':')) == NULL) + { return 1; } p += 1; - if (sscanf(p, "%hx", &addr.sipx_port) != 1) { + if (sscanf(p, "%hx", &addr.sipx_port) != 1) + { return 1; } addr.sipx_port = htons(addr.sipx_port); @@ -171,19 +226,16 @@ static int ipx_sscanf_saddr(char *buf, struct sockaddr_ipx *target) return 0; } -void ipx_assign_node(IPXNode dest, IPXNode src) -{ - memcpy(dest, src, IPX_NODE_LEN); -} - -int ipx_node_equal(IPXNode n1, IPXNode n2) +int +ipx_node_equal(CIPXNode n1, CIPXNode n2) { return memcmp(n1, n2, IPX_NODE_LEN) == 0; } -static int ipx_recvfrom(int sock, void *buf, int len, unsigned int flags, - struct sockaddr_ipx *sender, int *addrlen, int timeout, - long *err) +static int +x_recvfrom(int sock, void *buf, int len, unsigned int flags, + struct sockaddr *sender, int *addrlen, int timeout, + long *err) { fd_set rd, wr, ex; struct timeval tv; @@ -197,34 +249,277 @@ static int ipx_recvfrom(int sock, void *buf, int len, unsigned int flags, tv.tv_sec = timeout; tv.tv_usec = 0; - if ((result = select(sock + 1, &rd, &wr, &ex, &tv)) == -1) { + if ((result = select(sock + 1, &rd, &wr, &ex, &tv)) == -1) + { *err = errno; return -1; } - if (FD_ISSET(sock, &rd)) { - result = recvfrom(sock, buf, len, flags, - (struct sockaddr *) sender, addrlen); - } else { + if (FD_ISSET(sock, &rd)) + { + result = sender?recvfrom(sock, buf, len, flags, + sender, addrlen): + recv(sock, buf, len, flags); + } else + { result = -1; errno = ETIMEDOUT; } - if (result < 0) { + if (result < 0) + { *err = errno; } return result; } -static int ipx_recv(int sock, void *buf, int len, unsigned int flags, int timeout, - long *err) +static int +x_recv(int sock, void *buf, int len, unsigned int flags, int timeout, + long *err) { - struct sockaddr_ipx sender; - int addrlen = sizeof(sender); - - return ipx_recvfrom(sock, buf, len, flags, &sender, &addrlen, + return x_recvfrom(sock, buf, len, flags, NULL, 0, timeout, err); } -static int install_wdog(struct ncp_conn *conn) +#ifdef __MAKE_SULIB__ +static long +ipx_sap_find_nearest(int server_type, struct sockaddr_ipx *result, + char server_name[NCP_BINDERY_NAME_LEN]) +{ + struct sockaddr_ipx addr; + char data[1024]; + int sock; + int opt; + int packets; + int len; + + struct sap_server_ident *ident; + + if ((sock = socket(PF_IPX, SOCK_DGRAM, IPXPROTO_IPX)) < 0) + { + if (errno == EINVAL) + { + return NCPL_ET_NO_IPX; + } + return errno; + } + opt = 1; + /* Permit broadcast output */ + if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt)) == -1) + { + goto finished; + } + memzero(addr); + addr.sipx_family = AF_IPX; + addr.sipx_network = htonl(0x0); + addr.sipx_port = htons(0x0); + addr.sipx_type = IPX_SAP_PTYPE; + + if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) == -1) + { + if (errno == EADDRNOTAVAIL) + { + errno = NCPL_ET_NO_INTERFACE; + } + goto finished; + } + WSET_HL(data, 0, IPX_SAP_NEAREST_QUERY); + WSET_HL(data, 2, server_type); + + memzero(addr); + addr.sipx_family = AF_IPX; + addr.sipx_port = htons(IPX_SAP_PORT); + addr.sipx_type = IPX_SAP_PTYPE; + addr.sipx_network = htonl(0x0); + ipx_assign_node(addr.sipx_node, IPX_BROADCAST_NODE); + + if (sendto(sock, data, 4, 0, + (struct sockaddr *) &addr, sizeof(addr)) < 0) + { + goto finished; + } + packets = 5; + do + { + long err; + len = x_recv(sock, data, 1024, 0, 1, &err); + if (len < 66) + { + packets = packets - 1; + continue; + } + } + while ((ntohs(*((__u16 *) data)) != IPX_SAP_NEAREST_RESPONSE) + && (packets > 0)); + + if (packets == 0) + { + close(sock); + return NCPL_ET_NO_SERVER; + } + ident = (struct sap_server_ident *) (data + 2); + + result->sipx_family = AF_IPX; + result->sipx_network = ident->server_network; + result->sipx_port = ident->server_port; + ipx_assign_node(result->sipx_node, ident->server_node); + + memcpy(server_name, ident->server_name, sizeof(ident->server_name)); + + errno = 0; + + finished: + close(sock); + return errno; +} +#endif /* __MAKE_SULIB__ */ + +static int +ipx_make_reachable(const struct sockaddr_ipx* target) +{ +#ifdef __MAKE_SULIB__ + IPXNet network = target->sipx_network; + struct rtentry rt_def; + /* Router */ + struct sockaddr_ipx *sr = (struct sockaddr_ipx *) &rt_def.rt_gateway; + /* Target */ + struct sockaddr_ipx *st = (struct sockaddr_ipx *) &rt_def.rt_dst; + + struct ipx_rip_packet rip; + struct sockaddr_ipx addr; + int addrlen; + int sock; + int opt; + int res = -1; + int i; + int packets; + + if (geteuid() != 0) + { + errno = EPERM; + return -1; + } + memzero(rip); + + sock = socket(PF_IPX, SOCK_DGRAM, IPXPROTO_IPX); + + if (sock == -1) + { + if (errno == EINVAL) + { + return NCPL_ET_NO_IPX; + } + return errno; + } + opt = 1; + /* Permit broadcast output */ + if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt)) != 0) + { + goto finished; + } + memzero(addr); + addr.sipx_family = AF_IPX; + addr.sipx_network = htonl(0x0); + addr.sipx_port = htons(0x0); + addr.sipx_type = IPX_RIP_PTYPE; + + if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) != 0) + { + goto finished; + } + addr.sipx_family = AF_IPX; + addr.sipx_port = htons(IPX_RIP_PORT); + addr.sipx_type = IPX_RIP_PTYPE; + addr.sipx_network = htonl(0x0); + ipx_assign_node(addr.sipx_node, IPX_BROADCAST_NODE); + + rip.operation = htons(IPX_RIP_REQUEST); + rip.rt[0].network = network; + + if (sendto(sock, &rip, sizeof(rip), 0, + (struct sockaddr *) &addr, sizeof(addr)) < 0) + { + goto finished; + } + packets = 3; + do + { + long err; + int len; + + if (packets == 0) + { + goto finished; + } + addrlen = sizeof(struct sockaddr_ipx); + + len = x_recvfrom(sock, &rip, sizeof(rip), 0, (struct sockaddr*)sr, &addrlen, 1, + &err); + + if (len < sizeof(rip)) + { + packets = packets - 1; + continue; + } + } + while (ntohs(rip.operation) != IPX_RIP_RESPONSE); + + if (rip.rt[0].network != network) + { + goto finished; + } + rt_def.rt_flags = RTF_GATEWAY; + st->sipx_network = network; + st->sipx_family = AF_IPX; + sr->sipx_family = AF_IPX; + + i = 0; + do + { + res = ioctl(sock, SIOCADDRT, &rt_def); + i++; + } + while ((i < 5) && (res < 0) && (errno == EAGAIN)); + + finished: + close(sock); + + if (res != 0) + { + errno = ENETUNREACH; + } + return res; +#else + FILE *p; + char buf[40]; + + sprintf(buf, "nwsfind -a %08x:%02x%02x%02x%02x%02x%02x:%04x", + (u_int32_t)ntohl(target->sipx_network), + ((const unsigned char*)target->sipx_node)[0], + ((const unsigned char*)target->sipx_node)[1], + ((const unsigned char*)target->sipx_node)[2], + ((const unsigned char*)target->sipx_node)[3], + ((const unsigned char*)target->sipx_node)[4], + ((const unsigned char*)target->sipx_node)[5], + ntohs(target->sipx_port)); + + if (!(p = popen(buf, "r"))) { + return errno; + } + fgets(buf, sizeof(buf), p); + if (pclose(p)) { + return ENETUNREACH; + } + return 0; +#endif +} + +void +ipx_assign_node(IPXNode dest, CIPXNode src) +{ + memcpy(dest, src, IPX_NODE_LEN); +} + +static int +install_wdog(struct ncp_conn *conn) { int parent_pid = getpid(); int pid; @@ -236,28 +531,33 @@ static int install_wdog(struct ncp_conn *conn) int pktsize; - if ((pid = fork()) < 0) { + if ((pid = fork()) < 0) + { return -1; } - if (pid != 0) { + if (pid != 0) + { /* Parent, should go on as usual */ conn->wdog_pid = pid; return 0; } - while (1) { + while (1) + { long err; /* every 120 seconds we look if our parent is still alive */ - pktsize = ipx_recvfrom(sock, buf, sizeof(buf), 0, - &sender, &sizeofaddr, 120, &err); + pktsize = x_recvfrom(sock, buf, sizeof(buf), 0, + (struct sockaddr*)&sender, &sizeofaddr, 120, &err); - if (getppid() != parent_pid) { + if (getppid() != parent_pid) + { /* our parent has died, so nothing to do anymore */ exit(0); } if ((pktsize != 2) - || (buf[1] != '?')) { + || (buf[1] != '?')) + { continue; } buf[1] = 'Y'; @@ -272,26 +572,31 @@ static int install_wdog(struct ncp_conn *conn) static void assert_conn_locked(struct ncp_conn *conn); -static void assert_conn_not_locked(struct ncp_conn *conn) +static void +assert_conn_not_locked(struct ncp_conn *conn) { - if (conn->lock != 0) { + if (conn->lock != 0) + { ncp_printf("ncpfs: conn already locked!\n"); } } -static void ncp_lock_conn(struct ncp_conn *conn) +static void +ncp_lock_conn(struct ncp_conn *conn) { assert_conn_not_locked(conn); conn->lock = 1; } -static void ncp_unlock_conn(struct ncp_conn *conn) +static void +ncp_unlock_conn(struct ncp_conn *conn) { assert_conn_locked(conn); conn->lock = 0; } -static long do_ncp_call(struct ncp_conn *conn, int request_size) +static long +do_ncp_call(struct ncp_conn *conn, int request_size) { struct ncp_request_header request; @@ -301,53 +606,58 @@ static long do_ncp_call(struct ncp_conn *conn, int request_size) long err; memcpy(&request, conn->packet, sizeof(request)); +#ifdef SIGNATURES + if (conn->sign_active) + { + sign_packet(conn, &request_size); + } +#endif - while (retries > 0) { + while (retries > 0) + { struct ncp_reply_header reply; - struct sockaddr_ipx sender; - int sizeofaddr = sizeof(sender); retries -= 1; - result = sendto(conn->ncp_sock, conn->packet, - request_size, - 0, (struct sockaddr *) &(conn->i.addr), - sizeof(conn->i.addr)); + result = send(conn->ncp_sock, conn->packet, + request_size, 0); - if (result < 0) { + if (result < 0) + { return errno; } re_select: - len = ipx_recvfrom(conn->ncp_sock, - (char *) &reply, sizeof(reply), - MSG_PEEK, &sender, &sizeofaddr, 3, &err); + len = x_recv(conn->ncp_sock, + (char *) &reply, sizeof(reply), + MSG_PEEK, 3, &err); - if ((len < 0) && (err == ETIMEDOUT)) { + if ((len < 0) && (err == ETIMEDOUT)) + { continue; } - if (len < 0) { + if (len < 0) + { return err; } - if ( /* Is the sender wrong? */ - (memcmp(&sender.sipx_node, - &(conn->i.addr.sipx_node), 6) != 0) - || (sender.sipx_port != conn->i.addr.sipx_port) + if ( /* Did the sender send a positive acknowledge? */ - || ((len == sizeof(reply)) + ((len == sizeof(reply)) && (reply.type == NCP_POSITIVE_ACK)) + /* Did we get a bogus answer? */ || ((len < sizeof(reply)) || (reply.type != NCP_REPLY) - || ((request.type != NCP_ALLOC_SLOT_REQUEST) - && ((reply.sequence != request.sequence) - || (reply.conn_low != request.conn_low) - || (reply.conn_high != request.conn_high))))) { + || ((request.type != NCP_ALLOC_SLOT_REQUEST) + && ((reply.sequence != request.sequence) + || (reply.conn_low != request.conn_low) + || (reply.conn_high != request.conn_high))))) + { /* Then throw away the packet */ - ipx_recv(conn->ncp_sock, (char *) &reply, sizeof(reply), + x_recv(conn->ncp_sock, (char *) &reply, sizeof(reply), 0, 1, &err); goto re_select; } - ipx_recv(conn->ncp_sock, conn->packet, NCP_PACKET_SIZE, + len = x_recv(conn->ncp_sock, conn->packet, NCP_PACKET_SIZE, 0, 1, &err); conn->reply_size = len; return 0; @@ -355,14 +665,16 @@ static long do_ncp_call(struct ncp_conn *conn, int request_size) return ETIMEDOUT; } -static int ncp_mount_request(struct ncp_conn *conn, int function) +static int +ncp_mount_request(struct ncp_conn *conn, int function) { struct ncp_ioctl_request request; int result; assert_conn_locked(conn); - if (conn->has_subfunction != 0) { + if (conn->has_subfunction != 0) + { WSET_HL(conn->packet, 7, conn->current_size - sizeof(struct ncp_request_header) - 2); } @@ -370,20 +682,23 @@ static int ncp_mount_request(struct ncp_conn *conn, int function) request.size = conn->current_size; request.data = conn->packet; - if ((result = ioctl(conn->mount_fid, NCP_IOC_NCPREQUEST, &request)) < 0) { + if ((result = ioctl(conn->mount_fid, NCP_IOC_NCPREQUEST, &request)) < 0) + { return result; } conn->completion = BVAL(conn->packet, 6); conn->conn_status = BVAL(conn->packet, 7); conn->ncp_reply_size = result - sizeof(struct ncp_reply_header); - if ((conn->completion != 0) && (conn->verbose != 0)) { + if ((conn->completion != 0) && (conn->verbose != 0)) + { ncp_printf("ncp_request_error: %d\n", conn->completion); } return conn->completion == 0 ? 0 : NCPL_ET_REQUEST_ERROR; } -static long ncp_temp_request(struct ncp_conn *conn, int function) +static long +ncp_temp_request(struct ncp_conn *conn, int function) { long err; @@ -398,11 +713,13 @@ static long ncp_temp_request(struct ncp_conn *conn, int function) BSET(conn->packet, 4, 1); BSET(conn->packet, 6, function); - if (conn->has_subfunction != 0) { + if (conn->has_subfunction != 0) + { WSET_HL(conn->packet, 7, conn->current_size - sizeof(struct ncp_request_header) - 2); } - if ((err = do_ncp_call(conn, conn->current_size)) != 0) { + if ((err = do_ncp_call(conn, conn->current_size)) != 0) + { return err; } conn->completion = BVAL(conn->packet, 6); @@ -410,42 +727,71 @@ static long ncp_temp_request(struct ncp_conn *conn, int function) conn->ncp_reply_size = conn->reply_size - sizeof(struct ncp_reply_header); - if ((conn->completion != 0) && (conn->verbose != 0)) { + if ((conn->completion != 0) && (conn->verbose != 0)) + { ncp_printf("ncp_completion_code: %d\n", conn->completion); } return conn->completion == 0 ? 0 : NCPL_ET_REQUEST_ERROR; } -#ifdef PACKET_SIGNATURES -static long ncp_setup_security(struct ncp_conn *conn) +long +ncp_renegotiate_connparam(struct ncp_conn *conn, int buffsize, int in_options) { - __u8 security; - __u8 accepted_security; - __u16 socket, size; + int neg_buffsize; + int err; +#ifdef SIGNATURES + int options; + + /* TODO: Signatures active? I am not sure whether we can unnegotiate them */ + if (conn->sign_active) in_options |= 2; - conn->want_signatures = 0; - if (ncp_get_big_ncp_max_packet_size(conn, 576, 0, &size, &socket, - &accepted_security) != 0) { - return 0; + if ((err = ncp_negotiate_size_and_options(conn, buffsize, in_options, + &neg_buffsize, &options)) == 0) + { + if ((options & 2) != (in_options & 2)) + { + err = ncp_negotiate_size_and_options(conn, + buffsize, options & 2, &neg_buffsize, &options); + } } - if ((accepted_security & NCP_SEC_SIGNATURE_REQUESTED) == 0) { - return 0; + else +#endif + { +#ifdef SIGNATURES + options = 0; +#endif + err = ncp_negotiate_buffersize(conn, NCP_DEFAULT_BUFSIZE, + &neg_buffsize); + } + if (err) { + return err; } - security = NCP_SEC_SIGNATURE_REQUESTED; - if (ncp_get_big_ncp_max_packet_size(conn, 576, security, - &size, &socket, - &accepted_security) != 0) { - return 0; - } - if ((accepted_security & NCP_SEC_SIGNATURE_REQUESTED) != 0) { - conn->want_signatures = 1; + if ((neg_buffsize < 512) || (neg_buffsize > NCP_MAX_BUFSIZE)) + return -1; + conn->i.buffer_size = neg_buffsize; +#ifdef SIGNATURES + conn->sign_wanted = (options & 2) ? 1:0; + if (conn->is_connected == CONN_PERMANENT) { + int cursign; + + if (ioctl(conn->mount_fid, NCP_IOC_SIGN_WANTED, &cursign)) { + /* ncpfs does not support SIGN_WANTED -> current sign level = 0 */ + cursign = 0; + } + if (cursign) cursign = 1; + if (cursign != conn->sign_wanted) { + int newsign = conn->sign_wanted; + + err = ioctl(conn->mount_fid, NCP_IOC_SET_SIGN_WANTED, &newsign); + } } +#endif return 0; } -#endif -static long ncp_connect_addr(struct ncp_conn *conn, const struct sockaddr_ipx *target, - int wdog_needed) +static long +ncp_connect_ipx_addr(struct ncp_conn *conn, const struct sockaddr_ipx *target, + int wdog_needed) { struct sockaddr_ipx addr; int addrlen; @@ -456,10 +802,13 @@ static long ncp_connect_addr(struct ncp_conn *conn, const struct sockaddr_ipx *t conn->is_connected = NOT_CONNECTED; conn->verbose = 0; - if ((ncp_sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX)) == -1) { + if ((ncp_sock = socket(PF_IPX, SOCK_DGRAM, IPXPROTO_IPX)) == -1) + { return errno; } - if ((wdog_sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX)) == -1) { + if ((wdog_sock = socket(PF_IPX, SOCK_DGRAM, IPXPROTO_IPX)) == -1) + { + close(ncp_sock); return errno; } addr.sipx_family = AF_IPX; @@ -471,7 +820,8 @@ static long ncp_connect_addr(struct ncp_conn *conn, const struct sockaddr_ipx *t addrlen = sizeof(addr); if ((bind(ncp_sock, (struct sockaddr *) &addr, sizeof(addr)) == -1) - || (getsockname(ncp_sock, (struct sockaddr *) &addr, &addrlen) == -1)) { + || (getsockname(ncp_sock, (struct sockaddr *) &addr, &addrlen) == -1)) + { int saved_errno = errno; close(ncp_sock); close(wdog_sock); @@ -479,7 +829,8 @@ static long ncp_connect_addr(struct ncp_conn *conn, const struct sockaddr_ipx *t } addr.sipx_port = htons(ntohs(addr.sipx_port) + 1); - if (bind(wdog_sock, (struct sockaddr *) &addr, sizeof(addr)) == -1) { + if (bind(wdog_sock, (struct sockaddr *) &addr, sizeof(addr)) == -1) + { int saved_errno = errno; close(ncp_sock); close(wdog_sock); @@ -491,6 +842,18 @@ static long ncp_connect_addr(struct ncp_conn *conn, const struct sockaddr_ipx *t conn->sequence = 0; conn->i.addr = *target; + if (connect(ncp_sock, (const struct sockaddr*)target, sizeof(*target)) == -1) + { + int saved_errno = errno; + + if ((saved_errno != ENETUNREACH) || ipx_make_reachable(target) + || connect(ncp_sock, (const struct sockaddr*)target, sizeof(*target))) {; + close(ncp_sock); + close(wdog_sock); + return saved_errno; + } + } + WSET_LH(conn->packet, 0, NCP_ALLOC_SLOT_REQUEST); BSET(conn->packet, 2, conn->sequence); BSET(conn->packet, 3, 0xff); @@ -498,14 +861,24 @@ static long ncp_connect_addr(struct ncp_conn *conn, const struct sockaddr_ipx *t BSET(conn->packet, 5, 0xff); BSET(conn->packet, 6, 0); - if ((err = do_ncp_call(conn, sizeof(struct ncp_request_header))) != 0) { - close(ncp_sock); - close(wdog_sock); - return err; + if ((err = do_ncp_call(conn, sizeof(struct ncp_request_header))) != 0) + { + if ((err != ENETUNREACH) + || (ipx_make_reachable(target) != 0) + || ((err = + do_ncp_call(conn, + sizeof(struct ncp_request_header))) != 0)) + { + close(ncp_sock); + close(wdog_sock); + return err; + } } - if (wdog_needed != 0) { + if (wdog_needed != 0) + { install_wdog(conn); - } else { + } else + { conn->wdog_pid = 0; } @@ -514,115 +887,370 @@ static long ncp_connect_addr(struct ncp_conn *conn, const struct sockaddr_ipx *t BVAL(conn->packet, 3) + (BVAL(conn->packet, 5) << 8); conn->is_connected = CONN_TEMPORARY; - if ((ncp_negotiate_buffersize(conn, 1024, - &(conn->i.buffer_size)) != 0) - || (conn->i.buffer_size < 512) - || (conn->i.buffer_size > 1024)) { +#ifdef SIGNATURES + conn->sign_active = 0; + conn->sign_wanted = 0; + err = ncp_renegotiate_connparam(conn, NCP_DEFAULT_BUFSIZE, in_options); +#else + err = ncp_renegotiate_connparam(conn, NCP_DEFAULT_BUFSIZE, 0); +#endif + + if (err != 0) + { ncp_do_close(conn); return -1; } return 0; } -static long ncp_connect_any(struct ncp_conn *conn, int wdog_needed) +#ifdef CONFIG_NATIVE_IP +static long +ncp_connect_in_addr(struct ncp_conn *conn, const struct sockaddr_in *target, + int wdog_needed) { - struct sockaddr_ipx *addr; - long result; - const char *server = NULL; + struct sockaddr_in addr; + int addrlen; + + int ncp_sock; long err; - if ((addr = ncp_find_server(&server, NCP_BINDERY_FSERVER, &err)) == NULL) { + conn->is_connected = NOT_CONNECTED; + conn->verbose = 0; + + if ((ncp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) + { + return errno; + } + addr.sin_family = AF_INET; + addr.sin_port = htons(0x0); + addr.sin_addr.s_addr = INADDR_ANY; + + addrlen = sizeof(addr); + + if (bind(ncp_sock, (struct sockaddr *) &addr, sizeof(addr)) == -1) + { + int saved_errno = errno; + close(ncp_sock); + return saved_errno; + } + + conn->ncp_sock = ncp_sock; + conn->wdog_sock = -1; + + conn->sequence = 0; + conn->i.addr = *(const struct sockaddr_ipx*)target; + + if (connect(ncp_sock, (const struct sockaddr*)target, sizeof(*target)) == -1) + { + int saved_errno = errno; + close(ncp_sock); + return saved_errno; + } + + WSET_LH(conn->packet, 0, NCP_ALLOC_SLOT_REQUEST); + BSET(conn->packet, 2, conn->sequence); + BSET(conn->packet, 3, 0xff); + BSET(conn->packet, 4, 1); + BSET(conn->packet, 5, 0xff); + BSET(conn->packet, 6, 0); + + if ((err = do_ncp_call(conn, sizeof(struct ncp_request_header))) != 0) + { + /* ? request route ? */ + close(ncp_sock); return err; } - if ((result = ncp_connect_addr(conn, addr, wdog_needed)) != 0) { + + conn->wdog_pid = 0; + + conn->sequence = 0; + conn->i.connection = + BVAL(conn->packet, 3) + (BVAL(conn->packet, 5) << 8); + conn->is_connected = CONN_TEMPORARY; + +#ifdef SIGNATURES + conn->sign_active = 0; + conn->sign_wanted = 0; + err = ncp_renegotiate_connparam(conn, NCP_DEFAULT_BUFSIZE, in_options); +#else + err = ncp_renegotiate_connparam(conn, NCP_DEFAULT_BUFSIZE, 0); +#endif + + if (err != 0) + { + ncp_do_close(conn); + return -1; + } + return 0; +} +#endif /* CONFIG_NATIVE_IP */ + +static long +ncp_connect_addr(struct ncp_conn *conn, const struct sockaddr *target, + int wdog_needed) { + if (target->sa_family == AF_IPX) { + return ncp_connect_ipx_addr(conn, (const struct sockaddr_ipx*)target, wdog_needed); + } +#ifdef CONFIG_NATIVE_IP + if (target->sa_family == AF_INET) { + return ncp_connect_in_addr(conn, (const struct sockaddr_in*)target, wdog_needed); + } +#endif /* CONFIG_NATIVE_IP */ + return EAFNOSUPPORT; +} + +static long +ncp_connect_any(struct ncp_conn *conn, int wdog_needed) +{ +#ifndef __MAKE_SULIB__ + const char* server = NULL; +#else /* __MAKE_SULIB__ */ + char server[NCP_BINDERY_NAME_LEN]; +#endif /* __MAKE_SULIB__ */ + struct sockaddr_ipx addr; + long result; + +#ifndef __MAKE_SULIB__ + if ((result = ncp_find_server_ipx(&server, NCP_BINDERY_FSERVER, &addr)) != 0) +#else /* __MAKE_SULIB__ */ + if ((result = ipx_sap_find_nearest(IPX_SAP_FILE_SERVER, + &addr, server)) != 0) +#endif /* __MAKE_SULIB__ */ + { + return result; + } + if ((result = ncp_connect_ipx_addr(conn, &addr, wdog_needed)) != 0) + { return result; } strcpy(conn->server, server); return 0; } -struct sockaddr_ipx * - ncp_find_fileserver(const char *server_name, long *err) +static long +ncp_find_server_ipx(const char **server_name, int type, struct sockaddr_ipx* server_addr) { - return ncp_find_server(&server_name, NCP_BINDERY_FSERVER, err); -} - -struct sockaddr_ipx * - ncp_find_server(const char **server_name, int type, long *err) -{ - char command[256]; - char buf[128]; char server[NCP_BINDERY_NAME_LEN + 1]; - static struct sockaddr_ipx result; +#ifndef __MAKE_SULIB__ + char command[256]; + static char buf[128]; FILE *p; int res; char *n; +#else + long err; + static char nearest[NCP_BINDERY_NAME_LEN + 1]; + struct nw_property prop; + struct prop_net_address *n_addr = (struct prop_net_address *) ∝ + struct ncp_conn conn; + + initialize_NCPL_error_table(); +#endif /* __MAKE_SULIB__ */ memset(server, 0, sizeof(server)); - if (*server_name != NULL) { +#ifndef __MAKE_SULIB__ + if (*server_name != NULL) + { strncpy(server, *server_name, sizeof(server) - 1); str_upper(server); } sprintf(command, "nwsfind -t %d %s", type, server); p = popen(command, "r"); - if (p == NULL) { - *err = errno; - return NULL; + if (p == NULL) + { + return errno; } fgets(buf, sizeof(buf), p); - - if (buf[strlen(buf)] - 1 == '\n'); + res = strlen(buf); + if (res && (buf[res - 1] == '\n')) { - buf[strlen(buf)] = '\0'; + buf[res - 1] = '\0'; } - - if (((res = pclose(p)) != 0) || (ipx_sscanf_saddr(buf, &result) != 0)) { - *err = (*server_name != NULL) + if (((res = pclose(p)) != 0) || (ipx_sscanf_saddr(buf, server_addr) != 0)) + { + return (*server_name != NULL) ? NCPL_ET_HOST_UNKNOWN : NCPL_ET_NO_SERVER; - return NULL; } - if (*server_name == NULL) { - if ((n = strchr(buf, ' ')) == NULL) { - *err = NCPL_ET_HOST_UNKNOWN; - return NULL; + if (*server_name == NULL) + { + if ((n = strchr(buf, ' ')) == NULL) + { + return NCPL_ET_HOST_UNKNOWN; } *server_name = n; } - return &result; + return 0; +#else /* __MAKE_SULIB__ */ + memset(nearest, 0, sizeof(nearest)); + + if (*server_name != NULL) + { + if (strlen(*server_name) >= sizeof(server)) + { + return NCPL_ET_NAMETOOLONG; + } + strcpy(server, *server_name); + str_upper(server); + } + if ((err = ipx_sap_find_nearest(type, server_addr, nearest)) != 0) + { + return err; + } + /* We have to ask the nearest server for our wanted server */ + memzero(conn); + if ((err = ncp_connect_ipx_addr(&conn, server_addr, 0)) != 0) + { + return err; + } + if (*server_name == NULL) + { + *server_name = nearest; + ncp_do_close(&conn); + return 0; + } + /* The following optimization should have been done before + ncp_connect_addr. This would be convenient if there was a + simple way to find out whether there is a route to the + server. Parsing /proc/net/ipx_route is not too nice, so we + just connect to the server and immediately disconnect + again. This way we also find out if the server still has + free connection slots. */ + if (strcmp(server, nearest) == 0) + { + /* Our wanted server answered the SAP GNS request, so + use it */ + ncp_do_close(&conn); + return 0; + } + if (ncp_read_property_value(&conn, type, server, 1, + "NET_ADDRESS", &prop) != 0) + { + ncp_do_close(&conn); + return NCPL_ET_HOST_UNKNOWN; + } + if ((err = ncp_do_close(&conn)) != 0) + { + return err; + } + server_addr->sipx_family = AF_IPX; + server_addr->sipx_network = n_addr->network; + server_addr->sipx_port = n_addr->port; + ipx_assign_node(server_addr->sipx_node, n_addr->node); + + /* To make the final server reachable, we connect again. See + above. (When can we rely on all users running ipxd??? :-)) */ + memzero(conn); + if (((err = ncp_connect_ipx_addr(&conn, server_addr, 0)) != 0) + || ((err = ncp_do_close(&conn)) != 0)) + { + return err; + } + return 0; +#endif /* __MAKE_SULIB__ */ } -static long ncp_open_temporary(struct ncp_conn *conn, - const struct ncp_conn_spec *spec) +long +ncp_find_server(const char **server_name, int type, struct sockaddr* addr, size_t len) { + long err = NCPL_ET_HOST_UNKNOWN; + if (len >= sizeof(struct sockaddr_ipx)) { + err = ncp_find_server_ipx(server_name, type, (struct sockaddr_ipx*)addr); + if (!err) return 0; + } + return err; +} + +long +ncp_find_fileserver(const char *server_name, struct sockaddr* addr, size_t len) { - struct sockaddr_ipx *addr; - long err; + return ncp_find_server(&server_name, NCP_BINDERY_FSERVER, addr, len); +} - if (spec == NULL) { - return ncp_connect_any(conn, 1); - } - if ((addr = ncp_find_fileserver(spec->server, &err)) == NULL) { - return err; - } - if ((err = ncp_connect_addr(conn, addr, 1)) != 0) { - return err; - } - strcpy(conn->server, spec->server); +static int +ncp_login_conn(struct ncp_conn* conn, const char* object_name, int object_type, const char* password) { + int err; - if (strlen(spec->user) != 0) { - if (ncp_login_object(conn, spec->user, spec->login_type, - spec->password) != 0) { - ncp_do_close(conn); - return EACCES; +#ifdef NDS_SUPPORT + if (!nds_get_tree_name(conn, NULL, 0)) + { + err = nds_login_auth(conn, object_name, password); + if (!err) return 0; + if ((err == NCPL_ET_REQUEST_ERROR) && (conn->completion == NDS_GRACE_PERIOD)) { + fprintf(stderr, "Your password has expired\n"); + return 0; } - strcpy(conn->user, spec->user); + fprintf(stderr, "Unable to NDS log-in (error %d), trying bindery...\n", conn->completion); + } +#endif + if (ncp_login_object(conn, object_name, object_type, password) != 0) + { + return EACCES; } return 0; } +static long +ncp_open_temporary(struct ncp_conn *conn, + const char* server) +{ + struct sockaddr addr; + long err; + + if (server == NULL) + { + return ncp_connect_any(conn, 1); + } + if ((err = ncp_find_fileserver(server, &addr, sizeof(addr))) != 0) + { + return err; + } + if ((err = ncp_connect_addr(conn, &addr, 1)) != 0) + { + return err; + } + strcpy(conn->server, server); + + return 0; +} + +static long +ncp_open_temporary2(struct ncp_conn *conn, + const char* address, + const char* server) +{ +#ifdef CONFIG_NATIVE_IP + struct sockaddr_in addr; + long err; + struct hostent* h; + + if (!address) return EFAULT; + + h = gethostbyname(address); + if (!h) return NCPL_ET_HOST_UNKNOWN; + if (h->h_addrtype != AF_INET) return EAFNOSUPPORT; + if (h->h_length != 4) return EAFNOSUPPORT; + addr.sin_family = AF_INET; + addr.sin_port = htons(0x020C); + memcpy(&addr.sin_addr.s_addr, h->h_addr, 4); + + if ((err = ncp_connect_addr(conn, (struct sockaddr*)&addr, 1)) != 0) + { + return err; + } + strcpy(conn->server, server); + + return 0; +#else /* CONFIG_NATIVE_IP */ + (void)conn; + (void)address; + (void)server; + return EAFNOSUPPORT; +#endif /* CONFIG_NATIVE_IP */ +} + char * - ncp_find_permanent(const struct ncp_conn_spec *spec) +ncp_find_permanent(const struct ncp_conn_spec *spec) { FILE *mtab; struct ncp_conn_ent *conn_ent; @@ -632,28 +1260,34 @@ char * initialize_NCPL_error_table(); - if ((mtab = fopen(MOUNTED, "r")) == NULL) { + if ((mtab = fopen(MOUNTED, "r")) == NULL) + { return NULL; } - while ((conn_ent = ncp_get_conn_ent(mtab)) != NULL) { - if (spec != NULL) { + while ((conn_ent = ncp_get_conn_ent(mtab)) != NULL) + { + if (spec != NULL) + { if ((conn_ent->uid != spec->uid) || ((strlen(spec->server) != 0) && (strcasecmp(conn_ent->server, spec->server) != 0)) || ((strlen(spec->user) != 0) && (strcasecmp(conn_ent->user, - spec->user) != 0))) { + spec->user) != 0))) + { continue; } } mount_fid = open(conn_ent->mount_point, O_RDONLY, 0); - if (mount_fid < 0) { + if (mount_fid < 0) + { continue; } i.version = NCP_GET_FS_INFO_VERSION; - if (ioctl(mount_fid, NCP_IOC_GET_FS_INFO, &i) < 0) { + if (ioctl(mount_fid, NCP_IOC_GET_FS_INFO, &i) < 0) + { close(mount_fid); continue; } @@ -667,106 +1301,132 @@ char * return result; } -static int ncp_open_permanent(struct ncp_conn *conn, - const struct ncp_conn_spec *spec) +#ifdef SIGNATURES +static void +ncp_sign_init_perm(struct ncp_conn *conn) +{ + if (ioctl(conn->mount_fid, NCP_IOC_SIGN_WANTED, + &conn->sign_wanted) != 0) + conn->sign_wanted = 0; + conn->sign_active = 0; +} +#endif + +static int +ncp_open_permanent(const struct ncp_conn_spec *spec, struct ncp_conn** conn) { char *mount_point; + int err; - if (conn->is_connected != NOT_CONNECTED) { - errno = EBUSY; + if ((mount_point = ncp_find_permanent(spec)) == NULL) + { return -1; } - if ((mount_point = ncp_find_permanent(spec)) == NULL) { - return -1; + err = ncp_open_mount(mount_point, conn); + if (!err) { + if (spec != NULL) { + strncpy((*conn)->server, spec->server, sizeof((*conn)->server)); + strncpy((*conn)->user, spec->user, sizeof((*conn)->user)); + } else { + memset((*conn)->server, '\0', sizeof((*conn)->server)); + memset((*conn)->user, '\0', sizeof((*conn)->user)); + } } - if (strlen(mount_point) >= sizeof(conn->mount_point)) { - errno = ENAMETOOLONG; - return -1; - } - /* The rest has already been done in ncp_find_permanent, so we - * do not check errors anymore */ - conn->mount_fid = open(mount_point, O_RDONLY, 0); - conn->i.version = NCP_GET_FS_INFO_VERSION; - ioctl(conn->mount_fid, NCP_IOC_GET_FS_INFO, &(conn->i)); - if (spec != NULL) { - strncpy(conn->server, spec->server, sizeof(conn->server)); - strncpy(conn->user, spec->user, sizeof(conn->user)); - } else { - memset(conn->server, '\0', sizeof(conn->server)); - memset(conn->user, '\0', sizeof(conn->user)); - } - strcpy(conn->mount_point, mount_point); - conn->is_connected = CONN_PERMANENT; - return 0; + return err; } -struct ncp_conn * - ncp_open(const struct ncp_conn_spec *spec, long *err) +static struct ncp_conn * +ncp_open_2(const struct ncp_conn_spec *spec, long *err, const char* address) { struct ncp_conn *result; initialize_NCPL_error_table(); + if (ncp_open_permanent(spec, &result) == 0) { + return result; + } + result = malloc(sizeof(struct ncp_conn)); - if (result == NULL) { + if (result == NULL) + { *err = ENOMEM; return NULL; } memzero(*result); - if (ncp_open_permanent(result, spec) == 0) { - return result; + if (spec) { + *err = ncp_open_temporary2(result, address, spec->server); + if (*err) *err = ncp_open_temporary(result, spec->server); + } else { + *err = ncp_connect_any(result, 1); } - if ((*err = ncp_open_temporary(result, spec)) != 0) { + if (*err) { free(result); return NULL; } + if (spec && (strlen(spec->user) != 0)) { + *err = ncp_login_conn(result, spec->user, spec->login_type, spec->password); + if (*err) { + ncp_close(result); + return NULL; + } + strcpy(result->user, spec->user); + } return result; } - struct ncp_conn * - ncp_open_mount(const char *mount_point, long *err) +ncp_open(const struct ncp_conn_spec *spec, long *err) { + return ncp_open_2(spec, err, NULL); +} + +int +ncp_open_mount(const char *mount_point, struct ncp_conn** conn) { struct ncp_conn *result; initialize_NCPL_error_table(); + *conn = NULL; + if (strlen(mount_point) >= sizeof(result->mount_point)) { - *err = ENAMETOOLONG; - return NULL; + return ENAMETOOLONG; } result = malloc(sizeof(struct ncp_conn)); if (result == NULL) { - *err = ENOMEM; - return NULL; + return ENOMEM; } memzero(*result); result->is_connected = NOT_CONNECTED; result->mount_fid = open(mount_point, O_RDONLY, 0); - if (result->mount_fid < 0) { + if (result->mount_fid < 0) + { free(result); - *err = ENODEV; - return NULL; + return ENODEV; } strcpy(result->mount_point, mount_point); result->is_connected = CONN_PERMANENT; result->i.version = NCP_GET_FS_INFO_VERSION; - if (ioctl(result->mount_fid, NCP_IOC_GET_FS_INFO, &(result->i)) != 0) { + if (ioctl(result->mount_fid, NCP_IOC_GET_FS_INFO, &(result->i)) != 0) + { free(result); - *err = NCPL_ET_NO_NCPFS_FILE; - return NULL; + return NCPL_ET_NO_NCPFS_FILE; } - return result; +#ifdef SIGNATURES + ncp_sign_init_perm(result); +#endif + *conn = result; + return 0; } -static long ncp_user_disconnect(struct ncp_conn *conn) +static long +ncp_user_disconnect(struct ncp_conn *conn) { long result; @@ -779,24 +1439,30 @@ static long ncp_user_disconnect(struct ncp_conn *conn) BSET(conn->packet, 5, (conn->i.connection) >> 8); BSET(conn->packet, 6, 0); - if ((result = do_ncp_call(conn, sizeof(struct ncp_request_header))) != 0) { + if ((result = do_ncp_call(conn, sizeof(struct ncp_request_header))) != 0) + { return result; } close(conn->ncp_sock); - close(conn->wdog_sock); + if (conn->wdog_sock != -1) { + close(conn->wdog_sock); + } - if (conn->wdog_pid != 0) { + if (conn->wdog_pid != 0) + { kill(conn->wdog_pid, SIGTERM); wait(NULL); } return 0; } -static long ncp_do_close(struct ncp_conn *conn) +static long +ncp_do_close(struct ncp_conn *conn) { long result = -1; - switch (conn->is_connected) { + switch (conn->is_connected) + { case CONN_PERMANENT: result = close(conn->mount_fid); break; @@ -814,21 +1480,36 @@ static long ncp_do_close(struct ncp_conn *conn) return result; } -long ncp_close(struct ncp_conn *conn) +long +ncp_close(struct ncp_conn *conn) { long result; - if (conn == NULL) { + if (conn == NULL) + { return 0; } - if ((result = ncp_do_close(conn)) != 0) { + if ((result = ncp_do_close(conn)) != 0) + { return result; } free(conn); return 0; } +int +ncp_get_mount_uid(int fid, uid_t* uid) +{ + __kernel_uid_t k_uid; + int err; + + err = ioctl(fid, NCP_IOC_GETMOUNTUID, &k_uid); + if (err) return err; + *uid = k_uid; + return 0; +} + struct ncp_conn_ent * - ncp_get_conn_ent(FILE * filep) +ncp_get_conn_ent(FILE * filep) { static struct ncp_conn_ent entry; char server[2 * NCP_BINDERY_NAME_LEN]; @@ -839,25 +1520,31 @@ struct ncp_conn_ent * memzero(server); memzero(entry); - while ((mnt_ent = getmntent(filep)) != NULL) { - if (strcmp(mnt_ent->mnt_type, "ncpfs") != 0) { + while ((mnt_ent = getmntent(filep)) != NULL) + { + if (strcmp(mnt_ent->mnt_type, "ncpfs") != 0) + { continue; } - if (strlen(mnt_ent->mnt_fsname) >= sizeof(server)) { + if (strlen(mnt_ent->mnt_fsname) >= sizeof(server)) + { continue; } strcpy(server, mnt_ent->mnt_fsname); user = strchr(server, '/'); - if (user != NULL) { + if (user != NULL) + { *user = '\0'; user += 1; - if (strlen(user) >= sizeof(entry.user)) { + if (strlen(user) >= sizeof(entry.user)) + { continue; } strcpy(entry.user, user); } if ((strlen(server) >= sizeof(entry.server)) - || (strlen(mnt_ent->mnt_dir) >= sizeof(entry.mount_point))) { + || (strlen(mnt_ent->mnt_dir) >= sizeof(entry.mount_point))) + { continue; } strcpy(entry.server, server); @@ -865,10 +1552,12 @@ struct ncp_conn_ent * fid = open(entry.mount_point, O_RDONLY, 0); - if (fid == -1) { + if (fid == -1) + { continue; } - if (ioctl(fid, NCP_IOC_GETMOUNTUID, &entry.uid) != 0) { + if (ncp_get_mount_uid(fid, &entry.uid) != 0) + { close(fid); continue; } @@ -880,7 +1569,7 @@ struct ncp_conn_ent * } static struct ncp_conn_spec * - ncp_get_nwc_ent(FILE * nwc) +ncp_get_nwc_ent(FILE * nwc) { static struct ncp_conn_spec spec; char line[512]; @@ -891,41 +1580,51 @@ static struct ncp_conn_spec * memzero(spec); spec.uid = getuid(); - while (fgets(line, sizeof(line), nwc) != NULL) { + while (fgets(line, sizeof(line), nwc) != NULL) + { if ((line[0] == '\n') - || (line[0] == '#')) { + || (line[0] == '#')) + { continue; } line_len = strlen(line); - if (line[line_len - 1] == '\n') { + if (line[line_len - 1] == '\n') + { line[line_len - 1] = '\0'; } user = strchr(line, '/'); password = strchr(user != NULL ? user : line, ' '); - if (password != NULL) { + if (password != NULL) + { *password = '\0'; password += 1; } - if (user != NULL) { + if (user != NULL) + { *user = '\0'; user += 1; - if (strlen(user) >= sizeof(spec.user)) { + if (strlen(user) >= sizeof(spec.user)) + { continue; } strcpy(spec.user, user); } - if (strlen(line) >= sizeof(spec.server)) { + if (strlen(line) >= sizeof(spec.server)) + { continue; } strcpy(spec.server, line); - if (password != NULL) { - while (*password == ' ') { + if (password != NULL) + { + while (*password == ' ') + { password += 1; } - if (strlen(password) >= sizeof(spec.password)) { + if (strlen(password) >= sizeof(spec.password)) + { continue; } strcpy(spec.password, password); @@ -936,27 +1635,32 @@ static struct ncp_conn_spec * } FILE * - ncp_fopen_nwc(const char *user, const char *mode, long *err) +ncp_fopen_nwc(const char *user, const char *mode, long *err) { char path[MAXPATHLEN]; char *home = NULL; struct stat st; - if (mode == NULL) { + if (mode == NULL) + { mode = "r"; } - if (user == NULL) { + if (user == NULL) + { home = getenv("HOME"); - } else { + } else + { struct passwd *pwd; - if ((pwd = getpwnam(user)) != NULL) { + if ((pwd = getpwnam(user)) != NULL) + { home = pwd->pw_dir; } } if ((home == NULL) - || (strlen(home) + sizeof(NWCLIENT) + 2 > sizeof(path))) { + || (strlen(home) + sizeof(NWCLIENT) + 2 > sizeof(path))) + { *err = ENAMETOOLONG; return NULL; } @@ -964,26 +1668,25 @@ FILE * strcat(path, "/"); strcat(path, NWCLIENT); - if (stat(path, &st) != 0) { + if (stat(path, &st) != 0) + { *err = errno; return NULL; } - if ((st.st_mode & (S_IRWXO | S_IRWXG)) != 0) { + if ((st.st_mode & (S_IRWXO | S_IRWXG)) != 0) + { *err = NCPL_ET_INVALID_MODE; return NULL; } return fopen(path, mode); } - 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) +ncp_find_conn_spec2(const char *server, const char *user, const char *password, + int login_necessary, uid_t uid, int allow_multiple_conns, long *err) { static struct ncp_conn_spec spec; - struct ncp_conn conn; - FILE *nwc; struct ncp_conn_spec *nwc_ent; @@ -993,21 +1696,26 @@ struct ncp_conn_spec * memzero(spec); spec.uid = getuid(); - if (server != NULL) { - if (strlen(server) >= sizeof(spec.server)) { + if (server != NULL) + { + if (strlen(server) >= sizeof(spec.server)) + { *err = NCPL_ET_NAMETOOLONG; return NULL; } strcpy(spec.server, server); - } else { - if ((nwc = ncp_fopen_nwc(NULL, NULL, err)) == NULL) { + } else + { + if ((nwc = ncp_fopen_nwc(NULL, NULL, err)) == NULL) + { *err = NCPL_ET_NO_SERVER; return NULL; } nwc_ent = ncp_get_nwc_ent(nwc); fclose(nwc); - if (nwc_ent == NULL) { + if (nwc_ent == NULL) + { *err = NCPL_ET_NO_SPEC; return NULL; } @@ -1017,13 +1725,16 @@ struct ncp_conn_spec * str_upper(spec.server); - if (login_necessary == 0) { + if (login_necessary == 0) + { memset(spec.user, 0, sizeof(spec.user)); memset(spec.password, 0, sizeof(spec.password)); return &spec; } - if (user != NULL) { - if (strlen(user) >= sizeof(spec.user)) { + if (user != NULL) + { + if (strlen(user) >= sizeof(spec.user)) + { *err = NCPL_ET_NAMETOOLONG; return NULL; } @@ -1032,24 +1743,35 @@ struct ncp_conn_spec * str_upper(spec.user); spec.login_type = NCP_BINDERY_USER; - if (ncp_open_permanent(&conn, &spec) == 0) { - ncp_do_close(&conn); - return &spec; + if (!allow_multiple_conns) { + struct ncp_conn* conn; + + if (ncp_open_permanent(&spec, &conn) == 0) + { + ncp_close(conn); + return &spec; + } } - if (password != NULL) { - if (strlen(password) >= sizeof(spec.password)) { + if (password != NULL) + { + if (strlen(password) >= sizeof(spec.password)) + { *err = NCPL_ET_NAMETOOLONG; return NULL; } strcpy(spec.password, password); - } else { - if ((nwc = ncp_fopen_nwc(NULL, NULL, err)) != NULL) { - while ((nwc_ent = ncp_get_nwc_ent(nwc)) != NULL) { + } else + { + if ((nwc = ncp_fopen_nwc(NULL, NULL, err)) != NULL) + { + while ((nwc_ent = ncp_get_nwc_ent(nwc)) != NULL) + { if ((strcasecmp(spec.server, nwc_ent->server) != 0) || ((*spec.user != '\0') && (strcasecmp(spec.user, - nwc_ent->user) != 0))) { + nwc_ent->user) != 0))) + { continue; } strcpy(spec.user, nwc_ent->user); @@ -1060,25 +1782,31 @@ struct ncp_conn_spec * } } - if (strlen(spec.user) == 0) { + if (strlen(spec.user) == 0) + { *err = NCPL_ET_NO_USER; return NULL; } - if ((strlen(spec.password) == 0) && (password == NULL)) { + if ((strlen(spec.password) == 0) && (password == NULL)) + { char *password; - if (!(isatty(0) && isatty(1))) { + if (!(isatty(0) && isatty(1))) + { return NULL; } printf("Logging into %s as %s\n", spec.server, spec.user); password = getpass("Password: "); - if (strlen(password) > sizeof(spec.password)) { + if (strlen(password) > sizeof(spec.password)) + { return NULL; } strcpy(spec.password, password); - } else { - if (strcmp(spec.password, NWC_NOPASSWORD) == 0) { + } else + { + if (strcmp(spec.password, NWC_NOPASSWORD) == 0) + { *spec.password = '\0'; } } @@ -1089,21 +1817,32 @@ struct ncp_conn_spec * return &spec; } +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) { + return ncp_find_conn_spec2(server, user, password, login_necessary, + uid, 0, err); +} + struct ncp_conn * - ncp_initialize_as(int *argc, char **argv, - int login_necessary, int login_type, long *err) +ncp_initialize_as(int *argc, char **argv, + int login_necessary, int login_type, long *err) { - char *server = NULL; - char *user = NULL; - char *password = NULL; + const char *server = NULL; + const char *user = NULL; + const char *password = NULL; + const char *address = NULL; struct ncp_conn_spec *spec; int i = 1; - int get_argument(int arg_no, char **target) { + int get_argument(int arg_no, const char **target) + { int count = 1; - if (target != NULL) { - if (arg_no + 1 >= *argc) { + if (target != NULL) + { + if (arg_no + 1 >= *argc) + { /* No argument to switch */ errno = EINVAL; return -1; @@ -1113,7 +1852,8 @@ struct ncp_conn * } /* Delete the consumed switch from the argument list and decrement the argument count */ - while (count + arg_no < *argc) { + while (count + arg_no < *argc) + { argv[arg_no] = argv[arg_no + count]; arg_no += 1; } @@ -1125,34 +1865,58 @@ struct ncp_conn * *err = EINVAL; - while (i < *argc) { + while (i < *argc) + { if ((argv[i][0] != '-') - || (strlen(argv[i]) != 2)) { + || (strlen(argv[i]) != 2)) + { i += 1; continue; } - switch (argv[i][1]) { + switch (argv[i][1]) + { case 'S': - if (get_argument(i, &server) != 0) { + if (get_argument(i, &server) != 0) + { return NULL; } continue; case 'U': - if (get_argument(i, &user) != 0) { + if (get_argument(i, &user) != 0) + { return NULL; } continue; case 'P': - if (get_argument(i, &password) != 0) { + if (get_argument(i, &password) != 0) + { return NULL; } continue; case 'n': - if (get_argument(i, 0) != 0) { + if (get_argument(i, NULL) != 0) + { return NULL; } password = NWC_NOPASSWORD; continue; +#ifdef NDS_SUPPORT + case 'b': + if (get_argument(i, NULL) != 0) + { + return NULL; + } + bindery_only = 1; + continue; +#endif +#ifdef CONFIG_NATIVE_IP + case 'A': + if (get_argument(i, &address) != 0) + { + return NULL; + } + continue; +#endif /* CONFIG_NATIVE_IP */ } i += 1; } @@ -1160,32 +1924,38 @@ struct ncp_conn * spec = ncp_find_conn_spec(server, user, password, login_necessary, getuid(), err); - if (spec == NULL) { - if (login_necessary != 0) { + if (spec == NULL) + { + if (login_necessary != 0) + { return NULL; - } else { + } else + { return ncp_open(NULL, err); } } spec->login_type = login_type; - if (login_necessary == 0) { + if (login_necessary == 0) + { spec->user[0] = '\0'; } - return ncp_open(spec, err); + return ncp_open_2(spec, err, address); } struct ncp_conn * - ncp_initialize(int *argc, char **argv, - int login_necessary, long *err) +ncp_initialize(int *argc, char **argv, + int login_necessary, long *err) { return ncp_initialize_as(argc, argv, login_necessary, NCP_BINDERY_USER, err); } -static long ncp_request(struct ncp_conn *conn, int function) +static long +ncp_request(struct ncp_conn *conn, int function) { - switch (conn->is_connected) { + switch (conn->is_connected) + { case CONN_PERMANENT: return ncp_mount_request(conn, function); case CONN_TEMPORARY: @@ -1201,12 +1971,15 @@ static long ncp_request(struct ncp_conn *conn, int function) /* */ /****************************************************************************/ -static inline int min(int a, int b) +static inline int +min(int a, int b) { return (a < b) ? a : b; } -struct nw_time_buffer { +#ifndef __MAKE_SULIB__ +struct nw_time_buffer +{ __u8 year __attribute__((packed)); __u8 month __attribute__((packed)); __u8 day __attribute__((packed)); @@ -1217,7 +1990,7 @@ struct nw_time_buffer { }; static time_t - nw_to_ctime(struct nw_time_buffer *source) +nw_to_ctime(struct nw_time_buffer *source) { struct tm u_time; @@ -1229,20 +2002,25 @@ static time_t u_time.tm_mon = source->month - 1; u_time.tm_year = source->year; - if (u_time.tm_year < 80) { + if (u_time.tm_year < 80) + { u_time.tm_year += 100; } return mktime(&u_time); } +#endif /* not __MAKE_SULIB__ */ -static void assert_conn_locked(struct ncp_conn *conn) +static void +assert_conn_locked(struct ncp_conn *conn) { - if (conn->lock == 0) { + if (conn->lock == 0) + { ncp_printf("ncpfs: conn not locked!\n"); } } -static void ncp_add_byte(struct ncp_conn *conn, byte x) +static void +ncp_add_byte(struct ncp_conn *conn, byte x) { assert_conn_locked(conn); BSET(conn->packet, conn->current_size, x); @@ -1250,7 +2028,8 @@ static void ncp_add_byte(struct ncp_conn *conn, byte x) return; } -static void ncp_add_word_lh(struct ncp_conn *conn, word x) +static void +ncp_add_word_lh(struct ncp_conn *conn, word x) { assert_conn_locked(conn); WSET_LH(conn->packet, conn->current_size, x); @@ -1258,7 +2037,8 @@ static void ncp_add_word_lh(struct ncp_conn *conn, word x) return; } -static void ncp_add_dword_lh(struct ncp_conn *conn, dword x) +static void +ncp_add_dword_lh(struct ncp_conn *conn, dword x) { assert_conn_locked(conn); DSET_LH(conn->packet, conn->current_size, x); @@ -1266,7 +2046,8 @@ static void ncp_add_dword_lh(struct ncp_conn *conn, dword x) return; } -static void ncp_add_word_hl(struct ncp_conn *conn, word x) +static void +ncp_add_word_hl(struct ncp_conn *conn, word x) { assert_conn_locked(conn); WSET_HL(conn->packet, conn->current_size, x); @@ -1274,15 +2055,19 @@ static void ncp_add_word_hl(struct ncp_conn *conn, word x) return; } -static void ncp_add_dword_hl(struct ncp_conn *conn, dword x) +#ifndef __MAKE_SULIB__ +static void +ncp_add_dword_hl(struct ncp_conn *conn, dword x) { assert_conn_locked(conn); DSET_HL(conn->packet, conn->current_size, x); conn->current_size += 4; return; } +#endif /* __MAKE_SULIB__ */ -static void ncp_add_mem(struct ncp_conn *conn, const void *source, int size) +static void +ncp_add_mem(struct ncp_conn *conn, const void *source, int size) { assert_conn_locked(conn); memcpy(&(conn->packet[conn->current_size]), source, size); @@ -1290,11 +2075,13 @@ static void ncp_add_mem(struct ncp_conn *conn, const void *source, int size) return; } -static void ncp_add_pstring(struct ncp_conn *conn, const char *s) +static void +ncp_add_pstring(struct ncp_conn *conn, const char *s) { int len = strlen(s); assert_conn_locked(conn); - if (len > 255) { + if (len > 255) + { ncp_printf("ncpfs: string too long: %s\n", s); len = 255; } @@ -1303,7 +2090,8 @@ static void ncp_add_pstring(struct ncp_conn *conn, const char *s) return; } -static void ncp_init_request(struct ncp_conn *conn) +static void +ncp_init_request(struct ncp_conn *conn) { ncp_lock_conn(conn); @@ -1311,7 +2099,8 @@ static void ncp_init_request(struct ncp_conn *conn) conn->has_subfunction = 0; } -static void ncp_init_request_s(struct ncp_conn *conn, int subfunction) +static void +ncp_init_request_s(struct ncp_conn *conn, int subfunction) { ncp_init_request(conn); ncp_add_word_lh(conn, 0); /* preliminary size */ @@ -1322,37 +2111,39 @@ static void ncp_init_request_s(struct ncp_conn *conn, int subfunction) } static char * - ncp_reply_data(struct ncp_conn *conn, int offset) +ncp_reply_data(struct ncp_conn *conn, int offset) { return &(conn->packet[sizeof(struct ncp_reply_header) + offset]); } static byte - ncp_reply_byte(struct ncp_conn *conn, int offset) +ncp_reply_byte(struct ncp_conn *conn, int offset) { return *(byte *) (ncp_reply_data(conn, offset)); } static word - ncp_reply_word_hl(struct ncp_conn *conn, int offset) +ncp_reply_word_hl(struct ncp_conn *conn, int offset) { return WVAL_HL(ncp_reply_data(conn, offset), 0); } +#ifndef __MAKE_SULIB__ static word - ncp_reply_word_lh(struct ncp_conn *conn, int offset) +ncp_reply_word_lh(struct ncp_conn *conn, int offset) { return WVAL_LH(ncp_reply_data(conn, offset), 0); } +#endif /* __MAKE_SULIB__ */ static dword - ncp_reply_dword_hl(struct ncp_conn *conn, int offset) +ncp_reply_dword_hl(struct ncp_conn *conn, int offset) { return DVAL_HL(ncp_reply_data(conn, offset), 0); } static dword - ncp_reply_dword_lh(struct ncp_conn *conn, int offset) +ncp_reply_dword_lh(struct ncp_conn *conn, int offset) { return DVAL_LH(ncp_reply_data(conn, offset), 0); } @@ -1360,15 +2151,17 @@ static dword /* Here the ncp calls begin */ -static long ncp_negotiate_buffersize(struct ncp_conn *conn, - int size, int *target) +static long +ncp_negotiate_buffersize(struct ncp_conn *conn, + int size, int *target) { long result; ncp_init_request(conn); ncp_add_word_hl(conn, size); - if ((result = ncp_request(conn, 33)) != 0) { + if ((result = ncp_request(conn, 33)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -1378,15 +2171,45 @@ static long ncp_negotiate_buffersize(struct ncp_conn *conn, return 0; } +#ifdef SIGNATURES +static long + ncp_negotiate_size_and_options(struct ncp_conn *conn, + int size, int options, + int *ret_size, int *ret_options) +{ + long result; -long ncp_get_file_server_description_strings(struct ncp_conn *conn, - char target[512]) + ncp_init_request(conn); + ncp_add_word_hl(conn, size); + ncp_add_byte(conn, options); + + if ((result = ncp_request(conn, 0x61)) != 0) + { + ncp_unlock_conn(conn); + return result; + } + if (ncp_reply_word_hl(conn, 0) == 0) + *ret_size = size; + else + *ret_size = min(ncp_reply_word_hl(conn, 0), size); + *ret_options = ncp_reply_byte(conn, 4); + + ncp_unlock_conn(conn); + return 0; +} +#endif + +#ifndef __MAKE_SULIB__ +long +ncp_get_file_server_description_strings(struct ncp_conn *conn, + char target[512]) { long result; ncp_init_request_s(conn, 201); - if ((result = ncp_request(conn, 23)) != 0) { + if ((result = ncp_request(conn, 23)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -1395,13 +2218,15 @@ long ncp_get_file_server_description_strings(struct ncp_conn *conn, return 0; } -long ncp_get_file_server_time(struct ncp_conn *conn, time_t * target) +long +ncp_get_file_server_time(struct ncp_conn *conn, time_t * target) { long result; ncp_init_request(conn); - if ((result = ncp_request(conn, 20)) != 0) { + if ((result = ncp_request(conn, 20)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -1410,14 +2235,16 @@ long ncp_get_file_server_time(struct ncp_conn *conn, time_t * target) return 0; } -long ncp_set_file_server_time(struct ncp_conn *conn, time_t * source) +long +ncp_set_file_server_time(struct ncp_conn *conn, time_t * source) { long result; int year; struct tm *utime = localtime(source); year = utime->tm_year; - if (year > 99) { + if (year > 99) + { year -= 100; } ncp_init_request_s(conn, 202); @@ -1433,12 +2260,14 @@ long ncp_set_file_server_time(struct ncp_conn *conn, time_t * source) return result; } -long ncp_get_file_server_information(struct ncp_conn *conn, - struct ncp_file_server_info *target) +long +ncp_get_file_server_information(struct ncp_conn *conn, + struct ncp_file_server_info *target) { long result; ncp_init_request_s(conn, 17); - if ((result = ncp_request(conn, 23)) != 0) { + if ((result = ncp_request(conn, 23)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -1455,9 +2284,10 @@ long ncp_get_file_server_information(struct ncp_conn *conn, return 0; } -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_connlist(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + int *returned_no, __u8 conn_numbers[256]) { long result; @@ -1465,7 +2295,8 @@ long ncp_get_connlist(struct ncp_conn *conn, ncp_add_word_hl(conn, object_type); ncp_add_pstring(conn, object_name); - if ((result = ncp_request(conn, 23)) != 0) { + if ((result = ncp_request(conn, 23)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -1475,16 +2306,18 @@ long ncp_get_connlist(struct ncp_conn *conn, return 0; } -long ncp_get_stations_logged_info(struct ncp_conn *conn, - __u32 connection, - struct ncp_bindery_object *target, - time_t * login_time) +long +ncp_get_stations_logged_info(struct ncp_conn *conn, + __u32 connection, + struct ncp_bindery_object *target, + time_t * login_time) { long result; ncp_init_request_s(conn, 28); ncp_add_dword_lh(conn, connection); - if ((result = ncp_request(conn, 23)) != 0) { + if ((result = ncp_request(conn, 23)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -1499,16 +2332,18 @@ long ncp_get_stations_logged_info(struct ncp_conn *conn, return 0; } -long ncp_get_internet_address(struct ncp_conn *conn, - __u32 connection, - struct sockaddr_ipx *target, - __u8 * conn_type) +long +ncp_get_internet_address(struct ncp_conn *conn, + __u32 connection, + struct sockaddr_ipx *target, + __u8 * conn_type) { long result; ncp_init_request_s(conn, 26); ncp_add_dword_lh(conn, connection); - if ((result = ncp_request(conn, 23)) != 0) { + if ((result = ncp_request(conn, 23)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -1521,18 +2356,20 @@ long ncp_get_internet_address(struct ncp_conn *conn, return 0; } -long ncp_send_broadcast(struct ncp_conn *conn, - __u8 no_conn, const __u8 * connections, - const char *message) +long +ncp_send_broadcast(struct ncp_conn *conn, + __u8 no_conn, const __u8 * connections, + const char *message) { long result; - if (strlen(message) > 58) { + if (strlen(message) > 58) + { return NCPL_ET_MSG_TOO_LONG; } ncp_init_request_s(conn, 0); ncp_add_byte(conn, no_conn); - ncp_add_mem(conn, (char *) (connections), no_conn); + ncp_add_mem(conn, connections, no_conn); ncp_add_pstring(conn, message); result = ncp_request(conn, 21); @@ -1540,21 +2377,53 @@ long ncp_send_broadcast(struct ncp_conn *conn, return result; } +long +ncp_send_broadcast2(struct ncp_conn *conn, + unsigned int conns, const unsigned int* connlist, + const char* message) +{ + int i; + long result; + + i = strlen(message); + if (i > 255) + { + return NCPL_ET_MSG_TOO_LONG; + } + if (conns > 350) /* max pkt len ~ 1KB */ + /* maybe do it by handshaked length ? */ + return NCPL_ET_MSG_TOO_LONG; + + ncp_init_request_s(conn, 0x0A); + ncp_add_word_lh(conn, conns); + for (;conns; --conns) + ncp_add_dword_lh(conn, *connlist++); + ncp_add_byte(conn, i); + ncp_add_mem(conn, message, i); + result = ncp_request(conn, 0x15); + ncp_unlock_conn(conn); + return result; +} +#endif /* not __MAKE_SULIB__ */ + /* * target is a 8-byte buffer */ -long ncp_get_encryption_key(struct ncp_conn *conn, - char *target) +long +ncp_get_encryption_key(struct ncp_conn *conn, + char *target) { long result; ncp_init_request_s(conn, 23); - if ((result = ncp_request(conn, 23)) != 0) { + if ((result = ncp_request(conn, 23)) != 0) + { ncp_unlock_conn(conn); return result; } - if (conn->ncp_reply_size < 8) { + if (conn->ncp_reply_size < 8) + { ncp_printf("ncp_reply_size %d < 8\n", conn->ncp_reply_size); ncp_unlock_conn(conn); @@ -1565,21 +2434,24 @@ long ncp_get_encryption_key(struct ncp_conn *conn, return 0; } -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_id(struct ncp_conn *conn, + __u16 object_type, + const char *object_name, + struct ncp_bindery_object *target) { long result; ncp_init_request_s(conn, 53); ncp_add_word_hl(conn, object_type); ncp_add_pstring(conn, object_name); - if ((result = ncp_request(conn, 23)) != 0) { + if ((result = ncp_request(conn, 23)) != 0) + { ncp_unlock_conn(conn); return result; } - if (conn->ncp_reply_size < 54) { + if (conn->ncp_reply_size < 54) + { ncp_printf("ncp_reply_size %d < 54\n", conn->ncp_reply_size); ncp_unlock_conn(conn); @@ -1592,15 +2464,18 @@ long ncp_get_bindery_object_id(struct ncp_conn *conn, return 0; } -long ncp_get_bindery_object_name(struct ncp_conn *conn, - __u32 object_id, - struct ncp_bindery_object *target) +#ifndef __MAKE_SULIB__ +long +ncp_get_bindery_object_name(struct ncp_conn *conn, + __u32 object_id, + struct ncp_bindery_object *target) { long result; ncp_init_request_s(conn, 54); ncp_add_dword_hl(conn, object_id); - if ((result = ncp_request(conn, 23)) != 0) { + if ((result = ncp_request(conn, 23)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -1611,9 +2486,10 @@ long ncp_get_bindery_object_name(struct ncp_conn *conn, return 0; } -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_scan_bindery_object(struct ncp_conn *conn, + __u32 last_id, __u16 object_type, char *search_string, + struct ncp_bindery_object *target) { long result; ncp_init_request_s(conn, 55); @@ -1621,7 +2497,8 @@ long ncp_scan_bindery_object(struct ncp_conn *conn, ncp_add_word_hl(conn, object_type); ncp_add_pstring(conn, search_string); - if ((result = ncp_request(conn, 23)) != 0) { + if ((result = ncp_request(conn, 23)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -1637,11 +2514,12 @@ long ncp_scan_bindery_object(struct ncp_conn *conn, return 0; } -long ncp_create_bindery_object(struct ncp_conn *conn, - __u16 object_type, - const char *object_name, - __u8 object_security, - __u8 object_status) +long +ncp_create_bindery_object(struct ncp_conn *conn, + __u16 object_type, + const char *object_name, + __u8 object_security, + __u8 object_status) { long result; ncp_init_request_s(conn, 50); @@ -1656,9 +2534,10 @@ long ncp_create_bindery_object(struct ncp_conn *conn, } -long ncp_delete_bindery_object(struct ncp_conn *conn, - __u16 object_type, - const char *object_name) +long +ncp_delete_bindery_object(struct ncp_conn *conn, + __u16 object_type, + const char *object_name) { long result; ncp_init_request_s(conn, 51); @@ -1669,11 +2548,13 @@ long ncp_delete_bindery_object(struct ncp_conn *conn, ncp_unlock_conn(conn); return result; } +#endif /* not __MAKE_SULIB__ */ -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_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 result; ncp_init_request_s(conn, 61); @@ -1682,7 +2563,8 @@ long ncp_read_property_value(struct ncp_conn *conn, ncp_add_byte(conn, segment); ncp_add_pstring(conn, prop_name); - if ((result = ncp_request(conn, 23)) != 0) { + if ((result = ncp_request(conn, 23)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -1693,11 +2575,12 @@ long ncp_read_property_value(struct ncp_conn *conn, return 0; } - -long ncp_scan_property(struct ncp_conn *conn, - __u16 object_type, const char *object_name, - __u32 last_id, char *search_string, - struct ncp_property_info *property_info) +#ifndef __MAKE_SULIB__ +long +ncp_scan_property(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + __u32 last_id, const char *search_string, + struct ncp_property_info *property_info) { long result; ncp_init_request_s(conn, 60); @@ -1706,7 +2589,8 @@ long ncp_scan_property(struct ncp_conn *conn, ncp_add_dword_hl(conn, last_id); ncp_add_pstring(conn, search_string); - if ((result = ncp_request(conn, 23)) != 0) { + if ((result = ncp_request(conn, 23)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -1720,11 +2604,12 @@ long ncp_scan_property(struct ncp_conn *conn, return 0; } -long ncp_add_object_to_set(struct ncp_conn *conn, - __u16 object_type, const char *object_name, - const char *property_name, - __u16 member_type, - const char *member_name) +long +ncp_add_object_to_set(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + const char *property_name, + __u16 member_type, + const char *member_name) { long result; ncp_init_request_s(conn, 65); @@ -1739,10 +2624,11 @@ long ncp_add_object_to_set(struct ncp_conn *conn, return result; } -long ncp_change_property_security(struct ncp_conn *conn, - __u16 object_type, const char *object_name, - const char *property_name, - __u8 property_security) +long +ncp_change_property_security(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + const char *property_name, + __u8 property_security) { long result; ncp_init_request_s(conn, 59); @@ -1756,10 +2642,11 @@ long ncp_change_property_security(struct ncp_conn *conn, return result; } -long ncp_create_property(struct ncp_conn *conn, - __u16 object_type, const char *object_name, - const char *property_name, - __u8 property_flags, __u8 property_security) +long +ncp_create_property(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + const char *property_name, + __u8 property_flags, __u8 property_security) { long result; ncp_init_request_s(conn, 57); @@ -1774,11 +2661,12 @@ long ncp_create_property(struct ncp_conn *conn, return result; } -long ncp_delete_object_from_set(struct ncp_conn *conn, - __u16 object_type, const char *object_name, - const char *property_name, - __u16 member_type, - const char *member_name) +long +ncp_delete_object_from_set(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + const char *property_name, + __u16 member_type, + const char *member_name) { long result; ncp_init_request_s(conn, 66); @@ -1793,9 +2681,10 @@ long ncp_delete_object_from_set(struct ncp_conn *conn, return result; } -long ncp_delete_property(struct ncp_conn *conn, - __u16 object_type, const char *object_name, - const char *property_name) +long +ncp_delete_property(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + const char *property_name) { long result; ncp_init_request_s(conn, 58); @@ -1808,11 +2697,12 @@ long ncp_delete_property(struct ncp_conn *conn, return result; } -long ncp_write_property_value(struct ncp_conn *conn, - __u16 object_type, const char *object_name, - const char *property_name, - __u8 segment, - struct nw_property *property_value) +long +ncp_write_property_value(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + const char *property_name, + __u8 segment, + const struct nw_property *property_value) { long result; ncp_init_request_s(conn, 62); @@ -1828,19 +2718,21 @@ long ncp_write_property_value(struct ncp_conn *conn, return result; } -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_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 result; ncp_init_request(conn); ncp_add_word_hl(conn, proposed_max_size); ncp_add_byte(conn, proposed_security_flag); - if ((result = ncp_request(conn, 97)) != 0) { + if ((result = ncp_request(conn, 97)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -1850,11 +2742,13 @@ long ncp_get_big_ncp_max_packet_size(struct ncp_conn *conn, ncp_unlock_conn(conn); return 0; } +#endif /* not __MAKE_SULIB__ */ -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_encrypted(struct ncp_conn *conn, + const struct ncp_bindery_object *object, + const unsigned char *key, + const unsigned char *passwd) { dword tmpID = htonl(object->object_id); unsigned char buf[128]; @@ -1871,12 +2765,22 @@ long ncp_login_encrypted(struct ncp_conn *conn, result = ncp_request(conn, 23); ncp_unlock_conn(conn); +#ifdef SIGNATURES + if ((result == 0) || ((result == NCPL_ET_REQUEST_ERROR) && + (conn->completion == NCP_GRACE_PERIOD))) + { + memcpy(buf + 16, key, 8); + sign_init(buf, buf); + result = ncp_sign_start(conn, buf); + } +#endif return result; } -long ncp_login_unencrypted(struct ncp_conn *conn, - __u16 object_type, const char *object_name, - const unsigned char *passwd) +long +ncp_login_unencrypted(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + const unsigned char *passwd) { long result; ncp_init_request_s(conn, 20); @@ -1888,11 +2792,13 @@ long ncp_login_unencrypted(struct ncp_conn *conn, return result; } -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) +#ifndef __MAKE_SULIB__ +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) { long id = htonl(object->object_id); unsigned char cryptkey[8]; @@ -1907,7 +2813,8 @@ long ncp_change_login_passwd(struct ncp_conn *conn, nw_encrypt(cryptkey, oldpwd, cryptkey); newpassencrypt(oldpwd, newpwd, newpwd); newpassencrypt(oldpwd + 8, newpwd + 8, newpwd + 8); - if ((len = strlen(newpasswd)) > 63) { + if ((len = strlen(newpasswd)) > 63) + { len = 63; } len = ((len ^ oldpwd[0] ^ oldpwd[1]) & 0x7f) | 0x40; @@ -1922,38 +2829,45 @@ long ncp_change_login_passwd(struct ncp_conn *conn, ncp_unlock_conn(conn); return result; } +#endif /* not __MAKE_SULIB__ */ -long ncp_login_user(struct ncp_conn *conn, - const unsigned char *username, - const unsigned char *password) +long +ncp_login_user(struct ncp_conn *conn, + const unsigned char *username, + const unsigned char *password) { return ncp_login_object(conn, username, NCP_BINDERY_USER, password); } -static long ncp_login_object(struct ncp_conn *conn, - const unsigned char *username, - int login_type, - const unsigned char *password) +static long +ncp_login_object(struct ncp_conn *conn, + const unsigned char *username, + int login_type, + const unsigned char *password) { long result; unsigned char ncp_key[8]; struct ncp_bindery_object user; - if ((result = ncp_get_encryption_key(conn, ncp_key)) != 0) { + if ((result = ncp_get_encryption_key(conn, ncp_key)) != 0) + { return ncp_login_unencrypted(conn, login_type, username, password); } if ((result = ncp_get_bindery_object_id(conn, login_type, - username, &user)) != 0) { + username, &user)) != 0) + { return result; } if ((result = ncp_login_encrypted(conn, &user, - ncp_key, password)) != 0) { + ncp_key, password)) != 0) + { struct nw_property p; struct ncp_prop_login_control *l = (struct ncp_prop_login_control *) &p; - if (conn->completion != NCP_GRACE_PERIOD) { + if (conn->completion != NCP_GRACE_PERIOD) + { return result; } fprintf(stderr, "Your password has expired\n"); @@ -1961,7 +2875,8 @@ static long ncp_login_object(struct ncp_conn *conn, if ((result = ncp_read_property_value(conn, NCP_BINDERY_USER, username, 1, "LOGIN_CONTROL", - &p)) == 0) { + &p)) == 0) + { fprintf(stderr, "You have %d login attempts left\n", l->GraceLogins); } @@ -1969,8 +2884,10 @@ static long ncp_login_object(struct ncp_conn *conn, return 0; } -long ncp_get_volume_info_with_number(struct ncp_conn *conn, int n, - struct ncp_volume_info *target) +#ifndef __MAKE_SULIB__ +long +ncp_get_volume_info_with_number(struct ncp_conn *conn, int n, + struct ncp_volume_info *target) { long result; int len; @@ -1978,7 +2895,8 @@ long ncp_get_volume_info_with_number(struct ncp_conn *conn, int n, ncp_init_request_s(conn, 44); ncp_add_byte(conn, n); - if ((result = ncp_request(conn, 22)) != 0) { + if ((result = ncp_request(conn, 22)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -1993,24 +2911,27 @@ long ncp_get_volume_info_with_number(struct ncp_conn *conn, int n, memzero(target->volume_name); len = ncp_reply_byte(conn, 29); - if (len > NCP_VOLNAME_LEN) { + if (len > NCP_VOLNAME_LEN) + { ncp_printf("ncpfs: volume name too long: %d\n", len); ncp_unlock_conn(conn); - return -EIO; + return EIO; } memcpy(&(target->volume_name), ncp_reply_data(conn, 30), len); ncp_unlock_conn(conn); return 0; } -long ncp_get_volume_number(struct ncp_conn *conn, const char *name, int *target) +long +ncp_get_volume_number(struct ncp_conn *conn, const char *name, int *target) { long result; ncp_init_request_s(conn, 5); ncp_add_pstring(conn, name); - if ((result = ncp_request(conn, 22)) != 0) { + if ((result = ncp_request(conn, 22)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -2020,9 +2941,10 @@ 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_init(struct ncp_conn *conn, + int dir_handle, const char *path, + struct ncp_filesearch_info *target) { long result; @@ -2030,7 +2952,8 @@ long ncp_file_search_init(struct ncp_conn *conn, ncp_add_byte(conn, dir_handle); ncp_add_pstring(conn, path); - if ((result = ncp_request(conn, 62)) != 0) { + if ((result = ncp_request(conn, 62)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -2043,10 +2966,11 @@ long ncp_file_search_init(struct ncp_conn *conn, } -long ncp_file_search_continue(struct ncp_conn *conn, - struct ncp_filesearch_info *fsinfo, - int attributes, const char *name, - struct ncp_file_info *target) +long +ncp_file_search_continue(struct ncp_conn *conn, + struct ncp_filesearch_info *fsinfo, + int attributes, const char *name, + struct ncp_file_info *target) { long result; @@ -2059,7 +2983,8 @@ long ncp_file_search_continue(struct ncp_conn *conn, ncp_add_byte(conn, attributes); ncp_add_pstring(conn, name); - if ((result = ncp_request(conn, 63)) != 0) { + if ((result = ncp_request(conn, 63)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -2081,33 +3006,38 @@ long ncp_file_search_continue(struct ncp_conn *conn, return 0; } -long ncp_get_finfo(struct ncp_conn *conn, - int dir_handle, const char *path, const char *name, - 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 result; struct ncp_filesearch_info fsinfo; if ((result = ncp_file_search_init(conn, dir_handle, path, - &fsinfo)) != 0) { + &fsinfo)) != 0) + { return result; } if ((result = ncp_file_search_continue(conn, &fsinfo, 0, name, - target)) == 0) { + target)) == 0) + { return result; } if ((result = ncp_file_search_init(conn, dir_handle, path, - &fsinfo)) != 0) { + &fsinfo)) != 0) + { return result; } return ncp_file_search_continue(conn, &fsinfo, aDIR, name, 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_open_file(struct ncp_conn *conn, + int dir_handle, const char *path, + int attr, int access, + struct ncp_file_info *target) { long result; @@ -2117,7 +3047,8 @@ long ncp_open_file(struct ncp_conn *conn, ncp_add_byte(conn, access); ncp_add_pstring(conn, path); - if ((result = ncp_request(conn, 76)) != 0) { + if ((result = ncp_request(conn, 76)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -2140,7 +3071,8 @@ long ncp_open_file(struct ncp_conn *conn, return 0; } -long ncp_close_file(struct ncp_conn *conn, const char *file_id) +long +ncp_close_file(struct ncp_conn *conn, const char *file_id) { long result; @@ -2153,11 +3085,12 @@ long ncp_close_file(struct ncp_conn *conn, const char *file_id) return result; } -static int ncp_do_create(struct ncp_conn *conn, - int dir_handle, const char *path, - int attr, - struct ncp_file_info *target, - int function) +static int +ncp_do_create(struct ncp_conn *conn, + int dir_handle, const char *path, + int attr, + struct ncp_file_info *target, + int function) { long result; @@ -2166,7 +3099,8 @@ static int ncp_do_create(struct ncp_conn *conn, ncp_add_byte(conn, attr); ncp_add_pstring(conn, path); - if ((result = ncp_request(conn, function)) != 0) { + if ((result = ncp_request(conn, function)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -2189,25 +3123,28 @@ static int ncp_do_create(struct ncp_conn *conn, return 0; } -long ncp_create_newfile(struct ncp_conn *conn, - int dir_handle, const char *path, - int attr, - struct ncp_file_info *target) +long +ncp_create_newfile(struct ncp_conn *conn, + int dir_handle, const char *path, + int attr, + struct ncp_file_info *target) { return ncp_do_create(conn, dir_handle, path, attr, target, 77); } -long ncp_create_file(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) { return ncp_do_create(conn, dir_handle, path, attr, target, 67); } -long ncp_erase_file(struct ncp_conn *conn, - int dir_handle, const char *path, - int attr) +long +ncp_erase_file(struct ncp_conn *conn, + int dir_handle, const char *path, + int attr) { long result; @@ -2221,10 +3158,11 @@ long ncp_erase_file(struct ncp_conn *conn, return result; } -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_rename_file(struct ncp_conn *conn, + int old_handle, const char *old_path, + int attr, + int new_handle, const char *new_path) { long result; @@ -2235,7 +3173,8 @@ long ncp_rename_file(struct ncp_conn *conn, ncp_add_byte(conn, new_handle); ncp_add_pstring(conn, new_path); - if ((result = ncp_request(conn, 69)) != 0) { + if ((result = ncp_request(conn, 69)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -2243,9 +3182,10 @@ long ncp_rename_file(struct ncp_conn *conn, return 0; } -long ncp_create_directory(struct ncp_conn *conn, - int dir_handle, const char *path, - int inherit_mask) +long +ncp_create_directory(struct ncp_conn *conn, + int dir_handle, const char *path, + int inherit_mask) { long result; @@ -2259,8 +3199,9 @@ long ncp_create_directory(struct ncp_conn *conn, return result; } -long ncp_delete_directory(struct ncp_conn *conn, - int dir_handle, const char *path) +long +ncp_delete_directory(struct ncp_conn *conn, + int dir_handle, const char *path) { long result; @@ -2274,9 +3215,10 @@ long ncp_delete_directory(struct ncp_conn *conn, return result; } -long ncp_add_trustee(struct ncp_conn *conn, - int dir_handle, const char *path, - __u32 object_id, __u8 rights) +long +ncp_add_trustee(struct ncp_conn *conn, + int dir_handle, const char *path, + __u32 object_id, __u8 rights) { long result; @@ -2291,8 +3233,9 @@ long ncp_add_trustee(struct ncp_conn *conn, return result; } -long ncp_delete_trustee(struct ncp_conn *conn, - int dir_handle, const char *path, __u32 object_id) +long +ncp_delete_trustee(struct ncp_conn *conn, + int dir_handle, const char *path, __u32 object_id) { long result; @@ -2307,9 +3250,10 @@ long ncp_delete_trustee(struct ncp_conn *conn, return result; } -long ncp_get_trustee(struct ncp_conn *conn, __u32 object_id, - __u8 vol, char *path, - __u16 * trustee, __u16 * contin) +long +ncp_get_trustee(struct ncp_conn *conn, __u32 object_id, + __u8 vol, char *path, + __u16 * trustee, __u16 * contin) { long result; @@ -2318,7 +3262,8 @@ long ncp_get_trustee(struct ncp_conn *conn, __u32 object_id, ncp_add_word_hl(conn, *contin); ncp_add_dword_hl(conn, object_id); - if ((result = ncp_request(conn, 23)) != 0) { + if ((result = ncp_request(conn, 23)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -2330,9 +3275,10 @@ long ncp_get_trustee(struct ncp_conn *conn, __u32 object_id, return 0; } -long ncp_rename_directory(struct ncp_conn *conn, - int dir_handle, - const char *old_path, const char *new_path) +long +ncp_rename_directory(struct ncp_conn *conn, + int dir_handle, + const char *old_path, const char *new_path) { long result; @@ -2346,44 +3292,53 @@ long ncp_rename_directory(struct ncp_conn *conn, return result; } -static void ncp_add_handle_path(struct ncp_conn *conn, - __u8 vol_num, - __u32 dir_base, int have_dir_base, - const char *path) +static void +ncp_add_handle_path(struct ncp_conn *conn, + __u8 vol_num, + __u32 dir_base, int have_dir_base, + const char *path) { ncp_add_byte(conn, vol_num); ncp_add_dword_lh(conn, dir_base); - if (have_dir_base != 0) { + if (have_dir_base != 0) + { ncp_add_byte(conn, 1); /* dir_base */ - } else { + } else + { ncp_add_byte(conn, 0xff); /* no handle */ } - if (path != NULL) { + if (path != NULL) + { ncp_add_byte(conn, 1); /* 1 component */ ncp_add_pstring(conn, path); - } else { + } else + { ncp_add_byte(conn, 0); } } +#endif /* __MAKE_SULIB */ -static void ncp_extract_file_info(void *structure, struct nw_info_struct *target) +static void +ncp_extract_file_info(void *structure, struct nw_info_struct *target) { __u8 *name_len; const int info_struct_size = sizeof(struct nw_info_struct) - 257; memcpy(target, structure, info_struct_size); - name_len = structure + info_struct_size; + name_len = (u_int8_t*)structure + info_struct_size; target->nameLen = *name_len; strncpy(target->entryName, name_len + 1, *name_len); target->entryName[*name_len] = '\0'; return; } -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) +#ifndef __MAKE_SULIB__ +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) { long result; @@ -2395,7 +3350,8 @@ long ncp_obtain_file_or_subdir_info(struct ncp_conn *conn, ncp_add_dword_lh(conn, rim); ncp_add_handle_path(conn, vol, dirent, 1, path); - if ((result = ncp_request(conn, 87)) != 0) { + if ((result = ncp_request(conn, 87)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -2404,11 +3360,12 @@ long ncp_obtain_file_or_subdir_info(struct ncp_conn *conn, return 0; } -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_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 result; @@ -2420,7 +3377,8 @@ long ncp_get_eff_directory_rights(struct ncp_conn *conn, ncp_add_dword_lh(conn, 0); ncp_add_handle_path(conn, vol, dirent, 1, path); - if ((result = ncp_request(conn, 87)) != 0) { + if ((result = ncp_request(conn, 87)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -2429,20 +3387,23 @@ long ncp_get_eff_directory_rights(struct ncp_conn *conn, return 0; } -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_do_lookup(struct ncp_conn *conn, + struct nw_info_struct *dir, + const char *path, /* may only be one component */ + struct nw_info_struct *target) { __u8 vol_num; __u32 dir_base; long result; - char *volname = NULL; + const char *volname = NULL; - if (target == NULL) { - return -EINVAL; + if (target == NULL) + { + return EINVAL; } - if (dir == NULL) { + if (dir == NULL) + { /* Access a volume's root directory */ ncp_init_request(conn); @@ -2454,7 +3415,8 @@ long ncp_do_lookup(struct ncp_conn *conn, ncp_add_handle_path(conn, 0, 0, 0, /* no handle */ path); - if ((result = ncp_request(conn, 87)) != 0) { + if ((result = ncp_request(conn, 87)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -2463,7 +3425,8 @@ long ncp_do_lookup(struct ncp_conn *conn, ncp_unlock_conn(conn); volname = path; path = NULL; - } else { + } else + { vol_num = dir->volNumber; dir_base = dir->DosDirNum; } @@ -2477,13 +3440,15 @@ long ncp_do_lookup(struct ncp_conn *conn, ncp_add_handle_path(conn, vol_num, dir_base, 1, path); - if ((result = ncp_request(conn, 87)) != 0) { + if ((result = ncp_request(conn, 87)) != 0) + { ncp_unlock_conn(conn); return result; } ncp_extract_file_info(ncp_reply_data(conn, 0), target); - if (volname != NULL) { + if (volname != NULL) + { target->nameLen = strlen(volname); strcpy(target->entryName, volname); } @@ -2491,10 +3456,11 @@ long ncp_do_lookup(struct ncp_conn *conn, return 0; } -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_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 result; @@ -2514,8 +3480,9 @@ long ncp_modify_file_or_subdir_dos_info(struct ncp_conn *conn, return result; } -long ncp_del_file_or_subdir(struct ncp_conn *conn, - struct nw_info_struct *dir, char *name) +long +ncp_del_file_or_subdir(struct ncp_conn *conn, + struct nw_info_struct *dir, char *name) { long result; @@ -2532,7 +3499,8 @@ long ncp_del_file_or_subdir(struct ncp_conn *conn, return result; } -static inline void ConvertToNWfromDWORD(__u32 sfd, __u8 ret[6]) +static inline void +ConvertToNWfromDWORD(__u32 sfd, __u8 ret[6]) { __u16 *dest = (__u16 *) ret; memcpy(&(dest[1]), &sfd, 4); @@ -2540,12 +3508,13 @@ static inline void ConvertToNWfromDWORD(__u32 sfd, __u8 ret[6]) return; } -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_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 result; @@ -2564,7 +3533,8 @@ long ncp_open_create_file_or_subdir(struct ncp_conn *conn, ncp_add_handle_path(conn, dir->volNumber, dir->DosDirNum, 1, name); - if ((result = ncp_request(conn, 87)) != 0) { + if ((result = ncp_request(conn, 87)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -2578,14 +3548,16 @@ long ncp_open_create_file_or_subdir(struct ncp_conn *conn, return 0; } -long ncp_initialize_search(struct ncp_conn *conn, - const struct nw_info_struct *dir, - int namespace, - struct ncp_search_seq *target) +long +ncp_initialize_search(struct ncp_conn *conn, + const struct nw_info_struct *dir, + int namespace, + struct ncp_search_seq *target) { long result; - if ((namespace < 0) || (namespace > 255)) { + if ((namespace < 0) || (namespace > 255)) + { return EINVAL; } memzero(*target); @@ -2597,7 +3569,8 @@ long ncp_initialize_search(struct ncp_conn *conn, ncp_add_handle_path(conn, dir->volNumber, dir->DosDirNum, 1, NULL); - if ((result = ncp_request(conn, 87)) != 0) { + if ((result = ncp_request(conn, 87)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -2609,9 +3582,12 @@ long ncp_initialize_search(struct ncp_conn *conn, } /* Search for everything */ -long ncp_search_for_file_or_subdir(struct ncp_conn *conn, - struct ncp_search_seq *seq, - struct nw_info_struct *target) +long +ncp_search_for_file_or_subdir2(struct ncp_conn *conn, + int search_attributes, + u_int32_t RIM, + struct ncp_search_seq *seq, + struct nw_info_struct *target) { long result; @@ -2619,33 +3595,44 @@ long ncp_search_for_file_or_subdir(struct ncp_conn *conn, ncp_add_byte(conn, 3); /* subfunction */ ncp_add_byte(conn, seq->namespace); ncp_add_byte(conn, 0); /* data stream (???) */ - ncp_add_word_lh(conn, 0xffff); /* Search attribs */ - ncp_add_dword_lh(conn, RIM_ALL); /* return info mask */ + ncp_add_word_lh(conn, search_attributes); /* Search attribs */ + ncp_add_dword_lh(conn, RIM); /* return info mask */ ncp_add_mem(conn, &(seq->s), 9); ncp_add_byte(conn, 2); /* 2 byte pattern */ ncp_add_byte(conn, 0xff); /* following is a wildcard */ ncp_add_byte(conn, '*'); - if ((result = ncp_request(conn, 87)) != 0) { + if ((result = ncp_request(conn, 87)) != 0) + { ncp_unlock_conn(conn); return result; } - memcpy(seq, ncp_reply_data(conn, 0), sizeof(*seq)); + memcpy(&(seq->s), ncp_reply_data(conn, 0), sizeof(seq->s)); ncp_extract_file_info(ncp_reply_data(conn, 10), target); ncp_unlock_conn(conn); return 0; } -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) +/* Search for everything */ +long +ncp_search_for_file_or_subdir(struct ncp_conn *conn, + struct ncp_search_seq *seq, + struct nw_info_struct *target) +{ + return ncp_search_for_file_or_subdir2(conn, 0x8006, RIM_ALL, seq, 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 result; if ((old_dir == NULL) || (old_name == NULL) || (new_dir == NULL) || (new_name == NULL)) - return -EINVAL; + return EINVAL; ncp_init_request(conn); ncp_add_byte(conn, 4); /* subfunction */ @@ -2677,9 +3664,10 @@ long ncp_ren_or_mov_file_or_subdir(struct ncp_conn *conn, /* Create a new job entry */ -long ncp_create_queue_job_and_file(struct ncp_conn *conn, - __u32 queue_id, - struct queue_job *job) +long +ncp_create_queue_job_and_file(struct ncp_conn *conn, + __u32 queue_id, + struct queue_job *job) { long result; @@ -2687,7 +3675,8 @@ long ncp_create_queue_job_and_file(struct ncp_conn *conn, ncp_add_dword_hl(conn, queue_id); ncp_add_mem(conn, &(job->j), sizeof(job->j)); - if ((result = ncp_request(conn, 23)) != 0) { + if ((result = ncp_request(conn, 23)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -2698,9 +3687,10 @@ long ncp_create_queue_job_and_file(struct ncp_conn *conn, return 0; } -long ncp_close_file_and_start_job(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 result; @@ -2713,8 +3703,9 @@ long ncp_close_file_and_start_job(struct ncp_conn *conn, return result; } -long ncp_attach_to_queue(struct ncp_conn *conn, - __u32 queue_id) +long +ncp_attach_to_queue(struct ncp_conn *conn, + __u32 queue_id) { long result; @@ -2726,8 +3717,9 @@ long ncp_attach_to_queue(struct ncp_conn *conn, return result; } -long ncp_detach_from_queue(struct ncp_conn *conn, - __u32 queue_id) +long +ncp_detach_from_queue(struct ncp_conn *conn, + __u32 queue_id) { long result; @@ -2739,8 +3731,9 @@ long ncp_detach_from_queue(struct ncp_conn *conn, return result; } -long ncp_service_queue_job(struct ncp_conn *conn, __u32 queue_id, __u16 job_type, - struct queue_job *job) +long +ncp_service_queue_job(struct ncp_conn *conn, __u32 queue_id, __u16 job_type, + struct queue_job *job) { long result; @@ -2748,7 +3741,8 @@ long ncp_service_queue_job(struct ncp_conn *conn, __u32 queue_id, __u16 job_type ncp_add_dword_hl(conn, queue_id); ncp_add_word_hl(conn, job_type); - if ((result = ncp_request(conn, 23)) != 0) { + if ((result = ncp_request(conn, 23)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -2759,8 +3753,9 @@ long ncp_service_queue_job(struct ncp_conn *conn, __u32 queue_id, __u16 job_type return 0; } -long ncp_finish_servicing_job(struct ncp_conn *conn, __u32 queue_id, - __u32 job_number, __u32 charge_info) +long +ncp_finish_servicing_job(struct ncp_conn *conn, __u32 queue_id, + __u32 job_number, __u32 charge_info) { long result; @@ -2774,8 +3769,9 @@ long ncp_finish_servicing_job(struct ncp_conn *conn, __u32 queue_id, return result; } -long ncp_abort_servicing_job(struct ncp_conn *conn, __u32 queue_id, - __u32 job_number) +long +ncp_abort_servicing_job(struct ncp_conn *conn, __u32 queue_id, + __u32 job_number) { long result; @@ -2788,9 +3784,147 @@ long ncp_abort_servicing_job(struct ncp_conn *conn, __u32 queue_id, return result; } -static int ncp_do_read(struct ncp_conn *conn, const char *file_id, - __u32 offset, __u16 to_read, - char *target, int *bytes_read) +long +ncp_get_queue_length(struct ncp_conn *conn, + __u32 queue_id, + __u32 *queue_length) +{ + long result=-EINVAL; + + ncp_init_request_s(conn, 125); + ncp_add_dword_hl(conn, queue_id); + + if ((result = ncp_request(conn, 23)) != 0) + goto out; + + if (conn->ncp_reply_size < 12) + { + ncp_printf("ncp_reply_size %d < 12\n", + conn->ncp_reply_size); + result=-EINVAL; + goto out; + } + + if (ncp_reply_dword_hl(conn,0) != queue_id) + { + printf("Ouch! Server didn't reply with same queue id in ncp_get_queue_length!\n"); + result=-EINVAL; + } + else + *queue_length = ncp_reply_dword_lh(conn,8); + + out: + ncp_unlock_conn(conn); + return result; +} + +long +ncp_get_queue_job_ids(struct ncp_conn *conn, + __u32 queue_id, + __u32 queue_section, + __u32 *length1, + __u32 *length2, + __u32 ids[]) +{ + long result; + + ncp_init_request_s(conn,129); + ncp_add_dword_hl(conn, queue_id); + ncp_add_dword_lh(conn, queue_section); + + if ((result = ncp_request(conn, 23)) != 0) + goto out; + + if (conn->ncp_reply_size < 8) + { + ncp_printf("ncp_reply_size %d < 8\n", + conn->ncp_reply_size); + result=-EINVAL; + goto out; + } + + *length2 = ncp_reply_dword_lh(conn,4); + if (conn->ncp_reply_size < 8 + 4*(*length2)) + { + ncp_printf("ncp_reply_size %d < %d\n", + conn->ncp_reply_size, 8+4*(*length2)); + result=-EINVAL; + goto out; + } + if (ids) { + int count = min(*length1, *length2)*sizeof(__u32); + int pos; + + for (pos=0; posncp_reply_size < sizeof(struct nw_queue_job_entry)) + { + ncp_printf("ncp_reply_size %d < %d\n", + conn->ncp_reply_size,sizeof(struct nw_queue_job_entry)); + result=-EINVAL; + } + else + memcpy(jobdata,ncp_reply_data(conn,0), sizeof(struct nw_queue_job_entry)); + +out: + ncp_unlock_conn(conn); + return result; +} + +long +NWRemoveJobFromQueue2 +( + struct ncp_conn* conn, + __u32 queueID, + __u32 jobNumber +) { + long result; + + ncp_init_request_s(conn, 0x80); + ncp_add_dword_hl(conn, queueID); + ncp_add_dword_lh(conn, jobNumber); + result = ncp_request(conn, 0x17); + if (result) { + if (result == NCPL_ET_REQUEST_ERROR) { + result = 0x8900 | conn->completion; + } else { + result = 0x88FF; + } + } else { + /* no output */ + } + ncp_unlock_conn(conn); + return result; +} + +static int +ncp_do_read(struct ncp_conn *conn, const char *file_id, + __u32 offset, __u16 to_read, + char *target, int *bytes_read) { long result; @@ -2800,7 +3934,8 @@ static int ncp_do_read(struct ncp_conn *conn, const char *file_id, ncp_add_dword_hl(conn, offset); ncp_add_word_hl(conn, to_read); - if ((result = ncp_request(conn, 72)) != 0) { + if ((result = ncp_request(conn, 72)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -2812,35 +3947,40 @@ static int ncp_do_read(struct ncp_conn *conn, const char *file_id, return 0; } -long ncp_read(struct ncp_conn *conn, const char *file_id, - off_t offset, size_t count, char *target) +long +ncp_read(struct ncp_conn *conn, const char *file_id, + off_t offset, size_t count, char *target) { const int bufsize = conn->i.buffer_size; - int already_read = 0; + size_t already_read = 0; - while (already_read < count) { + while (already_read < count) + { int read_this_time; int to_read = min(bufsize - (offset % bufsize), count - already_read); if (ncp_do_read(conn, file_id, offset, to_read, - target, &read_this_time) != 0) { + target, &read_this_time) != 0) + { return -1; } offset += read_this_time; target += read_this_time; already_read += read_this_time; - if (read_this_time < to_read) { + if (read_this_time < to_read) + { break; } } return already_read; } -static int ncp_do_write(struct ncp_conn *conn, const char *file_id, - __u32 offset, __u16 to_write, - const char *source, int *bytes_written) +static int +ncp_do_write(struct ncp_conn *conn, const char *file_id, + __u32 offset, __u16 to_write, + const char *source, int *bytes_written) { long result; @@ -2851,7 +3991,8 @@ static int ncp_do_write(struct ncp_conn *conn, const char *file_id, ncp_add_word_hl(conn, to_write); ncp_add_mem(conn, source, to_write); - if ((result = ncp_request(conn, 73)) != 0) { + if ((result = ncp_request(conn, 73)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -2861,39 +4002,44 @@ static int ncp_do_write(struct ncp_conn *conn, const char *file_id, return 0; } -long ncp_write(struct ncp_conn *conn, const char *file_id, - off_t offset, size_t count, const char *source) +long +ncp_write(struct ncp_conn *conn, const char *file_id, + off_t offset, size_t count, const char *source) { const int bufsize = conn->i.buffer_size; - int already_written = 0; + size_t already_written = 0; - while (already_written < count) { + while (already_written < count) + { int written_this_time; int to_write = min(bufsize - (offset % bufsize), count - already_written); if (ncp_do_write(conn, file_id, offset, to_write, - source, &written_this_time) != 0) { + source, &written_this_time) != 0) + { return -1; } offset += written_this_time; source += written_this_time; already_written += written_this_time; - if (written_this_time < to_write) { + if (written_this_time < to_write) + { break; } } return already_written; } -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_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 result; @@ -2906,7 +4052,8 @@ long ncp_copy_file(struct ncp_conn *conn, ncp_add_dword_hl(conn, target_offset); ncp_add_dword_hl(conn, count); - if ((result = ncp_request(conn, 74)) != 0) { + if ((result = ncp_request(conn, 74)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -2915,25 +4062,8 @@ long ncp_copy_file(struct ncp_conn *conn, return 0; } -long ncp_get_broadcast_message(struct ncp_conn *conn, char message[256]) -{ - long result; - int length; - - ncp_init_request_s(conn, 1); - - if ((result = ncp_request(conn, 21)) != 0) { - ncp_unlock_conn(conn); - return result; - } - length = ncp_reply_byte(conn, 0); - message[length] = 0; - memcpy(message, ncp_reply_data(conn, 1), length); - ncp_unlock_conn(conn); - return 0; -} - -long ncp_dealloc_dir_handle(struct ncp_conn *conn, __u8 dir_handle) +long +ncp_dealloc_dir_handle(struct ncp_conn *conn, __u8 dir_handle) { long result; @@ -2945,10 +4075,11 @@ long ncp_dealloc_dir_handle(struct ncp_conn *conn, __u8 dir_handle) return result; } -long ncp_alloc_short_dir_handle(struct ncp_conn *conn, - struct nw_info_struct *dir, - word alloc_mode, - byte * target) +long +ncp_alloc_short_dir_handle(struct ncp_conn *conn, + struct nw_info_struct *dir, + word alloc_mode, + byte * target) { long result; @@ -2960,7 +4091,8 @@ long ncp_alloc_short_dir_handle(struct ncp_conn *conn, ncp_add_handle_path(conn, dir->volNumber, dir->DosDirNum, 1, NULL); - if ((result = ncp_request(conn, 87)) != 0) { + if ((result = ncp_request(conn, 87)) != 0) + { ncp_unlock_conn(conn); return result; } @@ -2969,10 +4101,11 @@ long ncp_alloc_short_dir_handle(struct ncp_conn *conn, return result; } -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) +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) { long result = 0; @@ -2985,7 +4118,8 @@ long ncp_add_trustee_set(struct ncp_conn *conn, ncp_add_word_lh(conn, object_count); ncp_add_handle_path(conn, volume_number, dir_entry, 1, NULL); - while (object_count > 0) { + while (object_count > 0) + { ncp_add_dword_hl(conn, rights->object_id); ncp_add_word_lh(conn, rights->rights); object_count -= 1; @@ -2996,3 +4130,537 @@ long ncp_add_trustee_set(struct ncp_conn *conn, ncp_unlock_conn(conn); return result; } +#endif /* not __MAKE_SULIB__ */ + +#ifdef SIGNATURES +long +ncp_sign_start(struct ncp_conn *conn, const char *sign_root) +{ + char init_last[16]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}; + struct ncp_sign_init sign_init; + + if (conn->sign_wanted) + { + memcpy(sign_init.sign_root, sign_root, 8); + memcpy(sign_init.sign_last, init_last, 16); + conn->sign_active = 1; + if (conn->is_connected == CONN_PERMANENT) + { + if (ioctl(conn->mount_fid, NCP_IOC_SIGN_INIT, + &sign_init)) + return NCPL_ET_SIGNATURE_FAILED; + } + else + { + memcpy(conn->sign_root, sign_init.sign_root, 8); + memcpy(conn->sign_last, sign_init.sign_last, 16); + } + + } + return 0; +} +#endif + +#ifdef NDS_SUPPORT +long +ncp_send_nds_frag(struct ncp_conn *conn, + int ndsverb, + const char *inbuf, size_t inbuflen, + char *outbuf, size_t outbufsize, size_t *outbuflen) +{ + long result; + size_t sizeleft, i; + size_t maxdatasize = 514; + int first = 1; + int firstReply = 1; + int fraghnd = -1; + int32_t ndsCode = -399; + size_t replyLen = 0; + size_t fragLen; + + if (outbuflen) *outbuflen = 0; + do + { + sizeleft = maxdatasize; + ncp_init_request(conn); + ncp_add_byte(conn, 2); + ncp_add_dword_lh(conn, fraghnd); + if (first) + { + ncp_add_dword_lh(conn, maxdatasize - 8); + ncp_add_dword_lh(conn, inbuflen + 12); + ncp_add_dword_lh(conn, 0); + ncp_add_dword_lh(conn, ndsverb); + ncp_add_dword_lh(conn, outbufsize); + sizeleft -= 25; + first = 0; + } + else + sizeleft -= 5; + i = (sizeleft > inbuflen) ? inbuflen : sizeleft; + if (i) ncp_add_mem(conn, inbuf, i); + inbuflen -= i; + inbuf += i; + if ((result = ncp_request(conn, 0x68)) != 0) + { + ncp_unlock_conn(conn); + ncp_dprintf("Error in ncp_request\n"); + return result; + } + fragLen = ncp_reply_dword_lh(conn, 0); + if (fragLen < 4) { + ncp_unlock_conn(conn); + ncp_dprintf("Fragment too short\n"); + return NCPL_ET_REPLY_FORMAT; + } + fraghnd = ncp_reply_dword_lh(conn, 4); + fragLen -= 4; + if (fragLen) { + int hdr; + + if (firstReply) { + ndsCode = ncp_reply_dword_lh(conn, 8); + hdr = 12; + fragLen -= 4; + firstReply = 0; + } else { + hdr = 8; + } + if (fragLen > outbufsize) { + ncp_unlock_conn(conn); + ncp_dprintf("Fragment too large, len=%d, max=%d\n", fragLen, outbufsize); + return NCPL_ET_REPLY_TOO_LARGE; + } + if (outbuf) { + memcpy(outbuf, ncp_reply_data(conn, hdr), fragLen); + outbuf += fragLen; + } + replyLen += fragLen; + } else { + /* if reply len == 0 then we must have something to transmit */ + /* otherwise it can cause endless loop */ + if ((fraghnd != -1) && (inbuflen == 0)) { + ncp_unlock_conn(conn); + ncp_dprintf("Why next fragment?\n"); + return NCPL_ET_REPLY_FORMAT; + } + } + ncp_unlock_conn(conn); + if (fraghnd != -1) { + ncp_dprintf("Fragmented\n"); + } + } while (fraghnd != -1); + if (inbuflen || firstReply) { + ncp_dprintf("InBufLen after request=%d, FirstReply=%d\n", inbuflen, firstReply); + return NCPL_ET_REPLY_FORMAT; + } + if (outbuflen) *outbuflen = replyLen; + if ((conn->completion = ndsCode) != 0) { + ncp_dprintf("NDS error %d\n", ndsCode); + return NCPL_ET_REQUEST_ERROR; + } + return 0; +} + +long +ncp_send_nds(struct ncp_conn *conn, int fn, + const char *data_in, size_t data_in_len, + char *data_out, size_t data_out_max, size_t *data_out_len) +{ + size_t i; + long err; + + ncp_init_request(conn); + ncp_add_byte(conn, fn); + if (data_in) ncp_add_mem(conn, data_in, data_in_len); + if (!(err = ncp_request(conn, 0x68))) + { + i = conn->ncp_reply_size; + if (i > data_out_max) i = data_out_max; + if (data_out) + memcpy(data_out, ncp_reply_data(conn, 0), i); + if (data_out_len) *data_out_len = i; + } + else + if (data_out_len) *data_out_len = 0; + ncp_unlock_conn(conn); + return err; +} + +long +ncp_change_conn_state(struct ncp_conn *conn, int new_state) +{ + long err; + + ncp_init_request_s(conn, 0x1d); + ncp_add_dword_lh(conn, new_state); + err = ncp_request(conn, 0x17); + ncp_unlock_conn(conn); + return err; +} +#endif /* NDS_SUPPORT */ + +struct ncp_conn * +ncp_open_addr(struct sockaddr *target, long *err) { + struct ncp_conn *conn; + + if (!(conn = malloc(sizeof(struct ncp_conn)))) { + *err = ENOMEM; + return NULL; + } + memzero(*conn); + + *err = ncp_connect_addr(conn, target, 1); + if (*err) { + free(conn); + return NULL; + } + return conn; +} + +int +ncp_attach_by_addr(struct sockaddr *target, struct ncp_conn** conn) +{ + long err; + + *conn = ncp_open_addr(target, &err); + return err; +} + +long +ncp_get_broadcast_message(struct ncp_conn *conn, char message[256]) +{ + long result; + int length; + + ncp_init_request_s(conn, 0x0B); + if ((result = ncp_request(conn, 0x15)) != 0) + { + ncp_unlock_conn(conn); + ncp_init_request_s(conn, 0x01); + if ((result = ncp_request(conn, 0x15)) != 0) + { + ncp_unlock_conn(conn); + return result; + } + } + length = ncp_reply_byte(conn, 0); + message[length] = 0; + memcpy(message, ncp_reply_data(conn, 1), length); + ncp_unlock_conn(conn); + return 0; +} + +static void +ncp_add_handle_path2(struct ncp_conn *conn, + __u8 vol_num, + __u32 dir_base, int dir_style, + const unsigned char *encpath, int pathlen) +{ + ncp_add_byte(conn, vol_num); + ncp_add_dword_lh(conn, dir_base); + ncp_add_byte(conn, dir_style); /* 1 = dir_base, 0xFF = no handle, 0 = handle */ + if (encpath) { + ncp_add_mem(conn, encpath, pathlen); + } else { + ncp_add_byte(conn, 0); /* empty path */ + } +} + +#ifndef __MAKE_SULIB__ +long +ncp_ns_scan_salvageable_file(struct ncp_conn* conn, __u8 src_ns, + int dirstyle, + __u8 vol_num, __u32 dir_base, + const unsigned char *encpath, int pathlen, + struct ncp_deleted_file* finfo, + char* name, int maxnamelen) +{ + long result; + __u8 namelen; + + ncp_init_request(conn); + ncp_add_byte(conn, 0x10); + ncp_add_byte(conn, src_ns); + ncp_add_byte(conn, 0); + ncp_add_dword_lh(conn, RIM_NAME); + ncp_add_dword_lh(conn, finfo->seq); + ncp_add_handle_path2(conn, vol_num, dir_base, dirstyle, encpath, pathlen); + result = ncp_request(conn, 0x57); + if (result) { + ncp_unlock_conn(conn); + return result; + } + /* reply format: * == returned by RIM_NAME + +00 __u32 lh next sequence * + +04 __u16 deletion time * + +06 __u16 deletion date * + +08 __u32 lh deletor ID * + +0C __u32 lh volume * + +10 __u32 lh directory base * + +14 __u32 ? + +18 __u32 lh attributes + +1C __u16 hl flags ? + +1E __u32 lh size + +22 __u32 ? + +26 __u16 ? + +28 __u16 creation time + +2A __u16 creation date + +2C __u32 lh creator ID + +30 __u16 modify time + +32 __u16 modify date + +34 __u32 lh modifier ID + +38 __u16 last access date + +3A __u16 last archive time + +3C __u16 last archive date + +3E __u32 lh last archiver ID + +42 __u16 inherited right mask + +44 __u8[0x18] ? + +5C __u32 lh owning namespace + +60 __u8[var] name, length preceeded * + */ + + if (conn->ncp_reply_size < 0x61) { + ncp_unlock_conn(conn); + return NCPL_ET_REPLY_FORMAT; + } + finfo->seq = ncp_reply_dword_lh(conn, 0x00); + finfo->vol = ncp_reply_dword_lh(conn, 0x0C); + finfo->base = ncp_reply_dword_lh(conn, 0x10); + if (name) { + namelen = ncp_reply_byte(conn, 0x60); + if (namelen >= maxnamelen) { + result = NCPL_ET_NAMETOOLONG; + namelen = maxnamelen-1; + } + memcpy(name, ncp_reply_data(conn, 0x61), namelen); + name[namelen] = 0; + } + ncp_unlock_conn(conn); + return result; +} + +long +ncp_ns_purge_file(struct ncp_conn* conn, + const struct ncp_deleted_file* finfo) +{ + long result; + + ncp_init_request(conn); + ncp_add_byte(conn, 0x12); + ncp_add_byte(conn, NW_NS_DOS); + ncp_add_byte(conn, 0); /* reserved? */ + ncp_add_dword_lh(conn, finfo->seq); + ncp_add_dword_lh(conn, finfo->vol); + ncp_add_dword_lh(conn, finfo->base); + result = ncp_request(conn, 87); + ncp_unlock_conn(conn); + return result; +} + +struct ncpi_gfn_cookies { + int flag; + int32_t cookie1; + int32_t cookie2; + }; +static long +ncp_ns_get_full_name_int(struct ncp_conn* conn, __u8 src_ns, __u8 dst_ns, + int dirstyle, __u8 vol_num, __u32 dir_base, + const unsigned char* encpath, size_t pathlen, + struct ncpi_gfn_cookies* cookies, + unsigned char* name, size_t maxnamelen, unsigned char** begin) +{ + long result; + size_t comps; + unsigned char* putpos; + unsigned char* getpos; + unsigned char* getend; + + ncp_init_request(conn); + ncp_add_byte(conn, 0x1C); + ncp_add_byte(conn, src_ns); + ncp_add_byte(conn, dst_ns); + ncp_add_word_lh(conn, cookies->flag); + ncp_add_dword_lh(conn, cookies->cookie1); + ncp_add_dword_lh(conn, cookies->cookie2); + ncp_add_handle_path2(conn, vol_num, dir_base, dirstyle, encpath, pathlen); + result = ncp_request(conn, 0x57); + if (result) { + ncp_unlock_conn(conn); + return result; + } + if (conn->ncp_reply_size < 14) { + ncp_unlock_conn(conn); + return NCPL_ET_REPLY_FORMAT; + } + cookies->flag = ncp_reply_word_lh(conn, 0); + cookies->cookie1 = ncp_reply_dword_lh(conn, 2); + cookies->cookie2 = ncp_reply_dword_lh(conn, 6); + comps = ncp_reply_word_lh(conn, 12); + getpos = ncp_reply_data(conn, 14); + getend = getpos + ncp_reply_word_lh(conn, 10); + putpos = name + maxnamelen; + while (comps--) { + size_t partl; + + if (getpos >= getend) { + ncp_unlock_conn(conn); + return NCPL_ET_REPLY_FORMAT; + } + partl = *getpos++; + if (getpos + partl > getend) { + ncp_unlock_conn(conn); + return NCPL_ET_REPLY_FORMAT; + } + putpos -= partl+1; + if (putpos < name) { + ncp_unlock_conn(conn); + return NCPL_ET_NAMETOOLONG; + } + memcpy(putpos + 1, getpos, partl); + *putpos = partl; + getpos += partl; + } + ncp_unlock_conn(conn); + *begin = putpos; + return 0; +} + +static long +ncp_ns_NW_to_path(char* name, size_t maxnamelen, + const unsigned char* encpath, const unsigned char* encend) +{ + char* nameend = name + maxnamelen; + int pos = 0; + + while (encpath < encend) { + int namel; + + if (pos >= 2) { + if (name >= nameend) return NCPL_ET_NAMETOOLONG; + *name++ = '/'; + } + namel = *encpath++; + if (encpath + namel > encend) { + return NCPL_ET_REPLY_FORMAT; + } + if (name + namel >= nameend) { + return NCPL_ET_NAMETOOLONG; + } + memcpy(name, encpath, namel); + encpath += namel; + name += namel; + if (pos == 0) { + if (name >= nameend) return NCPL_ET_NAMETOOLONG; + *name++ = ':'; + } + pos++; + } + if (name >= nameend) return NCPL_ET_NAMETOOLONG; + *name = 0; + return 0; +} + +long +ncp_ns_get_full_name(struct ncp_conn* conn, __u8 src_ns, __u8 dst_ns, + int dirstyle, __u8 vol_num, __u32 dir_base, + const unsigned char* encpath, size_t pathlen, + char* name, size_t maxnamelen) +{ + unsigned char space[1024]; + struct ncpi_gfn_cookies cookie = { 0, -1, -1}; + size_t len = sizeof(space); + long results; + + do { + unsigned char* npos; + + results = ncp_ns_get_full_name_int(conn, src_ns, dst_ns, + dirstyle, vol_num, dir_base, encpath, pathlen, + &cookie, space, len, &npos); + if (results) return results; + len = npos-space; + } while (cookie.cookie2 != -1); + return ncp_ns_NW_to_path(name, maxnamelen, space+len, space+sizeof(space)); +} + +#endif /* not __MAKE_SULIB__ */ + +#ifdef __MAKE_SULIB__ +int +ncp_path_to_NW_format(const char* path, unsigned char* buff, int buffsize) +{ + int components = 0; + unsigned char* pos = buff+1; + buffsize--; + + if (path != NULL) { + if (*path == '/') path++; /* skip optional leading / */ + while (*path) { + const char *c; + const char *d; + int l; + + c = strchr(path, '/'); + if (!c) c=path+strlen(path); + l = c-path; + if (components == 0) { /* volume */ + d = strchr(path, ':'); /* can be separated by :, / or :/ */ + if (!d) d=path+strlen(path); + if (d < c) { + c=d; + if (c[1]=='/') c++; /* skip optional / after : */ + l = d-path; + } + } + if (l == 0) + return -EINVAL; + if (l > 255) + return -ENAMETOOLONG; + if ((l != 1)||(*path!='.')) { + if (buffsize <= l) return -ENOBUFS; + buffsize -= l+1; + *pos++ = l; + memcpy(pos, path, l); + pos+=l; + components++; + } + path = c; + if (!*c) break; + path++; + } + } + *buff = components; + return pos-buff; +} + +long +ncp_obtain_file_or_subdir_info2(struct ncp_conn *conn, + __u8 source_ns, __u8 target_ns, + __u16 search_attribs, __u32 rim, + int dir_style, + __u8 vol, __u32 dirent, const unsigned char *path, + int pathlen, struct nw_info_struct *target) +{ + long result; + + ncp_init_request(conn); + ncp_add_byte(conn, 6); + ncp_add_byte(conn, source_ns); + ncp_add_byte(conn, target_ns); + ncp_add_word_lh(conn, search_attribs); + ncp_add_dword_lh(conn, rim); + ncp_add_handle_path2(conn, vol, dirent, dir_style, path, pathlen); + + if ((result = ncp_request(conn, 87)) != 0) + { + ncp_unlock_conn(conn); + return result; + } + ncp_extract_file_info(ncp_reply_data(conn, 0), target); + ncp_unlock_conn(conn); + return 0; +} + +#endif /* __MAKE_SULIB__ */ diff --git a/lib/ncplib_err.et b/lib/ncplib_err.et index 2eee6e3..233ae5d 100644 --- a/lib/ncplib_err.et +++ b/lib/ncplib_err.et @@ -42,4 +42,16 @@ ec NCPL_ET_NO_IPX, ec NCPL_ET_NO_NCPFS_FILE, "The file is probably not on a ncpfs mounted directory" -end \ No newline at end of file +ec NCPL_ET_REPLY_FORMAT, + "The reply packet is not in the expected format" + +ec NCPL_ET_REPLY_TOO_LARGE, + "The reply packet/message is too large for the allocated buffer" + +ec NCPL_ET_SIGNATURE_FAILED, + "Packet signature initializing failed" + +ec NCPL_ET_TRANSPORT_UNKNOWN, + "Unknown transport type" + +end diff --git a/lib/ncpsign.c b/lib/ncpsign.c new file mode 100644 index 0000000..880e515 --- /dev/null +++ b/lib/ncpsign.c @@ -0,0 +1,103 @@ +#ifdef SIGNATURES +/* + * ncpsign.c + * + * Arne de Bruijn (arne@knoware.nl), 1997 + * + */ + +#include +#include "ncplib.h" +#include "ncpsign.h" + +#define rol32(i,c) (((((i)&0xffffffff)<>(32-c))) +/* i386: 32-bit, little endian, handles mis-alignment */ +#ifdef __i386__ +#define GET_LE32(p) (*(const int *)(p)) +#define PUT_LE32(p,v) { *(int *)(p)=v; } +#else +#define GET_LE32(p) DVAL_LH(p,0) +#define PUT_LE32(p,v) DSET_LH(p,0,v) +#endif + +#define min(a,b) ((a)<(b)?(a):(b)) + +static void nwsign(const char *r_data1, char *r_data2, char *outdata) { + int i; + unsigned int w0,w1,w2,w3; + static int rbit[4]={0, 2, 1, 3}; +#ifdef __i386__ + unsigned int *data2=(int *)r_data2; +#else + unsigned int data2[16]; + for (i=0;i<16;i++) + data2[i]=GET_LE32(r_data2+(i<<2)); +#endif + w0=GET_LE32(r_data1); + w1=GET_LE32(r_data1+4); + w2=GET_LE32(r_data1+8); + w3=GET_LE32(r_data1+12); + for (i=0;i<16;i+=4) { + w0=rol32(w0 + ((w1 & w2) | ((~w1) & w3)) + data2[i+0],3); + w3=rol32(w3 + ((w0 & w1) | ((~w0) & w2)) + data2[i+1],7); + w2=rol32(w2 + ((w3 & w0) | ((~w3) & w1)) + data2[i+2],11); + w1=rol32(w1 + ((w2 & w3) | ((~w2) & w0)) + data2[i+3],19); + } + for (i=0;i<4;i++) { + w0=rol32(w0 + (((w2 | w3) & w1) | (w2 & w3)) + 0x5a827999 + data2[i+0],3); + w3=rol32(w3 + (((w1 | w2) & w0) | (w1 & w2)) + 0x5a827999 + data2[i+4],5); + w2=rol32(w2 + (((w0 | w1) & w3) | (w0 & w1)) + 0x5a827999 + data2[i+8],9); + w1=rol32(w1 + (((w3 | w0) & w2) | (w3 & w0)) + 0x5a827999 + data2[i+12],13); + } + for (i=0;i<4;i++) { + w0=rol32(w0 + ((w1 ^ w2) ^ w3) + 0x6ed9eba1 + data2[rbit[i]+0],3); + w3=rol32(w3 + ((w0 ^ w1) ^ w2) + 0x6ed9eba1 + data2[rbit[i]+8],9); + w2=rol32(w2 + ((w3 ^ w0) ^ w1) + 0x6ed9eba1 + data2[rbit[i]+4],11); + w1=rol32(w1 + ((w2 ^ w3) ^ w0) + 0x6ed9eba1 + data2[rbit[i]+12],15); + } + PUT_LE32(outdata,(w0+GET_LE32(r_data1)) & 0xffffffff); + PUT_LE32(outdata+4,(w1+GET_LE32(r_data1+4)) & 0xffffffff); + PUT_LE32(outdata+8,(w2+GET_LE32(r_data1+8)) & 0xffffffff); + PUT_LE32(outdata+12,(w3+GET_LE32(r_data1+12)) & 0xffffffff); +} + +/* + * Initialize packet signatures + * The first 16 bytes of logindata are the shuffled password, + * the last 8 bytes the encryption key as received from the server. + */ +void sign_init(const char *logindata, char *sign_root) { + static const char initlast[16]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}; + static const char *initdata="Authorized NetWare Client"; + char msg[64]; + char hash[16]; + + memset(msg, 0, 64); + memcpy(msg, logindata, 24); + memcpy(msg + 24, initdata, 25); + nwsign(initlast, msg, hash); + + memcpy(sign_root, hash, 8); +} + +/* + * Make a signature for the current packet and add it at the end of the + * packet. + */ +void sign_packet(struct ncp_conn *conn, int *size) { + char data[64]; + + memset(data,0,64); + memcpy(data,conn->sign_root,8); + PUT_LE32(data+8,(*size)); + memcpy(data+12,conn->packet+sizeof(struct ncp_request_header)-1, + min((*size)-sizeof(struct ncp_request_header)+1,52)); + + nwsign(conn->sign_last,data,conn->sign_last); + + memcpy(conn->packet+(*size),conn->sign_last,8); + (*size)+=8; +} +#endif diff --git a/lib/ndscrypt.c b/lib/ndscrypt.c new file mode 100644 index 0000000..1420d4e --- /dev/null +++ b/lib/ndscrypt.c @@ -0,0 +1,297 @@ +/* + NDS client for ncpfs + Copyright (C) 1997 Arne de Bruijn + + 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 +#include "ndscrypt.h" +#include "ncplib.h" + +static unsigned int rol16(unsigned int i, int c) { + return ((i << c) & 65535) | ((unsigned int)(i & 65535) >> (16 - c)); +} +static unsigned int ror16(unsigned int i, int c) { + return ((unsigned int)(i & 65535) >> c) | ((i << (16 - c)) & 65535); +} + +static unsigned char nwcryptdata[256]={ + 0xD9,0x78,0xF9,0xC4,0x19,0xDD,0xB5,0xED,0x28,0xE9,0xFD,0x79, + 0x4A,0xA0,0xD8,0x9D,0xC6,0x7E,0x37,0x83,0x2B,0x76,0x53,0x8E, + 0x62,0x4C,0x64,0x88,0x44,0x8B,0xFB,0xA2,0x17,0x9A,0x59,0xF5, + 0x87,0xB3,0x4F,0x13,0x61,0x45,0x6D,0x8D,0x09,0x81,0x7D,0x32, + 0xBD,0x8F,0x40,0xEB,0x86,0xB7,0x7B,0x0B,0xF0,0x95,0x21,0x22, + 0x5C,0x6B,0x4E,0x82,0x54,0xD6,0x65,0x93,0xCE,0x60,0xB2,0x1C, + 0x73,0x56,0xC0,0x14,0xA7,0x8C,0xF1,0xDC,0x12,0x75,0xCA,0x1F, + 0x3B,0xBE,0xE4,0xD1,0x42,0x3D,0xD4,0x30,0xA3,0x3C,0xB6,0x26, + 0x6F,0xBF,0x0E,0xDA,0x46,0x69,0x07,0x57,0x27,0xF2,0x1D,0x9B, + 0xBC,0x94,0x43,0x03,0xF8,0x11,0xC7,0xF6,0x90,0xEF,0x3E,0xE7, + 0x06,0xC3,0xD5,0x2F,0xC8,0x66,0x1E,0xD7,0x08,0xE8,0xEA,0xDE, + 0x80,0x52,0xEE,0xF7,0x84,0xAA,0x72,0xAC,0x35,0x4D,0x6A,0x2A, + 0x96,0x1A,0xD2,0x71,0x5A,0x15,0x49,0x74,0x4B,0x9F,0xD0,0x5E, + 0x04,0x18,0xA4,0xEC,0xC2,0xE0,0x41,0x6E,0x0F,0x51,0xCB,0xCC, + 0x24,0x91,0xAF,0x50,0xA1,0xF4,0x70,0x39,0x99,0x7C,0x3A,0x85, + 0x23,0xB8,0xB4,0x7A,0xFC,0x02,0x36,0x5B,0x25,0x55,0x97,0x31, + 0x2D,0x5D,0xFA,0x98,0xE3,0x8A,0x92,0xAE,0x05,0xDF,0x29,0x10, + 0x67,0x6C,0xBA,0xC9,0xD3,0x00,0xE6,0xCF,0xE1,0x9E,0xA8,0x2C, + 0x63,0x16,0x01,0x3F,0x58,0xE2,0x89,0xA9,0x0D,0x38,0x34,0x1B, + 0xAB,0x33,0xFF,0xB0,0xBB,0x48,0x0C,0x5F,0xB9,0xB1,0xCD,0x2E, + 0xC5,0xF3,0xDB,0x47,0xE5,0xA5,0x9C,0x77,0x0A,0xA6,0x20,0x68, + 0xFE,0x7F,0xC1,0xAD}; + +#if 0 +static unsigned char shuffle_table[32]= + {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 unsigned char shuffle_table2[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}; +#endif + +static unsigned char nwhashdata[256] = + {0xBD,0x56,0xEA,0xF2,0xA2,0xF1,0xAC,0x2A,0xB0,0x93,0xD1,0x9C, + 0x1B,0x33,0xFD,0xD0,0x30,0x04,0xB6,0xDC,0x7D,0xDF,0x32,0x4B, + 0xF7,0xCB,0x45,0x9B,0x31,0xBB,0x21,0x5A,0x41,0x9F,0xE1,0xD9, + 0x4A,0x4D,0x9E,0xDA,0xA0,0x68,0x2C,0xC3,0x27,0x5F,0x80,0x36, + 0x3E,0xEE,0xFB,0x95,0x1A,0xFE,0xCE,0xA8,0x34,0xA9,0x13,0xF0, + 0xA6,0x3F,0xD8,0x0C,0x78,0x24,0xAF,0x23,0x52,0xC1,0x67,0x17, + 0xF5,0x66,0x90,0xE7,0xE8,0x07,0xB8,0x60,0x48,0xE6,0x1E,0x53, + 0xF3,0x92,0xA4,0x72,0x8C,0x08,0x15,0x6E,0x86,0x00,0x84,0xFA, + 0xF4,0x7F,0x8A,0x42,0x19,0xF6,0xDB,0xCD,0x14,0x8D,0x50,0x12, + 0xBA,0x3C,0x06,0x4E,0xEC,0xB3,0x35,0x11,0xA1,0x88,0x8E,0x2B, + 0x94,0x99,0xB7,0x71,0x74,0xD3,0xE4,0xBF,0x3A,0xDE,0x96,0x0E, + 0xBC,0x0A,0xED,0x77,0xFC,0x37,0x6B,0x03,0x79,0x89,0x62,0xC6, + 0xD7,0xC0,0xD2,0x7C,0x6A,0x8B,0x22,0xA3,0x5B,0x05,0x5D,0x02, + 0x75,0xD5,0x61,0xE3,0x18,0x8F,0x55,0x51,0xAD,0x1F,0x0B,0x5E, + 0x85,0xE5,0xC2,0x57,0x63,0xCA,0x3D,0x6C,0xB4,0xC5,0xCC,0x70, + 0xB2,0x91,0x59,0x0D,0x47,0x20,0xC8,0x4F,0x58,0xE0,0x01,0xE2, + 0x16,0x38,0xC4,0x6F,0x3B,0x0F,0x65,0x46,0xBE,0x7E,0x2D,0x7B, + 0x82,0xF9,0x40,0xB5,0x1D,0x73,0xF8,0xEB,0x26,0xC7,0x87,0x97, + 0x25,0x54,0xB1,0x28,0xAA,0x98,0x9D,0xA5,0x64,0x6D,0x7A,0xD4, + 0x10,0x81,0x44,0xEF,0x49,0xD6,0xAE,0x2E,0xDD,0x76,0x5C,0x2F, + 0xA7,0x1C,0xC9,0x09,0x69,0x9A,0x83,0xCF,0x29,0x39,0xB9,0xE9, + 0x4C,0xFF,0x43,0xAB}; + + +void nwencrypt(const unsigned short *cryptbuf, const char *in, char *out) { + int i, j; + register unsigned int i1, i2, i3, i4; + const unsigned short *p; + + i1 = WVAL_LH(in, 0); + i2 = WVAL_LH(in, 2); + i3 = WVAL_LH(in, 4); + i4 = WVAL_LH(in, 6); + p = cryptbuf; + for (j = 3; j; j--) { + for (i = (j == 2) ? 6 : 5; i; i--) { + i1 = rol16(i1 + (*p++) + (i4 & i3) + (~i4 & i2), 1); + i2 = rol16(i2 + (*p++) + (i1 & i4) + (~i1 & i3), 2); + i3 = rol16(i3 + (*p++) + (i2 & i1) + (~i2 & i4), 3); + i4 = rol16(i4 + (*p++) + (i3 & i2) + (~i3 & i1), 5); + } + if (j > 1) { + i1 += cryptbuf[i4 & 63]; + i2 += cryptbuf[i1 & 63]; + i3 += cryptbuf[i2 & 63]; + i4 += cryptbuf[i3 & 63]; + } + } + WSET_LH(out, 0, i1); + WSET_LH(out, 2, i2); + WSET_LH(out, 4, i3); + WSET_LH(out, 6, i4); +} + +void nwdecrypt(const unsigned short *cryptbuf, const char *in, char *out) { + int i, j; + const unsigned short *p; + register unsigned int i1, i2, i3, i4; + + i1 = WVAL_LH(in, 0); + i2 = WVAL_LH(in, 2); + i3 = WVAL_LH(in, 4); + i4 = WVAL_LH(in, 6); + p = cryptbuf + 64; + for (j = 3; j; j--) { + for (i = (j == 2) ? 6 : 5; i; i--) { + i4 = ror16(i4, 5) - (~i3 & i1) - (i3 & i2) - (*--p); + i3 = ror16(i3, 3) - (~i2 & i4) - (i2 & i1) - (*--p); + i2 = ror16(i2, 2) - (~i1 & i3) - (i1 & i4) - (*--p); + i1 = ror16(i1, 1) - (~i4 & i2) - (i4 & i3) - (*--p); + } + if (j > 1) { + i4 -= cryptbuf[i3 & 63]; + i3 -= cryptbuf[i2 & 63]; + i2 -= cryptbuf[i1 & 63]; + i1 -= cryptbuf[i4 & 63]; + } + } + WSET_LH(out, 0, i1); + WSET_LH(out, 2, i2); + WSET_LH(out, 4, i3); + WSET_LH(out, 6, i4); +} + +void nwcryptinit(unsigned short *scryptbuf, const char *key) { + int i; + unsigned char cryptbuf[128], *p; + + memcpy(cryptbuf, key, 8); + for (i = 0; i < 120; i++) + cryptbuf[i + 8] = + nwcryptdata[(unsigned char)(cryptbuf[i] + cryptbuf[i + 7]) & 255]; + cryptbuf[128 - 8] = nwcryptdata[(unsigned char)cryptbuf[128 - 8] & 255]; + for (i = 127 - 8; i >= 0; i--) + cryptbuf[i] = nwcryptdata[(unsigned char)cryptbuf[i + 1] ^ + (unsigned char)cryptbuf[i + 8]]; + for (i = 0, p = cryptbuf; i < 64; i++, p += 2) + scryptbuf[i] = (*p) | (*(p+1)) << 8; +} + +void nwencryptblock(const char *cryptkey, const char *buf, int buflen, + char *outbuf) { + int i; + char nhash[8]; + unsigned short cryptbuf[64]; + + nwcryptinit(cryptbuf, cryptkey); + memset(nhash, 0, 8); + while (buflen >= 8) { + for (i = 0; i < 8; i++, buf++) + nhash[i] ^= *buf; + nwencrypt(cryptbuf, nhash, nhash); + memcpy(outbuf, nhash, 8); + outbuf += 8; + buflen -= 8; + } + memset(cryptbuf, 0, sizeof(cryptbuf)); +} + +void nwdecryptblock(const char *cryptkey, const char *buf, int buflen, + char *outbuf) { + int i; + char nhash[16], *p; + unsigned short cryptbuf[64]; + + nwcryptinit(cryptbuf, cryptkey); + memset(nhash, 0, 16); + p = nhash; + while (buflen >= 8) { + memcpy(p, buf, 8); + p = nhash + 8 - (p - nhash); + nwdecrypt(cryptbuf, buf, outbuf); + for (i = 0; i < 8; i++, outbuf++) + *outbuf ^= p[i]; + buf += 8; + buflen -= 8; + } + memset(cryptbuf, 0, sizeof(cryptbuf)); +} + +void nwhash1(char *hash, int hashlen, const char *data, int datalen) { + unsigned char *hp, *hp1, *hend, c; + const unsigned char *dp; + + hp1 = (hp = (unsigned char *)hash) + 1; + hend = hp + hashlen; + dp = (const unsigned char *)data; + while (datalen--) { + *hp = nwhashdata[*hp1 ^ *hp] ^ *dp++; + hp = hp1++; + if (hp1 == hend) + hp1 = (unsigned char *)hash; + } + while (hp-- > (unsigned char *)hash) { + hp1 = (unsigned char *)hash; + c = *hp1++; + while (*(hp1 - 1) = *hp1, ++hp1 < (unsigned char *)hash + hashlen); + *(hp1 - 1) = c; + } +} + +void nwhash2(char *hashbuf, char c) { + int i, j; + char *p = hashbuf + hashbuf[0x40]; + + p[0x20] = p[0x00] ^ (p[0x10] = c); + hashbuf[0x41] = (p[0x30] ^= nwhashdata[(unsigned char)(c ^ hashbuf[0x41])]); + if (!(hashbuf[0x40] = (hashbuf[0x40] + 1) & 15)) { + c = 0; + for (i = 18; i; i--) + for (j = 48, p = hashbuf; j; j--) + c = (*(p++) ^= nwhashdata[((unsigned char)c + j) & 255]); + } +} + +void nwhash2block(char *hashbuf, const char *data, int datalen) { + while (datalen--) + nwhash2(hashbuf, *data++); +} + +void nwhash2end(char *hashbuf) { + int i, j; + + for(j = i = 16 - hashbuf[0x40]; j; j--) + nwhash2(hashbuf, i); + for(i = 0x30; i < 0x40; i++) + nwhash2(hashbuf, hashbuf[i]); +} + +#if 0 +void shuffle(const char *objid, const char *pwd, char *out) { + unsigned char temp[32]; + int i, j, k; + i = strlen(pwd); + memset(temp, 0, 32); + for (j = 0; j < i; j++) + temp[j & 31] ^= pwd[j]; + if (i) + for (j = i; j < 32; j += i) { + temp[j++] = shuffle_table[j]; + k = 32 - j; + memcpy(temp + j, pwd, (k > i) ? i : k); + } + for (i = 0; i < 32; i++) + temp[i] ^= objid[i & 3]; + j = 0; + for (k = 0; k < 2; k++) + for (i = 0; i < 32; i++) + (char)j += temp[i] = (temp[i] + j) ^ + (temp[(i + j) & 31] - shuffle_table[i]); + for (i = 0; i < 16; i++) + out[i] = shuffle_table2[temp[i * 2]] | + (shuffle_table2[temp[i * 2 + 1]] << 4); +} +#endif + diff --git a/lib/ndscrypt.h b/lib/ndscrypt.h new file mode 100644 index 0000000..07fc788 --- /dev/null +++ b/lib/ndscrypt.h @@ -0,0 +1,47 @@ +/* + NDS client for ncpfs + Copyright (C) 1997 Arne de Bruijn + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _NDSCRYPT_H +#define _NDSCRYPT_H + +#include + +void nwencrypt(const unsigned short *cryptbuf, const char *in, char *out); +void nwdecrypt(const unsigned short *cryptbuf, const char *in, char *out); +void nwcryptinit(unsigned short *scryptbuf, const char *key); +void nwencryptblock(const char *cryptkey, const char *buf, int buflen, + char *outbuf); +void nwdecryptblock(const char *cryptkey, const char *buf, int buflen, + char *outbuf); + +#define nwhash1init(hash, hashlen) memset(hash, 0, hashlen) +void nwhash1(char *hash, int hashlen, const char *data, int datalen); + +#define nwhash2init(hashbuf) memset(hashbuf, 0, 0x42) +void nwhash2(char *hashbuf, char c); +void nwhash2block(char *hashbuf, const char *data, int datalen); +void nwhash2end(char *hashbuf); + +#if 0 +void shuffle(const char *objid, const char *pwd, char *out); +#else +void shuffle(const char *objid, const char *pwd, int buflen, char *out); +#endif + +#endif /* _NDSCRYPT_H */ diff --git a/lib/ndslib.c b/lib/ndslib.c new file mode 100644 index 0000000..51b88cd --- /dev/null +++ b/lib/ndslib.c @@ -0,0 +1,1253 @@ +/* + NDS client for ncpfs + Copyright (C) 1997 Arne de Bruijn + + 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. +*/ + +#define RANDBUF /* if defined: read random data once from /dev/urandom */ +/*#define ERR_MSG*/ /* if defined: show error messages in nds_login_auth */ + +#include +#include +#include +#ifdef ERR_MSG +#include +#endif +#include +#include +#ifdef RANDBUF +#include +#endif +#include "ncplib.h" +#include "ncplib_err.h" +#include "ndslib.h" +#include "ndscrypt.h" + +#define USUALS +typedef u_int32_t word32; +typedef u_int16_t word16; +typedef unsigned char boolean; + +#include "mpilib.h" +#include +#include +#include "kernel/ipx.h" +#include +#include "ndslib.h" + +int bindery_only = 0; + +static int buf_get_dword_lh(char **buf, char *bufend, u_int32_t *v) { + if ((*buf) + 4 <= bufend) { + if (v) + *v = DVAL_LH(*buf, 0); + (*buf) += 4; + return 0; + } else + return -1; +} + +static int buf_get_lbuf(char **buf, char *bufend, char *out, int outmax, + int *outlen) { + int i, j; + + if ((!buf_get_dword_lh(buf, bufend, &i)) && (*buf + i <= bufend)) { + j = i; + if (out) { + if (j > outmax) j = outmax; + memcpy(out, *buf, j); + } + if (outlen) *outlen = j; + *buf += (i + 3) & (~3); + return 0; + } else + return -1; +} + +static int buf_put_word_lh2(char **buf, char *bufend, u_int16_t v) { + if ((*buf) + 2 <= bufend) { + WSET_LH(*buf, 0, v); + *buf += 2; + return 0; + } else + return -1; +} + +static int buf_put_dword_lh(char **buf, char *bufend, u_int32_t v) { + if ((buf) && ((*buf) + 4 <= bufend)) { + DSET_LH(*buf, 0, v); + *buf += 4; + return 0; + } else + return -1; +} + +static int buf_put_dword_hl(char **buf, char *bufend, u_int32_t v) { + if ((*buf) + 4 <= bufend) { + DSET_HL(*buf, 0, v); + *buf += 4; + return 0; + } else + return -1; +} + +static int buf_put_lbuf(char **buf, char *bufend, const char *databuf, + size_t buflen) { + if ((!buf_put_dword_lh(buf, bufend, buflen)) && + (*buf + buflen <= bufend)) { + if (!buflen) return 0; /* explicitly allow {NULL, 0} buffer */ + if (!databuf) return -1; + memcpy(*buf, databuf, buflen); + (*buf) += buflen; + while (buflen++ & 3) + *(*buf)++ = 0; + return 0; + } else + return -1; +} + +static int buf_put_buf(char **buf, char *bufend, const char *databuf, + size_t buflen) { + if ((databuf) && (*buf + buflen <= bufend)) { + memcpy(*buf, databuf, buflen); + (*buf) += buflen; + while (buflen++ & 3) + *(*buf)++ = 0; + return 0; + } else + return -1; +} + +static int buf_put_unistr(char **buf, char *bufend, const uni_char *str) { + int i = (strlen_u(str) + 1) * 2; + + if ((str) && (!buf_put_dword_lh(buf, bufend, i)) && + (*buf + i <= bufend)) { + memcpy(*buf, str, i); + (*buf) += i; + while (i++ & 3) + *(*buf)++ = 0; + return 0; + } else + return -1; +} + +static int buf_get_dword_hl(char **buf, char *bufend, u_int32_t *v) { + if ((*buf) + 4 <= bufend) { + if (v) { + *v = DVAL_HL(*buf, 0); + } + (*buf) += 4; + return 0; + } else + return -1; +} + +static int buf_get_word_lh(char **buf, char *bufend, u_int16_t *v) { + if (((*buf) + 2 <= bufend)) { + if (v) { + *v = WVAL_LH(*buf, 0); + } + (*buf) += 4; + return 0; + } else + return -1; +} + +static int buf_get_word_lh2(char **buf, char *bufend, u_int16_t *v) { + if (((*buf) + 2 <= bufend)) { + if (v) { + *v = WVAL_LH(*buf, 0); + } + (*buf) += 2; + return 0; + } else + return -1; +} + +static int buf_get_lbuf_alloc(char **buf, char *bufend, + char **outbuf, int *bufsize) { + int i, err = 0; + + if ((!buf_get_dword_lh(buf, bufend, &i)) && (*buf + i <= bufend)) { + if (outbuf) { + if (((*outbuf) = malloc(i))) + memcpy(*outbuf, *buf, i); + else + err = ENOMEM; + } + (*buf) += (i + 3) & (~3); + if (bufsize) *bufsize = i; + return err; + } else { + if (outbuf) *outbuf = NULL; + if (bufsize) *bufsize = 0; + return -1; + } +} + +static int buf_get_buf(char **buf, char *bufend, char *outbuf, size_t bufsize) { + if (*buf + bufsize <= bufend) { + if (outbuf) memcpy(outbuf, *buf, bufsize); + *buf += (bufsize + 3) & (~3); + return 0; + } else + return -1; +} + +int strlen_u(const uni_char *s) { + int i = 0; + while (*s++) i++; + return i; +} + +void strcpy_uc(char *d, const uni_char *s) { + while ((*d++ = *s++)); +} + +void strcpy_cu(uni_char *d, const char *s) { + while ((*d++ = *s++)); +} + +long nds_get_server_name(struct ncp_conn *conn, uni_char **server_name) { + long err; + int outlen; + char *p, *pend, *outbuf; + + if (!(outbuf = malloc(4096))) + return ENOMEM; + if (server_name) *server_name = NULL; + if ((err = ncp_send_nds_frag(conn, 53, NULL, 0, + outbuf, 4096, &outlen)) == 0) { + pend = (p = outbuf) + outlen; + if (buf_get_dword_lh(&p, pend, &outlen)) + err = NCPL_ET_REPLY_FORMAT; + else { + if (!((*server_name) = malloc(outlen))) + err = ENOMEM; + else + memcpy(*server_name, p, outlen); + } + } + free(outbuf); + return err; +} + +long nds_get_tree_name(struct ncp_conn *conn, char *name, int name_buf_len) { + char buf[128]; + int size; + long err; + char *p, *pend; + + if (bindery_only) return -1; + + if (!(err = ncp_send_nds(conn, 1, "\0\0\0", 3, buf, sizeof(buf), + &size))) { + p = buf + 4; + pend = buf + size; + if (buf_get_lbuf(&p, pend, name, name_buf_len, &size)) + return NCPL_ET_REPLY_FORMAT; + if (name) { + p = name + size - 1; + while ((p >= name) && (!*p)) + p--; + while ((p >= name) && (*p == '_')) + p--; + *(p + 1) = 0; + } + } + return err; +} + +/* for login */ +long nds_resolve_name(struct ncp_conn *conn, int flags, uni_char *entry_name, + int *entry_id, int *remote, struct sockaddr *serv_addr, size_t *addr_len) { + char *buf, *p, *pend, addr_buf[12]; + long err; + int i; + + if (!(buf = malloc(4096))) + return ENOMEM; + pend = (p = buf) + 2048; + buf_put_dword_lh(&p, pend, 0); + buf_put_dword_lh(&p, pend, flags); + buf_put_dword_lh(&p, pend, 0); + buf_put_unistr(&p, pend, entry_name); + buf_put_dword_lh(&p, pend, 1); + buf_put_dword_lh(&p, pend, 0); + buf_put_dword_lh(&p, pend, 1); + buf_put_dword_lh(&p, pend, 0); + if ((err = ncp_send_nds_frag(conn, 1, buf, p - buf, buf + 2048, 2048, + &i)) == 0) { + pend = (p = buf + 2048) + i; + if (buf_get_dword_lh(&p, pend, &i) || (i < 0) || (i > 2)) + err = NCPL_ET_REPLY_FORMAT; + else if (i == 1) { + if (remote) *remote = 0; + if (buf_get_dword_hl(&p, pend, entry_id)) + err = NCPL_ET_REPLY_FORMAT; + } else { + if (remote) *remote = 1; + if ((!serv_addr) || (!addr_len)) { + free(buf); + return 0; + } + if (buf_get_dword_hl(&p, pend, entry_id) || + buf_get_dword_lh(&p, pend, &i) || (i != 0) || + buf_get_dword_lh(&p, pend, &i) || (i == 0) || + buf_get_dword_lh(&p, pend, &i)) + err = NCPL_ET_REPLY_FORMAT; + else if (i != 0) /* no ipx? */ + err = NCPL_ET_TRANSPORT_UNKNOWN; + else if (buf_get_dword_lh(&p, pend, &i) || (i != 12) || + buf_get_buf(&p, pend, addr_buf, 12)) + err = NCPL_ET_REPLY_FORMAT; + else if (*addr_len < sizeof(struct sockaddr_ipx)) + err = EINVAL; + else { + ((struct sockaddr_ipx *)serv_addr)->sipx_family = AF_IPX; + ((struct sockaddr_ipx *)serv_addr)->sipx_type = NCP_PTYPE; + /* buf and addr both in network order */ + memcpy(&((struct sockaddr_ipx *)serv_addr)->sipx_network, + addr_buf, 4); + memcpy(((struct sockaddr_ipx *)serv_addr)->sipx_node, + addr_buf + 4, 6); + memcpy(&((struct sockaddr_ipx *)serv_addr)->sipx_port, + addr_buf + 10, 2); + *addr_len = sizeof(struct sockaddr_ipx); + } + } + } + free(buf); + return err; +} + +long nds_readentryname(struct ncp_conn *conn, int obj_id, + uni_char **name, int *namelen) { + char reqbuf[16], *p, *pend, *buf; + uni_char *p2; + long err; + int outlen; + + if (name) *name = NULL; + if (namelen) *namelen = 0; + pend = (p = reqbuf) + 16; + buf_put_dword_lh(&p, pend, 2); + buf_put_dword_lh(&p, pend, 0); + buf_put_dword_lh(&p, pend, 0x281d); + buf_put_dword_hl(&p, pend, obj_id); + if (!(buf = malloc(4096))) + return ENOMEM; + if ((err = ncp_send_nds_frag(conn, 2, reqbuf, 16, buf, 4096, &outlen))) { + free(buf); + return err; + } + pend = (p = buf) + outlen; + p += 16; + buf_get_lbuf(&p, pend, NULL, 0, NULL); + if ((buf_get_dword_lh(&p, pend, &outlen)) || + (outlen > pend - p)) { + free(buf); + return NCPL_ET_REPLY_FORMAT; + } + if (name) { + if (!(p2 = malloc(outlen))) { + free(buf); + return ENOMEM; + } + memcpy(p2, p, outlen); + *name = p2; + } + if (namelen) *namelen = outlen; + free(buf); + return 0; +} + +long nds_read(struct ncp_conn *conn, int obj_id, uni_char *propname, + char **outbuf, int *outlen) { + long err; + char *buf, *p, *pend; + int n1, n2, n3, n4, n5; + + if (outbuf) *outbuf = NULL; + if (outlen) *outlen = 0; + if (!(buf = malloc(4096))) + return ENOMEM; + pend = (p = buf) + 2048; + buf_put_dword_lh(&p, pend, 0); + buf_put_dword_lh(&p, pend, -1L); + buf_put_dword_hl(&p, pend, obj_id); + buf_put_dword_lh(&p, pend, 1); + buf_put_dword_lh(&p, pend, 0); + buf_put_dword_lh(&p, pend, 1); + buf_put_unistr(&p, pend, propname); + if (!(err = ncp_send_nds_frag(conn, 3, buf, p - buf, + buf + 2048, 2048, &n1))) { + pend = (p = (buf + 2048)) + n1; + if (!(err = buf_get_dword_lh(&p, pend, &n1)) && + !(err = buf_get_dword_lh(&p, pend, &n2)) && + !(err = buf_get_dword_lh(&p, pend, &n3)) && + !(err = buf_get_dword_lh(&p, pend, &n4)) && + !(err = buf_get_lbuf(&p, pend, NULL, 0, NULL)) && + !(err = buf_get_dword_lh(&p, pend, &n5))) { + if ((n1 != -1) || (n2 != 1) || (n3 != 1) || + (n4 != 9) || (n5 != 1)) + err = -1; + else + err = buf_get_lbuf_alloc(&p, pend, outbuf, outlen); + } + } + free(buf); + return err; +} + +#ifdef RANDBUF +#define RANDBUFSIZE 1236 /* total size of all fillrandom's for login+auth */ +char global_randbuf[RANDBUFSIZE]; +char *g_rndp = global_randbuf + RANDBUFSIZE; + +void fillrandom(char *buf, int buflen) { + int fh,i; + + do { + if (g_rndp == global_randbuf + RANDBUFSIZE) { + if ((fh = open("/dev/urandom", O_RDONLY)) >=0) { + read(fh, global_randbuf, RANDBUFSIZE); + close(fh); + } else { + g_rndp = global_randbuf; + while (g_rndp - global_randbuf < RANDBUFSIZE) + *(g_rndp++) = rand() / ((((unsigned)RAND_MAX)+255) / 256); + } + g_rndp = global_randbuf; + } + if ((i = RANDBUFSIZE - (g_rndp - global_randbuf)) > buflen) i = buflen; + memcpy(buf, g_rndp, i); + buf += i; + g_rndp += i; + buflen -= i; + } while (buflen); +} +#else +void fillrandom(char *buf, int buflen) { + int fh; + char *p; + + if (((fh = open("/dev/urandom", O_RDONLY)) >= 0) { + read(fh, buf, buflen); + close(fh); + } else { + p = buf; + while (p - buf < buflen) + *(p++) = rand() / ((((unsigned)RAND_MAX)+255) / 256); + } +} +#endif + +static int countbits_l(char *buf, int bufsize) { + unsigned char b; + + while ((--bufsize) && (!buf[bufsize])); + b = (unsigned char)buf[bufsize]; + bufsize <<= 3; + while (b) { + b >>= 2; bufsize++; + } + return bufsize; +} + +static void copyfill(void *outbuf, int outsize, const void *inbuf, int insize) { + if (outsize < insize) insize = outsize; + memcpy(outbuf, inbuf, insize); + memset((char *)outbuf + insize, 0, outsize - insize); +} + +static uni_char c_public_key[] = {'P','u','b','l','i','c',' ','K','e','y',0}; + +static char keyprefix[] = {1, 0, 0, 0, 3, 0, 1, 0}; + +static int initkey(const char *key, char **keyptr, int *keylen) { /* 1=ok, 0=err */ + if (!memcmp(key, keyprefix, 8)) { + if (keylen) *keylen = WVAL_LH(key, 8); + if (keyptr) (const char *)(*keyptr) = key + 10; + return 1; + } else + return 0; +} + +static void clearkey(char *key) { + char *keyptr; + int keylen; + if (initkey(key, &keyptr, &keylen)) + memset(key, 0, keylen + 10); +} + +static int findchunk(const char *keyptr, int keylen, const char *chunk, + char **chunkptr) { + const char *p; + + if ((p = keyptr)) { + while (p - keyptr < keylen) { + if ((p[0] != chunk[0]) || (p[1] != chunk[1])) + p += 4 + (unsigned char)p[2] + (unsigned char)p[3]; + else { + if (chunkptr) (const char *)(*chunkptr) = p + 4; + return (unsigned char)p[2] + (unsigned char)p[3]; + } + } + } + if (chunkptr) *chunkptr = NULL; + return 0; +} + +static int checkkey(const char *key) { /* 0 - wrong key, != 0 - key ok */ + char temp[8]; + char *keyptr, *p; + int keylen; + + if ((initkey(key, &keyptr, &keylen)) && + (findchunk(keyptr, keylen, "MA", &p))) { + nwhash1init(temp, 8); + nwhash1(temp, 8, key + 10, WVAL_LH(key, 8) - 20); + return (!memcmp(p, temp, 8)); + } else + return 0; + +} + +static long modexpkey(const char *s_key, char *buf, char *outbuf, int bufsize) { + char *s_keyptr; + int s_keylen, i, nbits, nblocksize; + int err = -1; + unitptr nmod, nexp, nin, nout; + char *p; + + nmod = nexp = nin = nout = NULL; + + if (!initkey(s_key, &s_keyptr, &s_keylen)) + return NCPL_ET_REPLY_FORMAT; + i = findchunk(s_keyptr, s_keylen, "NN", &p); + if (!p) + return NCPL_ET_REPLY_FORMAT; + nbits = countbits_l(p, i); + nblocksize = ((nbits + 31) & (~31)) >> 3; + if (!(nmod = malloc(nblocksize))) + return ENOMEM; + copyfill(nmod, nblocksize, p, i); + i = findchunk(s_keyptr, s_keylen, "EN", &p); + err = NCPL_ET_REPLY_FORMAT; + if (!p) goto end; + err = ENOMEM; + if (!(nexp = malloc(nblocksize))) goto end; + copyfill(nexp, nblocksize, p, i); + if (!(nin = malloc(nblocksize))) goto end; + copyfill(nin, nblocksize, buf, bufsize); + if (!(nout = malloc(nblocksize))) goto end; + set_precision(bytes2units(nblocksize)); + if (mp_modexp((unitptr) nout, (unitptr) nin, (unitptr) nexp, + (unitptr) nmod)) + err = NCPL_ET_REPLY_FORMAT; + else { + copyfill(outbuf, bufsize, nout, nblocksize); + err = 0; + } +end: + if (nout) { mp_init0(nout); free(nout); } + if (nin) { mp_init0(nin); free(nin); } + if (nexp) free(nexp); + if (nmod) free(nmod); + return err; +} + +long get_public_key(struct ncp_conn *conn, long obj_id, char **key) { + char *keybuf, *kptr; + long err; + int keylen, ofs, klen; + + if ((err = nds_read(conn, obj_id, c_public_key, &keybuf, &keylen))) { + return err; + } + ofs = WVAL_LH(keybuf, 10) + 0x1a; + if ((ofs > keylen) || (!initkey(keybuf + ofs, &kptr, &klen)) || + (klen + ofs > keylen) || (!checkkey(keybuf + ofs))) { + err = NCPL_ET_REPLY_FORMAT; + goto err_exit; + } + if (key) { + if (!(kptr = malloc(klen + 10))) { + err = ENOMEM; + goto err_exit; + } + memcpy(kptr, keybuf + ofs, klen + 10); + *key = kptr; + } + err = 0; +err_exit: + free(keybuf); + return err; +} + +char buf2str1[8] = {1,0,0,0,9,0,2,0}; +char buf2str2[16] = {65,0,0,0,1,0,0,0,1,0,9,0,53,0,28,0}; +char buf2str3[8] = {1,0,0,0,1,0,6,0}; +static long rsa_crypt(struct ncp_conn *conn, char *data, int datalen, + long serv_id, char **outp, char *pend) { + char rand[28]; + char hashrand[8], temp[8]; + unsigned short cryptbuf[128]; + char buf2[56]; + int i; + long err; + char *s_key; + char *p; + + if ((*outp + datalen + 108) > pend) + return -1; + if ((err = get_public_key(conn, serv_id, &s_key))) + return err; + + fillrandom(rand, 28); + nwhash1init(hashrand, 8); + for (i = 10; i; i--) + nwhash1(hashrand, 8, rand, 28); + + memset(buf2 + 40, 0, 16); + buf2[0] = 11; + memcpy(buf2 + 1, rand, 28); + memset(buf2 + 29, 11, 11); + nwhash1(buf2 + 40, 5, buf2 + 1, 39); + nwhash1(buf2 + 45, 2, buf2, 45); + fillrandom(buf2 + 47, 5); + + err = modexpkey(s_key, buf2, buf2, 56); + free(s_key); + if (err) + return err; + + buf_put_dword_lh(outp, pend, datalen + 108); + buf_put_buf(outp, pend, buf2str1, sizeof(buf2str1)); + buf_put_dword_lh(outp, pend, datalen + 96); + buf_put_buf(outp, pend, buf2str2, sizeof(buf2str2)); + buf_put_buf(outp, pend, buf2, 56); + buf_put_dword_lh(outp, pend, datalen + 20); + buf_put_buf(outp, pend, buf2str3, sizeof(buf2str3)); + buf_put_dword_lh(outp, pend, (datalen + 8) | (datalen << 16)); + + memset(temp, 3, 3); + nwhash1init(temp + 3, 5); + nwhash1(temp + 3, 5, data, datalen); + nwhash1(temp + 3, 5, temp, 3); + nwencryptblock(hashrand, data, datalen, *outp); + *outp += datalen; + for (i = 0, p = *outp - 8; i < 8; i++, p++) + temp[i] ^= *p; + nwcryptinit(cryptbuf, hashrand); + nwencrypt(cryptbuf, temp, *outp); + *outp += 8; + memzero(rand); + memzero(hashrand); + memzero(temp); + memzero(cryptbuf); + memzero(buf2); + return 0; +} + +static char bufstr[16]={28, 0, 0, 0, 1, 0, 0, 0, 1, 0, 6, 0, 16, 0, 4, 0}; +long nds_login(struct ncp_conn *conn, long user_id, const char *pwd, + long serv_id, char *logindata, char **u_priv_key) { + char *buf, *p, *pend; + char temp[16]; + char hashshuf[8]; + char loginid[4]; + char crypt1strc[28]; + char randno[4]; + char randbuf[1024]; + char *tempbuf; + int i, outlen; + int n1, n2; + u_int16_t n2a, n3; + long err; + int grace_period = 0; + + if (u_priv_key) *u_priv_key = NULL; + if (!(buf = malloc(4096))) + return ENOMEM; + pend = (p = buf) + 2048; + buf_put_dword_lh(&p, pend, 0); + buf_put_dword_hl(&p, pend, user_id); + if ((err = ncp_send_nds_frag(conn, 57, buf, p - buf, buf + 2048, 2048, + &outlen))) { + free(buf); + return err; + } + pend = (p = buf + 2048) + outlen; + if ((buf_get_buf(&p, pend, temp, 4)) || + (buf_get_buf(&p, pend, loginid, 4))) { + free(buf); + return NCPL_ET_REPLY_FORMAT; + } + free(buf); + if (strlen(pwd) > 127) + return NCPL_ET_PWD_TOO_LONG; + if (!(tempbuf = malloc(1064))) + return ENOMEM; + if (!(buf = malloc(4096))) { + free(tempbuf); + return ENOMEM; + } + strcpy(randbuf, pwd); + for (p = randbuf; *p; p++) + *p = toupper(*p); +#if 0 + shuffle(temp, randbuf, temp); +#else + shuffle(temp, randbuf, strlen(randbuf), temp); +#endif + nwhash1init(hashshuf, 8); + for (i = 10; i; i--) + nwhash1(hashshuf, 8, temp, 16); + memcpy(temp, loginid, 4); + memset(temp + 4, 7, 7); + nwhash1init(temp + 11, 5); + nwhash1(temp + 11, 5, temp, 11); + memcpy(crypt1strc, bufstr + 4, 12); + nwencryptblock(hashshuf, temp, 16, crypt1strc + 12); + + fillrandom(randno, 4); + fillrandom(randbuf, 1024); + pend = (p = tempbuf) + 1064; + buf_put_buf(&p, pend, randno, 4); + buf_put_dword_lh(&p, pend, 1024); + buf_put_buf(&p, pend, randbuf, 1024); + buf_put_buf(&p, pend, bufstr, sizeof(bufstr)); + buf_put_buf(&p, pend, crypt1strc + 12, 16); + + pend = (p = buf) + 2048; + buf_put_dword_lh(&p, pend, 2); + buf_put_dword_lh(&p, pend, 0); + buf_put_dword_hl(&p, pend, user_id); + + rsa_crypt(conn, tempbuf, 1064, serv_id, &p, pend); + memset(tempbuf, 0, 1064); + free(tempbuf); + + if ((err = ncp_send_nds_frag(conn, 58, buf, p - buf, buf + 2048, 2048, + &outlen))) { + if ((err != NCPL_ET_REQUEST_ERROR) || + (conn->completion != NDS_GRACE_PERIOD)) + goto err_exit; + grace_period = 1; + } + err = NCPL_ET_REPLY_FORMAT; + pend = (p = buf + 2048) + outlen; + if ((buf_get_buf(&p, pend, logindata, 8)) || + (buf_get_dword_lh(&p, pend, &n1)) || + (n1 > pend - p)) + goto err_exit; + pend = p + n1; + if ((buf_get_dword_lh(&p, pend, &n1)) || + (buf_get_dword_lh(&p, pend, &n2)) || + (buf_get_word_lh(&p, pend, &n3)) || + (n1 != 1) || (n2 != 0x060001) || (n3 > pend - p)) + goto err_exit; + + nwhash1init(temp, 8); + for (i = 10; i; i--) + nwhash1(temp, 8, crypt1strc, 28); + nwdecryptblock(temp, p, n3, p); + nwhash1init(temp, 5); + nwhash1(temp, 5, p, n3 - 5); + if (memcmp(temp, p + n3 - 5, 5)) + goto err_exit; + pend = p + n3 - 12; + if ((buf_get_buf(&p, pend, loginid, 4)) || + (buf_get_dword_lh(&p, pend, &n2)) || + (memcmp(loginid, randno, 4)) || (n2 > pend - p)) + goto err_exit; + pend = p + n2; + for (i = 0; i < n2; i++) + p[i] ^= randbuf[i]; + if ((buf_get_dword_lh(&p, pend, &n1)) || + (buf_get_dword_lh(&p, pend, &n2)) || + (buf_get_word_lh(&p, pend, &n3)) || + (n1 != 1) || (n2 != 0x060001) || (n3 > pend - p)) + goto err_exit; + pend = p + n3; + nwdecryptblock(hashshuf, p, n3, p); + if ((buf_get_dword_lh(&p, pend, &n1)) || + (buf_get_word_lh2(&p, pend, &n2a)) || + (buf_get_word_lh2(&p, pend, &n3)) || + (n1 != 1) || (n2a != 2) || (n3 > pend - p)) + goto err_exit; + if (u_priv_key) { + if (!(tempbuf = malloc(n3 + 10))) { + err = ENOMEM; + goto err_exit; + } + memset(tempbuf, 0, 8); + tempbuf[0] = 1; + tempbuf[4] = 3; + tempbuf[6] = 1; + WSET_LH(tempbuf, 8, n3); + memcpy(tempbuf + 10, p, n3); + if (!checkkey(tempbuf)) { + free(tempbuf); + goto err_exit; + } + *u_priv_key = tempbuf; + } + err = 0; + if (grace_period) { + conn->completion = NDS_GRACE_PERIOD; + err = NCPL_ET_REQUEST_ERROR; + } + +err_exit: + memzero(hashshuf); + memzero(randbuf); + memzero(crypt1strc); + memzero(randno); + memzero(temp); + if (buf) free(buf); + return err; +} + +long nds_beginauth(struct ncp_conn *conn, long user_id, struct ncp_conn *readkey_conn, + long serv_id, char *authid) { + char *buf, *p, *pend, *n_temp, temp[8]; + char *s_key; + char randno[4]; + long err; + int outlen, n1, n2, n3, n4; + u_int16_t n3a; + + if (!(buf = malloc(2048))) + return ENOMEM; + n_temp = NULL; + fillrandom(randno, 4); + pend = (p = buf) + 512; + buf_put_dword_lh(&p, pend, 0); + buf_put_dword_hl(&p, pend, user_id); + buf_put_buf(&p, pend, randno, 4); + if ((err = ncp_send_nds_frag(conn, 59, buf, p - buf, buf + 1024, 1024, + &outlen))) + goto err_exit; + + err = NCPL_ET_REPLY_FORMAT; + pend = (p = buf + 1024) + outlen; + if ((buf_get_buf(&p, pend, authid, 4)) || + (buf_get_dword_lh(&p, pend, &outlen)) || + (outlen > pend - p)) + goto err_exit; + pend = p + outlen; + if ((buf_get_dword_lh(&p, pend, &n1)) || + (buf_get_dword_lh(&p, pend, &n2)) || + (buf_get_dword_lh(&p, pend, &n3)) || + (n1 != 1) || (n2 != 0x020009) || (n3 > pend - p)) + goto err_exit; + pend = p + n3; + if ((buf_get_dword_lh(&p, pend, &n1)) || + (buf_get_dword_lh(&p, pend, &n1)) || + (buf_get_dword_lh(&p, pend, &n2)) || + (buf_get_word_lh(&p, pend, &n3a)) || + (n1 != 1) || (n2 != 0x0a0001) || (n3a > pend - p)) + goto err_exit; + n1 = ((countbits_l(p, n3a) + 31) & (~31)) >> 3; + if (n1 < 52) + goto err_exit; + if (!(n_temp = malloc(n1))) { + err = ENOMEM; + goto err_exit; + } + copyfill(n_temp, n1, p, n3a); + p += (n3a + 3) & (~3); + + if ((err = get_public_key(readkey_conn, serv_id, &s_key))) + goto err_exit; + err = modexpkey(s_key, n_temp, n_temp, n1); + free(s_key); + if (err) + goto err_exit; + err = NCPL_ET_REPLY_FORMAT; + nwhash1init(temp, 7); + nwhash1(temp + 5, 2, n_temp, 45); + nwhash1(temp, 5, n_temp + 1, 39); + if (memcmp(temp, n_temp + 40, 7)) + goto err_exit; + nwhash1init(temp, 8); + for (n1 = 10; n1; n1--) + nwhash1(temp, 8, n_temp + 1, 28); + free(n_temp); n_temp = NULL; + if ((buf_get_dword_lh(&p, pend, &n1)) || + (buf_get_dword_lh(&p, pend, &n2)) || + (buf_get_dword_lh(&p, pend, &n3)) || + (buf_get_dword_lh(&p, pend, &n4)) || + (n1 != 28) || (n2 != 1) || (n3 != 0x060001) || (n4 != 0x040010) || + (pend - p < 16)) + goto err_exit; + nwdecryptblock(temp, p, 16, p); + nwhash1init(temp, 5); + nwhash1(temp, 5, p, 11); + if ((!memcmp(temp, p + 11, 5)) || (!memcmp(p, randno, 4))) + err = 0; +err_exit: + if (n_temp) free(n_temp); + if (buf) free(buf); + return err; +} + +static char *allocfillchunk(const char *keyptr, int keylen, const char *chunk, + int destsize) { + char *p, *p2; + int i; + i = findchunk(keyptr, keylen, chunk, &p); + if (!p) + return NULL; + if (!(p2 = malloc(destsize))) + return NULL; + copyfill(p2, destsize, p, i); + return p2; +} + +static long gen_auth_data(char **outp, char *outend, + const char *u_key, const char *u_priv_key, + const char *authid, char *loginstrc, int loginstrc_len) { + char *keyptr; + int keylen, i, j; + int nbits, nblocksize, nbytes; + unsigned char nmask; + unitptr n_mod, n_exp, n_pn, n_qn, n_dp, n_dq, n_cr, n_key, n_temp; + unitptr n_key_dp, n_key_dq; + unitptr up, up2; + char *p, *tempbuf; + char *randbuf = NULL; + char hashbuf[0x42]; + long err; + + n_temp = n_mod = n_exp = n_pn = n_qn = n_dp = n_dq = n_cr = n_key = + n_key_dp = n_key_dq = NULL; + if (!initkey(u_key, &keyptr, &keylen)) + return NCPL_ET_REPLY_FORMAT; + i = findchunk(keyptr, keylen, "NN", &p); + if (!p) + return NCPL_ET_REPLY_FORMAT; + nbits = countbits_l(p, i); + nbytes = (nbits + 7) >> 3; + nmask = (unsigned char)(255 >> (8 - (nbits & 7))); + nblocksize = ((nbits + 31) & (~31)) >> 3; + + set_precision(bytes2units(nblocksize)); + + n_mod = (unitptr)allocfillchunk(keyptr, keylen, "NN", nblocksize); + n_exp = (unitptr)allocfillchunk(keyptr, keylen, "EN", nblocksize); + if (!initkey(u_priv_key, &keyptr, &keylen)) { + err = NCPL_ET_REPLY_FORMAT; + goto err_exit; + } + n_pn = (unitptr)allocfillchunk(keyptr, keylen, "PN", nblocksize); + n_qn = (unitptr)allocfillchunk(keyptr, keylen, "QN", nblocksize); + n_dp = (unitptr)allocfillchunk(keyptr, keylen, "DP", nblocksize); + n_dq = (unitptr)allocfillchunk(keyptr, keylen, "DQ", nblocksize); + n_cr = (unitptr)allocfillchunk(keyptr, keylen, "CR", nblocksize); + n_key = malloc(nblocksize); + + nwhash2init(hashbuf); + nwhash2block(hashbuf, loginstrc, loginstrc_len); + nwhash2end(hashbuf); + copyfill(n_key, nblocksize, hashbuf, 16); + + if (!(tempbuf = malloc(loginstrc_len + 16))) { + err = ENOMEM; + goto err_exit; + } + memset(tempbuf, 0, 16); + tempbuf[4] = 0x3c; + memcpy(tempbuf + 8, authid, 4); + p = tempbuf + 12; + buf_put_dword_lh(&p, tempbuf + 16, loginstrc_len); + memcpy(p, loginstrc, loginstrc_len); + + nwhash2init(hashbuf); + nwhash2block(hashbuf, tempbuf, loginstrc_len + 16); + free(tempbuf); + + n_temp = malloc(nblocksize); + n_key_dp = malloc(nblocksize); + n_key_dq = malloc(nblocksize); + mp_mult(n_temp, n_pn, n_qn); + mp_modexp(n_key_dp, n_key, n_dp, n_pn); + mp_modexp(n_key_dq, n_key, n_dq, n_qn); + mp_move(n_temp, n_key_dp); + mp_add(n_temp, n_pn); + mp_sub(n_temp, n_key_dq); + stage_modulus(n_pn); + mp_modmult(n_temp, n_temp, n_cr); + mp_mult(n_key, n_temp, n_qn); + mp_add(n_key, n_key_dq); + + randbuf = malloc(nblocksize * 3); + memset(randbuf, 0, nblocksize * 3); + + buf_put_dword_lh(outp, outend, 12 + nblocksize * 6); + buf_put_dword_lh(outp, outend, 1); + buf_put_dword_lh(outp, outend, 0x100008); + buf_put_word_lh2(outp, outend, 3); + buf_put_word_lh2(outp, outend, nblocksize * 3); + memset(*outp, 0, nblocksize * 6); + + up = (unitptr)randbuf; up2 = (unitptr)*outp; + for (i = 3; i; i--) { + fillrandom((char *)up, nbytes); + ((char *)up)[nbytes - 1] &= nmask; + if (!(j = mp_compare(up, n_mod))) + mp_dec(up); + else if (j > 0) { + mp_sub(up, n_mod); + mp_neg(up); + mp_add(up, n_mod); + } + mp_modexp(up2, up, n_exp, n_mod); + ((char *)up) += nblocksize; + ((char *)up2) += nblocksize; + } + nwhash2block(hashbuf, *outp, nblocksize * 3); + nwhash2end(hashbuf); + + up = (unitptr)randbuf; + for (i = 0; i < 3; i++) { + mp_init(n_temp, (unsigned char)hashbuf[i << 1] | + ((unsigned char)hashbuf[(i << 1) + 1] << 8)); + mp_modexp(up2, n_key, n_temp, n_mod); + stage_modulus(n_mod); + mp_modmult(up2, up2, up); + ((char *)up) += nblocksize; + ((char *)up2) += nblocksize; + } + *outp = (char *)up2; + err = 0; +err_exit: + memzero(hashbuf); + free(randbuf); + if (n_temp) { mp_init0(n_temp); free(n_temp); } + if (n_key_dp) { mp_init0(n_key_dp); free(n_key_dp); } + if (n_key_dq) { mp_init0(n_key_dq); free(n_key_dq); } + if (n_pn) { mp_init0(n_pn); free(n_pn); } + if (n_qn) { mp_init0(n_qn); free(n_qn); } + if (n_dp) { mp_init0(n_dp); free(n_dp); } + if (n_dq) { mp_init0(n_dq); free(n_dq); } + if (n_cr) { mp_init0(n_cr); free(n_cr); } + free(n_mod); + free(n_exp); + return err; +} + + +long nds_authenticate(struct ncp_conn *conn, long user_id, struct ncp_conn* readkey_conn, + long serv_id, const char *logindata, const char *u_priv_key) { + char authid[4]; + long err; + int user_name_len; + uni_char *user_name = NULL; + char *loginstrc; + int loginstrc_len; + char *buf, *p, *pend; + char *u_key; +#ifdef SIGNATURES + char signkey[8]; +#endif + + if (!readkey_conn) readkey_conn = conn; + u_key = loginstrc = buf = NULL; + if ((err = nds_beginauth(conn, user_id, readkey_conn, serv_id, authid))) + return err; + if ((err = nds_readentryname(conn, user_id, &user_name, &user_name_len))) + return err; + loginstrc_len = user_name_len + 22; + if (!(loginstrc = malloc(loginstrc_len))) { + err = ENOMEM; + goto err_exit; + } + memset(loginstrc, 0, 22); + loginstrc[0] = 1; + loginstrc[4] = 6; + memcpy(loginstrc + 6, logindata, 8); + fillrandom(loginstrc + 14, 4); + WSET_LH(loginstrc, 20, user_name_len); + memcpy(loginstrc + 22, user_name, user_name_len); + free(user_name); user_name = NULL; + if ((err = get_public_key(conn, user_id, &u_key))) + goto err_exit; + if (!(buf = malloc(2048))) { + err = ENOMEM; + goto err_exit; + } + pend = (p = buf) + 2048; + buf_put_dword_lh(&p, pend, 0); +#ifdef SIGNATURES + if (conn->sign_wanted) { + fillrandom(signkey, 8); + rsa_crypt(readkey_conn, signkey, 8, serv_id, &p, pend); + } else +#endif + buf_put_dword_lh(&p, pend, 0); + buf_put_lbuf(&p, pend, loginstrc, loginstrc_len); + + if ((err = gen_auth_data(&p, pend, u_key, u_priv_key, + authid, loginstrc, loginstrc_len))) + goto err_exit; + if ((err = ncp_send_nds_frag(conn, 60, buf, p - buf, NULL, 0, NULL))) + goto err_exit; +#ifdef SIGNATURES + if ((err = ncp_sign_start(conn, signkey))) + goto err_exit; +#endif + err = ncp_change_conn_state(conn, 1); + +err_exit: + if (loginstrc) free(loginstrc); + if (buf) free(buf); + if (u_key) free(u_key); + if (user_name) free(user_name); + return err; +} + +long nds_login_auth(struct ncp_conn *conn, const char *user, + const char *pwd) { + long err; + uni_char user_u[200]; + char *u_priv_key = NULL; + char logindata[8]; + uni_char *server_name = NULL; + __u32 serv_id, user_id; + struct sockaddr_ipx wserv_addr; + struct ncp_conn *login_conn, *wserv_conn = NULL, *readkey_conn = NULL; + int not_wserv; /* =1: current server doesn't have a writable replica */ + int i; + struct timeval tv; + int grace_period = 0; +#ifdef ERR_MSG + char buf[200]; /* to print username */ +#endif + gettimeofday(&tv, NULL); + srand(tv.tv_usec); + + if (strlen(user) >= 200) + return NCPL_ET_NAMETOOLONG; + strcpy_cu(user_u, user); + i = sizeof(wserv_addr); + err = nds_resolve_name(conn, 0x64, user_u, &user_id, ¬_wserv, + (struct sockaddr *)&wserv_addr, &i); + if ((err == NCPL_ET_REQUEST_ERROR) && (conn->completion == -601) && + (user_u[strlen_u(user_u)-1] != '.')) { +#ifdef ERR_MSG + strcpy_uc(buf, user_u); + printf("User %s not found in current context.\n" + "Trying server context...\n", buf); +#endif + if ((err = nds_get_server_name(conn, &server_name)) != 0) + goto err_exit; + i = 0; + while ((server_name[i]) && (server_name[i] != '.')) + i++; + memcpy(user_u + strlen_u(user_u), server_name + i, + (strlen_u(server_name) - i + 1) * 2); + free(server_name); + server_name = NULL; + i = sizeof(wserv_addr); + err = nds_resolve_name(conn, 0x64, user_u, &user_id, ¬_wserv, + (struct sockaddr *)&wserv_addr, &i); + } + if (err) { +#ifdef ERR_MSG + if (err == NCPL_ET_REQUEST_ERROR) + fprintf(stderr, "error %d finding user\n", conn->completion); +#endif + goto err_exit; + } + if (not_wserv) { + if (!(login_conn = wserv_conn = ncp_open_addr((struct sockaddr*)&wserv_addr, &err))) + goto err_exit; + } else + login_conn = conn; + if ((err = nds_get_server_name(login_conn, &server_name)) != 0) + goto err_exit2; + if ((err = nds_resolve_name(login_conn, 0x62, server_name, &serv_id, + NULL, NULL, NULL)) != 0) + goto err_exit2; + if ((err = nds_login(login_conn, user_id, pwd, serv_id, logindata, + &u_priv_key))) { + if ((err != NCPL_ET_REQUEST_ERROR) || + (login_conn->completion != NDS_GRACE_PERIOD)) { +#ifdef ERR_MSG + if (err == NCPL_ET_REQUEST_ERROR) + fprintf(stderr, "error %d logging in\n", login_conn->completion); +#endif +err_exit2:; + conn->completion = login_conn->completion; + goto err_exit; + } + grace_period = 1; + } + if (not_wserv) { + struct sockaddr xaddr; + int remoteserver; + int i; + + free(server_name); + if ((err = nds_get_server_name(conn, &server_name)) != 0) + goto err_exit; + i = sizeof(xaddr); + if ((err = nds_resolve_name(conn, 0x62, server_name, &serv_id, + &remoteserver, (struct sockaddr*)&xaddr, &i)) != 0) + goto err_exit; + if (remoteserver) { + if (!(readkey_conn = ncp_open_addr((struct sockaddr*)&xaddr, &err))) + goto err_exit; + } + if ((err = nds_resolve_name(conn, 0x51, user_u, &user_id, + NULL, NULL, NULL)) !=0) + goto err_exit; + } + if ((err = nds_authenticate(conn, user_id, readkey_conn, serv_id, logindata, + u_priv_key))) { +#ifdef ERR_MSG + if (err == NCPL_ET_REQUEST_ERROR) + fprintf(stderr, "error %d authenticating\n", conn->completion); +#endif + goto err_exit; + } + if (grace_period && (!err)) { + conn->completion = NDS_GRACE_PERIOD; + err = NCPL_ET_REQUEST_ERROR; + } +err_exit: + if (readkey_conn) ncp_close(readkey_conn); + if (wserv_conn) ncp_close(wserv_conn); + if (u_priv_key) { clearkey(u_priv_key); free(u_priv_key); } + free(server_name); +#ifdef RANDBUF + memset(global_randbuf, 0, RANDBUFSIZE); + g_rndp = global_randbuf + RANDBUFSIZE; +#endif + return err; +} + +#ifdef NDS_PRIVATEKEY +long +nds_authenticate(struct ncp_conn* conn, uni_char* name, u_int8_t* code1, void* privateKey, size_t privateKeyLen) { +} +#endif /* NDS_PRIVATE_KEY */ + diff --git a/lib/nwcrypt.c b/lib/nwcrypt.c index 07d8ff7..48b80e4 100644 --- a/lib/nwcrypt.c +++ b/lib/nwcrypt.c @@ -92,20 +92,20 @@ 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, +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 = @@ -115,7 +115,8 @@ static buf32 encryptkeys = 0xF4, 0x47, 0xDC, 0xA7, 0xEC, 0xCF, 0x50, 0xC0}; -static void shuffle1(buf32 temp, unsigned char *target) +static void +shuffle1(buf32 temp, unsigned char *target) { short b4; unsigned char b3; @@ -123,51 +124,63 @@ static void shuffle1(buf32 temp, unsigned char *target) b4 = 0; - for (b2 = 0; b2 <= 1; ++b2) { - for (s = 0; s <= 31; ++s) { + 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) { + 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) +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)) { + && (buf[buflen - 1] == 0)) + { buflen = buflen - 1; } - for (s = 0; s < 32; s++) { + for (s = 0; s < 32; s++) + { temp[s] = 0; } d = 0; - while (buflen >= 32) { - for (s = 0; s <= 31; ++s) { + 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) { + if (buflen > 0) + { + for (s = 0; s <= 31; ++s) + { + if (d + buflen == b2) + { b2 = d; temp[s] = temp[s] ^ encryptkeys[s]; - } else { + } else + { temp[s] = temp[s] ^ buf[b2]; b2 = b2 + 1; } @@ -180,9 +193,10 @@ static void shuffle(const unsigned char *lon, const unsigned char *buf, int bufl } -static void nw_encrypt(const unsigned char *fra, - const unsigned char *buf, - unsigned char *til) +static void +nw_encrypt(const unsigned char *fra, + const unsigned char *buf, + unsigned char *til) { buf32 k; int s; @@ -197,6 +211,7 @@ static void nw_encrypt(const unsigned char *fra, til[s] = k[s] ^ k[15 - s]; } +#ifndef __MAKE_SULIB__ /*****************************************************************************/ /* */ @@ -288,7 +303,8 @@ static char * in ncplib.c. */ -static void newpassencrypt(char *old, char *new, char *out) +static void +newpassencrypt(char *old, char *new, char *out) { char *p, *bx; char copy[8]; @@ -297,22 +313,26 @@ static void newpassencrypt(char *old, char *new, char *out) memcpy(copy, new, 8); - for (i = 0; i < 16; i++) { - for (di = 0, ax = 0, p = old; di < 8; di++, ax += 0x20, p++) { + 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--) { + 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++) { + for (di = 0; di < 16; di++) + { if (newshuffle[di + 0x100] & 1) ch = ((copy[newshuffle[di + 0x100] / 2] >> 4) & 0x0f); else @@ -322,3 +342,5 @@ static void newpassencrypt(char *old, char *new, char *out) memcpy(copy, out, 8); } } +#endif /* __MAKE_SULIB__ */ + diff --git a/lib/platform.h b/lib/platform.h new file mode 100644 index 0000000..2358c99 --- /dev/null +++ b/lib/platform.h @@ -0,0 +1,218 @@ +/* platform.h - computer platform customization for PGP + multiprecision math package. #Included in mpilib.h. +*/ +#ifndef PLATFORM_H +#define PLATFORM_H + +/* Platform customization: + * A version which runs on almost any computer can be implemented by + * defining PORTABLE and MPORTABLE, preferably as a command line + * parameter. Faster versions can be generated by specifying specific + * parameters, such as size of unit and MULTUNIT, and by supplying some + * of the critical in assembly. + * + * This file holds customizations for different environments. + * This is done in one of two ways: + * 1. A symbol is defined on the command line which designates a + * particular environment, such as MSDOS. This file detects the + * environment symbol and sets the appropriate low-level defines. + * + * 2. If no environment is named, the low-level defines are set in + * the same manner as for PGP 2.0, thereby providing an easy upgrade. + * + * Following are a description of the low-level definition symbols: + * + * The following preprocessor symbols should be conditionally set to + * optimize for a particular environment. + * + * Define one of the following: + * UNIT8, UNIT16, or UNIT32 - specifies size of operands for + * multiprecision add, subtract, shift, and initialization operations. + * Define one of the following: + * MUNIT8, MUNIT16, MUNIT32 - specified size of operands for + * multiprecision multiply and mod_mult. This must be less than or + * equal to unit size. It should be the word size for the native + * atomic multiply instruction. For a 16x16 bit multiply yielding a + * 32-bit product, MUNIT16 should be set. + * Define one (or more) of the following: + * PEASANT, MERRITT, UPTON, SMITH -algorithm used for modmult. All defined + * algorithms are compiled, but the first defined name listed will be + * assigned to the generic entry point symbols. Multiple algorithms are + * used primarily for testing. + * HIGHFIRST - specified if longs are stored with the most significant + * bit at the lowest address (Motorola), undefined otherwise. This should + * be defined on the command line, normally in the makefile. + * + * The following symbol, if initialized, is set to specific values: + * ALIGN - variable declaration attribute which forces optimum alignment + * of words, e.g. for VAX C: ALIGN=_align(quadword) + * + * The following symbols correspond to individual multiprecision routines + * that may be implemented with assembly language. If they are implemented + * in assembly, the symbols should be defined with the name of the + * corresponding external entry points, e.g., mp_addc=P_ADDC + * mp_setp - set precision for external routines + * mp_addc - add with carry + * mp_subb - subtract with borrow + * mp_rotate_left - rotate left + * mp_compare - compare + * mp_move - move + * unitfill0 - zero fill + * mp_smul - multiply vector by single word * + * mp_smula - multiply vector by single word and accumulate * + * mp_dmul - full multiply + * mp_set_recip - setup for mp_quo_digit + * mp_quo_digit - quotient digit for modulus reduction + * + * Either mp_smul or mp_smula should be defined. mp_smula provides + * for accumulation to an existing value, while mp_smul is for use of the + * older definition of mp_smul, used in PGP 2.0, which assumed that the high + * order accumulator word is zero. Use of mp_smula causes one less word of + * precision to be used, thereby slightly increasing speed. + */ + +/******************************************************************** + * Environment customization. Please send any additions or corrections + * to Philip Zimmermann. + */ +#ifndef PORTABLE + +#ifdef MSDOS +#ifndef i386 /* gcc */ +#define UNIT16 +#define MUNIT16 +#define mp_setp P_SETP +#define mp_addc P_ADDC +#define mp_subb P_SUBB +#define mp_rotate_left P_ROTL +#define mp_smula P_SMULA +#define mp_quo_digit P_QUO_DIGIT +#define mp_set_recip P_SETRECIP +#define SMITH +#define PLATFORM_SPECIFIED +#endif /* i386 */ +#endif /* MSDOS */ + +#ifdef VMS +#define UNIT32 /* use 32-bit units */ +#define MUNIT32 /* not used in C code, only in assembler */ +#define UPTON +#define mp_setp p_setp +#define mp_addc p_addc +#define mp_subb p_subb +#define mp_rotate_left p_rotl +#define mp_smul p_smul +#define mp_dmul p_dmul +#define mp_compare p_cmp +#define ALIGN _align(quadword) + +#ifdef VAXC +/* + * A VAX is a CISC machine. Unfortunately C is at to low a level to use + * many of the instruction set enhancements so we define some macros + * here that implement fast moves and fast zero fills with single + * instructions. + */ +#pragma builtins +#define mp_move( dst, src) _MOVC3( global_precision*4, (char *) src, (char *) dst) +#define unitfill0( r, unitcount) _MOVC5( 0, (char *) 0, 0, unitcount*4, (char *) r) +#define mp_burn(r) _MOVC5(0, (char *) 0, 0, global_precision*4, (char *) r) +#define mp_init0(r) mp_burn(r) /* Just for documentation purposes */ +#endif /* VAXC */ + +#define PLATFORM_SPECIFIED +#endif /* VMS */ + +#ifdef mips +/* + * Needs r3kd.s and r3000.s (or r3000.c) + */ +#define UNIT32 +#define MUNIT32 +#define SMITH +#define mp_dmul p_dmul +#define mp_setp p_setp +#define mp_addc p_addc +#define mp_subb p_subb +#define mp_rotate_left p_rotl +#define mp_smula p_smula +#define mp_quo_digit p_quo_digit +#define mp_set_recip p_setrecip +#define PLATFORM_SPECIFIED +#endif /* mips */ + +#ifdef i386 +/* + * Needs 80386.S + */ +#define UNIT32 +#define MUNIT32 +#define SMITH +#define mp_setp P_SETP +#define mp_addc P_ADDC +#define mp_subb P_SUBB +#define mp_rotate_left P_ROTL +#define unitfill0(r,ct) memset((void*)r, 0, (ct)*sizeof(unit)) +#define mp_smula P_SMULA +#define mp_quo_digit p_quo_digit +#define mp_set_recip p_setrecip +#define PLATFORM_SPECIFIED +#endif /* i386 */ + +#ifdef sparc +/* + * Needs sparc.s + */ +#define UNIT32 +#define MERRITT +#define mp_setp P_SETP +#define mp_addc P_ADDC +#define mp_subb P_SUBB +#define mp_rotate_left P_ROTL +#define unitfill0(r,ct) memset((void*)r, 0, (ct)*sizeof(unit)) +#define PLATFORM_SPECIFIED +#endif /* sparc */ + +#if defined(mc68000) || defined(mc68020) +/* + * Needs mc68020.S + */ +#define UNIT32 +#define mp_setp P_SETP +#define mp_addc P_ADDC +#define mp_subb P_SUBB +#define mp_rotate_left P_ROTL +#define unitfill0(r,ct) memset((void*)r, 0, (ct)*sizeof(unit)) +#if defined(sun3) || defined(mc68020) +# define UPTON +# define MUNIT32 +# define mp_smul P_SMUL +/* # define mp_dmul P_DMUL */ /* mc68020.s has a bug in P_DMUL */ +#else +# define SMITH +# define MUNIT16 +#endif +#define PLATFORM_SPECIFIED +#endif /* mc68000 */ + +/* Add additional platforms here ... */ + +/**************** End of system specification ************************/ + +#ifndef PLATFORM_SPECIFIED +/* No platform explicitly selected. Customization is controlled by + * PORTABLE and MPORTABLE. + */ +#define mp_setp P_SETP +#define mp_addc P_ADDC +#define mp_subb P_SUBB +#define mp_rotate_left P_ROTL +#define UPTON +#define unitfill0(r,ct) memset((void*)r, 0, (ct)*sizeof(unit)) +#ifndef MPORTABLE +#define mp_smul P_SMUL +#endif /* MPORTABLE */ +#endif /* PLATFORM_SPECIFIED */ +#endif /* PORTABLE */ +#endif /* PLATFORM_H */ + diff --git a/lib/usuals.h b/lib/usuals.h new file mode 100644 index 0000000..80ef96f --- /dev/null +++ b/lib/usuals.h @@ -0,0 +1,39 @@ +/* usuals.h - The usual typedefs, etc. +*/ +#ifndef USUALS /* Assures no redefinitions of usual types...*/ +#define USUALS + +#include + +typedef unsigned char boolean; /* values are TRUE or FALSE */ +typedef u_int8_t byte; /* values are 0-255 */ +typedef byte *byteptr; /* pointer to byte */ +typedef char *string; /* pointer to ASCII character string */ +typedef u_int16_t word16; /* values are 0-65535 */ +typedef u_int32_t word32; /* values are 0-4294967295 */ + +#ifndef TRUE +#define FALSE 0 +#define TRUE (!FALSE) +#endif /* if TRUE not already defined */ + +#ifndef min /* if min macro not already defined */ +#define min(a,b) (((a)<(b)) ? (a) : (b) ) +#define max(a,b) (((a)>(b)) ? (a) : (b) ) +#endif /* if min macro not already defined */ + +/* void for use in pointers */ +#ifndef NO_VOID_STAR +#define VOID void +#else +#define VOID char +#endif + + /* Zero-fill the byte buffer. */ +#define fill0(buffer,count) memset( buffer, 0, count ) + + /* This macro is for burning sensitive data. Many of the + file I/O routines use it for zapping buffers */ +#define burn(x) fill0((VOID *)&(x),sizeof(x)) + +#endif /* if USUALS not already defined */ diff --git a/man/Makefile b/man/Makefile index 5cdd1a7..18c608f 100644 --- a/man/Makefile +++ b/man/Makefile @@ -1,12 +1,22 @@ +include ../Makeinit + +MAN1 = ncopy nwbols nwfsinfo nwsfind pqlist nprint nwboprops nwfstime \ + nwtrustee pserver nsend nwbpset nwpasswd nwuserlist slist \ + nwauth nwbpvalues nwrights nwvolinfo pqrm pqstat nwpurge +MAN5 = nwclient +MAN8 = ncpmount nwbpadd nwmsg ncpumount nwbpcreate nwrevoke nwbocreate \ + nwbprm nwborm nwgrant 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 + for i in $(MAN1); do install $$i.1 -m 644 $(MANDIR)/man1; done + for i in $(MAN5); do install $$i.5 -m 644 $(MANDIR)/man5; done + for i in $(MAN8); do install $$i.8 -m 644 $(MANDIR)/man8; done clean: - rm -f *~ \ No newline at end of file + rm -f *~ + +mrproper: clean diff --git a/man/nwmsg.8 b/man/nwmsg.8 new file mode 100644 index 0000000..a4d538b --- /dev/null +++ b/man/nwmsg.8 @@ -0,0 +1,33 @@ +.TH NWMSG 8 02/29/1996 nwmsg nwmsg +.SH NAME +nwmsg \- Deliver NetWare user broadcast messages +.SH SYNOPSIS +.B nwmsg +.I mount-point +.SH DESCRIPTION +.B nwmsg +is called by kerneld when a broadcast message arrives from a NetWare +server. +.B nwmsg +fetches this message via the mount point and delivers it to +the user using the same way write(1) uses. + +Please note that +.I kerneld +must run when broadcast messages should be delivered to users. + +NetWare servers can send asynchronous broadcast messages to users, +either on explicit request by another user, or when the server is +shutdown. The client workstation is informed about this event by an +IPX packet on a special socket, the message socket. + +This can happen at any time, so the user has to be informed about this +event whenever it appears. I chose to use the kerneld feature of the +Linux kernel to call the program nwmsg. For nwmsg, I used the relevant +parts of the +.I write +program, so you can expect the NetWare broadcast +messages to appear where user messages would appear. + +.SH SEE ALSO +ncpmount(8), kerneld(8), write(1) \ No newline at end of file diff --git a/man/nwpurge.1 b/man/nwpurge.1 new file mode 100644 index 0000000..82e9294 --- /dev/null +++ b/man/nwpurge.1 @@ -0,0 +1,65 @@ +.TH NWPURGE 1 4/2/1998 nwpurge nwpurge +.SH NAME +nwpurge \- Permanently delete previously erased files +.SH SYNOPSIS +.B nwpurge +[ +.B -h +] [ +.B -a +] [ +.B -l +] [ +.B -s +] [ +.B directory +] + +.SH DESCRIPTION +.B nwpurge +purges files from specified NetWare directory. + +.SH OPTIONS + +.B -h +.RS 3 +.B -h +is used to print out a short help text. +.RE + +.B -a +.RS 3 +.B -a +is used to specify that not only specified directory, but also its +subdirectories have to be purged. +.RE + +.B -l +.RS 3 +.B -l +is used to disable purge. Files are only printed out. +.RE + +.B -s +.RS 3 +.B -s +specifies silent mode (no print output, only total is printed). +.RE + +.B directory +.RS 3 +You can specify the directory in which you want to purge files. Current +working directory is used by default. You have to specify path in +Linux format, not in NetWare format. + +.SH EXAMPLES + +nwpurge -a /NetWare/server/sys + +With this example, all files from directory /NetWare/server/sys and from +all its subdirectories are purged. + +.SH AUTHORS +nwpurge was written by Petr Vandrovec with the corresponding NetWare +utility in mind. See the Changes file of ncpfs for other contributors. + diff --git a/man/pqrm.1 b/man/pqrm.1 new file mode 100644 index 0000000..7a3288e --- /dev/null +++ b/man/pqrm.1 @@ -0,0 +1,105 @@ +.TH PQRM 1 03/03/1998 pqrm pqrm +.SH NAME +pqrm \- Remove job from NetWare print queue +.SH SYNOPSIS +.B pqrm +[ +.B -h +] [ +.B -S +.I server +] [ +.B -U +.I user name +] [ +.B -P +.I password + | +.B -n +] [ +.B -C +] +.I queue_name +.I job_ID +[ +.I another_job_ID +... ] + +.SH DESCRIPTION +.B pqrm +remove specified jobs from the NetWare print queue available +to you on some server. If you are already connected to some server, this one +is used. + +.B pqrm +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 queue_name +.RS 3 +.B queue_name +is used to specify queue. You can not use wildcards in the name. +.RE + +.B job_ID +, +.B another_job_ID +.RS 3 +.B job_ID +is used to specify which job has to be deleted. +.RE + +.B -S +.I server +.RS 3 +.B server +is the name of the server you want to use. +.RE + +.B -U +.I user name +.RS 3 +If the user name your NetWare administrator gave to you differs +from your unix user-id, you should use +.B -U +to tell the server about your NetWare user name. +.RE + +.B -P +.I password +.RS 3 +You may want to give the password required by the server on the +command line. You should be careful about using passwords in scripts. +.RE + +.B -n +.RS 3 +.B -n +should be given to mount shares which do not require a password to log in. + +If neither +.B -n +nor +.B -P +are given, pqstat prompts for a password. +.RE + +.B -C +.RS 3 +By default, passwords are converted to uppercase before they are sent +to the server, because most servers require this. You can turn off +this conversion by +.B -C. +.RE + +.SH SEE ALSO +.B nwclient(5), nprint(1), slist(1), ncpmount(8), ncpumount(8), pqlist(1), pqstat(1) + +.SH CREDITS +pqrm was written by Petr Vandrovec (vandrove@vc.cvut.cz) + diff --git a/man/pqstat.1 b/man/pqstat.1 new file mode 100644 index 0000000..6f647fd --- /dev/null +++ b/man/pqstat.1 @@ -0,0 +1,107 @@ +.TH PQSTAT 1 03/03/1998 pqstat pqstat +.SH NAME +pqstat \- List jobs in NetWare print queue +.SH SYNOPSIS +.B pqstat +[ +.B -h +] [ +.B -S +.I server +] [ +.B -U +.I user name +] [ +.B -P +.I password + | +.B -n +] [ +.B -C +] +.I queue name +[ +.I job count +] +.SH DESCRIPTION +.B pqstat +lists specified number of jobs from the specified NetWare print queue available +to you on some server. If you are already connected to some server, this one +is used. + +If pqstat does not print to a tty, the decorative header line is +not printed, so that you can count the jobs in print queue by doing + + pqstat -S server queue | wc -l + +.B pqstat +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 queue name +.RS 3 +.B queue name +is used to specify queue. You can not use wildcards in the name. +.RE + +.B job count +.RS 3 +.B job count +is used to specify how much entries will be shown. Default is to show all +entries. +.RE + +.B -S +.I server +.RS 3 +.B server +is the name of the server you want to use. +.RE + +.B -U +.I user name +.RS 3 +If the user name your NetWare administrator gave to you differs +from your unix user-id, you should use +.B -U +to tell the server about your NetWare user name. +.RE + +.B -P +.I password +.RS 3 +You may want to give the password required by the server on the +command line. You should be careful about using passwords in scripts. +.RE + +.B -n +.RS 3 +.B -n +should be given to mount shares which do not require a password to log in. + +If neither +.B -n +nor +.B -P +are given, pqstat prompts for a password. +.RE + +.B -C +.RS 3 +By default, passwords are converted to uppercase before they are sent +to the server, because most servers require this. You can turn off +this conversion by +.B -C. +.RE + +.SH SEE ALSO +.B nwclient(5), nprint(1), slist(1), ncpmount(8), ncpumount(8), pqlist(1), pqrm(1) + +.SH CREDITS +pqstat was written by David Woodhouse (dave@imladris.demon.co.uk) + diff --git a/man/pserver.1 b/man/pserver.1 index b8358a0..be34f9f 100644 --- a/man/pserver.1 +++ b/man/pserver.1 @@ -108,6 +108,9 @@ print job. %u: This field will be replaced by the name of the user who posted this print job. + +%d: This field will be replaced by the job description field of +this print job. .RE .B -j diff --git a/ncpfs-2.1.1.lsm b/ncpfs-2.2.0.lsm similarity index 50% rename from ncpfs-2.1.1.lsm rename to ncpfs-2.2.0.lsm index 171ddd3..d92a363 100644 --- a/ncpfs-2.1.1.lsm +++ b/ncpfs-2.2.0.lsm @@ -1,19 +1,19 @@ Begin3 Title: ncpfs -Version: 2.1.1 -Entered-date: 23. March 1997 +Version: 2.2.0 +Entered-date: May 1, 1998 Description: With ncpfs you can mount volumes of your netware server under Linux. You can also print to netware print queues and spool netware print queues to the - Linux printing system. You need kernel 1.2.x or - 1.3.71 and above. ncpfs does NOT work with any 1.3.x - kernel below 1.3.71. + Linux printing system. Keywords: filesystem ncp novell netware printing -Author: lendecke@namu01.Num.Math.Uni-Goettingen.de (Volker Lendecke) -Maintained-by: lendecke@namu01.Num.Math.Uni-Goettingen.de (Volker Lendecke) +Author: lendecke@Math.Uni-Goettingen.de (Volker Lendecke) +Maintained-by: lendecke@Math.Uni-Goettingen.de (Volker Lendecke), + vandrove@vc.cvut.cz (Petr Vandrovec) Primary-site: ftp.gwdg.de:/pub/linux/misc/ncpfs Alternate-site: sunsite.unc.edu:/pub/Linux/system/Filesystems/ncpfs - ~177k ncpfs-2.1.1.tgz - ~ 1k ncpfs-2.1.1.lsm + platan.vc.cvut.cz:/pub/linux/ncpfs + ~190k ncpfs-2.2.0.tgz + ~ 1k ncpfs-2.2.0.lsm Copying-policy: GPL End diff --git a/ncpfs-nds-0.06.CHANGES b/ncpfs-nds-0.06.CHANGES new file mode 100644 index 0000000..3b70f7a --- /dev/null +++ b/ncpfs-nds-0.06.CHANGES @@ -0,0 +1,96 @@ +Release 0.06, January 20, 1998 +* Signature support (re)included. Because of this the name has changed + and the kernel patch is added. +* Fixed segfault in nds_login_auth when trying server context. + (with thanks to K J MacDonald, kenny@holyrood.ed.ac.uk) + + +Release 0.05, November 7, 1997 +* Added include errno.h to ndslib.c (needed for glibc) +* Modified nwsfind to accept -a parameter that causes nwsfind to + interpret the server name as an address. +* Fixed segfault in ncp_open_addr +* Modified lib/ncplib.c:ncp_open_addr to call nwsfind with the address + (creates a route to the address if necessary). + +Release 0.04, November 5, 1997 +Changes since 0.03: +* Added support for NDS login/authenticate to a read-only replica + (untested) +* ncpmount has new option -b to use bindery logins to NDS servers + (actually since 0.01) +(Again with thanks to Petr Vandrovec, vandrove@vc.cvut.cz) + + +Release 0.03, November 2, 1997 +Changes since 0.02: +* (Hopefully temporarily) removed signature support, it seems to be + legally protected. Because of this the name has changed and the + kernel patch is removed. + + +Release 0.02, October 15, 1997 +Changes since 0.01: +* Fixed bug with empty passwords +* Fixed bug with beginlogin id != user id +* Fixed bug with fragger handle != 0 +* Removed ncpsign.* from ./sutil, moved ncpsign.h to ./include +* Reorganized packet signature initializing +* Added support for NDS grace logins +(With thanks to Petr Vandrovec, vandrove@vc.cvut.cz) + + +Changes made by ncpfs-nds-sign-0.01.patch: + +* Adds NDS_SUPPORT conditional variable to main Makefile +* Puts set -e; ahead of the SUBDIRS loop in the main Makefile to abort + the loop if compilation in a subdir fails +* Adds README.NDS file +* Adds fields for packet signatures to struct ncp_conn +* Adds the following functions to the lib/ncplib.c + ncp_negotiate_size_and_options Negotiate packet size and options + ncp_get_bindery_access_level Get bindery access level + ncp_init_pb_conn Initialize packet burst connection + ncp_send_nds_frag Send message with NDS fragger protocol + ncp_sign_start Initialize internal signing structures + ncp_send_nds Send request for NDS function + ncp_change_conn_state Change NW 4 connection state +* Modifies ncp_open_temporary in lib/ncplib.c to use NDS login if + compiled with -DNDS_SUPPORT and server has NDS. +* Adds two error messages to ncplib_err.et +* Modifies lib/ncplib.c to generate packet signatures when wanted. +* Adds lib/ndslib.c with the following external used functions: + strlen_u Get length of unicode string + strcpy_uc Copy unicode string to normal string + strcpy_cu Copy normal string to unicode string + nds_get_server_name Get name and domain of current server + nds_get_tree_name Get current NDS tree name + nds_login_auth NDS login and authenticate to current server +* Adds mpilib.c, mpilib.h, usuals.h and platform.h from the PGP 2.3 + source to lib/ for the RSA encryption, which is necessary for NDS + login/authenticate. +* Adds lib/ndscrypt.c with hash and encrypt functions for NDS login. +* Adds lib/ncpsign.c with a MD4 hash function for packet signatures. +* Modifies lib/Makefile to add ncpsign.o, ndslib.o, mpilib.o and + ndscrypt.o to libncp. +* Modifies sutil/Makefile to add ndslib.o,mpilib.o,ndscrypt.o to libncp. +* Adds ncp_send_nds_frag, ncp_send_nds, ncp_change_conn_state to + sutil/ncplib.c +* Modifies sutil/ncpmount.c to: + give more verbose error message if mount(2) fails; + use NDS login if compiled with -DNDS_SUPPORT and server has NDS; + start packet signature generation. +(See below for changes to kernel-1.2/*) + + +Changes made by ncpfs-nds-sign-0.01.kernel.patch: + +* Modifies Makefile to add ncpsign_kernel.o to ncpfs.o +* Modifies inode.c to query whether the server wants packet signatures. +* Adds ioctls to start packet signature generation and to query + whether the server wants packet signing. +* Adds ncp_negotiate_size_and_options to ncplib_kernel.c. +* Modifies sock.c to sign packets when enabled. +* Adds ncpsign_kernel.c to generatie packet signatures. + +Arne de Bruijn, October 4, 1997 diff --git a/ncpfs-nds-0.06.README b/ncpfs-nds-0.06.README new file mode 100644 index 0000000..625d515 --- /dev/null +++ b/ncpfs-nds-0.06.README @@ -0,0 +1,42 @@ + + NDS support for ncpfs (linux) + + ncpfs is a NetWare client for the Linux operating system, maintained + by Volker Lendecke (lendecke@namu01.gwdg.de). I have written + support for NDS logins to NetWare 4 servers. + + Warning! NDS logins require the RSA public key algorithm, which is + patented in the U.S.A. and Canada, and possibly in other countries. + Because of this you may not be allowed to use this code. Check this + before you use NDS logins! + + Warning! The NDS support for ncpfs is in early beta stage, currently + I have only tested it on my own test NW 4.10 server. The NDS support + may not work for you, or even give problems like crashing your linux + box, or the NetWare server! Please apply the patch only if you know + what you are doing. Note that this version of the patch is not + little-endian free, so it won't work on big-endian architectures. + THIS PATCH IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER + EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS + WITH YOU. SHOULD THE PATCH PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL + NECESSARY SERVICING, REPAIR OR CORRECTION. + + This file contains a patch for the non-kernel part of ncpfs: + ncpfs-nds-0.05.patch. This is against ncpfs 2.0.11, but works the same + for ncpfs 2.0.10. + + Apply the patches by cd'ing into the appropriate source directory (e.g + /usr/local/src/ncpfs-2.0.11) and do: + + patch < patch-file + + You can disable NDS support after applying the patch by uncommenting + the line NDS_SUPPORT = 1 in the main Makefile from ncpfs. + + If you have comments or suggestinons about this patch please mail them + to me. + +Arne de Bruijn +arne@knoware.nl diff --git a/patches/README b/patches/README index 85432ae..5db9985 100644 --- a/patches/README +++ b/patches/README @@ -4,10 +4,11 @@ and do: patch -p1 < patch-file -lockup-2.0.28.diff: -An *extremely* dirty fix to the lockup bug mentioned in the BUGS -file. Please only apply it if you experience the problem. Should apply -to 2.0.28 and above in the 2.0.x series. NOT TESTED with 2.1.x. +lockup-2.0.30.diff: +Please apply this patch to your 2.0.30 kernel to get rid of the ncpfs +lockups. See ../BUGS for the symptoms. -linux-2.1.26.diff: -Development version of ncpfs +Patches for other kernels to support new features must be downloaded +separately because of kernel changes have no relations to ncpfs changes. +Kernel patches should be available on same place as this package or +at ftp://platan.vc.cvut.cz/pub/linux/ncpfs/latest. diff --git a/patches/linux-2.1.26.diff b/patches/linux-2.1.26.diff deleted file mode 100644 index 3b6e7fb..0000000 --- a/patches/linux-2.1.26.diff +++ /dev/null @@ -1,35 +0,0 @@ ---- 2.1.26/fs/ncpfs/sock.c Sun Jan 26 11:07:44 1997 -+++ 2.1.26-patched/fs/ncpfs/sock.c Sun Feb 16 17:05:13 1997 -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - #include - - -@@ -343,7 +344,6 @@ - char *start = server->packet; - poll_table wait_table; - struct poll_table_entry entry; -- int (*select) (struct inode *, poll_table *); - int init_timeout, max_timeout; - int timeout; - int retrans; -@@ -362,7 +362,6 @@ - - file = server->ncp_filp; - inode = file->f_inode; -- select = file->f_op->poll; - sock = &inode->u.socket_i; - if (!sock) - { -@@ -418,7 +417,7 @@ - wait_table.nr = 0; - wait_table.entry = &entry; - current->state = TASK_INTERRUPTIBLE; -- if (!select(inode, &wait_table)) -+ if (!(file->f_op->poll(file, &wait_table) & POLLIN)) - { - if (timeout > max_timeout) - { diff --git a/patches/linux-2.1.29.diff b/patches/linux-2.1.29.diff deleted file mode 100644 index ce7d1b8..0000000 --- a/patches/linux-2.1.29.diff +++ /dev/null @@ -1,5281 +0,0 @@ -diff -urN 2.1.29/fs/ncpfs/dir.c 2.1.29-patched/fs/ncpfs/dir.c ---- 2.1.29/fs/ncpfs/dir.c Sun Jan 26 11:07:44 1997 -+++ 2.1.29-patched/fs/ncpfs/dir.c Sun Mar 23 09:38:45 1997 -@@ -23,95 +23,88 @@ - - struct ncp_dirent { - struct nw_info_struct i; -- struct nw_search_sequence s; /* given back for i */ -+ struct nw_search_sequence s; /* given back for i */ - unsigned long f_pos; - }; - - static long --ncp_dir_read(struct inode *inode, struct file *filp, char *buf, unsigned long count); -+ ncp_dir_read(struct inode *inode, struct file *filp, char *buf, unsigned long count); - --static int --ncp_readdir(struct inode *inode, struct file *filp, -- void *dirent, filldir_t filldir); -+static int -+ ncp_readdir(struct inode *inode, struct file *filp, -+ void *dirent, filldir_t filldir); - - static int --ncp_read_volume_list(struct ncp_server *server, int start_with, -- int cache_size); -+ ncp_read_volume_list(struct ncp_server *server, int start_with, -+ int cache_size); - - static int --ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos, -- int cache_size, struct ncp_dirent *entry); -+ ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos, -+ int cache_size, struct ncp_dirent *entry); - - static struct inode * --ncp_iget(struct inode *dir, struct nw_file_info *finfo); -+ ncp_iget(struct inode *dir, struct nw_file_info *finfo); - - static struct ncp_inode_info * --ncp_find_dir_inode(struct inode *dir, const char *name); -+ ncp_find_dir_inode(struct inode *dir, const char *name); - - static int --ncp_lookup(struct inode *dir, const char *__name, -- int len, struct inode **result); -+ ncp_lookup(struct inode *dir, const char *__name, -+ int len, struct inode **result); - --static int --ncp_create(struct inode *dir, const char *name, int len, int mode, -- struct inode **result); -+static int -+ ncp_create(struct inode *dir, const char *name, int len, int mode, -+ struct inode **result); - --static int --ncp_mkdir(struct inode *dir, const char *name, int len, int mode); -+static int -+ ncp_mkdir(struct inode *dir, const char *name, int len, int mode); - --static int --ncp_rmdir(struct inode *dir, const char *name, int len); -+static int -+ ncp_rmdir(struct inode *dir, const char *name, int len); - - static int --ncp_unlink(struct inode *dir, const char *name, int len); -+ ncp_unlink(struct inode *dir, const char *name, int len); - - static int --ncp_rename(struct inode *old_dir, const char *old_name, int old_len, -- struct inode *new_dir, const char *new_name, int new_len, -- int must_be_dir); -- --static inline void --str_upper(char *name) --{ -- while (*name) -- { -- if (*name >= 'a' && *name <= 'z') -- { -+ ncp_rename(struct inode *old_dir, const char *old_name, int old_len, -+ struct inode *new_dir, const char *new_name, int new_len, -+ int must_be_dir); -+ -+static inline void str_upper(char *name) -+{ -+ while (*name) { -+ if (*name >= 'a' && *name <= 'z') { - *name -= ('a' - 'A'); - } - name++; - } - } - --static inline void --str_lower(char *name) -+static inline void str_lower(char *name) - { -- while (*name) -- { -- if (*name >= 'A' && *name <= 'Z') -- { -+ while (*name) { -+ if (*name >= 'A' && *name <= 'Z') { - *name += ('a' - 'A'); - } -- name ++; -+ name++; - } - } - --static inline int --ncp_namespace(struct inode *i) -+static inline int ncp_namespace(struct inode *i) - { -- struct ncp_server *server = NCP_SERVER(i); -+ struct ncp_server *server = NCP_SERVER(i); - struct nw_info_struct *info = NCP_ISTRUCT(i); - return server->name_space[info->volNumber]; - } - --static inline int --ncp_preserve_case(struct inode *i) -+static inline int ncp_preserve_case(struct inode *i) - { - return (ncp_namespace(i) == NW_NS_OS2); - } - --static struct file_operations ncp_dir_operations = { -- NULL, /* lseek - default */ -+static struct file_operations ncp_dir_operations = -+{ -+ NULL, /* lseek - default */ - ncp_dir_read, /* read - bad */ - NULL, /* write - bad */ - ncp_readdir, /* readdir */ -@@ -123,23 +116,24 @@ - NULL /* fsync */ - }; - --struct inode_operations ncp_dir_inode_operations = { -+struct inode_operations ncp_dir_inode_operations = -+{ - &ncp_dir_operations, /* default directory file ops */ - ncp_create, /* create */ -- ncp_lookup, /* lookup */ -+ ncp_lookup, /* lookup */ - NULL, /* link */ -- ncp_unlink, /* unlink */ -+ ncp_unlink, /* unlink */ - NULL, /* symlink */ -- ncp_mkdir, /* mkdir */ -- ncp_rmdir, /* rmdir */ -+ ncp_mkdir, /* mkdir */ -+ ncp_rmdir, /* rmdir */ - NULL, /* mknod */ -- ncp_rename, /* rename */ -+ ncp_rename, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* bmap */ - NULL, /* truncate */ - NULL, /* permission */ -- NULL /* smap */ -+ NULL /* smap */ - }; - - -@@ -151,223 +145,181 @@ - * enable the NFS exportability of a ncpfs-mounted volume. - */ - --static inline int --ncp_single_volume(struct ncp_server *server) -+static inline int ncp_single_volume(struct ncp_server *server) - { - return (server->m.mounted_vol[0] != '\0'); - } - - inline ino_t --ncp_info_ino(struct ncp_server *server, struct ncp_inode_info *info) -+ ncp_info_ino(struct ncp_server * server, struct ncp_inode_info * info) - { - return ncp_single_volume(server) -- ? info->finfo.i.dirEntNum : (ino_t)info; -+ ? info->finfo.i.dirEntNum : (ino_t) info; - } - --static inline int --ncp_is_server_root(struct inode *inode) -+static inline int ncp_is_server_root(struct inode *inode) - { - struct ncp_server *s = NCP_SERVER(inode); - -- return ( (!ncp_single_volume(s)) -+ return ((!ncp_single_volume(s)) - && (inode->i_ino == ncp_info_ino(s, &(s->root)))); - } - - struct ncp_inode_info * --ncp_find_inode(struct inode *inode) -+ ncp_find_inode(struct inode *inode) - { - struct ncp_server *server = NCP_SERVER(inode); -- struct ncp_inode_info *root = &(server->root); -- struct ncp_inode_info *this = root; -+ struct ncp_inode_info *root = &(server->root); -+ struct ncp_inode_info *this = root; - - ino_t ino = inode->i_ino; - -- do -- { -- if (ino == ncp_info_ino(server, this)) -- { -+ do { -+ if (ino == ncp_info_ino(server, this)) { - return this; - } - this = this->next; -- } -+ } - while (this != root); - - return NULL; - } -- --static long --ncp_dir_read(struct inode *inode, struct file *filp, char *buf, unsigned long count) -+ -+static long ncp_dir_read(struct inode *inode, struct file *filp, char *buf, unsigned long count) - { - return -EISDIR; - } - --static kdev_t c_dev = 0; --static unsigned long c_ino = 0; --static int c_size; --static int c_seen_eof; --static int c_last_returned_index; --static struct ncp_dirent* c_entry = NULL; --static int c_lock = 0; -+static kdev_t c_dev = 0; -+static unsigned long c_ino = 0; -+static int c_size; -+static int c_seen_eof; -+static int c_last_returned_index; -+static struct ncp_dirent *c_entry = NULL; -+static int c_lock = 0; - static struct wait_queue *c_wait = NULL; - --static inline void --ncp_lock_dircache(void) -+static inline void ncp_lock_dircache(void) - { - while (c_lock) - sleep_on(&c_wait); - c_lock = 1; - } - --static inline void --ncp_unlock_dircache(void) -+static inline void ncp_unlock_dircache(void) - { - c_lock = 0; - wake_up(&c_wait); - } - --static int --ncp_readdir(struct inode *inode, struct file *filp, -- void *dirent, filldir_t filldir) -+static int ncp_readdir(struct inode *inode, struct file *filp, -+ void *dirent, filldir_t filldir) - { - int result = 0; - int i = 0; -- int index = 0; -+ int index = 0; - struct ncp_dirent *entry = NULL; -- struct ncp_server *server = NCP_SERVER(inode); -+ struct ncp_server *server = NCP_SERVER(inode); - struct ncp_inode_info *dir = NCP_INOP(inode); - -- DDPRINTK("ncp_readdir: filp->f_pos = %d\n", (int)filp->f_pos); -+ DDPRINTK("ncp_readdir: filp->f_pos = %d\n", (int) filp->f_pos); - DDPRINTK("ncp_readdir: inode->i_ino = %ld, c_ino = %ld\n", - inode->i_ino, c_ino); - -- if (!inode || !S_ISDIR(inode->i_mode)) -- { -+ if (!inode || !S_ISDIR(inode->i_mode)) { - printk("ncp_readdir: inode is NULL or not a directory\n"); - return -EBADF; - } -- -- if (!ncp_conn_valid(server)) -- { -+ if (!ncp_conn_valid(server)) { - return -EIO; - } -- - ncp_lock_dircache(); - -- if (c_entry == NULL) -- { -- i = sizeof (struct ncp_dirent) * NCP_READDIR_CACHE_SIZE; -+ if (c_entry == NULL) { -+ i = sizeof(struct ncp_dirent) * NCP_READDIR_CACHE_SIZE; - c_entry = (struct ncp_dirent *) vmalloc(i); -- if (c_entry == NULL) -- { -+ if (c_entry == NULL) { - printk("ncp_readdir: no MEMORY for cache\n"); - result = -ENOMEM; - goto finished; - } - } -- -- if (filp->f_pos == 0) -- { -- ncp_invalid_dir_cache(inode); -- if (filldir(dirent,".",1, filp->f_pos, -- ncp_info_ino(server, dir)) < 0) -- { -+ if (filp->f_pos == 0) { -+ ncp_invalid_dir_cache(inode); -+ if (filldir(dirent, ".", 1, filp->f_pos, -+ ncp_info_ino(server, dir)) < 0) { - goto finished; - } - filp->f_pos += 1; -- } -- -- if (filp->f_pos == 1) -- { -- if (filldir(dirent,"..",2, filp->f_pos, -- ncp_info_ino(server, dir->dir)) < 0) -- { -+ } -+ if (filp->f_pos == 1) { -+ if (filldir(dirent, "..", 2, filp->f_pos, -+ ncp_info_ino(server, dir->dir)) < 0) { - goto finished; - } - filp->f_pos += 1; - } -- -- if ((inode->i_dev == c_dev) && (inode->i_ino == c_ino)) -- { -- for (i = 0; i < c_size; i++) -- { -- if (filp->f_pos == c_entry[i].f_pos) -- { -- entry = &c_entry[i]; -- c_last_returned_index = i; -- index = i; -- break; -+ if ((inode->i_dev == c_dev) && (inode->i_ino == c_ino)) { -+ for (i = 0; i < c_size; i++) { -+ if (filp->f_pos == c_entry[i].f_pos) { -+ entry = &c_entry[i]; -+ c_last_returned_index = i; -+ index = i; -+ break; - } - } -- if ((entry == NULL) && c_seen_eof) -- { -+ if ((entry == NULL) && c_seen_eof) { - goto finished; - } - } -- -- if (entry == NULL) -- { -+ if (entry == NULL) { - int entries; - DDPRINTK("ncp_readdir: Not found in cache.\n"); - -- if (ncp_is_server_root(inode)) -- { -+ if (ncp_is_server_root(inode)) { - entries = ncp_read_volume_list(server, filp->f_pos, -- NCP_READDIR_CACHE_SIZE); -+ NCP_READDIR_CACHE_SIZE); - DPRINTK("ncp_read_volume_list returned %d\n", entries); - -- } -- else -- { -+ } else { - entries = ncp_do_readdir(server, inode, filp->f_pos, - NCP_READDIR_CACHE_SIZE, - c_entry); - DPRINTK("ncp_readdir returned %d\n", entries); - } - -- if (entries < 0) -- { -+ if (entries < 0) { - c_dev = 0; - c_ino = 0; - result = entries; - goto finished; - } -- -- if (entries > 0) -- { -- c_seen_eof = (entries < NCP_READDIR_CACHE_SIZE); -- c_dev = inode->i_dev; -- c_ino = inode->i_ino; -+ if (entries > 0) { -+ c_seen_eof = (entries < NCP_READDIR_CACHE_SIZE); -+ c_dev = inode->i_dev; -+ c_ino = inode->i_ino; - c_size = entries; - entry = c_entry; -- c_last_returned_index = 0; -- index = 0; -+ c_last_returned_index = 0; -+ index = 0; - -- if (!ncp_preserve_case(inode)) -- { -- for (i = 0; i < c_size; i++) -- { -+ if (!ncp_preserve_case(inode)) { -+ for (i = 0; i < c_size; i++) { - str_lower(c_entry[i].i.entryName); - } - } - } - } -- -- if (entry == NULL) -- { -- /* Nothing found, even from a ncp call */ -+ if (entry == NULL) { -+ /* Nothing found, even from a ncp call */ - goto finished; -- } -- -- while (index < c_size) -- { -+ } -+ while (index < c_size) { - ino_t ino; - -- if (ncp_single_volume(server)) -- { -- ino = (ino_t)(entry->i.dirEntNum); -- } -- else -- { -+ if (ncp_single_volume(server)) { -+ ino = (ino_t) (entry->i.dirEntNum); -+ } else { - /* For getwd() we have to return the correct - * inode in d_ino if the inode is currently in - * use. Otherwise the inode number does not -@@ -379,41 +331,36 @@ - /* Some programs seem to be confused about a - * zero inode number, so we set it to one. - * Thanks to Gordon Chaffee for this one. */ -- if (ino_info == NULL) -- { -+ if (ino_info == NULL) { - ino_info = (struct ncp_inode_info *) 1; - } -- ino = (ino_t)(ino_info); -+ ino = (ino_t) (ino_info); - } - - DDPRINTK("ncp_readdir: entry->path= %s\n", entry->i.entryName); - DDPRINTK("ncp_readdir: entry->f_pos = %ld\n", entry->f_pos); - -- if (filldir(dirent, entry->i.entryName, entry->i.nameLen, -- entry->f_pos, ino) < 0) -- { -+ if (filldir(dirent, entry->i.entryName, entry->i.nameLen, -+ entry->f_pos, ino) < 0) { - break; -- } -- -- if ( (inode->i_dev != c_dev) -+ } -+ if ((inode->i_dev != c_dev) - || (inode->i_ino != c_ino) -- || (entry->f_pos != filp->f_pos)) -- { -+ || (entry->f_pos != filp->f_pos)) { - /* Someone has destroyed the cache while we slept - in filldir */ - break; - } -- filp->f_pos += 1; -- index += 1; -- entry += 1; -+ filp->f_pos += 1; -+ index += 1; -+ entry += 1; - } -- finished: -+ finished: - ncp_unlock_dircache(); - return result; - } - --static int --ncp_read_volume_list(struct ncp_server *server, int fpos, int cache_size) -+static int ncp_read_volume_list(struct ncp_server *server, int fpos, int cache_size) - { - struct ncp_dirent *entry = c_entry; - -@@ -421,47 +368,35 @@ - int i; - - #if 1 -- if (fpos < 2) -- { -+ if (fpos < 2) { - printk("OOPS, we expect fpos >= 2"); - fpos = 2; - } - #endif - -- for (i=0; i 0) -- { -- if (total_count < fpos) -- { -+ if (strlen(info.volume_name) > 0) { -+ if (total_count < fpos) { - DPRINTK("ncp_read_volumes: skipped vol: %s\n", - info.volume_name); -- } -- else if (total_count >= fpos + cache_size) -- { -+ } else if (total_count >= fpos + cache_size) { - return (total_count - fpos); -- } -- else -- { -+ } else { - DPRINTK("ncp_read_volumes: found vol: %s\n", - info.volume_name); - - if (ncp_lookup_volume(server, - info.volume_name, -- &(entry->i)) != 0) -- { -+ &(entry->i)) != 0) { - DPRINTK("ncpfs: could not lookup vol " - "%s\n", info.volume_name); - continue; - } -- - entry->f_pos = total_count; - entry += 1; - } -@@ -471,59 +406,46 @@ - return (total_count - fpos); - } - --static int --ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos, -- int cache_size, struct ncp_dirent *entry) -+static int ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos, -+ int cache_size, struct ncp_dirent *entry) - { - static struct nw_search_sequence seq; - static struct inode *last_dir; - static int total_count; - - #if 1 -- if (fpos < 2) -- { -+ if (fpos < 2) { - printk("OOPS, we expect fpos >= 2"); - fpos = 2; - } - #endif - DPRINTK("ncp_do_readdir: fpos = %d\n", fpos); - -- if (fpos == 2) -- { -+ if (fpos == 2) { - last_dir = NULL; - total_count = 2; - } -- -- if ((fpos != total_count) || (dir != last_dir)) -- { -+ if ((fpos != total_count) || (dir != last_dir)) { - total_count = 2; - last_dir = dir; - - DPRINTK("ncp_do_readdir: re-used seq for %s\n", - NCP_ISTRUCT(dir)->entryName); - -- if (ncp_initialize_search(server, NCP_ISTRUCT(dir), &seq)!=0) -- { -+ if (ncp_initialize_search(server, NCP_ISTRUCT(dir), &seq) != 0) { - DPRINTK("ncp_init_search failed\n"); - return total_count - fpos; - } - } -- -- while (total_count < fpos + cache_size) -- { -+ while (total_count < fpos + cache_size) { - if (ncp_search_for_file_or_subdir(server, &seq, -- &(entry->i)) != 0) -- { -+ &(entry->i)) != 0) { - return total_count - fpos; - } -- -- if (total_count < fpos) -- { -+ if (total_count < fpos) { - DPRINTK("ncp_do_readdir: skipped file: %s\n", - entry->i.entryName); -- } -- else -- { -+ } else { - DDPRINTK("ncp_do_r: file: %s, f_pos=%d,total_count=%d", - entry->i.entryName, fpos, total_count); - entry->s = seq; -@@ -535,143 +457,124 @@ - return (total_count - fpos); - } - --void --ncp_init_dir_cache(void) -+void ncp_init_dir_cache(void) - { -- c_dev = 0; -- c_ino = 0; -- c_entry = NULL; -+ c_dev = 0; -+ c_ino = 0; -+ c_entry = NULL; - } - --void --ncp_invalid_dir_cache(struct inode *ino) -+void ncp_invalid_dir_cache(struct inode *ino) - { -- if ((ino->i_dev == c_dev) && (ino->i_ino == c_ino)) -- { -+ if ((ino->i_dev == c_dev) && (ino->i_ino == c_ino)) { - c_dev = 0; -- c_ino = 0; -- c_seen_eof = 0; -- } -+ c_ino = 0; -+ c_seen_eof = 0; -+ } - } - --void --ncp_free_dir_cache(void) --{ -- DPRINTK("ncp_free_dir_cache: enter\n"); -- -- if (c_entry == NULL) -- { -- return; -- } -+void ncp_free_dir_cache(void) -+{ -+ DPRINTK("ncp_free_dir_cache: enter\n"); - -+ if (c_entry == NULL) { -+ return; -+ } - vfree(c_entry); - c_entry = NULL; - -- DPRINTK("ncp_free_dir_cache: exit\n"); -+ DPRINTK("ncp_free_dir_cache: exit\n"); - } - - - static struct inode * --ncp_iget(struct inode *dir, struct nw_file_info *finfo) -+ ncp_iget(struct inode *dir, struct nw_file_info *finfo) - { - struct inode *inode; -- struct ncp_inode_info *new_inode_info; -- struct ncp_inode_info *root; -+ struct ncp_inode_info *new_inode_info; -+ struct ncp_inode_info *root; - -- if (dir == NULL) -- { -+ if (dir == NULL) { - printk("ncp_iget: dir is NULL\n"); - return NULL; - } -- -- if (finfo == NULL) -- { -+ if (finfo == NULL) { - printk("ncp_iget: finfo is NULL\n"); - return NULL; - } -+ new_inode_info = ncp_kmalloc(sizeof(struct ncp_inode_info), -+ GFP_KERNEL); - -- new_inode_info = ncp_kmalloc(sizeof(struct ncp_inode_info), -- GFP_KERNEL); -- -- if (new_inode_info == NULL) -- { -- printk("ncp_iget: could not alloc mem for %s\n", -+ if (new_inode_info == NULL) { -+ printk("ncp_iget: could not alloc mem for %s\n", - finfo->i.entryName); -- return NULL; -- } -+ return NULL; -+ } -+ new_inode_info->state = NCP_INODE_LOOKED_UP; -+ new_inode_info->nused = 0; -+ new_inode_info->dir = NCP_INOP(dir); -+ new_inode_info->finfo = *finfo; -+ -+ NCP_INOP(dir)->nused += 1; -+ -+ /* We have to link the new inode_info into the doubly linked -+ list of inode_infos to make a complete linear search -+ possible. */ -+ -+ root = &(NCP_SERVER(dir)->root); -+ -+ new_inode_info->prev = root; -+ new_inode_info->next = root->next; -+ root->next->prev = new_inode_info; -+ root->next = new_inode_info; - -- new_inode_info->state = NCP_INODE_LOOKED_UP; -- new_inode_info->nused = 0; -- new_inode_info->dir = NCP_INOP(dir); -- new_inode_info->finfo = *finfo; -- -- NCP_INOP(dir)->nused += 1; -- -- /* We have to link the new inode_info into the doubly linked -- list of inode_infos to make a complete linear search -- possible. */ -- -- root = &(NCP_SERVER(dir)->root); -- -- new_inode_info->prev = root; -- new_inode_info->next = root->next; -- root->next->prev = new_inode_info; -- root->next = new_inode_info; -- - if (!(inode = iget(dir->i_sb, ncp_info_ino(NCP_SERVER(dir), -- new_inode_info)))) -- { -+ new_inode_info)))) { - printk("ncp_iget: iget failed!"); - return NULL; - } -- - return inode; - } - --void --ncp_free_inode_info(struct ncp_inode_info *i) -+void ncp_free_inode_info(struct ncp_inode_info *i) - { -- if (i == NULL) -- { -- printk("ncp_free_inode: i == NULL\n"); -- return; -- } -- -- i->state = NCP_INODE_CACHED; -- while ((i->nused == 0) && (i->state == NCP_INODE_CACHED)) -- { -- struct ncp_inode_info *dir = i->dir; -+ if (i == NULL) { -+ printk("ncp_free_inode: i == NULL\n"); -+ return; -+ } -+ i->state = NCP_INODE_CACHED; -+ while ((i->nused == 0) && (i->state == NCP_INODE_CACHED)) { -+ struct ncp_inode_info *dir = i->dir; - -- i->next->prev = i->prev; -- i->prev->next = i->next; -+ i->next->prev = i->prev; -+ i->prev->next = i->next; - - DDPRINTK("ncp_free_inode_info: freeing %s\n", - i->finfo.i.entryName); - -- ncp_kfree_s(i, sizeof(struct ncp_inode_info)); -+ ncp_kfree_s(i, sizeof(struct ncp_inode_info)); - -- if (dir == i) return; -+ if (dir == i) -+ return; - -- (dir->nused)--; -- i = dir; -- } -+ (dir->nused)--; -+ i = dir; -+ } - } -- --void --ncp_init_root(struct ncp_server *server) -+ -+void ncp_init_root(struct ncp_server *server) - { -- struct ncp_inode_info *root = &(server->root); -+ struct ncp_inode_info *root = &(server->root); - struct nw_info_struct *i = &(root->finfo.i); - unsigned short dummy; - -- DPRINTK("ncp_init_root: server %s\n", server->m.server_name); -- DPRINTK("ncp_init_root: i = %x\n", (int)i); -+ DPRINTK("ncp_init_root: i = %x\n", (int) i); - -- root->finfo.opened = 0; -- i->attributes = aDIR; -+ root->finfo.opened = 0; -+ i->attributes = aDIR; - i->dataStreamSize = 1024; - i->dirEntNum = i->DosDirNum = 0; -- i->volNumber = NCP_NUMBER_OF_VOLUMES+1; /* illegal volnum */ -+ i->volNumber = NCP_NUMBER_OF_VOLUMES + 1; /* illegal volnum */ - ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate)); - ncp_date_unix2dos(0, &(i->modifyTime), &(i->modifyDate)); - ncp_date_unix2dos(0, &dummy, &(i->lastAccessDate)); -@@ -683,25 +586,21 @@ - i->nameLen = 0; - i->entryName[0] = '\0'; - -- root->state = NCP_INODE_LOOKED_UP; -- root->nused = 1; -- root->dir = root; -- root->next = root->prev = root; -- return; -+ root->state = NCP_INODE_LOOKED_UP; -+ root->nused = 1; -+ root->dir = root; -+ root->next = root->prev = root; -+ return; - } - --int --ncp_conn_logged_in(struct ncp_server *server) -+int ncp_conn_logged_in(struct ncp_server *server) - { -- if (server->m.mounted_vol[0] == '\0') -- { -+ if (server->m.mounted_vol[0] == '\0') { - return 0; - } -- - str_upper(server->m.mounted_vol); - if (ncp_lookup_volume(server, server->m.mounted_vol, -- &(server->root.finfo.i)) != 0) -- { -+ &(server->root.finfo.i)) != 0) { - return -ENOENT; - } - str_lower(server->root.finfo.i.entryName); -@@ -709,202 +608,166 @@ - return 0; - } - --void --ncp_free_all_inodes(struct ncp_server *server) -+void ncp_free_all_inodes(struct ncp_server *server) - { -- /* Here nothing should be to do. I do not know whether it's -- better to leave some memory allocated or be stuck in an -- endless loop */ -+ /* Here nothing should be to do. I do not know whether it's -+ better to leave some memory allocated or be stuck in an -+ endless loop */ - #if 1 -- struct ncp_inode_info *root = &(server->root); -+ struct ncp_inode_info *root = &(server->root); - -- if (root->next != root) -- { -- printk("ncp_free_all_inodes: INODES LEFT!!!\n"); -- } -- -- while (root->next != root) -- { -- printk("ncp_free_all_inodes: freeing inode\n"); -- ncp_free_inode_info(root->next); -- /* In case we have an endless loop.. */ -- schedule(); -- } --#endif -- -- return; -+ if (root->next != root) { -+ printk("ncp_free_all_inodes: INODES LEFT!!!\n"); -+ } -+ while (root->next != root) { -+ printk("ncp_free_all_inodes: freeing inode\n"); -+ ncp_free_inode_info(root->next); -+ /* In case we have an endless loop.. */ -+ schedule(); -+ } -+#endif -+ -+ return; - } - - /* We will search the inode that belongs to this name, currently by a - complete linear search through the inodes belonging to this - filesystem. This has to be fixed. */ - static struct ncp_inode_info * --ncp_find_dir_inode(struct inode *dir, const char *name) -+ ncp_find_dir_inode(struct inode *dir, const char *name) - { - struct ncp_server *server = NCP_SERVER(dir); - struct nw_info_struct *dir_info = NCP_ISTRUCT(dir); -- struct ncp_inode_info *result = &(server->root); -+ struct ncp_inode_info *result = &(server->root); - -- if (name == NULL) -- { -- return NULL; -+ if (name == NULL) { -+ return NULL; - } -- -- do -- { -- if ( (result->dir->finfo.i.dirEntNum == dir_info->dirEntNum) -- && (result->dir->finfo.i.volNumber == dir_info->volNumber) -+ do { -+ if ((result->dir->finfo.i.dirEntNum == dir_info->dirEntNum) -+ && (result->dir->finfo.i.volNumber == dir_info->volNumber) - && (strcmp(result->finfo.i.entryName, name) == 0) -- /* The root dir is never looked up using this -- * routine. Without the following test a root -- * directory 'sys' in a volume named 'sys' could -- * never be looked up, because -- * server->root->dir==server->root. */ -- && (result != &(server->root))) -- { -- return result; -+ /* The root dir is never looked up using this -+ * routine. Without the following test a root -+ * directory 'sys' in a volume named 'sys' could -+ * never be looked up, because -+ * server->root->dir==server->root. */ -+ && (result != &(server->root))) { -+ return result; - } -- result = result->next; -+ result = result->next; - -- } -+ } - while (result != &(server->root)); - -- return NULL; -+ return NULL; - } - --static int --ncp_lookup(struct inode *dir, const char *__name, int len, -- struct inode **result) -+static int ncp_lookup(struct inode *dir, const char *__name, int len, -+ struct inode **result) - { - struct nw_file_info finfo; - struct ncp_server *server; - struct ncp_inode_info *result_info; - int found_in_cache; - int down_case = 0; -- char name[len+1]; -+ char name[len + 1]; - - *result = NULL; - -- if (!dir || !S_ISDIR(dir->i_mode)) -- { -+ if (!dir || !S_ISDIR(dir->i_mode)) { - printk("ncp_lookup: inode is NULL or not a directory.\n"); - iput(dir); - return -ENOENT; - } -- - server = NCP_SERVER(dir); - -- if (!ncp_conn_valid(server)) -- { -+ if (!ncp_conn_valid(server)) { - iput(dir); - return -EIO; - } -- - DPRINTK("ncp_lookup: %s, len %d\n", __name, len); - - /* Fast cheat for . */ -- if (len == 0 || (len == 1 && __name[0] == '.')) -- { -+ if (len == 0 || (len == 1 && __name[0] == '.')) { - *result = dir; - return 0; - } -- - /* ..and for .. */ -- if (len == 2 && __name[0] == '.' && __name[1] == '.') -- { -+ if (len == 2 && __name[0] == '.' && __name[1] == '.') { - struct ncp_inode_info *parent = NCP_INOP(dir)->dir; - -- if (parent->state == NCP_INODE_CACHED) -- { -+ if (parent->state == NCP_INODE_CACHED) { - parent->state = NCP_INODE_LOOKED_UP; - } -- - *result = iget(dir->i_sb, ncp_info_ino(server, parent)); - iput(dir); -- if (*result == 0) -- { -+ if (*result == 0) { - return -EACCES; -- } -- else -- { -+ } else { - return 0; - } - } -- - memcpy(name, __name, len); - name[len] = 0; - lock_super(dir->i_sb); - result_info = ncp_find_dir_inode(dir, name); - -- if (result_info != 0) -- { -- if (result_info->state == NCP_INODE_CACHED) -- { -- result_info->state = NCP_INODE_LOOKED_UP; -+ if (result_info != 0) { -+ if (result_info->state == NCP_INODE_CACHED) { -+ result_info->state = NCP_INODE_LOOKED_UP; - } -+ /* Here we convert the inode_info address into an -+ inode number */ - -- /* Here we convert the inode_info address into an -- inode number */ -- -- *result = iget(dir->i_sb, ncp_info_ino(server, result_info)); -+ *result = iget(dir->i_sb, ncp_info_ino(server, result_info)); - unlock_super(dir->i_sb); -- iput(dir); -- -- if (*result == NULL) -- { -- return -EACCES; -- } -+ iput(dir); - -+ if (*result == NULL) { -+ return -EACCES; -+ } - return 0; -- } -- -- /* If the file is in the dir cache, we do not have to ask the -- server. */ -+ } -+ /* If the file is in the dir cache, we do not have to ask the -+ server. */ - -- found_in_cache = 0; -+ found_in_cache = 0; - ncp_lock_dircache(); - -- if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino)) -- { -- int first = c_last_returned_index; -- int i; -- -- i = first; -- do -- { -- DDPRINTK("ncp_lookup: trying index: %d, name: %s\n", -+ if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino)) { -+ int first = c_last_returned_index; -+ int i; -+ -+ i = first; -+ do { -+ DDPRINTK("ncp_lookup: trying index: %d, name: %s\n", - i, c_entry[i].i.entryName); - -- if (strcmp(c_entry[i].i.entryName, name) == 0) -- { -- DPRINTK("ncp_lookup: found in cache!\n"); -+ if (strcmp(c_entry[i].i.entryName, name) == 0) { -+ DPRINTK("ncp_lookup: found in cache!\n"); - finfo.i = c_entry[i].i; - found_in_cache = 1; - break; -- } -- i = (i + 1) % c_size; -- } -+ } -+ i = (i + 1) % c_size; -+ } - while (i != first); -- } -+ } - ncp_unlock_dircache(); - -- if (found_in_cache == 0) -- { -+ if (found_in_cache == 0) { - int res; - - DDPRINTK("ncp_lookup: do_lookup on %s/%s\n", - NCP_ISTRUCT(dir)->entryName, name); - -- if (ncp_is_server_root(dir)) -- { -+ if (ncp_is_server_root(dir)) { - str_upper(name); - down_case = 1; - res = ncp_lookup_volume(server, name, &(finfo.i)); -- } -- else -- { -- if (!ncp_preserve_case(dir)) -- { -+ } else { -+ if (!ncp_preserve_case(dir)) { - str_upper(name); - down_case = 1; - } -@@ -913,313 +776,246 @@ - NCP_ISTRUCT(dir)->dirEntNum, - name, &(finfo.i)); - } -- if (res != 0) -- { -+ if (res != 0) { - unlock_super(dir->i_sb); -- iput(dir); -- return -ENOENT; -- } -- } -- -+ iput(dir); -+ return -ENOENT; -+ } -+ } - finfo.opened = 0; - -- if (down_case != 0) -- { -+ if (down_case != 0) { - str_lower(finfo.i.entryName); - } -- -- if (!(*result = ncp_iget(dir, &finfo))) -- { -+ if (!(*result = ncp_iget(dir, &finfo))) { - unlock_super(dir->i_sb); - iput(dir); - return -EACCES; - } -- - unlock_super(dir->i_sb); - iput(dir); - return 0; - } - --static int --ncp_create(struct inode *dir, const char *name, int len, int mode, -- struct inode **result) -+static int ncp_create(struct inode *dir, const char *name, int len, int mode, -+ struct inode **result) - { - struct nw_file_info finfo; -- __u8 _name[len+1]; -+ __u8 _name[len + 1]; - - *result = NULL; - -- if (!dir || !S_ISDIR(dir->i_mode)) -- { -+ if (!dir || !S_ISDIR(dir->i_mode)) { - printk("ncp_create: inode is NULL or not a directory\n"); - iput(dir); - return -ENOENT; - } -- if (!ncp_conn_valid(NCP_SERVER(dir))) -- { -+ if (!ncp_conn_valid(NCP_SERVER(dir))) { - iput(dir); - return -EIO; - } -- - strncpy(_name, name, len); - _name[len] = '\0'; - -- if (!ncp_preserve_case(dir)) -- { -+ if (!ncp_preserve_case(dir)) { - str_upper(_name); - } -- - lock_super(dir->i_sb); - if (ncp_open_create_file_or_subdir(NCP_SERVER(dir), - NCP_ISTRUCT(dir), _name, -- OC_MODE_CREATE|OC_MODE_OPEN| -+ OC_MODE_CREATE | OC_MODE_OPEN | - OC_MODE_REPLACE, -- 0, AR_READ|AR_WRITE, -- &finfo) != 0) -- { -+ 0, AR_READ | AR_WRITE, -+ &finfo) != 0) { - unlock_super(dir->i_sb); - iput(dir); - return -EACCES; - } -- - ncp_invalid_dir_cache(dir); - -- if (!ncp_preserve_case(dir)) -- { -+ if (!ncp_preserve_case(dir)) { - str_lower(finfo.i.entryName); - } -- - finfo.access = O_RDWR; - -- if (!(*result = ncp_iget(dir, &finfo)) < 0) -- { -+ if (!(*result = ncp_iget(dir, &finfo)) < 0) { - ncp_close_file(NCP_SERVER(dir), finfo.file_handle); - unlock_super(dir->i_sb); - iput(dir); - return -EINVAL; - } -- - unlock_super(dir->i_sb); - iput(dir); -- return 0; -+ return 0; - } - --static int --ncp_mkdir(struct inode *dir, const char *name, int len, int mode) -+static int ncp_mkdir(struct inode *dir, const char *name, int len, int mode) - { - int error; - struct nw_file_info new_dir; -- __u8 _name[len+1]; -+ __u8 _name[len + 1]; - -- if ( (name[0] == '.') -- && ( (len == 1) -- || ( (len == 2) -- && (name[1] == '.')))) -- { -+ if ((name[0] == '.') -+ && ((len == 1) -+ || ((len == 2) -+ && (name[1] == '.')))) { - iput(dir); - return -EEXIST; - } -- - strncpy(_name, name, len); - _name[len] = '\0'; - -- if (!ncp_preserve_case(dir)) -- { -+ if (!ncp_preserve_case(dir)) { - str_upper(_name); - } -- -- if (!dir || !S_ISDIR(dir->i_mode)) -- { -+ if (!dir || !S_ISDIR(dir->i_mode)) { - printk("ncp_mkdir: inode is NULL or not a directory\n"); - iput(dir); - return -ENOENT; - } -- if (!ncp_conn_valid(NCP_SERVER(dir))) -- { -+ if (!ncp_conn_valid(NCP_SERVER(dir))) { - iput(dir); - return -EIO; - } -- - if (ncp_open_create_file_or_subdir(NCP_SERVER(dir), - NCP_ISTRUCT(dir), _name, - OC_MODE_CREATE, aDIR, 0xffff, -- &new_dir) != 0) -- { -+ &new_dir) != 0) { - error = -EACCES; -- } -- else -- { -+ } else { - error = 0; -- ncp_invalid_dir_cache(dir); -- } -+ ncp_invalid_dir_cache(dir); -+ } - - iput(dir); - return error; - } - --static int --ncp_rmdir(struct inode *dir, const char *name, int len) -+static int ncp_rmdir(struct inode *dir, const char *name, int len) - { - int error; -- __u8 _name[len+1]; -+ __u8 _name[len + 1]; - -- if (!dir || !S_ISDIR(dir->i_mode)) -- { -+ if (!dir || !S_ISDIR(dir->i_mode)) { - printk("ncp_rmdir: inode is NULL or not a directory\n"); - iput(dir); - return -ENOENT; - } -- if (!ncp_conn_valid(NCP_SERVER(dir))) -- { -+ if (!ncp_conn_valid(NCP_SERVER(dir))) { - iput(dir); - return -EIO; - } -- if (ncp_find_dir_inode(dir, name) != NULL) -- { -+ if (ncp_find_dir_inode(dir, name) != NULL) { - iput(dir); -- error = -EBUSY; -- } -- else -- { -+ error = -EBUSY; -+ } else { - - strncpy(_name, name, len); - _name[len] = '\0'; - -- if (!ncp_preserve_case(dir)) -- { -+ if (!ncp_preserve_case(dir)) { - str_upper(_name); - } -- -- if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir), -+ if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir), - NCP_ISTRUCT(dir), -- _name)) == 0) -- { -- ncp_invalid_dir_cache(dir); -- } -- else -- { -+ _name)) == 0) { -+ ncp_invalid_dir_cache(dir); -+ } else { - error = -EACCES; - } -- } -+ } - iput(dir); - return error; - } - --static int --ncp_unlink(struct inode *dir, const char *name, int len) -+static int ncp_unlink(struct inode *dir, const char *name, int len) - { - int error; -- __u8 _name[len+1]; -+ __u8 _name[len + 1]; - -- if (!dir || !S_ISDIR(dir->i_mode)) -- { -+ if (!dir || !S_ISDIR(dir->i_mode)) { - printk("ncp_unlink: inode is NULL or not a directory\n"); - iput(dir); - return -ENOENT; - } -- if (!ncp_conn_valid(NCP_SERVER(dir))) -- { -+ if (!ncp_conn_valid(NCP_SERVER(dir))) { - iput(dir); - return -EIO; - } -- if (ncp_find_dir_inode(dir, name) != NULL) -- { -+ if (ncp_find_dir_inode(dir, name) != NULL) { - iput(dir); -- error = -EBUSY; -- } -- else -- { -+ error = -EBUSY; -+ } else { - strncpy(_name, name, len); - _name[len] = '\0'; - -- if (!ncp_preserve_case(dir)) -- { -+ if (!ncp_preserve_case(dir)) { - str_upper(_name); - } -- -- if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir), -+ if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir), - NCP_ISTRUCT(dir), -- _name)) == 0) -- { -- ncp_invalid_dir_cache(dir); -- } -- else -- { -+ _name)) == 0) { -+ ncp_invalid_dir_cache(dir); -+ } else { - error = -EACCES; - } -- } -+ } - iput(dir); - return error; - } - --static int --ncp_rename(struct inode *old_dir, const char *old_name, int old_len, -- struct inode *new_dir, const char *new_name, int new_len, -- int must_be_dir) -+static int ncp_rename(struct inode *old_dir, const char *old_name, int old_len, -+ struct inode *new_dir, const char *new_name, int new_len, -+ int must_be_dir) - { - int res; -- char _old_name[old_len+1]; -- char _new_name[new_len+1]; -+ char _old_name[old_len + 1]; -+ char _new_name[new_len + 1]; - -- if (!old_dir || !S_ISDIR(old_dir->i_mode)) -- { -+ if (!old_dir || !S_ISDIR(old_dir->i_mode)) { - printk("ncp_rename: old inode is NULL or not a directory\n"); -- res = -ENOENT; -- goto finished; -+ res = -ENOENT; -+ goto finished; - } -- -- if (!ncp_conn_valid(NCP_SERVER(old_dir))) -- { -+ if (!ncp_conn_valid(NCP_SERVER(old_dir))) { - res = -EIO; - goto finished; - } -- -- if (!new_dir || !S_ISDIR(new_dir->i_mode)) -- { -+ if (!new_dir || !S_ISDIR(new_dir->i_mode)) { - printk("ncp_rename: new inode is NULL or not a directory\n"); -- res = -ENOENT; -- goto finished; -+ res = -ENOENT; -+ goto finished; -+ } -+ if ((ncp_find_dir_inode(old_dir, old_name) != NULL) -+ || (ncp_find_dir_inode(new_dir, new_name) != NULL)) { -+ res = -EBUSY; -+ goto finished; - } -- -- if ( (ncp_find_dir_inode(old_dir, old_name) != NULL) -- || (ncp_find_dir_inode(new_dir, new_name) != NULL)) -- { -- res = -EBUSY; -- goto finished; -- } -- - strncpy(_old_name, old_name, old_len); - _old_name[old_len] = '\0'; - -- if (!ncp_preserve_case(old_dir)) -- { -+ if (!ncp_preserve_case(old_dir)) { - str_upper(_old_name); - } -- - strncpy(_new_name, new_name, new_len); - _new_name[new_len] = '\0'; - -- if (!ncp_preserve_case(new_dir)) -- { -+ if (!ncp_preserve_case(new_dir)) { - str_upper(_new_name); - } -- - res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir), -- NCP_ISTRUCT(old_dir), _old_name, -- NCP_ISTRUCT(new_dir), _new_name); -+ NCP_ISTRUCT(old_dir), _old_name, -+ NCP_ISTRUCT(new_dir), _new_name); - -- if (res == 0) -- { -- ncp_invalid_dir_cache(old_dir); -- ncp_invalid_dir_cache(new_dir); -- } -- else -- { -+ if (res == 0) { -+ ncp_invalid_dir_cache(old_dir); -+ ncp_invalid_dir_cache(new_dir); -+ } else { - res = -EACCES; - } -- -- finished: -- iput(old_dir); -+ -+ finished: -+ iput(old_dir); - iput(new_dir); - return res; - } -@@ -1228,64 +1024,62 @@ - - /* Linear day numbers of the respective 1sts in non-leap years. */ - --static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 }; -+static int day_n[] = -+{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0}; - /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */ - - - extern struct timezone sys_tz; - --static int --utc2local(int time) -+static int utc2local(int time) - { -- return time - sys_tz.tz_minuteswest*60 + -+ return time - sys_tz.tz_minuteswest * 60 + - (sys_tz.tz_dsttime ? 3600 : 0); - } - --static int --local2utc(int time) -+static int local2utc(int time) - { -- return time + sys_tz.tz_minuteswest*60 - -+ return time + sys_tz.tz_minuteswest * 60 - - (sys_tz.tz_dsttime ? 3600 : 0); - } - - /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ - --int --ncp_date_dos2unix(unsigned short time,unsigned short date) -+int ncp_date_dos2unix(unsigned short time, unsigned short date) - { -- int month,year,secs; -+ int month, year, secs; - -- month = ((date >> 5) & 15)-1; -+ month = ((date >> 5) & 15) - 1; - year = date >> 9; -- secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400* -- ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 && -- month < 2 ? 1 : 0)+3653); -- /* days since 1.1.70 plus 80's leap day */ -+ secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + 86400 * -+ ((date & 31) - 1 + day_n[month] + (year / 4) + year * 365 - ((year & 3) == 0 && -+ month < 2 ? 1 : 0) + 3653); -+ /* days since 1.1.70 plus 80's leap day */ - return local2utc(secs); - } - - - /* Convert linear UNIX date to a MS-DOS time/date pair. */ --void --ncp_date_unix2dos(int unix_date,unsigned short *time, unsigned short *date) -+void ncp_date_unix2dos(int unix_date, unsigned short *time, unsigned short *date) - { -- int day,year,nl_day,month; -+ int day, year, nl_day, month; - - unix_date = utc2local(unix_date); -- *time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+ -- (((unix_date/3600) % 24) << 11); -- day = unix_date/86400-3652; -- year = day/365; -- if ((year+3)/4+365*year > day) year--; -- day -= (year+3)/4+365*year; -+ *time = (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) + -+ (((unix_date / 3600) % 24) << 11); -+ day = unix_date / 86400 - 3652; -+ year = day / 365; -+ if ((year + 3) / 4 + 365 * year > day) -+ year--; -+ day -= (year + 3) / 4 + 365 * year; - if (day == 59 && !(year & 3)) { - nl_day = day; - month = 2; -- } -- else { -- nl_day = (year & 3) || day <= 59 ? day : day-1; -+ } else { -+ nl_day = (year & 3) || day <= 59 ? day : day - 1; - for (month = 0; month < 12; month++) -- if (day_n[month] > nl_day) break; -+ if (day_n[month] > nl_day) -+ break; - } -- *date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9); -+ *date = nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9); - } -diff -urN 2.1.29/fs/ncpfs/file.c 2.1.29-patched/fs/ncpfs/file.c ---- 2.1.29/fs/ncpfs/file.c Sun Jan 26 11:07:44 1997 -+++ 2.1.29-patched/fs/ncpfs/file.c Sat Mar 22 19:13:11 1997 -@@ -21,215 +21,172 @@ - - static inline int min(int a, int b) - { -- return aopened = %d\n", finfo->opened); -+ DPRINTK("ncp_make_open: dirent->opened = %d\n", finfo->opened); - - lock_super(i->i_sb); -- if (finfo->opened == 0) -- { -+ if (finfo->opened == 0) { - finfo->access = -1; -- /* tries max. rights */ -+ /* tries max. rights */ - if (ncp_open_create_file_or_subdir(NCP_SERVER(i), - NULL, NULL, - OC_MODE_OPEN, 0, - AR_READ | AR_WRITE, -- finfo) == 0) -- { -+ finfo) == 0) { - finfo->access = O_RDWR; -- } -- else if (ncp_open_create_file_or_subdir(NCP_SERVER(i), -- NULL, NULL, -- OC_MODE_OPEN, 0, -- AR_READ, -- finfo) == 0) -- { -+ } else if (ncp_open_create_file_or_subdir(NCP_SERVER(i), -+ NULL, NULL, -+ OC_MODE_OPEN, 0, -+ AR_READ, -+ finfo) == 0) { - finfo->access = O_RDONLY; - } -- } -- -+ } - unlock_super(i->i_sb); - -- if ( ((right == O_RDONLY) && ( (finfo->access == O_RDONLY) -- || (finfo->access == O_RDWR))) -- || ((right == O_WRONLY) && ( (finfo->access == O_WRONLY) -- || (finfo->access == O_RDWR))) -- || ((right == O_RDWR) && (finfo->access == O_RDWR))) -- return 0; -+ if (((right == O_RDONLY) && ((finfo->access == O_RDONLY) -+ || (finfo->access == O_RDWR))) -+ || ((right == O_WRONLY) && ((finfo->access == O_WRONLY) -+ || (finfo->access == O_RDWR))) -+ || ((right == O_RDWR) && (finfo->access == O_RDWR))) -+ return 0; - -- return -EACCES; -+ return -EACCES; - } - --static long --ncp_file_read(struct inode *inode, struct file *file, char *buf, unsigned long count) -+static long ncp_file_read(struct inode *inode, struct file *file, char *buf, unsigned long count) - { - int bufsize, already_read; - off_t pos; -- int errno; -+ int errno; - -- DPRINTK("ncp_file_read: enter %s\n", NCP_ISTRUCT(inode)->entryName); -- -- if (inode == NULL) -- { -+ DPRINTK("ncp_file_read: enter %s\n", NCP_ISTRUCT(inode)->entryName); -+ -+ if (inode == NULL) { - DPRINTK("ncp_file_read: inode = NULL\n"); - return -EINVAL; - } -- if (!ncp_conn_valid(NCP_SERVER(inode))) -- { -+ 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", -- inode->i_mode); -+ inode->i_mode); - return -EINVAL; - } -- - pos = file->f_pos; - -- if (pos + count > inode->i_size) -- { -+ if (pos + count > inode->i_size) { - count = inode->i_size - pos; - } -- -- if (count <= 0) -- { -+ if (count <= 0) { - return 0; - } -- -- if ((errno = ncp_make_open(inode, O_RDONLY)) != 0) -- { -- return errno; -+ if ((errno = ncp_make_open(inode, O_RDONLY)) != 0) { -+ return errno; - } -- - bufsize = NCP_SERVER(inode)->buffer_size; - -- already_read = 0; -+ already_read = 0; - - /* First read in as much as possible for each bufsize. */ -- while (already_read < count) -- { -+ while (already_read < count) { - int read_this_time; - int to_read = min(bufsize - (pos % bufsize), - count - already_read); - - if (ncp_read(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, -- pos, to_read, buf, &read_this_time) != 0) -- { -- return -EIO; /* This is not exact, i know.. */ -+ pos, to_read, buf, &read_this_time) != 0) { -+ return -EIO; /* This is not exact, i know.. */ - } -- - pos += read_this_time; - buf += read_this_time; -- already_read += read_this_time; -+ already_read += read_this_time; - -- if (read_this_time < to_read) -- { -- break; -+ if (read_this_time < to_read) { -+ break; - } - } - -- file->f_pos = pos; -+ file->f_pos = pos; - -- if (!IS_RDONLY(inode)) -- { -+ if (!IS_RDONLY(inode)) { - inode->i_atime = CURRENT_TIME; - } -- - 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); - -- return already_read; -+ return already_read; - } - --static long --ncp_file_write(struct inode *inode, struct file *file, const char *buf, -- unsigned long count) -+static long ncp_file_write(struct inode *inode, struct file *file, const char *buf, -+ unsigned long count) - { - int bufsize, already_written; -- off_t pos; -- int errno; -- -- if (inode == NULL) -- { -+ off_t pos; -+ int errno; -+ -+ if (inode == NULL) { - DPRINTK("ncp_file_write: inode = NULL\n"); - return -EINVAL; - } -- if (!ncp_conn_valid(NCP_SERVER(inode))) -- { -+ 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", -- inode->i_mode); -+ inode->i_mode); - return -EINVAL; - } -+ 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; - } -- -- if ((errno = ncp_make_open(inode, O_RDWR)) != 0) -- { -- return errno; -+ if ((errno = ncp_make_open(inode, O_RDWR)) != 0) { -+ return errno; - } -- - pos = file->f_pos; - -- if (file->f_flags & O_APPEND) -- { -+ if (file->f_flags & O_APPEND) { - pos = inode->i_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 to_write = min(bufsize - (pos % bufsize), - count - already_written); - - 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; -- } -- -+ } - pos += written_this_time; - buf += written_this_time; - already_written += written_this_time; - -- if (written_this_time < to_write) -- { -+ if (written_this_time < to_write) { - break; - } - } -@@ -239,18 +196,17 @@ - - file->f_pos = pos; - -- if (pos > inode->i_size) -- { -- inode->i_size = pos; -+ if (pos > inode->i_size) { -+ 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); - - return already_written; - } - --static struct file_operations ncp_file_operations = { -+static struct file_operations ncp_file_operations = -+{ - NULL, /* lseek - default */ - ncp_file_read, /* read */ - ncp_file_write, /* write */ -@@ -258,12 +214,13 @@ - NULL, /* poll - default */ - ncp_ioctl, /* ioctl */ - ncp_mmap, /* mmap */ -- NULL, /* open */ -- NULL, /* release */ -+ NULL, /* open */ -+ NULL, /* release */ - ncp_fsync, /* fsync */ - }; - --struct inode_operations ncp_file_inode_operations = { -+struct inode_operations ncp_file_inode_operations = -+{ - &ncp_file_operations, /* default file operations */ - NULL, /* create */ - NULL, /* lookup */ -diff -urN 2.1.29/fs/ncpfs/inode.c 2.1.29-patched/fs/ncpfs/inode.c ---- 2.1.29/fs/ncpfs/inode.c Sun Jan 19 14:47:26 1997 -+++ 2.1.29-patched/fs/ncpfs/inode.c Sun Mar 23 11:38:08 1997 -@@ -36,8 +36,9 @@ - static void ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz); - static int ncp_notify_change(struct inode *inode, struct iattr *attr); - --static struct super_operations ncp_sops = { -- ncp_read_inode, /* read inode */ -+static struct super_operations ncp_sops = -+{ -+ ncp_read_inode, /* read inode */ - ncp_notify_change, /* notify change */ - NULL, /* write inode */ - ncp_put_inode, /* put inode */ -@@ -51,202 +52,150 @@ - ncp_inode_info's and initializes the inode from the data found - there. It does not allocate or deallocate anything. */ - --static void --ncp_read_inode(struct inode *inode) -+static void ncp_read_inode(struct inode *inode) - { -- /* Our task should be extremely simple here. We only have to -- look up the information somebody else (ncp_iget) put into -- the inode tree. The address of this information is the -- inode->i_ino. Just to make sure everything went well, we -- check it's there. */ -+ /* Our task should be extremely simple here. We only have to -+ look up the information somebody else (ncp_iget) put into -+ the inode tree. The address of this information is the -+ inode->i_ino. Just to make sure everything went well, we -+ check it's there. */ - -- struct ncp_inode_info *inode_info = ncp_find_inode(inode); -+ struct ncp_inode_info *inode_info = ncp_find_inode(inode); - -- if (inode_info == NULL) -- { -+ if (inode_info == NULL) { - /* 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; - } -+ inode_info->state = NCP_INODE_VALID; - -- inode_info->state = NCP_INODE_VALID; -- -- NCP_INOP(inode) = inode_info; -+ NCP_INOP(inode) = inode_info; - inode_info->inode = inode; - -- if (NCP_ISTRUCT(inode)->attributes & aDIR) -- { -- inode->i_mode = NCP_SERVER(inode)->m.dir_mode; -+ if (NCP_ISTRUCT(inode)->attributes & aDIR) { -+ inode->i_mode = NCP_SERVER(inode)->m.dir_mode; - /* for directories dataStreamSize seems to be some - Object ID ??? */ - inode->i_size = 512; -- } -- else -- { -- inode->i_mode = NCP_SERVER(inode)->m.file_mode; -+ } else { -+ inode->i_mode = NCP_SERVER(inode)->m.file_mode; - inode->i_size = le32_to_cpu(NCP_ISTRUCT(inode)->dataStreamSize); - } - -- DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode); -+ DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode); - -- inode->i_nlink = 1; -- inode->i_uid = NCP_SERVER(inode)->m.uid; -- inode->i_gid = NCP_SERVER(inode)->m.gid; -- inode->i_blksize = 512; -- inode->i_rdev = 0; -- -- if ((inode->i_blksize != 0) && (inode->i_size != 0)) -- { -- inode->i_blocks = -- (inode->i_size - 1) / inode->i_blksize + 1; -- } -- else -- { -- inode->i_blocks = 0; -+ inode->i_nlink = 1; -+ inode->i_uid = NCP_SERVER(inode)->m.uid; -+ inode->i_gid = NCP_SERVER(inode)->m.gid; -+ inode->i_blksize = 512; -+ inode->i_rdev = 0; -+ -+ if ((inode->i_blksize != 0) && (inode->i_size != 0)) { -+ inode->i_blocks = -+ (inode->i_size - 1) / inode->i_blksize + 1; -+ } else { -+ inode->i_blocks = 0; - } - - inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(NCP_ISTRUCT(inode)->modifyTime), -- le16_to_cpu(NCP_ISTRUCT(inode)->modifyDate)); -+ le16_to_cpu(NCP_ISTRUCT(inode)->modifyDate)); - inode->i_ctime = ncp_date_dos2unix(le16_to_cpu(NCP_ISTRUCT(inode)->creationTime), -- le16_to_cpu(NCP_ISTRUCT(inode)->creationDate)); -+ le16_to_cpu(NCP_ISTRUCT(inode)->creationDate)); - inode->i_atime = ncp_date_dos2unix(0, -- le16_to_cpu(NCP_ISTRUCT(inode)->lastAccessDate)); -+ le16_to_cpu(NCP_ISTRUCT(inode)->lastAccessDate)); - -- if (S_ISREG(inode->i_mode)) -- { -- inode->i_op = &ncp_file_inode_operations; -- } -- else if (S_ISDIR(inode->i_mode)) -- { -- inode->i_op = &ncp_dir_inode_operations; -- } -- else -- { -- inode->i_op = NULL; -+ if (S_ISREG(inode->i_mode)) { -+ inode->i_op = &ncp_file_inode_operations; -+ } else if (S_ISDIR(inode->i_mode)) { -+ inode->i_op = &ncp_dir_inode_operations; -+ } else { -+ inode->i_op = NULL; - } - } - --static void --ncp_put_inode(struct inode *inode) -+static void 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; - - lock_super(sb); -- if (finfo->opened != 0) -- { -- if (ncp_close_file(NCP_SERVER(inode), finfo->file_handle)!=0) -- { -- /* We can't do anything but complain. */ -- printk("ncp_put_inode: could not close\n"); -- } -- } -- -+ if (finfo->opened != 0) { -+ if (ncp_close_file(NCP_SERVER(inode), finfo->file_handle) != 0) { -+ /* We can't do anything but complain. */ -+ printk("ncp_put_inode: could not close\n"); -+ } -+ } - DDPRINTK("ncp_put_inode: put %s\n", -- finfo->i.entryName); -+ finfo->i.entryName); - -- ncp_free_inode_info(NCP_INOP(inode)); -+ ncp_free_inode_info(NCP_INOP(inode)); - -- if (S_ISDIR(inode->i_mode)) -- { -- DDPRINTK("ncp_put_inode: put directory %ld\n", -+ if (S_ISDIR(inode->i_mode)) { -+ DDPRINTK("ncp_put_inode: put directory %ld\n", - inode->i_ino); -- ncp_invalid_dir_cache(inode); -- } -- -+ ncp_invalid_dir_cache(inode); -+ } - clear_inode(inode); - unlock_super(sb); - } - - struct super_block * --ncp_read_super(struct super_block *sb, void *raw_data, int silent) -+ ncp_read_super(struct super_block *sb, void *raw_data, int silent) - { - struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data; -- struct ncp_server *server; -+ struct ncp_server *server; - struct file *ncp_filp; -- struct file *wdog_filp; -- struct file *msg_filp; - kdev_t dev = sb->s_dev; - int error; - -- if (data == NULL) -- { -+ if (data == NULL) { - printk("ncp_read_super: missing data argument\n"); - sb->s_dev = 0; - return NULL; - } -- -- if (data->version != NCP_MOUNT_VERSION) -- { -+ if (data->version != NCP_MOUNT_VERSION) { - printk("ncp warning: mount version %s than kernel\n", - (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) -- || (!S_ISSOCK(ncp_filp->f_inode->i_mode))) -- { -+ || (!S_ISSOCK(ncp_filp->f_inode->i_mode))) { - printk("ncp_read_super: invalid ncp socket\n"); - sb->s_dev = 0; - return NULL; - } -+ /* We must malloc our own super-block info */ -+ server = (struct ncp_server *) ncp_kmalloc(sizeof(struct ncp_server), -+ GFP_KERNEL); - -- if ( (data->wdog_fd >= NR_OPEN) -- || ((wdog_filp = current->files->fd[data->wdog_fd]) == NULL) -- || (!S_ISSOCK(wdog_filp->f_inode->i_mode))) -- { -- printk("ncp_read_super: invalid wdog socket\n"); -- sb->s_dev = 0; -+ if (server == NULL) { -+ printk("ncp_read_super: could not alloc ncp_server\n"); - return NULL; - } -- -- if ( (data->message_fd >= NR_OPEN) -- || ((msg_filp = current->files->fd[data->message_fd]) == NULL) -- || (!S_ISSOCK(msg_filp->f_inode->i_mode))) -- { -- printk("ncp_read_super: invalid wdog socket\n"); -- sb->s_dev = 0; -- return NULL; -- } -- -- /* We must malloc our own super-block info */ -- server = (struct ncp_server *)ncp_kmalloc(sizeof(struct ncp_server), -- GFP_KERNEL); -- -- if (server == NULL) -- { -- printk("ncp_read_super: could not alloc ncp_server\n"); -- return NULL; -- } -- - ncp_filp->f_count += 1; -- wdog_filp->f_count += 1; -- msg_filp->f_count += 1; - - lock_super(sb); - -- NCP_SBP(sb) = server; -+ NCP_SBP(sb) = server; - -- sb->s_blocksize = 1024; /* Eh... Is this correct? */ -+ sb->s_blocksize = 1024; /* Eh... Is this correct? */ - sb->s_blocksize_bits = 10; - sb->s_magic = NCP_SUPER_MAGIC; - sb->s_dev = dev; - sb->s_op = &ncp_sops; - -- server->ncp_filp = ncp_filp; -- server->wdog_filp = wdog_filp; -- server->msg_filp = msg_filp; -- server->lock = 0; -- server->wait = NULL; -- server->packet = NULL; -+ server->ncp_filp = ncp_filp; -+ server->lock = 0; -+ server->wait = NULL; -+ server->packet = NULL; - server->buffer_size = 0; - server->conn_status = 0; - -- server->m = *data; -+ server->m = *data; - /* Althought anything producing this is buggy, it happens - now because of PATH_MAX changes.. */ - if (server->m.time_out < 10) { -@@ -254,166 +203,98 @@ - printk("You need to recompile your ncpfs utils..\n"); - } - server->m.file_mode = (server->m.file_mode & -- (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG; -- server->m.dir_mode = (server->m.dir_mode & -- (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR; -- -- /* protect against invalid mount points */ -- server->m.mount_point[sizeof(server->m.mount_point)-1] = '\0'; -+ (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG; -+ server->m.dir_mode = (server->m.dir_mode & -+ (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR; - - 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"); - error = -ENOMEM; - unlock_super(sb); - goto fail; - } -- -- /* -- * Make the connection to the server -- */ -- -- if (ncp_catch_watchdog(server) != 0) -- { -- printk("ncp_read_super: Could not catch watchdog\n"); -- error = -EINVAL; -- unlock_super(sb); -- goto fail; -- } -- -- if (ncp_catch_message(server) != 0) -- { -- printk("ncp_read_super: Could not catch messages\n"); -- ncp_dont_catch_watchdog(server); -- error = -EINVAL; -- unlock_super(sb); -- goto fail; -- } -- - ncp_lock_server(server); - error = ncp_connect(server); - ncp_unlock_server(server); - unlock_super(sb); - -- if (error < 0) -- { -+ if (error < 0) { - sb->s_dev = 0; - printk("ncp_read_super: Failed connection, bailing out " -- "(error = %d).\n", -error); -- ncp_kfree_s(server->packet, server->packet_size); -- ncp_dont_catch_watchdog(server); -- goto fail; -+ "(error = %d).\n", -error); -+ ncp_kfree_s(server->packet, server->packet_size); -+ goto fail; - } -- -- 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)); - - ncp_init_root(server); - -- if (!(sb->s_mounted = iget(sb, ncp_info_ino(server, &(server->root))))) -- { -+ if (!(sb->s_mounted = iget(sb, ncp_info_ino(server, -+ &(server->root))))) { - sb->s_dev = 0; - printk("ncp_read_super: get root inode failed\n"); -- goto disconnect; -+ goto disconnect; - } -- - if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE, -- &(server->buffer_size)) != 0) -- { -+ &(server->buffer_size)) != 0) { - sb->s_dev = 0; - printk("ncp_read_super: could not get bufsize\n"); - goto disconnect; - } -- - DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size); - -- MOD_INC_USE_COUNT; -+ MOD_INC_USE_COUNT; - return sb; - -- disconnect: -+ disconnect: - ncp_lock_server(server); - ncp_disconnect(server); - ncp_unlock_server(server); - ncp_kfree_s(server->packet, server->packet_size); -- ncp_dont_catch_watchdog(server); -- fail: -+ fail: - ncp_filp->f_count -= 1; -- wdog_filp->f_count -= 1; -- msg_filp->f_count -= 1; -- ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server)); -- return NULL; -+ ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server)); -+ return NULL; - } - --static void --ncp_put_super(struct super_block *sb) -+static void ncp_put_super(struct super_block *sb) - { -- struct ncp_server *server = NCP_SBP(sb); -+ struct ncp_server *server = NCP_SBP(sb); - - lock_super(sb); - - ncp_lock_server(server); -- ncp_disconnect(server); -+ ncp_disconnect(server); - ncp_unlock_server(server); - - close_fp(server->ncp_filp); -+ kill_proc(server->m.wdog_pid, SIGTERM, 0); - -- ncp_dont_catch_watchdog(server); -- close_fp(server->wdog_filp); -- close_fp(server->msg_filp); -- -- ncp_free_all_inodes(server); -+ ncp_free_all_inodes(server); - -- ncp_kfree_s(server->packet, server->packet_size); -+ ncp_kfree_s(server->packet, server->packet_size); - - sb->s_dev = 0; -- ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server)); -+ ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server)); - NCP_SBP(sb) = NULL; - - unlock_super(sb); - -- MOD_DEC_USE_COUNT; -+ MOD_DEC_USE_COUNT; - } - --/* This routine is called from an interrupt in ncp_msg_data_ready. So -- * we have to be careful NOT to sleep here! */ --void --ncp_trigger_message(struct ncp_server *server) --{ --#ifdef CONFIG_KERNELD -- char command[ sizeof(server->m.mount_point) -- + sizeof(NCP_MSG_COMMAND) + 2]; --#endif -- -- if (server == NULL) -- { -- printk("ncp_trigger_message: invalid server!\n"); -- return; -- } -- -- DPRINTK("ncp_trigger_message: on %s\n", -- server->m.mount_point); -- --#ifdef CONFIG_KERNELD -- strcpy(command, NCP_MSG_COMMAND); -- strcat(command, " "); -- strcat(command, server->m.mount_point); -- DPRINTK("ksystem: %s\n", command); -- ksystem(command, KERNELD_NOWAIT); --#endif --} -- --static void --ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) -+static void ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) - { - struct statfs tmp; - - /* We cannot say how much disk space is left on a mounted -- NetWare Server, because free space is distributed over -- volumes, and the current user might have disk quotas. So -- free space is not that simple to determine. Our decision -- here is to err conservatively. */ -+ NetWare Server, because free space is distributed over -+ volumes, and the current user might have disk quotas. So -+ free space is not that simple to determine. Our decision -+ here is to err conservatively. */ - - tmp.f_type = NCP_SUPER_MAGIC; - tmp.f_bsize = 512; -@@ -426,18 +307,15 @@ - copy_to_user(buf, &tmp, bufsiz); - } - --static int --ncp_notify_change(struct inode *inode, struct iattr *attr) -+static int ncp_notify_change(struct inode *inode, struct iattr *attr) - { - int result = 0; - int info_mask; - struct nw_modify_dos_info info; - -- if (!ncp_conn_valid(NCP_SERVER(inode))) -- { -+ if (!ncp_conn_valid(NCP_SERVER(inode))) { - return -EIO; - } -- - if ((result = inode_change_ok(inode, attr)) < 0) - return result; - -@@ -447,7 +325,7 @@ - - if (((attr->ia_valid & ATTR_GID) && - (attr->ia_uid != NCP_SERVER(inode)->m.gid))) -- return -EPERM; -+ return -EPERM; - - if (((attr->ia_valid & ATTR_MODE) && - (attr->ia_mode & -@@ -457,67 +335,54 @@ - info_mask = 0; - memset(&info, 0, sizeof(info)); - -- if ((attr->ia_valid & ATTR_CTIME) != 0) -- { -- info_mask |= (DM_CREATE_TIME|DM_CREATE_DATE); -+ if ((attr->ia_valid & ATTR_CTIME) != 0) { -+ info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE); - ncp_date_unix2dos(attr->ia_ctime, -- &(info.creationTime), &(info.creationDate)); -+ &(info.creationTime), &(info.creationDate)); - info.creationTime = le16_to_cpu(info.creationTime); - info.creationDate = le16_to_cpu(info.creationDate); - } -- -- if ((attr->ia_valid & ATTR_MTIME) != 0) -- { -- info_mask |= (DM_MODIFY_TIME|DM_MODIFY_DATE); -+ if ((attr->ia_valid & ATTR_MTIME) != 0) { -+ info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE); - ncp_date_unix2dos(attr->ia_mtime, - &(info.modifyTime), &(info.modifyDate)); - info.modifyTime = le16_to_cpu(info.modifyTime); - info.modifyDate = le16_to_cpu(info.modifyDate); - } -- -- if ((attr->ia_valid & ATTR_ATIME) != 0) -- { -+ if ((attr->ia_valid & ATTR_ATIME) != 0) { - __u16 dummy; - info_mask |= (DM_LAST_ACCESS_DATE); - ncp_date_unix2dos(attr->ia_ctime, - &(dummy), &(info.lastAccessDate)); - info.lastAccessDate = le16_to_cpu(info.lastAccessDate); - } -- -- if (info_mask != 0) -- { -+ if (info_mask != 0) { - if ((result = - ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode), -- NCP_ISTRUCT(inode), -+ NCP_ISTRUCT(inode), - info_mask, -- &info)) != 0) -- { -+ &info)) != 0) { - result = -EACCES; - -- if (info_mask == (DM_CREATE_TIME|DM_CREATE_DATE)) -- { -+ 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. */ -+ 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; - - DPRINTK("ncpfs: trying to change size of %s to %ld\n", - 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; - } -- - ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, - attr->ia_size, 0, "", &written); - -@@ -529,8 +394,7 @@ - - result = 0; - } -- -- ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode); -+ ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode); - - return result; - } -@@ -540,40 +404,40 @@ - int ncp_current_malloced; - #endif - --static struct file_system_type ncp_fs_type = { -- ncp_read_super, "ncpfs", 0, NULL -- }; -+static struct file_system_type ncp_fs_type = -+{ -+ ncp_read_super, "ncpfs", 0, NULL -+}; - - int init_ncp_fs(void) - { -- return register_filesystem(&ncp_fs_type); -+ return register_filesystem(&ncp_fs_type); - } - - #ifdef MODULE - EXPORT_NO_SYMBOLS; - --int init_module( void) -+int init_module(void) - { -- DPRINTK("ncpfs: init_module called\n"); -+ DPRINTK("ncpfs: init_module called\n"); - - #ifdef DEBUG_NCP_MALLOC -- ncp_malloced = 0; -- ncp_current_malloced = 0; -+ ncp_malloced = 0; -+ ncp_current_malloced = 0; - #endif -- ncp_init_dir_cache(); -+ ncp_init_dir_cache(); - - return init_ncp_fs(); - } - --void --cleanup_module(void) -+void cleanup_module(void) - { -- DPRINTK("ncpfs: cleanup_module called\n"); -- ncp_free_dir_cache(); -- unregister_filesystem(&ncp_fs_type); -+ DPRINTK("ncpfs: cleanup_module called\n"); -+ ncp_free_dir_cache(); -+ unregister_filesystem(&ncp_fs_type); - #ifdef DEBUG_NCP_MALLOC -- printk("ncp_malloced: %d\n", ncp_malloced); -- printk("ncp_current_malloced: %d\n", ncp_current_malloced); -+ printk("ncp_malloced: %d\n", ncp_malloced); -+ printk("ncp_current_malloced: %d\n", ncp_current_malloced); - #endif - } - -diff -urN 2.1.29/fs/ncpfs/ioctl.c 2.1.29-patched/fs/ncpfs/ioctl.c ---- 2.1.29/fs/ncpfs/ioctl.c Mon Oct 28 13:29:26 1996 -+++ 2.1.29-patched/fs/ncpfs/ioctl.c Sat Mar 22 19:13:11 1997 -@@ -14,70 +14,41 @@ - #include - #include - --int --ncp_ioctl (struct inode * inode, struct file * filp, -- unsigned int cmd, unsigned long arg) -+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. -- * 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) { -+ switch (cmd) { - case NCP_IOC_NCPREQUEST: - -- if ( (permission(inode, MAY_WRITE) != 0) -- && (current->uid != server->m.mounted_uid)) -- { -+ 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) -- { -+ if ((result = verify_area(VERIFY_READ, (char *) arg, -+ sizeof(request))) != 0) { - return result; - } -+ copy_from_user(&request, (struct ncp_ioctl_request *) arg, -+ sizeof(request)); - -- copy_from_user(&request, (struct ncp_ioctl_request *)arg, -- sizeof(request)); -- -- if ( (request.function > 255) -+ if ((request.function > 255) - || (request.size > -- NCP_PACKET_SIZE - sizeof(struct ncp_request_header))) -- { -+ NCP_PACKET_SIZE - sizeof(struct ncp_request_header))) { - return -EINVAL; - } -- -- if ((result = verify_area(VERIFY_WRITE, (char *)request.data, -- NCP_PACKET_SIZE)) != 0) -- { -+ 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 */ -+ here to be able to use ncp_request */ - - server->has_subfunction = 0; - server->current_size = request.size; -@@ -95,66 +66,55 @@ - - case NCP_IOC_CONN_LOGGED_IN: - -- if ( (permission(inode, MAY_WRITE) != 0) -- && (current->uid != server->m.mounted_uid)) -- { -+ 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)) -- { -+ 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) -- { -+ if ((result = verify_area(VERIFY_WRITE, (char *) arg, -+ sizeof(info))) != 0) { - return result; - } -+ copy_from_user(&info, (struct ncp_fs_info *) arg, -+ sizeof(info)); - -- copy_from_user(&info, (struct ncp_fs_info *)arg, -- sizeof(info)); -- -- if (info.version != NCP_GET_FS_INFO_VERSION) -- { -+ 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; -+ /* TODO: 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; -+ info.directory_id = NCP_ISTRUCT(inode)->DosDirNum; - -- copy_to_user((struct ncp_fs_info *)arg, &info, sizeof(info)); -- return 0; -+ copy_to_user((struct ncp_fs_info *) arg, &info, sizeof(info)); -+ return 0; - -- case NCP_IOC_GETMOUNTUID: -+ case NCP_IOC_GETMOUNTUID: - -- if ( (permission(inode, MAY_READ) != 0) -- && (current->uid != server->m.mounted_uid)) -- { -+ 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_user(server->m.mounted_uid, (uid_t *) arg); -- return 0; -+ if ((result = verify_area(VERIFY_WRITE, (uid_t *) arg, -+ sizeof(uid_t))) != 0) { -+ return result; -+ } -+ put_user(server->m.mounted_uid, (uid_t *) arg); -+ return 0; - - default: - return -EINVAL; - } -- -+ - return -EINVAL; - } -diff -urN 2.1.29/fs/ncpfs/mmap.c 2.1.29-patched/fs/ncpfs/mmap.c ---- 2.1.29/fs/ncpfs/mmap.c Mon Oct 28 13:29:26 1996 -+++ 2.1.29-patched/fs/ncpfs/mmap.c Sat Mar 22 19:13:11 1997 -@@ -23,17 +23,16 @@ - - static inline int min(int a, int b) - { -- return avm_inode; -+ struct inode *inode = area->vm_inode; - unsigned long page; - unsigned int clear; - unsigned long tmp; -@@ -48,37 +47,28 @@ - pos = address - area->vm_start + area->vm_offset; - - clear = 0; -- if (address + PAGE_SIZE > area->vm_end) -- { -+ if (address + PAGE_SIZE > area->vm_end) { - clear = address + PAGE_SIZE - area->vm_end; - } -- -- /* what we can read in one go */ -+ /* 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 -- { -+ 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) -- { -+ while (already_read < count) { - int read_this_time; - -- if ((pos % bufsize) != 0) -- { -+ if ((pos % bufsize) != 0) { - to_read = bufsize - (pos % bufsize); -- } -- else -- { -+ } else { - to_read = bufsize; - } - -@@ -87,33 +77,31 @@ - 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; -+ (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) -- { -+ if (read_this_time < to_read) { - break; - } - } - -- } -+ } - - set_fs(fs); - - tmp = page + PAGE_SIZE; - while (clear--) { -- *(char *)--tmp = 0; -+ *(char *) --tmp = 0; - } - return page; - } - --struct vm_operations_struct ncp_file_mmap = { -+struct vm_operations_struct ncp_file_mmap = -+{ - NULL, /* open */ - NULL, /* close */ - NULL, /* unmap */ -@@ -128,18 +116,15 @@ - - - /* 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) -+int ncp_mmap(struct inode *inode, struct file *file, struct vm_area_struct *vma) - { -- DPRINTK("ncp_mmap: called\n"); -+ DPRINTK("ncp_mmap: called\n"); - -- if (!ncp_conn_valid(NCP_SERVER(inode))) -- { -+ if (!ncp_conn_valid(NCP_SERVER(inode))) { - return -EIO; - } -- -- /* only PAGE_COW or read-only supported now */ -- if (vma->vm_flags & VM_SHARED) -+ /* 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; -@@ -147,7 +132,6 @@ - inode->i_atime = CURRENT_TIME; - inode->i_dirt = 1; - } -- - vma->vm_inode = inode; - inode->i_count++; - vma->vm_ops = &ncp_file_mmap; -diff -urN 2.1.29/fs/ncpfs/ncplib_kernel.c 2.1.29-patched/fs/ncpfs/ncplib_kernel.c ---- 2.1.29/fs/ncpfs/ncplib_kernel.c Mon Dec 30 11:03:22 1996 -+++ 2.1.29-patched/fs/ncpfs/ncplib_kernel.c Sat Mar 22 19:13:11 1997 -@@ -8,53 +8,43 @@ - - #include "ncplib_kernel.h" - --typedef __u8 byte; --typedef __u16 word; --typedef __u32 dword; -- - static inline int min(int a, int b) - { -- return alock == 0) -- { -+ if (server->lock == 0) { - DPRINTK("ncpfs: server not locked!\n"); - } - } - --static void --ncp_add_byte(struct ncp_server *server, byte x) -+static void ncp_add_byte(struct ncp_server *server, __u8 x) - { - assert_server_locked(server); -- *(byte *)(&(server->packet[server->current_size])) = x; -+ *(__u8 *) (&(server->packet[server->current_size])) = x; - server->current_size += 1; - return; - } - --static void --ncp_add_word(struct ncp_server *server, word x) -+static void ncp_add_word(struct ncp_server *server, __u16 x) - { - assert_server_locked(server); -- put_unaligned(x, (word *)(&(server->packet[server->current_size]))); -+ put_unaligned(x, (__u16 *) (&(server->packet[server->current_size]))); - server->current_size += 2; - return; - } - --static void --ncp_add_dword(struct ncp_server *server, dword x) -+static void ncp_add_dword(struct ncp_server *server, __u32 x) - { - assert_server_locked(server); -- put_unaligned(x, (dword *)(&(server->packet[server->current_size]))); -+ put_unaligned(x, (__u32 *) (&(server->packet[server->current_size]))); - server->current_size += 4; - return; - } - --static void --ncp_add_mem(struct ncp_server *server, const void *source, int size) -+static void ncp_add_mem(struct ncp_server *server, const void *source, int size) - { - assert_server_locked(server); - memcpy(&(server->packet[server->current_size]), source, size); -@@ -62,8 +52,7 @@ - return; - } - --static void --ncp_add_mem_fromfs(struct ncp_server *server, const char *source, int size) -+static void ncp_add_mem_fromfs(struct ncp_server *server, const char *source, int size) - { - assert_server_locked(server); - copy_from_user(&(server->packet[server->current_size]), source, size); -@@ -71,13 +60,11 @@ - return; - } - --static void --ncp_add_pstring(struct ncp_server *server, const char *s) -+static void ncp_add_pstring(struct ncp_server *server, const char *s) - { - int len = strlen(s); - assert_server_locked(server); -- if (len > 255) -- { -+ if (len > 255) { - DPRINTK("ncpfs: string too long: %s\n", s); - len = 255; - } -@@ -86,8 +73,7 @@ - return; - } - --static void --ncp_init_request(struct ncp_server *server) -+static void ncp_init_request(struct ncp_server *server) - { - ncp_lock_server(server); - -@@ -95,11 +81,10 @@ - server->has_subfunction = 0; - } - --static void --ncp_init_request_s(struct ncp_server *server, int subfunction) -+static void ncp_init_request_s(struct ncp_server *server, int subfunction) - { - ncp_init_request(server); -- ncp_add_word(server, 0); /* preliminary size */ -+ ncp_add_word(server, 0); /* preliminary size */ - - ncp_add_byte(server, subfunction); - -@@ -107,53 +92,49 @@ - } - - static char * --ncp_reply_data(struct ncp_server *server, int offset) -+ ncp_reply_data(struct ncp_server *server, int offset) - { - return &(server->packet[sizeof(struct ncp_reply_header) + offset]); - } - --static byte --ncp_reply_byte(struct ncp_server *server, int offset) -+static __u8 -+ ncp_reply_byte(struct ncp_server *server, int offset) - { -- return *(byte *)(ncp_reply_data(server, offset)); -+ return get_unaligned((__u8 *) ncp_reply_data(server, offset)); - } - --static word --ncp_reply_word(struct ncp_server *server, int offset) -+static __u16 -+ ncp_reply_word(struct ncp_server *server, int offset) - { -- return *(word *)(ncp_reply_data(server, offset)); -+ return get_unaligned((__u16 *) ncp_reply_data(server, offset)); - } - --static dword --ncp_reply_dword(struct ncp_server *server, int offset) -+static __u32 -+ ncp_reply_dword(struct ncp_server *server, int offset) - { -- return *(dword *)(ncp_reply_data(server, offset)); -+ return get_unaligned((__u32 *) ncp_reply_data(server, offset)); - } - --int --ncp_negotiate_buffersize(struct ncp_server *server, -- int size, int *target) -+int ncp_negotiate_buffersize(struct ncp_server *server, -+ int size, int *target) - { - int result; - - ncp_init_request(server); - ncp_add_word(server, htons(size)); -- -- if ((result = ncp_request(server, 33)) != 0) -- { -+ -+ if ((result = ncp_request(server, 33)) != 0) { - ncp_unlock_server(server); - return result; - } -- -- *target =min(ntohs(ncp_reply_word(server, 0)), size); -+ *target = min(ntohs(ncp_reply_word(server, 0)), size); - - ncp_unlock_server(server); - return 0; - } - --int --ncp_get_volume_info_with_number(struct ncp_server *server, int n, -- struct ncp_volume_info *target) -+int ncp_get_volume_info_with_number(struct ncp_server *server, int n, -+ struct ncp_volume_info *target) - { - int result; - int len; -@@ -161,14 +142,12 @@ - ncp_init_request_s(server, 44); - ncp_add_byte(server, n); - -- if ((result = ncp_request(server, 22)) != 0) -- { -+ if ((result = ncp_request(server, 22)) != 0) { - ncp_unlock_server(server); - return result; - } -- - target->total_blocks = ncp_reply_dword(server, 0); -- target->free_blocks = ncp_reply_dword(server, 4); -+ target->free_blocks = ncp_reply_dword(server, 4); - target->purgeable_blocks = ncp_reply_dword(server, 8); - target->not_yet_purgeable_blocks = ncp_reply_dword(server, 12); - target->total_dir_entries = ncp_reply_dword(server, 16); -@@ -178,20 +157,17 @@ - memset(&(target->volume_name), 0, sizeof(target->volume_name)); - - 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); - ncp_unlock_server(server); - return -EIO; - } -- - memcpy(&(target->volume_name), ncp_reply_data(server, 30), len); - ncp_unlock_server(server); - return 0; - } - --int --ncp_close_file(struct ncp_server *server, const char *file_id) -+int ncp_close_file(struct ncp_server *server, const char *file_id) - { - int result; - -@@ -204,35 +180,27 @@ - return result; - } - --static void --ncp_add_handle_path(struct ncp_server *server, -- __u8 vol_num, -- __u32 dir_base, int have_dir_base, -- char *path) -+static void ncp_add_handle_path(struct ncp_server *server, -+ __u8 vol_num, -+ __u32 dir_base, int have_dir_base, -+ char *path) - { - ncp_add_byte(server, vol_num); - ncp_add_dword(server, dir_base); -- if (have_dir_base != 0) -- { -- ncp_add_byte(server, 1); /* dir_base */ -- } -- else -- { -- ncp_add_byte(server, 0xff); /* no handle */ -- } -- if (path != NULL) -- { -- ncp_add_byte(server, 1); /* 1 component */ -- ncp_add_pstring(server, path); -+ if (have_dir_base != 0) { -+ ncp_add_byte(server, 1); /* dir_base */ -+ } else { -+ ncp_add_byte(server, 0xff); /* no handle */ - } -- else -- { -+ if (path != NULL) { -+ ncp_add_byte(server, 1); /* 1 component */ -+ ncp_add_pstring(server, path); -+ } else { - ncp_add_byte(server, 0); - } - } - --static void --ncp_extract_file_info(void *structure, struct nw_info_struct *target) -+static void ncp_extract_file_info(void *structure, struct nw_info_struct *target) - { - __u8 *name_len; - const int info_struct_size = sizeof(struct nw_info_struct) - 257; -@@ -240,70 +208,60 @@ - memcpy(target, structure, info_struct_size); - name_len = structure + info_struct_size; - target->nameLen = *name_len; -- strncpy(target->entryName, name_len+1, *name_len); -+ strncpy(target->entryName, name_len + 1, *name_len); - target->entryName[*name_len] = '\0'; - return; - } - --int --ncp_obtain_info(struct ncp_server *server, -- __u8 vol_num, __u32 dir_base, -- char *path, /* At most 1 component */ -- struct nw_info_struct *target) -+int ncp_obtain_info(struct ncp_server *server, -+ __u8 vol_num, __u32 dir_base, -+ char *path, /* At most 1 component */ -+ struct nw_info_struct *target) - { - int result; - -- if (target == NULL) -- { -+ if (target == NULL) { - return -EINVAL; - } -- - ncp_init_request(server); -- ncp_add_byte(server, 6); /* subfunction */ -+ ncp_add_byte(server, 6); /* subfunction */ - ncp_add_byte(server, server->name_space[vol_num]); - ncp_add_byte(server, server->name_space[vol_num]); -- ncp_add_word(server, htons(0xff00)); /* get all */ -+ ncp_add_word(server, htons(0xff00)); /* get all */ - ncp_add_dword(server, RIM_ALL); - ncp_add_handle_path(server, vol_num, dir_base, 1, path); - -- if ((result = ncp_request(server, 87)) != 0) -- { -+ if ((result = ncp_request(server, 87)) != 0) { - ncp_unlock_server(server); - return result; - } -- - ncp_extract_file_info(ncp_reply_data(server, 0), target); - ncp_unlock_server(server); - return 0; - } - --static inline int --ncp_has_os2_namespace(struct ncp_server *server, __u8 volume) -+static inline int ncp_has_os2_namespace(struct ncp_server *server, __u8 volume) - { - int result; - __u8 *namespace; - __u16 no_namespaces; - - ncp_init_request(server); -- ncp_add_byte(server, 24); /* Subfunction: Get Name Spaces Loaded */ -+ 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) -- { -+ 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); -+ while (no_namespaces > 0) { -+ DPRINTK("get_namespaces: found %d on %d\n", *namespace, volume); - -- if (*namespace == 4) -- { -+ if (*namespace == 4) { - DPRINTK("get_namespaces: found OS2\n"); - ncp_unlock_server(server); - return 1; -@@ -315,10 +273,9 @@ - return 0; - } - --int --ncp_lookup_volume(struct ncp_server *server, -- char *volname, -- struct nw_info_struct *target) -+int ncp_lookup_volume(struct ncp_server *server, -+ char *volname, -+ struct nw_info_struct *target) - { - int result; - int volnum; -@@ -326,30 +283,28 @@ - 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_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) -- { -+ 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; -+ server->name_space[volnum] = ncp_has_os2_namespace(server, volnum) ? 4 : 0; - - DPRINTK("lookup_vol: namespace[%d] = %d\n", - volnum, server->name_space[volnum]); -@@ -360,19 +315,18 @@ - return 0; - } - --int --ncp_modify_file_or_subdir_dos_info(struct ncp_server *server, -- struct nw_info_struct *file, -- __u32 info_mask, -- struct nw_modify_dos_info *info) -+int ncp_modify_file_or_subdir_dos_info(struct ncp_server *server, -+ struct nw_info_struct *file, -+ __u32 info_mask, -+ struct nw_modify_dos_info *info) - { - int result; - - ncp_init_request(server); -- ncp_add_byte(server, 7); /* subfunction */ -+ ncp_add_byte(server, 7); /* subfunction */ - ncp_add_byte(server, server->name_space[file->volNumber]); -- ncp_add_byte(server, 0); /* reserved */ -- ncp_add_word(server, htons(0x0680)); /* search attribs: all */ -+ ncp_add_byte(server, 0); /* reserved */ -+ ncp_add_word(server, htons(0x0680)); /* search attribs: all */ - - ncp_add_dword(server, info_mask); - ncp_add_mem(server, info, sizeof(*info)); -@@ -384,55 +338,50 @@ - return result; - } - --int --ncp_del_file_or_subdir(struct ncp_server *server, -- struct nw_info_struct *dir, char *name) -+int ncp_del_file_or_subdir(struct ncp_server *server, -+ struct nw_info_struct *dir, char *name) - { - int result; - - ncp_init_request(server); -- ncp_add_byte(server, 8); /* subfunction */ -+ ncp_add_byte(server, 8); /* subfunction */ - ncp_add_byte(server, server->name_space[dir->volNumber]); -- ncp_add_byte(server, 0); /* reserved */ -- ncp_add_word(server, ntohs(0x0680)); /* search attribs: all */ -+ ncp_add_byte(server, 0); /* reserved */ -+ ncp_add_word(server, ntohs(0x0680)); /* search attribs: all */ - ncp_add_handle_path(server, dir->volNumber, - dir->dirEntNum, 1, name); -- -+ - result = ncp_request(server, 87); - ncp_unlock_server(server); - return result; - } - --static inline void --ConvertToNWfromDWORD ( __u32 sfd , __u8 ret[6] ) -+static inline void ConvertToNWfromDWORD(__u32 sfd, __u8 ret[6]) - { -- __u16 *dest = (__u16 *) ret; -- memcpy (ret + 2, &sfd, 4); -- dest[0] = cpu_to_le16((le16_to_cpu(dest[1]) + le16_to_cpu(1))); -- return; -+ __u16 *dest = (__u16 *) ret; -+ memcpy(ret + 2, &sfd, 4); -+ dest[0] = cpu_to_le16((le16_to_cpu(dest[1]) + le16_to_cpu(1))); -+ return; - } - - /* If both dir and name are NULL, then in target there's already a - looked-up entry that wants to be opened. */ --int --ncp_open_create_file_or_subdir(struct ncp_server *server, -- struct nw_info_struct *dir, char *name, -- int open_create_mode, -- __u32 create_attributes, -- int desired_acc_rights, -- struct nw_file_info *target) -+int ncp_open_create_file_or_subdir(struct ncp_server *server, -+ struct nw_info_struct *dir, char *name, -+ int open_create_mode, -+ __u32 create_attributes, -+ int desired_acc_rights, -+ struct nw_file_info *target) - { - int result; - __u16 search_attribs = ntohs(0x0600); - __u8 volume = (dir != NULL) ? dir->volNumber : target->i.volNumber; - -- if ((create_attributes & aDIR) != 0) -- { -- search_attribs |= ntohs(0x0080); -+ if ((create_attributes & aDIR) != 0) { -+ search_attribs |= ntohs(0x0080); - } -- - ncp_init_request(server); -- ncp_add_byte(server, 1); /* subfunction */ -+ ncp_add_byte(server, 1); /* subfunction */ - ncp_add_byte(server, server->name_space[volume]); - ncp_add_byte(server, open_create_mode); - ncp_add_word(server, search_attribs); -@@ -442,89 +391,76 @@ - for directories */ - ncp_add_word(server, desired_acc_rights); - -- if (dir != NULL) -- { -+ if (dir != NULL) { - ncp_add_handle_path(server, volume, dir->dirEntNum, 1, name); -- } -- else -- { -+ } else { - ncp_add_handle_path(server, volume, target->i.dirEntNum, - 1, NULL); -- } -+ } - -- if ((result = ncp_request(server, 87)) != 0) -- { -+ if ((result = ncp_request(server, 87)) != 0) { - ncp_unlock_server(server); - return result; - } -- - target->opened = 1; - target->server_file_handle = ncp_reply_dword(server, 0); - target->open_create_action = ncp_reply_byte(server, 4); - -- if (dir != NULL) -- { -+ if (dir != NULL) { - /* in target there's a new finfo to fill */ - ncp_extract_file_info(ncp_reply_data(server, 5), &(target->i)); - } -- - ConvertToNWfromDWORD(target->server_file_handle, target->file_handle); - - ncp_unlock_server(server); - return 0; - } -- - --int --ncp_initialize_search(struct ncp_server *server, -- struct nw_info_struct *dir, -- struct nw_search_sequence *target) -+ -+int ncp_initialize_search(struct ncp_server *server, -+ struct nw_info_struct *dir, -+ struct nw_search_sequence *target) - { - int result; - - ncp_init_request(server); -- ncp_add_byte(server, 2); /* subfunction */ -+ ncp_add_byte(server, 2); /* subfunction */ - 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->dirEntNum, 1, NULL); -- -- if ((result = ncp_request(server, 87)) != 0) -- { -+ -+ if ((result = ncp_request(server, 87)) != 0) { - ncp_unlock_server(server); - return result; - } -- - memcpy(target, ncp_reply_data(server, 0), sizeof(*target)); - - ncp_unlock_server(server); - return 0; - } -- -+ - /* Search for everything */ --int --ncp_search_for_file_or_subdir(struct ncp_server *server, -- struct nw_search_sequence *seq, -- struct nw_info_struct *target) -+int ncp_search_for_file_or_subdir(struct ncp_server *server, -+ struct nw_search_sequence *seq, -+ struct nw_info_struct *target) - { - int result; - - ncp_init_request(server); -- ncp_add_byte(server, 3); /* subfunction */ -+ ncp_add_byte(server, 3); /* subfunction */ - ncp_add_byte(server, server->name_space[seq->volNumber]); -- ncp_add_byte(server, 0); /* data stream (???) */ -- ncp_add_word(server, 0xffff); /* Search attribs */ -- ncp_add_dword(server, RIM_ALL); /* return info mask */ -+ ncp_add_byte(server, 0); /* data stream (???) */ -+ ncp_add_word(server, 0xffff); /* Search attribs */ -+ ncp_add_dword(server, RIM_ALL); /* return info mask */ - ncp_add_mem(server, seq, 9); -- ncp_add_byte(server, 2); /* 2 byte pattern */ -- ncp_add_byte(server, 0xff); /* following is a wildcard */ -+ ncp_add_byte(server, 2); /* 2 byte pattern */ -+ ncp_add_byte(server, 0xff); /* following is a wildcard */ - ncp_add_byte(server, '*'); -- -- if ((result = ncp_request(server, 87)) != 0) -- { -+ -+ if ((result = ncp_request(server, 87)) != 0) { - ncp_unlock_server(server); - return result; - } -- - memcpy(seq, ncp_reply_data(server, 0), sizeof(*seq)); - ncp_extract_file_info(ncp_reply_data(server, 10), target); - -@@ -532,34 +468,33 @@ - return 0; - } - --int --ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, -- struct nw_info_struct *old_dir, char *old_name, -- struct nw_info_struct *new_dir, char *new_name) -+int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, -+ struct nw_info_struct *old_dir, char *old_name, -+ struct nw_info_struct *new_dir, char *new_name) - { - int result; - -- if ( (old_dir == NULL) || (old_name == NULL) -+ if ((old_dir == NULL) || (old_name == NULL) - || (new_dir == NULL) || (new_name == NULL)) - return -EINVAL; -- -+ - ncp_init_request(server); -- ncp_add_byte(server, 4); /* subfunction */ -+ ncp_add_byte(server, 4); /* subfunction */ - ncp_add_byte(server, server->name_space[old_dir->volNumber]); -- ncp_add_byte(server, 1); /* rename flag */ -- ncp_add_word(server, ntohs (0x0680)); /* search attributes */ -+ ncp_add_byte(server, 1); /* rename flag */ -+ ncp_add_word(server, ntohs(0x0680)); /* search attributes */ - - /* source Handle Path */ - ncp_add_byte(server, old_dir->volNumber); - ncp_add_dword(server, old_dir->dirEntNum); - ncp_add_byte(server, 1); -- ncp_add_byte(server, 1); /* 1 source component */ -+ ncp_add_byte(server, 1); /* 1 source component */ - - /* dest Handle Path */ - ncp_add_byte(server, new_dir->volNumber); - ncp_add_dword(server, new_dir->dirEntNum); - ncp_add_byte(server, 1); -- ncp_add_byte(server, 1); /* 1 destination component */ -+ ncp_add_byte(server, 1); /* 1 destination component */ - - /* source path string */ - ncp_add_pstring(server, old_name); -@@ -570,13 +505,12 @@ - ncp_unlock_server(server); - return result; - } -- -+ - - /* We have to transfer to/from user space */ --int --ncp_read(struct ncp_server *server, const char *file_id, -- __u32 offset, __u16 to_read, -- char *target, int *bytes_read) -+int ncp_read(struct ncp_server *server, const char *file_id, -+ __u32 offset, __u16 to_read, -+ char *target, int *bytes_read) - { - int result; - -@@ -586,24 +520,21 @@ - ncp_add_dword(server, htonl(offset)); - 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); - return result; - } -- - *bytes_read = ntohs(ncp_reply_word(server, 0)); - -- copy_to_user(target, ncp_reply_data(server, 2+(offset&1)), *bytes_read); -+ copy_to_user(target, ncp_reply_data(server, 2 + (offset & 1)), *bytes_read); - - ncp_unlock_server(server); - return 0; - } - --int --ncp_write(struct ncp_server *server, const char *file_id, -- __u32 offset, __u16 to_write, -- const char *source, int *bytes_written) -+int ncp_write(struct ncp_server *server, const char *file_id, -+ __u32 offset, __u16 to_write, -+ const char *source, int *bytes_written) - { - int result; - -@@ -614,15 +545,12 @@ - ncp_add_word(server, htons(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); - return result; - } -- - *bytes_written = to_write; - - ncp_unlock_server(server); - return 0; - } -- -diff -urN 2.1.29/fs/ncpfs/ncplib_kernel.h 2.1.29-patched/fs/ncpfs/ncplib_kernel.h ---- 2.1.29/fs/ncpfs/ncplib_kernel.h Mon Dec 30 11:03:22 1996 -+++ 2.1.29-patched/fs/ncpfs/ncplib_kernel.h Sun Mar 23 13:05:18 1997 -@@ -29,89 +29,11 @@ - ncp_negotiate_buffersize(struct ncp_server *server, int size, - int *target); - int --ncp_get_encryption_key(struct ncp_server *server, -- char *target); --int --ncp_get_bindery_object_id(struct ncp_server *server, -- int object_type, char *object_name, -- struct ncp_bindery_object *target); --int --ncp_login_encrypted(struct ncp_server *server, -- struct ncp_bindery_object *object, -- unsigned char *key, -- unsigned char *passwd); --int --ncp_login_user(struct ncp_server *server, -- unsigned char *username, -- unsigned char *password); --int - ncp_get_volume_info_with_number(struct ncp_server *server, int n, - struct ncp_volume_info *target); - - int --ncp_get_volume_number(struct ncp_server *server, const char *name, -- int *target); -- --int --ncp_file_search_init(struct ncp_server *server, -- int dir_handle, const char *path, -- struct ncp_filesearch_info *target); -- --int --ncp_file_search_continue(struct ncp_server *server, -- struct ncp_filesearch_info *fsinfo, -- int attributes, const char *path, -- struct ncp_file_info *target); -- --int --ncp_get_finfo(struct ncp_server *server, -- int dir_handle, const char *path, const char *name, -- struct ncp_file_info *target); -- --int --ncp_open_file(struct ncp_server *server, -- int dir_handle, const char *path, -- int attr, int access, -- struct ncp_file_info *target); --int - ncp_close_file(struct ncp_server *server, const char *file_id); -- --int --ncp_create_newfile(struct ncp_server *server, -- int dir_handle, const char *path, -- int attr, -- struct ncp_file_info *target); -- --int --ncp_create_file(struct ncp_server *server, -- int dir_handle, const char *path, -- int attr, -- struct ncp_file_info *target); -- --int --ncp_erase_file(struct ncp_server *server, -- int dir_handle, const char *path, -- int attr); -- --int --ncp_rename_file(struct ncp_server *server, -- int old_handle, const char *old_path, -- int attr, -- int new_handle, const char *new_path); -- --int --ncp_create_directory(struct ncp_server *server, -- int dir_handle, const char *path, -- int inherit_mask); -- --int --ncp_delete_directory(struct ncp_server *server, -- int dir_handle, const char *path); -- --int --ncp_rename_directory(struct ncp_server *server, -- int dir_handle, -- const char *old_path, const char *new_path); - - int - ncp_read(struct ncp_server *server, const char *file_id, -diff -urN 2.1.29/fs/ncpfs/sock.c 2.1.29-patched/fs/ncpfs/sock.c ---- 2.1.29/fs/ncpfs/sock.c Sun Jan 26 11:07:44 1997 -+++ 2.1.29-patched/fs/ncpfs/sock.c Sun Mar 23 09:37:46 1997 -@@ -25,315 +25,59 @@ - #include - #include - #include -+#include - -- --#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) -+static int _recv(struct socket *sock, unsigned char *ubuf, int size, -+ unsigned flags) - { -- struct iovec iov; -- struct msghdr msg; -+ struct iovec iov; -+ struct msghdr msg; - struct scm_cookie scm; - - memset(&scm, 0, sizeof(scm)); - -- iov.iov_base = ubuf; -- iov.iov_len = size; -- -- msg.msg_name = (void *)sa; -- msg.msg_namelen = 0; -- if (sa) -- msg.msg_namelen = sizeof(struct sockaddr_ipx); -- msg.msg_control = NULL; -- msg.msg_iov = &iov; -- msg.msg_iovlen = 1; -- if (noblock) { -- flags |= MSG_DONTWAIT; -- } -+ iov.iov_base = ubuf; -+ iov.iov_len = size; - -- return sock->ops->recvmsg(sock, &msg, size, flags, &scm); -+ msg.msg_name = NULL; -+ msg.msg_namelen = 0; -+ msg.msg_control = NULL; -+ msg.msg_iov = &iov; -+ msg.msg_iovlen = 1; -+ return sock->ops->recvmsg(sock, &msg, size, flags, &scm); - } - --static int _sendto(struct socket *sock, const void *buff, -- int len, int noblock, unsigned flags, -- struct sockaddr_ipx *sa) -- -+static int _send(struct socket *sock, const void *buff, int len) - { -- struct iovec iov; -- struct msghdr msg; -+ struct iovec iov; -+ struct msghdr msg; - struct scm_cookie scm; - int err; - -- iov.iov_base = (void *)buff; -- iov.iov_len = len; -- -- msg.msg_name = (void *)sa; -- msg.msg_namelen = sizeof(struct sockaddr_ipx); -- msg.msg_control = NULL; -- msg.msg_iov = &iov; -- msg.msg_iovlen = 1; -+ iov.iov_base = (void *) buff; -+ iov.iov_len = len; - -- if (noblock) { -- flags |= MSG_DONTWAIT; -- } -- -- msg.msg_flags = flags; -+ msg.msg_name = NULL; -+ msg.msg_namelen = 0; -+ msg.msg_control = NULL; -+ msg.msg_iov = &iov; -+ msg.msg_iovlen = 1; -+ msg.msg_flags = 0; - - err = scm_send(sock, &msg, &scm); -- if (err < 0) -+ if (err < 0) { - return err; -- err = sock->ops->sendmsg(sock, &msg, len, &scm); -+ } -+ err = sock->ops->sendmsg(sock, &msg, len, &scm); - scm_destroy(&scm); - return err; - } - -- --static void --ncp_wdog_data_ready(struct sock *sk, int len) --{ -- struct socket *sock = sk->socket; -- -- if (!sk->dead) -- { -- unsigned char packet_buf[2]; -- struct sockaddr_ipx sender; -- int result; -- unsigned short fs; -- -- fs = get_fs(); -- set_fs(get_ds()); -- -- result = _recvfrom(sock, (void *)packet_buf, 2, 1, 0, -- &sender); -- -- if ( (result != 2) -- || (packet_buf[1] != '?') -- /* How to check connection number here? */ -- ) -- { -- printk("ncpfs: got strange packet on watchdog " -- "socket\n"); -- } -- else -- { -- int result; -- DDPRINTK("ncpfs: got watchdog from:\n"); -- DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X," -- " conn:%02X,type:%c\n", -- htonl(sender.sipx_network), -- sender.sipx_node[0], sender.sipx_node[1], -- sender.sipx_node[2], sender.sipx_node[3], -- sender.sipx_node[4], sender.sipx_node[5], -- ntohs(sender.sipx_port), -- packet_buf[0], packet_buf[1]); -- -- packet_buf[1] = 'Y'; -- result = _sendto(sock, (void *)packet_buf, 2, 1, 0, -- &sender); -- DDPRINTK("send result: %d\n", result); -- } -- set_fs(fs); -- } --} -- --int --ncp_catch_watchdog(struct ncp_server *server) --{ -- struct file *file; -- struct inode *inode; -- struct socket *sock; -- struct sock *sk; -- -- if ( (server == NULL) -- || ((file = server->wdog_filp) == NULL) -- || ((inode = file->f_inode) == NULL) -- || (!S_ISSOCK(inode->i_mode))) -- { -- printk("ncp_catch_watchdog: did not get valid server!\n"); -- server->data_ready = NULL; -- return -EINVAL; -- } -- -- sock = &(inode->u.socket_i); -- -- if (sock->type != SOCK_DGRAM) -- { -- printk("ncp_catch_watchdog: did not get SOCK_DGRAM\n"); -- server->data_ready = NULL; -- return -EINVAL; -- } -- -- sk = sock->sk; -- -- if (sk == NULL) -- { -- printk("ncp_catch_watchdog: sk == NULL"); -- server->data_ready = NULL; -- return -EINVAL; -- } -- -- DDPRINTK("ncp_catch_watchdog: sk->d_r = %x, server->d_r = %x\n", -- (unsigned int)(sk->data_ready), -- (unsigned int)(server->data_ready)); -- -- if (sk->data_ready == ncp_wdog_data_ready) -- { -- printk("ncp_catch_watchdog: already done\n"); -- return -EINVAL; -- } -- -- server->data_ready = sk->data_ready; -- sk->data_ready = ncp_wdog_data_ready; -- sk->allocation = GFP_ATOMIC; -- return 0; --} -- --int --ncp_dont_catch_watchdog(struct ncp_server *server) --{ -- struct file *file; -- struct inode *inode; -- struct socket *sock; -- struct sock *sk; -- -- if ( (server == NULL) -- || ((file = server->wdog_filp) == NULL) -- || ((inode = file->f_inode) == NULL) -- || (!S_ISSOCK(inode->i_mode))) -- { -- printk("ncp_dont_catch_watchdog: " -- "did not get valid server!\n"); -- return -EINVAL; -- } -- -- sock = &(inode->u.socket_i); -- -- if (sock->type != SOCK_DGRAM) -- { -- printk("ncp_dont_catch_watchdog: did not get SOCK_DGRAM\n"); -- return -EINVAL; -- } -- -- sk = sock->sk; -- -- if (sk == NULL) -- { -- printk("ncp_dont_catch_watchdog: sk == NULL"); -- return -EINVAL; -- } -- -- if (server->data_ready == NULL) -- { -- printk("ncp_dont_catch_watchdog: " -- "server->data_ready == NULL\n"); -- return -EINVAL; -- } -- -- if (sk->data_ready != ncp_wdog_data_ready) -- { -- printk("ncp_dont_catch_watchdog: " -- "sk->data_callback != ncp_data_callback\n"); -- return -EINVAL; -- } -- -- DDPRINTK("ncp_dont_catch_watchdog: sk->d_r = %x, server->d_r = %x\n", -- (unsigned int)(sk->data_ready), -- (unsigned int)(server->data_ready)); -- -- sk->data_ready = server->data_ready; -- sk->allocation = GFP_KERNEL; -- server->data_ready = NULL; -- return 0; --} -- --static void --ncp_msg_data_ready(struct sock *sk, int len) --{ -- struct socket *sock = sk->socket; -- -- if (!sk->dead) -- { -- unsigned char packet_buf[2]; -- struct sockaddr_ipx sender; -- int result; -- unsigned short fs; -- -- fs = get_fs(); -- set_fs(get_ds()); -- -- result = _recvfrom(sock, (void *)packet_buf, 2, 1, 0, -- &sender); -- -- DPRINTK("ncpfs: got message of size %d from:\n", result); -- DPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X," -- " conn:%02X,type:%c\n", -- htonl(sender.sipx_network), -- sender.sipx_node[0], sender.sipx_node[1], -- sender.sipx_node[2], sender.sipx_node[3], -- sender.sipx_node[4], sender.sipx_node[5], -- ntohs(sender.sipx_port), -- packet_buf[0], packet_buf[1]); -- -- ncp_trigger_message(sk->protinfo.af_ipx.ncp_server); -- -- set_fs(fs); -- } --} -- --int --ncp_catch_message(struct ncp_server *server) --{ -- struct file *file; -- struct inode *inode; -- struct socket *sock; -- struct sock *sk; -- -- if ( (server == NULL) -- || ((file = server->msg_filp) == NULL) -- || ((inode = file->f_inode) == NULL) -- || (!S_ISSOCK(inode->i_mode))) -- { -- printk("ncp_catch_message: did not get valid server!\n"); -- return -EINVAL; -- } -- -- sock = &(inode->u.socket_i); -- -- if (sock->type != SOCK_DGRAM) -- { -- printk("ncp_catch_message: did not get SOCK_DGRAM\n"); -- return -EINVAL; -- } -- -- sk = sock->sk; -- -- if (sk == NULL) -- { -- printk("ncp_catch_message: sk == NULL"); -- return -EINVAL; -- } -- -- DDPRINTK("ncp_catch_message: sk->d_r = %x\n", -- (unsigned int)(sk->data_ready)); -- -- if (sk->data_ready == ncp_msg_data_ready) -- { -- printk("ncp_catch_message: already done\n"); -- return -EINVAL; -- } -- -- sk->data_ready = ncp_msg_data_ready; -- sk->protinfo.af_ipx.ncp_server = server; -- return 0; --} -- - #define NCP_SLACK_SPACE 1024 - - #define _S(nr) (1<<((nr)-1)) - --static int --do_ncp_rpc_call(struct ncp_server *server, int size) -+static int do_ncp_rpc_call(struct ncp_server *server, int size) - { - struct file *file; - struct inode *inode; -@@ -343,29 +87,24 @@ - char *start = server->packet; - poll_table wait_table; - struct poll_table_entry entry; -- int (*select) (struct inode *, poll_table *); - int init_timeout, max_timeout; - int timeout; - int retrans; - int major_timeout_seen; - int acknowledge_seen; -- char *server_name; - int n; - unsigned long old_mask; - - /* We have to check the result, so store the complete header */ - struct ncp_request_header request = -- *((struct ncp_request_header *)(server->packet)); -- -- struct ncp_reply_header reply; -+ *((struct ncp_request_header *) (server->packet)); - -+ struct ncp_reply_header reply; - - file = server->ncp_filp; - inode = file->f_inode; -- select = file->f_op->poll; - sock = &inode->u.socket_i; -- if (!sock) -- { -+ if (!sock) { - printk("ncp_rpc_call: socki_lookup failed\n"); - return -EBADF; - } -@@ -374,61 +113,53 @@ - retrans = server->m.retry_count; - major_timeout_seen = 0; - acknowledge_seen = 0; -- server_name = server->m.server_name; - old_mask = current->blocked; - current->blocked |= ~(_S(SIGKILL) - #if 0 -- | _S(SIGSTOP) -+ | _S(SIGSTOP) - #endif -- | ((server->m.flags & NCP_MOUNT_INTR) -- ? ((current->sig->action[SIGINT - 1].sa_handler == SIG_DFL -- ? _S(SIGINT) : 0) -- | (current->sig->action[SIGQUIT - 1].sa_handler == SIG_DFL -- ? _S(SIGQUIT) : 0)) -- : 0)); -+ | ((server->m.flags & NCP_MOUNT_INTR) -+ ? ((current->sig->action[SIGINT - 1].sa_handler == SIG_DFL -+ ? _S(SIGINT) : 0) -+ | (current->sig->action[SIGQUIT - 1].sa_handler == SIG_DFL -+ ? _S(SIGQUIT) : 0)) -+ : 0)); - fs = get_fs(); - 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", -- htonl(server->m.serv_addr.sipx_network), -- server->m.serv_addr.sipx_node[0], -- server->m.serv_addr.sipx_node[1], -- server->m.serv_addr.sipx_node[2], -- server->m.serv_addr.sipx_node[3], -- server->m.serv_addr.sipx_node[4], -- server->m.serv_addr.sipx_node[5], -- ntohs(server->m.serv_addr.sipx_port)); -+ htonl(server->m.serv_addr.sipx_network), -+ server->m.serv_addr.sipx_node[0], -+ server->m.serv_addr.sipx_node[1], -+ server->m.serv_addr.sipx_node[2], -+ server->m.serv_addr.sipx_node[3], -+ server->m.serv_addr.sipx_node[4], -+ server->m.serv_addr.sipx_node[5], -+ ntohs(server->m.serv_addr.sipx_port)); - DDPRINTK("ncpfs: req.typ: %04X, con: %d, " -- "seq: %d", -- request.type, -- (request.conn_high << 8) + request.conn_low, -- request.sequence); -+ "seq: %d", -+ request.type, -+ (request.conn_high << 8) + request.conn_low, -+ request.sequence); - DDPRINTK(" func: %d\n", - request.function); - -- result = _sendto(sock, (void *) start, size, 0, 0, -- &(server->m.serv_addr)); -- if (result < 0) -- { -+ result = _send(sock, (void *) start, size); -+ if (result < 0) { - printk("ncp_rpc_call: send error = %d\n", result); - break; - } -- re_select: -+ re_select: - wait_table.nr = 0; - wait_table.entry = &entry; - current->state = TASK_INTERRUPTIBLE; -- if (!select(inode, &wait_table)) -- { -- if (timeout > max_timeout) -- { -+ if (!(file->f_op->poll(file, &wait_table) & POLLIN)) { -+ if (timeout > max_timeout) { - /* JEJB/JSP 2/7/94 - * This is useful to see if the system is - * hanging */ -- if (acknowledge_seen == 0) -- { -- printk("NCP max timeout reached on " -- "%s\n", server_name); -+ if (acknowledge_seen == 0) { -+ printk("NCP max timeout\n"); - } - timeout = max_timeout; - } -@@ -436,102 +167,87 @@ - schedule(); - remove_wait_queue(entry.wait_address, &entry.wait); - current->state = TASK_RUNNING; -- if (current->signal & ~current->blocked) -- { -+ if (current->signal & ~current->blocked) { - current->timeout = 0; - result = -ERESTARTSYS; - break; - } -- if (!current->timeout) -- { -+ if (!current->timeout) { - if (n < retrans) - continue; -- if (server->m.flags & NCP_MOUNT_SOFT) -- { -- printk("NCP server %s not responding, " -- "timed out\n", server_name); -+ if (server->m.flags & NCP_MOUNT_SOFT) { -+ printk("NCP server not responding\n"); - result = -EIO; - break; - } - n = 0; - timeout = init_timeout; - init_timeout <<= 1; -- if (!major_timeout_seen) -- { -- printk("NCP server %s not responding, " -- "still trying\n", server_name); -+ if (!major_timeout_seen) { -+ printk("NCP server not responding\n"); - } - major_timeout_seen = 1; - continue; -- } -- else -+ } else - current->timeout = 0; -- } -- else if (wait_table.nr) -+ } else if (wait_table.nr) - remove_wait_queue(entry.wait_address, &entry.wait); - current->state = TASK_RUNNING; - - /* 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 - * we don't now need, so discard it */ -- result = _recvfrom(sock, (void *)&reply, -- sizeof(reply), 1, MSG_PEEK, NULL); -- if (result < 0) -- { -- if (result == -EAGAIN) -- { -+ result = _recv(sock, (void *) &reply, sizeof(reply), -+ MSG_PEEK | MSG_DONTWAIT); -+ if (result < 0) { -+ if (result == -EAGAIN) { - DPRINTK("ncp_rpc_call: bad select ready\n"); - goto re_select; - } -- if (result == -ECONNREFUSED) -- { -+ if (result == -ECONNREFUSED) { - DPRINTK("ncp_rpc_call: server playing coy\n"); - goto re_select; - } -- if (result != -ERESTARTSYS) -- { -+ if (result != -ERESTARTSYS) { - printk("ncp_rpc_call: recv error = %d\n", -- -result); -+ -result); - } - break; - } -- if ( (result == sizeof(reply)) -- && (reply.type == NCP_POSITIVE_ACK)) -- { -+ if ((result == sizeof(reply)) -+ && (reply.type == NCP_POSITIVE_ACK)) { - /* Throw away the packet */ - DPRINTK("ncp_rpc_call: got positive acknowledge\n"); -- _recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0, -- NULL); -+ _recv(sock, (void *) &reply, sizeof(reply), -+ MSG_DONTWAIT); - n = 0; - timeout = max_timeout; - acknowledge_seen = 1; - goto re_select; - } -- - DDPRINTK("ncpfs: rep.typ: %04X, con: %d, tsk: %d," -- "seq: %d\n", -- reply.type, -- (reply.conn_high << 8) + reply.conn_low, -- reply.task, -- reply.sequence); -- -- if ( (result >= sizeof(reply)) -- && (reply.type == NCP_REPLY) -- && ( (request.type == NCP_ALLOC_SLOT_REQUEST) -- || ( (reply.sequence == request.sequence) -- && (reply.conn_low == request.conn_low) --/* seem to get wrong task from NW311 && (reply.task == request.task)*/ -- && (reply.conn_high == request.conn_high)))) -- { -+ "seq: %d\n", -+ reply.type, -+ (reply.conn_high << 8) + reply.conn_low, -+ reply.task, -+ reply.sequence); -+ -+ if ((result >= sizeof(reply)) -+ && (reply.type == NCP_REPLY) -+ && ((request.type == NCP_ALLOC_SLOT_REQUEST) -+ || ((reply.sequence == request.sequence) -+ && (reply.conn_low == request.conn_low) -+/* seem to get wrong task from NW311 && (reply.task == request.task) */ -+ && (reply.conn_high == request.conn_high)))) { - if (major_timeout_seen) -- printk("NCP server %s OK\n", server_name); -+ printk("NCP server OK\n"); - break; - } - /* JEJB/JSP 2/7/94 - * we have xid mismatch, so discard the packet and start - * again. What a hack! but I can't call recvfrom with - * a null buffer yet. */ -- _recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0, NULL); -+ _recv(sock, (void *) &reply, sizeof(reply), MSG_DONTWAIT); - - DPRINTK("ncp_rpc_call: reply mismatch\n"); - goto re_select; -@@ -540,54 +256,42 @@ - * we have the correct reply, so read into the correct place and - * return it - */ -- result = _recvfrom(sock, (void *)start, server->packet_size, -- 1, 0, NULL); -- if (result < 0) -- { -+ result = _recv(sock, (void *) start, server->packet_size, MSG_DONTWAIT); -+ if (result < 0) { - 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..., " - "email to NET channel\n"); - printk("NCP: result=%d\n", result); - result = -EIO; - } -- - current->blocked = old_mask; - set_fs(fs); - return result; - } - -- - /* - * We need the server to be locked here, so check! - */ - --static int --ncp_do_request(struct ncp_server *server, int size) -+static int ncp_do_request(struct ncp_server *server, int size) - { - int result; - -- if (server->lock == 0) -- { -+ if (server->lock == 0) { - printk("ncpfs: Server not locked!\n"); - return -EIO; - } -- -- if (!ncp_conn_valid(server)) -- { -+ if (!ncp_conn_valid(server)) { - return -EIO; - } -- - result = do_ncp_rpc_call(server, size); - - DDPRINTK("do_ncp_rpc_call returned %d\n", result); - -- if (result < 0) -- { -+ if (result < 0) { - /* There was a problem with I/O, so the connections is -- * no longer usable. */ -+ * no longer usable. */ - ncp_invalidate_conn(server); - } - return result; -@@ -596,121 +300,105 @@ - /* ncp_do_request assures that at least a complete reply header is - * received. It assumes that server->current_size contains the ncp - * request size */ --int --ncp_request(struct ncp_server *server, int function) -+int ncp_request(struct ncp_server *server, int function) - { - struct ncp_request_header *h -- = (struct ncp_request_header *)(server->packet); -+ = (struct ncp_request_header *) (server->packet); - struct ncp_reply_header *reply -- = (struct ncp_reply_header *)(server->packet); -+ = (struct ncp_reply_header *) (server->packet); - - int request_size = server->current_size -- - sizeof(struct ncp_request_header); -+ - sizeof(struct ncp_request_header); - - int result; - -- if (server->has_subfunction != 0) -- { -- *(__u16 *)&(h->data[0]) = htons(request_size - 2); -+ if (server->has_subfunction != 0) { -+ *(__u16 *) & (h->data[0]) = htons(request_size - 2); - } -- - h->type = NCP_REQUEST; -- -+ - server->sequence += 1; -- h->sequence = server->sequence; -- h->conn_low = (server->connection) & 0xff; -+ h->sequence = server->sequence; -+ h->conn_low = (server->connection) & 0xff; - h->conn_high = ((server->connection) & 0xff00) >> 8; -- h->task = (current->pid) & 0xff; -- h->function = function; -+ h->task = (current->pid) & 0xff; -+ 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); - return result; - } -- -- server->completion = reply->completion_code; -+ server->completion = reply->completion_code; - server->conn_status = reply->connection_state; -- server->reply_size = result; -+ server->reply_size = result; - server->ncp_reply_size = result - sizeof(struct ncp_reply_header); - - result = reply->completion_code; - -- if (result != 0) -- { -+ if (result != 0) { - DPRINTK("ncp_completion_code: %x\n", result); - } -- return result; -+ return result; - } - --int --ncp_connect(struct ncp_server *server) -+int ncp_connect(struct ncp_server *server) - { - struct ncp_request_header *h -- = (struct ncp_request_header *)(server->packet); -+ = (struct ncp_request_header *) (server->packet); - int result; - - h->type = NCP_ALLOC_SLOT_REQUEST; -- -+ - server->sequence = 0; -- h->sequence = server->sequence; -- h->conn_low = 0xff; -+ h->sequence = server->sequence; -+ h->conn_low = 0xff; - h->conn_high = 0xff; -- h->task = (current->pid) & 0xff; -- h->function = 0; -+ h->task = (current->pid) & 0xff; -+ h->function = 0; - -- if ((result = ncp_do_request(server, sizeof(*h))) < 0) -- { -+ if ((result = ncp_do_request(server, sizeof(*h))) < 0) { - return result; - } -- - server->sequence = 0; - server->connection = h->conn_low + (h->conn_high * 256); - return 0; - } -- --int --ncp_disconnect(struct ncp_server *server) -+ -+int ncp_disconnect(struct ncp_server *server) - { - struct ncp_request_header *h -- = (struct ncp_request_header *)(server->packet); -+ = (struct ncp_request_header *) (server->packet); - - h->type = NCP_DEALLOC_SLOT_REQUEST; -- -+ - server->sequence += 1; -- h->sequence = server->sequence; -- h->conn_low = (server->connection) & 0xff; -+ h->sequence = server->sequence; -+ h->conn_low = (server->connection) & 0xff; - h->conn_high = ((server->connection) & 0xff00) >> 8; -- h->task = (current->pid) & 0xff; -- h->function = 0; -+ h->task = (current->pid) & 0xff; -+ h->function = 0; - - return ncp_do_request(server, sizeof(*h)); - } - --void --ncp_lock_server(struct ncp_server *server) -+void ncp_lock_server(struct ncp_server *server) - { - #if 0 - /* For testing, only 1 process */ -- if (server->lock != 0) -- { -+ if (server->lock != 0) { - DPRINTK("ncpfs: server locked!!!\n"); - } - #endif -- while (server->lock) -+ while (server->lock) - sleep_on(&server->wait); - server->lock = 1; - } - --void --ncp_unlock_server(struct ncp_server *server) -+void ncp_unlock_server(struct ncp_server *server) - { -- if (server->lock != 1) -- { -- printk("ncp_unlock_server: was not locked!\n"); -- } -- -- server->lock = 0; -- wake_up(&server->wait); -+ if (server->lock != 1) { -+ printk("ncp_unlock_server: was not locked!\n"); -+ } -+ server->lock = 0; -+ wake_up(&server->wait); - } -- -diff -urN 2.1.29/include/linux/ipx.h 2.1.29-patched/include/linux/ipx.h ---- 2.1.29/include/linux/ipx.h Thu Dec 12 16:14:38 1996 -+++ 2.1.29-patched/include/linux/ipx.h Sun Mar 23 11:28:24 1997 -@@ -1,6 +1,7 @@ - #ifndef _IPX_H_ - #define _IPX_H_ - #include -+#include - #define IPX_NODE_LEN 6 - #define IPX_MTU 576 - -diff -urN 2.1.29/include/linux/ncp.h 2.1.29-patched/include/linux/ncp.h ---- 2.1.29/include/linux/ncp.h Thu Feb 6 11:58:49 1997 -+++ 2.1.29-patched/include/linux/ncp.h Sun Mar 23 13:02:34 1997 -@@ -20,78 +20,42 @@ - #define NCP_DEALLOC_SLOT_REQUEST (0x5555) - - struct ncp_request_header { -- __u16 type __attribute__ ((packed)); -- __u8 sequence __attribute__ ((packed)); -- __u8 conn_low __attribute__ ((packed)); -- __u8 task __attribute__ ((packed)); -- __u8 conn_high __attribute__ ((packed)); -- __u8 function __attribute__ ((packed)); -- __u8 data[0] __attribute__ ((packed)); -+ __u16 type __attribute__((packed)); -+ __u8 sequence __attribute__((packed)); -+ __u8 conn_low __attribute__((packed)); -+ __u8 task __attribute__((packed)); -+ __u8 conn_high __attribute__((packed)); -+ __u8 function __attribute__((packed)); -+ __u8 data[0] __attribute__((packed)); - }; - - #define NCP_REPLY (0x3333) - #define NCP_POSITIVE_ACK (0x9999) - - struct ncp_reply_header { -- __u16 type __attribute__ ((packed)); -- __u8 sequence __attribute__ ((packed)); -- __u8 conn_low __attribute__ ((packed)); -- __u8 task __attribute__ ((packed)); -- __u8 conn_high __attribute__ ((packed)); -- __u8 completion_code __attribute__ ((packed)); -- __u8 connection_state __attribute__ ((packed)); -- __u8 data[0] __attribute__ ((packed)); --}; -- -- --#define NCP_BINDERY_USER (0x0001) --#define NCP_BINDERY_UGROUP (0x0002) --#define NCP_BINDERY_PQUEUE (0x0003) --#define NCP_BINDERY_FSERVER (0x0004) --#define NCP_BINDERY_NAME_LEN (48) --struct ncp_bindery_object { -- __u32 object_id; -- __u16 object_type; -- __u8 object_name[NCP_BINDERY_NAME_LEN]; -- __u8 object_flags; -- __u8 object_security; -- __u8 object_has_prop; --}; -- --struct nw_property { -- __u8 value[128]; -- __u8 more_flag; -- __u8 property_flag; --}; -- --struct prop_net_address { -- __u32 network __attribute__ ((packed)); -- __u8 node[IPX_NODE_LEN] __attribute__ ((packed)); -- __u16 port __attribute__ ((packed)); -+ __u16 type __attribute__((packed)); -+ __u8 sequence __attribute__((packed)); -+ __u8 conn_low __attribute__((packed)); -+ __u8 task __attribute__((packed)); -+ __u8 conn_high __attribute__((packed)); -+ __u8 completion_code __attribute__((packed)); -+ __u8 connection_state __attribute__((packed)); -+ __u8 data[0] __attribute__((packed)); - }; - - #define NCP_VOLNAME_LEN (16) - #define NCP_NUMBER_OF_VOLUMES (64) - struct ncp_volume_info { -- __u32 total_blocks; -- __u32 free_blocks; -- __u32 purgeable_blocks; -- __u32 not_yet_purgeable_blocks; -- __u32 total_dir_entries; -- __u32 available_dir_entries; -- __u8 sectors_per_block; -- char volume_name[NCP_VOLNAME_LEN+1]; --}; -- --struct ncp_filesearch_info { -- __u8 volume_number; -- __u16 directory_id; -- __u16 sequence_no; -- __u8 access_rights; -+ __u32 total_blocks; -+ __u32 free_blocks; -+ __u32 purgeable_blocks; -+ __u32 not_yet_purgeable_blocks; -+ __u32 total_dir_entries; -+ __u32 available_dir_entries; -+ __u8 sectors_per_block; -+ char volume_name[NCP_VOLNAME_LEN + 1]; - }; - --#define NCP_MAX_FILENAME 14 -- - /* these define the attribute byte as seen by NCP */ - #define aRONLY (ntohl(0x01000000)) - #define aHIDDEN (ntohl(0x02000000)) -@@ -105,17 +69,6 @@ - #define AR_EXCLUSIVE (ntohs(0x2000)) - - #define NCP_FILE_ID_LEN 6 --struct ncp_file_info { -- __u8 file_id[NCP_FILE_ID_LEN]; -- char file_name[NCP_MAX_FILENAME+1]; -- __u8 file_attributes; -- __u8 file_mode; -- __u32 file_length; -- __u16 creation_date; -- __u16 access_date; -- __u16 update_date; -- __u16 update_time; --}; - - /* Defines for Name Spaces */ - #define NW_NS_DOS 0 -@@ -164,34 +117,33 @@ - #define AR_OPEN_COMPRESSED 0x0100 - #endif - --struct nw_info_struct --{ -- __u32 spaceAlloc __attribute__ ((packed)); -- __u32 attributes __attribute__ ((packed)); -- __u16 flags __attribute__ ((packed)); -- __u32 dataStreamSize __attribute__ ((packed)); -- __u32 totalStreamSize __attribute__ ((packed)); -- __u16 numberOfStreams __attribute__ ((packed)); -- __u16 creationTime __attribute__ ((packed)); -- __u16 creationDate __attribute__ ((packed)); -- __u32 creatorID __attribute__ ((packed)); -- __u16 modifyTime __attribute__ ((packed)); -- __u16 modifyDate __attribute__ ((packed)); -- __u32 modifierID __attribute__ ((packed)); -- __u16 lastAccessDate __attribute__ ((packed)); -- __u16 archiveTime __attribute__ ((packed)); -- __u16 archiveDate __attribute__ ((packed)); -- __u32 archiverID __attribute__ ((packed)); -- __u16 inheritedRightsMask __attribute__ ((packed)); -- __u32 dirEntNum __attribute__ ((packed)); -- __u32 DosDirNum __attribute__ ((packed)); -- __u32 volNumber __attribute__ ((packed)); -- __u32 EADataSize __attribute__ ((packed)); -- __u32 EAKeyCount __attribute__ ((packed)); -- __u32 EAKeySize __attribute__ ((packed)); -- __u32 NSCreator __attribute__ ((packed)); -- __u8 nameLen __attribute__ ((packed)); -- __u8 entryName[256] __attribute__ ((packed)); -+struct nw_info_struct { -+ __u32 spaceAlloc __attribute__((packed)); -+ __u32 attributes __attribute__((packed)); -+ __u16 flags __attribute__((packed)); -+ __u32 dataStreamSize __attribute__((packed)); -+ __u32 totalStreamSize __attribute__((packed)); -+ __u16 numberOfStreams __attribute__((packed)); -+ __u16 creationTime __attribute__((packed)); -+ __u16 creationDate __attribute__((packed)); -+ __u32 creatorID __attribute__((packed)); -+ __u16 modifyTime __attribute__((packed)); -+ __u16 modifyDate __attribute__((packed)); -+ __u32 modifierID __attribute__((packed)); -+ __u16 lastAccessDate __attribute__((packed)); -+ __u16 archiveTime __attribute__((packed)); -+ __u16 archiveDate __attribute__((packed)); -+ __u32 archiverID __attribute__((packed)); -+ __u16 inheritedRightsMask __attribute__((packed)); -+ __u32 dirEntNum __attribute__((packed)); -+ __u32 DosDirNum __attribute__((packed)); -+ __u32 volNumber __attribute__((packed)); -+ __u32 EADataSize __attribute__((packed)); -+ __u32 EAKeyCount __attribute__((packed)); -+ __u32 EAKeySize __attribute__((packed)); -+ __u32 NSCreator __attribute__((packed)); -+ __u8 nameLen __attribute__((packed)); -+ __u8 entryName[256] __attribute__((packed)); - }; - - /* modify mask - use with MODIFY_DOS_INFO structure */ -@@ -209,97 +161,36 @@ - #define DM_INHERITED_RIGHTS_MASK (ntohl(0x00100000L)) - #define DM_MAXIMUM_SPACE (ntohl(0x00200000L)) - --struct nw_modify_dos_info --{ -- __u32 attributes __attribute__ ((packed)); -- __u16 creationDate __attribute__ ((packed)); -- __u16 creationTime __attribute__ ((packed)); -- __u32 creatorID __attribute__ ((packed)); -- __u16 modifyDate __attribute__ ((packed)); -- __u16 modifyTime __attribute__ ((packed)); -- __u32 modifierID __attribute__ ((packed)); -- __u16 archiveDate __attribute__ ((packed)); -- __u16 archiveTime __attribute__ ((packed)); -- __u32 archiverID __attribute__ ((packed)); -- __u16 lastAccessDate __attribute__ ((packed)); -- __u16 inheritanceGrantMask __attribute__ ((packed)); -- __u16 inheritanceRevokeMask __attribute__ ((packed)); -- __u32 maximumSpace __attribute__ ((packed)); -+struct nw_modify_dos_info { -+ __u32 attributes __attribute__((packed)); -+ __u16 creationDate __attribute__((packed)); -+ __u16 creationTime __attribute__((packed)); -+ __u32 creatorID __attribute__((packed)); -+ __u16 modifyDate __attribute__((packed)); -+ __u16 modifyTime __attribute__((packed)); -+ __u32 modifierID __attribute__((packed)); -+ __u16 archiveDate __attribute__((packed)); -+ __u16 archiveTime __attribute__((packed)); -+ __u32 archiverID __attribute__((packed)); -+ __u16 lastAccessDate __attribute__((packed)); -+ __u16 inheritanceGrantMask __attribute__((packed)); -+ __u16 inheritanceRevokeMask __attribute__((packed)); -+ __u32 maximumSpace __attribute__((packed)); - }; - - struct nw_file_info { - struct nw_info_struct i; -- int opened; -- int access; -- __u32 server_file_handle __attribute__ ((packed)); -- __u8 open_create_action __attribute__ ((packed)); -- __u8 file_handle[6] __attribute__ ((packed)); -+ int opened; -+ int access; -+ __u32 server_file_handle __attribute__((packed)); -+ __u8 open_create_action __attribute__((packed)); -+ __u8 file_handle[6] __attribute__((packed)); - }; - - struct nw_search_sequence { -- __u8 volNumber __attribute__ ((packed)); -- __u32 dirBase __attribute__ ((packed)); -- __u32 sequence __attribute__ ((packed)); -+ __u8 volNumber __attribute__((packed)); -+ __u32 dirBase __attribute__((packed)); -+ __u32 sequence __attribute__((packed)); - }; - --struct nw_queue_job_entry { -- __u16 InUse __attribute__ ((packed)); -- __u32 prev __attribute__ ((packed)); -- __u32 next __attribute__ ((packed)); -- __u32 ClientStation __attribute__ ((packed)); -- __u32 ClientTask __attribute__ ((packed)); -- __u32 ClientObjectID __attribute__ ((packed)); -- __u32 TargetServerID __attribute__ ((packed)); -- __u8 TargetExecTime[6] __attribute__ ((packed)); -- __u8 JobEntryTime[6] __attribute__ ((packed)); -- __u32 JobNumber __attribute__ ((packed)); -- __u16 JobType __attribute__ ((packed)); -- __u16 JobPosition __attribute__ ((packed)); -- __u16 JobControlFlags __attribute__ ((packed)); -- __u8 FileNameLen __attribute__ ((packed)); -- char JobFileName[13] __attribute__ ((packed)); -- __u32 JobFileHandle __attribute__ ((packed)); -- __u32 ServerStation __attribute__ ((packed)); -- __u32 ServerTaskNumber __attribute__ ((packed)); -- __u32 ServerObjectID __attribute__ ((packed)); -- char JobTextDescription[50] __attribute__ ((packed)); -- char ClientRecordArea[152] __attribute__ ((packed)); --}; -- --struct queue_job { -- struct nw_queue_job_entry j; -- __u8 file_handle[6]; --}; -- --#define QJE_OPER_HOLD 0x80 --#define QJE_USER_HOLD 0x40 --#define QJE_ENTRYOPEN 0x20 --#define QJE_SERV_RESTART 0x10 --#define QJE_SERV_AUTO 0x08 -- --/* 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 { -- __u8 Version __attribute__ ((packed)); -- __u8 TabSize __attribute__ ((packed)); -- __u16 Copies __attribute__ ((packed)); -- __u16 CtrlFlags __attribute__ ((packed)); -- __u16 Lines __attribute__ ((packed)); -- __u16 Rows __attribute__ ((packed)); -- char FormName[16] __attribute__ ((packed)); -- __u8 Reserved[6] __attribute__ ((packed)); -- char BannerName[13] __attribute__ ((packed)); -- char FnameBanner[13] __attribute__ ((packed)); -- char FnameHeader[14] __attribute__ ((packed)); -- char Path[80] __attribute__ ((packed)); --}; -- -- --#endif /* _LINUX_NCP_H */ -+#endif /* _LINUX_NCP_H */ -diff -urN 2.1.29/include/linux/ncp_fs.h 2.1.29-patched/include/linux/ncp_fs.h ---- 2.1.29/include/linux/ncp_fs.h Thu Feb 6 11:58:49 1997 -+++ 2.1.29-patched/include/linux/ncp_fs.h Sun Mar 23 13:02:43 1997 -@@ -21,22 +21,22 @@ - */ - - struct ncp_ioctl_request { -- unsigned int function; -- unsigned int size; -- char *data; -+ unsigned int function; -+ unsigned int size; -+ char *data; - }; - - struct ncp_fs_info { -- int version; -+ 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 -+ 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; --}; -+ 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) -@@ -53,8 +53,6 @@ - #define NCP_MAXPATHLEN 255 - #define NCP_MAXNAMELEN 14 - --#define NCP_MSG_COMMAND "/sbin/nwmsg" -- - #ifdef __KERNEL__ - - /* The readdir cache size controls how many directory entries are -@@ -62,7 +60,6 @@ - */ - #define NCP_READDIR_CACHE_SIZE 64 - -- - #define NCP_MAX_RPC_TIMEOUT (6*HZ) - - /* Guess, what 0x564c is :-) */ -@@ -84,26 +81,25 @@ - extern int ncp_current_malloced; - - static inline void * --ncp_kmalloc(unsigned int size, int priority) -+ ncp_kmalloc(unsigned int size, int priority) - { -- ncp_malloced += 1; -- ncp_current_malloced += 1; -- return kmalloc(size, priority); -+ ncp_malloced += 1; -+ ncp_current_malloced += 1; -+ return kmalloc(size, priority); - } - --static inline void --ncp_kfree_s(void *obj, int size) -+static inline void ncp_kfree_s(void *obj, int size) - { -- ncp_current_malloced -= 1; -- kfree_s(obj, size); -+ ncp_current_malloced -= 1; -+ kfree_s(obj, size); - } - --#else /* DEBUG_NCP_MALLOC */ -+#else /* DEBUG_NCP_MALLOC */ - - #define ncp_kmalloc(s,p) kmalloc(s,p) - #define ncp_kfree_s(o,s) kfree_s(o,s) - --#endif /* DEBUG_NCP_MALLOC */ -+#endif /* DEBUG_NCP_MALLOC */ - - #if DEBUG_NCP > 0 - #define DPRINTK(format, args...) printk(format , ## args) -@@ -127,39 +123,35 @@ - void ncp_free_inode_info(struct ncp_inode_info *i); - void ncp_free_all_inodes(struct ncp_server *server); - void ncp_init_root(struct ncp_server *server); --int ncp_conn_logged_in(struct ncp_server *server); -+int ncp_conn_logged_in(struct ncp_server *server); - void ncp_init_dir_cache(void); - 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_free_dir_cache(void); --int ncp_date_dos2unix(__u16 time, __u16 date); --void ncp_date_unix2dos(int unix_date, __u16 *time, __u16 *date); -+int ncp_date_dos2unix(__u16 time, __u16 date); -+void ncp_date_unix2dos(int unix_date, __u16 * time, __u16 * date); - - - /* linux/fs/ncpfs/ioctl.c */ --int ncp_ioctl (struct inode * inode, struct file * filp, -- unsigned int cmd, unsigned long arg); -+int ncp_ioctl(struct inode *inode, struct file *filp, -+ unsigned int cmd, unsigned long arg); - - /* linux/fs/ncpfs/inode.c */ - struct super_block *ncp_read_super(struct super_block *sb, -- void *raw_data, int silent); -+ void *raw_data, int silent); - extern int init_ncp_fs(void); --void ncp_trigger_message(struct ncp_server *server); - - /* linux/fs/ncpfs/sock.c */ - int ncp_request(struct ncp_server *server, int function); - int ncp_connect(struct ncp_server *server); - int ncp_disconnect(struct ncp_server *server); --int ncp_catch_watchdog(struct ncp_server *server); --int ncp_dont_catch_watchdog(struct ncp_server *server); --int ncp_catch_message(struct ncp_server *server); - void ncp_lock_server(struct ncp_server *server); - void ncp_unlock_server(struct ncp_server *server); - - /* linux/fs/ncpfs/mmap.c */ --int ncp_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma); -+int ncp_mmap(struct inode *inode, struct file *file, struct vm_area_struct *vma); - --#endif /* __KERNEL__ */ -+#endif /* __KERNEL__ */ - --#endif /* _LINUX_NCP_FS_H */ -+#endif /* _LINUX_NCP_FS_H */ -diff -urN 2.1.29/include/linux/ncp_fs_i.h 2.1.29-patched/include/linux/ncp_fs_i.h ---- 2.1.29/include/linux/ncp_fs_i.h Thu Feb 6 11:58:49 1997 -+++ 2.1.29-patched/include/linux/ncp_fs_i.h Sun Mar 23 13:02:43 1997 -@@ -13,21 +13,21 @@ - #ifdef __KERNEL__ - - enum ncp_inode_state { -- NCP_INODE_VALID = 19, /* Inode currently in use */ -- NCP_INODE_LOOKED_UP, /* directly before iget */ -- NCP_INODE_CACHED, /* in a path to an inode which is in use */ -- NCP_INODE_INVALID -+ NCP_INODE_VALID = 19, /* Inode currently in use */ -+ NCP_INODE_LOOKED_UP, /* directly before iget */ -+ NCP_INODE_CACHED, /* in a path to an inode which is in use */ -+ NCP_INODE_INVALID - }; - - /* - * ncp fs inode data (in memory only) - */ - struct ncp_inode_info { -- enum ncp_inode_state state; -- int nused; /* for directories: -- number of references in memory */ -- struct ncp_inode_info *dir; -- struct ncp_inode_info *next, *prev; -+ enum ncp_inode_state state; -+ int nused; /* for directories: -+ number of references in memory */ -+ struct ncp_inode_info *dir; -+ struct ncp_inode_info *next, *prev; - struct inode *inode; - struct nw_file_info finfo; - }; -diff -urN 2.1.29/include/linux/ncp_fs_sb.h 2.1.29-patched/include/linux/ncp_fs_sb.h ---- 2.1.29/include/linux/ncp_fs_sb.h Thu Feb 6 11:58:49 1997 -+++ 2.1.29-patched/include/linux/ncp_fs_sb.h Sun Mar 23 13:02:43 1997 -@@ -17,60 +17,52 @@ - - struct ncp_server { - -- struct ncp_mount_data m; /* Nearly all of the mount data is of -- interest for us later, so we store -- it completely. */ -+ struct ncp_mount_data m; /* Nearly all of the mount data is of -+ interest for us later, so we store -+ it completely. */ - - __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 *msg_filp; /* File pointer to message socket */ -- void *data_ready; /* The wdog socket gets a new -- data_ready callback. We store the -- old one for checking purposes and -- to reset it on unmounting. */ -- -- u8 sequence; -- u8 task; -- u16 connection; /* Remote connection number */ - -- u8 completion; /* Status message from server */ -- u8 conn_status; /* Bit 4 = 1 ==> Server going down, no -+ u8 sequence; -+ u8 task; -+ u16 connection; /* Remote connection number */ -+ -+ u8 completion; /* Status message from server */ -+ u8 conn_status; /* Bit 4 = 1 ==> Server going down, no - requests allowed anymore. - Bit 0 = 1 ==> Server is down. */ - -- int buffer_size; /* Negotiated bufsize */ -+ int buffer_size; /* Negotiated bufsize */ - -- int reply_size; /* Size of last reply */ -+ int reply_size; /* Size of last reply */ - -- int packet_size; -+ int packet_size; - unsigned char *packet; /* Here we prepare requests and - receive replies */ - -- int lock; /* To prevent mismatch in protocols. */ -+ int lock; /* To prevent mismatch in protocols. */ - struct wait_queue *wait; - -- int current_size; /* for packet preparation */ -- int has_subfunction; -- int ncp_reply_size; -+ int current_size; /* for packet preparation */ -+ int has_subfunction; -+ int ncp_reply_size; - -- struct ncp_inode_info root; -- char root_path; /* '\0' */ -+ struct ncp_inode_info root; -+ char root_path; /* '\0' */ - }; - --static inline int --ncp_conn_valid(struct ncp_server *server) -+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) -+static inline void ncp_invalidate_conn(struct ncp_server *server) - { - server->conn_status |= 0x01; - } - --#endif /* __KERNEL__ */ -+#endif /* __KERNEL__ */ - - #endif -diff -urN 2.1.29/include/linux/ncp_mount.h 2.1.29-patched/include/linux/ncp_mount.h ---- 2.1.29/include/linux/ncp_mount.h Thu Feb 6 11:58:49 1997 -+++ 2.1.29-patched/include/linux/ncp_mount.h Sun Mar 23 13:02:43 1997 -@@ -13,40 +13,28 @@ - #include - #include - --#define NCP_MOUNT_VERSION 2 -- --#define NCP_USERNAME_LEN (NCP_BINDERY_NAME_LEN) --#define NCP_PASSWORD_LEN 20 -+#define NCP_MOUNT_VERSION 3 - - /* Values for flags */ - #define NCP_MOUNT_SOFT 0x0001 - #define NCP_MOUNT_INTR 0x0002 - --/* Gosh... */ --#define NCP_PATH_MAX 1024 -- - struct ncp_mount_data { - int version; - unsigned int ncp_fd; /* The socket to the ncp port */ -- unsigned int wdog_fd; /* Watchdog packets come here */ -- unsigned int message_fd; /* Message notifications come here */ -- uid_t mounted_uid; /* Who may umount() this filesystem? */ -- -- struct sockaddr_ipx serv_addr; -- unsigned char server_name[NCP_BINDERY_NAME_LEN]; -- -- unsigned char mount_point[NCP_PATH_MAX+1]; -- unsigned char mounted_vol[NCP_VOLNAME_LEN+1]; -+ uid_t mounted_uid; /* Who may umount() this filesystem? */ -+ pid_t wdog_pid; /* Who cares for our watchdog packets? */ - -+ unsigned char mounted_vol[NCP_VOLNAME_LEN + 1]; - unsigned int time_out; /* How long should I wait after - sending a NCP request? */ -- unsigned int retry_count; /* And how often should I retry? */ -+ unsigned int retry_count; /* And how often should I retry? */ - unsigned int flags; - -- uid_t uid; -- gid_t gid; -- mode_t file_mode; -- mode_t dir_mode; -+ uid_t uid; -+ gid_t gid; -+ mode_t file_mode; -+ mode_t dir_mode; - }; - - #endif diff --git a/patches/lockup-2.0.28.diff b/patches/lockup-2.0.28.diff deleted file mode 100644 index 13d924e..0000000 --- a/patches/lockup-2.0.28.diff +++ /dev/null @@ -1,44 +0,0 @@ -diff -urN 2.0.11/fs/ncpfs/sock.c linux/fs/ncpfs/sock.c ---- 2.0.28/fs/ncpfs/sock.c Fri Jul 12 08:14:53 1996 -+++ linux/fs/ncpfs/sock.c Thu Aug 8 19:27:26 1996 -@@ -55,7 +55,8 @@ - { - struct iovec iov; - struct msghdr msg; -- -+ int result; -+ - iov.iov_base = (void *)buff; - iov.iov_len = len; - -@@ -65,7 +66,29 @@ - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - -- return sock->ops->sendmsg(sock, &msg, len, nonblock, flags); -+ result = sock->ops->sendmsg(sock, &msg, len, 1, flags); -+ -+ if ((result != -EAGAIN) || (nonblock != 0)) -+ { -+ return result; -+ } -+ -+ /* The following is probably one of the worst sins you can do -+ to a multitasking kernel: active polling. But when you call -+ ipx_sendmsg with nonblock==0, then it will block forever -+ from time to time. I really do not know why. To work around -+ this, I try to send the packet with nonblock=1 and retry -+ it. */ -+ -+ do { -+ /* Before retrying, give others a chance */ -+ current->state = TASK_INTERRUPTIBLE; -+ current->timeout = jiffies + HZ/10; -+ schedule(); -+ result = sock->ops->sendmsg(sock, &msg, len, 1, flags); -+ } while (result == -EAGAIN); -+ -+ return result; - } - - diff --git a/patches/lockup-2.0.30.diff b/patches/lockup-2.0.30.diff new file mode 100644 index 0000000..2d3d346 --- /dev/null +++ b/patches/lockup-2.0.30.diff @@ -0,0 +1,12 @@ +diff -u -urN 2.0.30/net/ipx/af_ipx.c 2.0.30-patched/net/ipx/af_ipx.c +--- 2.0.30/net/ipx/af_ipx.c Wed Nov 27 08:44:21 1996 ++++ 2.0.30-patched/net/ipx/af_ipx.c Mon Jul 14 17:25:12 1997 +@@ -1723,6 +1723,7 @@ + } + sk->rcvbuf=SK_RMEM_MAX; + sk->sndbuf=SK_WMEM_MAX; ++ sk->allocation=GFP_KERNEL; + sk->prot=NULL; /* So we use default free mechanisms */ + skb_queue_head_init(&sk->receive_queue); + skb_queue_head_init(&sk->write_queue); + diff --git a/sutil/Makefile b/sutil/Makefile index 638f2de..56f30b7 100644 --- a/sutil/Makefile +++ b/sutil/Makefile @@ -2,9 +2,17 @@ # Makefile for the linux ncp-filesystem routines. # -UTILS = ncpmount ncpumount nwsfind +include ../Makeinit -CC = gcc +ifdef MOUNT3 +# environ in ncpmount +CCFLAGS += -D_GNU_SOURCE +endif + +O_UTILS = ncpmount.o ncpumount.o nwsfind.o +UTILS = $(O_UTILS:%.o=%) + +CCFLAGS += -D__MAKE_SULIB__ default: make -C .. @@ -15,20 +23,20 @@ install: all for i in $(UTILS); \ do install $$i -m 4755 $(BINDIR); done -$(UTILS): %: %.o libncp.a - $(CC) -o $@ $(addsuffix .o,$@) -L. -lncp -L../lib -lcom_err +$(O_UTILS): %.o: %.c ../lib-static-su/ncplib_err.h + $(CC) $(CFLAGS) $(CCFLAGS) -I../lib-static-su -o $@ -c $< -ncplib.o: ncplib.c ncplib.h - $(CC) $(CFLAGS) -finline-functions -c ncplib.c +$(UTILS): %: %.o ../lib-static-su/libncp.a + $(CC) -o $@ $(addsuffix .o,$@) -L../lib-static-su -lncp -libncp.a: ncplib.o ../lib/ncplib_err.o - ar r libncp.a ncplib.o ../lib/ncplib_err.o +../lib-static-su/libncp.a ../lib-static-su/ncplib_err.h: + make -C ../lib-static-su libncp.a dep: $(CPP) -M $(INCLUDES) *.c > .depend clean: - rm -f *.o *~ libncp.a $(UTILS) + rm -f *.o *~ $(UTILS) mrproper: clean rm -f .depend diff --git a/sutil/ipxlib.h b/sutil/ipxlib.h deleted file mode 100644 index a4ecd0b..0000000 --- a/sutil/ipxlib.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * ipxlib.h - * - * Copyright (C) 1995 by Volker Lendecke - * - */ - -#ifndef _IPXLIB_H -#define _IPXLIB_H - - -#include -#include -#include -#include -#include - -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 */ diff --git a/sutil/ncplib.c b/sutil/ncplib.c deleted file mode 100644 index d5d96fd..0000000 --- a/sutil/ncplib.c +++ /dev/null @@ -1,1668 +0,0 @@ -/* - * ncplib.c - * - * Copyright (C) 1995, 1996 by Volker Lendecke - * - */ - -#include "ncplib.h" -#include "ncplib_err.h" - -#include -extern pid_t wait(int *); -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static long - ncp_negotiate_buffersize(struct ncp_conn *conn, - int size, int *target); -static long - ncp_login_object(struct ncp_conn *conn, - const unsigned char *username, - int login_type, - const unsigned char *password); - -static long - ncp_do_close(struct ncp_conn *conn); - -void str_upper(char *name) -{ - while (*name) { - *name = toupper(*name); - name = name + 1; - } -} - -/* I know it's terrible to include a .c file here, but I want to keep - the file nwcrypt.c intact and separate for copyright reasons */ -#include "nwcrypt.c" - -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", ntohl(net)); -} - -void ipx_fprint_port(FILE * file, IPXPort port) -{ - fprintf(file, "%04X", ntohs(port)); -} - -void ipx_fprint_saddr(FILE * file, struct sockaddr_ipx *sipx) -{ - ipx_fprint_network(file, sipx->sipx_network); - fprintf(file, ":"); - ipx_fprint_node(file, sipx->sipx_node); - fprintf(file, ":"); - ipx_fprint_port(file, 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); -} - -int ipx_sscanf_node(char *buf, unsigned char node[6]) -{ - 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 i; - } - for (i = 0; i < 6; i++) { - node[i] = n[i]; - } - return 6; -} - -void ipx_assign_node(IPXNode dest, IPXNode src) -{ - memcpy(dest, src, IPX_NODE_LEN); -} - -int ipx_node_equal(IPXNode n1, IPXNode n2) -{ - return memcmp(n1, n2, IPX_NODE_LEN) == 0; -} - -static int ipx_recvfrom(int sock, void *buf, int len, unsigned int flags, - struct sockaddr_ipx *sender, int *addrlen, int timeout, - long *err) -{ - fd_set rd, wr, ex; - struct timeval tv; - int result; - - FD_ZERO(&rd); - FD_ZERO(&wr); - FD_ZERO(&ex); - FD_SET(sock, &rd); - - tv.tv_sec = timeout; - tv.tv_usec = 0; - - if ((result = select(sock + 1, &rd, &wr, &ex, &tv)) == -1) { - *err = errno; - return -1; - } - if (FD_ISSET(sock, &rd)) { - result = recvfrom(sock, buf, len, flags, - (struct sockaddr *) sender, addrlen); - } else { - result = -1; - errno = ETIMEDOUT; - } - if (result < 0) { - *err = errno; - } - return result; -} - -static int ipx_recv(int sock, void *buf, int len, unsigned int flags, int timeout, - long *err) -{ - struct sockaddr_ipx sender; - int addrlen = sizeof(sender); - - return ipx_recvfrom(sock, buf, len, flags, &sender, &addrlen, - timeout, err); -} - -static long ipx_sap_find_nearest(int server_type, struct sockaddr_ipx *result, - char server_name[NCP_BINDERY_NAME_LEN]) -{ - struct sockaddr_ipx addr; - char data[1024]; - int sock; - int opt; - int packets; - int len; - - struct sap_server_ident *ident; - - if ((sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX)) < 0) { - if (errno == EINVAL) { - return NCPL_ET_NO_IPX; - } - return errno; - } - opt = 1; - /* Permit broadcast output */ - if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt)) == -1) { - goto finished; - } - memzero(addr); - addr.sipx_family = AF_IPX; - addr.sipx_network = htonl(0x0); - addr.sipx_port = htons(0x0); - addr.sipx_type = IPX_SAP_PTYPE; - - if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) == -1) { - if (errno == EADDRNOTAVAIL) { - errno = NCPL_ET_NO_INTERFACE; - } - goto finished; - } - WSET_HL(data, 0, IPX_SAP_NEAREST_QUERY); - WSET_HL(data, 2, server_type); - - memzero(addr); - addr.sipx_family = AF_IPX; - addr.sipx_port = htons(IPX_SAP_PORT); - addr.sipx_type = IPX_SAP_PTYPE; - addr.sipx_network = htonl(0x0); - ipx_assign_node(addr.sipx_node, IPX_BROADCAST_NODE); - - if (sendto(sock, data, 4, 0, - (struct sockaddr *) &addr, sizeof(addr)) < 0) { - goto finished; - } - packets = 5; - do { - long err; - len = ipx_recv(sock, data, 1024, 0, 1, &err); - if (len < 66) { - packets = packets - 1; - continue; - } - } - while ((ntohs(*((__u16 *) data)) != IPX_SAP_NEAREST_RESPONSE) - && (packets > 0)); - - if (packets == 0) { - close(sock); - return NCPL_ET_NO_SERVER; - } - ident = (struct sap_server_ident *) (data + 2); - - result->sipx_family = AF_IPX; - result->sipx_network = ident->server_network; - result->sipx_port = ident->server_port; - ipx_assign_node(result->sipx_node, ident->server_node); - - memcpy(server_name, ident->server_name, sizeof(ident->server_name)); - - errno = 0; - - finished: - close(sock); - return errno; -} - -static int ipx_make_reachable(IPXNet network) -{ - struct rtentry rt_def; - /* Router */ - struct sockaddr_ipx *sr = (struct sockaddr_ipx *) &rt_def.rt_gateway; - /* Target */ - struct sockaddr_ipx *st = (struct sockaddr_ipx *) &rt_def.rt_dst; - - struct ipx_rip_packet rip; - struct sockaddr_ipx addr; - int addrlen; - int sock; - int opt; - int res = -1; - int i; - int packets; - - if (geteuid() != 0) { - errno = EPERM; - return -1; - } - memzero(rip); - - sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX); - - if (sock == -1) { - if (errno == EINVAL) { - return NCPL_ET_NO_IPX; - } - return errno; - } - opt = 1; - /* Permit broadcast output */ - if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt)) != 0) { - goto finished; - } - memzero(addr); - addr.sipx_family = AF_IPX; - addr.sipx_network = htonl(0x0); - addr.sipx_port = htons(0x0); - addr.sipx_type = IPX_RIP_PTYPE; - - if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) != 0) { - goto finished; - } - addr.sipx_family = AF_IPX; - addr.sipx_port = htons(IPX_RIP_PORT); - addr.sipx_type = IPX_RIP_PTYPE; - addr.sipx_network = htonl(0x0); - ipx_assign_node(addr.sipx_node, IPX_BROADCAST_NODE); - - rip.operation = htons(IPX_RIP_REQUEST); - rip.rt[0].network = htonl(network); - - if (sendto(sock, &rip, sizeof(rip), 0, - (struct sockaddr *) &addr, sizeof(addr)) < 0) { - goto finished; - } - packets = 3; - do { - long err; - int len; - - if (packets == 0) { - goto finished; - } - addrlen = sizeof(struct sockaddr_ipx); - - len = ipx_recvfrom(sock, &rip, sizeof(rip), 0, sr, &addrlen, 1, - &err); - - if (len < sizeof(rip)) { - packets = packets - 1; - continue; - } - } - while (ntohs(rip.operation) != IPX_RIP_RESPONSE); - - if (rip.rt[0].network != htonl(network)) { - goto finished; - } - rt_def.rt_flags = RTF_GATEWAY; - st->sipx_network = htonl(network); - st->sipx_family = AF_IPX; - sr->sipx_family = AF_IPX; - - i = 0; - do { - res = ioctl(sock, SIOCADDRT, &rt_def); - i++; - } - while ((i < 5) && (res < 0) && (errno == EAGAIN)); - - finished: - close(sock); - - if (res != 0) { - errno = ENETUNREACH; - } - return res; -} - -static int install_wdog(struct ncp_conn *conn) -{ - int parent_pid = getpid(); - int pid; - int sock = conn->wdog_sock; - - char buf[1024]; - struct sockaddr_ipx sender; - int sizeofaddr = sizeof(struct sockaddr_ipx); - int pktsize; - - - if ((pid = fork()) < 0) { - return -1; - } - if (pid != 0) { - /* Parent, should go on as usual */ - conn->wdog_pid = pid; - return 0; - } - while (1) { - long err; - /* every 120 seconds we look if our parent is - still alive */ - pktsize = ipx_recvfrom(sock, buf, sizeof(buf), 0, - &sender, &sizeofaddr, 120, &err); - - if (getppid() != parent_pid) { - /* our parent has died, so nothing to do - anymore */ - exit(0); - } - if ((pktsize != 2) - || (buf[1] != '?')) { - continue; - } - buf[1] = 'Y'; - pktsize = sendto(sock, buf, 2, 0, - (struct sockaddr *) &sender, - sizeof(sender)); - } -} - -#define ncp_printf printf - -#define ncp_printf printf - -static void - assert_conn_locked(struct ncp_conn *conn); - -static void assert_conn_not_locked(struct ncp_conn *conn) -{ - if (conn->lock != 0) { - ncp_printf("ncpfs: conn already locked!\n"); - } -} - -static void ncp_lock_conn(struct ncp_conn *conn) -{ - assert_conn_not_locked(conn); - conn->lock = 1; -} - -static void ncp_unlock_conn(struct ncp_conn *conn) -{ - assert_conn_locked(conn); - conn->lock = 0; -} - -static long do_ncp_call(struct ncp_conn *conn, int request_size) -{ - struct ncp_request_header request; - - int result; - int retries = 20; - int len; - long err; - - memcpy(&request, conn->packet, sizeof(request)); - - while (retries > 0) { - struct ncp_reply_header reply; - struct sockaddr_ipx sender; - int sizeofaddr = sizeof(sender); - - retries -= 1; - - result = sendto(conn->ncp_sock, conn->packet, - request_size, - 0, (struct sockaddr *) &(conn->i.addr), - sizeof(conn->i.addr)); - - if (result < 0) { - return errno; - } - re_select: - len = ipx_recvfrom(conn->ncp_sock, - (char *) &reply, sizeof(reply), - MSG_PEEK, &sender, &sizeofaddr, 3, &err); - - if ((len < 0) && (err == ETIMEDOUT)) { - continue; - } - if (len < 0) { - return err; - } - if ( /* Is the sender wrong? */ - (memcmp(&sender.sipx_node, - &(conn->i.addr.sipx_node), 6) != 0) - || (sender.sipx_port != conn->i.addr.sipx_port) - /* Did the sender send a positive acknowledge? */ - || ((len == sizeof(reply)) - && (reply.type == NCP_POSITIVE_ACK)) - /* Did we get a bogus answer? */ - || ((len < sizeof(reply)) - || (reply.type != NCP_REPLY) - || ((request.type != NCP_ALLOC_SLOT_REQUEST) - && ((reply.sequence != request.sequence) - || (reply.conn_low != request.conn_low) - || (reply.conn_high != request.conn_high))))) { - /* Then throw away the packet */ - ipx_recv(conn->ncp_sock, (char *) &reply, sizeof(reply), - 0, 1, &err); - goto re_select; - } - ipx_recv(conn->ncp_sock, conn->packet, NCP_PACKET_SIZE, - 0, 1, &err); - conn->reply_size = len; - return 0; - } - return ETIMEDOUT; -} - -static int ncp_mount_request(struct ncp_conn *conn, int function) -{ - struct ncp_ioctl_request request; - int result; - - assert_conn_locked(conn); - - if (conn->has_subfunction != 0) { - WSET_HL(conn->packet, 7, conn->current_size - - sizeof(struct ncp_request_header) - 2); - } - request.function = function; - request.size = conn->current_size; - request.data = conn->packet; - - if ((result = ioctl(conn->mount_fid, NCP_IOC_NCPREQUEST, &request)) < 0) { - return result; - } - conn->completion = BVAL(conn->packet, 6); - conn->conn_status = BVAL(conn->packet, 7); - conn->ncp_reply_size = result - sizeof(struct ncp_reply_header); - - if ((conn->completion != 0) && (conn->verbose != 0)) { - ncp_printf("ncp_request_error: %d\n", conn->completion); - } - return conn->completion == 0 ? 0 : NCPL_ET_REQUEST_ERROR; -} - -static long ncp_temp_request(struct ncp_conn *conn, int function) -{ - long err; - - assert_conn_locked(conn); - - conn->sequence += 1; - - WSET_LH(conn->packet, 0, NCP_REQUEST); - BSET(conn->packet, 2, conn->sequence); - BSET(conn->packet, 3, (conn->i.connection) & 0xff); - BSET(conn->packet, 5, (conn->i.connection) >> 8); - BSET(conn->packet, 4, 1); - BSET(conn->packet, 6, function); - - if (conn->has_subfunction != 0) { - WSET_HL(conn->packet, 7, conn->current_size - - sizeof(struct ncp_request_header) - 2); - } - if ((err = do_ncp_call(conn, conn->current_size)) != 0) { - return err; - } - conn->completion = BVAL(conn->packet, 6); - conn->conn_status = BVAL(conn->packet, 7); - conn->ncp_reply_size = - conn->reply_size - sizeof(struct ncp_reply_header); - - if ((conn->completion != 0) && (conn->verbose != 0)) { - ncp_printf("ncp_completion_code: %d\n", conn->completion); - } - return conn->completion == 0 ? 0 : NCPL_ET_REQUEST_ERROR; -} - -static long ncp_connect_addr(struct ncp_conn *conn, const struct sockaddr_ipx *target, - int wdog_needed) -{ - struct sockaddr_ipx addr; - int addrlen; - - int ncp_sock, wdog_sock; - long err; - - conn->is_connected = NOT_CONNECTED; - conn->verbose = 0; - - if ((ncp_sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX)) == -1) { - return errno; - } - if ((wdog_sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX)) == -1) { - return errno; - } - addr.sipx_family = AF_IPX; - addr.sipx_port = htons(0x0); - addr.sipx_type = NCP_PTYPE; - addr.sipx_network = IPX_THIS_NET; - ipx_assign_node(addr.sipx_node, IPX_THIS_NODE); - - addrlen = sizeof(addr); - - if ((bind(ncp_sock, (struct sockaddr *) &addr, sizeof(addr)) == -1) - || (getsockname(ncp_sock, (struct sockaddr *) &addr, &addrlen) == -1)) { - int saved_errno = errno; - close(ncp_sock); - close(wdog_sock); - return saved_errno; - } - addr.sipx_port = htons(ntohs(addr.sipx_port) + 1); - - if (bind(wdog_sock, (struct sockaddr *) &addr, sizeof(addr)) == -1) { - int saved_errno = errno; - close(ncp_sock); - close(wdog_sock); - return saved_errno; - } - conn->ncp_sock = ncp_sock; - conn->wdog_sock = wdog_sock; - - conn->sequence = 0; - conn->i.addr = *target; - - WSET_LH(conn->packet, 0, NCP_ALLOC_SLOT_REQUEST); - BSET(conn->packet, 2, conn->sequence); - BSET(conn->packet, 3, 0xff); - BSET(conn->packet, 4, 1); - BSET(conn->packet, 5, 0xff); - BSET(conn->packet, 6, 0); - - if ((err = do_ncp_call(conn, sizeof(struct ncp_request_header))) != 0) { - if ((err != ENETUNREACH) - || (ipx_make_reachable(htonl(target->sipx_network)) != 0) - || ((err = - do_ncp_call(conn, - sizeof(struct ncp_request_header))) != 0)) { - close(ncp_sock); - close(wdog_sock); - return err; - } - } - if (wdog_needed != 0) { - install_wdog(conn); - } else { - conn->wdog_pid = 0; - } - - conn->sequence = 0; - conn->i.connection = - BVAL(conn->packet, 3) + (BVAL(conn->packet, 5) << 8); - conn->is_connected = CONN_TEMPORARY; - - if ((ncp_negotiate_buffersize(conn, 1024, - &(conn->i.buffer_size)) != 0) - || (conn->i.buffer_size < 512) - || (conn->i.buffer_size > 1024)) { - ncp_do_close(conn); - return -1; - } - return 0; -} - -static long ncp_connect_any(struct ncp_conn *conn, int wdog_needed) -{ - struct sockaddr_ipx addr; - char name[NCP_BINDERY_NAME_LEN]; - long result; - - if ((result = ipx_sap_find_nearest(IPX_SAP_FILE_SERVER, - &addr, name)) != 0) { - return result; - } - if ((result = ncp_connect_addr(conn, &addr, wdog_needed)) != 0) { - return result; - } - strcpy(conn->server, name); - return 0; -} - -struct sockaddr_ipx * - ncp_find_fileserver(char *server_name, long *err) -{ - return ncp_find_server(&server_name, NCP_BINDERY_FSERVER, err); -} - -struct sockaddr_ipx * - ncp_find_server(char **server_name, int type, long *err) -{ - char server[NCP_BINDERY_NAME_LEN + 1]; - static char nearest[NCP_BINDERY_NAME_LEN + 1]; - struct nw_property prop; - struct prop_net_address *n_addr = (struct prop_net_address *) ∝ - struct ncp_conn conn; - - static struct sockaddr_ipx result; - - initialize_NCPL_error_table(); - - memset(server, 0, sizeof(server)); - memset(nearest, 0, sizeof(nearest)); - - if (*server_name != NULL) { - if (strlen(*server_name) >= sizeof(server)) { - *err = NCPL_ET_NAMETOOLONG; - return NULL; - } - strcpy(server, *server_name); - str_upper(server); - } - if ((*err = ipx_sap_find_nearest(type, &result, nearest)) != 0) { - return NULL; - } - /* We have to ask the nearest server for our wanted server */ - - memzero(conn); - if ((*err = ncp_connect_addr(&conn, &result, 0)) != 0) { - return NULL; - } - if (*server_name == NULL) { - *server_name = nearest; - ncp_do_close(&conn); - errno = 0; - return &result; - } - /* The following optimization should have been done before - ncp_connect_addr. This would be convenient if there was a - simple way to find out whether there is a route to the - server. Parsing /proc/net/ipx_route is not too nice, so we - just connect to the server and immediately disconnect - again. This way we also find out if the server still has - free connection slots. */ - - if (strcmp(server, nearest) == 0) { - /* Our wanted server answered the SAP GNS request, so - use it */ - ncp_do_close(&conn); - errno = 0; - return &result; - } - if (ncp_read_property_value(&conn, type, server, 1, - "NET_ADDRESS", &prop) != 0) { - ncp_do_close(&conn); - *err = NCPL_ET_HOST_UNKNOWN; - return NULL; - } - if ((*err = ncp_do_close(&conn)) != 0) { - return NULL; - } - result.sipx_family = AF_IPX; - result.sipx_network = n_addr->network; - result.sipx_port = n_addr->port; - ipx_assign_node(result.sipx_node, n_addr->node); - - /* To make the final server reachable, we connect again. See - above. (When can we rely on all users running ipxd??? :-)) */ - memzero(conn); - if (((*err = ncp_connect_addr(&conn, &result, 0)) != 0) - || ((*err = ncp_do_close(&conn)) != 0)) { - return NULL; - } - return &result; -} - -static long ncp_open_temporary(struct ncp_conn *conn, - struct ncp_conn_spec *spec) -{ - struct sockaddr_ipx *addr; - long err; - - if (spec == NULL) { - return ncp_connect_any(conn, 1); - } - if ((addr = ncp_find_fileserver(spec->server, &err)) == NULL) { - return err; - } - if ((err = ncp_connect_addr(conn, addr, 1)) != 0) { - return err; - } - strcpy(conn->server, spec->server); - - if (strlen(spec->user) != 0) { - if (ncp_login_object(conn, spec->user, spec->login_type, - spec->password) != 0) { - ncp_do_close(conn); - return EACCES; - } - strcpy(conn->user, spec->user); - } - return 0; -} - -char * - ncp_find_permanent(const struct ncp_conn_spec *spec) -{ - FILE *mtab; - struct ncp_conn_ent *conn_ent; - char *result = NULL; - int mount_fid; - struct ncp_fs_info i; - - initialize_NCPL_error_table(); - - if ((mtab = fopen(MOUNTED, "r")) == NULL) { - return NULL; - } - while ((conn_ent = ncp_get_conn_ent(mtab)) != NULL) { - if (spec != NULL) { - if ((conn_ent->uid != spec->uid) - || ((strlen(spec->server) != 0) - && (strcasecmp(conn_ent->server, - spec->server) != 0)) - || ((strlen(spec->user) != 0) - && (strcasecmp(conn_ent->user, - spec->user) != 0))) { - continue; - } - } - mount_fid = open(conn_ent->mount_point, O_RDONLY, 0); - if (mount_fid < 0) { - continue; - } - i.version = NCP_GET_FS_INFO_VERSION; - - if (ioctl(mount_fid, NCP_IOC_GET_FS_INFO, &i) < 0) { - close(mount_fid); - continue; - } - close(mount_fid); - result = conn_ent->mount_point; - break; - } - - fclose(mtab); - errno = (result == NULL) ? ENOENT : 0; - return result; -} - -static int ncp_open_permanent(struct ncp_conn *conn, - const struct ncp_conn_spec *spec) -{ - char *mount_point; - - if (conn->is_connected != NOT_CONNECTED) { - errno = EBUSY; - return -1; - } - if ((mount_point = ncp_find_permanent(spec)) == NULL) { - return -1; - } - if (strlen(mount_point) >= sizeof(conn->mount_point)) { - errno = ENAMETOOLONG; - return -1; - } - /* The rest has already been done in ncp_find_permanent, so we - * do not check errors anymore */ - conn->mount_fid = open(mount_point, O_RDONLY, 0); - conn->i.version = NCP_GET_FS_INFO_VERSION; - ioctl(conn->mount_fid, NCP_IOC_GET_FS_INFO, &(conn->i)); - if (spec != NULL) { - strncpy(conn->server, spec->server, sizeof(conn->server)); - strncpy(conn->user, spec->user, sizeof(conn->user)); - } else { - memset(conn->server, '\0', sizeof(conn->server)); - memset(conn->user, '\0', sizeof(conn->user)); - } - strcpy(conn->mount_point, mount_point); - conn->is_connected = CONN_PERMANENT; - return 0; -} - -struct ncp_conn * - ncp_open(struct ncp_conn_spec *spec, long *err) -{ - struct ncp_conn *result; - - initialize_NCPL_error_table(); - - result = malloc(sizeof(struct ncp_conn)); - - if (result == NULL) { - *err = ENOMEM; - return NULL; - } - memzero(*result); - - if (ncp_open_permanent(result, spec) == 0) { - return result; - } - if ((*err = ncp_open_temporary(result, spec)) != 0) { - free(result); - return NULL; - } - return result; -} - - -struct ncp_conn * - ncp_open_mount(const char *mount_point, long *err) -{ - struct ncp_conn *result; - - initialize_NCPL_error_table(); - - if (strlen(mount_point) >= sizeof(result->mount_point)) { - *err = ENAMETOOLONG; - return NULL; - } - result = malloc(sizeof(struct ncp_conn)); - - if (result == NULL) { - *err = ENOMEM; - return NULL; - } - memzero(*result); - - result->is_connected = NOT_CONNECTED; - - result->mount_fid = open(mount_point, O_RDONLY, 0); - if (result->mount_fid < 0) { - free(result); - *err = ENODEV; - return NULL; - } - strcpy(result->mount_point, mount_point); - result->is_connected = CONN_PERMANENT; - - result->i.version = NCP_GET_FS_INFO_VERSION; - - if (ioctl(result->mount_fid, NCP_IOC_GET_FS_INFO, &(result->i)) != 0) { - free(result); - *err = NCPL_ET_NO_NCPFS_FILE; - return NULL; - } - return result; -} - -static long ncp_user_disconnect(struct ncp_conn *conn) -{ - long result; - - conn->sequence += 1; - - WSET_LH(conn->packet, 0, NCP_DEALLOC_SLOT_REQUEST); - BSET(conn->packet, 2, conn->sequence); - BSET(conn->packet, 3, (conn->i.connection) & 0xff); - BSET(conn->packet, 4, 1); - BSET(conn->packet, 5, (conn->i.connection) >> 8); - BSET(conn->packet, 6, 0); - - if ((result = do_ncp_call(conn, sizeof(struct ncp_request_header))) != 0) { - return result; - } - close(conn->ncp_sock); - close(conn->wdog_sock); - - if (conn->wdog_pid != 0) { - kill(conn->wdog_pid, SIGTERM); - wait(NULL); - } - return 0; -} - -static long ncp_do_close(struct ncp_conn *conn) -{ - long result = -1; - - switch (conn->is_connected) { - case CONN_PERMANENT: - result = close(conn->mount_fid); - break; - - case CONN_TEMPORARY: - result = ncp_user_disconnect(conn); - break; - - default: - break; - } - - conn->is_connected = NOT_CONNECTED; - - return result; -} - -long ncp_close(struct ncp_conn *conn) -{ - long result; - if (conn == NULL) { - return 0; - } - if ((result = ncp_do_close(conn)) != 0) { - return result; - } - free(conn); - return 0; -} - -struct ncp_conn_ent * - ncp_get_conn_ent(FILE * filep) -{ - static struct ncp_conn_ent entry; - char server[2 * NCP_BINDERY_NAME_LEN]; - char *user; - struct mntent *mnt_ent; - int fid; - - memzero(server); - memzero(entry); - - while ((mnt_ent = getmntent(filep)) != NULL) { - if (strcmp(mnt_ent->mnt_type, "ncpfs") != 0) { - continue; - } - if (strlen(mnt_ent->mnt_fsname) >= sizeof(server)) { - continue; - } - strcpy(server, mnt_ent->mnt_fsname); - user = strchr(server, '/'); - if (user != NULL) { - *user = '\0'; - user += 1; - if (strlen(user) >= sizeof(entry.user)) { - continue; - } - strcpy(entry.user, user); - } - if ((strlen(server) >= sizeof(entry.server)) - || (strlen(mnt_ent->mnt_dir) >= sizeof(entry.mount_point))) { - continue; - } - strcpy(entry.server, server); - strcpy(entry.mount_point, mnt_ent->mnt_dir); - - fid = open(entry.mount_point, O_RDONLY, 0); - - if (fid == -1) { - continue; - } - if (ioctl(fid, NCP_IOC_GETMOUNTUID, &entry.uid) != 0) { - close(fid); - continue; - } - close(fid); - return &entry; - } - - return NULL; -} - -static struct ncp_conn_spec * - ncp_get_nwc_ent(FILE * nwc) -{ - static struct ncp_conn_spec spec; - char line[512]; - int line_len; - char *user; - char *password; - - memzero(spec); - spec.uid = getuid(); - - while (fgets(line, sizeof(line), nwc) != NULL) { - if ((line[0] == '\n') - || (line[0] == '#')) { - continue; - } - line_len = strlen(line); - if (line[line_len - 1] == '\n') { - line[line_len - 1] = '\0'; - } - user = strchr(line, '/'); - password = strchr(user != NULL ? user : line, ' '); - - if (password != NULL) { - *password = '\0'; - password += 1; - } - if (user != NULL) { - *user = '\0'; - user += 1; - if (strlen(user) >= sizeof(spec.user)) { - continue; - } - strcpy(spec.user, user); - } - if (strlen(line) >= sizeof(spec.server)) { - continue; - } - strcpy(spec.server, line); - - if (password != NULL) { - while (*password == ' ') { - password += 1; - } - - if (strlen(password) >= sizeof(spec.password)) { - continue; - } - strcpy(spec.password, password); - } - return &spec; - } - return NULL; -} - -FILE * - ncp_fopen_nwc(const char *user, const char *mode, long *err) -{ - char path[MAXPATHLEN]; - char *home = NULL; - struct stat st; - - if (mode == NULL) { - mode = "r"; - } - if (user == NULL) { - home = getenv("HOME"); - } else { - struct passwd *pwd; - - if ((pwd = getpwnam(user)) != NULL) { - home = pwd->pw_dir; - } - } - - if ((home == NULL) - || (strlen(home) + sizeof(NWCLIENT) + 2 > sizeof(path))) { - *err = ENAMETOOLONG; - return NULL; - } - strcpy(path, home); - strcat(path, "/"); - strcat(path, NWCLIENT); - - if (stat(path, &st) != 0) { - *err = errno; - return NULL; - } - if ((st.st_mode & (S_IRWXO | S_IRWXG)) != 0) { - *err = NCPL_ET_INVALID_MODE; - return NULL; - } - return fopen(path, mode); -} - -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) -{ - static struct ncp_conn_spec spec; - - struct ncp_conn conn; - - FILE *nwc; - struct ncp_conn_spec *nwc_ent; - - initialize_NCPL_error_table(); - - *err = 0; - memzero(spec); - spec.uid = getuid(); - - if (server != NULL) { - if (strlen(server) >= sizeof(spec.server)) { - *err = NCPL_ET_NAMETOOLONG; - return NULL; - } - strcpy(spec.server, server); - } else { - if ((nwc = ncp_fopen_nwc(NULL, NULL, err)) == NULL) { - *err = NCPL_ET_NO_SERVER; - return NULL; - } - nwc_ent = ncp_get_nwc_ent(nwc); - fclose(nwc); - - if (nwc_ent == NULL) { - *err = NCPL_ET_NO_SPEC; - return NULL; - } - strcpy(spec.server, nwc_ent->server); - strcpy(spec.user, nwc_ent->user); - } - - str_upper(spec.server); - - if (login_necessary == 0) { - memset(spec.user, 0, sizeof(spec.user)); - memset(spec.password, 0, sizeof(spec.password)); - return &spec; - } - if (user != NULL) { - if (strlen(user) >= sizeof(spec.user)) { - *err = NCPL_ET_NAMETOOLONG; - return NULL; - } - strcpy(spec.user, user); - } - str_upper(spec.user); - spec.login_type = NCP_BINDERY_USER; - - if (ncp_open_permanent(&conn, &spec) == 0) { - ncp_do_close(&conn); - return &spec; - } - if (password != NULL) { - if (strlen(password) >= sizeof(spec.password)) { - *err = NCPL_ET_NAMETOOLONG; - return NULL; - } - strcpy(spec.password, password); - } else { - if ((nwc = ncp_fopen_nwc(NULL, NULL, err)) != NULL) { - while ((nwc_ent = ncp_get_nwc_ent(nwc)) != NULL) { - if ((strcasecmp(spec.server, - nwc_ent->server) != 0) - || ((*spec.user != '\0') - && (strcasecmp(spec.user, - nwc_ent->user) != 0))) { - continue; - } - strcpy(spec.user, nwc_ent->user); - strcpy(spec.password, nwc_ent->password); - break; - } - fclose(nwc); - } - } - - if (strlen(spec.user) == 0) { - *err = NCPL_ET_NO_USER; - return NULL; - } - if ((strlen(spec.password) == 0) && (password == NULL)) { - char *password; - if (!(isatty(0) && isatty(1))) { - return NULL; - } - printf("Logging into %s as %s\n", - spec.server, spec.user); - - password = getpass("Password: "); - if (strlen(password) > sizeof(spec.password)) { - return NULL; - } - strcpy(spec.password, password); - } else { - if (strcmp(spec.password, NWC_NOPASSWORD) == 0) { - *spec.password = '\0'; - } - } - - str_upper(spec.server); - str_upper(spec.user); - str_upper(spec.password); - return &spec; -} - -struct ncp_conn * - ncp_initialize_as(int *argc, char **argv, - int login_necessary, int login_type, long *err) -{ - char *server = NULL; - char *user = NULL; - char *password = NULL; - struct ncp_conn_spec *spec; - int i = 1; - - int get_argument(int arg_no, char **target) { - int count = 1; - - if (target != NULL) { - if (arg_no + 1 >= *argc) { - /* No argument to switch */ - errno = EINVAL; - return -1; - } - *target = argv[arg_no + 1]; - count = 2; - } - /* Delete the consumed switch from the argument list - and decrement the argument count */ - while (count + arg_no < *argc) { - argv[arg_no] = argv[arg_no + count]; - arg_no += 1; - } - *argc -= count; - return 0; - } - - initialize_NCPL_error_table(); - - *err = EINVAL; - - while (i < *argc) { - if ((argv[i][0] != '-') - || (strlen(argv[i]) != 2)) { - i += 1; - continue; - } - switch (argv[i][1]) { - case 'S': - if (get_argument(i, &server) != 0) { - return NULL; - } - continue; - case 'U': - if (get_argument(i, &user) != 0) { - return NULL; - } - continue; - case 'P': - if (get_argument(i, &password) != 0) { - return NULL; - } - continue; - case 'n': - if (get_argument(i, 0) != 0) { - return NULL; - } - password = NWC_NOPASSWORD; - continue; - } - i += 1; - } - - spec = ncp_find_conn_spec(server, user, password, login_necessary, - getuid(), err); - - if (spec == NULL) { - if (login_necessary != 0) { - return NULL; - } else { - return ncp_open(NULL, err); - } - } - spec->login_type = login_type; - - if (login_necessary == 0) { - spec->user[0] = '\0'; - } - return ncp_open(spec, err); -} - -struct ncp_conn * - ncp_initialize(int *argc, char **argv, - int login_necessary, long *err) -{ - return ncp_initialize_as(argc, argv, login_necessary, - NCP_BINDERY_USER, err); -} - -static long ncp_request(struct ncp_conn *conn, int function) -{ - switch (conn->is_connected) { - case CONN_PERMANENT: - return ncp_mount_request(conn, function); - case CONN_TEMPORARY: - return ncp_temp_request(conn, function); - default: - } - return ENOTCONN; -} - -/****************************************************************************/ -/* */ -/* Helper functions */ -/* */ -/****************************************************************************/ - -static inline int min(int a, int b) -{ - return (a < b) ? a : b; -} - -static void assert_conn_locked(struct ncp_conn *conn) -{ - if (conn->lock == 0) { - ncp_printf("ncpfs: conn not locked!\n"); - } -} - -static void ncp_add_byte(struct ncp_conn *conn, byte x) -{ - assert_conn_locked(conn); - BSET(conn->packet, conn->current_size, x); - conn->current_size += 1; - return; -} - -static void ncp_add_word_lh(struct ncp_conn *conn, word x) -{ - assert_conn_locked(conn); - WSET_LH(conn->packet, conn->current_size, x); - conn->current_size += 2; - return; -} - -static void ncp_add_dword_lh(struct ncp_conn *conn, dword x) -{ - assert_conn_locked(conn); - DSET_LH(conn->packet, conn->current_size, x); - conn->current_size += 4; - return; -} - -static void ncp_add_word_hl(struct ncp_conn *conn, word x) -{ - assert_conn_locked(conn); - WSET_HL(conn->packet, conn->current_size, x); - conn->current_size += 2; - return; -} - -static void ncp_add_dword_hl(struct ncp_conn *conn, dword x) -{ - assert_conn_locked(conn); - DSET_HL(conn->packet, conn->current_size, x); - conn->current_size += 4; - return; -} - -static void ncp_add_mem(struct ncp_conn *conn, const void *source, int size) -{ - assert_conn_locked(conn); - memcpy(&(conn->packet[conn->current_size]), source, size); - conn->current_size += size; - return; -} - -static void ncp_add_pstring(struct ncp_conn *conn, const char *s) -{ - int len = strlen(s); - assert_conn_locked(conn); - if (len > 255) { - ncp_printf("ncpfs: string too long: %s\n", s); - len = 255; - } - ncp_add_byte(conn, len); - ncp_add_mem(conn, s, len); - return; -} - -static void ncp_init_request(struct ncp_conn *conn) -{ - ncp_lock_conn(conn); - - conn->current_size = sizeof(struct ncp_request_header); - conn->has_subfunction = 0; -} - -static void ncp_init_request_s(struct ncp_conn *conn, int subfunction) -{ - ncp_init_request(conn); - ncp_add_word_lh(conn, 0); /* preliminary size */ - - ncp_add_byte(conn, subfunction); - - conn->has_subfunction = 1; -} - -static char * - ncp_reply_data(struct ncp_conn *conn, int offset) -{ - return &(conn->packet[sizeof(struct ncp_reply_header) + offset]); -} - -static byte - ncp_reply_byte(struct ncp_conn *conn, int offset) -{ - return *(byte *) (ncp_reply_data(conn, offset)); -} - -static word - ncp_reply_word_hl(struct ncp_conn *conn, int offset) -{ - return WVAL_HL(ncp_reply_data(conn, offset), 0); -} - -static word - ncp_reply_word_lh(struct ncp_conn *conn, int offset) -{ - return WVAL_LH(ncp_reply_data(conn, offset), 0); -} - -static dword - ncp_reply_dword_hl(struct ncp_conn *conn, int offset) -{ - return DVAL_HL(ncp_reply_data(conn, offset), 0); -} - -static dword - ncp_reply_dword_lh(struct ncp_conn *conn, int offset) -{ - return DVAL_LH(ncp_reply_data(conn, offset), 0); -} - -/* Here the ncp calls begin - */ - -static long ncp_negotiate_buffersize(struct ncp_conn *conn, - int size, int *target) -{ - long result; - - ncp_init_request(conn); - ncp_add_word_hl(conn, size); - - if ((result = ncp_request(conn, 33)) != 0) { - ncp_unlock_conn(conn); - return result; - } - *target = min(ncp_reply_word_hl(conn, 0), size); - - ncp_unlock_conn(conn); - return 0; -} - -/* - * target is a 8-byte buffer - */ -long ncp_get_encryption_key(struct ncp_conn *conn, - char *target) -{ - long result; - - ncp_init_request_s(conn, 23); - - if ((result = ncp_request(conn, 23)) != 0) { - ncp_unlock_conn(conn); - return result; - } - if (conn->ncp_reply_size < 8) { - ncp_printf("ncp_reply_size %d < 8\n", - conn->ncp_reply_size); - ncp_unlock_conn(conn); - return result; - } - memcpy(target, ncp_reply_data(conn, 0), 8); - ncp_unlock_conn(conn); - return 0; -} - -long ncp_get_bindery_object_id(struct ncp_conn *conn, - __u16 object_type, - const char *object_name, - struct ncp_bindery_object *target) -{ - long result; - ncp_init_request_s(conn, 53); - ncp_add_word_hl(conn, object_type); - ncp_add_pstring(conn, object_name); - - if ((result = ncp_request(conn, 23)) != 0) { - ncp_unlock_conn(conn); - return result; - } - if (conn->ncp_reply_size < 54) { - ncp_printf("ncp_reply_size %d < 54\n", - conn->ncp_reply_size); - ncp_unlock_conn(conn); - return result; - } - target->object_id = ncp_reply_dword_hl(conn, 0); - target->object_type = ncp_reply_word_hl(conn, 4); - memcpy(target->object_name, ncp_reply_data(conn, 6), 48); - ncp_unlock_conn(conn); - return 0; -} - -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 result; - ncp_init_request_s(conn, 61); - ncp_add_word_hl(conn, object_type); - ncp_add_pstring(conn, object_name); - ncp_add_byte(conn, segment); - ncp_add_pstring(conn, prop_name); - - if ((result = ncp_request(conn, 23)) != 0) { - ncp_unlock_conn(conn); - return result; - } - memcpy(&(target->value), ncp_reply_data(conn, 0), 128); - target->more_flag = ncp_reply_byte(conn, 128); - target->property_flag = ncp_reply_byte(conn, 129); - ncp_unlock_conn(conn); - return 0; -} - -long ncp_login_encrypted(struct ncp_conn *conn, - const struct ncp_bindery_object *object, - const unsigned char *key, - const unsigned char *passwd) -{ - dword tmpID = htonl(object->object_id); - unsigned char buf[128]; - unsigned char encrypted[8]; - long result; - - shuffle((byte *) & tmpID, passwd, strlen(passwd), buf); - nw_encrypt(key, buf, encrypted); - - ncp_init_request_s(conn, 24); - ncp_add_mem(conn, encrypted, 8); - ncp_add_word_hl(conn, object->object_type); - ncp_add_pstring(conn, object->object_name); - - result = ncp_request(conn, 23); - ncp_unlock_conn(conn); - return result; -} - -long ncp_login_unencrypted(struct ncp_conn *conn, - __u16 object_type, const char *object_name, - const unsigned char *passwd) -{ - long result; - ncp_init_request_s(conn, 20); - ncp_add_word_hl(conn, object_type); - ncp_add_pstring(conn, object_name); - ncp_add_pstring(conn, passwd); - result = ncp_request(conn, 23); - ncp_unlock_conn(conn); - return result; -} - -long ncp_login_user(struct ncp_conn *conn, - const unsigned char *username, - const unsigned char *password) -{ - return ncp_login_object(conn, username, NCP_BINDERY_USER, password); -} - -static long ncp_login_object(struct ncp_conn *conn, - const unsigned char *username, - int login_type, - const unsigned char *password) -{ - long result; - unsigned char ncp_key[8]; - struct ncp_bindery_object user; - - if ((result = ncp_get_encryption_key(conn, ncp_key)) != 0) { - return ncp_login_unencrypted(conn, login_type, username, - password); - } - if ((result = ncp_get_bindery_object_id(conn, login_type, - username, &user)) != 0) { - return result; - } - if ((result = ncp_login_encrypted(conn, &user, - ncp_key, password)) != 0) { - struct nw_property p; - struct ncp_prop_login_control *l - = (struct ncp_prop_login_control *) &p; - - if (conn->completion != NCP_GRACE_PERIOD) { - return result; - } - fprintf(stderr, "Your password has expired\n"); - - if ((result = ncp_read_property_value(conn, NCP_BINDERY_USER, - username, 1, - "LOGIN_CONTROL", - &p)) == 0) { - fprintf(stderr, "You have %d login attempts left\n", - l->GraceLogins); - } - } - return 0; -} - -long ncp_get_broadcast_message(struct ncp_conn *conn, char message[256]) -{ - long result; - int length; - - ncp_init_request_s(conn, 1); - - if ((result = ncp_request(conn, 21)) != 0) { - ncp_unlock_conn(conn); - return result; - } - length = ncp_reply_byte(conn, 0); - message[length] = 0; - memcpy(message, ncp_reply_data(conn, 1), length); - ncp_unlock_conn(conn); - return 0; -} diff --git a/sutil/ncplib.h b/sutil/ncplib.h deleted file mode 100644 index f580835..0000000 --- a/sutil/ncplib.h +++ /dev/null @@ -1,280 +0,0 @@ - - -/* - * ncplib.h - * - * Copyright (C) 1995, 1996 by Volker Lendecke - * - */ - -#ifndef _NCPLIB_H -#define _NCPLIB_H - -#include -#include "ncp.h" -#include -#include -#include -#include - -#include "ipxlib.h" -#include "com_err.h" - -#ifndef memzero -#include -#define memzero(object) memset(&(object), 0, sizeof(object)) -#endif - -typedef __u8 byte; -typedef __u16 word; -typedef __u32 dword; - -#define BVAL(buf,pos) (((__u8 *)(buf))[pos]) -#define PVAL(buf,pos) ((unsigned)BVAL(buf,pos)) -#define BSET(buf,pos,val) (BVAL(buf,pos) = (val)) - -static inline word - WVAL_HL(__u8 * buf, int pos) -{ - return PVAL(buf, pos) << 8 | PVAL(buf, pos + 1); -} -static inline dword - DVAL_HL(__u8 * buf, int pos) -{ - return WVAL_HL(buf, pos) << 16 | WVAL_HL(buf, pos + 2); -} -static inline void WSET_HL(__u8 * buf, int pos, word val) -{ - BSET(buf, pos, val >> 8); - BSET(buf, pos + 1, val & 0xff); -} -static inline void DSET_HL(__u8 * buf, int pos, dword val) -{ - WSET_HL(buf, pos, val >> 16); - WSET_HL(buf, pos + 2, val & 0xffff); -} - - -/* we know that the 386 can handle misalignment and has the "right" - byteorder */ -#if defined(__i386__) - -static inline word - WVAL_LH(__u8 * buf, int pos) -{ - return *((word *) (buf + pos)); -} -static inline dword - DVAL_LH(__u8 * buf, int pos) -{ - return *((dword *) (buf + pos)); -} -static inline void WSET_LH(__u8 * buf, int pos, word val) -{ - *((word *) (buf + pos)) = val; -} -static inline void DSET_LH(__u8 * buf, int pos, dword val) -{ - *((dword *) (buf + pos)) = val; -} - -#else - -static inline word - WVAL_LH(__u8 * buf, int pos) -{ - return PVAL(buf, pos) | PVAL(buf, pos + 1) << 8; -} -static inline dword - DVAL_LH(__u8 * buf, int pos) -{ - return WVAL_LH(buf, pos) | WVAL_LH(buf, pos + 2) << 16; -} -static inline void WSET_LH(__u8 * buf, int pos, word val) -{ - BSET(buf, pos, val & 0xff); - BSET(buf, pos + 1, val >> 8); -} -static inline void DSET_LH(__u8 * buf, int pos, dword val) -{ - WSET_LH(buf, pos, val & 0xffff); - WSET_LH(buf, pos + 2, val >> 16); -} - -#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_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(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(char *server_name, long *err); - -/* Find the address of a server */ -struct sockaddr_ipx * - ncp_find_server(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_encryption_key(struct ncp_conn *conn, - char *target); - -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); - -#define NCP_GRACE_PERIOD (0xdf) - -long - ncp_get_bindery_object_id(struct ncp_conn *conn, - __u16 object_type, - const char *object_name, - struct ncp_bindery_object *target); - -long - ncp_login_user(struct ncp_conn *conn, - const unsigned char *username, - const unsigned char *password); - -long - ncp_get_broadcast_message(struct ncp_conn *conn, char message[256]); - -#endif /* _NCPLIB_H */ diff --git a/sutil/ncpmount.c b/sutil/ncpmount.c index 4d31620..f614922 100644 --- a/sutil/ncpmount.c +++ b/sutil/ncpmount.c @@ -36,45 +36,198 @@ extern pid_t waitpid(pid_t, int *, int); #include #include #include -#include +#include "kernel/ipx.h" #include +#ifdef MOUNT3 #include #include +#endif -#include -#include -#include -#include +#include "kernel/ncp.h" +#include "kernel/ncp_fs.h" +#include "ncpmount.h" #include "ncplib.h" #include "com_err.h" +#include "ncplib_err.h" +#ifdef NDS_SUPPORT +#include "ndslib.h" +#endif + +#if defined(MOUNT2) && defined(MOUNT3) +#define MULTIVERSION_MOUNT 1 +#else +#define MULTIVERSION_MOUNT 0 +#endif + +#if MULTIVERSION_MOUNT +#include +#endif static char *progname; static char mount_point[MAXPATHLEN + 1]; static void usage(void); static void help(void); -static int process_connection(int wdog_fd, int msg_fd); + +#ifdef MOUNT2 +/* Returns 0 if the filesystem is in the kernel after this routine + completes */ +static int +load_ncpfs(void) +{ + FILE *ffs; + char s[1024]; + char *p, *p1; + pid_t pid; + int status; + + /* Check if ncpfs is in the kernel */ + ffs = fopen("/proc/filesystems", "r"); + + if (ffs == NULL) + { + perror("Error: \"/proc/filesystems\" could not be read:"); + return -1; + } + p = NULL; + while (!feof(ffs)) + { + p1 = fgets(s, sizeof(s), ffs); + if (p1) + { + p = strstr(s, "ncpfs"); + if (p) + { + break; + } + } + } + fclose(ffs); + + if (p) + { + return 0; + } + /* system() function without signal handling, from Stevens */ + + if ((pid = fork()) < 0) + { + return 1; + } else if (pid == 0) + { + /* child */ + execl("/sbin/modprobe", "modprobe", "ncpfs", NULL); + _exit(127); /* execl error */ + } else + { + /* parent */ + while (waitpid(pid, &status, 0) < 0) + { + if (errno != EINTR) + { + status = -1; + break; + } + } + } + return status; +} +#endif /* MOUNT2 */ + +struct ncp_mount_data_independent { + int ncp_fd; + int wdog_fd; + int message_fd; + uid_t mounted_uid; + struct sockaddr_ipx serv_addr; + unsigned char *server_name; + unsigned char *mount_point; + unsigned char *mounted_vol; + unsigned int time_out; + unsigned int retry_count; + struct { + unsigned int mount_soft:1; + unsigned int mount_intr:1; + unsigned int mount_strong:1; + unsigned int mount_no_os2:1; + unsigned int mount_no_nfs:1; + } flags; + uid_t uid; + gid_t gid; + mode_t file_mode; + mode_t dir_mode; +}; + +#ifdef MOUNT3 +static int process_connection(const struct ncp_mount_data_independent* mnt); +#endif + +#if MULTIVERSION_MOUNT +int getmountver(void) { + struct utsname name; + int maj, mid; + int ver; + + if (uname(&name)) { + fprintf(stderr, "Cannot get kernel release\n"); + exit(1); + } + if (sscanf(name.release, "%d.%d", &maj, &mid) != 2) { + fprintf(stderr, "Cannot convert kernel release \"%s\" to number\n", name.release); + exit(1); + } + ver = maj*0x10000 + mid*0x100; + if (ver < 0x20100) { +#ifdef MOUNT2 + return 2; +#else + fprintf(stderr, "This kernel requires mount version 2 which is not available\n"); + exit(1); +#endif + } +#ifdef MOUNT3 + return 3; +#else + fprintf(stderr, "This kernel requires mount version 3 which is not available\n"); + exit(1); +#endif +} +#else +#ifdef MOUNT3 +#define getmountver() 3 +#else +#ifdef MOUNT2 +#define getmountver() 2 +#else +#error "You must define at least one of MOUNT2, MOUNT3" +#endif +#endif +#endif /* Check whether user is allowed to mount on the specified mount point */ -static int mount_ok(struct stat *st) +static int +mount_ok(struct stat *st) { - if (!S_ISDIR(st->st_mode)) { + if (!S_ISDIR(st->st_mode)) + { errno = ENOTDIR; return -1; } if ((getuid() != 0) && ((getuid() != st->st_uid) - || ((st->st_mode & S_IRWXU) != S_IRWXU))) { + || ((st->st_mode & S_IRWXU) != S_IRWXU))) + { errno = EPERM; return -1; } return 0; } +#ifdef MOUNT3 /* * This function changes the processes name as shown by the system. * Stolen from Marcin Dalecki's modald :-) */ -static void inststr(char *dst[], int argc, char *src) +static void inststr(char *dst[], int argc, const char *src) { /* stolen from the source to perl 4.036 (assigning to $0) */ char *ptr, *ptr2; @@ -99,17 +252,142 @@ static void inststr(char *dst[], int argc, char *src) dst[count] = NULL; } } +#endif -int main(int argc, char *argv[]) +#ifdef MOUNT2 +int ncp_mount_v2(const char* mount_name, unsigned long flags, const struct ncp_mount_data_independent* data) { + struct ncp_mount_data_v2 datav2; + + if (data->serv_addr.sipx_family != AF_IPX) { + errno = EPROTONOSUPPORT; + return -1; + } + datav2.version = NCP_MOUNT_VERSION_V2; + datav2.ncp_fd = data->ncp_fd; + datav2.wdog_fd = data->wdog_fd; + datav2.message_fd = data->message_fd; + datav2.mounted_uid = data->mounted_uid; + memcpy(&datav2.serv_addr, &data->serv_addr, sizeof(datav2.serv_addr)); + strncpy(datav2.server_name, data->server_name, sizeof(datav2.server_name)); + strncpy(datav2.mount_point, data->mount_point, sizeof(datav2.mount_point)); + strncpy(datav2.mounted_vol, data->mounted_vol, sizeof(datav2.mounted_vol)); + datav2.time_out = data->time_out; + datav2.retry_count = data->retry_count; + datav2.flags = 0; + datav2.flags |= data->flags.mount_soft?NCP_MOUNT2_SOFT:0; + datav2.flags |= data->flags.mount_intr?NCP_MOUNT2_INTR:0; + datav2.flags |= data->flags.mount_strong?NCP_MOUNT2_STRONG:0; + datav2.flags |= data->flags.mount_no_os2?NCP_MOUNT2_NO_OS2:0; + datav2.flags |= data->flags.mount_no_nfs?NCP_MOUNT2_NO_NFS:0; + datav2.uid = data->uid; + datav2.gid = data->gid; + datav2.file_mode = data->file_mode; + datav2.dir_mode = data->dir_mode; + return mount(mount_name, data->mount_point, "ncpfs", flags, (void*) &datav2); +} +#endif + +#ifdef MOUNT3 +int ncp_mount_v3(const char* mount_name, unsigned long flags, const struct ncp_mount_data_independent* data, int argc, char* argv[]) { + struct ncp_mount_data_v3 datav3; + int err; + + datav3.version = NCP_MOUNT_VERSION_V3; + datav3.ncp_fd = data->ncp_fd; + datav3.mounted_uid = data->mounted_uid; + strncpy(datav3.mounted_vol, data->mounted_vol, sizeof(datav3.mounted_vol)); + datav3.time_out = data->time_out; + datav3.retry_count = data->retry_count; + datav3.flags = 0; + datav3.flags |= data->flags.mount_soft?NCP_MOUNT3_SOFT:0; + datav3.flags |= data->flags.mount_intr?NCP_MOUNT3_INTR:0; + datav3.flags |= data->flags.mount_strong?NCP_MOUNT3_STRONG:0; + datav3.flags |= data->flags.mount_no_os2?NCP_MOUNT3_NO_OS2:0; + datav3.flags |= data->flags.mount_no_nfs?NCP_MOUNT3_NO_NFS:0; + datav3.uid = data->uid; + datav3.gid = data->gid; + datav3.file_mode = data->file_mode; + datav3.dir_mode = data->dir_mode; + connect(datav3.ncp_fd, (const struct sockaddr *)&data->serv_addr, sizeof(data->serv_addr)); + datav3.wdog_pid = fork(); + if (datav3.wdog_pid < 0) { + fprintf(stderr, "could not fork: %s\n", strerror(errno)); + exit(1); + } + if (datav3.wdog_pid == 0) { + /* Child */ + inststr(argv, argc, "ncpd"); + process_connection(data); + exit(0); /* Should not return from process_connection */ + } + err=mount(mount_name, data->mount_point, "ncpfs", flags, (void*) &datav3); + if (err) { + /* Mount unsuccesful so we have to kill daemon */ + /* If mount success, kernel kills daemon (at least in 2.1.79) */ + kill(datav3.wdog_pid, SIGTERM); + } + return err; +} +#endif + +int +ncp_mount_specific(struct ncp_conn* conn, int pathNS, const unsigned char* NWpath, int pathlen) { + int result; + +#ifdef NCP_IOC_SETROOT + { + struct ncp_setroot_ioctl sr; + + if (pathlen == 1) { + sr.volNumber = -1; + sr.namespace = -1; + sr.dirEntNum = 0; + } else { + struct nw_info_struct dirinfo; + + result = ncp_obtain_file_or_subdir_info2(conn, pathNS, NW_NS_DOS, + 0x8006, RIM_ALL, 0xFF, 0, 0, NWpath, pathlen, &dirinfo); + if (result) { + return -ENOENT; + } + if (!(dirinfo.attributes & htonl(0x10000000))) { + return -ENOTDIR; + } + sr.volNumber = dirinfo.volNumber; + sr.namespace = NW_NS_DOS; + sr.dirEntNum = dirinfo.dirEntNum; + } + result = ioctl(conn->mount_fid, NCP_IOC_SETROOT, &sr); + if (!result) { + return 0; + } + } +#endif + if ((pathlen != 1) && (*NWpath != 1)) { + fprintf(stderr, "Remote directory is specified but " +#ifdef NCP_IOC_SETROOT + "kernel" +#else + "ncpmount" +#endif + " does not support subdir mounts\n"); + return -ENOPKG; + } + if (ioctl(conn->mount_fid, NCP_IOC_CONN_LOGGED_IN, NULL) != 0) { + return -errno; + } + return 0; +} + +int +main(int argc, char *argv[]) { - struct ncp_mount_data data; + struct ncp_mount_data_independent mdata; struct stat st; char mount_name[256]; int fd, result; - int wdog_fd, msg_fd; struct sockaddr_ipx addr; - struct sockaddr_ipx *server_addr; int addrlen; int upcase_password; @@ -124,43 +402,91 @@ int main(int argc, char *argv[]) char *server = NULL; char *user = NULL; char *password = NULL; - struct ncp_conn_spec *spec; - uid_t conn_uid = getuid(); + struct ncp_conn_spec *spec; struct ncp_conn *conn; int opt; +#ifdef SIGNATURES + int sig_level = -1; +#endif +#ifdef NDS_SUPPORT + int force_bindery_login = 0; +#endif +#ifdef CONFIG_NATIVE_IP + struct sockaddr_in server_in; + const char* server_name = NULL; +#endif + + char *tmp_mount; + int allow_multiple_connections = 0; + + int mount_protocol_version = -1; + + const char* remotepath = "/"; + unsigned char NWpath[512]; + int pathlen = 1; + NWpath[0] = 0; + progname = argv[0]; - memzero(data); + memzero(mdata); memzero(spec); - if (geteuid() != 0) { + mdata.mounted_uid = getuid(); + + if (geteuid() != 0) + { fprintf(stderr, "%s must be installed suid root\n", progname); exit(1); } - data.uid = getuid(); - data.gid = getgid(); + mdata.uid = getuid(); + mdata.gid = getgid(); um = umask(0); umask(um); - data.file_mode = (S_IRWXU | S_IRWXG | S_IRWXO) & ~um; - data.dir_mode = 0; - data.flags |= NCP_MOUNT_SOFT; - data.time_out = 60; - data.retry_count = 5; + mdata.file_mode = (S_IRWXU | S_IRWXG | S_IRWXO) & ~um; + mdata.dir_mode = 0; + mdata.flags.mount_soft = 1; + mdata.flags.mount_intr = 0; + mdata.flags.mount_strong = 0; + mdata.flags.mount_no_os2 = 0; + mdata.flags.mount_no_nfs = 0; + mdata.time_out = 60; + mdata.retry_count = 5; + mdata.mounted_vol = ""; upcase_password = 1; - while ((opt = getopt(argc, argv, "CS:U:c:u:g:f:d:P:nh?vV:t:r:")) - != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "CS:U:c:u:g:f:d:P:nh?vV:t:r:" + "sN:" +#ifdef SIGNATURES + "i:" +#endif +#ifdef NDS_SUPPORT + "b" +#endif + "m" +#ifdef MOUNT2 + "2" +#endif +#ifdef MOUNT3 + "3" +#endif +#ifdef CONFIG_NATIVE_IP + "A:" +#endif + )) != EOF) + { + switch (opt) + { case 'C': upcase_password = 0; break; case 'S': - if (strlen(optarg) >= sizeof(spec->server)) { + if (strlen(optarg) >= sizeof(spec->server)) + { fprintf(stderr, "Servername too long:%s\n", optarg); return 1; @@ -168,80 +494,97 @@ int main(int argc, char *argv[]) server = optarg; break; case 'U': - if (strlen(optarg) >= sizeof(spec->user)) { - fprintf(stderr, "Username too long: %s\n", - optarg); - return 1; - } user = optarg; break; case 'c': - if (isdigit(optarg[0])) { - conn_uid = atoi(optarg); - } else { + if (isdigit(optarg[0])) + { + mdata.mounted_uid = atoi(optarg); + } else + { struct passwd *pwd = getpwnam(optarg); - if (pwd == NULL) { + if (pwd == NULL) + { fprintf(stderr, "Unknown user: %s\n", optarg); return 1; } - data.uid = pwd->pw_uid; + mdata.mounted_uid = pwd->pw_uid; } break; case 'u': - if (isdigit(optarg[0])) { - data.uid = atoi(optarg); - } else { + if (isdigit(optarg[0])) + { + mdata.uid = atoi(optarg); + } else + { struct passwd *pwd = getpwnam(optarg); - if (pwd == NULL) { + if (pwd == NULL) + { fprintf(stderr, "Unknown user: %s\n", optarg); return 1; } - data.uid = pwd->pw_uid; + mdata.uid = pwd->pw_uid; } break; case 'g': - if (isdigit(optarg[0])) { - data.gid = atoi(optarg); - } else { + if (isdigit(optarg[0])) + { + mdata.gid = atoi(optarg); + } else + { struct group *grp = getgrnam(optarg); - if (grp == NULL) { + if (grp == NULL) + { fprintf(stderr, "Unknown group: %s\n", optarg); return 1; } - data.gid = grp->gr_gid; + mdata.gid = grp->gr_gid; } break; case 'f': - data.file_mode = strtol(optarg, NULL, 8); + mdata.file_mode = strtol(optarg, NULL, 8); break; case 'd': - data.dir_mode = strtol(optarg, NULL, 8); + mdata.dir_mode = strtol(optarg, NULL, 8); break; case 'P': - if (strlen(optarg) >= sizeof(spec->password)) { + if (strlen(optarg) >= sizeof(spec->password)) + { printf("password too long\n"); exit(1); } password = optarg; break; case 'V': - if (strlen(optarg) >= sizeof(data.mounted_vol)) { - printf("Volume too long: %s\n", optarg); + pathlen = ncp_path_to_NW_format(optarg, NWpath, sizeof(NWpath)); + remotepath = optarg; + if (pathlen < 0) { + fprintf(stderr, "Volume path invalid: %s\n", strerror(-pathlen)); exit(1); + }; + if (pathlen == 1) { + mdata.mounted_vol = ""; + remotepath = "/"; + } else if (*NWpath != 1) { + mdata.mounted_vol = "dummy"; + } else if (strlen(optarg) > NCP_VOLNAME_LEN) { + fprintf(stderr, "Volume too long: %s\n", optarg); + exit(1); + } else { + mdata.mounted_vol=optarg; } - strcpy(data.mounted_vol, optarg); break; case 'n': password = ""; break; case 't': - data.time_out = atoi(optarg); + mdata.time_out = atoi(optarg); break; case 'r': - data.retry_count = atoi(optarg); + mdata.retry_count = atoi(optarg); break; case 'h': case '?': @@ -250,112 +593,247 @@ int main(int argc, char *argv[]) case 'v': fprintf(stderr, "ncpfs version %s\n", NCPFS_VERSION); exit(1); + case 's': + mdata.flags.mount_strong = 1; + break; +#ifdef SIGNATURES + case 'i': + sig_level = atoi(optarg); + if ((sig_level < 0) || (sig_level > 3)) { + fprintf(stderr, "Invalid NCP signature level option `%s' (must be number between 0 and 3)\n", optarg); + exit(1); + } + break; +#endif +#ifdef NDS_SUPPORT + case 'b': + force_bindery_login = 1; + break; +#endif + case 'm': + allow_multiple_connections = 1; + break; +#ifdef MOUNT2 + case '2': + mount_protocol_version = 2; + break; +#endif +#ifdef MOUNT3 + case '3': + mount_protocol_version = 3; + break; +#endif +#ifdef CONFIG_NATIVE_IP + case 'A': + server_name = optarg; + break; +#endif + case 'N': + { + char *inp = optarg; + char *out; + + while ((out = strtok(inp, ",;:"))!=NULL) { + inp=NULL; + if (!strcasecmp(out, "OS2")) + mdata.flags.mount_no_os2=1; + else if (!strcasecmp(out, "LONG")) + mdata.flags.mount_no_os2=1; + else if (!strcasecmp(out, "NFS")) + mdata.flags.mount_no_nfs=1; + else { + fprintf(stderr, "Unknown namespace \"%s\"\n", out); + return 128; + } + } + }; + break; + default: usage(); return -1; } } - - if ((spec = ncp_find_conn_spec(server, user, password, - 1, data.uid, &err)) - == NULL) { + + if (mount_protocol_version < 0) { + mount_protocol_version = getmountver(); + } + if ((spec = ncp_find_conn_spec2(server, user, password, 1, mdata.uid, allow_multiple_connections, &err)) + == NULL) + { com_err(progname, err, "in find_conn_spec"); exit(1); } - if (upcase_password != 0) { + if (upcase_password != 0) + { str_upper(spec->password); } - if (optind != argc - 1) { + if (optind != argc - 1) + { usage(); return -1; } realpath(argv[optind], mount_point); - if (stat(mount_point, &st) == -1) { + if (stat(mount_point, &st) == -1) + { fprintf(stderr, "could not find mount point %s: %s\n", mount_point, strerror(errno)); exit(1); } - if (mount_ok(&st) != 0) { + if (mount_ok(&st) != 0) + { fprintf(stderr, "cannot to mount on %s: %s\n", mount_point, strerror(errno)); exit(1); } -#if NCP_MOUNT_VERSION < 3 -#error "Use Linux 2.1.29 with patch applied !!!" + +#ifdef MOUNT2 + if (mount_protocol_version < 3) { + /* Check if the ncpfs filesystem is in the kernel. If not, attempt + * to load the ncpfs module */ + if (load_ncpfs() != 0) + { + fprintf(stderr, "Error: Unable to load ncpfs, exiting...\n"); + exit(1); + } + } #endif - data.version = NCP_MOUNT_VERSION; - data.mounted_uid = conn_uid; + mdata.server_name = spec->server; - if (data.dir_mode == 0) { - data.dir_mode = data.file_mode; - if ((data.dir_mode & S_IRUSR) != 0) - data.dir_mode |= S_IXUSR; - if ((data.dir_mode & S_IRGRP) != 0) - data.dir_mode |= S_IXGRP; - if ((data.dir_mode & S_IROTH) != 0) - data.dir_mode |= S_IXOTH; + if (mdata.dir_mode == 0) + { + mdata.dir_mode = mdata.file_mode; + if ((mdata.dir_mode & S_IRUSR) != 0) + mdata.dir_mode |= S_IXUSR; + if ((mdata.dir_mode & S_IRGRP) != 0) + mdata.dir_mode |= S_IXGRP; + if ((mdata.dir_mode & S_IROTH) != 0) + mdata.dir_mode |= S_IXOTH; } - if ((server_addr = ncp_find_fileserver(spec->server, &err)) == NULL) { - com_err("ncpmount", err, "when trying to find %s", - spec->server); - exit(1); - } - data.ncp_fd = socket(AF_IPX, SOCK_DGRAM, PF_IPX); - if (data.ncp_fd == -1) { - com_err("ncpmount", err, "opening ncp_socket"); - exit(1); - } - wdog_fd = socket(AF_IPX, SOCK_DGRAM, PF_IPX); - if (wdog_fd == -1) { - fprintf(stderr, "could not open wdog socket: %s\n", - strerror(errno)); - exit(1); - } - memzero(addr); - addr.sipx_type = NCP_PTYPE; +#ifdef CONFIG_NATIVE_IP + if (server_name) { + struct hostent* h; - if (bind(data.ncp_fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) { + h = gethostbyname(server_name); + if (!h) { + fprintf(stderr, "Get host address `%s': ", server_name); + herror(NULL); + return 1; + } + if (h->h_addrtype != AF_INET) { + fprintf(stderr, "Get host address `%s': Not AF_INET\n", server_name); + return 1; + } + if (h->h_length != 4) { + fprintf(stderr, "Get host address `%s': Bad address length\n", server_name); + return 1; + } + server_in.sin_family = h->h_addrtype; + memcpy(&server_in.sin_addr.s_addr, h->h_addr, 4); + server_in.sin_port = htons(0x020C); + memcpy(&mdata.serv_addr, &server_in, sizeof(server_in)); + } else +#endif /* CONFIG_NATIVE_IP */ + { + if ((!allow_multiple_connections)&& + ((tmp_mount = ncp_find_permanent(spec)) != NULL)) + { + fprintf(stderr, + "You already have mounted server %s\nas user " + "%s\non mount point %s\n", spec->server, spec->user, + tmp_mount); + exit(1); + } + if ((err = ncp_find_fileserver(spec->server, (struct sockaddr*)&mdata.serv_addr, sizeof(mdata.serv_addr))) != 0) + { + com_err("ncpmount", err, "when trying to find %s", + spec->server); + exit(1); + } + } + +#ifdef CONFIG_NATIVE_IP + if (mdata.serv_addr.sipx_family == AF_INET) { + mdata.ncp_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (mdata.ncp_fd == -1) { + com_err("ncpmount", err, "opening ncp_socket"); + exit(1); + } + mdata.wdog_fd = -1; + mdata.message_fd = -1; + memzero(addr); + addr.sipx_family = AF_INET; + } else +#endif + { + mdata.ncp_fd = socket(AF_IPX, SOCK_DGRAM, PF_IPX); + if (mdata.ncp_fd == -1) + { + com_err("ncpmount", err, "opening ncp_socket"); + exit(1); + } + mdata.wdog_fd = socket(AF_IPX, SOCK_DGRAM, PF_IPX); + if (mdata.wdog_fd == -1) + { + fprintf(stderr, "could not open wdog socket: %s\n", + strerror(errno)); + exit(1); + } + memzero(addr); + addr.sipx_family = AF_IPX; + addr.sipx_type = NCP_PTYPE; + } + if (bind(mdata.ncp_fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) + { fprintf(stderr, "\nbind: %s\n", strerror(errno)); fprintf(stderr, "\nMaybe you want to use \n" - "ipx_configure --auto_interface=on --auto_primary=on\n" + "ipx_configure --auto_interface=on --auto_primary=on\n" "and try again after waiting a minute.\n\n"); exit(1); } - addrlen = sizeof(addr); - if (getsockname(data.ncp_fd, - (struct sockaddr *) &addr, &addrlen) == -1) { - perror("getsockname ncp socket"); - close(data.ncp_fd); - close(wdog_fd); - exit(1); - } - addr.sipx_port = htons(ntohs(addr.sipx_port) + 1); + if (mdata.serv_addr.sipx_family == AF_IPX) { + addrlen = sizeof(addr); - if (bind(wdog_fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) { - fprintf(stderr, "bind(wdog_sock, ): %s\n", - strerror(errno)); - exit(1); - } - msg_fd = socket(AF_IPX, SOCK_DGRAM, PF_IPX); - if (msg_fd == -1) { - fprintf(stderr, "could not open message socket: %s\n", - strerror(errno)); - exit(1); - } - addr.sipx_port = htons(ntohs(addr.sipx_port) + 1); + if (getsockname(mdata.ncp_fd, (struct sockaddr *) &addr, &addrlen) == -1) + { + perror("getsockname ncp socket"); + close(mdata.ncp_fd); + close(mdata.wdog_fd); + exit(1); + } + addr.sipx_port = htons(ntohs(addr.sipx_port) + 1); + + if (bind(mdata.wdog_fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) + { + fprintf(stderr, "bind(wdog_sock, ): %s\n", + strerror(errno)); + exit(1); + } +#if 1 - if (bind(msg_fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) { - fprintf(stderr, "bind(message_sock, ): %s\n", - strerror(errno)); - exit(1); + mdata.message_fd = socket(AF_IPX, SOCK_DGRAM, PF_IPX); + if (mdata.message_fd == -1) + { + fprintf(stderr, "could not open message socket: %s\n", + strerror(errno)); + exit(1); + } + addr.sipx_port = htons(ntohs(addr.sipx_port) + 1); + + if (bind(mdata.message_fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) + { + fprintf(stderr, "bind(message_sock, ): %s\n", + strerror(errno)); + exit(1); + } +#endif } - connect(data.ncp_fd, - (struct sockaddr *) server_addr, sizeof(*server_addr)); + mdata.mount_point = mount_point; flags = MS_MGC_VAL; @@ -363,33 +841,86 @@ int main(int argc, char *argv[]) strcat(mount_name, "/"); strcat(mount_name, spec->user); - data.wdog_pid = fork(); - if (data.wdog_pid < 0) { - fprintf(stderr, "could not fork: %s\n", strerror(errno)); + switch (mount_protocol_version) { +#ifdef MOUNT2 + case 2: + result = ncp_mount_v2(mount_name, flags, &mdata); + break; +#endif +#ifdef MOUNT3 + case 3: + result = ncp_mount_v3(mount_name, flags, &mdata, argc, argv); + break; +#endif + default: + fprintf(stderr, "Unsupported mount protocol version %d\n", mount_protocol_version); + exit(2); + } + if (result < 0) + { + com_err("ncpmount", errno, "in mount(2)"); exit(1); } - if (data.wdog_pid == 0) { - /* Child */ - inststr(argv, argc, "ncpd"); - process_connection(wdog_fd, msg_fd); - } - result = mount(mount_name, mount_point, "ncpfs", flags, (char *) &data); - - if (result < 0) { - printf("mount failed\n"); - exit(1); - } - if ((conn = ncp_open_mount(mount_point, &err)) == NULL) { + if ((err = ncp_open_mount(mount_point, &conn)) != 0) + { com_err("ncpmount", err, "attempt to open mount point"); umount(mount_point); exit(1); } - if ((err = ncp_login_user(conn, spec->user, spec->password)) != 0) { +#ifdef SIGNATURES + if (sig_level >= 0) { + int err = 0; + + err = ncp_renegotiate_connparam(conn, conn->i.buffer_size, (sig_level > 1)? 2:0); +#if 0 + if (conn->sign_wanted) { + if (sig_level < 2) { + err = ncp_renegotiate_connparam(conn, conn->i.buffer_size, 0); + } + } else { + if (sig_level >= 2) { + err = ncp_renegotiate_connparam(conn, conn->i.buffer_size, 2); + } + } +#endif + if (err || ((sig_level == 0) && (conn->sign_wanted)) + || ((sig_level == 3) && (!conn->sign_wanted))) { + fprintf(stderr, "Unable to negotiate requested security level\n"); + umount(mount_point); + exit(1); + } + } +#endif +#ifdef NDS_SUPPORT + if ((!force_bindery_login) && (!nds_get_tree_name(conn, NULL, 0))) + { + if ((err = nds_login_auth(conn, spec->user, spec->password))) + { + if ((err != NCPL_ET_REQUEST_ERROR) || + (conn->completion != NDS_GRACE_PERIOD)) { + com_err("ncpmount", err, "in nds login"); + if (err == NCPL_ET_REQUEST_ERROR) + fprintf(stderr, "NDS error code %d.\n", + conn->completion); + fprintf(stderr, "Login denied.\n"); + ncp_close(conn); + umount(mount_point); + exit(1); + } + fprintf(stderr, "Your password has expired\n"); + } + } + else + { +#endif + if ((err = ncp_login_user(conn, spec->user, spec->password)) != 0) + { struct nw_property p; struct ncp_prop_login_control *l = (struct ncp_prop_login_control *) &p; - if (conn->completion != NCP_GRACE_PERIOD) { + if (conn->completion != NCP_GRACE_PERIOD) + { com_err("ncpmount", err, "in login"); fprintf(stderr, "Login denied\n"); ncp_close(conn); @@ -400,13 +931,18 @@ int main(int argc, char *argv[]) if ((err = ncp_read_property_value(conn, NCP_BINDERY_USER, spec->user, 1, - "LOGIN_CONTROL", &p)) == 0) { + "LOGIN_CONTROL", &p)) == 0) + { fprintf(stderr, "You have %d login attempts left\n", l->GraceLogins); } } - if ((err = ioctl(conn->mount_fid, NCP_IOC_CONN_LOGGED_IN, NULL)) != 0) { - com_err("ncpmount", err, "in logged_indication"); +#ifdef NDS_SUPPORT + } +#endif + if ((err = ncp_mount_specific(conn, NW_NS_DOS, NWpath, pathlen)) != 0) + { + fprintf(stderr, "Cannot access path \"%s\": %s\n", remotepath, strerror(-err)); ncp_close(conn); umount(mount_point); exit(1); @@ -420,27 +956,32 @@ int main(int argc, char *argv[]) ment.mnt_freq = 0; ment.mnt_passno = 0; - if ((fd = open(MOUNTED "~", O_RDWR | O_CREAT | O_EXCL, 0600)) == -1) { + if ((fd = open(MOUNTED "~", O_RDWR | O_CREAT | O_EXCL, 0600)) == -1) + { fprintf(stderr, "Can't get " MOUNTED "~ lock file"); exit(1); } close(fd); - if ((mtab = setmntent(MOUNTED, "a+")) == NULL) { + if ((mtab = setmntent(MOUNTED, "a+")) == NULL) + { fprintf(stderr, "Can't open " MOUNTED); exit(1); } - if (addmntent(mtab, &ment) == 1) { + if (addmntent(mtab, &ment) == 1) + { fprintf(stderr, "Can't write mount entry"); exit(1); } - if (fchmod(fileno(mtab), 0644) == -1) { + if (fchmod(fileno(mtab), 0644) == -1) + { fprintf(stderr, "Can't set perms on " MOUNTED); exit(1); } endmntent(mtab); - if (unlink(MOUNTED "~") == -1) { + if (unlink(MOUNTED "~") == -1) + { fprintf(stderr, "Can't remove " MOUNTED "~"); exit(1); } @@ -453,7 +994,8 @@ static void usage(void) printf("Try `%s -h' for more information\n", progname); } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options] mount-point\n", progname); @@ -463,9 +1005,9 @@ static void help(void) "-V volume Volume to mount, for NFS re-export\n" "-u uid uid the mounted files get\n" "-g gid gid the mounted files get\n" - "-f mode permission the files get (octal notation)\n" + "-f mode permission the files get (octal notation)\n" "-d mode permission the dirs get (octal notation)\n" - "-c uid uid to identify the connection to mount on\n" + "-c uid uid to identify the connection to mount on\n" " Only makes sense for root\n" "-t time_out Waiting time (in 1/100s) to wait for\n" " an answer from the server. Default: 60\n" @@ -475,18 +1017,30 @@ static void help(void) "-n Do not use any password\n" " If neither -P nor -n are given, you are\n" " asked for a password.\n" + "-s Enable renaming/deletion of read-only files\n" "-h print this help text\n" "-v print ncpfs version number\n" +#ifdef NDS_SUPPORT + "-b Force bindery login to NDS servers\n" +#endif +#ifdef SIGNATURES + "-i level Signature level, 0=never, 1=supported, 2=preferred, 3=required\n" +#endif + "-m Allow multiple logins to server\n" + "-N os2,nfs Do not use specified namespaces on mounted volume\n" "\n"); } +#ifdef MOUNT3 + /* The following routines have been taken from util-linux-2.5's write.c */ /* * term_chk - check that a terminal exists, and get the message bit * and the access time */ -static int term_chk(char *tty, int *msgsokP, time_t * atimeP, int *showerror) +static int +term_chk (char *tty, int *msgsokP, time_t * atimeP, int *showerror) { struct stat s; char path[MAXPATHLEN]; @@ -514,51 +1068,57 @@ static int term_chk(char *tty, int *msgsokP, time_t * atimeP, int *showerror) * Special case for writing to yourself - ignore the terminal you're * writing from, unless that's the only terminal with messages enabled. */ -static int search_utmp(char *user, char *tty) +static int +search_utmp (char *user, char *tty) { struct utmp u; time_t bestatime, atime; int ufd, nloggedttys, nttys, msgsok, user_is_me; - char atty[sizeof(u.ut_line) + 1]; + char atty[sizeof (u.ut_line) + 1]; - if ((ufd = open(_PATH_UTMP, O_RDONLY)) < 0) { - perror("utmp"); + if ((ufd = open (_PATH_UTMP, O_RDONLY)) < 0) + { + perror ("utmp"); return -1; } nloggedttys = nttys = 0; bestatime = 0; user_is_me = 0; - while (read(ufd, (char *) &u, sizeof(u)) == sizeof(u)) - if (strncmp(user, u.ut_name, sizeof(u.ut_name)) == 0) { + while (read (ufd, (char *) &u, sizeof (u)) == sizeof (u)) + if (strncmp (user, u.ut_name, sizeof (u.ut_name)) == 0) + { ++nloggedttys; - (void) strncpy(atty, u.ut_line, sizeof(u.ut_line)); - atty[sizeof(u.ut_line)] = '\0'; + (void) strncpy (atty, u.ut_line, sizeof (u.ut_line)); + atty[sizeof (u.ut_line)] = '\0'; - if (term_chk(atty, &msgsok, &atime, 0)) - continue; /* bad term? skip */ + if (term_chk (atty, &msgsok, &atime, 0)) + continue; /* bad term? skip */ if (!msgsok) - continue; /* skip ttys with msgs off */ + continue; /* skip ttys with msgs off */ if (u.ut_type != USER_PROCESS) - continue; /* it's not a valid entry */ + continue; /* it's not a valid entry */ ++nttys; - if (atime > bestatime) { + if (atime > bestatime) + { bestatime = atime; - (void) strcpy(tty, atty); + (void) strcpy (tty, atty); } - } - (void) close(ufd); - if (nloggedttys == 0) { - (void) fprintf(stderr, "write: %s is not logged in\n", user); - return -1; - } - return 0; + } + (void) close (ufd); + if (nloggedttys == 0) + { + (void) fprintf (stderr, "write: %s is not logged in\n", user); + return -1; + } + return 0; } -static void msg_received(void) +static void +msg_received (void) { struct ncp_conn *conn; char message[256]; @@ -571,9 +1131,9 @@ static void msg_received(void) struct mntent *mnt; long err; - openlog("nwmsg", LOG_PID, LOG_LPR); + openlog ("nwmsg", LOG_PID, LOG_LPR); - if ((conn = ncp_open_mount(mount_point, &err)) == NULL) { + if ((err = ncp_open_mount(mount_point, &conn)) != 0) { return; } if (ncp_get_broadcast_message(conn, message) != 0) { @@ -630,27 +1190,46 @@ static void msg_received(void) return; } -static void process_msg_packet(int msg_fd) +/* MSG_DONTWAIT defined and module can run only on 2.1.x kernel */ +#if defined(MSG_DONTWAIT) && !defined(MOUNT2) +#define recvfrom_notm(fd,buf,ln,sender,addrlen) recvfrom(fd,buf,ln,MSG_DONTWAIT,sender,addrlen) +#else +int recvfrom_notm(int fd, void* buf, size_t len, struct sockaddr* sender, size_t* addrlen) { + int ret; + int flg; + + flg = fcntl(fd, F_GETFL); + if (flg == -1) return -1; + fcntl(fd, F_SETFL, flg | O_NONBLOCK); + ret = recvfrom(fd, buf, len, 0, sender, addrlen); + fcntl(fd, F_SETFL, flg); + return ret; +} +#endif + +static void +process_msg_packet (int msg_fd) { struct sockaddr_ipx sender; int addrlen = sizeof(sender); char buf[1024]; - if (recvfrom(msg_fd, buf, sizeof(buf), MSG_DONTWAIT, + if (recvfrom_notm(msg_fd, buf, sizeof(buf), (struct sockaddr *) &sender, &addrlen) <= 0) { return; } msg_received(); } -static void process_wdog_packet(int wdog_fd) +static void +process_wdog_packet (int wdog_fd) { struct sockaddr_ipx sender; int addrlen = sizeof(sender); char buf[2]; - if (recvfrom(wdog_fd, buf, sizeof(buf), MSG_DONTWAIT, - (struct sockaddr *) &sender, &addrlen) < sizeof(buf)) { + if (recvfrom_notm(wdog_fd, buf, sizeof(buf), + (struct sockaddr *) &sender, &addrlen) < (int)sizeof(buf)) { return; } if (buf[1] != '?') { @@ -660,14 +1239,48 @@ static void process_wdog_packet(int wdog_fd) sendto(wdog_fd, buf, 2, 0, (struct sockaddr *) &sender, addrlen); } -static int process_connection(int wdog_fd, int msg_fd) +static int +process_connection (const struct ncp_mount_data_independent* mnt) { int i; int result; int max; + int wdog_fd = mnt->wdog_fd; + int msg_fd = mnt->message_fd; chdir("/"); setsid(); + +#ifdef CONFIG_NATIVE_IP + if (wdog_fd == -1) { + unsigned char buf[]={0x3E, 0x3E, 0, 0, 0, 0, 0, 0, 0, 'Y'}; + struct ncp_fs_info fsinfo; + int fd, err; + int ncp_fd = mnt->ncp_fd; + + for (i = 0; i < NR_OPEN; i++) { + if (i == ncp_fd) continue; + close(i); + } + /* we sleep here because of mount(2) must have enough time to run */ + sleep(180); /* 3 min. */ + fd = open(mnt->mount_point, O_RDONLY); + if (fd < 0) return 1; /* Give up */ + fsinfo.version = NCP_GET_FS_INFO_VERSION; + err = ioctl(fd, NCP_IOC_GET_FS_INFO, &fsinfo); + close(fd); + if (err) return 1; /* Give up */ + buf[3] = buf[8] = fsinfo.connection&0xFF; + buf[5] = buf[7] = (fsinfo.connection>>8)&0xFF; + + while (1) { + send(ncp_fd, buf, sizeof(buf), 0); + sleep(180); /* 3 min. */ + } + return 0; + } +#endif + for (i = 0; i < NR_OPEN; i++) { if ((i == wdog_fd) || (i == msg_fd)) { continue; @@ -694,4 +1307,7 @@ static int process_connection(int wdog_fd, int msg_fd) process_msg_packet(msg_fd); } } + return 0; } + +#endif diff --git a/sutil/ncpmount.h b/sutil/ncpmount.h new file mode 100644 index 0000000..a12df9e --- /dev/null +++ b/sutil/ncpmount.h @@ -0,0 +1,76 @@ +/* + * ncp_mount.h + * + * Copyright (C) 1995, 1996 by Volker Lendecke + * + */ + +#ifndef __NCPMOUNT_H__ +#define __NCPMOUNT_H__ + +#include "ncp.h" + +#define NCP_MOUNT_VERSION_V2 2 + +/* Values for flags */ +#define NCP_MOUNT2_SOFT 0x0001 +#define NCP_MOUNT2_INTR 0x0002 +#define NCP_MOUNT2_STRONG 0x0004 +#define NCP_MOUNT2_NO_OS2 0x0008 +#define NCP_MOUNT2_NO_NFS 0x0010 + +#define PATH_MAX_V20 1024 /* PATH_MAX for 2.0 kernel */ + +struct ncp_mount_data_v2 { + int version; + unsigned int ncp_fd; /* The socket to the ncp port */ + unsigned int wdog_fd; /* Watchdog packets come here */ + unsigned int message_fd; /* Message notifications come here */ + __ker20_uid_t mounted_uid; /* Who may umount() this filesystem? */ + + struct sockaddr_ipx serv_addr; + unsigned char server_name[NCP_BINDERY_NAME_LEN]; + + unsigned char mount_point[PATH_MAX_V20+1]; + unsigned char mounted_vol[NCP_VOLNAME_LEN+1]; + + unsigned int time_out; /* How long should I wait after + sending a NCP request? */ + unsigned int retry_count; /* And how often should I retry? */ + unsigned int flags; + + __ker20_uid_t uid; + __ker20_gid_t gid; + __ker20_mode_t file_mode; + __ker20_mode_t dir_mode; +}; + +#define NCP_MOUNT_VERSION_V3 3 + +/* Values for flags */ +#define NCP_MOUNT3_SOFT 0x0001 +#define NCP_MOUNT3_INTR 0x0002 +#define NCP_MOUNT3_STRONG 0x0004 +#define NCP_MOUNT3_NO_OS2 0x0008 +#define NCP_MOUNT3_NO_NFS 0x0010 + +struct ncp_mount_data_v3 { + int version; + unsigned int ncp_fd; /* The socket to the ncp port */ + __ker21_uid_t mounted_uid; /* Who may umount() this filesystem? */ + __ker21_pid_t wdog_pid; /* Who cares for our watchdog packets? */ + + unsigned char mounted_vol[NCP_VOLNAME_LEN + 1]; + unsigned int time_out; /* How long should I wait after + sending a NCP request? */ + unsigned int retry_count; /* And how often should I retry? */ + unsigned int flags; + + __ker21_uid_t uid; + __ker21_gid_t gid; + __ker21_mode_t file_mode; + __ker21_mode_t dir_mode; +}; + +#endif /* __NCPMOUNT_H__ */ + diff --git a/sutil/ncpumount.c b/sutil/ncpumount.c index ba5bfb2..1d59847 100644 --- a/sutil/ncpumount.c +++ b/sutil/ncpumount.c @@ -16,7 +16,7 @@ #include #include #include - /* #include *//* generates a warning here */ +/* #include */ /* generates a warning here */ extern pid_t waitpid(pid_t, int *, int); #include #include @@ -27,36 +27,37 @@ extern pid_t waitpid(pid_t, int *, int); #include #include -#include -#include -#include -#include -#include +#include "ncplib.h" static char *progname; -static void usage(void) +static void +usage(void) { printf("usage: %s mount-point\n", progname); } -static int umount_ok(const char *mount_point) +static int +umount_ok(const char *mount_point) { int fid = open(mount_point, O_RDONLY, 0); uid_t mount_uid; - if (fid == -1) { + if (fid == -1) + { fprintf(stderr, "Could not open %s: %s\n", mount_point, strerror(errno)); return -1; } - if (ioctl(fid, NCP_IOC_GETMOUNTUID, &mount_uid) != 0) { + if (ncp_get_mount_uid(fid, &mount_uid) != 0) + { fprintf(stderr, "%s probably not ncp-filesystem\n", mount_point); return -1; } if ((getuid() != 0) - && (mount_uid != getuid())) { + && (mount_uid != getuid())) + { fprintf(stderr, "You are not allowed to umount %s\n", mount_point); return -1; @@ -71,7 +72,7 @@ static int umount_ok(const char *mount_point) is not a legal pathname for ``/dev/fd0.'' Anything we cannot parse we return unmodified. */ char * - canonicalize(const char *path) +canonicalize(const char *path) { char *canonical = malloc(PATH_MAX + 1); @@ -81,7 +82,8 @@ char * if (realpath(path, canonical)) return canonical; - if (strlen(path) > PATH_MAX) { + if (strlen(path) > PATH_MAX) + { return NULL; } strcpy(canonical, path); @@ -89,7 +91,8 @@ char * } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { int fd; @@ -101,70 +104,83 @@ int main(int argc, char *argv[]) progname = argv[0]; - if (geteuid() != 0) { + if (geteuid() != 0) + { fprintf(stderr, "%s must be installed suid root\n", progname); exit(1); } - if (argc != 2) { + if (argc != 2) + { usage(); exit(1); } mount_point = canonicalize(argv[1]); - if (mount_point == NULL) { + if (mount_point == NULL) + { fprintf(stderr, "Invalid mount point: %s\n", argv[1]); exit(1); } - if (umount_ok(mount_point) != 0) { + if (umount_ok(mount_point) != 0) + { fprintf(stderr, "You are not allowed to umount %s\n", mount_point); exit(1); } - if (umount(mount_point) != 0) { + if (umount(mount_point) != 0) + { fprintf(stderr, "Could not umount %s: %s\n", mount_point, strerror(errno)); exit(1); } - if ((fd = open(MOUNTED "~", O_RDWR | O_CREAT | O_EXCL, 0600)) == -1) { + if ((fd = open(MOUNTED "~", O_RDWR | O_CREAT | O_EXCL, 0600)) == -1) + { fprintf(stderr, "Can't get " MOUNTED "~ lock file"); return 1; } close(fd); - if ((mtab = setmntent(MOUNTED, "r")) == NULL) { + if ((mtab = setmntent(MOUNTED, "r")) == NULL) + { fprintf(stderr, "Can't open " MOUNTED ": %s\n", strerror(errno)); return 1; } #define MOUNTED_TMP MOUNTED".tmp" - if ((new_mtab = setmntent(MOUNTED_TMP, "w")) == NULL) { + if ((new_mtab = setmntent(MOUNTED_TMP, "w")) == NULL) + { fprintf(stderr, "Can't open " MOUNTED_TMP ": %s\n", strerror(errno)); endmntent(mtab); return 1; } - while ((mnt = getmntent(mtab)) != NULL) { - if (strcmp(mnt->mnt_dir, mount_point) != 0) { + while ((mnt = getmntent(mtab)) != NULL) + { + if (strcmp(mnt->mnt_dir, mount_point) != 0) + { addmntent(new_mtab, mnt); } } endmntent(mtab); - if (fchmod(fileno(new_mtab), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) { + if (fchmod(fileno(new_mtab), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) + { fprintf(stderr, "Error changing mode of %s: %s\n", MOUNTED_TMP, strerror(errno)); exit(1); } endmntent(new_mtab); - if (rename(MOUNTED_TMP, MOUNTED) < 0) { + if (rename(MOUNTED_TMP, MOUNTED) < 0) + { fprintf(stderr, "Cannot rename %s to %s: %s\n", MOUNTED, MOUNTED_TMP, strerror(errno)); exit(1); } - if (unlink(MOUNTED "~") == -1) { + if (unlink(MOUNTED "~") == -1) + { fprintf(stderr, "Can't remove " MOUNTED "~"); return 1; } diff --git a/sutil/nwcrypt.c b/sutil/nwcrypt.c deleted file mode 100644 index a0474e1..0000000 --- a/sutil/nwcrypt.c +++ /dev/null @@ -1,198 +0,0 @@ -/*$********************************************************* - $* - $* 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 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 about -the legal status of this piece of code: - - ---- -Date: Thu, 12 Oct 1995 13:44:18 +0100 -From: Volker 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 -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]; -} diff --git a/sutil/nwsfind.c b/sutil/nwsfind.c index 2766fd3..d2e4fdd 100644 --- a/sutil/nwsfind.c +++ b/sutil/nwsfind.c @@ -13,25 +13,30 @@ #include #include #include +#include static char *progname; -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [server]\n", progname); } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [server]\n", progname); printf("\n" "-t Server type, default: File server\n" + "-a server is in form ::\n" "-h Print this help text\n" "\n"); } -static void swallow_error(const char *name, long code, const char *format, va_list arg) +static void +swallow_error(const char *name, long code, const char *format, va_list arg) { printf("%s ", error_message(code)); vfprintf(stdout, format, arg); @@ -39,12 +44,15 @@ static void swallow_error(const char *name, long code, const char *format, va_li return; } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { - char *server = NULL; + const char *server = NULL; int object_type = NCP_BINDERY_FSERVER; - struct sockaddr_ipx *result; + struct sockaddr_ipx addr; + struct ncp_conn *conn; long err; + int is_address = 0; int opt; @@ -52,11 +60,16 @@ int main(int argc, char *argv[]) set_com_err_hook(swallow_error); - while ((opt = getopt(argc, argv, "t:")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "at:")) != EOF) + { + switch (opt) + { case 't': object_type = atoi(optarg); break; + case 'a': + is_address = 1; + break; case 'h': case '?': help(); @@ -67,24 +80,47 @@ int main(int argc, char *argv[]) } } - if (optind < argc - 1) { + if (optind < argc - 1) + { usage(); exit(1); } - if (optind == argc - 1) { - server = argv[optind]; - if (strlen(server) >= NCP_BINDERY_NAME_LEN) { - com_err(argv[0], ENAMETOOLONG, "server name too long"); + if (is_address) + { + if ((optind > argc - 1) || + ipx_sscanf_saddr(argv[optind], &addr)) + { + usage(); exit(1); } + if ((!(conn = ncp_open_addr((struct sockaddr*)&addr, &err))) || + (err = ncp_close(conn))) {; + } + else + { + server = argv[optind]; + } + } + else + { + if (optind == argc - 1) + { + server = argv[optind]; + if (strlen(server) >= NCP_BINDERY_NAME_LEN) + { + com_err(argv[0], ENAMETOOLONG, "server name too long"); + exit(1); + } + } + err = ncp_find_server(&server, object_type, (struct sockaddr*)&addr, sizeof(addr)); } - result = ncp_find_server(&server, object_type, &err); - if (result == NULL) { + if (err != 0) + { com_err(argv[0], err, "when trying to find server"); exit(1); } - ipx_print_saddr(result); + ipx_print_saddr(&addr); printf(" %s\n", server); return 0; } diff --git a/util/Makefile b/util/Makefile index 98dfd1e..09b6b50 100644 --- a/util/Makefile +++ b/util/Makefile @@ -2,21 +2,30 @@ # Makefile for the linux ncp-filesystem routines. # -USERUTILS = slist pqlist nwfsinfo pserver nprint nsend ncopy nwpasswd -USERUTILS += nwbols nwbocreate nwborm nwboprops -USERUTILS += nwbpcreate nwbprm nwbpvalues nwbpadd nwbpset -USERUTILS += nwgrant nwrevoke nwuserlist nwrights nwauth -USERUTILS += nwfstime nwvolinfo nwtrustee +include ../Makeinit + +O_USERUTILS = slist.o pqlist.o nwfsinfo.o pserver.o nprint.o nsend.o \ + ncopy.o nwpasswd.o nwbols.o nwbocreate.o nwborm.o nwboprops.o \ + pqstat.o pqrm.o nwbpcreate.o nwbprm.o nwbpvalues.o nwbpadd.o \ + nwbpset.o nwgrant.o nwrevoke.o nwuserlist.o nwrights.o nwauth.o \ + nwfstime.o nwvolinfo.o nwtrustee.o nwpurge.o +ifdef MOUNT2 +O_SBINUTILS = nwmsg.o +endif + +USERUTILS = $(O_USERUTILS:%.o=%) +SBINUTILS = $(O_SBINUTILS:%.o=%) UTILS = $(USERUTILS) $(SBINUTILS) ncptest -CC = gcc - ifeq ($(HAVE_ELF),yes) -NCP_LIB = libncp.so.1.0 +NCP_LIB = libncp.so +NCPLIB_DIR = ../lib-shared +LIBDEP = $(NCPLIB_DIR)/$(NCP_LIB) else NCP_LIB = libncp.a -LIBDEP = ../lib/libncp.a +NCPLIB_DIR = ../lib-static +LIBDEP = $(NCPLIB_DIR)/$(NCP_LIB) endif default: @@ -30,11 +39,20 @@ install: all for i in $(SBINUTILS); \ do install $$i -m 755 $(SBINDIR); done +../lib-static/libncp.a: + make -C ../lib-static libncp.a + +../lib-shared/libncp.so: + make -C ../lib-shared libncp.so + +$(O_USERUTILS) $(O_SBINUTILS) ncptest.o: %.o: %.c + $(CC) $(CFLAGS) $(CCFLAGS) -o $@ -c $< + $(UTILS): %: %.o $(LIBDEP) - $(CC) -o $@ $(addsuffix .o,$@) -L../lib -lncp + $(CC) $(CFLAGS) -o $@ $(addsuffix .o,$@) -L$(NCPLIB_DIR) -lncp ipx_probe: ipx_probe.c - $(CC) $(CFLAGS) -o ipx_probe ipx_probe.c + $(CC) $(CFLAGS) $(CCFLAGS) -o ipx_probe ipx_probe.c dep: $(CPP) -M $(INCLUDES) *.c > .depend diff --git a/util/ipx_probe b/util/ipx_probe deleted file mode 100755 index 4869a8f8be7bbe816cbd9805a0064f0d3daa978e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27138 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 diff --git a/util/ipx_probe.c b/util/ipx_probe.c index 48ae8ac..de2a435 100644 --- a/util/ipx_probe.c +++ b/util/ipx_probe.c @@ -22,23 +22,25 @@ static char *progname; int verbose = 0; -static void usage() +static void +usage () { - fprintf(stderr, "usage: %s [options]\n", progname); - fprintf(stderr, "type '%s -h' for help\n", progname); + fprintf (stderr, "usage: %s [options]\n", progname); + fprintf (stderr, "type '%s -h' for help\n", progname); } -static void help() +static void +help () { - printf("\n" - "Probe an interface for ipx networks\n" - "\n"); - printf("usage: %s [options]\n", progname); - printf("\n" - "-v Verbose output\n" - "-i interface Interface to probe, default: eth0\n" - "-t timeout Seconds to wait for answer, default: 3\n" - "-h Print this help text\n\n"); + printf ("\n" + "Probe an interface for ipx networks\n" + "\n"); + printf ("usage: %s [options]\n", progname); + printf ("\n" + "-v Verbose output\n" + "-i interface Interface to probe, default: eth0\n" + "-t timeout Seconds to wait for answer, default: 3\n" + "-h Print this help text\n\n"); } #define IPX_SAP_PTYPE (0x04) @@ -48,360 +50,407 @@ static void help() #define BVAL(buf,pos) (((__u8 *)(buf))[pos]) #define BSET(buf,pos,val) (BVAL(buf,pos) = (val)) -static inline void WSET_HL(__u8 * buf, int pos, __u16 val) +static inline void +WSET_HL (__u8 * buf, int pos, __u16 val) { - BSET(buf, pos, val >> 8); - BSET(buf, pos + 1, val & 0xff); + BSET (buf, pos, val >> 8); + BSET (buf, pos + 1, val & 0xff); } -struct frame_type { - char *ft_name; - unsigned char ft_val; +struct frame_type +{ + char *ft_name; + unsigned char ft_val; }; static struct frame_type frame_types[] = { - { - "802.2", IPX_FRAME_8022 - } - , + { + "802.2", IPX_FRAME_8022 + } + , #ifdef IPX_FRAME_TR_8022 - { - "802.2TR", IPX_FRAME_TR_8022 - } - , + { + "802.2TR", IPX_FRAME_TR_8022 + } + , #endif - { - "802.3", IPX_FRAME_8023 - } - , - { - "SNAP", IPX_FRAME_SNAP - } - , - { - "EtherII", IPX_FRAME_ETHERII - } + { + "802.3", IPX_FRAME_8023 + } + , + { + "SNAP", IPX_FRAME_SNAP + } + , + { + "EtherII", IPX_FRAME_ETHERII + } }; #define NFTYPES (sizeof(frame_types)/sizeof(struct frame_type)) static char * - frame_name(int frame_type) +frame_name (int frame_type) { - int i; - for (i = 0; i < NFTYPES; i++) { - if (frame_types[i].ft_val == frame_type) { - return frame_types[i].ft_name; - } + int i; + for (i = 0; i < NFTYPES; i++) + { + if (frame_types[i].ft_val == frame_type) + { + return frame_types[i].ft_name; } - return NULL; + } + return NULL; } -static int ipx_recvfrom(int sock, void *buf, int len, unsigned int flags, - struct sockaddr_ipx *sender, int *addrlen, int timeout, - long *err) +static int +ipx_recvfrom (int sock, void *buf, int len, unsigned int flags, + struct sockaddr_ipx *sender, int *addrlen, int timeout, + long *err) { - fd_set rd, wr, ex; - struct timeval tv; - int result; + fd_set rd, wr, ex; + struct timeval tv; + int result; - FD_ZERO(&rd); - FD_ZERO(&wr); - FD_ZERO(&ex); - FD_SET(sock, &rd); + FD_ZERO (&rd); + FD_ZERO (&wr); + FD_ZERO (&ex); + FD_SET (sock, &rd); - tv.tv_sec = timeout; - tv.tv_usec = 0; + tv.tv_sec = timeout; + tv.tv_usec = 0; - if ((result = select(sock + 1, &rd, &wr, &ex, &tv)) == -1) { - *err = errno; - return -1; - } - if (FD_ISSET(sock, &rd)) { - result = recvfrom(sock, buf, len, flags, - (struct sockaddr *) sender, addrlen); - } else { - result = -1; - errno = ETIMEDOUT; - } - if (result < 0) { - *err = errno; - } - return result; + if ((result = select (sock + 1, &rd, &wr, &ex, &tv)) == -1) + { + *err = errno; + return -1; + } + if (FD_ISSET (sock, &rd)) + { + result = recvfrom (sock, buf, len, flags, + (struct sockaddr *) sender, addrlen); + } + else + { + result = -1; + errno = ETIMEDOUT; + } + if (result < 0) + { + *err = errno; + } + return result; } -static int ipx_recv(int sock, void *buf, int len, unsigned int flags, int timeout, - long *err) +static int +ipx_recv (int sock, void *buf, int len, unsigned int flags, int timeout, + long *err) { - struct sockaddr_ipx sender; - int addrlen = sizeof(sender); + struct sockaddr_ipx sender; + int addrlen = sizeof (sender); - return ipx_recvfrom(sock, buf, len, flags, &sender, &addrlen, - timeout, err); + return ipx_recvfrom (sock, buf, len, flags, &sender, &addrlen, + timeout, err); } -static int probe_frame(char *interface, int frame_type, int timeout, unsigned long *net) +static int +probe_frame (char *interface, int frame_type, int timeout, unsigned long *net) { - int i, sock, opt; - int result; - long err; - char errmsg[strlen(progname) + 20]; - char data[1024]; + int i, sock, opt; + int result; + long err; + char errmsg[strlen (progname) + 20]; + char data[1024]; - static struct ifreq id; - struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &id.ifr_addr; + static struct ifreq id; + struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &id.ifr_addr; - if (verbose != 0) { - printf("probing %s on %s -- ", frame_name(frame_type), - interface); - fflush(stdout); + if (verbose != 0) + { + printf ("probing %s on %s -- ", frame_name (frame_type), + interface); + fflush (stdout); + } + sock = socket (AF_IPX, SOCK_DGRAM, AF_IPX); + if (sock < 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"); } - sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX); - if (sock < 0) { - int old_errno = errno; + close (sock); + return -1; + } + memset (&id, 0, sizeof (id)); + strncpy (id.ifr_name, interface, sizeof (id.ifr_name) - 1); + sipx->sipx_family = AF_IPX; + sipx->sipx_action = IPX_CRTITF; + sipx->sipx_special = IPX_PRIMARY; + sipx->sipx_network = 0L; + sipx->sipx_type = frame_type; - sprintf(errmsg, "%s: socket", progname); - perror(errmsg); - if (old_errno == -EINVAL) { - fprintf(stderr, "Probably you have no IPX support in " - "your kernel\n"); - } - close(sock); - return -1; - } - memset(&id, 0, sizeof(id)); - strncpy(id.ifr_name, interface, sizeof(id.ifr_name) - 1); - sipx->sipx_family = AF_IPX; - sipx->sipx_action = IPX_CRTITF; - sipx->sipx_special = IPX_PRIMARY; - sipx->sipx_network = 0L; - sipx->sipx_type = frame_type; + i = 0; + do + { + result = ioctl (sock, SIOCSIFADDR, &id); + i++; + } + while ((i < 5) && (result < 0) && (errno == EAGAIN)); - i = 0; - do { - result = ioctl(sock, SIOCSIFADDR, &id); - i++; - } - while ((i < 5) && (result < 0) && (errno == EAGAIN)); + if (result < 0) + { + int old_errno = errno; + close (sock); + errno = old_errno; + return result; + } + /* We do a GNS request on the new socket. If something comes + back, we assume that the frame type is valid. */ - if (result < 0) { - int old_errno = errno; - close(sock); - errno = old_errno; - return result; - } - /* We do a GNS request on the new socket. If something comes - back, we assume that the frame type is valid. */ + opt = 1; + if ((result = setsockopt (sock, SOL_SOCKET, + SO_BROADCAST, &opt, sizeof (opt))) < 0) + { + int old_errno = errno; + close (sock); + errno = old_errno; + return result; + } + memset (&id, 0, sizeof (id)); + sipx->sipx_family = AF_IPX; + sipx->sipx_network = htonl (0x0); + sipx->sipx_port = htons (0x0); + sipx->sipx_type = IPX_SAP_PTYPE; - opt = 1; - if ((result = setsockopt(sock, SOL_SOCKET, - SO_BROADCAST, &opt, sizeof(opt))) < 0) { - int old_errno = errno; - close(sock); - errno = old_errno; - return result; - } - memset(&id, 0, sizeof(id)); - sipx->sipx_family = AF_IPX; - sipx->sipx_network = htonl(0x0); - sipx->sipx_port = htons(0x0); - sipx->sipx_type = IPX_SAP_PTYPE; + if ((result = bind (sock, (struct sockaddr *) sipx, + sizeof (*sipx))) < 0 - 1) + { + int old_errno = errno; + close (sock); + errno = old_errno; + return result; + } + WSET_HL (data, 0, IPX_SAP_NEAREST_QUERY); + WSET_HL (data, 2, 4); - if ((result = bind(sock, (struct sockaddr *) sipx, - sizeof(*sipx))) < 0 - 1) { - int old_errno = errno; - close(sock); - errno = old_errno; - return result; - } - WSET_HL(data, 0, IPX_SAP_NEAREST_QUERY); - WSET_HL(data, 2, 4); + memset (&id, 0, sizeof (id)); + sipx->sipx_family = AF_IPX; + sipx->sipx_port = htons (IPX_SAP_PORT); + sipx->sipx_type = IPX_SAP_PTYPE; + sipx->sipx_network = htonl (0x0); + memcpy (sipx->sipx_node, IPX_BROADCAST_NODE, 6); - memset(&id, 0, sizeof(id)); - sipx->sipx_family = AF_IPX; - sipx->sipx_port = htons(IPX_SAP_PORT); - sipx->sipx_type = IPX_SAP_PTYPE; - sipx->sipx_network = htonl(0x0); - memcpy(sipx->sipx_node, IPX_BROADCAST_NODE, 6); + if ((result = sendto (sock, data, 4, 0, (struct sockaddr *) sipx, + sizeof (*sipx))) < 0) + { + int old_errno = errno; + close (sock); + errno = old_errno; + return result; + } + result = ipx_recv (sock, data, 1024, 0, timeout, &err); - if ((result = sendto(sock, data, 4, 0, (struct sockaddr *) sipx, - sizeof(*sipx))) < 0) { - int old_errno = errno; - close(sock); - errno = old_errno; - return result; - } - result = ipx_recv(sock, data, 1024, 0, timeout, &err); + if (result > 0) + { + struct sockaddr_ipx sipx; + int namelen = sizeof (sipx); - if (result > 0) { - struct sockaddr_ipx sipx; - int namelen = sizeof(sipx); + if (getsockname (sock, (struct sockaddr *) &sipx, + &namelen) < 0) + { + fprintf (stderr, "%s: Could not find socket address\n", + progname); + exit (1); + } + *net = ntohl (sipx.sipx_network); + } + memset (&id, 0, sizeof (id)); + strncpy (id.ifr_name, interface, sizeof (id.ifr_name) - 1); + sipx->sipx_family = AF_IPX; + sipx->sipx_action = IPX_DLTITF; + sipx->sipx_network = 0L; + sipx->sipx_type = frame_type; + result = ioctl (sock, SIOCSIFADDR, &id); + close (sock); - if (getsockname(sock, (struct sockaddr *) &sipx, - &namelen) < 0) { - fprintf(stderr, "%s: Could not find socket address\n", - progname); - exit(1); - } - *net = ntohl(sipx.sipx_network); + if (result < 0) + { + fprintf (stderr, "%s: could not delete interface\n", + progname); + exit (1); + } + if (err == ETIMEDOUT) + { + if (verbose != 0) + { + printf ("no network found\n"); } - memset(&id, 0, sizeof(id)); - strncpy(id.ifr_name, interface, sizeof(id.ifr_name) - 1); - sipx->sipx_family = AF_IPX; - sipx->sipx_action = IPX_DLTITF; - sipx->sipx_network = 0L; - sipx->sipx_type = frame_type; - result = ioctl(sock, SIOCSIFADDR, &id); - close(sock); - - if (result < 0) { - fprintf(stderr, "%s: could not delete interface\n", - progname); - exit(1); - } - if (err == ETIMEDOUT) { - if (verbose != 0) { - printf("no network found\n"); - } - return -1; - } - if (verbose != 0) { - printf("found IPX network %8.8lX\n", *net); - } - return 0; + return -1; + } + if (verbose != 0) + { + printf ("found IPX network %8.8lX\n", *net); + } + return 0; } -static int file_lines(char *name) +static int +file_lines (char *name) { - FILE *f = fopen(name, "r"); - char buf[100]; - int lines = 0; + FILE *f = fopen (name, "r"); + char buf[100]; + int lines = 0; - if (f == NULL) { - return -errno; - } - while (fgets(buf, sizeof(buf), f) != NULL) { - lines += 1; - } - fclose(f); - return lines; + if (f == NULL) + { + return -errno; + } + while (fgets (buf, sizeof (buf), f) != NULL) + { + lines += 1; + } + fclose (f); + return lines; } -static int ipx_interfaces(void) +static int +ipx_interfaces (void) { - int result = file_lines("/proc/net/ipx_interface"); - if (result == 0) { - result = -EIO; - } - return result - 1; + int result = file_lines ("/proc/net/ipx_interface"); + if (result == 0) + { + result = -EIO; + } + return result - 1; } -static int ipx_auto_off(void) +static int +ipx_auto_off (void) { - int s; - char errmsg[strlen(progname) + 20]; - int val = 0; + int s; + char errmsg[strlen (progname) + 20]; + int val = 0; - s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); - if (s < 0) { - int old_errno = errno; + 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"); - } - close(s); - return -1; + sprintf (errmsg, "%s: socket", progname); + perror (errmsg); + if (old_errno == -EINVAL) + { + fprintf (stderr, "Probably you have no IPX support in " + "your kernel\n"); } - sprintf(errmsg, "%s: ioctl", progname); + close (s); + return -1; + } + sprintf (errmsg, "%s: ioctl", progname); - if (ioctl(s, SIOCAIPXPRISLT, &val) < 0) { - perror(errmsg); - close(s); - return -1; - } - if (ioctl(s, SIOCAIPXITFCRT, &val) < 0) { - perror(errmsg); - close(s); - return -1; - } - close(s); - return 0; + if (ioctl (s, SIOCAIPXPRISLT, &val) < 0) + { + perror (errmsg); + close (s); + return -1; + } + if (ioctl (s, SIOCAIPXITFCRT, &val) < 0) + { + perror (errmsg); + close (s); + return -1; + } + close (s); + return 0; } -int main(int argc, char *argv[]) +int +main (int argc, char *argv[]) { - int interfaces; - char *interface = "eth0"; - int opt; - int timeout = 3; + int interfaces; + char *interface = "eth0"; + int opt; + int timeout = 3; - unsigned long network[5] = - {0,}; + unsigned long network[5] = + {0,}; - progname = argv[0]; + progname = argv[0]; - while ((opt = getopt(argc, argv, "vi:ht:")) != EOF) { - switch (opt) { - case 'v': - verbose = 1; - break; - case 'i': - interface = optarg; - break; - case 't': - timeout = atoi(optarg); - break; - case 'h': - help(); - exit(1); - default: - usage(); - exit(1); - } + while ((opt = getopt (argc, argv, "vi:ht:")) != EOF) + { + switch (opt) + { + case 'v': + verbose = 1; + break; + case 'i': + interface = optarg; + break; + case 't': + timeout = atoi (optarg); + break; + case 'h': + help (); + exit (1); + default: + usage (); + exit (1); } + } - if (ipx_auto_off() < 0) { - exit(1); - } - interfaces = ipx_interfaces(); - if (interfaces > 0) { - fprintf(stderr, "%s must be run with no interfaces configured." - " Found %d interface%s.\n", - progname, interfaces, - interfaces == 1 ? "" : "s"); - exit(1); - } - if (interfaces < 0) { - fprintf(stderr, "%s: %s\n", progname, strerror(interfaces)); - exit(1); - } - probe_frame(interface, IPX_FRAME_8022, timeout, &(network[0])); - probe_frame(interface, IPX_FRAME_8023, timeout, &(network[1])); - probe_frame(interface, IPX_FRAME_SNAP, timeout, &(network[2])); - probe_frame(interface, IPX_FRAME_ETHERII, timeout, &(network[3])); + if (ipx_auto_off () < 0) + { + exit (1); + } + interfaces = ipx_interfaces (); + if (interfaces > 0) + { + fprintf (stderr, "%s must be run with no interfaces configured." + " Found %d interface%s.\n", + progname, interfaces, + interfaces == 1 ? "" : "s"); + exit (1); + } + if (interfaces < 0) + { + fprintf (stderr, "%s: %s\n", progname, strerror (interfaces)); + exit (1); + } + probe_frame (interface, IPX_FRAME_8022, timeout, &(network[0])); + probe_frame (interface, IPX_FRAME_8023, timeout, &(network[1])); + probe_frame (interface, IPX_FRAME_SNAP, timeout, &(network[2])); + probe_frame (interface, IPX_FRAME_ETHERII, timeout, &(network[3])); - if (verbose == 0) { - if (network[0] != 0) { - printf("%s %8.8lX\n", - frame_name(IPX_FRAME_8022), network[0]); - } - if (network[1] != 0) { - printf("%s %8.8lX\n", - frame_name(IPX_FRAME_8023), network[1]); - } - if (network[2] != 0) { - printf("%s %8.8lX\n", - frame_name(IPX_FRAME_SNAP), network[2]); - } - if (network[3] != 0) { - printf("%s %8.8lX\n", - frame_name(IPX_FRAME_ETHERII), network[3]); - } + if (verbose == 0) + { + if (network[0] != 0) + { + printf ("%s %8.8lX\n", + frame_name (IPX_FRAME_8022), network[0]); } - return 0; + if (network[1] != 0) + { + printf ("%s %8.8lX\n", + frame_name (IPX_FRAME_8023), network[1]); + } + if (network[2] != 0) + { + printf ("%s %8.8lX\n", + frame_name (IPX_FRAME_SNAP), network[2]); + } + if (network[3] != 0) + { + printf ("%s %8.8lX\n", + frame_name (IPX_FRAME_ETHERII), network[3]); + } + } + return 0; } diff --git a/util/ncopy.c b/util/ncopy.c index 1127d0d..9bf82ad 100644 --- a/util/ncopy.c +++ b/util/ncopy.c @@ -23,9 +23,10 @@ #include #include #include "ncplib.h" +#include - -struct NCPMountRec { +struct NCPMountRec +{ char *mountDir; char *server; struct ncp_conn *conn; @@ -70,7 +71,8 @@ static struct sigaction sTermSig; /**************************************************************************** * */ -static void usage() +static void +usage(void) { fprintf(stderr, "usage: %s [-V]\n", ProgramName); fprintf(stderr, " %s [-vn] [-s amt] sourcefile destinationfile|directory\n", ProgramName); @@ -84,17 +86,19 @@ static void usage() * Return pointer to original string if no "/" in string. (except at end) */ static const char * - myBaseName(const char *path) +myBaseName(const char *path) { const char *p; - for (p = &path[strlen(path)]; p != path; p--) { /* skip ENDING "/" chars */ + for (p = &path[strlen(path)]; p != path; p--) + { /* skip ENDING "/" chars */ if (*p && *p != '/') break; } if (p == path) return p; - for (; p != path || *p == '/'; p--) { + for (; p != path || *p == '/'; p--) + { if (*p == '/') return ++p; } @@ -105,7 +109,7 @@ static const char * * */ static const char * - notDir(const char *path) +notDir(const char *path) { struct stat buf; static const char *notDirectory = "not a directory"; @@ -120,12 +124,15 @@ static const char * /**************************************************************************** * */ -static int handleOptions(const int argc, char *const argv[]) +static int +handleOptions(const int argc, char *const argv[]) { int opt; - while ((opt = getopt(argc, argv, "vVns:")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "vVns:")) != EOF) + { + switch (opt) + { case 'V': /* Version */ optVersion = 1; @@ -142,7 +149,8 @@ static int handleOptions(const int argc, char *const argv[]) case 's': /* Nice Factor */ optNiceFactorSel = 1; optNiceFactor = atoi(optarg); - if (optNiceFactor < 1) { + if (optNiceFactor < 1) + { fprintf(stderr, "%s: -s option requires positive numeric argument > 0\n", ProgramName); return 1; @@ -160,18 +168,22 @@ static int handleOptions(const int argc, char *const argv[]) /**************************************************************************** * TODO: if recursive flag last MUST be a directory, even if only 2 args. */ -static int validateFileArgs(const int argc, char *const argv[]) +static int +validateFileArgs(const int argc, char *const argv[]) { const char *p; - if (argc == 0) { + if (argc == 0) + { fprintf(stderr, "%s: No arguments specified.\n", ProgramName); return 1; } - if (argc == 1) { + if (argc == 1) + { fprintf(stderr, "%s: No destination specified.\n", ProgramName); return 1; } - if ((argc > 2) && (p = notDir(argv[argc - 1]))) { /* last arg MUST be dir */ + if ((argc > 2) && (p = notDir(argv[argc - 1]))) + { /* last arg MUST be dir */ fprintf(stderr, "%s: %s: %s\n", ProgramName, argv[argc - 1], p); return 1; } @@ -182,7 +194,7 @@ static int validateFileArgs(const int argc, char *const argv[]) * Duplicate a string. */ char * - duplicateStr(const char *InStr) +duplicateStr(const char *InStr) { char *dup; if (!InStr) @@ -196,31 +208,38 @@ char * /**************************************************************************** * load a table of ncpfs mount points. */ -int loadMountTable() +int +loadMountTable(void) { FILE *mountedFile; struct mntent *mountEntry = NULL; ncpCount = 0; - if ((mountedFile = fopen(MOUNTED, "r")) == NULL) { + if ((mountedFile = fopen(MOUNTED, "r")) == NULL) + { fprintf(stderr, "ncopy: cannot open %s, %s\n", MOUNTED, strerror(errno)); return 1; } - while ((mountEntry = getmntent(mountedFile)) != NULL) { + while ((mountEntry = getmntent(mountedFile)) != NULL) + { if (!strcmp(mountEntry->mnt_type, "ncpfs")) ncpCount++; } - if (ncpCount) { + if (ncpCount) + { NcpMountTable = (struct NCPMountRec *) malloc(ncpCount * sizeof(struct NCPMountRec)); - if (!NcpMountTable) { + if (!NcpMountTable) + { fprintf(stderr, "Out of memory\n"); fclose(mountedFile); return 1; } fseek(mountedFile, 0, SEEK_SET); ncpCount = 0; - while ((mountEntry = getmntent(mountedFile)) != NULL) { - if (!strcmp(mountEntry->mnt_type, "ncpfs")) { + while ((mountEntry = getmntent(mountedFile)) != NULL) + { + if (!strcmp(mountEntry->mnt_type, "ncpfs")) + { NcpMountTable[ncpCount].mountDir = duplicateStr(mountEntry->mnt_dir); NcpMountTable[ncpCount].server = duplicateStr(mountEntry->mnt_fsname); @@ -236,13 +255,16 @@ int loadMountTable() /**************************************************************************** * Releases the table of ncpfs mount points. */ -void releaseMountTable() +void +releaseMountTable(void) { int loop; if (!ncpCount) return; - for (loop = ncpCount; loop; loop--, ncpCount--) { - if (NcpMountTable[loop - 1].conn) { + for (loop = ncpCount; loop; loop--, ncpCount--) + { + if (NcpMountTable[loop - 1].conn) + { ncp_close(NcpMountTable[loop - 1].conn); NcpMountTable[loop - 1].conn = NULL; } @@ -257,14 +279,16 @@ void releaseMountTable() * the file. * Returns -1 if the files do not reference the same server. */ -int ncpIndex(const char *InputFile, const char *OutputFile) +int +ncpIndex(const char *InputFile, const char *OutputFile) { int loop; char *mountDir; if (!ncpCount) return -1; - for (loop = 0; loop < ncpCount; loop++) { + for (loop = 0; loop < ncpCount; loop++) + { mountDir = NcpMountTable[loop].mountDir; if (!strncmp(mountDir, InputFile, strlen(mountDir)) && !strncmp(mountDir, OutputFile, strlen(mountDir))) @@ -278,40 +302,46 @@ int ncpIndex(const char *InputFile, const char *OutputFile) * Does a regular buffered file copy. * This is used if we cannot use the Netware file copy. */ -int normalFileCopy(const char *InputFile, const char *OutputFile, - char *Buffer, int BufferSize, - const char *paramInputFile, - const char *paramOutputFile) +int +normalFileCopy(const char *InputFile, const char *OutputFile, + char *Buffer, int BufferSize, + const char *paramInputFile, + const char *paramOutputFile) { int fdIn, fdOut; long fileSize, totalSize; struct stat statBuf; fdIn = open(InputFile, O_RDONLY); - if (fdIn == -1) { + if (fdIn == -1) + { fprintf(stderr, "%s: Cannot open %s, %s\n", ProgramName, paramInputFile, strerror(errno)); return 1; } - if (fstat(fdIn, &statBuf)) { + if (fstat(fdIn, &statBuf)) + { fprintf(stderr, "%s: Cannot stat %s, %s\n", ProgramName, paramInputFile, strerror(errno)); close(fdIn); return 1; } - if (S_ISDIR(statBuf.st_mode)) { + if (S_ISDIR(statBuf.st_mode)) + { close(fdIn); fprintf(stderr, "%s: %s: omitting directory\n", ProgramName, paramInputFile); return 0; /* At this point, don't consider this a fatal error */ } fdOut = open(OutputFile, O_CREAT | O_TRUNC | O_WRONLY, statBuf.st_mode); - if (fdOut == -1) { + if (fdOut == -1) + { fprintf(stderr, "%s: Cannot create %s, %s\n", ProgramName, paramOutputFile, strerror(errno)); close(fdIn); return 1; } fileSize = lseek(fdIn, 0, SEEK_END); - if (fileSize < 0) { + if (fileSize < 0) + { fprintf(stderr, "%s: lseek error on %s, %s\n", ProgramName, paramInputFile, strerror(errno)); close(fdOut); @@ -319,16 +349,19 @@ int normalFileCopy(const char *InputFile, const char *OutputFile, return 1; } lseek(fdIn, 0, SEEK_SET); - if (optVerbose) { + if (optVerbose) + { printf("Normal copy: %s -> %s 0%%", paramInputFile, paramOutputFile); fflush(stdout); } totalSize = fileSize; - while (fileSize) { + while (fileSize) + { int currentMove; int writeAmt; currentMove = (fileSize > BufferSize) ? BufferSize : fileSize; - if (read(fdIn, Buffer, currentMove) != currentMove) { + if (read(fdIn, Buffer, currentMove) != currentMove) + { fprintf(stderr, "%s: Error reading %s, %s\n", ProgramName, paramInputFile, strerror(errno)); close(fdIn); @@ -336,13 +369,15 @@ int normalFileCopy(const char *InputFile, const char *OutputFile, return 1; } writeAmt = write(fdOut, Buffer, currentMove); - if (writeAmt < 0) { + if (writeAmt < 0) + { fprintf(stderr, "%s: Error writing %s, %s\n", ProgramName, paramOutputFile, strerror(errno)); close(fdIn); close(fdOut); return 1; - } else if (writeAmt == 0) { + } else if (writeAmt == 0) + { fprintf(stderr, "%s: Out of space on destination device writing %s\n", ProgramName, OutputFile); close(fdIn); @@ -350,7 +385,8 @@ int normalFileCopy(const char *InputFile, const char *OutputFile, return 1; } fileSize -= currentMove; - if (optVerbose) { + if (optVerbose) + { printf("\rNormal copy: %s -> %s %ld%%", paramInputFile, paramOutputFile, (100 - (fileSize * 100 / totalSize))); fflush(stdout); } @@ -367,10 +403,11 @@ int normalFileCopy(const char *InputFile, const char *OutputFile, * Netware file names need to be all upper case. */ char * - upString(char *str) +upString(char *str) { char *alias = str; - while (*alias) { + while (*alias) + { *alias = toupper(*alias); ++alias; } @@ -381,10 +418,12 @@ char * * Locates the first occurrance of a single character in the input string. * returns -1 if the character is not found. */ -int stringPosition(const char *str, char token) +int +stringPosition(const char *str, char token) { const char *alias = str; - while (*alias) { + while (*alias) + { if (*alias == token) return alias - str; alias++; @@ -398,7 +437,8 @@ int stringPosition(const char *str, char token) * This will mangle the input "FileString", leaving just the file name * component in it when it is finished. */ -int getDirHandle(struct ncp_conn *conn, char *FileString, __u8 * NewDirHandle) +int +getDirHandle(struct ncp_conn *conn, char *FileString, __u8 * NewDirHandle) { struct nw_info_struct info1, info2; int currentLevel = 0; @@ -406,20 +446,25 @@ int getDirHandle(struct ncp_conn *conn, char *FileString, __u8 * NewDirHandle) struct nw_info_struct *parentInfo = NULL; struct nw_info_struct *currentInfo = NULL; - while ((k = stringPosition(FileString, '/')) >= 0) { + while ((k = stringPosition(FileString, '/')) >= 0) + { FileString[k] = 0; - if (!currentLevel) { + if (!currentLevel) + { parentInfo = NULL; currentInfo = &info1; - } else if (currentLevel % 2) { + } else if (currentLevel % 2) + { parentInfo = &info1; currentInfo = &info2; - } else { + } else + { parentInfo = &info2; currentInfo = &info1; } if (ncp_do_lookup(conn, parentInfo, FileString, - currentInfo) != 0) { + currentInfo) != 0) + { fprintf(stderr, "%s: Ncp lookup failed on directory %s--%s\n", ProgramName, FileString, strerror(errno)); return 1; @@ -429,7 +474,8 @@ int getDirHandle(struct ncp_conn *conn, char *FileString, __u8 * NewDirHandle) } if (ncp_alloc_short_dir_handle(conn, currentInfo, NCP_ALLOC_TEMPORARY, - NewDirHandle) != 0) { + NewDirHandle) != 0) + { fprintf(stderr, "%s: Ncp alloc dir handle failed--%s\n", ProgramName, strerror(errno)); return 1; @@ -441,10 +487,11 @@ int getDirHandle(struct ncp_conn *conn, char *FileString, __u8 * NewDirHandle) /**************************************************************************** * Interfaces with the ncplib to do the netware copy of the file. */ -int netwareCopyFile(int ncpMountIndex, const char *sourcefile, - const char *destfile, - const char *paramInputFile, - const char *paramOutputFile) +int +netwareCopyFile(int ncpMountIndex, const char *sourcefile, + const char *destfile, + const char *paramInputFile, + const char *paramOutputFile) { __u8 source_dir_handle; __u8 dest_dir_handle; @@ -465,10 +512,12 @@ int netwareCopyFile(int ncpMountIndex, const char *sourcefile, /* Establish a connection to a Netware mount point if one is not already established. */ - if (!NcpMountTable[ncpMountIndex].conn) { - NcpMountTable[ncpMountIndex].conn = - ncp_open_mount(NcpMountTable[ncpMountIndex].mountDir, &err); - if (err) { + if (!NcpMountTable[ncpMountIndex].conn) + { + err = ncp_open_mount(NcpMountTable[ncpMountIndex].mountDir, + &NcpMountTable[ncpMountIndex].conn); + if (err) + { com_err(ProgramName, err, "opening ncp connection on mount point %s", NcpMountTable[ncpMountIndex].mountDir); return 2; @@ -481,7 +530,8 @@ int netwareCopyFile(int ncpMountIndex, const char *sourcefile, stroffset = strlen(NcpMountTable[ncpMountIndex].mountDir) + 1; sourceDup = duplicateStr(sourcefile + stroffset); destDup = duplicateStr(destfile + stroffset); - if (!sourceDup || !destDup) { + if (!sourceDup || !destDup) + { fprintf(stderr, "%s: Malloc failed duplicating file names\n", ProgramName); return 2; @@ -491,14 +541,16 @@ int netwareCopyFile(int ncpMountIndex, const char *sourcefile, /* Get Handles to the input and output directories */ if (getDirHandle(sourceconn, sourceDup, &source_dir_handle) || - getDirHandle(sourceconn, destDup, &dest_dir_handle)) { + getDirHandle(sourceconn, destDup, &dest_dir_handle)) + { free(sourceDup); free(destDup); return 1; } /* Open the input and output files. */ if (ncp_open_file(sourceconn, source_dir_handle, sourceDup, 0, AR_READ, - &source_file) != 0) { + &source_file) != 0) + { fprintf(stderr, "%s: Cannot open %s--%s\n", ProgramName, paramInputFile, strerror(errno)); free(sourceDup); @@ -506,7 +558,8 @@ int netwareCopyFile(int ncpMountIndex, const char *sourcefile, return 1; } if (ncp_create_file(sourceconn, dest_dir_handle, destDup, - source_file.file_attributes, &dest_file) != 0) { + source_file.file_attributes, &dest_file) != 0) + { fprintf(stderr, "%s: Cannot create %s--%s\n", ProgramName, paramOutputFile, strerror(errno)); ncp_close_file(sourceconn, source_file.file_id); @@ -523,7 +576,8 @@ int netwareCopyFile(int ncpMountIndex, const char *sourcefile, free(destDup); retValue = 0; - if (optVerbose) { + if (optVerbose) + { printf("NetWare copy: %s -> %s 0%%", paramInputFile, paramOutputFile); fflush(stdout); } @@ -533,24 +587,28 @@ int netwareCopyFile(int ncpMountIndex, const char *sourcefile, sourceOff = 0; retryCount = 0; - while (amtLeft && retryCount < MaxNcopyRetries) { + while (amtLeft && retryCount < MaxNcopyRetries) + { int ncopyRetValue; if (amtLeft > CopyBlockSize) thisMove = CopyBlockSize; else thisMove = amtLeft; /* If we are being nice and we've copied enough blocks, go to sleep */ - if (optNice) { - if (BlocksCopied == optNiceFactor) { + if (optNice) + { + if (BlocksCopied == optNiceFactor) + { sleep(NiceSleepTime); BlocksCopied = 0; } else ++BlocksCopied; } ncopyRetValue = ncp_copy_file(sourceconn, source_file.file_id, - dest_file.file_id, sourceOff, sourceOff, + dest_file.file_id, sourceOff, sourceOff, thisMove, &amountCopied); - if (ncopyRetValue != 0) { + if (ncopyRetValue != 0) + { /* In my testing this only happens when you run out of space on the server. Netware seems to wait a bit before reporting space recently @@ -559,7 +617,8 @@ int netwareCopyFile(int ncpMountIndex, const char *sourcefile, retryCount++; amountCopied = thisMove = 0; } - if (amountCopied != thisMove) { + if (amountCopied != thisMove) + { fprintf(stderr, "%s: Warning, amountCopied (%u) != thisMove (%u)\n", ProgramName, (unsigned int) amountCopied, (unsigned int) thisMove); } @@ -569,7 +628,8 @@ int netwareCopyFile(int ncpMountIndex, const char *sourcefile, #endif amtLeft -= amountCopied; sourceOff += amountCopied; - if (optVerbose) { + if (optVerbose) + { printf("\rNetWare copy: %s -> %s %ld%%", paramInputFile, paramOutputFile, (100 - (long) ((float) amtLeft / (float) totalSize * 100.0))); if (retryCount) @@ -581,7 +641,8 @@ int netwareCopyFile(int ncpMountIndex, const char *sourcefile, retValue = 1; if (optVerbose) printf("\n"); - if (ncp_close_file(sourceconn, dest_file.file_id) != 0) { + if (ncp_close_file(sourceconn, dest_file.file_id) != 0) + { fprintf(stderr, "%s: Close failed for %s\n", ProgramName, paramOutputFile); retValue = 1; } @@ -590,16 +651,19 @@ int netwareCopyFile(int ncpMountIndex, const char *sourcefile, CurrentConn = NULL; CurrentFile = NULL; - if (ncp_close_file(sourceconn, source_file.file_id) != 0) { + if (ncp_close_file(sourceconn, source_file.file_id) != 0) + { fprintf(stderr, "%s: Close failed for %s\n", ProgramName, paramInputFile); retValue = 1; } - if (ncp_dealloc_dir_handle(sourceconn, dest_dir_handle) != 0) { + if (ncp_dealloc_dir_handle(sourceconn, dest_dir_handle) != 0) + { fprintf(stderr, "%s: Dealloc dir handle error for %s\n", ProgramName, paramOutputFile); retValue = 1; } - if (ncp_dealloc_dir_handle(sourceconn, source_dir_handle) != 0) { + if (ncp_dealloc_dir_handle(sourceconn, source_dir_handle) != 0) + { fprintf(stderr, "%s: Dealloc dir handle error for %s\n", ProgramName, paramInputFile); retValue = 1; @@ -612,8 +676,9 @@ int netwareCopyFile(int ncpMountIndex, const char *sourcefile, * Decides whether to use the traditional file copy or the netware remote * file copy. */ -int copyFiles(const char *realsource, const char *realdestination, - const char *paraminputfile, const char *paramoutputfile) +int +copyFiles(const char *realsource, const char *realdestination, + const char *paraminputfile, const char *paramoutputfile) { int oldUMask; char fileBuffer[24000]; @@ -623,7 +688,7 @@ int copyFiles(const char *realsource, const char *realdestination, printf("Real Source '%s'\n" "Real Dest '%s'\n" "Param Src '%s'\n" - "Param Dest '%s'\n", realsource, realdestination, paraminputfile, + "Param Dest '%s'\n", realsource, realdestination, paraminputfile, paramoutputfile); #endif @@ -657,7 +722,8 @@ int copyFiles(const char *realsource, const char *realdestination, * Is it failure if destination fails? * Do we Stay in the loop? */ -static int copyRealPaths(const char *source, const char *destination) +static int +copyRealPaths(const char *source, const char *destination) { char realsource[MAXPATHLEN * 2]; char realdestination[MAXPATHLEN * 2]; @@ -665,18 +731,21 @@ static int copyRealPaths(const char *source, const char *destination) char filePart[MAXPATHLEN + 1]; const char *p; - if (realpath(source, realsource) == 0) { /* the source must at least exist */ + if (realpath(source, realsource) == 0) + { /* the source must at least exist */ fprintf(stderr, "%s: %s: %s\n", ProgramName, source, strerror(errno)); return 1; /* indicate a "source" problem */ } - if (realpath(destination, realdestination) == 0) { /* dest file missing? OK */ + if (realpath(destination, realdestination) == 0) + { /* dest file missing? OK */ strncpy(dirPart, destination, MAXPATHLEN); /* but "dirpart" must work */ dirPart[MAXPATHLEN] = 0; p = myBaseName(dirPart); strcpy(filePart, p); dirPart[p - dirPart] = 0; /* isolates "directory" part from "file part" */ - if (realpath(dirPart, realdestination) == 0) { + if (realpath(dirPart, realdestination) == 0) + { fprintf(stderr, "%s: %s: %s\n", ProgramName, dirPart, strerror(errno)); return 2; /* indicate a "destination" problem */ @@ -701,7 +770,8 @@ static int copyRealPaths(const char *source, const char *destination) * if argc > 2 last parameter is a directory * by validateFileArgs() */ -static int handleFileArgs(int argc, char *const argv[]) +static int +handleFileArgs(int argc, char *const argv[]) { int loop; const char *destination; @@ -711,10 +781,12 @@ static int handleFileArgs(int argc, char *const argv[]) char destinationfile[MAXPATHLEN * 2]; destination = argv[argc - 1]; /* get LAST argument */ - for (loop = 0; loop < (argc - 1); loop++) { /* all file arguments, but last */ + for (loop = 0; loop < (argc - 1); loop++) + { /* all file arguments, but last */ strncpy(destinationfile, destination, MAXPATHLEN); destinationfile[MAXPATHLEN] = 0; - if ((argc > 2) || (!notDir(argv[argc - 1]))) { /* destination is a dir */ + if ((argc > 2) || (!notDir(argv[argc - 1]))) + { /* destination is a dir */ if (*destinationfile != '/' || *(destinationfile + 1)) strcat(destinationfile, "/"); baseNamePtr = myBaseName(argv[loop]); /* get the file name */ @@ -731,41 +803,48 @@ static int handleFileArgs(int argc, char *const argv[]) /**************************************************************************** * */ -static void handleSignals(int sigNumber) +static void +handleSignals(int sigNumber) { /* Ignore Signal Handling while cleaning up */ /* SIGHUP */ sHangupSig.sa_handler = SIG_IGN; - if (sigaction(SIGHUP, &sHangupSig, NULL) == -1) { + if (sigaction(SIGHUP, &sHangupSig, NULL) == -1) + { fprintf(stderr, "%s: Reset to ignore SIGHUP signal failed: %s", ProgramName, strerror(errno)); } /* SIGINT */ sInterruptSig.sa_handler = SIG_IGN; - if (sigaction(SIGINT, &sInterruptSig, NULL) == -1) { + if (sigaction(SIGINT, &sInterruptSig, NULL) == -1) + { fprintf(stderr, "%s: Reset to ignore SIGINT signal failed: %s", ProgramName, strerror(errno)); } /* SIGQUIT */ sQuitSig.sa_handler = SIG_IGN; - if (sigaction(SIGQUIT, &sQuitSig, NULL) == -1) { + if (sigaction(SIGQUIT, &sQuitSig, NULL) == -1) + { fprintf(stderr, "%s: Reset to ignore SIGQUIT signal failed: %s", ProgramName, strerror(errno)); } /* SIGTERM */ sTermSig.sa_handler = SIG_IGN; - if (sigaction(SIGTERM, &sTermSig, NULL) == -1) { + if (sigaction(SIGTERM, &sTermSig, NULL) == -1) + { fprintf(stderr, "%s: Reset to ignore SIGTERM signal failed: %s", ProgramName, strerror(errno)); } /* If we don't close the ncp output file, we have to ncpumount and ncpmount before we can get rid of it. */ - if (OutputOpen) { + if (OutputOpen) + { /* Issue a warning if we cannot close the file */ /* If an error occurs we probably have to umount/mount to remove the file */ - if (ncp_close_file(CurrentConn, CurrentFile->file_id) != 0) { + if (ncp_close_file(CurrentConn, CurrentFile->file_id) != 0) + { fprintf(stderr, "%s: unclean close of output file", ProgramName); } OutputOpen = 0; @@ -776,48 +855,57 @@ static void handleSignals(int sigNumber) /**************************************************************************** * We'll trap Hangup, Interrupt, Quit or Terminate */ -static int trapSignals() +static int +trapSignals(void) { - if (sigaction(SIGHUP, NULL, &sHangupSig)) { /* init structure fields */ + if (sigaction(SIGHUP, NULL, &sHangupSig)) + { /* init structure fields */ fprintf(stderr, "%s: Get HANGUP signal action failed: %s", ProgramName, strerror(errno)); return 1; } sHangupSig.sa_handler = handleSignals; - if (sigaction(SIGHUP, &sHangupSig, NULL) == -1) { + if (sigaction(SIGHUP, &sHangupSig, NULL) == -1) + { fprintf(stderr, "%s: Reset HANGUP signal action failed: %s", ProgramName, strerror(errno)); return 1; } - if (sigaction(SIGINT, NULL, &sInterruptSig)) { /* init structure fields */ + if (sigaction(SIGINT, NULL, &sInterruptSig)) + { /* init structure fields */ fprintf(stderr, "%s: Get INTERRUPT signal action failed: %s", ProgramName, strerror(errno)); return 1; } sInterruptSig.sa_handler = handleSignals; - if (sigaction(SIGINT, &sInterruptSig, NULL) == -1) { + if (sigaction(SIGINT, &sInterruptSig, NULL) == -1) + { fprintf(stderr, "%s: Reset INTERRUPT signal action failed: %s", ProgramName, strerror(errno)); return 1; } - if (sigaction(SIGQUIT, NULL, &sQuitSig)) { /* init structure fields */ + if (sigaction(SIGQUIT, NULL, &sQuitSig)) + { /* init structure fields */ fprintf(stderr, "%s: Get QUIT signal action failed: %s", ProgramName, strerror(errno)); return 1; } sQuitSig.sa_handler = handleSignals; - if (sigaction(SIGQUIT, &sQuitSig, NULL) == -1) { + if (sigaction(SIGQUIT, &sQuitSig, NULL) == -1) + { fprintf(stderr, "%s: Reset QUIT signal action failed: %s", ProgramName, strerror(errno)); return 1; } - if (sigaction(SIGTERM, NULL, &sTermSig)) { /* init structure fields */ + if (sigaction(SIGTERM, NULL, &sTermSig)) + { /* init structure fields */ fprintf(stderr, "%s: Get TERMINATE signal action failed: %s", ProgramName, strerror(errno)); return 1; } sTermSig.sa_handler = handleSignals; - if (sigaction(SIGTERM, &sTermSig, NULL) == -1) { + if (sigaction(SIGTERM, &sTermSig, NULL) == -1) + { fprintf(stderr, "%s: Reset TERMINATE signal action failed: %s", ProgramName, strerror(errno)); return 1; @@ -828,20 +916,24 @@ static int trapSignals() /**************************************************************************** * */ -int main(int argc, char *const argv[]) +int +main(int argc, char *const argv[]) { int returnCode; ProgramName = argv[0]; - if (handleOptions(argc, argv)) { /* bad option, missing option parameter */ + if (handleOptions(argc, argv)) + { /* bad option, missing option parameter */ usage(); return 1; } - if (optVersion) { /* only option not requiring any arguments */ + if (optVersion) + { /* only option not requiring any arguments */ printf("%s version %s\n", ProgramName, VersionStr); return 0; } - if (validateFileArgs(argc - optind, argv + optind)) { + if (validateFileArgs(argc - optind, argv + optind)) + { usage(); return 1; } diff --git a/util/ncptest.c b/util/ncptest.c index 7afd222..6e5a02f 100644 --- a/util/ncptest.c +++ b/util/ncptest.c @@ -1,4 +1,3 @@ - /* * ncptest.c * @@ -20,7 +19,7 @@ #include #include #include - /* #include *//* generates a warning here */ + /* #include *//* generates a warning here */ extern pid_t waitpid(pid_t, int *, int); #include #include @@ -30,16 +29,16 @@ extern pid_t waitpid(pid_t, int *, int); #include #include #include -#include +#include "kernel/ipx.h" -#include -#include -#include -#include +#include "kernel/fs.h" +#include "kernel/ncp.h" +#include "kernel/ncp_fs.h" #include "ncplib.h" -void test_connlist(struct ncp_conn *conn) +void +test_connlist(struct ncp_conn *conn) { __u8 conn_list[256] = {0,}; @@ -50,92 +49,110 @@ void test_connlist(struct ncp_conn *conn) return; } -void test_send(struct ncp_conn *conn) +void +test_send(struct ncp_conn *conn) { __u8 conn_list[256] = {0,}; int no; if (ncp_get_connlist(conn, NCP_BINDERY_USER, "ME", &no, - conn_list) != 0) { + conn_list) != 0) + { no = 0; } - if (no > 0) { + if (no > 0) + { ncp_send_broadcast(conn, no, conn_list, "Hallo"); } return; } -void test_create(struct ncp_conn *conn) +void +test_create(struct ncp_conn *conn) { struct nw_info_struct sys; struct nw_info_struct me; __u8 dir_handle; struct ncp_file_info new_file; - if (ncp_do_lookup(conn, NULL, "SYS", &sys) != 0) { + if (ncp_do_lookup(conn, NULL, "SYS", &sys) != 0) + { printf("lookup error\n"); return; } - if (ncp_do_lookup(conn, &sys, "ME", &me) != 0) { + if (ncp_do_lookup(conn, &sys, "ME", &me) != 0) + { printf("lookup public error\n"); return; } if (ncp_alloc_short_dir_handle(conn, &me, NCP_ALLOC_TEMPORARY, - &dir_handle) != 0) { + &dir_handle) != 0) + { printf("alloc_dir_handle error\n"); return; } if (ncp_create_file(conn, dir_handle, "BLUB.TXT", 0, - &new_file) != 0) { + &new_file) != 0) + { printf("create error\n"); return; } - if (ncp_dealloc_dir_handle(conn, dir_handle) != 0) { + if (ncp_dealloc_dir_handle(conn, dir_handle) != 0) + { printf("dealloc error\n"); return; } } -int test_change(struct ncp_conn *conn) +int +test_change(struct ncp_conn *conn) { long result; unsigned char ncp_key[8]; struct ncp_bindery_object user; - if ((result = ncp_get_encryption_key(conn, ncp_key)) != 0) { + if ((result = ncp_get_encryption_key(conn, ncp_key)) != 0) + { return result; } if ((result = ncp_get_bindery_object_id(conn, 1, - "ME", &user)) != 0) { + "ME", &user)) != 0) + { return result; } if ((result = ncp_change_login_passwd(conn, &user, ncp_key, - "MEE", "ME")) != 0) { + "MEE", "ME")) != 0) + { return result; } return 0; } -void test_readdir(struct ncp_conn *conn) +void +test_readdir(struct ncp_conn *conn) { struct nw_info_struct sys; struct nw_info_struct blub; struct ncp_search_seq seq; struct nw_info_struct entry; - if (ncp_do_lookup(conn, NULL, "SYS", &sys) != 0) { + if (ncp_do_lookup(conn, NULL, "SYS", &sys) != 0) + { printf("lookup error\n"); return; } - if (ncp_do_lookup(conn, &sys, "BLUB", &blub) != 0) { + if (ncp_do_lookup(conn, &sys, "BLUB", &blub) != 0) + { printf("lookup blub error\n"); return; } - if (ncp_initialize_search(conn, &sys, 0, &seq) != 0) { + if (ncp_initialize_search(conn, &sys, 0, &seq) != 0) + { printf("init error\n"); return; } - while (ncp_search_for_file_or_subdir(conn, &seq, &entry) == 0) { + while (ncp_search_for_file_or_subdir(conn, &seq, &entry) == 0) + { struct nw_info_struct nfs; printf("found: %s\n", entry.entryName); if (ncp_obtain_file_or_subdir_info(conn, NW_NS_DOS, NW_NS_NFS, @@ -143,7 +160,8 @@ void test_readdir(struct ncp_conn *conn) entry.volNumber, entry.DosDirNum, NULL, - &nfs) == 0) { + &nfs) == 0) + { printf("nfs name: %s\n", nfs.entryName); } if (ncp_obtain_file_or_subdir_info(conn, NW_NS_DOS, NW_NS_OS2, @@ -151,30 +169,35 @@ void test_readdir(struct ncp_conn *conn) entry.volNumber, entry.DosDirNum, NULL, - &nfs) == 0) { + &nfs) == 0) + { printf("os2 name: %s\n", nfs.entryName); } } } -void test_rights(struct ncp_conn *conn) +void +test_rights(struct ncp_conn *conn) { struct nw_info_struct sys; struct nw_info_struct me; __u16 rights; - if (ncp_do_lookup(conn, NULL, "SYS", &sys) != 0) { + if (ncp_do_lookup(conn, NULL, "SYS", &sys) != 0) + { printf("lookup error\n"); return; } - if (ncp_do_lookup(conn, &sys, "ME", &me) != 0) { + if (ncp_do_lookup(conn, &sys, "ME", &me) != 0) + { printf("lookup me error\n"); return; } if (ncp_get_eff_directory_rights(conn, 0, 0, 0x8006, - sys.volNumber, sys.DosDirNum, NULL, - &rights) != 0) { + sys.volNumber, sys.DosDirNum, NULL, + &rights) != 0) + { printf("get sys rights error\n"); return; } @@ -182,7 +205,8 @@ void test_rights(struct ncp_conn *conn) if (ncp_get_eff_directory_rights(conn, 0, 0, 0x8006, me.volNumber, me.DosDirNum, NULL, - &rights) != 0) { + &rights) != 0) + { printf("get me rights error\n"); return; } @@ -190,12 +214,14 @@ void test_rights(struct ncp_conn *conn) return; } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { struct ncp_conn *conn; long err; - if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { com_err(argv[0], err, "in ncp_initialize"); return 1; } diff --git a/util/nprint.c b/util/nprint.c index 9e04aac..76a0b40 100644 --- a/util/nprint.c +++ b/util/nprint.c @@ -22,7 +22,8 @@ static void usage(void); static void help(void); -void main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { struct ncp_conn *conn; @@ -50,11 +51,13 @@ void main(int argc, char *argv[]) memzero(q); if ((argc == 2) - && (strcmp(argv[1], "-h") == 0)) { + && (strcmp(argv[1], "-h") == 0)) + { help(); exit(0); } - if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { com_err(argv[0], err, "when initializing connection"); exit(1); } @@ -75,8 +78,10 @@ void main(int argc, char *argv[]) pj.Rows = htons(80); strcpy(pj.FnameHeader, "stdin"); - while ((opt = getopt(argc, argv, "h?q:d:p:b:f:l:r:c:t:F:TN")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?q:d:p:b:f:l:r:c:t:F:TN")) != EOF) + { + switch (opt) + { case 'h': case '?': help(); @@ -85,38 +90,45 @@ void main(int argc, char *argv[]) case 'p': /* Path */ pj.CtrlFlags |= PRINT_BANNER; - if (strlen(optarg) >= sizeof(pj.Path)) { + if (strlen(optarg) >= sizeof(pj.Path)) + { strncpy(pj.Path, optarg, sizeof(pj.Path)); - } else { + } else + { strcpy(pj.Path, optarg); } break; case 'b': /* Banner Name */ pj.CtrlFlags |= PRINT_BANNER; - if (strlen(optarg) >= sizeof(pj.BannerName)) { + if (strlen(optarg) >= sizeof(pj.BannerName)) + { strncpy(pj.BannerName, optarg, sizeof(pj.BannerName)); - } else { + } else + { strcpy(pj.BannerName, optarg); } break; case 'f': /* File Name in Banner */ pj.CtrlFlags |= PRINT_BANNER; - if (strlen(optarg) >= sizeof(pj.FnameBanner)) { + if (strlen(optarg) >= sizeof(pj.FnameBanner)) + { strncpy(pj.FnameBanner, optarg, sizeof(pj.FnameBanner)); - } else { + } else + { strcpy(pj.FnameBanner, optarg); } break; case 'l': /* lines, default: 66 */ - if ((atoi(optarg) < 0) || (atoi(optarg) > 65535)) { + if ((atoi(optarg) < 0) || (atoi(optarg) > 65535)) + { fprintf(stderr, - "invalid line number: %s\n", optarg); + "invalid line number: %s\n", optarg); break; } pj.Lines = htons(atoi(optarg)); @@ -124,9 +136,10 @@ void main(int argc, char *argv[]) break; case 'r': /* rows, default: 80 */ - if ((atoi(optarg) < 0) || (atoi(optarg) > 65535)) { + if ((atoi(optarg) < 0) || (atoi(optarg) > 65535)) + { fprintf(stderr, - "invalid row number: %s\n", optarg); + "invalid row number: %s\n", optarg); break; } pj.Rows = htons(atoi(optarg)); @@ -134,7 +147,8 @@ void main(int argc, char *argv[]) break; case 'c': /* copies, default: 1 */ - if ((atoi(optarg) < 0) || (atoi(optarg) > 65000)) { + if ((atoi(optarg) < 0) || (atoi(optarg) > 65000)) + { fprintf(stderr, "invalid copies: %s\n", optarg); break; @@ -144,7 +158,8 @@ void main(int argc, char *argv[]) break; case 't': /* tab size, default: 8 */ - if ((atoi(optarg) < 0) || (atoi(optarg) > 255)) { + if ((atoi(optarg) < 0) || (atoi(optarg) > 255)) + { fprintf(stderr, "invalid tab size: %s\n", optarg); break; @@ -162,16 +177,18 @@ void main(int argc, char *argv[]) break; case 'F': /* Form number, default: 0 */ - if ((atoi(optarg) < 0) || (atoi(optarg) > 255)) { + if ((atoi(optarg) < 0) || (atoi(optarg) > 255)) + { fprintf(stderr, - "invalid form number: %s\n", optarg); + "invalid form number: %s\n", optarg); break; } j.j.JobType = htons(atoi(optarg)); break; case 'q': /* Queue name to print on, default: '*' */ - if (strlen(optarg) >= NCP_BINDERY_NAME_LEN) { + if (strlen(optarg) >= NCP_BINDERY_NAME_LEN) + { printf("queue name too long: %s\n", optarg); ncp_close(conn); @@ -182,10 +199,12 @@ void main(int argc, char *argv[]) case 'd': /* Job Description */ pj.CtrlFlags |= PRINT_BANNER; - if (strlen(optarg) >= sizeof(j.j.JobTextDescription)) { + if (strlen(optarg) >= sizeof(j.j.JobTextDescription)) + { strncpy(j.j.JobTextDescription, optarg, sizeof(j.j.JobTextDescription)); - } else { + } else + { strcpy(j.j.JobTextDescription, optarg); } break; @@ -197,34 +216,43 @@ void main(int argc, char *argv[]) } } - if (optind != argc - 1) { + if (optind != argc - 1) + { usage(); ncp_close(conn); exit(1); } file_name = argv[optind]; - if (strcmp(file_name, "-") == 0) { + if (strcmp(file_name, "-") == 0) + { file = 0; /* stdin */ - } else { + } else + { file = open(file_name, O_RDONLY, 0); - if (file < 0) { + if (file < 0) + { perror("could not open file"); ncp_close(conn); exit(1); } - if (strlen(file_name) >= sizeof(pj.FnameHeader)) { + if (strlen(file_name) >= sizeof(pj.FnameHeader)) + { strncpy(pj.FnameHeader, file_name, sizeof(pj.FnameHeader)); - } else { + } else + { strcpy(pj.FnameHeader, file_name); } - if (strlen(pj.FnameBanner) == 0) { - if (strlen(file_name) >= sizeof(pj.FnameBanner)) { + if (strlen(pj.FnameBanner) == 0) + { + if (strlen(file_name) >= sizeof(pj.FnameBanner)) + { strncpy(pj.FnameBanner, file_name, sizeof(pj.FnameBanner)); - } else { + } else + { strcpy(pj.FnameBanner, file_name); } } @@ -235,24 +263,29 @@ void main(int argc, char *argv[]) str_upper(queue); if (ncp_scan_bindery_object(conn, 0xffffffff, NCP_BINDERY_PQUEUE, - queue, &q) != 0) { + queue, &q) != 0) + { printf("could not find queue %s\n", queue); ncp_close(conn); exit(1); } - if (ncp_create_queue_job_and_file(conn, q.object_id, &j) != 0) { + if (ncp_create_queue_job_and_file(conn, q.object_id, &j) != 0) + { printf("create error\n"); ncp_close(conn); exit(1); } written = 0; - do { + do + { read_this_time = read(file, buf, sizeof(buf)); - if (read_this_time < 0) { + if (read_this_time < 0) + { break; } if (ncp_write(conn, j.file_handle, - written, read_this_time, buf) < read_this_time) { + written, read_this_time, buf) < read_this_time) + { break; } written += read_this_time; @@ -261,19 +294,22 @@ void main(int argc, char *argv[]) close(file); - if (ncp_close_file_and_start_job(conn, q.object_id, &j) != 0) { + if (ncp_close_file_and_start_job(conn, q.object_id, &j) != 0) + { printf("close error\n"); } ncp_close(conn); - return; + return 0; } -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [options] file\n", progname); } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options] file\n", progname); diff --git a/util/nsend.c b/util/nsend.c index d359cce..3af5a23 100644 --- a/util/nsend.c +++ b/util/nsend.c @@ -12,22 +12,27 @@ #include #include "ncplib.h" -int main(int argc, char **argv) +int +main(int argc, char **argv) { struct ncp_conn *conn; __u8 conn_list[256] = {0,}; int no_conn; + int conn_list2[256]; + int i; char *message = NULL; char *user = NULL; long err; - if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { com_err(argv[0], err, "when initializing"); exit(1); } - if (argc != 3) { + if (argc != 3) + { fprintf(stderr, "usage: %s [options] user message\n", argv[0]); ncp_close(conn); exit(1); @@ -36,20 +41,31 @@ int main(int argc, char **argv) message = argv[2]; if ((err = ncp_get_connlist(conn, NCP_BINDERY_USER, user, &no_conn, - conn_list)) != 0) { + conn_list)) != 0) + { com_err(argv[0], err, "in get_connlist"); ncp_close(conn); exit(1); } - if (no_conn == 0) { + if (no_conn == 0) + { fprintf(stderr, "No connection found for %s\n", user); ncp_close(conn); exit(1); } - if ((err = ncp_send_broadcast(conn, no_conn, conn_list, message)) != 0) { - com_err(argv[0], err, "in send_broadcast"); - ncp_close(conn); - exit(1); + for (i=0; icompletion == 0xFB) + err = ncp_send_broadcast(conn, no_conn, conn_list, message); + if (err) + { + com_err(argv[0], err, "in send_broadcast"); + ncp_close(conn); + exit(1); + } } ncp_close(conn); return 0; diff --git a/util/nwauth.c b/util/nwauth.c index 2df39e0..6882352 100644 --- a/util/nwauth.c +++ b/util/nwauth.c @@ -14,12 +14,14 @@ static char *progname; -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [options]\n", progname); } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options]\n", progname); @@ -31,18 +33,21 @@ static void help(void) "\n"); } -static void swallow_error(const char *s, long x, const char *t, va_list arg) +static void +swallow_error(const char *s, long x, const char *t, va_list arg) { return; } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { struct ncp_conn_spec *spec; struct ncp_conn *conn; char *server = NULL; char *object_name = NULL; int object_type = NCP_BINDERY_USER; + struct sockaddr_ipx addr; long err; char *str; @@ -51,11 +56,14 @@ int main(int argc, char *argv[]) progname = argv[0]; - if (!isatty(0)) { + if (!isatty(0)) + { set_com_err_hook(swallow_error); } - while ((opt = getopt(argc, argv, "h?S:U:t:")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?S:U:t:")) != EOF) + { + switch (opt) + { case 'S': server = optarg; break; @@ -78,31 +86,37 @@ int main(int argc, char *argv[]) spec = ncp_find_conn_spec(server, object_name, "", 1, getuid(), &err); - if (spec == NULL) { + if (spec == NULL) + { com_err(argv[0], err, "when trying to find server"); exit(1); } - if (ncp_find_fileserver(spec->server, &err) == NULL) { + if ((err = ncp_find_fileserver(spec->server, (struct sockaddr*)&addr, sizeof(addr))) != 0) + { com_err(argv[0], err, "when trying to find server"); exit(1); } spec->login_type = object_type; memset(spec->password, 0, sizeof(spec->password)); - if (isatty(0)) { + if (isatty(0)) + { str = getpass("Enter password: "); - if (strlen(str) >= sizeof(spec->password)) { + if (strlen(str) >= sizeof(spec->password)) + { printf("Password too long\n"); exit(1); } strcpy(spec->password, str); - } else { + } else + { fgets(spec->password, sizeof(spec->password), stdin); } str_upper(spec->password); - if ((conn = ncp_open(spec, &err)) == NULL) { + if ((conn = ncp_open(spec, &err)) == NULL) + { com_err(argv[0], err, "when trying to open connection"); exit(1); } diff --git a/util/nwbocreate.c b/util/nwbocreate.c index b2a4643..794c3ad 100644 --- a/util/nwbocreate.c +++ b/util/nwbocreate.c @@ -13,12 +13,14 @@ static char *progname; -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [options]\n", progname); } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options]\n", progname); @@ -37,27 +39,34 @@ static void help(void) "\n"); } -static int parse_security(const char *security) +static int +parse_security(const char *security) { - if (strcasecmp(security, "anyone") == 0) { + if (strcasecmp(security, "anyone") == 0) + { return 0; } - if (strcasecmp(security, "logged") == 0) { + if (strcasecmp(security, "logged") == 0) + { return 1; } - if (strcasecmp(security, "object") == 0) { + if (strcasecmp(security, "object") == 0) + { return 2; } - if (strcasecmp(security, "supervisor") == 0) { + if (strcasecmp(security, "supervisor") == 0) + { return 3; } - if (strcasecmp(security, "netware") == 0) { + if (strcasecmp(security, "netware") == 0) + { return 4; } return -1; } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { struct ncp_conn *conn; char *object_name = NULL; @@ -72,12 +81,15 @@ int main(int argc, char *argv[]) progname = argv[0]; - if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { com_err(argv[0], err, "when initializing"); goto finished; } - while ((opt = getopt(argc, argv, "h?o:t:r:w:")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?o:t:r:w:")) != EOF) + { + switch (opt) + { case 'o': object_name = optarg; str_upper(object_name); @@ -87,7 +99,8 @@ int main(int argc, char *argv[]) break; case 'r': read_sec = parse_security(optarg); - if (read_sec < 0) { + if (read_sec < 0) + { fprintf(stderr, "%s: Wrong read security\n" "Must be one of anyone, logged, " @@ -98,7 +111,8 @@ int main(int argc, char *argv[]) break; case 'w': write_sec = parse_security(optarg); - if (write_sec < 0) { + if (write_sec < 0) + { fprintf(stderr, "%s: Wrong write security\n" "Must be one of anyone, logged, " @@ -117,20 +131,24 @@ int main(int argc, char *argv[]) } } - if (object_type < 0) { + if (object_type < 0) + { fprintf(stderr, "%s: You must specify an object type\n", argv[0]); goto finished; } - if (object_name == NULL) { + if (object_name == NULL) + { fprintf(stderr, "%s: You must specify an object name\n", argv[0]); goto finished; } if (ncp_create_bindery_object(conn, object_type, object_name, - (write_sec << 4) + read_sec, 0) != 0) { + (write_sec << 4) + read_sec, 0) != 0) + { fprintf(stderr, "%s: Could not create the object\n", argv[0]); - } else { + } else + { result = 0; } diff --git a/util/nwbols.c b/util/nwbols.c index c551328..1ecdcca 100644 --- a/util/nwbols.c +++ b/util/nwbols.c @@ -15,13 +15,15 @@ static char *progname; -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [options] pattern\n", progname); return; } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options]\n", progname); @@ -39,7 +41,8 @@ static void help(void) "\n"); } -int main(int argc, char **argv) +int +main(int argc, char **argv) { struct ncp_conn *conn; struct ncp_bindery_object o; @@ -55,12 +58,15 @@ int main(int argc, char **argv) progname = argv[0]; - if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { com_err(argv[0], err, "when initializing"); return 1; } - while ((opt = getopt(argc, argv, "h?vt:o:")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?vt:o:")) != EOF) + { + switch (opt) + { case 'h': case '?': help(); @@ -80,26 +86,31 @@ int main(int argc, char **argv) } } - if (optind < argc) { + if (optind < argc) + { usage(); exit(1); } - for (p = pattern; *p != '\0'; p++) { + for (p = pattern; *p != '\0'; p++) + { *p = toupper(*p); } o.object_id = 0xffffffff; while (ncp_scan_bindery_object(conn, o.object_id, - type, pattern, &o) == 0) { + type, pattern, &o) == 0) + { found = 1; - if (verbose != 0) { + if (verbose != 0) + { printf("%s %08X %04X %d %02X %d\n", o.object_name, (unsigned int) o.object_id, (unsigned int) o.object_type, o.object_flags, o.object_security, o.object_has_prop); - } else { + } else + { printf("%s %08X %04X\n", o.object_name, (unsigned int) o.object_id, (unsigned int) o.object_type); diff --git a/util/nwboprops.c b/util/nwboprops.c index 0e91765..790850a 100644 --- a/util/nwboprops.c +++ b/util/nwboprops.c @@ -13,12 +13,14 @@ static char *progname; -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [options]\n", progname); } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options]\n", progname); @@ -36,7 +38,8 @@ static void help(void) "\n"); } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { struct ncp_conn *conn; char *object_name = NULL; @@ -51,12 +54,15 @@ int main(int argc, char *argv[]) progname = argv[0]; - if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { com_err(argv[0], err, "when initializing"); goto finished; } - while ((opt = getopt(argc, argv, "h?o:t:v")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?o:t:v")) != EOF) + { + switch (opt) + { case 'o': object_name = optarg; str_upper(object_name); @@ -77,12 +83,14 @@ int main(int argc, char *argv[]) } } - if (object_type < 0) { + if (object_type < 0) + { fprintf(stderr, "%s: You must specify an object type\n", argv[0]); goto finished; } - if (object_name == NULL) { + if (object_name == NULL) + { fprintf(stderr, "%s: You must specify an object name\n", argv[0]); goto finished; @@ -90,13 +98,16 @@ int main(int argc, char *argv[]) info.search_instance = 0xffffffff; while (ncp_scan_property(conn, object_type, object_name, - info.search_instance, "*", &info) == 0) { - if (verbose != 0) { + info.search_instance, "*", &info) == 0) + { + if (verbose != 0) + { printf("%s %d %02x %d\n", info.property_name, info.property_flags, info.property_security, info.value_available_flag); - } else { + } else + { printf("%s\n", info.property_name); } } diff --git a/util/nwborm.c b/util/nwborm.c index 88e911e..f0dc321 100644 --- a/util/nwborm.c +++ b/util/nwborm.c @@ -13,12 +13,14 @@ static char *progname; -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [options]\n", progname); } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options]\n", progname); @@ -35,7 +37,8 @@ static void help(void) "\n"); } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { struct ncp_conn *conn; char *object_name = NULL; @@ -48,12 +51,15 @@ int main(int argc, char *argv[]) progname = argv[0]; - if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { com_err(argv[0], err, "when initializing"); goto finished; } - while ((opt = getopt(argc, argv, "h?o:t:")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?o:t:")) != EOF) + { + switch (opt) + { case 'o': object_name = optarg; str_upper(object_name); @@ -71,19 +77,23 @@ int main(int argc, char *argv[]) } } - if (object_type < 0) { + if (object_type < 0) + { fprintf(stderr, "%s: You must specify an object type\n", argv[0]); goto finished; } - if (object_name == NULL) { + if (object_name == NULL) + { fprintf(stderr, "%s: You must specify an object name\n", argv[0]); goto finished; } - if (ncp_delete_bindery_object(conn, object_type, object_name) != 0) { + if (ncp_delete_bindery_object(conn, object_type, object_name) != 0) + { fprintf(stderr, "%s: Could not delete the object\n", argv[0]); - } else { + } else + { result = 0; } diff --git a/util/nwbpadd.c b/util/nwbpadd.c index adaaf52..77283fd 100644 --- a/util/nwbpadd.c +++ b/util/nwbpadd.c @@ -13,12 +13,14 @@ static char *progname; -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [options]\n", progname); } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options] [values]\n", progname); @@ -36,15 +38,16 @@ static void help(void) "value value to be added\n" "\n" "If property is of type SET, value is an object id (hex)\n" - "Otherwise, value is either a string value to be written, or\n" - "a count of bytes to be written. The latter is assumed if\n" - "more than one value argument is given. The count is decimal,\n" + "Otherwise, value is either a string value to be written, or\n" + "a count of bytes to be written. The latter is assumed if\n" + "more than one value argument is given. The count is decimal,\n" "and the following arguments are interpreted as bytes in\n" "hexadecimal notation.\n" "\n"); } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { struct ncp_conn *conn; char *object_name = NULL; @@ -58,12 +61,15 @@ int main(int argc, char *argv[]) progname = argv[0]; - if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { com_err(argv[0], err, "when initializing"); goto finished; } - while ((opt = getopt(argc, argv, "h?o:t:p:v:")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?o:t:p:v:")) != EOF) + { + switch (opt) + { case 'o': object_name = optarg; str_upper(object_name); @@ -73,7 +79,8 @@ int main(int argc, char *argv[]) break; case 'p': property_name = optarg; - if (strlen(property_name) > 15) { + if (strlen(property_name) > 15) + { fprintf(stderr, "%s: Property Name too long\n", argv[0]); exit(1); @@ -93,22 +100,26 @@ int main(int argc, char *argv[]) } } - if (object_type < 0) { + if (object_type < 0) + { fprintf(stderr, "%s: You must specify an object type\n", argv[0]); goto finished; } - if (object_name == NULL) { + if (object_name == NULL) + { fprintf(stderr, "%s: You must specify an object name\n", argv[0]); goto finished; } - if (property_name == NULL) { + if (property_name == NULL) + { fprintf(stderr, "%s: You must specify a property name\n", argv[0]); goto finished; } - if (optind > argc - 1) { + if (optind > argc - 1) + { fprintf(stderr, "%s: You must specify a property value\n", argv[0]); goto finished; @@ -117,35 +128,41 @@ int main(int argc, char *argv[]) optind += 1; if (ncp_scan_property(conn, object_type, object_name, - 0xffffffff, property_name, &info) != 0) { + 0xffffffff, property_name, &info) != 0) + { fprintf(stderr, "%s: Could not find property\n", argv[0]); goto finished; } - if ((info.property_flags & 2) != 0) { + if ((info.property_flags & 2) != 0) + { /* Property is of type SET */ struct ncp_bindery_object o; - if (optind != argc) { + if (optind != argc) + { fprintf(stderr, "%s: For the SET property %s, you must" " specify an object id as value\n", progname, property_name); goto finished; } if (ncp_get_bindery_object_name(conn, - ntohl(strtol(value, NULL, 16)), - &o) != 0) { + ntohl(strtol(value, NULL, 16)), + &o) != 0) + { fprintf(stderr, "%s: %s is not a valid object id\n", progname, value); goto finished; } if (ncp_add_object_to_set(conn, object_type, object_name, property_name, - o.object_type, o.object_name) != 0) { + o.object_type, o.object_name) != 0) + { fprintf(stderr, "%s: could not add object %s\n", progname, o.object_name); goto finished; } - } else { + } else + { /* Property is of type ITEM */ char contents[255 * 128]; int segno = 1; @@ -153,42 +170,50 @@ int main(int argc, char *argv[]) memset(contents, 0, sizeof(contents)); - if (optind == argc) { + if (optind == argc) + { /* value is the string to add */ length = strlen(value); - if (length >= sizeof(contents)) { + if (length >= sizeof(contents)) + { fprintf(stderr, "%s: Value too long\n", progname); goto finished; } strcpy(contents, value); - } else { + } else + { /* value is the byte count */ int i; length = atoi(value); - if (length >= sizeof(contents)) { + if (length >= sizeof(contents)) + { fprintf(stderr, "%s: Value too long\n", progname); goto finished; } - if (optind != argc - length) { + if (optind != argc - length) + { fprintf(stderr, "%s: Byte count does not match" " number of bytes\n", progname); goto finished; } i = 0; - while (optind < argc) { + while (optind < argc) + { contents[i] = strtol(argv[optind], NULL, 16); i += 1; optind += 1; } } - for (segno = 1; segno <= 255; segno++) { + for (segno = 1; segno <= 255; segno++) + { struct nw_property segment; int offset = (segno - 1) * 128; - if (offset > length) { + if (offset > length) + { /* everything written */ break; } @@ -197,7 +222,8 @@ int main(int argc, char *argv[]) if (ncp_write_property_value(conn, object_type, object_name, property_name, - segno, &segment) != 0) { + segno, &segment) != 0) + { fprintf(stderr, "%s: Could not write " "property\n", progname); goto finished; diff --git a/util/nwbpcreate.c b/util/nwbpcreate.c index b58d0b9..f7394da 100644 --- a/util/nwbpcreate.c +++ b/util/nwbpcreate.c @@ -13,12 +13,14 @@ static char *progname; -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [options]\n", progname); } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options]\n", progname); @@ -39,27 +41,34 @@ static void help(void) "\n"); } -static int parse_security(const char *security) +static int +parse_security(const char *security) { - if (strcasecmp(security, "anyone") == 0) { + if (strcasecmp(security, "anyone") == 0) + { return 0; } - if (strcasecmp(security, "logged") == 0) { + if (strcasecmp(security, "logged") == 0) + { return 1; } - if (strcasecmp(security, "object") == 0) { + if (strcasecmp(security, "object") == 0) + { return 2; } - if (strcasecmp(security, "supervisor") == 0) { + if (strcasecmp(security, "supervisor") == 0) + { return 3; } - if (strcasecmp(security, "netware") == 0) { + if (strcasecmp(security, "netware") == 0) + { return 4; } return -1; } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { struct ncp_conn *conn; char *object_name = NULL; @@ -76,12 +85,15 @@ int main(int argc, char *argv[]) progname = argv[0]; - if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { com_err(argv[0], err, "when initializing"); goto finished; } - while ((opt = getopt(argc, argv, "h?o:t:p:sr:w:")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?o:t:p:sr:w:")) != EOF) + { + switch (opt) + { case 'o': object_name = optarg; str_upper(object_name); @@ -91,7 +103,8 @@ int main(int argc, char *argv[]) break; case 'p': property_name = optarg; - if (strlen(property_name) > 15) { + if (strlen(property_name) > 15) + { fprintf(stderr, "%s: Property Name too long\n", argv[0]); exit(1); @@ -103,7 +116,8 @@ int main(int argc, char *argv[]) break; case 'r': read_sec = parse_security(optarg); - if (read_sec < 0) { + if (read_sec < 0) + { fprintf(stderr, "%s: Wrong read security\n" "Must be one of anyone, logged, " @@ -114,7 +128,8 @@ int main(int argc, char *argv[]) break; case 'w': write_sec = parse_security(optarg); - if (write_sec < 0) { + if (write_sec < 0) + { fprintf(stderr, "%s: Wrong write security\n" "Must be one of anyone, logged, " @@ -133,17 +148,20 @@ int main(int argc, char *argv[]) } } - if (object_type < 0) { + if (object_type < 0) + { fprintf(stderr, "%s: You must specify an object type\n", argv[0]); goto finished; } - if (object_name == NULL) { + if (object_name == NULL) + { fprintf(stderr, "%s: You must specify an object name\n", argv[0]); goto finished; } - if (property_name == NULL) { + if (property_name == NULL) + { fprintf(stderr, "%s: You must specify a property name\n", argv[0]); goto finished; @@ -151,9 +169,11 @@ int main(int argc, char *argv[]) if (ncp_create_property(conn, object_type, object_name, property_name, property_is_set ? 2 : 0, - (write_sec << 4) + read_sec) != 0) { + (write_sec << 4) + read_sec) != 0) + { fprintf(stderr, "%s: Could not create the property\n", argv[0]); - } else { + } else + { result = 0; } diff --git a/util/nwbprm.c b/util/nwbprm.c index 48c5fde..baa37b2 100644 --- a/util/nwbprm.c +++ b/util/nwbprm.c @@ -13,12 +13,14 @@ static char *progname; -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [options] [pattern]\n", progname); } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options]\n", progname); @@ -36,7 +38,8 @@ static void help(void) "\n"); } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { struct ncp_conn *conn; char *object_name = NULL; @@ -50,12 +53,15 @@ int main(int argc, char *argv[]) progname = argv[0]; - if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { com_err(argv[0], err, "when initializing"); goto finished; } - while ((opt = getopt(argc, argv, "h?o:t:p:")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?o:t:p:")) != EOF) + { + switch (opt) + { case 'o': object_name = optarg; str_upper(object_name); @@ -65,7 +71,8 @@ int main(int argc, char *argv[]) break; case 'p': property_name = optarg; - if (strlen(property_name) > 15) { + if (strlen(property_name) > 15) + { fprintf(stderr, "%s: Property Name too long\n", argv[0]); exit(1); @@ -82,25 +89,30 @@ int main(int argc, char *argv[]) } } - if (object_type < 0) { + if (object_type < 0) + { fprintf(stderr, "%s: You must specify an object type\n", argv[0]); goto finished; } - if (object_name == NULL) { + if (object_name == NULL) + { fprintf(stderr, "%s: You must specify an object name\n", argv[0]); goto finished; } - if (property_name == NULL) { + if (property_name == NULL) + { fprintf(stderr, "%s: You must specify a property name\n", argv[0]); goto finished; } if (ncp_delete_property(conn, object_type, object_name, - property_name) != 0) { + property_name) != 0) + { fprintf(stderr, "%s: Could not delete the property\n", argv[0]); - } else { + } else + { result = 0; } diff --git a/util/nwbpset.c b/util/nwbpset.c index eba285d..091a592 100644 --- a/util/nwbpset.c +++ b/util/nwbpset.c @@ -13,12 +13,14 @@ static char *progname; -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [options]\n", progname); } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options] [values]\n", progname); @@ -33,16 +35,18 @@ static void help(void) } static char * - get_line(char *buf, int len, FILE * stream) +get_line(char *buf, int len, FILE * stream) { char *result = fgets(buf, len, stream); - if (result != NULL) { + if (result != NULL) + { buf[strlen(buf) - 1] = '\0'; /* remove newline */ } return result; } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { struct ncp_conn *conn; char object_name[49]; @@ -57,12 +61,15 @@ int main(int argc, char *argv[]) progname = argv[0]; - if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { com_err(argv[0], err, "when initializing"); goto finished; } - while ((opt = getopt(argc, argv, "h?")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?")) != EOF) + { + switch (opt) + { case 'h': case '?': help(); @@ -74,88 +81,104 @@ int main(int argc, char *argv[]) } memset(buf, 0, sizeof(buf)); - if (get_line(buf, sizeof(buf), stdin) == NULL) { + if (get_line(buf, sizeof(buf), stdin) == NULL) + { fprintf(stderr, "Illegal format on stdin\n"); goto finished; } object_type = strtoul(buf, NULL, 16); memset(object_name, 0, sizeof(object_name)); - if (get_line(object_name, sizeof(object_name), stdin) == NULL) { + if (get_line(object_name, sizeof(object_name), stdin) == NULL) + { fprintf(stderr, "Illegal format on stdin\n"); goto finished; } memset(property_name, 0, sizeof(property_name)); - if (get_line(property_name, sizeof(property_name), stdin) == NULL) { + if (get_line(property_name, sizeof(property_name), stdin) == NULL) + { fprintf(stderr, "Illegal format on stdin\n"); goto finished; } memset(buf, 0, sizeof(buf)); - if (get_line(buf, sizeof(buf), stdin) == NULL) { + if (get_line(buf, sizeof(buf), stdin) == NULL) + { fprintf(stderr, "Illegal format on stdin\n"); goto finished; } property_flag = (atoi(buf) & 3); memset(buf, 0, sizeof(buf)); - if (get_line(buf, sizeof(buf), stdin) == NULL) { + if (get_line(buf, sizeof(buf), stdin) == NULL) + { fprintf(stderr, "Illegal format on stdin\n"); goto finished; } property_security = (strtoul(buf, NULL, 16) & 0xff); if (ncp_scan_property(conn, object_type, object_name, - 0xffffffff, property_name, &info) == 0) { + 0xffffffff, property_name, &info) == 0) + { /* Property already exists */ - if ((property_flag & 2) != (info.property_flags & 2)) { + if ((property_flag & 2) != (info.property_flags & 2)) + { fprintf(stderr, "Tried to write %s property\n", (property_flag & 2) != 0 ? "SET over existing ITEM" : "ITEM over existing SET"); goto finished; } - if (info.property_security != property_security) { + if (info.property_security != property_security) + { if (ncp_change_property_security(conn, object_type, object_name, property_name, - property_security) != 0) { + property_security) != 0) + { fprintf(stderr, "Could not change " "property security\n"); goto finished; } } - } else { + } else + { if (ncp_create_property(conn, object_type, object_name, property_name, property_flag, - property_security) != 0) { + property_security) != 0) + { fprintf(stderr, "Could not create property\n"); goto finished; } } - if ((property_flag & 2) == 0) { + if ((property_flag & 2) == 0) + { /* ITEM property */ - int i; + size_t i; int length; int segno; char property_value[255 * 128]; memset(property_value, 0, sizeof(property_value)); - for (i = 0; i < sizeof(property_value); i++) { - if (get_line(buf, sizeof(buf), stdin) == NULL) { + for (i = 0; i < sizeof(property_value); i++) + { + if (get_line(buf, sizeof(buf), stdin) == NULL) + { break; } property_value[i] = strtoul(buf, NULL, 16); } length = i - 1; - for (segno = 1; segno <= 255; segno++) { + for (segno = 1; segno <= 255; segno++) + { struct nw_property segment; int offset = (segno - 1) * 128; - if (offset > length) { + if (offset > length) + { /* everything written */ break; } @@ -164,30 +187,36 @@ int main(int argc, char *argv[]) if (ncp_write_property_value(conn, object_type, object_name, property_name, - segno, &segment) != 0) { + segno, &segment) != 0) + { fprintf(stderr, "Could not write property\n"); goto finished; } } - } else { + } else + { /* SET property */ - while (get_line(buf, sizeof(buf), stdin) != NULL) { + while (get_line(buf, sizeof(buf), stdin) != NULL) + { int element_type = strtoul(buf, NULL, 16); char element_name[49]; memset(element_name, 0, sizeof(element_name)); if (get_line(element_name, sizeof(element_name), - stdin) == NULL) { + stdin) == NULL) + { fprintf(stderr, "Illegal format on stdin\n"); goto finished; } if (ncp_add_object_to_set(conn, object_type, - object_name, property_name, + object_name, property_name, element_type, - element_name) != 0) { - if (conn->completion != 0xE9) { /* object already - in set */ + element_name) != 0) + { + if (conn->completion != 0xE9) /* object already + in set */ + { fprintf(stderr, "Could not add object " "to set\n"); goto finished; diff --git a/util/nwbpvalues.c b/util/nwbpvalues.c index 203f6ab..9245bff 100644 --- a/util/nwbpvalues.c +++ b/util/nwbpvalues.c @@ -17,12 +17,14 @@ static char *progname; static void print_property(char *prop_name, __u8 * val, int segments); -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [options]\n", progname); } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options]\n", progname); @@ -42,7 +44,8 @@ static void help(void) "\n"); } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { struct ncp_conn *conn; char *object_name = NULL; @@ -62,12 +65,15 @@ int main(int argc, char *argv[]) progname = argv[0]; - if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { com_err(argv[0], err, "when initializing"); goto finished; } - while ((opt = getopt(argc, argv, "h?o:t:p:vc")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?o:t:p:vc")) != EOF) + { + switch (opt) + { case 'o': object_name = optarg; str_upper(object_name); @@ -77,7 +83,8 @@ int main(int argc, char *argv[]) break; case 'p': property_name = optarg; - if (strlen(property_name) > 15) { + if (strlen(property_name) > 15) + { fprintf(stderr, "%s: Property Name too long\n", argv[0]); exit(1); @@ -100,77 +107,95 @@ int main(int argc, char *argv[]) } } - if (object_type < 0) { + if (object_type < 0) + { fprintf(stderr, "%s: You must specify an object type\n", argv[0]); goto finished; } - if (object_name == NULL) { + if (object_name == NULL) + { fprintf(stderr, "%s: You must specify an object name\n", argv[0]); goto finished; } - if (property_name == NULL) { + if (property_name == NULL) + { fprintf(stderr, "%s: You must specify a property name\n", argv[0]); goto finished; } if (ncp_scan_property(conn, object_type, object_name, - 0xffffffff, property_name, &info) != 0) { + 0xffffffff, property_name, &info) != 0) + { fprintf(stderr, "%s: Could not find property\n", argv[0]); goto finished; } segno = 1; while (ncp_read_property_value(conn, object_type, object_name, - segno, property_name, &segment) == 0) { + segno, property_name, &segment) == 0) + { memcpy(&(property_value[(segno - 1) * 128]), segment.value, 128); - if ((segment.more_flag == 0) || (segno == 255)) { + if ((segment.more_flag == 0) || (segno == 255)) + { break; } segno += 1; } - if (canonical != 0) { + if (canonical != 0) + { printf("%-4.4x\n%s\n", object_type, object_name); printf("%s\n%d\n%x\n", info.property_name, info.property_flags, info.property_security); } - if ((info.property_flags & 2) == 0) { + if ((info.property_flags & 2) == 0) + { /* ITEM property */ - if (canonical != 0) { + if (canonical != 0) + { int i; - for (i = 0; i < segno * 128; i++) { + for (i = 0; i < segno * 128; i++) + { printf("%-2.2x\n", property_value[i]); } - } else { + } else + { print_property(property_name, property_value, segno); } - } else { + } else + { int objects = 32 * segno; __u32 *value = (__u32 *) property_value; int i = 0; - while (i < objects) { + while (i < objects) + { struct ncp_bindery_object o; - if ((value[i] == 0) || (value[i] == 0xffffffff)) { + if ((value[i] == 0) || (value[i] == 0xffffffff)) + { /* Continue with next segment */ i = ((i / 32) + 1) * 32; continue; } if (ncp_get_bindery_object_name(conn, ntohl(value[i]), - &o) == 0) { - if (canonical != 0) { + &o) == 0) + { + if (canonical != 0) + { printf("%-4.4x\n%s\n", - (unsigned int) o.object_type, + (unsigned int) o.object_type, o.object_name); - } else if (verbose != 0) { + } else if (verbose != 0) + { printf("%s %08X %04X\n", o.object_name, (unsigned int) o.object_id, - (unsigned int) o.object_type); - } else { + (unsigned int) o.object_type); + } else + { printf("%s\n", o.object_name); } } @@ -184,20 +209,25 @@ int main(int argc, char *argv[]) return result; } -static void print_unknown(__u8 * val) +static void +print_unknown(__u8 * val) { int j = (128 / 16); - while (1) { + while (1) + { int i; - for (i = 0; i < 16; i++) { + for (i = 0; i < 16; i++) + { printf("%02X ", val[i]); } printf(" ["); - for (i = 0; i < 16; i++) { + for (i = 0; i < 16; i++) + { printf("%c", isprint(val[i]) ? val[i] : '.'); } j -= 1; - if (j == 0) { + if (j == 0) + { printf("]\n"); return; } @@ -206,24 +236,29 @@ static void print_unknown(__u8 * val) } } -static void print_string(__u8 * val) +static void +print_string(__u8 * val) { puts(val); } static char * - print_station_addr(char *fmt, struct ncp_station_addr *addr, char *buff) +print_station_addr(const char *fmt, const struct ncp_station_addr *addr, char *buff) { char *ret = buff; - while (*fmt != 0) { - switch (*fmt) { + while (*fmt != 0) + { + switch (*fmt) + { case '%': - switch (*(++fmt)) { + switch (*(++fmt)) + { case 'N': /* node */ { int i; - for (i = 0; i < 6; buff += 2, i++) { + for (i = 0; i < 6; buff += 2, i++) + { sprintf(buff, "%02X", addr->Node[i]); } } @@ -233,7 +268,7 @@ static char * buff += 4; break; case 'L': /* Lan */ - sprintf(buff, "%08lX", htonl(addr->NetWork)); + sprintf(buff, "%08X", (u_int32_t)htonl(addr->NetWork)); buff += 8; break; case '%': @@ -241,7 +276,8 @@ static char * default: break; } - if (*fmt) { + if (*fmt) + { fmt++; } break; @@ -253,35 +289,41 @@ static char * return ret; } -void print_login_control(__u8 * val) +void +print_login_control(__u8 * val) { int i, j, mask; char buff[32]; struct ncp_prop_login_control *a = (struct ncp_prop_login_control *) val; - static char *days[] + static const char *days[] = {"Sun", "Mon", "Tue", "Wen", "Thu", "Fri", "Sat"}; if (a->LastLogin[2] || a->LastLogin[1] || a->LastLogin[0] || - a->LastLogin[3] || a->LastLogin[4] || a->LastLogin[5]) { + a->LastLogin[3] || a->LastLogin[4] || a->LastLogin[5]) + { printf("Last Login: %d.%d.%02d at %2d:%02d:%02d\n", a->LastLogin[2], a->LastLogin[1], a->LastLogin[0], a->LastLogin[3], a->LastLogin[4], a->LastLogin[5]); - } else { + } else + { printf("Never logged in\n"); } - if (a->Disabled != 0) { + if (a->Disabled != 0) + { printf(" --- Account disabled ---\n"); } if (a->AccountExpireDate[2] || a->AccountExpireDate[1] || - a->AccountExpireDate[0]) { + a->AccountExpireDate[0]) + { printf("Account expires on: %d.%d.%d\n", a->AccountExpireDate[2], a->AccountExpireDate[1], a->AccountExpireDate[0]); } if (a->PasswordExpireDate[2] || a->PasswordExpireDate[1] || - a->PasswordExpireDate[0]) { + a->PasswordExpireDate[0]) + { printf("Password expires on: %d.%d.%d\n", a->PasswordExpireDate[2], a->PasswordExpireDate[1], @@ -291,51 +333,64 @@ void print_login_control(__u8 * val) printf("PasswortChangeInterval : %d days\n", ntohs(a->PasswordExpireInterval)); } - if ((a->RestrictionMask & 2) != 0) { + if ((a->RestrictionMask & 2) != 0) + { printf("New password must be different when changing\n"); } - if ((a->RestrictionMask & 1) != 0) { + if ((a->RestrictionMask & 1) != 0) + { printf("User ist not allowed to change password\n"); } printf("Minimal password length : %d\n", a->MinPasswordLength); - if (ntohs(a->MaxConnections) != 0) { + if (ntohs(a->MaxConnections) != 0) + { printf("Maximum no of connections: %d\n", ntohs(a->MaxConnections)); } - if (a->MaxDiskUsage != 0xFFFFFF7FL) { - printf("Maximum DiskQuota : %8ld blocks\n", - ntohl(a->MaxDiskUsage)); + if (a->MaxDiskUsage != 0xFFFFFF7FL) + { + printf("Maximum DiskQuota : %8d blocks\n", + (u_int32_t)ntohl(a->MaxDiskUsage)); } printf("Failed Logins: %5d\n", ntohs(a->BadLoginCount)); - if (a->BadLoginCountDown != 0L) { - printf("Account disabled still %8ld seconds\n", - ntohl(a->BadLoginCountDown)); + if (a->BadLoginCountDown != 0L) + { + printf("Account disabled still %8d seconds\n", + (u_int32_t)ntohl(a->BadLoginCountDown)); } - if (a->LastIntruder.NetWork != 0L) { + if (a->LastIntruder.NetWork != 0L) + { printf("Last \'intruder\' address: %s\n", print_station_addr("(%L): %N[%S]", &(a->LastIntruder), buff)); } - if (a->RestrictionMask & 0xFC) { + if (a->RestrictionMask & 0xFC) + { printf("RestrictionMask : %02X\n", a->RestrictionMask); } - for (i = 0; i < 42; i++) { - if (a->ConnectionTimeMask[i] != 0xFF) { + for (i = 0; i < 42; i++) + { + if (a->ConnectionTimeMask[i] != 0xFF) + { i = 101; } } - if (i < 100) { + if (i < 100) + { return; } val = a->ConnectionTimeMask; printf("Time restrictions: 1 1 1 1 1 1 1 1 1 1 2 2 2 2 ]\n"); printf(" Day [0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 ]\n"); - for (i = 0; i < 7; i++) { + for (i = 0; i < 7; i++) + { printf(" %s [", days[i]); - for (j = 0; j < 6; j++) { - for (mask = 1; mask < 0x100; mask <<= 1) { + for (j = 0; j < 6; j++) + { + for (mask = 1; mask < 0x100; mask <<= 1) + { putchar((*val & mask) ? '*' : ' '); } val++; @@ -344,7 +399,8 @@ void print_login_control(__u8 * val) } } -void print_addr(__u8 * val) +void +print_addr(__u8 * val) { char buff[50]; print_station_addr("(%L): %N[%S]", @@ -352,11 +408,12 @@ void print_addr(__u8 * val) printf("%s\n", buff); } -static struct { - char *pname; +static const struct +{ + const char *pname; void (*func) (__u8 *); -} formats[] = - +} +formats[] = { { "DESCRIPTION", print_string @@ -395,23 +452,28 @@ static struct { } }; -static void print_property(char *prop_name, __u8 * val, int segments) +static void +print_property(char *prop_name, __u8 * val, int segments) { int i; void (*f) (__u8 *); - for (i = 0; formats[i].pname != NULL; i++) { - if (strcasecmp(prop_name, formats[i].pname) == 0) { + for (i = 0; formats[i].pname != NULL; i++) + { + if (strcasecmp(prop_name, formats[i].pname) == 0) + { break; } } f = formats[i].func; - if (f != NULL) { + if (f != NULL) + { f(val); return; } - for (i = 0; i < segments; i++) { + for (i = 0; i < segments; i++) + { printf("Segment: %03d\n", i + 1); print_unknown(&(val[i * 128])); printf("\n"); diff --git a/util/nwfsinfo.c b/util/nwfsinfo.c index b15910e..af0ebec 100644 --- a/util/nwfsinfo.c +++ b/util/nwfsinfo.c @@ -14,12 +14,14 @@ static char *progname; -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [pattern]\n", progname); } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options]\n", progname); @@ -33,7 +35,8 @@ static void help(void) "\n"); } -static void print_info(struct ncp_file_server_info *info) +static void +print_info(struct ncp_file_server_info *info) { printf("\n"); printf("Fileservername %-48.48s\n", info->ServerName); @@ -67,7 +70,8 @@ static void print_info(struct ncp_file_server_info *info) return; } -int main(int argc, char **argv) +int +main(int argc, char **argv) { struct ncp_conn *conn; int opt; @@ -75,12 +79,15 @@ int main(int argc, char **argv) progname = argv[0]; - if ((conn = ncp_initialize(&argc, argv, 0, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 0, &err)) == NULL) + { com_err(argv[0], err, "when initializing"); return 1; } - while ((opt = getopt(argc, argv, "h?dti")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?dti")) != EOF) + { + switch (opt) + { case 'h': case '?': help(); @@ -91,15 +98,18 @@ int main(int argc, char **argv) char *s; if (ncp_get_file_server_description_strings(conn, - strings) - != 0) { + strings) + != 0) + { perror("could not get strings"); ncp_close(conn); return 1; } s = strings; - while (s < strings + 512) { - if (strlen(s) == 0) { + while (s < strings + 512) + { + if (strlen(s) == 0) + { break; } puts(s); @@ -111,7 +121,8 @@ int main(int argc, char **argv) { time_t t; - if (ncp_get_file_server_time(conn, &t) != 0) { + if (ncp_get_file_server_time(conn, &t) != 0) + { perror("could not get server time"); ncp_close(conn); return 1; @@ -122,7 +133,8 @@ int main(int argc, char **argv) case 'i': { struct ncp_file_server_info info; - if (ncp_get_file_server_information(conn, &info) != 0) { + if (ncp_get_file_server_information(conn, &info) != 0) + { perror("Could not get server information"); ncp_close(conn); return 1; diff --git a/util/nwfstime.c b/util/nwfstime.c index c1e53a2..eb9f152 100644 --- a/util/nwfstime.c +++ b/util/nwfstime.c @@ -13,12 +13,14 @@ static char *progname; -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [pattern]\n", progname); } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options]\n", progname); @@ -34,7 +36,8 @@ static void help(void) "\n"); } -int main(int argc, char **argv) +int +main(int argc, char **argv) { struct ncp_conn *conn; int opt; @@ -44,12 +47,15 @@ int main(int argc, char **argv) progname = argv[0]; - if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { com_err(argv[0], err, "when initializing"); return 1; } - while ((opt = getopt(argc, argv, "h?s")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?s")) != EOF) + { + switch (opt) + { case 'h': case '?': help(); @@ -65,15 +71,19 @@ int main(int argc, char **argv) finished: - if (set != 0) { + if (set != 0) + { time(&t); - if ((err = ncp_set_file_server_time(conn, &t)) != 0) { + if ((err = ncp_set_file_server_time(conn, &t)) != 0) + { com_err(argv[0], err, "when setting file server time"); ncp_close(conn); return 1; } - } else { - if ((err = ncp_get_file_server_time(conn, &t)) != 0) { + } else + { + if ((err = ncp_get_file_server_time(conn, &t)) != 0) + { com_err(argv[0], err, "when getting file server time"); ncp_close(conn); return 1; diff --git a/util/nwgrant.c b/util/nwgrant.c index 7394474..1226fed 100644 --- a/util/nwgrant.c +++ b/util/nwgrant.c @@ -13,12 +13,14 @@ static char *progname; -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [options]\n", progname); } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options] file/directory\n", progname); @@ -38,7 +40,8 @@ static void help(void) "\n"); } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { struct ncp_conn *conn; char *object_name = NULL; @@ -52,12 +55,15 @@ int main(int argc, char *argv[]) progname = argv[0]; - if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { com_err(argv[0], err, "when initializing"); goto finished; } - while ((opt = getopt(argc, argv, "h?o:t:r:")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?o:t:r:")) != EOF) + { + switch (opt) + { case 'o': object_name = optarg; str_upper(object_name); @@ -78,34 +84,40 @@ int main(int argc, char *argv[]) } } - if (object_type < 0) { + if (object_type < 0) + { fprintf(stderr, "%s: You must specify an object type\n", argv[0]); goto finished; } - if (object_name == NULL) { + if (object_name == NULL) + { fprintf(stderr, "%s: You must specify an object name\n", argv[0]); goto finished; } - if (rights < 0) { + if (rights < 0) + { fprintf(stderr, "%s: You must specify a rights mask\n", progname); goto finished; } - if (optind != argc - 1) { + if (optind != argc - 1) + { fprintf(stderr, "%s: You must specify a directory\n", progname); goto finished; } path = argv[optind]; - if (ncp_get_bindery_object_id(conn, object_type, object_name, &o) != 0) { + if (ncp_get_bindery_object_id(conn, object_type, object_name, &o) != 0) + { fprintf(stderr, "%s: Could not find object %s\n", progname, object_name); goto finished; } - if (ncp_add_trustee(conn, 0, path, o.object_id, rights) != 0) { + if (ncp_add_trustee(conn, 0, path, o.object_id, rights) != 0) + { fprintf(stderr, "%s: Could not add trustee rights\n", progname); goto finished; } diff --git a/util/nwmsg.c b/util/nwmsg.c new file mode 100644 index 0000000..6fc9089 --- /dev/null +++ b/util/nwmsg.c @@ -0,0 +1,215 @@ +/* + * nwmsg.c + * + * Fetch NetWare broadcast messages and write to the user + * + * Copyright (C) 1996 by Volker Lendecke + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ncplib.h" +#include + +static int search_utmp(char *user, char *tty); + +static char *progname; + +int +main(int argc, char *argv[]) +{ + struct ncp_conn *conn; + char message[256]; + char *mount_point; + struct ncp_fs_info info; + struct passwd *pwd; + char tty[256]; + char tty_path[256]; + FILE *tty_file; + FILE *mtab; + struct mntent *mnt; + long err; + + + progname = argv[0]; + + openlog("nwmsg", LOG_PID, LOG_LPR); + + if (argc != 2) + { + fprintf(stderr, "usage: %s mount-point\n", + progname); + exit(1); + } + mount_point = argv[1]; + if ((err = ncp_open_mount(mount_point, &conn)) != 0) + { + com_err(progname, err, "in ncp_open_mount"); + exit(1); + } + if (ncp_get_broadcast_message(conn, message) != 0) + { + fprintf(stderr, "%s: could not get broadcast message\n", + progname); + ncp_close(conn); + exit(1); + } + if (strlen(message) == 0) + { + syslog(LOG_DEBUG, "no message"); + exit(0); + } +#if 0 + syslog(LOG_DEBUG, "message: %s", message); +#endif + + info.version = NCP_GET_FS_INFO_VERSION; + if (ioctl(conn->mount_fid, NCP_IOC_GET_FS_INFO, &info) < 0) + { + fprintf(stderr, "%s: could not ioctl on connection: %s\n", + progname, strerror(errno)); + ncp_close(conn); + exit(1); + } + ncp_close(conn); + + if ((pwd = getpwuid(info.mounted_uid)) == NULL) + { + fprintf(stderr, "%s: user %d not known\n", + progname, info.mounted_uid); + exit(1); + } + if ((mtab = fopen(MOUNTED, "r")) == NULL) + { + fprintf(stderr, "%s: can't open %s\n", + progname, MOUNTED); + exit(1); + } + while ((mnt = getmntent(mtab)) != NULL) + { + if (strcmp(mnt->mnt_dir, mount_point) == 0) + { + break; + } + } + + if (mnt == NULL) + { + syslog(LOG_DEBUG, "cannot find mtab entry\n"); + } + if (search_utmp(pwd->pw_name, tty) != 0) + { + exit(1); + } + sprintf(tty_path, "/dev/%s", tty); + if ((tty_file = fopen(tty_path, "w")) == NULL) + { + fprintf(stderr, "%s: cannot open %s: %s\n", + progname, tty_path, strerror(errno)); + exit(1); + } + fprintf(tty_file, "\r\n\007\007\007Message from NetWare Server: %s\r\n", + mnt->mnt_fsname); + fprintf(tty_file, "%s\r\n", message); + fclose(tty_file); + fclose(mtab); + return 0; +} + +/* The following routines have been taken from util-linux-2.5's write.c */ + +/* + * term_chk - check that a terminal exists, and get the message bit + * and the access time + */ +static int +term_chk(char *tty, int *msgsokP, time_t * atimeP, int *showerror) +{ + struct stat s; + char path[MAXPATHLEN]; + + (void) sprintf(path, "/dev/%s", tty); + if (stat(path, &s) < 0) + { + if (showerror) + (void) fprintf(stderr, + "write: %s: %s\n", path, strerror(errno)); + return (1); + } + *msgsokP = (s.st_mode & (S_IWRITE >> 3)) != 0; /* group write bit */ + *atimeP = s.st_atime; + return (0); +} + +/* + * search_utmp - search utmp for the "best" terminal to write to + * + * Ignores terminals with messages disabled, and of the rest, returns + * the one with the most recent access time. Returns as value the number + * of the user's terminals with messages enabled, or -1 if the user is + * not logged in at all. + * + * Special case for writing to yourself - ignore the terminal you're + * writing from, unless that's the only terminal with messages enabled. + */ +static int +search_utmp(char *user, char *tty) +{ + struct utmp u; + time_t bestatime, atime; + int ufd, nloggedttys, nttys, msgsok, user_is_me; + + char atty[sizeof(u.ut_line) + 1]; + + if ((ufd = open(_PATH_UTMP, O_RDONLY)) < 0) + { + perror("utmp"); + return -1; + } + nloggedttys = nttys = 0; + bestatime = 0; + user_is_me = 0; + while (read(ufd, (char *) &u, sizeof(u)) == sizeof(u)) + if (strncmp(user, u.ut_name, sizeof(u.ut_name)) == 0) + { + ++nloggedttys; + + (void) strncpy(atty, u.ut_line, sizeof(u.ut_line)); + atty[sizeof(u.ut_line)] = '\0'; + + if (term_chk(atty, &msgsok, &atime, 0)) + continue; /* bad term? skip */ + if (!msgsok) + continue; /* skip ttys with msgs off */ + + if (u.ut_type != USER_PROCESS) + continue; /* it's not a valid entry */ + + ++nttys; + if (atime > bestatime) + { + bestatime = atime; + (void) strcpy(tty, atty); + } + } + (void) close(ufd); + if (nloggedttys == 0) + { + (void) fprintf(stderr, "write: %s is not logged in\n", user); + return -1; + } + return 0; +} diff --git a/util/nwpasswd.c b/util/nwpasswd.c index d6bedc1..2ef6234 100644 --- a/util/nwpasswd.c +++ b/util/nwpasswd.c @@ -13,12 +13,14 @@ static char *progname; -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [options]\n", progname); } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options]\n", progname); @@ -32,7 +34,8 @@ static void help(void) } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { struct ncp_conn_spec *spec; struct ncp_conn *conn; @@ -53,8 +56,10 @@ int main(int argc, char *argv[]) progname = argv[0]; - while ((opt = getopt(argc, argv, "h?S:U:O:t:")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?S:U:O:t:")) != EOF) + { + switch (opt) + { case 'S': server = optarg; break; @@ -79,13 +84,16 @@ int main(int argc, char *argv[]) spec = ncp_find_conn_spec(server, user_name, "", 1, getuid(), &err); - if (spec == NULL) { + if (spec == NULL) + { com_err(argv[0], err, "trying to find server"); exit(1); } - if (!object_name) { + if (!object_name) + { object_name = spec->user; - } else { + } else + { strcpy(buf_obj_name, object_name); object_name = buf_obj_name; str_upper(object_name); @@ -95,28 +103,33 @@ int main(int argc, char *argv[]) printf("Changing password for user %s on server %s\n", object_name, spec->server); - if (object_name == spec->user) { + if (object_name == spec->user) + { str = getpass("Enter old password: "); - } else { + } else + { char sx[80]; sprintf(sx, "Enter password for %s: ", spec->user); str = getpass(sx); } - if (strlen(str) >= sizeof(oldpass)) { + if (strlen(str) >= sizeof(oldpass)) + { printf("Password too long\n"); exit(1); } strcpy(oldpass, str); str = getpass("Enter new password: "); - if (strlen(str) >= sizeof(newpass1)) { + if (strlen(str) >= sizeof(newpass1)) + { printf("Password too long\n"); exit(1); } strcpy(newpass1, str); str = getpass("Re-Enter new password: "); - if (strlen(str) >= sizeof(newpass2)) { + if (strlen(str) >= sizeof(newpass2)) + { printf("Password too long\n"); exit(1); } @@ -126,22 +139,27 @@ int main(int argc, char *argv[]) str_upper(newpass1); str_upper(newpass2); - if (strcmp(newpass1, newpass2) != 0) { + if (strcmp(newpass1, newpass2) != 0) + { printf("You mistype the new password, try again\n"); exit(1); } strcpy(spec->password, oldpass); - if ((conn = ncp_open(spec, &err)) == NULL) { + if ((conn = ncp_open(spec, &err)) == NULL) + { com_err(argv[0], err, "when trying to open connection"); exit(1); } - if (object_name != spec->user) { + if (object_name != spec->user) + { if (!(err = ncp_get_bindery_object_id(conn, 1, spec->user, &user)) - && !(err = ncp_login_user(conn, spec->user, oldpass))) { + && !(err = ncp_login_user(conn, spec->user, oldpass))) + { *oldpass = '\0'; - } else { + } else + { com_err(argv[0], err, "not own password"); } } @@ -149,7 +167,8 @@ int main(int argc, char *argv[]) || ((err = ncp_get_bindery_object_id(conn, 1, object_name, &user)) != 0) || ((err = ncp_change_login_passwd(conn, &user, ncp_key, - oldpass, newpass1)) != 0)) { + oldpass, newpass1)) != 0)) + { com_err(argv[0], err, "trying to change password"); } ncp_close(conn); diff --git a/util/nwpurge.c b/util/nwpurge.c new file mode 100644 index 0000000..a6c7ad8 --- /dev/null +++ b/util/nwpurge.c @@ -0,0 +1,127 @@ +#include +#include + +void usage(void) { + printf( +"usage: nwpurge [options] [directory]\n" +"\n" +"-h Print this help text\n" +"-a Purge files in subdirectories\n" +"-l Do not purge files\n" +"-s Silent mode\n" +"\n" +"directory Directory to purge\n" +"\n" +); +} + +int subdirs = 0; +int show = 1; +int purge = 1; +int files = 0; +int failures = 0; + +void processpurge(struct ncp_conn* conn, int volume, __u32 directory_id) { + struct ncp_deleted_file info; + char tmp[1024]; + + if (show) { + if (!ncp_ns_get_full_name(conn, NW_NS_DOS, NW_NS_DOS, + 1, volume, directory_id, NULL, 0, + tmp, sizeof(tmp))) { + printf("%s\n", tmp); + } + } + + info.seq = -1; + while (!ncp_ns_scan_salvageable_file(conn, NW_NS_DOS, + 1, volume, directory_id, NULL, 0, + &info, tmp, sizeof(tmp))) { + if (show) { + printf("%8s%s\n", "", tmp); + } + files++; + if (purge) { + if (ncp_ns_purge_file(conn, &info)) { + failures++; + if (!show) { + printf("%8s%s\n", "", tmp); + } + printf("%8s-- failed\n", ""); + } + } + } + if (show) printf("\n"); + if (subdirs) { + struct nw_info_struct dir; + struct ncp_search_seq seq; + + dir.volNumber = volume; + dir.DosDirNum = directory_id; + if (!ncp_initialize_search(conn, &dir, NW_NS_DOS, &seq)) { + while (!ncp_search_for_file_or_subdir2(conn, + SA_SUBDIR_ALL, + /* RIM_ATTRIBUTES | */ RIM_DIRECTORY, + &seq, + &dir)) { + processpurge(conn, dir.volNumber, dir.DosDirNum); + } + } + + } +} + +int main(int argc, char* argv[]) { + const char* path; + struct ncp_conn* conn; + int err; + int c; + + while ((c = getopt(argc, argv, "ahls")) != -1) { + switch (c) { + case '?': + case ':':break; + case 'a':subdirs = 1; + break; + case 'h':usage(); exit(2); + case 'l':purge = 0; + break; + case 's':show = 0; + break; + default: fprintf(stderr, "Unexpected option `-%c'\n", c); + break; + } + } + if (optind < argc) { + path = argv[optind++]; + } else { + path = "."; + } + err = ncp_open_mount(path, &conn); + if (err) { + com_err("nwpurge", err, "in ncp_open_mount"); + exit(1); + } + processpurge(conn, conn->i.volume_number, conn->i.directory_id); + + files = files-failures; + if (!files) { + printf("No files were"); + } else if (files == 1) { + printf("1 file was"); + } else { + printf("%d files were", files); + } + printf(" purged from server.\n"); + if (failures) { + if (failures == 1) { + printf("1 file was not purged due to error."); + } else { + printf("%d files were not purged due to errors.", failures); + } + } + + ncp_close(conn); + return 0; +} + diff --git a/util/nwrevoke.c b/util/nwrevoke.c index 91e83b3..e2a5e65 100644 --- a/util/nwrevoke.c +++ b/util/nwrevoke.c @@ -13,12 +13,14 @@ static char *progname; -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [options]\n", progname); } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options] file/directory\n", progname); @@ -37,7 +39,8 @@ static void help(void) "\n"); } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { struct ncp_conn *conn; char *object_name = NULL; @@ -50,12 +53,15 @@ int main(int argc, char *argv[]) progname = argv[0]; - if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { com_err(argv[0], err, "when initializing"); goto finished; } - while ((opt = getopt(argc, argv, "h?o:t:")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?o:t:")) != EOF) + { + switch (opt) + { case 'o': object_name = optarg; str_upper(object_name); @@ -73,29 +79,34 @@ int main(int argc, char *argv[]) } } - if (object_type < 0) { + if (object_type < 0) + { fprintf(stderr, "%s: You must specify an object type\n", argv[0]); goto finished; } - if (object_name == NULL) { + if (object_name == NULL) + { fprintf(stderr, "%s: You must specify an object name\n", argv[0]); goto finished; } - if (optind != argc - 1) { + if (optind != argc - 1) + { fprintf(stderr, "%s: You must specify a directory\n", progname); goto finished; } path = argv[optind]; - if (ncp_get_bindery_object_id(conn, object_type, object_name, &o) != 0) { + if (ncp_get_bindery_object_id(conn, object_type, object_name, &o) != 0) + { fprintf(stderr, "%s: Could not find object %s\n", progname, object_name); goto finished; } - if (ncp_delete_trustee(conn, 0, path, o.object_id) != 0) { + if (ncp_delete_trustee(conn, 0, path, o.object_id) != 0) + { fprintf(stderr, "%s: Could not remove trustee rights\n", progname); goto finished; diff --git a/util/nwrights.c b/util/nwrights.c index 11fb9f5..b632875 100644 --- a/util/nwrights.c +++ b/util/nwrights.c @@ -13,12 +13,14 @@ static char *progname; -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [options]\n", progname); } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options] file/directory\n", progname); @@ -29,10 +31,11 @@ static void help(void) "\n"); } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { struct ncp_conn *conn = NULL; - char *path = "."; + const char *path = "."; long err; int result = 1; int opt; @@ -40,8 +43,10 @@ int main(int argc, char *argv[]) progname = argv[0]; - while ((opt = getopt(argc, argv, "h?")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?")) != EOF) + { + switch (opt) + { case 'h': case '?': help(); @@ -52,21 +57,25 @@ int main(int argc, char *argv[]) } } - if (optind > argc) { + if (optind > argc) + { usage(); goto finished; } - if (optind == argc - 1) { + if (optind == argc - 1) + { path = argv[optind]; } - if ((conn = ncp_open_mount(path, &err)) == NULL) { + if ((err = ncp_open_mount(path, &conn)) != 0) + { com_err(argv[0], err, "when initializing"); goto finished; } if ((err = ncp_get_eff_directory_rights(conn, 0, 0, 0x8006, conn->i.volume_number, - conn->i.directory_id, NULL, - &rights)) != 0) { + conn->i.directory_id, NULL, + &rights)) != 0) + { com_err(argv[0], err, "when finding rights"); goto finished; } @@ -81,28 +90,36 @@ int main(int argc, char *argv[]) ((rights & NCP_PERM_SEARCH) != 0) ? 'F' : ' ', ((rights & NCP_PERM_OWNER) != 0) ? 'A' : ' '); - if ((rights & NCP_PERM_SUPER) != 0) { + if ((rights & NCP_PERM_SUPER) != 0) + { printf("(S): You have SUPERVISOR rights\n"); } - if ((rights & NCP_PERM_READ) != 0) { + if ((rights & NCP_PERM_READ) != 0) + { printf("(R): You may READ from files\n"); } - if ((rights & NCP_PERM_WRITE) != 0) { + if ((rights & NCP_PERM_WRITE) != 0) + { printf("(W): You may WRITE to files\n"); } - if ((rights & NCP_PERM_CREATE) != 0) { + if ((rights & NCP_PERM_CREATE) != 0) + { printf("(C): You may CREATE files\n"); } - if ((rights & NCP_PERM_DELETE) != 0) { + if ((rights & NCP_PERM_DELETE) != 0) + { printf("(E): You may ERASE files\n"); } - if ((rights & NCP_PERM_MODIFY) != 0) { + if ((rights & NCP_PERM_MODIFY) != 0) + { printf("(M): You may MODIFY directory\n"); } - if ((rights & NCP_PERM_SEARCH) != 0) { + if ((rights & NCP_PERM_SEARCH) != 0) + { printf("(F): You may SCAN for files\n"); } - if ((rights & NCP_PERM_OWNER) != 0) { + if ((rights & NCP_PERM_OWNER) != 0) + { printf("(A): You may change ACCESS control\n"); } result = 0; diff --git a/util/nwtrustee.c b/util/nwtrustee.c index 6ab9524..c253d43 100644 --- a/util/nwtrustee.c +++ b/util/nwtrustee.c @@ -15,13 +15,15 @@ static char *progname; -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [options] pattern\n", progname); return; } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options]\n", progname); @@ -42,7 +44,8 @@ static void help(void) "\n"); } -int fromhex(char c) +int +fromhex(char c) { c -= '0'; if (c > 9) @@ -50,7 +53,8 @@ int fromhex(char c) return c & 15; } -int main(int argc, char **argv) +int +main(int argc, char **argv) { struct ncp_conn *conn; struct ncp_bindery_object bobj; @@ -65,12 +69,15 @@ int main(int argc, char **argv) progname = argv[0]; - if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { com_err(argv[0], err, "when initializing"); return 1; } - while ((opt = getopt(argc, argv, "h?vl:L:o:O:t:")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?vl:L:o:O:t:")) != EOF) + { + switch (opt) + { case 'h': case '?': help(); @@ -79,7 +86,8 @@ int main(int argc, char **argv) vid = atoi(optarg); break; case 'L': - if (ncp_get_volume_number(conn, optarg, &vid)) { + if (ncp_get_volume_number(conn, optarg, &vid)) + { ncp_close(conn); return 1; } @@ -87,16 +95,19 @@ int main(int argc, char **argv) case 'o': oid = 0; - while (*optarg) { + while (*optarg) + { oid = (oid << 4) | fromhex(*optarg); optarg++; } break; case 'O': - for (p = optarg; *p != 0; p++) { + for (p = optarg; *p != 0; p++) + { *p = toupper(*p); } - if (ncp_get_bindery_object_id(conn, type, optarg, &bobj)) { + if (ncp_get_bindery_object_id(conn, type, optarg, &bobj)) + { ncp_close(conn); return 1; } @@ -114,25 +125,30 @@ int main(int argc, char **argv) } } - if (optind < argc) { + if (optind < argc) + { usage(); exit(1); } nextp = 0; - while (!ncp_get_trustee(conn, oid, vid, ppath, &trust, &nextp)) { + while (!ncp_get_trustee(conn, oid, vid, ppath, &trust, &nextp)) + { if (!nextp) break; printf("%s ", ppath); - if (verbose) { + if (verbose) + { strcpy(ppath, "[ R W O C E A F M ]"); p = ppath + 2; - for (type = 1; type < 256; type <<= 1) { + for (type = 1; type < 256; type <<= 1) + { if (!(trust & type)) *p = ' '; p += 2; } printf("%s\n", ppath); - } else { + } else + { printf("%X\n", trust); } } diff --git a/util/nwuserlist.c b/util/nwuserlist.c index fc7fb04..43ad78c 100644 --- a/util/nwuserlist.c +++ b/util/nwuserlist.c @@ -13,22 +13,26 @@ static char *progname; -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [pattern]\n", progname); } -static void str_trim_right(char *s, char c) +static void +str_trim_right(char *s, char c) { int len = strlen(s) - 1; - while ((len > 0) && (s[len] == c)) { + while ((len > 0) && (s[len] == c)) + { s[len] = '\0'; len -= 1; } } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options]\n", progname); @@ -39,7 +43,8 @@ static void help(void) "\n"); } -int main(int argc, char **argv) +int +main(int argc, char **argv) { struct ncp_conn *conn; int opt; @@ -52,12 +57,15 @@ int main(int argc, char **argv) progname = argv[0]; - if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { com_err(argv[0], err, "when initializing"); goto finished; } - while ((opt = getopt(argc, argv, "h?a")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?a")) != EOF) + { + switch (opt) + { case 'h': case '?': help(); @@ -71,22 +79,26 @@ int main(int argc, char **argv) } } - if (ncp_get_file_server_information(conn, &info) != 0) { + if (ncp_get_file_server_information(conn, &info) != 0) + { perror("Could not get server information"); ncp_close(conn); return 1; } - if (isatty(1)) { - if (print_addr == 0) { + if (isatty(1)) + { + if (print_addr == 0) + { printf("\n%-6s%-21s%-12s\n" - "---------------------------------------------" + "---------------------------------------------" "------\n", "Conn", "User name", "Login time"); - } else { + } else + { printf("\n%-6s%-21s%-27s%-12s\n" - "---------------------------------------------" + "---------------------------------------------" "---------------------------------\n", "Conn", "User name", @@ -94,18 +106,21 @@ int main(int argc, char **argv) "Login time"); } } - for (i = 1; i <= info.MaximumServiceConnections; i++) { + for (i = 1; i <= info.MaximumServiceConnections; i++) + { char name[49]; name[48] = '\0'; if (ncp_get_stations_logged_info(conn, i, &user, - &login_time) != 0) { + &login_time) != 0) + { continue; } memcpy(name, user.object_name, 48); str_trim_right(name, ' '); printf("%4d: %-20s ", i, name); - if (print_addr != 0) { + if (print_addr != 0) + { struct sockaddr_ipx addr; __u8 conn_type; diff --git a/util/nwvolinfo.c b/util/nwvolinfo.c index f08413a..2ee0908 100644 --- a/util/nwvolinfo.c +++ b/util/nwvolinfo.c @@ -15,13 +15,15 @@ static char *progname; -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [options] pattern\n", progname); return; } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options]\n", progname); @@ -38,12 +40,13 @@ static void help(void) "\n"); } -int main(int argc, char **argv) +int +main(int argc, char **argv) { struct ncp_conn *conn; struct ncp_volume_info o; - char *volname = "SYS"; + const char *volname = "SYS"; long err; int opt; int numk; @@ -51,12 +54,15 @@ int main(int argc, char **argv) progname = argv[0]; - if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { com_err(argv[0], err, "when initializing"); return 1; } - while ((opt = getopt(argc, argv, "h?Nv:")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "h?Nv:")) != EOF) + { + switch (opt) + { case 'h': case '?': help(); @@ -73,19 +79,23 @@ int main(int argc, char **argv) } } - if (optind < argc) { + if (optind < argc) + { usage(); exit(1); } - if (ncp_get_volume_number(conn, volname, &opt)) { + if (ncp_get_volume_number(conn, volname, &opt)) + { exit(1); } - if (ncp_get_volume_info_with_number(conn, opt, &o)) { + if (ncp_get_volume_info_with_number(conn, opt, &o)) + { exit(1); } numk = o.sectors_per_block / 2; o.free_blocks += o.purgeable_blocks; - if (type) { + if (type) + { printf("%d %d %d %d %d %d\n", o.total_blocks * numk, o.free_blocks * numk, @@ -93,7 +103,8 @@ int main(int argc, char **argv) o.not_yet_purgeable_blocks * numk, o.total_dir_entries, o.available_dir_entries); - } else { + } else + { printf("Total : %dK\n", o.total_blocks * numk); printf("Free : %dK\n", o.free_blocks * numk); printf("Purgable : %dK\n", o.purgeable_blocks * numk); diff --git a/util/pqlist.c b/util/pqlist.c index 671ad2f..26ad308 100644 --- a/util/pqlist.c +++ b/util/pqlist.c @@ -12,7 +12,8 @@ #include #include "ncplib.h" -int main(int argc, char **argv) +int +main(int argc, char **argv) { struct ncp_conn *conn; struct ncp_bindery_object q; @@ -23,22 +24,27 @@ int main(int argc, char **argv) char *p; long err; - if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) { + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { com_err(argv[0], err, "when initializing"); return 1; } - if (argc > 2) { + if (argc > 2) + { fprintf(stderr, "usage: %s [options] [pattern]\n", argv[0]); return 1; } - if (argc == 2) { + if (argc == 2) + { pattern = argv[1]; } - for (p = pattern; *p != '\0'; p++) { + for (p = pattern; *p != '\0'; p++) + { *p = toupper(*p); } - if (isatty(1)) { + if (isatty(1)) + { printf("\nServer: %s\n", conn->server); printf("%-52s%-10s\n" "-----------------------------------------------" @@ -49,13 +55,15 @@ int main(int argc, char **argv) q.object_id = 0xffffffff; while (ncp_scan_bindery_object(conn, q.object_id, - NCP_BINDERY_PQUEUE, pattern, &q) == 0) { + NCP_BINDERY_PQUEUE, pattern, &q) == 0) + { found = 1; printf("%-52s", q.object_name); printf("%08X\n", (unsigned int) q.object_id); } - if ((found == 0) && (isatty(1))) { + if ((found == 0) && (isatty(1))) + { printf("No queues found\n"); } ncp_close(conn); diff --git a/util/pqrm.c b/util/pqrm.c new file mode 100644 index 0000000..e5a0dc2 --- /dev/null +++ b/util/pqrm.c @@ -0,0 +1,71 @@ +/* + * pqrm.c + * + * Remove job from a print queue on a server + * + * Copyright (C) 1998 by Petr Vandrovec, David Woodhouse + * Derived from pqlist.c, (C) 1996 Volker Lendecke + * + */ + +#include +#include +#include +#include +#include "ncplib.h" + +int +main(int argc, char **argv) +{ + struct ncp_conn *conn; + struct ncp_bindery_object q; + long err; + int i; + + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { + com_err(argv[0], err, "when initializing"); + return 1; + } + + if (argc < 3) + { + fprintf(stderr, "usage: %s [ ...]\n", argv[0]); + return 1; + } + + + if (ncp_get_bindery_object_id(conn, NCP_BINDERY_PQUEUE, + argv[1], &q) != 0) + { + printf("Queue \"%s\" on server %s not found.\n", + argv[1], conn->server); + ncp_close(conn); + exit(1); + + } + + for (i=2; i +#include +#include +#include +#include +#include "ncplib.h" + +/* move this to library ? */ +int +ncp_time_to_tm(struct tm* out, __u8* netwareTime) +{ + struct tm tmp; + + tmp.tm_year = netwareTime[0]; + if (tmp.tm_year < 80) tmp.tm_year += 100; + tmp.tm_mon = netwareTime[1]-1; + if ((tmp.tm_mon < 0) || (tmp.tm_mon >= 12)) return 1; + tmp.tm_mday = netwareTime[2]; + if ((tmp.tm_mday < 1) || (tmp.tm_mday >= 32)) return 1; + tmp.tm_hour = netwareTime[3]; + if (tmp.tm_hour >= 24) return 1; + tmp.tm_min = netwareTime[4]; + if (tmp.tm_min >= 60) return 1; + tmp.tm_sec = netwareTime[5]; + if (tmp.tm_sec >= 60) return 1; + memcpy(out, &tmp, sizeof(tmp)); + return 0; +} + +int +ncp_cmp_time(struct tm* tm1, struct tm* tm2) +{ +#undef XTST +#define XTST(Y) if (tm1->tm_##Y## != tm2->tm_##Y##) { \ + return (tm1->tm_##Y## > tm2->tm_##Y##) ? 1 : -1; \ + } + XTST(year); + XTST(mon); + XTST(mday); + XTST(hour); + XTST(min); + XTST(sec); +#undef XTST + return 0; +} + +int +main(int argc, char **argv) +{ + struct ncp_conn *conn; + struct ncp_bindery_object q,u; + unsigned long maxqlen=~0; + long err; + + __u32 qlen, idl1,idl2, job_id; + struct nw_queue_job_entry j; + + if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL) + { + com_err(argv[0], err, "when initializing"); + return 1; + } + + if (argc == 3) + { + char *end; + + maxqlen=strtoul(argv[2], &end, 10); + if (*end != 0) + argc = 4; + + } + if (argc < 2 || argc > 3) + { + fprintf(stderr, "usage: %s []\n", argv[0]); + return 1; + } + + + if (ncp_get_bindery_object_id(conn, NCP_BINDERY_PQUEUE, + argv[1], &q) != 0) + { + printf("Queue \"%s\" on server %s not found.\n", + argv[1], conn->server); + ncp_close(conn); + exit(1); + + } + + if (isatty(1)) + { + printf("\nServer: %s\tQueue: %s\tQueue ID: %8.8X\n", conn->server, q.object_name, q.object_id); + printf(" %5s %-12s %-32s %-7s %-4s %-8s\n" + + "-----------------------------------------------" + "--------------------------------\n", + "Seq","Name", + "Description", "Status", "Form", "Job ID"); + } + + + if ((err=ncp_get_queue_length(conn, q.object_id, &qlen)) != 0) + { + if (conn->completion == 0xD3) { + fprintf(stderr, "You have insufficient rights to list queue jobs\n"); + } else { + com_err(argv[0], err, ": cannot get queue length"); + } + ncp_close(conn); + exit(1); + } +/* printf("There are %d jobs in the queue.\n",qlen); */ + + idl1=1; + job_id =0; + + if ((err=ncp_get_queue_job_ids(conn, q.object_id, 1, + &idl1, &idl2, &job_id)) != 0) + { + printf("Error getting queue jobs ids: %ld\n",err); + ncp_close(conn); + exit(1); + } + +/* printf("First queue job ID is %8X\n",job_id);*/ + + while (maxqlen-- && job_id && (ncp_get_queue_job_info(conn, q.object_id, job_id, &j) == 0)) + { + const char* jst; + + char user[50]; + if ((ncp_get_bindery_object_name + (conn, ntohl(j.ClientObjectID), &u)) + == 0) + { + memcpy(user,u.object_name,48); + user[48]=0; + } + else + { + sprintf(user,""); + } + + j.JobFileName[j.FileNameLen]=0; + + if (j.JobControlFlags & 0xC0) { + jst = "Held"; + } else if (j.JobControlFlags & 0x20) { + jst = "Adding"; + } else if (j.ServerStation) { + jst = "Active"; + } else { + struct tm jobtime; + + jst = "Ready"; + if (!ncp_time_to_tm(&jobtime, j.TargetExecTime)) { + time_t ltime; + struct tm* loctime; + + time(<ime); + loctime = localtime(<ime); + + if (ncp_cmp_time(&jobtime, loctime) >= 0) + jst = "Waiting"; + } + } + + printf(" %5d %-12s %-32.32s %-7s %4d %08X\n", + j.JobPosition, user, j.JobTextDescription, jst, ntohs(j.JobType), j.JobNumber); + if (j.next == job_id) + job_id = 0; + else job_id = j.next; + } + + ncp_close(conn); + return 0; +} + diff --git a/util/pserver.c b/util/pserver.c index ebf4fbc..dda76d0 100644 --- a/util/pserver.c +++ b/util/pserver.c @@ -18,7 +18,8 @@ #include #include "ncplib.h" -struct nw_queue { +struct nw_queue +{ struct ncp_conn *conn; char queue_name[NCP_BINDERY_NAME_LEN]; @@ -40,13 +41,15 @@ static int static int poll_queue(struct nw_queue *q); -static void usage(void) +static void +usage(void) { fprintf(stderr, "usage: %s [options] file\n", progname); exit(1); } -static void help(void) +static void +help(void) { printf("\n"); printf("usage: %s [options]\n", progname); @@ -69,7 +72,8 @@ static void help(void) #define NCP_BINDERY_PSERVER (0x0007) #endif -static void terminate_handler() +static void +terminate_handler(int dummy) { signal(SIGTERM, terminate_handler); signal(SIGINT, terminate_handler); @@ -77,13 +81,16 @@ static void terminate_handler() } /* Daemon_init is taken from Stevens, Adv. Unix programming */ -static int daemon_init(void) +static int +daemon_init(void) { pid_t pid; - if ((pid = fork()) < 0) { + if ((pid = fork()) < 0) + { return -1; - } else if (pid != 0) { + } else if (pid != 0) + { exit(0); /* parent vanishes */ } /* child process */ @@ -96,7 +103,8 @@ static int daemon_init(void) return 0; } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { struct ncp_conn *conn; int poll_timeout = 30; @@ -113,32 +121,40 @@ int main(int argc, char *argv[]) progname = argv[0]; - for (i = 1; i < argc; i += 1) { + for (i = 1; i < argc; i += 1) + { if ((strcmp(argv[i], "-h") == 0) - || (strcmp(argv[i], "-?") == 0)) { + || (strcmp(argv[i], "-?") == 0)) + { help(); exit(0); } } - for (i = 1; i < argc; i += 1) { - if (strcmp(argv[i], "-d") == 0) { + for (i = 1; i < argc; i += 1) + { + if (strcmp(argv[i], "-d") == 0) + { debug = 1; break; } } - if (debug == 0) { + if (debug == 0) + { daemon_init(); openlog("pserver", LOG_PID, LOG_LPR); } if ((conn = ncp_initialize_as(&argc, argv, 1, - NCP_BINDERY_PSERVER, &err)) == NULL) { + NCP_BINDERY_PSERVER, &err)) == NULL) + { com_err(argv[0], err, "when initializing"); return 1; } - while ((opt = getopt(argc, argv, "q:c:j:t:dh")) != EOF) { - switch (opt) { + while ((opt = getopt(argc, argv, "q:c:j:t:dh")) != EOF) + { + switch (opt) + { case 'q': queue_name = optarg; break; @@ -162,17 +178,20 @@ int main(int argc, char *argv[]) } } - if (argc != optind) { + if (argc != optind) + { usage(); return -1; } memzero(q); - if (queue_name == NULL) { + if (queue_name == NULL) + { fprintf(stderr, "You must specify a queue\n"); return 1; } - if (init_queue(conn, queue_name, command, &q) != 0) { + if (init_queue(conn, queue_name, command, &q) != 0) + { perror("Could not init queue"); ncp_close(conn); return 1; @@ -183,12 +202,15 @@ int main(int argc, char *argv[]) signal(SIGTERM, terminate_handler); signal(SIGINT, terminate_handler); - while (1) { + while (1) + { if ((poll_queue(&q) != 0) - && (term_request == 0)) { + && (term_request == 0)) + { continue; } - if (term_request != 0) { + if (term_request != 0) + { break; } sleep(poll_timeout); @@ -200,8 +222,9 @@ int main(int argc, char *argv[]) return 0; } -static int init_queue(struct ncp_conn *conn, char *queue_name, char *command, - struct nw_queue *q) +static int +init_queue(struct ncp_conn *conn, char *queue_name, char *command, + struct nw_queue *q) { struct ncp_bindery_object obj; @@ -211,14 +234,16 @@ static int init_queue(struct ncp_conn *conn, char *queue_name, char *command, q->command = command; if (ncp_get_bindery_object_id(conn, NCP_BINDERY_PQUEUE, - queue_name, &obj) != 0) { + queue_name, &obj) != 0) + { fprintf(stderr, "Queue %s not found\n", queue_name); return -1; } q->queue_id = obj.object_id; memcpy(q->queue_name, obj.object_name, sizeof(q->queue_name)); - if (ncp_attach_to_queue(conn, q->queue_id) != 0) { + if (ncp_attach_to_queue(conn, q->queue_id) != 0) + { fprintf(stderr, "Could not attach to queue %s\n", queue_name); return -1; @@ -227,48 +252,50 @@ static int init_queue(struct ncp_conn *conn, char *queue_name, char *command, } -void build_command(struct nw_queue *q, struct queue_job *j, - char *target, int target_size) +void +build_command(struct nw_queue *q, struct queue_job *j, + char *target, int target_size, char *user) { char *s = q->command; char *target_end = target + target_size; - void add_string(char *s) { + void add_string(const char *s) + { int len = strlen(s); - if (target + len + 1 > target_end) { + if (target + len + 1 > target_end) + { len = target_end - target - 1; } strncpy(target, s, len); target += len; } - memset(target, 0, target_size); - while ((*s != 0) && (target < target_end)) { - if (*s != '%') { + while ((*s != 0) && (target < target_end)) + { + if (*s != '%') + { *target = *s; target += 1; s += 1; continue; } - switch (*(s + 1)) { + switch (*(s + 1)) + { case '%': *target = '%'; target += 1; + break; case 'u': - { - char *user; - struct ncp_bindery_object u; - if (ncp_get_bindery_object_name - (q->conn, j->j.ClientObjectID, &u) - == 0) { - user = u.object_name; - } else { - user = "*UNKNOWN USER*"; - } - add_string(user); - } + add_string(user); + break; + case 'd': + if (j->j.JobTextDescription[0]) + add_string(j->j.JobTextDescription); + else + add_string("No Description"); + break; default: *target = '%'; *(target + 1) = *(s + 1); @@ -281,26 +308,52 @@ void build_command(struct nw_queue *q, struct queue_job *j, -static int poll_queue(struct nw_queue *q) +static int +poll_queue(struct nw_queue *q) { struct queue_job job; int fd[2]; int pid; + int retcode; + struct ncp_bindery_object u; + char user[50]; if (ncp_service_queue_job(q->conn, q->queue_id, q->job_type, - &job) != 0) { + &job) != 0) + { /* No job for us */ return 0; } - if (pipe(fd) < 0) { + + if (ncp_get_queue_job_info(q->conn, q->queue_id, job.j.JobNumber, &job.j) != 0) + { + job.j.JobTextDescription[0]=0; + } + + if ((retcode=ncp_get_bindery_object_name + (q->conn, htonl(job.j.ClientObjectID), &u)) + == 0) + { + memcpy(user,u.object_name,48); + user[48]=0; + } + else + { + sprintf(user,""); + } + + if (pipe(fd) < 0) + { syslog(LOG_ERR, "pipe error: %m"); goto fail; } - if ((pid = fork()) < 0) { + if ((pid = fork()) < 0) + { syslog(LOG_ERR, "fork error: %m"); goto fail; } - if (pid > 0) { + if (pid > 0) + { /* parent */ char buf[1024]; size_t result; @@ -309,34 +362,41 @@ static int poll_queue(struct nw_queue *q) close(fd[0]); /* close read end */ while ((result = ncp_read(q->conn, job.file_handle, offset, - sizeof(buf), buf)) > 0) { + sizeof(buf), buf)) > 0) + { offset += result; - if (write(fd[1], buf, result) != result) { + if (write(fd[1], buf, result) != result) + { goto fail; } } close(fd[1]); /* and close write end */ - if (waitpid(pid, NULL, 0) < 0) { + if (waitpid(pid, NULL, 0) < 0) + { syslog(LOG_ERR, "waitpid: %m\n"); } - } else { + } else + { /* child */ char command[2048]; close(fd[1]); /* close write end */ - if (fd[0] != STDIN_FILENO) { - if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) { + if (fd[0] != STDIN_FILENO) + { + if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) + { syslog(LOG_ERR, "dup2 error: %m\n"); close(fd[0]); exit(1); } close(fd[0]); } - build_command(q, &job, command, sizeof(command)); + + build_command(q, &job, command, sizeof(command), user); execl("/bin/sh", "sh", "-c", command, NULL); syslog(LOG_ERR, "exec error: %m\n"); diff --git a/util/slist.c b/util/slist.c index cf00d1d..fe9ae14 100644 --- a/util/slist.c +++ b/util/slist.c @@ -14,7 +14,8 @@ #include #include -void main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { struct ncp_conn *conn; struct ncp_bindery_object obj; @@ -24,22 +25,27 @@ void main(int argc, char *argv[]) char *p; long err; - if (argc > 2) { + if (argc > 2) + { printf("usage: %s [pattern]\n", argv[0]); exit(1); } - if (argc == 2) { + if (argc == 2) + { pattern = argv[1]; } - for (p = pattern; *p != '\0'; p++) { + for (p = pattern; *p != '\0'; p++) + { *p = toupper(*p); } - if ((conn = ncp_open(NULL, &err)) == NULL) { + if ((conn = ncp_open(NULL, &err)) == NULL) + { com_err(argv[0], err, "in ncp_open"); exit(1); } - if (isatty(1)) { + if (isatty(1)) + { printf("\n%-52s%-10s%-12s\n" "-----------------------------------------------" "---------------------------\n", @@ -51,7 +57,8 @@ void main(int argc, char *argv[]) while (ncp_scan_bindery_object(conn, obj.object_id, NCP_BINDERY_FSERVER, pattern, - &obj) == 0) { + &obj) == 0) + { struct nw_property prop; struct prop_net_address *naddr = (struct prop_net_address *) ∝ @@ -61,8 +68,9 @@ void main(int argc, char *argv[]) printf("%-52s", obj.object_name); if (ncp_read_property_value(conn, NCP_BINDERY_FSERVER, - obj.object_name, 1, "NET_ADDRESS", - &prop) == 0) { + obj.object_name, 1, "NET_ADDRESS", + &prop) == 0) + { ipx_print_network(naddr->network); printf(" "); ipx_print_node(naddr->node); @@ -70,8 +78,10 @@ void main(int argc, char *argv[]) printf("\n"); } - if ((found == 0) && (isatty(1))) { + if ((found == 0) && (isatty(1))) + { printf("No servers found\n"); } ncp_close(conn); + return 0; }