mars_nwe-0.95.pl00

This commit is contained in:
Mario Fetka 2011-11-13 00:38:55 +01:00
commit 5b89fe9f28
27 changed files with 10348 additions and 0 deletions

339
COPYING Normal file
View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "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
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

41
INSTALL Normal file
View File

@ -0,0 +1,41 @@
************** GERMAN ********************
=========> Programme erzeugen <===================
1. make aufrufen.
2. mk.li und config.h evtl. anpassen
3. make aufrufen.
=========> Konfigurieren <===================
nw.ini bearbeiten !
=========> Installieren <===================
"make install"
evtl. "make install_ini" um eine installierte ini Datei
zu *ueberschreiben* .
=========> Starten <===================
nwserv starten ( als root !! )
mit Linux Version 1.2.13 getestet.
Der Linux Kernel muss mit IPX Unterstuetzung erzeugt worden sein.
IPX-Interface bzw. Routen werden durch das Programm automatisch
angelegt, falls in der nw.ini Datei eine
Networknummer > 0 angegeben wurde.
************** ENGLISH *******************
=========> create programs <===================
1. call make.
2. perhaps you must modify mk.li and config.h
3. call make
=========> configure <===================
modify nw.ini !
=========> install <===================
"make install"
"make install_ini" to overwrite your old _installed_ ini.
=========> start programs <===================
call nwserv ( as root !! )
tested with Linux Version 1.2.13.
the linux-kernel must be configured with IPX=Y.
ipx-interface and ipx-routes are setup by the program if the
network number in nw.ini is set > 0.
Viel Erfolg / good Luck :-)
Martin

71
Makefile Normal file
View File

@ -0,0 +1,71 @@
# Makefile mars_nwe: 16-Nov-95
VPATH=
all: rmeflag mk.li config.h nw.ini
@if [ -r .eflag ] ; then \
echo ""; \
echo "********************************************************"; \
cat .eflag; rm -f .eflag; \
echo "";\
echo "Please make your changes and run make again"; \
echo "********************************************************"; \
echo "";\
echo ""; else ./mk.li && (\
if [ -r .mk.notes ] ; then echo "" ; \
echo ""; \
echo "********************************************************" ; \
echo ""; \
cat .mk.notes; rm .mk.notes ; \
echo ""; \
echo "********************************************************" ; \
echo ""; echo "" ; fi ) fi
install:
./mk.li $@
install_ini: nw.ini
./mk.li $@
clean: mk.li nw.ini
./mk.li $@
distrib: mk.li nw.ini
./mk.li $@
mk.li: examples/mk.li
@if [ -r $@ ] ; then \
cp -f $@ $@.org && ( \
echo "********************************************************"; \
echo "";\
echo "saved: $@ -> $@.org, there is a new examples/$@"; \
echo "";\
echo "********************************************************"; \
echo "" ) ; fi
@ echo ""
@ echo ""
@ - cp -i examples/$@ .
@ touch -c $@
@ echo ""
@ echo "********************************************************"
@ echo ""
@ echo "perhaps $@ is new and you need to edit it."
@ echo ""
@ echo "********************************************************"
@ echo ""
@ echo "" > .eflag
config.h: examples/config.h
@if [ -r $@ ] ; then echo "note:examples/$@ is newer then $@" >> .eflag ;\
echo "$@ will be touched now" >> .eflag; touch -c $@ ; \
else cp examples/$@ . ; \
echo "$@ created (from examples/$@) Please edit $@" >> .eflag;\
echo "and change it to your requirements." >> .eflag ; fi
rmeflag:
@ - rm -f .eflag
nw.ini: examples/nw.ini
@if [ -r $@ ] ; then echo "note:examples/$@ is newer then $@" > .mk.notes ; \
echo "$@ will be touched now" >> .mk.notes; touch -c $@ ; \
else cp -a examples/$@ . ; \
echo "$@ created (from examples/$@) Please edit $@" > .mk.notes;\
echo "and change it to your requirements." >> .mk.notes ; fi

79
README Normal file
View File

@ -0,0 +1,79 @@
(C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
to compile and install, please read INSTALL !
This is a little try to emulate some functions from
a NOVELL-SERVER under UNIX (LINUX).
The first version I have written 1993 on a USL1.1
with TLI-Code.
1994 I have ported it to LINUX. This was easy, because
I only have to write a small TLI->SOCKET emu.
Unfortunately I had no full description of the NCP-calls,
so many of the calls based on trying. :-(
WARNING: this code has still many BUG's !!
BINDERY: this are the *.pag and *.dir files.
These files are generated by the first starting
of mars_nwe and are filled with the minimal
needed Objects and Properties.
USER is SUPERVISOR with no password.
NETWORK: If there is a real Novell-Server on the
same net-line, then the NETWORK Number of
the network device in nw.ini should match
the NETWORK Number of the Novell-Server.
LINUX
KERNEL: the only linux-kernel depending files
are emutli.[hc].
short description of the processes.
1) nwserv : the main program.Initiates all and starts 'ncpserv'.
sends broadcasts, wdogs, sap and rip packets.
If nwserv is started with a parameter, then the simple
test client 'nwclient', only for debugging, is started.
2) ncpserv: opens NCP-Socket and handles NCP-Requests.
When there comes NCP-Request 0x1111 (Get Connection Nr)
then there will be started a new process 'nwconn'.
Every client-ncp-request reaches nwconn over
ncpserv.
3) nwconn: will be started for every connection. Is connected
to ncpserv with a pipe.
Problems and TODO:
Many:-(
Here is a short list.
o - Some Problems with the IPX-kernelcode.
Frame Ethernet_ii isn't ok since linux-kernel > 1.1.??.
with linux-kernel 1.1.44 is was still ok.
trouble with some linux-kernel 1.3.xx
o - make routing better.
o - making printing better.
o - login's with password's.
o - clean the code !!!
o - make bindery code more complete.
o - and much more ...
Have luck with tryimg. :)
Martin
(mstover@kool.f.eunet.de)
BTW: The kick to make mars_nwe public was the
publication of linware ( lwared ), the Novell-Server-Emulator
from Ales Dryak (A.Dryak@sh.cvut.cz).
I hope both products kann make profit from each other.
-----> SuperNOS ala Linux ;-)
Novell don't want to make it anymore. :-(

95
README.ger Normal file
View File

@ -0,0 +1,95 @@
(C)opyright (C) 1993,1995 Martin Stover, Marburg
Hilfe zum Kompilieren bzw. Installieren siehe in 'INSTALL' !
Dieses ist ein kleiner Versuch Grundfunktionen
eines Novell Servers unter UNIX (LINUX) zur Verfuegung
zu stellen. Die erste Version entstand 1993 auf einer USL1.1
mittels TLI-Code und wurde 1994, mittels
dem modul 'emutli' (TLI -> SOCKETS) nach Linux portiert.
Leider stand mir eine vollstaendige Beschreibung der NCP-Calls
nicht zur Verfuegung, so daá die Behandlung vieler Calls
auf Vermutungen bzw. Ausprobieren basieren. :-(
WARNUNG: Es gibt noch viele Bugs !!
z.Z. forked nwserv nicht automatisch. Er kann jederzeit
abgebrochen und neu gestartet werden.
Kernel muss mit IPX Unterstuetzung erzeugt worden sein.
IPX-Routen werden automatisch angelegt.
Anmerkungen:
BINDERY: besteht aus den *.pag und *.dir Dateien.
diese Dateien werden, falls nicht vorhanden,
erzeugt und mit den Grundobjekten und Grundproperties
gefuellt. Ein automatisch angelegter USER
ist SUPERVISOR ohne Passwort.
NETWORK: Falls auch ein Novellserver am gleichem
Strang haengt, sollte die NETWORK Nummer
des Netzwerk Devices von mars_nwe auf
die des Novellservers gesetzt werden.
LINUX
KERNEL: Die einzigen Linux kernelabhaengigen
Dateien sind emutli.[hc]
Beschreibung der Prozesse
1) nwserv : Hauptprogramm, initialisiert alles und startet 'ncpserv'.
schickt Broadcasts, bearbeitet SAP, RIP und WDog-Pakete
Falls nwserv mit beliebigen Parameter gestartet wird,
wird der `Testclient` Code (nwclient.c) fuer Debugging
Zwecke abgearbeitet.
2) ncpserv: oeffnet NCP-Socket und behandelt NCP-Requests.
Bei NCP-Request 0x1111 (Get Connection Nr) wird fuer
jede Connection neuer Prozess 'nwconn' gestartet.
Jeder Client Request gelangt ueber NCP-SOCKET
nach ncpserv.
3) nwconn: Wird fuer jede Connection angelegt. Ist mit
nwserv ueber eine PIPE verbunden, erzeugt
einen Client-Schreib Socket.
PROBLEME bzw. TODO's:
Vieles :-(
Hier nur eine *kleine* Auswahl.
o - Frame Ethernet_ii geht nicht (mehr)
Liegt wohl am Kernel-ipx-Code. ??
mit Kernel-Version 1.1.44 funktionierte es noch.
einige Kernel 1.3.xx funktionieren nicht.
o - Routing verbessern.
o - Drucken verbessern.
o - Login nur mit unencrypted Passwords.
Ich kenne den Crypt-Algorithmus nicht. :-(
Habe ihn aber jetzt bei lwared (linware) gesehen :-)
o - Saeubern !!
o - Bindery Code vervollstaendigen.
o - und und ...
Viel Spaá beim Ausprobieren. :)
Ueber Erweiterungen, Korrekturen und insbesonderes der Beschreibung
der fehlenden bzw. fehlerhaften NCP-Calls wuerde ich mich freuen.
Martin
(mstover@kool.f.eunet.de)
PS: Den Anstoss, mars_nwe zu veroeffentlichen, gab die
Veroeffentlichung von linware ( lwared ), dem Novell-Server-Emulator
von Ales Dryak (A.Dryak@sh.cvut.cz).
Vielleicht koennen beide Produkte voneinander profitieren.
-----> SuperNOS ala Linux ;-)
Novell will es ja leider nicht mehr machen. :-(

11
config.h Normal file
View File

@ -0,0 +1,11 @@
/* config.h: 18-Nov-95 */
/* this config is needed by make and by cc */
#define FILENAME_NW_INI "./nw.ini" /* location of ini (conf) file */
#define PATHNAME_PROGS "." /* path location of progs */
#define MAX_CONNECTIONS 5 /* max. Number of Connections */
#define MAX_NW_VOLS 10 /* max. Volumes */
#define PATHNAME_BINDERY "/tmp" /* path location of bindery */
#define _WDOG_TESTING_

1748
connect.c Normal file

File diff suppressed because it is too large Load Diff

504
emutli.c Normal file
View File

@ -0,0 +1,504 @@
/* emutli.c 17-Nov-95 */
/*
* One short try to emulate TLI with SOCKETS.
*/
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* Some of the Code in this module is stolen from the following
* Programms: ipx_interface, ipx_route, ipx_configure, which was
* written by Greg Page, Caldera, Inc.
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/sockios.h>
#include "net.h"
#include <linux/if.h>
#include <linux/route.h>
#include <linux/in.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
static int locipxdebug=0;
static int have_ipx_started=0;
static void set_sock_debug(int sock)
{
if (setsockopt(sock, SOL_SOCKET, SO_DEBUG, &locipxdebug, sizeof(int))==-1){
perror("setsockopt SO_DEBUG");
}
}
static void sock2ipxadr(ipxAddr_t *i, struct sockaddr_ipx *so)
{
memcpy(i->net, &so->sipx_network, IPX_NET_SIZE + IPX_NODE_SIZE);
memcpy(i->sock, &so->sipx_port, 2);
}
static void ipx2sockadr(struct sockaddr_ipx *so, ipxAddr_t *i)
{
memcpy(&so->sipx_network, i->net, IPX_NET_SIZE + IPX_NODE_SIZE);
memcpy(&so->sipx_port, i->sock, 2);
}
void set_emu_tli(int ipx_debug)
{
locipxdebug = ipx_debug;
}
int init_ipx(char *device,
uint32 *network,
uint32 intnet,
int frame,
char *frame_name,
int ipx_debug)
{
int sock=-1;
int result=-1;
#ifndef OLD_KERNEL_IPX
struct ifreq id;
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
int i;
memset(&id, 0, sizeof(struct ifreq));
strcpy(id.ifr_name, device);
locipxdebug = ipx_debug;
sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (socket < 0) {
perror("EMUTLI:init_ipx");
exit(1);
}
/* NUN DEBUG ein bzw. ausschalten */
set_sock_debug(sock);
/* remove old ipx_interface */
if (*network) {
sipx->sipx_network = 0L;
sipx->sipx_special = IPX_INTERNAL;
sipx->sipx_family = AF_IPX;
sipx->sipx_action = IPX_DLTITF;
(void) ioctl(sock, SIOCSIFADDR, &id);
sipx->sipx_special = IPX_PRIMARY;
sipx->sipx_network = 0L;
sipx->sipx_family = AF_IPX;
sipx->sipx_type = frame;
sipx->sipx_action = IPX_DLTITF;
(void) ioctl(sock, SIOCSIFADDR, &id);
have_ipx_started++;
}
sipx->sipx_special = IPX_PRIMARY; /* IPX_SPECIAL_NONE */
/* IPX_INTERNAL */
/* IPX_PRIMARY */
sipx->sipx_network = htonl(*network);
sipx->sipx_type = frame;
sipx->sipx_family = AF_IPX;
sipx->sipx_action = IPX_CRTITF; /* anlegen */
/* IPX_DLTITF ist loeschen */
i = 0;
do {
result = ioctl(sock, SIOCSIFADDR, &id);
} while ((++i < 5) && (result < 0) && (errno == EAGAIN));
if (result) {
switch (errno) {
case EEXIST:
DPRINTF(("Primary network already selected.\n"));
result = 0; /* not a reallly error */
break;
case EADDRINUSE:
fprintf(stderr, "Network number (0X%08lX) already in use.\n",
htonl(sipx->sipx_network));
break;
case EPROTONOSUPPORT:
fprintf(stderr, "Invalid frame type (%s).\n",
frame_name);
break;
case ENODEV:
fprintf(stderr, "No such device (%s).\n",
id.ifr_name);
break;
case ENETDOWN:
fprintf(stderr, "Requested device (%s) is down.\n",
id.ifr_name);
break;
case EINVAL:
fprintf(stderr, "Invalid device (%s).\n",
id.ifr_name);
break;
case EAGAIN:
fprintf(stderr, "Insufficient memory to create interface.\n");
break;
default:
perror("ioctl:SIOCSIFADDR");
break;
} /* switch */
}
#else /* alte Kernel Version vor ???? */
struct ipx_route_def rt;
locipxdebug = ipx_debug;
rt.ipx_network=htonl(*network);
rt.ipx_router_network=IPX_ROUTE_NO_ROUTER;
strncpy(rt.ipx_device,"eth0",16);
rt.ipx_flags=frame;
sock=socket(AF_IPX,SOCK_DGRAM,PF_IPX);
if(sock==-1) {
perror("EMUTLI:init_ipx");
exit(1);
}
set_sock_debug(sock);
result = ioctl(sock,SIOCADDRT,(void *)&rt);
if (result && errno == EEXIST) result =0;
if (result) perror("ioctl");
#endif
#if 1
if (!*network) {
struct sockaddr_ipx ipxs;
int maxplen=sizeof(struct sockaddr_ipx);
memset((char*)&ipxs, 0, sizeof(struct sockaddr_ipx));
ipxs.sipx_family=AF_IPX;
if (bind(sock, (struct sockaddr*)&ipxs, sizeof(struct sockaddr_ipx))==-1){
perror("EMUTLI:init_ipx");
result = -1;
} else {
if (getsockname(sock, (struct sockaddr*)&ipxs, &maxplen) == -1){
perror("EMUTLI:init_ipx");
result = -1;
} else *network=ntohl(ipxs.sipx_network);
}
if (sock > -1) close(sock);
}
#endif
close(sock);
if (result) exit(1);
return(result);
}
void exit_ipx(char *devname, uint32 network, int frame)
{
if (have_ipx_started) {
int sock=-1;
int result=-1;
struct ifreq id;
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
int i;
memset(&id, 0, sizeof(struct ifreq));
strcpy(id.ifr_name, devname);
sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (socket < 0) {
perror("EMUTLI:exit_ipx");
return;
}
/* Switch DEBUG off */
locipxdebug = 0;
set_sock_debug(sock);
/* remove routes */
sipx->sipx_network = 0L;
sipx->sipx_special = IPX_INTERNAL;
sipx->sipx_family = AF_IPX;
sipx->sipx_action = IPX_DLTITF;
(void) ioctl(sock, SIOCSIFADDR, &id);
sipx->sipx_special = IPX_PRIMARY;
sipx->sipx_network = 0L;
sipx->sipx_family = AF_IPX;
sipx->sipx_type = frame;
sipx->sipx_action = IPX_DLTITF;
(void) ioctl(sock, SIOCSIFADDR, &id);
close(sock);
}
}
void myipx_route_add(unsigned char *dest_net,
unsigned char *route_net,
unsigned char *route_node)
{
struct rtentry rd;
int i;
int result;
int sock;
/* Router */
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
/* Target */
struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rd.rt_dst;
rd.rt_flags = RTF_GATEWAY;
memcpy(&(st->sipx_network), dest_net, IPX_NET_SIZE);
memcpy(&(sr->sipx_network), route_net, IPX_NET_SIZE);
memcpy(sr->sipx_node, route_node, IPX_NODE_SIZE);
if ( (sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX)) < 0){
perror("EMUTLI:myipx_route_add");
return;
}
sr->sipx_family = st->sipx_family = AF_IPX;
i = 0;
do {
result = ioctl(sock, SIOCADDRT, &rd);
i++;
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
if (result) {
switch (errno) {
case ENETUNREACH:
fprintf(stderr, "Router network (%08X) not reachable.\n",
htonl(sr->sipx_network));
break;
case EEXIST:
case EADDRINUSE:
break;
default:
perror("add route ioctl");
break;
}
}
close(sock);
}
void myipx_route_del(unsigned char *net)
{
struct rtentry rd;
int i;
int result;
int sock;
/* Router */
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
/* Target */
struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rd.rt_dst;
rd.rt_flags = RTF_GATEWAY;
memcpy(&(st->sipx_network), net, IPX_NET_SIZE);
if ( (sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX)) < 0){
perror("EMUTLI:myipx_route_del");
return;
}
sr->sipx_family = st->sipx_family = AF_IPX;
i = 0;
do {
result = ioctl(sock, SIOCDELRT, &rd);
i++;
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
/* errors doesn't matter here */
close(sock);
}
int t_open(char *name, int open_mode, char * p)
{
int opt=1;
int sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (sock < 0) return(sock);
/* NUN DEBUG ein bzw. ausschalten */
set_sock_debug(sock);
/* NUN Broadcast erlauben */
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &opt,sizeof(opt))==-1){
perror("setsockopt SO_BROADCAST");
close(sock);
return(-1);
}
return(sock);
}
int t_bind(int sock, struct t_bind *a_in, struct t_bind *a_out)
{
struct sockaddr_ipx ipxs;
int maxplen=sizeof(struct sockaddr_ipx);
memset((char*)&ipxs, 0, sizeof(struct sockaddr_ipx));
ipxs.sipx_family=AF_IPX;
if (a_in != (struct t_bind*) NULL
&& a_in->addr.len == sizeof(ipxAddr_t))
ipx2sockadr(&ipxs, (ipxAddr_t*) (a_in->addr.buf));
ipxs.sipx_network = 0L;
if (bind(sock, (struct sockaddr*)&ipxs, sizeof(struct sockaddr_ipx))==-1) {
char xx[100];
sprintf(xx, "TLI-BIND socket Nr:0x%x", (int)GET_BE16(&(ipxs.sipx_port)));
perror(xx);
return(-1);
}
if (a_out != (struct t_bind*) NULL) {
if (getsockname(sock, (struct sockaddr*)&ipxs, &maxplen) == -1){
perror("TLI-GETSOCKNAME");
return(-1);
}
sock2ipxadr((ipxAddr_t*) (a_out->addr.buf), &ipxs);
DPRINTF(("T_BIND ADR=%s\n", visable_ipx_adr((ipxAddr_t *) a_out->addr.buf ) ));
}
return(0);
}
int t_unbind(int sock)
{
return(0);
}
int t_errno=0;
void t_error(char *s)
{
perror(s);
t_errno=0;
}
int t_close(int fd)
{
return(close(fd));
}
int poll( struct pollfd *fds, unsigned long nfds, int timeout)
/* z.Z. nur POLL-IN */
{
fd_set readfs;
/*
fd_set writefs;
fd_set exceptfs;
*/
struct pollfd *p = fds;
struct timeval time_out;
int k = (int)nfds;
int result=-1;
int high_f=0;
FD_ZERO(&readfs);
/*
FD_ZERO(&writefs);
FD_ZERO(&exceptfs);
*/
while (k--){
if (p->fd > -1 && (p->events & POLLIN)) {
FD_SET(p->fd, &readfs);
if (p->fd > high_f) high_f = p->fd;
}
p->revents=0;
p++;
}
if (timeout > 1000) {
time_out.tv_sec = timeout / 1000;
time_out.tv_usec = 0;
} else {
time_out.tv_sec = 0;
time_out.tv_usec = timeout*1000;
}
result = select(high_f+1, &readfs, NULL, NULL, &time_out);
if (result < 0) return(-1);
if (result) {
int rest=result;
k = (int)nfds;
p = fds;
while (k--){
if (p->fd > -1 && FD_ISSET(p->fd, &readfs)){
p->revents = POLLIN;
if (! --rest) break; /* fertig */
}
p++;
}
}
return(result);
}
int t_rcvudata(int fd, struct t_unitdata *ud, int *flags)
{
struct sockaddr_ipx ipxs;
int sz = sizeof(struct sockaddr_ipx);
int result;
ipxs.sipx_family=AF_IPX;
if (ud->addr.maxlen < sizeof(ipxAddr_t)) return(-1);
result = recvfrom(fd, ud->udata.buf, ud->udata.maxlen, 0,
(struct sockaddr *) &ipxs, &sz);
if (result < 0) return(result);
if (ud->opt.maxlen) {
*((uint8*)ud->opt.buf) = ipxs.sipx_type;
ud->opt.len = 1;
}
ud->udata.len=result;
sock2ipxadr((ipxAddr_t*) (ud->addr.buf), &ipxs);
ud->addr.len = sizeof(ipxAddr_t);
return(result);
}
int t_sndudata(int fd, struct t_unitdata *ud)
{
int result;
struct sockaddr_ipx ipxs;
memset(&ipxs, 0, sizeof(struct sockaddr_ipx));
ipxs.sipx_family=AF_IPX;
if (ud->addr.len != sizeof(ipxAddr_t)) return(-1);
ipx2sockadr(&ipxs, (ipxAddr_t*) (ud->addr.buf));
ipxs.sipx_type = (ud->opt.len) ? (uint8) *((uint8*)(ud->opt.buf)) : 0;
result = sendto(fd,(void *)ud->udata.buf,
ud->udata.len, 0, (struct sockaddr *) &ipxs, sizeof(ipxs));
if (result<0) {
char xx[100];
sprintf(xx, "t_sndudata->result=%d, errno=%d\n", result, errno);
perror(xx);
}
return(result);
}
int t_rcvuderr(int fd, struct t_uderr *ud)
{
return(0);
}

125
emutli.h Normal file
View File

@ -0,0 +1,125 @@
/* emutli.h 11-Sep-95 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/ipx.h>
typedef unsigned char uint8;
typedef unsigned short int uint16;
typedef unsigned long int uint32;
#define IPX_NET_SIZE 4
#define IPX_NODE_SIZE 6
#define IPX_SOCK_SIZE 2
typedef struct {
uint8 net[IPX_NET_SIZE];
uint8 node[IPX_NODE_SIZE];
uint8 sock[IPX_SOCK_SIZE];
} ipxAddr_t;
#define IPXCMPNODE(a, b) ( \
((char *)(a))[0] == ((char*)(b))[0] && \
((char *)(a))[1] == ((char*)(b))[1] && \
((char *)(a))[2] == ((char*)(b))[2] && \
((char *)(a))[3] == ((char*)(b))[3] && \
((char *)(a))[4] == ((char*)(b))[4] && \
((char *)(a))[5] == ((char*)(b))[5] \
)
struct netbuf {
unsigned int maxlen;
unsigned int len;
char *buf;
};
struct t_bind {
struct netbuf addr;
unsigned int qlen;
};
struct t_unitdata {
struct netbuf addr; /* address */
struct netbuf opt; /* options */
struct netbuf udata; /* userdata */
};
struct t_uderr {
struct netbuf addr; /* address */
struct netbuf opt; /* options */
long error; /* eroorcode */
};
struct pollfd {
int fd;
short events;
short revents;
};
#define POLLIN 0x0001 /* fd readable */
#define POLLPRI 0x0002 /* high priority */
#define TOUTSTATE 6 /* out of state */
extern int poll(struct pollfd *fds, unsigned long nfds, int timeout);
extern int t_open(char *name, int open_mode, char *p);
extern int t_bind(int sock, struct t_bind *a_in, struct t_bind *a_out);
extern int t_unbind(int sock);
extern void t_error(char *s);
extern int t_close(int fd);
extern int t_rcvudata(int fd, struct t_unitdata *ud, int *flags);
extern int t_rcvuderr(int fd, struct t_uderr *ud);
extern int t_sndudata(int fd, struct t_unitdata *ud);
extern int init_ipx(char *device, uint32 *network,
uint32 intnet,
int frame,
char *frame_name,
int ipx_debug);
extern void exit_ipx(char *devname, uint32 network, int frame);
extern void myipx_route_add(unsigned char *dest_net,
unsigned char *route_net,
unsigned char *route_node);
extern void myipx_route_del(unsigned char *net);
extern void set_emu_tli(int ipx_debug);
#ifndef IPX_FRAME_8022
#define OLD_KERNEL_IPX 1
#define IPX_FRAME_8022 IPX_RT_8022
#endif
#ifndef IPX_FRAME_8023
#define IPX_FRAME_8023 0
#endif
#ifndef IPX_FRAME_SNAP
#define IPX_FRAME_SNAP IPX_RT_SNAP
#endif
#ifndef IPX_FRAME_ETHERII
#define IPX_FRAME_ETHERII IPX_RT_BLUEBOOK
#endif

9
examples/config.h Normal file
View File

@ -0,0 +1,9 @@
/* config.h: 22-Nov-95 */
/* this config is needed by make and by cc */
#define FILENAME_NW_INI "./nw.ini" /* full name of ini (conf) file */
#define PATHNAME_PROGS "." /* path location of progs */
#define PATHNAME_BINDERY "." /* path location of bindery */
#define MAX_CONNECTIONS 5 /* max. Number of Connections */
#define MAX_NW_VOLS 10 /* max. Volumes */

25
examples/mk.li Executable file
View File

@ -0,0 +1,25 @@
#!/bin/sh
# mk.li 16-Nov-95 ###
#
mk()
{
MYBASE=`pwd`;
ERRFILE=$TMP/`basename $MYBASE`.err;
rm -f $ERRFILE;
if [ ! -d obj ] ; then mkdir obj; fi
cd obj;
$MAKE -f ../makefile.unx $@ 2>&1 | tee $ERRFILE;
cd ..;
chmod 666 $ERRFILE
}
export CC=cc
export CCP="cc -E"
#export CFLAGS="-pipe -O2 -fomit-frame-pointer"
#problems gcc2.5.8 ^^^^^^^^^^^^^^^^^^^^^^^^
export CFLAGS="-pipe"
export HOSTCFLAGS="-DLINUX"
export TMP=/tmp
MAKE=make
mk $@

53
examples/nw.ini Normal file
View File

@ -0,0 +1,53 @@
# (C)opyright 1993, 1995, Martin Stover, Softwareentwicklung, Marburg
# MAR.S NW-Server Emulator
# Einfache Konfiguration, alles ab # ist Kommentar.
# Jeder Eintrag beginnt mit einer Zahl und dann folgt der Inhalt.
# simple configuration, all after # is ignored.
# Every entry begins with a number and then the meet follows.
# entry 1 VOLUMES (max. 5) entry 1
# Volumename Volumepath Options (k=lowercase)
1 SYS /u3/SYS/ # SYS 1
####################################
# Die folgenden Volumes sind optional.
# the following volumes are optional.
#1 SYS1 /u3/SYS1/ # SYS 2
#1 TMP /tmp/ k # TMP downshift
#1 CD /cdrom k # CDROM allways downshift
# Falls lowercase nicht gesetzt ist, werden GROSSBUCHSTABEN erwartet.
# If lowercase is not set then all filenames are upshift.
# SYS, der Name darf auch anders lauten, muss
# eingerichtet sein mit den folgenden Verzeichnissen:
# LOGIN, PUBLIC, SYSTEM, MAIL.
# SYS, may be named diffent but must be setup and must
# contains the following Directories: LOGIN, PUBLIC, SYSTEM, MAIL
#############################
# Eintrag 2 fuer den Servername.
# falls nicht gesetzt, wird hostname (in GROSSBUCHSTABEN) verwendet.
# entry 2 for the servername. If not set, then the hostname (upshift)
# will be taken.
#2 MAR1 # Servername
# entry 4: #
# NETWORK NUMBER, DEVICE, Frame-Typ
4 0x10 eth0 802.3
# Frames=ethernet_ii od. 802.2 od. 802.3 od SNAP (default 802.3)
# ACHTUNG ethernet_ii geht leider seit LINUX > V 1.1.44 nicht mehr.
# aktuell getestet nur mit 802.3 !!!!!
# actual testet with 802.3 !!
######################################
# z.Z. werden _alle_ Connections mit folgender UID bzw. GID gestartet.
# wird noch geaendert werden.
# _all_ connections will be started with the following UID and GID.
# will be change one time.
10 200 # GID
11 201 # UID
#############################
# entry 21 for simple print queues, dynamic
# QUEUE NAME, Q_DIRECTORY, UNIX-print-command (pipe)
21 Q1 SYS:/PRINT/Q1 lpr
#21 Q2 SYS:/PRINT/Q2 lpr -C printer2
#############################
# >= 100 debug flags
100 0 # debug IPX KERNEL (0 / 1)
101 1 # debug NWSERV
102 0 # debug NCPSERV
103 0 # debug NWCONN

195
makefile.unx Normal file
View File

@ -0,0 +1,195 @@
# makefile.unx 15-Nov-95
VPATH=..
O=.o
C=.c
DEBUG=-DDB
V_H=0
V_L=95
DISTRIB=mars_nwe
PATCHF=$(DISTRIB)p$(V_H).$(V_L)
STERN=*
#if 0
DESTMAKEFILE=Makefile.o
all: $(DESTMAKEFILE)
$(MAKE) -f $(DESTMAKEFILE) n_$@
clean: $(DESTMAKEFILE)
$(MAKE) -f $(DESTMAKEFILE) n_$@
distclean: $(DESTMAKEFILE)
$(MAKE) -f $(DESTMAKEFILE) n_$@
install: $(DESTMAKEFILE)
$(MAKE) -f $(DESTMAKEFILE) n_$@
install_ini: $(DESTMAKEFILE)
$(MAKE) -f $(DESTMAKEFILE) n_$@
diff: $(DESTMAKEFILE)
$(MAKE) -f $(DESTMAKEFILE) n_$@
distrib: $(DESTMAKEFILE)
$(MAKE) -f $(DESTMAKEFILE) n_$@
distrib_bin: $(DESTMAKEFILE)
$(MAKE) -f $(DESTMAKEFILE) n_$@
$(DESTMAKEFILE): makefile.unx config.h
rm -f $@
cp ../makefile.unx makefile.c
$(CPP) $(HOSTCFLAGS) -I$(VPATH) makefile.c > $@
rm -f makefile.c
#endif
PROG1=netinit
PROG2=nwserv
PROG3=nwconn
PROG4=ncpserv
PROG5=nwclient
#ifdef LINUX
EMUTLIOBJ=emutli$(O)
PROG1=
NDBMLIB=-ldbm
NSLLIB=
#else
NDBMLIB=/usr/ucblib/libucb.a
NSLLIB=-lnsl
#endif
PROGS=$(PROG1) $(PROG2) $(PROG3) $(PROG4) $(PROG5)
#include "config.h"
#ifdef FILENAME_NW_INI
M_FILENAME_NW_INI=FILENAME_NW_INI
#else
M_FILENAME_NW_INI="./nw.ini"
#endif
#ifdef PATHNAME_PROGS
M_PATHNAME_PROGS=PATHNAME_PROGS
#else
M_PATHNAME_PROGS="."
#endif
OBJ1= $(EMUTLIOBJ) net1$(O) tools$(O)
OBJ2= $(OBJ1)
#nwdbm$(O)
OBJ3= $(OBJ1) connect$(O)
OBJ4= $(OBJ1) nwdbm$(O)
OBJ5= $(OBJ1)
OBJS= net1$(O) tools$(O) connect$(O) nwdbm$(O) \
$(PROG2)$(O) $(PROG3)$(O) $(PROG4)$(O) $(PROG5)$(O)
$(PROG1): $(PROG1)$(O) $(OBJ1)
$(CC) -o ../$(PROG1) $(PROG1)$(O) $(OBJ1) $(NSLLIB)
$(PROG2): $(PROG2)$(O) $(OBJ2)
$(CC) -o ../$(PROG2) $(PROG2)$(O) $(OBJ2) $(NSLLIB)
#$(CC) -o ../$(PROG2) $(PROG2)$(O) $(OBJ2) $(NDBMLIB) $(NSLLIB)
$(PROG3): $(PROG3)$(O) $(OBJ3)
$(CC) -o ../$(PROG3) $(PROG3)$(O) $(OBJ3) $(NSLLIB)
$(PROG4): $(PROG4)$(O) $(OBJ4)
$(CC) -o ../$(PROG4) $(PROG4)$(O) $(OBJ4) $(NDBMLIB) $(NSLLIB)
$(PROG5): $(PROG5)$(O) $(OBJ5)
$(CC) -o ../$(PROG5) $(PROG5)$(O) $(OBJ5) $(NSLLIB)
$(OBJS): net.h config.h
$(C)$(O):
$(CC) -c $(CFLAGS) $(HOSTCFLAGS) $(DEBUG) -D_VERSION_H_=$(V_H) -D_VERSION_L_=$(V_L) $<
n_all: $(PROGS)
n_install_ini:
cd .. && install -m 664 nw.ini $(M_FILENAME_NW_INI) && cd obj
n_install:
cd .. && install -d $(M_PATHNAME_PROGS) && cd obj
cd .. && install $(PROGS) $(M_PATHNAME_PROGS) && cd obj
@cd .. && (if [ -r $(M_FILENAME_NW_INI) ] ; then \
echo ""; \
echo "********************************************************"; \
echo ""; \
echo "$(M_FILENAME_NW_INI) exist."; \
echo "to overwrite it with nw.ini, make install_ini";\
echo ""; \
echo "********************************************************"; \
echo ""; \
else \
install -m 664 nw.ini $(M_FILENAME_NW_INI); \
echo ""; \
echo "********************************************************"; \
echo ""; \
echo "$(M_FILENAME_NW_INI) created from nw.ini"; \
echo ""; \
echo "********************************************************"; \
echo ""; \
fi; cd obj )
n_clean1:
cd .. && (rm -f ~* examples/~* examples/.e.pck; cd obj)
n_clean: n_clean1
rm -f *.o
cd .. && (rm -f $(PROGS); cd obj )
n_distclean: n_clean
cd .. && (rm -f *.dir *.pag; cd obj)
n_diff: n_clean1
cd .. && (rm -rf obj/../$(DISTRIB) \
; mkdir $(DISTRIB) \
; mkdir $(DISTRIB)/examples \
; ln -f \
$(STERN).[ch] \
makefile.unx \
Makefile \
COPYING \
README \
README.ger \
INSTALL \
$(DISTRIB).lsm \
$(DISTRIB)/. \
; ln -f \
examples/$(STERN) \
$(DISTRIB)/examples/. \
; makepatch $(DISTRIB).org $(DISTRIB) > $(PATCHF) \
; gzip -9 -f $(PATCHF) \
; cd obj )
n_distrib: n_diff
-mkdir /tmp/x
cd .. && (tar cvzf $(DISTRIB).tgz $(DISTRIB) \
; uue $(DISTRIB).tgz \
; cp -a $(DISTRIB)/$(DISTRIB).lsm /tmp/yy \
; echo "" >> /tmp/yy \
; echo "" >> /tmp/yy \
; cat $(DISTRIB).uue >> /tmp/yy \
; chmod 664 /tmp/yy \
; rm $(DISTRIB).uue \
; mv $(DISTRIB).tgz /tmp/x/. \
; cp -a $(DISTRIB)/$(DISTRIB).lsm /tmp/x/. \
; cd obj )
n_distrib_bin:
cd .. && (tar cvzf /tmp/$(DISTRIB).bin.tgz \
$(PROGS) \
COPYING \
INSTALL \
README \
README.ger \
$(DISTRIB).lsm \
examples \
; cd obj)

15
mars_nwe.lsm Normal file
View File

@ -0,0 +1,15 @@
Begin3
Title: mars_nwe
Version: 0.95
Entered-date: 22-Nov-95
Description: simple novell-server-emulator (src),beta
needs no kernelchanges, usefull for testing ipx
file-services, bindery-services, printing-services
Keywords: novell, netware, server, ipx, ncp, tli
Author: mstover@kool.f.eunet.de (Martin Stover)
Maintained-by: mstover@kool.f.eunet.de (Martin Stover)
Primary-site: linux01.gwdg.de /pub/???
80kB mars_nwe.tgz
Platforms: Linux (1.2.xx testet, others should work)
Copying-policy: GNU
End

1350
ncpserv.c Normal file

File diff suppressed because it is too large Load Diff

405
net.h Normal file
View File

@ -0,0 +1,405 @@
/* net.h 20-Nov-95 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _M_NET_H_
#define _M_NET_H_
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#ifndef LINUX
/* z.B. USL */
# include "sys/tiuser.h"
#endif
#include "sys/fcntl.h"
#include "sys/types.h"
#include "unistd.h"
#include <sys/stat.h>
#include <time.h>
#ifndef LINUX
# include "stropts.h"
# include "poll.h"
# include "sys/nwctypes.h"
# include "sys/stream.h"
/* # include "common.h" */
/* # include "portable.h" , needed ??? */
# include "sys/ipx_app.h"
#else
# include "emutli.h" /* TLI-EMULATION */
#endif
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#define U16_TO_BE16(u, b) { uint16 a=(u); \
*( (uint8*) (b) ) = *( ((uint8*) (&a)) +1); \
*( ((uint8*) (b)) +1) = *( (uint8*) (&a)); }
#define U32_TO_BE32(u, ar) { uint32 a= (u); uint8 *b= ((uint8*)(ar))+3; \
*b-- = (uint8)a; a >>= 8; \
*b-- = (uint8)a; a >>= 8; \
*b-- = (uint8)a; a >>= 8; \
*b = (uint8)a; }
#define GET_BE16(b) ( (int) *(((uint8*)(b))+1) \
| ( ( (int) *( (uint8*)(b) ) << 8) ) )
#define GET_BE32(b) ( (uint32) *(((uint8*)(b))+3) \
| ( ((uint32) *(((uint8*)(b))+2)) << 8) \
| ( ((uint32) *(((uint8*)(b))+1)) << 16) \
| ( ((uint32) *( (uint8*)(b) ) << 24) ) )
#define MAX_U32 ((uint32)0xffffffffL)
#define MAX_U16 ((uint16)0xffff)
#define IPX_MAX_DATA /* 1058 */ 546
#define MAX_SERVER_NAME 48
typedef union {
struct S_SIP { /* Server Identification Packet, siehe auch SAP */
uint8 response_type[2]; /*hi-lo */
/* 2 periodic bzw. Shutdown */
/* bzw. General Service Response */
/* 4 nearest Service Response */
uint8 server_type[2]; /*hi-lo */
/* 0x0 unknown */
/* 0x1 user */
/* 0x2 user/group */
/* 0x3 Print Queue */
/* 0x4 File Server */
/* 0x5 Job Server */
/* 0x6 Gateway */
/* 0x7 Printserver */
/* 0x9 Archive Server */
/* 0x24 Remote Bridge Server */
/* 0x47 Advertising Print Server */
/* 0x107 Netware 386 */
/* 0xFFFF (-1) WILD */
uint8 server_name[MAX_SERVER_NAME];
ipxAddr_t server_adr;
uint8 intermediate_networks[2]; /* hi-lo */
/* normal 0 */
/* down 16 */
} sip; /* Server Identifikation Packet */
struct S_SQP { /* Service Query Packet */
uint8 query_type[2]; /* hi low */
/* 1 general Service Query */
/* 3 nearest Server Query */
uint8 server_type[2]; /* hi low s.o. */
} sqp;
struct S_SAP {
uint8 sap_operation[2]; /* hi-low */
struct S_SAPS {
uint8 server_type[2];
uint8 server_name[MAX_SERVER_NAME];
ipxAddr_t server_adr;
uint8 server_hops[2];
} saps;
} sap;
struct S_WDOG { /* Watchdog */
uint8 connid; /* connection ID */
uint8 status; /* STATUS */
} wdog;
struct S_CONFREQ { /* IPX Diagnose */
uint8 count;
uint8 ex_node[6];
} confreq;
struct S_RIP { /* ROUTING */
uint8 operation[2]; /* 1 request, 2 response */
uint8 network[4];
uint8 hops[2]; /* Anzahl Routerspassagen um Netzwerk zu Erreichen */
uint8 ticks[2]; /* Zeit in 1/18 sec. um Netzwerk Nummer zu erreichen */
} rip;
struct S_DIAGRESP {
uint8 majorversion;
uint8 minorversion;
uint8 spx_diag_sock[2]; /* SPX Diagnose SOCKET */
uint8 anz; /* Anzahl Componente */
/* .... Componente
* uint8 id; 0:IPX/SPX, 1: BRIGDE Driver, 2: Shell driver
* 3: Shell, 4: VAP Shell
*
* extented 5: external Bridge, 6 Files Server/Bridge
* 7: non dedicated IPX/SPX
*
* extented haben folgende Zusatzfelder
* uint8 count; Anzahl Local Networks
* jetzt pro Network
* uint8 type; 0: LAN-Board,
* 1: non dedicated File/Sever(virtuelles Board)
* 2: redirected remote Line;
*
* uint8 net; Netwerk Adresse
* uint8 node; Node
*
*
*/
} diaresp;
struct S_NCPRESPONSE {
uint8 type[2]; /* 0x3333 */
uint8 sequence;
uint8 connection; /* low connection */
uint8 task;
uint8 reserved; /* high connection */
uint8 completition; /* bzw. ERROR CODE */
uint8 connect_status;
} ncpresponse;
struct S_NCPREQUEST {
uint8 type[2]; /* 0x1111 od 0x2222 */
uint8 sequence;
uint8 connection; /* low connection */
uint8 task;
uint8 reserved; /* high connection */
uint8 function; /* Function */
} ncprequest;
char data[IPX_MAX_DATA];
} IPX_DATA;
typedef struct S_SIP SIP;
typedef struct S_SQP SQP;
typedef struct S_SAP SAP;
typedef struct S_SAPS SAPS;
typedef struct S_RIP RIP;
typedef struct S_CONFREQ CONFREQ;
typedef struct S_DIAGRESP DIAGRESP;
typedef struct S_NCPRESPONSE NCPRESPONSE;
typedef struct S_NCPREQUEST NCPREQUEST;
/* SOCKETS */
#define SOCK_ROUTE 0x0001 /* Routing Information */
#define SOCK_ECHO 0x0002 /* Echo Protokoll Packet */
#define SOCK_ERROR 0x0003 /* Error Handler Packet */
#define SOCK_NCP 0x0451 /* File Service CORE */
#define SOCK_SAP 0x0452 /* SAP Service Advertising Packet */
#define SOCK_RIP 0x0453 /* Routing Information Packet */
#define SOCK_NETBIOS 0x0455 /* NET BIOS Packet */
#define SOCK_DIAGNOSE 0x0456 /* Diagnostic Packet */
#define SOCK_NVT 0x8063 /* NVT (Netzerk Virtual Terminal) */
/* PACKET TYPES */
#define PACKT_0 0 /* unknown */
#define PACKT_ROUTE 1 /* Routing Information */
#define PACKT_ECHO 2 /* Echo Packet */
#define PACKT_ERROR 3 /* Error Packet */
#define PACKT_EXCH 4 /* Packet Exchange Packet */
#define PACKT_SPX 5 /* SPX Packet */
/* 16 - 31 Experimental */
#define PACKT_CORE 17 /* Core Protokoll (NCP) */
#define FD_NWSERV 3 /* one after stderr */
/* ===================> config.h <======================= */
#include "config.h"
#ifndef MAX_CONNECTIONS
# define MAX_CONNECTIONS 5 /* maximum Number of Connections */
#endif
#ifndef MAX_NW_VOLS
# define MAX_NW_VOLS 10
#endif
#ifndef FILENAME_NW_INI
# define FILENAME_NW_INI "./nw.ini" /* location of ini (conf) file */
#endif
#ifndef PATHNAME_BINDERY
# define PATHNAME_BINDERY "." /* location of bindery files */
#endif
#include "net1.h"
/* connect.c */
typedef struct {
uint8 name[14]; /* filename in DOS format */
uint8 attrib; /* Attribute */
uint8 ext_attrib; /* File Execute Type */
uint8 size[4]; /* size of file */
uint8 create_date[2];
uint8 acces_date[2];
uint8 modify_date[2];
uint8 modify_time[2];
} NW_FILE_INFO;
typedef struct {
uint8 name[14]; /* dirname */
uint8 attrib;
uint8 ext_attrib;
uint8 create_date[2];
uint8 create_time[2];
uint8 owner_id[4];
uint8 access_right_mask;
uint8 reserved; /* future use */
uint8 next_search[2];
} NW_DIR_INFO;
typedef struct {
uint8 record_in_use[2];
uint8 record_previous[4];
uint8 record_next[4];
uint8 client_connection[4];
uint8 client_task[4];
uint8 client_id[4];
uint8 target_id[4]; /* 0xff, 0xff, 0xff, 0xff */
uint8 target_execute_time[6]; /* alles 0xff */
uint8 job_entry_time[6]; /* ?? alles 0 */
uint8 job_id[4]; /* ?? alles 0 HI-LOW */
uint8 job_typ[2]; /* z.B. Printform HI-LOW */
uint8 job_position[2]; /* ?? alles 0 low-high ? */
uint8 job_control_flags[2]; /* z.B 0x10, 0x00 */
/* 0x80 operator hold flag */
/* 0x40 user hold flag */
/* 0x20 entry open flag */
/* 0x10 service restart flag */
/* 0x08 autostart flag */
uint8 job_file_name[14]; /* len + DOS filename */
uint8 job_file_handle[4];
uint8 server_station[4];
uint8 server_task[4];
uint8 server_id[4];
uint8 job_bez[50]; /* "LPT1 Catch" */
uint8 client_area[152];
} QUEUE_JOB;
typedef struct {
uint8 version; /* normal 0x0 */
uint8 tabsize; /* normal 0x8 */
uint8 anz_copies[2]; /* Anzahl Copien HI-LOW */
uint8 print_flags[2]; /* z.B fuer Banner */
uint8 max_lines[2];
uint8 max_chars[2];
uint8 form_name[16]; /* "UNKNOWN" */
uint8 reserved[6];
uint8 banner_user_name[13]; /* Username */
uint8 bannner_file_name[13];
uint8 bannner_header_file_name[14];
uint8 file_path_name[80];
} QUEUE_PRINT_AREA;
typedef struct {
uint8 volume;
uint8 base[4]; /* Base or Handle */
uint8 flag; /* 0=base, 1=handle, 0xff=not path nor handle */
uint8 components; /* nmbrs of pathes, components */
uint8 pathes[1]; /* form len+name */
} NW_HPATH;
extern int nw_init_connect(void);
extern int nw_free_handles(int task);
extern int nw_creat_open_file(int dir_handle, uint8 *data, int len,
NW_FILE_INFO *info, int attrib, int access, int mode);
extern int nw_read_datei(int fhandle, uint8 *data, int size, uint32 offset);
extern int nw_seek_datei(int fhandle, int modus);
extern int nw_write_datei(int fhandle, uint8 *data, int size, uint32 offset);
extern int nw_lock_datei(int fhandle, int offset, int size, int do_lock);
extern int nw_close_datei(int fhandle);
extern int nw_server_copy(int qfhandle, uint32 qoffset,
int zfhandle, uint32 zoffset,
uint32 size);
extern int nw_delete_datei(int dir_handle, uint8 *data, int len);
extern int nw_chmod_datei(int dir_handle, uint8 *data, int len, int modus);
extern int mv_file(int qdirhandle, uint8 *q, int qlen,
int zdirhandle, uint8 *z, int zlen);
extern int nw_mk_rd_dir(int dir_handle, uint8 *data, int len, int mode);
extern int nw_search(uint8 *info,
int dirhandle, int searchsequence,
int search_attrib, uint8 *data, int len);
extern int nw_dir_search(uint8 *info,
int dirhandle, int searchsequence,
int search_attrib, uint8 *data, int len);
extern int nw_find_dir_handle( int dir_handle,
uint8 *data, /* zus„tzlicher Pfad */
int len); /* L„nge Pfad */
extern int nw_alloc_dir_handle(
int dir_handle, /* Suche ab Pfad dirhandle */
uint8 *data, /* zus„tzl. Pfad */
int len, /* L„nge DATA */
int driveletter, /* A .. Z normal */
int is_temphandle, /* tempor„res Handle 1 */
/* spez. temp Handle 2 */
int task); /* Prozess Task */
extern int nw_open_dir_handle( int dir_handle,
uint8 *data, /* zus„tzlicher Pfad */
int len, /* L„nge DATA */
int *volume, /* Volume */
int *dir_id, /* „hnlich Filehandle */
int *searchsequence);
extern int nw_free_dir_handle(int dir_handle);
extern int nw_set_dir_handle(int targetdir, int dir_handle,
uint8 *data, int len, int task);
extern int nw_get_directory_path(int dir_handle, uint8 *name);
extern int nw_get_vol_number(int dir_handle);
extern int nw_get_volume_number(uint8 *volname, int namelen);
extern int nw_get_volume_name(int volnr, uint8 *volname);
extern int nw_get_eff_dir_rights(int dir_handle, uint8 *data, int len);
extern int nw_set_fdate_time(uint32 fhandle, uint8 *datum, uint8 *zeit);
extern int nw_scan_dir_info(int dir_handle, uint8 *data, int len,
uint8 *subnr, uint8 *subname,
uint8 *subdatetime, uint8 *owner);
extern int nw_generate_dir_path(uint8 *nwpathstruct,
uint8 *ns_dir_base, uint8 *dos_dir_base);
#include "tools.h"
extern int nw_get_fs_usage(char *volname, struct fs_usage *fsu);
#endif

168
net1.c Normal file
View File

@ -0,0 +1,168 @@
/* net1.c, 11-Sep-95 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "net.h"
#if HAVE_TLI
void print_t_info(struct t_info *t)
{
DPRINTF(("T_INFO:addr %ld, options %ld, tsdu %ld, etsdu %ld\n",
t->addr, t->options,t->tsdu, t->etsdu));
DPRINTF(("connect %ld, discon %ld, servtype %ld\n",
t->connect, t->discon,t->servtype));
#if 0
struct t_info {
long addr; /* size of protocol address */
long options; /* size of protocol options */
long tsdu; /* size of max transport service data unit */
long etsdu; /* size of max expedited tsdu */
long connect; /* max data for connection primitives */
long discon; /* max data for disconnect primitives */
long servtype; /* provider service type */
#endif
}
#endif
char *visable_ipx_adr(ipxAddr_t *p)
{
static char str[200];
sprintf(str,"net=%x:%x:%x:%x, node=%x:%x:%x:%x:%x:%x, sock=%02x:%02x",
(int)p->net[0], (int)p->net[1], (int)p->net[2], (int)p->net[3],
(int)p->node[0], (int)p->node[1], (int)p->node[2], (int)p->node[3],
(int)p->node[4], (int)p->node[5], (int)p->sock[0], (int)p->sock[1]);
return(str);
}
void print_ipx_addr(ipxAddr_t *p)
{
DPRINTF(("%s\n", visable_ipx_adr(p)));
}
void print_ud_data(struct t_unitdata *ud)
{
int packet_typ = *(int*)(ud->opt.buf);
int data_len = ud->udata.len;
IPX_DATA *ipxdata = (IPX_DATA *)(ud->udata.buf);
DPRINTF(("DATA-LEN %d, PACKET-TYPE %d von:",
data_len, packet_typ));
/* hierin steht nun Addresse u. Node des Senders */
print_ipx_addr((ipxAddr_t *)(ud->addr.buf));
if (packet_typ == PACKT_CORE) {
DPRINTF(("Query Type 0x%x, Server Type 0x%xd\n",
GET_BE16(ipxdata->sqp.query_type),
GET_BE16(ipxdata->sqp.server_type)));
} else if (data_len > sizeof(SIP)){
SAP *sap = &(ipxdata->sap);
SAPS *saps = &(ipxdata->sap.saps);
int sap_operation = GET_BE16(sap->sap_operation);
DPRINTF(("SAP-OPERATION %d\n", sap_operation));
while (data_len >= sizeof(SAPS)){
DPRINTF(("Name:%s:, typ:0x%x\n",saps->server_name,
GET_BE16(saps->server_type)));
print_ipx_addr(&(saps->server_adr));
saps++;
data_len -= sizeof(SAPS);
}
} else print_ipx_data(ipxdata);
}
void print_ipx_data(IPX_DATA *p)
{
print_sip_data(&(p->sip));
}
void print_sip_data(SIP *sip)
{
DPRINTF(("Name:%s:,response_type:0x%x,server_typ:0x%x\n",sip->server_name,
GET_BE16(sip->response_type), GET_BE16(sip->server_type)));
print_ipx_addr(&(sip->server_adr));
}
void adr_to_ipx_addr(ipxAddr_t *p, char *s)
{
int net0, net1, net2, net3;
int node0, node1, node2, node3, node4, node5;
int sock0, sock1;
sscanf(s, "%x.%x.%x.%x,%x.%x.%x.%x.%x.%x,%x.%x",
&net0, &net1, &net2, &net3,
&node0, &node1, &node2, &node3, &node4, &node5,
&sock0, &sock1);
p->net[0] = net0;
p->net[1] = net1;
p->net[2] = net2;
p->net[3] = net3;
p->node[0] = node0;
p->node[1] = node1;
p->node[2] = node2;
p->node[3] = node3;
p->node[4] = node4;
p->node[5] = node5;
p->sock[0] = sock0;
p->sock[1] = sock1;
}
void ipx_addr_to_adr(char *s, ipxAddr_t *p)
{
sprintf(s, "%x.%x.%x.%x,%x.%x.%x.%x.%x.%x,%x.%x",
(int)p->net[0] ,
(int)p->net[1] ,
(int)p->net[2] ,
(int)p->net[3] ,
(int)p->node[0],
(int)p->node[1],
(int)p->node[2],
(int)p->node[3],
(int)p->node[4],
(int)p->node[5],
(int)p->sock[0],
(int)p->sock[1]);
}
int send_ipx_data(int fd, int pack_typ,
int data_len, char *data,
ipxAddr_t *to_addr, char *comment)
{
struct t_unitdata ud;
uint8 ipx_pack_typ = (uint8) pack_typ;
ud.opt.len = sizeof(ipx_pack_typ);
ud.opt.maxlen = sizeof(ipx_pack_typ);
ud.opt.buf = (char*)&ipx_pack_typ;
ud.addr.len = sizeof(ipxAddr_t);
ud.addr.maxlen = sizeof(ipxAddr_t);
ud.udata.buf = (char*)data;
ud.udata.len = data_len;
ud.udata.maxlen = data_len;
ud.addr.buf = (char*)to_addr;
if (comment != NULL) DPRINTF(("%s TO: ", comment));
if (nw_debug)print_ipx_addr(to_addr);
if (t_sndudata(fd, &ud) < 0){
t_error("t_sndudata !OK");
return(-1);
}
return(0);
}

37
net1.h Normal file
View File

@ -0,0 +1,37 @@
/* net1.h 11-Sep-95 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LINUX
extern void print_t_info(struct t_info *t);
extern void print_ud_data(struct t_unitdata *ud);
#endif
extern char *visable_ipx_adr(ipxAddr_t *p);
extern void print_ipx_addr(ipxAddr_t *p);
extern void print_ipx_data(IPX_DATA *p);
extern void print_sip_data(SIP *sip);
extern void adr_to_ipx_addr(ipxAddr_t *p, char *s);
extern void ipx_addr_to_adr(char *s, ipxAddr_t *p);
extern int send_ipx_data(int fd, int pack_typ,
int data_len, char *data,
ipxAddr_t *to_addr, char *comment);

308
netinit.c Normal file
View File

@ -0,0 +1,308 @@
/* netinit.c 11-Sep-95 */
/* Initialisierung VON IPX u. SPX unter USL 1.1 */
/* 'emuliert' Teil von NPSD */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "net.h"
#include <sys/dlpi.h>
#define NET_DEBUG 1
#define MY_NETWORK 0x10
#if NET_DEBUG
void print_adaptinfo(FILE *fout, ipxAdapterInfo_t *ai, char *s)
{
if (s != NULL)
fprintf(fout, "\n---- %s ----\n", s);
fprintf(fout,
"dl_primitive = %lu \n\
dl_max_sdu = %lu \n\
dl_min_sdu = %lu \n\
dl_addr_length = %lu \n\
dl_mac_type = %lu \n\
dl_reserved = %lu \n\
dl_current_state = %lu \n\
dl_sap_length = %ld \n\
dl_service_mode = %lu \n\
dl_qos_length = %lu \n\
dl_qos_offset = %lu \n\
dl_qos_range_length = %lu \n\
dl_qos_range_offset = %lu \n\
dl_provider_style = %lu \n\
dl_addr_offset = %lu \n\
dl_version = %lu \n\
dl_brdcst_addr_length = %lu \n\
dl_brdcst_addr_offset = %lu \n\
dl_growth = %lu \n",
ai->dl_primitive,
ai->dl_max_sdu,
ai->dl_min_sdu,
ai->dl_addr_length,
ai->dl_mac_type,
ai->dl_reserved,
ai->dl_current_state,
ai->dl_sap_length,
ai->dl_service_mode,
ai->dl_qos_length,
ai->dl_qos_offset,
ai->dl_qos_range_length,
ai->dl_qos_range_offset,
ai->dl_provider_style,
ai->dl_addr_offset,
ai->dl_version,
ai->dl_brdcst_addr_length,
ai->dl_brdcst_addr_offset,
ai->dl_growth);
fflush(fout);
}
void print_netinfo(FILE *fout, netInfo_t *ni, char *s)
{
ipxAdapterInfo_t *ai = &(ni->adapInfo);
if (s != NULL)
fprintf(fout, "\n---- %s ----\n", s);
fprintf(fout, "Lan:%lx, state:%lx, err:%lx, netw:%lx, mux:%lx, node:%x.%x.%x.%x.%x.%x\n",
ni->lan, ni->state, ni->streamError, ni->network,
ni->muxId,
(int)ni->nodeAddress[0],
(int)ni->nodeAddress[1],
(int)ni->nodeAddress[2],
(int)ni->nodeAddress[3],
(int)ni->nodeAddress[4],
(int)ni->nodeAddress[5]);
print_adaptinfo(fout, ai, NULL);
}
#else
#define print_adaptinfo(fout, ai, s)
#define print_netinfo(fout, ni, s)
#endif
int main(int argc, char **argv)
{
int ipx0fd=open("/dev/ipx0", O_RDWR);
if (ipx0fd > -1) {
int lan0fd=open("/dev/lan0", O_RDWR);
if (lan0fd > -1) {
struct strioctl str1, str2, str3, str4;
int ipxfd;
int j = -1;
long max_adapter=0;
netInfo_t netinfo;
long info_req = DL_INFO_REQ;
ipxAdapterInfo_t *ai = &(netinfo.adapInfo);
dl_bind_req_t bind_req;
struct {
dl_bind_ack_t b;
uint8 addr[8]; /* Adresse */
} bind_ack;
int muxid;
int flagsp=0;
int ilen;
struct strbuf cntr1;
#if NET_DEBUG
FILE *fout = fopen("xyz", "w+");
#endif
/* DL_INFO */
cntr1.maxlen = 4;
cntr1.len = 4;
cntr1.buf = (char *)&info_req;
putmsg(lan0fd, &cntr1, NULL, 0);
cntr1.maxlen = sizeof(ipxAdapterInfo_t);
cntr1.len = 0;
cntr1.buf = (char*)ai;
if ((ilen=getmsg(lan0fd, &cntr1, NULL, &flagsp)) > 0) {
char dummy[100];
cntr1.maxlen = sizeof(dummy);
cntr1.len = 0;
cntr1.buf = dummy;
flagsp = 0;
getmsg(lan0fd, &cntr1, NULL, &flagsp);
fprintf(stderr, "DL_INFO getmsg=%d bzw. %d > 0\n", ilen, cntr1.len);
}
print_adaptinfo(fout, ai, "nach DL_INFO");
/* ----------------------------------------------- */
bind_req.dl_primitive = DL_BIND_REQ;
bind_req.dl_sap = 0x8137; /* SAP Type f<>r NetWare */
bind_req.dl_max_conind = 1;
bind_req.dl_service_mode = DL_CLDLS; /* 2 */
bind_req.dl_conn_mgmt = 0;
bind_req.dl_xidtest_flg = 1;
cntr1.maxlen = sizeof(dl_bind_req_t);
cntr1.len = sizeof(dl_bind_req_t);
cntr1.buf = (char*)&bind_req;
putmsg(lan0fd, &cntr1, NULL, 0);
memset(&bind_ack, 0, sizeof(bind_ack));
bind_ack.b.dl_primitive = DL_BIND_REQ;
cntr1.maxlen = sizeof(bind_ack);
cntr1.len = 0;
cntr1.buf = (char*)&bind_ack;
flagsp = 0;
getmsg(lan0fd, &cntr1, NULL, &flagsp);
fprintf(stderr, "BIND ACK:sap 0x%x, addr_len %d, addr_offs %d\n \
addr=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n" ,
bind_ack.b.dl_sap, bind_ack.b.dl_addr_length, bind_ack.b.dl_addr_offset,
(int)bind_ack.addr[0],
(int)bind_ack.addr[1],
(int)bind_ack.addr[2],
(int)bind_ack.addr[3],
(int)bind_ack.addr[4],
(int)bind_ack.addr[5],
(int)bind_ack.addr[6],
(int)bind_ack.addr[7]);
/* DL_INFO */
cntr1.maxlen = 4;
cntr1.len = 4;
cntr1.buf = (char *)&info_req;
putmsg(lan0fd, &cntr1, NULL, 0);
cntr1.maxlen = sizeof(ipxAdapterInfo_t);
cntr1.len = 0;
cntr1.buf = (char*)ai;
if ((ilen=getmsg(lan0fd, &cntr1, NULL, &flagsp)) > 0) {
char dummy[100];
cntr1.maxlen = sizeof(dummy);
cntr1.len = 0;
cntr1.buf = dummy;
flagsp = 0;
getmsg(lan0fd, &cntr1, NULL, &flagsp);
fprintf(stderr, "DL_INFO getmsg=%d bzw. %d > 0\n", ilen, cntr1.len);
}
print_adaptinfo(fout, ai, "nach DL_INFO 2");
/* ----------------------------------------------- */
str1.ic_cmd = IPX_GET_MAX_CONNECTED_LANS;
str1.ic_timout = 0;
str1.ic_len = 4;
str1.ic_dp = (char*)&max_adapter;
ioctl(ipx0fd, I_STR, &str1);
printf("Max Adapter %ld\n", max_adapter);
muxid = ioctl(ipx0fd, I_LINK, lan0fd); /* LINK */
/*-----------------------------------------------*/
/*
str3.ic_cmd = IPX_SET_FRAME_TYPE_8023;
str3.ic_len = 0;
str3.ic_timout = 5;
str3.ic_dp = 0;
ioctl(ipx0fd, I_STR, &str3);
*/
/*
str2.ic_cmd = IPX_SET_FRAME_TYPE_SNAP;
*/
/*
str2.ic_cmd = IPX_SET_FRAME_TYPE_8022;
*/
str2.ic_timout = 0;
str2.ic_len = sizeof(netinfo);
str2.ic_dp = (char*)&netinfo;
netinfo.lan = 0;
netinfo.state = 0;
netinfo.network = MY_NETWORK;
netinfo.muxId = muxid;
netinfo.nodeAddress[0] = bind_ack.addr[0]; /* 0x00 */
netinfo.nodeAddress[1] = bind_ack.addr[1]; /* 0x80 */
netinfo.nodeAddress[2] = bind_ack.addr[2]; /* 0x48 */
netinfo.nodeAddress[3] = bind_ack.addr[3]; /* 0x83 */
netinfo.nodeAddress[4] = bind_ack.addr[4]; /* 0x14 */
netinfo.nodeAddress[5] = bind_ack.addr[5]; /* 0x3f */
/*
ai->dl_primitive = DL_INFO_REQ ;
ioctl(ipx0fd, I_STR, &str2);
print_netinfo(fout, &netinfo, "nach SET_FRAME");
*/
str3.ic_cmd = IPX_SET_LAN_INFO;
str3.ic_len = sizeof(netinfo);
str3.ic_timout = 5;
str3.ic_dp = (char*)&netinfo;
ioctl(ipx0fd, I_STR, &str3);
print_netinfo(fout, &netinfo, "nach IPX_SET_LAN_INFO");
#if 0
if ((ipxfd = open("/dev/ipx", O_RDWR)) > -1){
int spxfd = open("/dev/nspxd", O_RDWR);
if (spxfd > -1){
int pid=-1;
int akt_pid = getpid();
char *progname = "nwserv";
muxid = ioctl(spxfd, I_LINK, ipxfd);
str4.ic_cmd = IPX_SET_SPX;
str4.ic_len = 0;
str4.ic_timout = 5;
str4.ic_dp = (char*) NULL;
ioctl(spxfd, I_STR, &str4);
close(ipxfd);
pid=fork();
if (pid == 0) { /* Child */
close(spxfd);
close(ipx0fd);
close(lan0fd);
execl(progname, progname, (argc > 1) ? *(argv+1) : NULL, NULL);
/* Falls nicht OK Calling Prozess killen */
kill(akt_pid, SIGTERM);
kill(akt_pid, SIGQUIT);
exit (1);
}
if (pid > -1){
pause();
kill(pid, SIGTERM); /* T”chter killen */
kill(pid, SIGQUIT);
} else perror("nwserv not running");
close(spxfd);
} else {
perror("spx not open");
close(ipxfd);
}
} else perror("ipx not open");
#else
if ((ipxfd = open("/dev/ipx", O_RDWR)) > -1){
int pid=-1;
int akt_pid = getpid();
char *progname = "nwserv";
close(ipxfd);
pid=fork();
if (pid == 0) { /* Child */
close(ipx0fd);
close(lan0fd);
execl(progname, progname, (argc > 1) ? *(argv+1) : NULL, NULL);
/* Falls nicht OK Calling Prozess killen */
kill(akt_pid, SIGTERM);
kill(akt_pid, SIGQUIT);
exit (1);
}
if (pid > -1){
pause();
kill(pid, SIGTERM); /* T”chter killen */
kill(pid, SIGQUIT);
} else perror("nwserv not running");
} else perror("ipx not open");
#endif
close(lan0fd);
#if NET_DEBUG
fclose(fout);
#endif
} else perror("lan0 not open");
close(ipx0fd);
} else perror("ipx0 not open");
}

34
netn.c Normal file
View File

@ -0,0 +1,34 @@
/* netr.c 11-Sep-95 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "net.h"
int main()
{
int ipx_fd = test1(SOCK_NCP);
if (ipx_fd > -1) {
if (t_unbind(ipx_fd) < 0){
t_error("t_unbind !OK");
}
t_close(ipx_fd);
}
return(0);
}

746
nwclient.c Normal file
View File

@ -0,0 +1,746 @@
/* nwclient.c: 12-Nov-95 */
/*
* Einfacher Testclient, wird von nwserv (im Client Modus) gestartet
* Dieses Modul hilft dabei, NCP Responses eines
* echten NW Servers zu analysieren.
* Beim 'echten' NW Server muá 'allow unencryted passwords' gesetzt
* sein.
*/
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "net.h"
static ipxAddr_t serv_addr;
static ipxAddr_t my_addr;
static int fd_ipx;
static int fd_wdog;
static int open_socket()
{
int ipx_fd=t_open("/dev/ipx", O_RDWR, NULL);
struct t_bind bind;
if (ipx_fd < 0) {
t_error("t_open !Ok");
return(-1);
}
U16_TO_BE16(0, my_addr.sock);
bind.addr.len = sizeof(ipxAddr_t);
bind.addr.maxlen = sizeof(ipxAddr_t);
bind.addr.buf = (char*)&my_addr;
bind.qlen = 0; /* immer */
if (t_bind(ipx_fd, &bind, &bind) < 0){
t_error("t_bind !OK");
t_close(ipx_fd);
return(-1);
}
XDPRINTF((0,"socket bound TO %s\n", visable_ipx_adr(&my_addr) ));
return(ipx_fd);
}
static int init_client()
{
return( (fd_ipx = open_socket()) > -1
&& (fd_wdog = open_socket()) > -1 ? 0 : 1);
}
/* DATA OUT */
static IPX_DATA ipxdata_out;
static NCPREQUEST *ncprequest =(NCPREQUEST*)&ipxdata_out;
static uint8 *requestdata=((uint8*)&ipxdata_out)+sizeof(NCPREQUEST);
static void ncp_request(int type, int sequence,
int connection, int task,
int reserved, int function,
int data_len, char *komment)
{
U16_TO_BE16(type, ncprequest->type);
ncprequest->sequence = (uint8) sequence;
ncprequest->connection = (uint8) connection;
ncprequest->task = (uint8) task;
ncprequest->reserved = (uint8) reserved;
ncprequest->function = (uint8) function;
{
int j = data_len;
DPRINTF(("NCP REQUEST: type:0x%x, seq:%d, conn:%d, task:%d, reserved:0x%x, func:0x%x\n",
type, sequence, connection, task, reserved, function));
if (j > 0){
uint8 *p=requestdata;
DPRINTF(("len %d, DATA:", j));
while (j--) {
int c = *p++;
if (c > 32 && c < 127) DPRINTF((",\'%c\'", (char) c));
else DPRINTF((",0x%x", c));
}
DPRINTF(("\n"));
}
}
send_ipx_data(fd_ipx, 17, sizeof(NCPREQUEST) + data_len,
(char *) ncprequest,
&serv_addr, komment);
}
/* DATA IN */
static IPX_DATA ipxdata_in;
static NCPRESPONSE *ncpresponse = (NCPRESPONSE*)&ipxdata_in;
static uint8 *responsedata = ((uint8*)&ipxdata_in) + sizeof(NCPRESPONSE);
/* -------------------------------------- */
static int sequence=0;
static int handle_event(void)
{
struct t_unitdata ud;
ipxAddr_t source_adr;
uint8 ipx_pack_typ;
int flags = 0;
ud.opt.len = sizeof(ipx_pack_typ);
ud.opt.maxlen = sizeof(ipx_pack_typ);
ud.opt.buf = (char*)&ipx_pack_typ; /* bekommt aktuellen Typ */
ud.addr.len = sizeof(ipxAddr_t);
ud.addr.maxlen = sizeof(ipxAddr_t);
ud.addr.buf = (char*)&source_adr;
ud.udata.len = sizeof(IPX_DATA);
ud.udata.maxlen = sizeof(IPX_DATA);
ud.udata.buf = (char*)&ipxdata_in;
if (t_rcvudata(fd_ipx, &ud, &flags) < 0){
struct t_uderr uderr;
ipxAddr_t erradr;
uint8 err_pack_typ;
uderr.addr.len = sizeof(ipxAddr_t);
uderr.addr.maxlen = sizeof(ipxAddr_t);
uderr.addr.buf = (char*)&erradr;
uderr.opt.len = sizeof(err_pack_typ);
uderr.opt.maxlen = sizeof(err_pack_typ);
uderr.opt.buf = (char*)&err_pack_typ; /* bekommt aktuellen Typ */
ud.addr.buf = (char*)&source_adr;
t_rcvuderr(fd_ipx, &uderr);
DPRINTF(("Error from %s, Code = 0x%lx\n", visable_ipx_adr(&erradr), uderr.error));
t_error("t_rcvudata !OK");
return(-1);
} else {
int responselen = ud.udata.len - sizeof(NCPRESPONSE);
int j = responselen;
int sequence = (int)ncpresponse->sequence;
int connection = (int)ncpresponse->connection;
int task = (int)ncpresponse->task;
int reserved = (int)ncpresponse->reserved;
int completition = (int)ncpresponse->completition;
int connect_status = (int)ncpresponse->connect_status;
int type = GET_BE16(ncpresponse->type);
DPRINTF(("Ptyp:%d von: %s, len=%d\n", (int)ipx_pack_typ, visable_ipx_adr(&source_adr), responselen));
DPRINTF(("RESPONSE:t:0x%x, seq:%d, conn:%d, task:%d, res:0x%x, complet.:0x%x, connect:0x%x\n",
type, sequence, connection, task, reserved, completition, connect_status));
if (j > 0){
uint8 *p=responsedata;
DPRINTF(("len %d, DATA:", j));
while (j--) {
int c = *p++;
if (c > 32 && c < 127) DPRINTF((",\'%c\'", (char) c));
else DPRINTF((",0x%x", c));
}
DPRINTF(("\n"));
}
}
if (sequence == ncpresponse->sequence) {
sequence++;
return((int)(ncpresponse->completition));
}
return(-1);
}
/* ------------------------------------------------------ */
static int connection=0;
#define RDATA(xdata, xfunc, xcomment) \
memcpy(requestdata, (xdata), sizeof(xdata)); \
ncp_request(0x2222, sequence, connection, 1, 0, \
(xfunc), sizeof(data), (xcomment))
#define ODATA(xfunc, xcomment) \
ncp_request(0x2222, sequence, connection, 1, 0, \
(xfunc), 0, (xcomment))
#define VDATA(xfunc, xsize, xcomment) \
ncp_request(0x2222, sequence, connection, 1, 0, \
(xfunc), (xsize), (xcomment))
static int get_conn_nr(void)
{
ncp_request(0x1111, sequence, 0xff, 0, 0xff, 0,
0, "Get Connection Nr.");
if (!handle_event()) {
connection = ncpresponse->connection;
DPRINTF(("NWCLIENT GOT CONNECTION NR:%d\n", connection));
return(0);
}
return(-1);
}
static int get_pkt_size(void)
{
uint8 data[] = {0x4, 0}; /* wanted ?? SIZE */
RDATA(data, 0x21, "Get Pktsize");
if (!handle_event()) {
DPRINTF(("NWCLIENT GOT PACKET SIZE =:%d\n", (int)GET_BE16(responsedata)));
return(0);
}
return(-1);
}
static int get_server_info(void)
{
uint8 data[] = {0, 1, 0x11};
RDATA(data, 0x17, "Get FileServer Info");
if (!handle_event()) {
DPRINTF(("NWCLIENT GOT SERVER INFO von=:%s\n", responsedata ));
return(0);
}
return(-1);
}
static int do_17_17(void)
{
uint8 data[] = {0, 1, 0x17};
RDATA(data, 0x17, "Do_17_17");
if (!handle_event()) {
return(0);
}
return(-1);
}
static int get_network_serial_number(void)
{
uint8 data[] = {0, 1, 0x12};
RDATA(data, 0x17, "Get Network Serial Number");
if (!handle_event()) return(0);
return(-1);
}
static int get_connect(void)
{
ODATA(0x19, "get CONNECT ??");
if (!handle_event()) {
return(0);
}
return(-1);
}
static int get_server_time(void)
{
ODATA(0x14, "get SERVER TIME");
if (!handle_event()) {
return(0);
}
return(-1);
}
typedef struct {
uint8 volume;
uint8 dir_id[2];
} DIR_IDS;
static int file_search_init(DIR_IDS *di, int dirhandle, char *path)
{
uint8 *p=requestdata;
int pathlen=path ? strlen(path) : 0;
*p++ = (uint8) dirhandle;
*p++ = (uint8) pathlen;
if (pathlen) memcpy(p, path, pathlen);
VDATA(0x3e, pathlen+2, "FILE SEARCH INIT");
if (!handle_event()) {
if (di) memcpy(di, responsedata, 3);
DPRINTF(("NWCLIENT GOT FILES SEARCH INIT HANDLE=:%d\n",
(int)GET_BE16(responsedata+1) ));
return( (int) *(responsedata+3) ); /* access */
}
return(-1);
}
static int file_search_cont(DIR_IDS *di, int seq,
int attrib, char *path)
{
uint8 *p=requestdata;
int pathlen=path ? strlen(path) : 0;
memcpy(p, di, 3);
p+=3;
U16_TO_BE16((uint16)seq, p);
p+=2;
*p++ = (uint8) attrib;
*p++ = (uint8) pathlen;
if (pathlen) memcpy(p, path, pathlen);
VDATA(0x3f, pathlen+7, "FILE SEARCH CONT");
if (!handle_event()) {
int dir_id = GET_BE16(responsedata+2);
seq = GET_BE16(responsedata);
DPRINTF(("GOT SEARCH CONT dir_id=%d, seq=%d\n", dir_id, seq));
return(seq);
}
return(-1);
}
static int allocate_dir_handle(int dirhandle,
int drive,
char *path,
int temp)
{
uint8 *p=requestdata;
uint8 pathlen= (path) ? strlen(path) : 0;
*p++ = 0;
*p++ = pathlen+4;
if (!temp) *p++ = 0x12; /* permanent */
else if (temp == 1) *p++=0x13; /* temp */
else *p++ = 0x16; /* spez. temp */
*p++ = dirhandle;
*p++ = drive;
*p++ = pathlen;
memcpy(p, path, pathlen);
VDATA(0x16, pathlen+6 , "ALLOCATE DIR HANDLE");
if (!handle_event()) return((int) *responsedata);
return(-1);
}
static void scan_irgendwas(int dirhandle, int attrib, char *name)
{
uint8 *p = requestdata;
int namlen = strlen(name);
*p++ = 0;
*p++ = namlen+6;
*p++ = 0x0f;
U16_TO_BE16(MAX_U16, p);
p+=2;
*p++ = dirhandle;
*p++ = attrib;
*p++ = namlen;
memcpy(p, name, namlen);
VDATA(0x16, namlen+8, "SCAN IRGENDWAS");
if (!handle_event()) {
;
}
}
static void scan_file_trustees(int dirhandle, int attrib, char *name)
{
uint8 *p = requestdata;
int namlen = strlen(name);
*p++ = 0;
*p++ = namlen+8;
*p++ = 0x1e;
*p++ = dirhandle;
*p++ = attrib;
U32_TO_BE32(MAX_U32, p);
p+=4;
*p++ = namlen;
memcpy(p, name, namlen);
VDATA(0x16, namlen+10, "SCAN FILE TRUST");
if (!handle_event()) {
;
}
}
static int get_dir_path(int dirhandle)
{
uint8 *p=requestdata;
*p++ = 0;
*p++ = 2;
*p++ = 1;
*p = (uint8) dirhandle;
VDATA(0x16, 4, "GET DIR PATH");
if (!handle_event()) {
;
}
return(0);
}
static void get_connection_info(int conn)
/* liefert Connection INFO */
{
uint8 *p=requestdata;
*p++ = 0;
*p++ = 2;
*p++ = 0x16;
*p = (uint8) conn;
VDATA(0x17, 4, "GET CONNECTION INFO");
if (!handle_event()) {
;;
}
}
static int get_bindery_access(void)
/* liefert ACCESS LEVEL und CONNECTION BIND ID */
{
uint8 data[] = {0, 1, 0x46};
RDATA(data, 0x17, "Get Bindery ACCESS ??");
if (!handle_event()) {
return(0);
}
return(-1);
}
static int scan_bindery_object(int type, char *name, uint32 lastid)
{
uint8 *p = requestdata;
int namlen = strlen(name);
*p++ = 0;
*p++ = namlen+8;
*p++ = 0x37;
U32_TO_BE32(lastid, p);
p+=4;
U16_TO_BE16(type, p);
p+=2;
*p++=namlen;
memcpy(p, name, namlen);
VDATA(0x17, namlen+10,"Scan Bindery Object");
if (!handle_event()) {
;
}
return(0);
}
static int scan_bindery_property(int type, char *name, char *propname, uint32 *lastid)
{
uint8 *p = requestdata;
int namlen = strlen(name);
int propnamlen = strlen(propname);
*p++ = 0;
*p++ = namlen+9 + propnamlen;
*p++ = 0x3c;
U16_TO_BE16(type, p);
p+=2;
*p++ = namlen;
memcpy(p, name, namlen);
U32_TO_BE32(*lastid, (p+=namlen));
*(p+=4) = propnamlen;
memcpy(++p, propname, propnamlen);
VDATA(0x17, namlen+propnamlen+11,"Scan Bindery Property");
if (!handle_event()) {
/*
*lastid = GET_BE32(responsedata + 20);
*/
*lastid = GET_BE32(responsedata + 18);
return(0);
} else return(-1);
}
static int get_bindery_object_id(int type, char *name)
{
uint8 *p = requestdata;
int namlen = strlen(name);
*p++ = 0;
*p++ = namlen+4;
*p++ = 0x35;
U16_TO_BE16(type, p);
p+=2;
*p++=namlen;
memcpy(p, name, namlen);
VDATA(0x17, namlen+6, "GET BINDERY OBJECT ID");
if (!handle_event()) {
DPRINTF(("GOT BIND OBJ ID=0x%lx\n", GET_BE32(responsedata)));
}
return(0);
}
static void send_console_broadcast(char *message)
{
uint8 *p = requestdata;
int len = strlen(message);
*p++ = 0;
*p++ = len+3;
*p++ = 0xd1;
U16_TO_BE16(len, p);
p+=2;
memcpy(p, message, len);
VDATA(0x17, len+5, "SEND CONSOLE BROADCAST");
if (!handle_event()) {
;;
}
}
static int get_bindery_object_name(uint32 id)
{
uint8 *p = requestdata;
*p++ = 0;
*p++ = 5;
*p++ = 0x36;
U32_TO_BE32(id, p);
VDATA(0x17, 7, "GET BINDERY OBJECT NAME");
if (!handle_event()) {
;
}
return(0);
}
static int get_volume_restriction_for_obj(uint32 id, int volnr)
{
uint8 *p = requestdata;
*p++ = 0;
*p++ = 6;
*p++ = 0x29;
*p++ = (uint8)volnr;
U32_TO_BE32(id, p);
VDATA(0x16, 8, "GET VOLUME RESTRICTION FOR OBJ");
if (!handle_event()) {
;
}
return(0);
}
static int login_object(int type, char *name, char *password)
{
uint8 *p = requestdata;
int namlen = strlen(name);
int passlen = (password) ? strlen(password) : 0;
*p++ = 0;
*p++ = namlen+passlen+5;
*p++ = 0x14;
U16_TO_BE16(type, p);
p+=2;
*p++ = namlen;
memcpy(p, name, namlen);
p += namlen;
if (passlen) memcpy(p, password, passlen);
else *p=0;
VDATA(0x17, namlen+7+passlen, "LOGIN OBJECT");
if (!handle_event()) {
;
}
return(0);
}
static void test_xx()
{
uint8 data[] = {0x0,0x1c,0xf,0xff,0xff,0x0,0x0,0x16,'S','Y','S',':','S','Y','S','T','E','M','\\','N','E','T','$','O','B','J','.','O','L','D'} ;
RDATA(data, 0x17, "test_xx");
if (!handle_event()) {
;
}
}
static int open_datei(int dirhandle, int attrib, int ext_attrib, char *name)
{
uint8 *p = requestdata;
int namlen = strlen(name);
*p++ = dirhandle;
*p++ = attrib;
*p++ = ext_attrib;
*p++ = namlen;
memcpy(p, name, namlen);
VDATA(0x4c, namlen+4, "OPEN_DATEI");
if (!handle_event()) {
return( (int) GET_BE32(responsedata));
} else return(-1);
}
static int read_datei(int fh, int offs, int size)
{
uint8 *p = requestdata;
*p++ = 0;
U32_TO_BE32(fh, p);
p+=6;
U32_TO_BE32(offs, p);
p+=4;
U16_TO_BE16(size, p);
VDATA(0x48, 13, "READ_DATEI");
if (!handle_event()) {
return( (int) GET_BE16(responsedata));
} else return(-1);
}
static void test1(void)
{
int dirhandle = allocate_dir_handle(0, 'F', "SYS:PUBLIC", 0);
if (dirhandle > -1) {
scan_file_trustees(dirhandle, 6, "NET$LOG.DAT");
scan_irgendwas(dirhandle, 6, "NET$LOG.DAT");
}
}
static void test2(void)
{
DIR_IDS di;
if (file_search_init(&di, 1, "\\MAIL") > -1) {
file_search_cont(&di, 0xffff, 0x10, "\252");
}
}
static void teste_reads(void)
{
int fh = open_datei(0, 0x4e, 0x11, "SYS:/LOGIN/SLIST.EXE");
int gelesen=0;
if (fh > -1) {
int offs=0;
int size = read_datei(fh, offs, 0x200);
while (size > 0) {
offs +=size;
gelesen+=size;
size = read_datei(fh, offs, 0x200);
}
}
DPRINTF(("%d Bytes readed\n", gelesen));
}
static void test_wdog(void)
{
struct t_unitdata ud;
ipxAddr_t source_adr;
IPX_DATA ipx_data_buff;
uint8 ipx_pack_typ;
int flags = 0;
ud.opt.len = sizeof(ipx_pack_typ);
ud.opt.maxlen = sizeof(ipx_pack_typ);
ud.opt.buf = (char*)&ipx_pack_typ; /* bekommt aktuellen Typ */
ud.addr.len = sizeof(ipxAddr_t);
ud.addr.maxlen = sizeof(ipxAddr_t);
ud.addr.buf = (char*)&source_adr;
ud.udata.len = sizeof(IPX_DATA);
ud.udata.maxlen = sizeof(IPX_DATA);
ud.udata.buf = (char*)&ipx_data_buff;
while (1) {
if (t_rcvudata(fd_wdog, &ud, &flags) < 0){
struct t_uderr uderr;
ipxAddr_t erradr;
uint8 err_pack_typ;
uderr.addr.len = sizeof(ipxAddr_t);
uderr.addr.maxlen = sizeof(ipxAddr_t);
uderr.addr.buf = (char*)&erradr;
uderr.opt.len = sizeof(err_pack_typ);
uderr.opt.maxlen = sizeof(err_pack_typ);
uderr.opt.buf = (char*)&err_pack_typ; /* bekommt aktuellen Typ */
ud.addr.buf = (char*)&source_adr;
t_rcvuderr(fd_ipx, &uderr);
DPRINTF(("Error from %s, Code = 0x%lx\n", visable_ipx_adr(&erradr), uderr.error));
t_error("t_rcvudata !OK");
return;
} else {
DPRINTF(("WDOG Packet von:%s, len=%d connid=%d, status=%d\n",
visable_ipx_adr(&source_adr),
(int)ud.udata.len, (int) ipx_data_buff.wdog.connid,
(int)ipx_data_buff.wdog.status));
if (ipx_data_buff.wdog.status == '?') {
ipx_data_buff.wdog.status = 'Y';
send_ipx_data(fd_wdog, 17, 2,
(char *) &ipx_data_buff,
&source_adr, "WDOG REPLY");
}
}
}
}
/* --------------------------------------------------------- */
int main(int argc, char **argv)
{
nw_debug = 1; /* dieses Modul dient nur zum Debuggen !! */
if (argc != 3) {
fprintf(stderr, "usage: nwclient MY_ADDR SERVER_ADDR\n");
exit(1);
}
DPRINTF(("NWCLIENT MYADDR=%s, SERVER=%s \n", *(argv+1), *(argv+2) ));
adr_to_ipx_addr(&my_addr, *(argv+1));
adr_to_ipx_addr(&serv_addr, *(argv+2));
if (init_client()) exit(1);
/* ------------------------------------------ */
get_conn_nr();
get_server_info();
get_pkt_size();
get_connect();
get_server_time();
file_search_init(NULL, 1, NULL);
get_bindery_access();
get_bindery_object_id(1, "SUPERVISOR");
do_17_17();
login_object(1, "SUPERVISOR", NULL);
get_network_serial_number();
get_bindery_access();
scan_bindery_object(1, "*", MAX_U32);
scan_bindery_object(1, "*", 1);
{
uint32 lastid = MAX_U32;
while (!scan_bindery_property(1, "NOBODY", "*", &lastid));;
}
get_volume_restriction_for_obj(1, 0);
test1();
test2();
get_connection_info(0);
get_connection_info(1);
get_connection_info(2);
get_connection_info(3);
send_console_broadcast("Hello Console !!!!");
teste_reads();
test_wdog();
/*-----------------------------------------------*/
t_unbind(fd_ipx);
t_close(fd_ipx);
t_unbind(fd_wdog);
t_close(fd_wdog);
return(0);
}

1370
nwconn.c Normal file

File diff suppressed because it is too large Load Diff

1161
nwdbm.c Normal file

File diff suppressed because it is too large Load Diff

170
nwdbm.h Normal file
View File

@ -0,0 +1,170 @@
/* nwdbm.h 11-Sep-95 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define NETOBJ_KEY_SIZE 4
typedef struct {
uint32 id; /* Objekt ID */
/* --------------- */
uint8 name[48];
uint16 type;
uint8 flags; /* statisch, dynamisch */
uint8 security;
} NETOBJ;
#define NETPROP_KEY_SIZE 5
typedef struct {
uint32 obj_id; /* ID OBJECT */
uint8 id; /* PROPERTY id */
/* --------------- */
uint8 name[16];
uint8 flags; /* statisch, dynamisch */
uint8 security;
} NETPROP;
#define NETVAL_KEY_SIZE 6
typedef struct {
uint32 obj_id; /* ID OBJECT */
uint8 prop_id; /* PROPERTY id */
uint8 segment; /* Segment Nr */
/* --------------- */
uint8 value[128]; /* Inhalt */
} NETVAL;
/* Object Flags */
#define O_FL_STAT 0x0
#define O_FL_DYNA 0x1
/* Property Flags */
/* BIT 7 */
#define P_FL_STAT 0x0
#define P_FL_DYNA 0x1
/* BIT 6 */
#define P_FL_ITEM 0x0
#define P_FL_SET 0x2
extern int nw_get_prop(int object_type,
uint8 *object_name, int object_namlen,
int segment_nr,
uint8 *prop_name, int prop_namlen,
uint8 *property_value,
uint8 *more_segments,
uint8 *property_flags);
extern int find_obj_id(NETOBJ *o, uint32 last_obj_id);
extern int nw_delete_obj(NETOBJ *obj);
extern int nw_rename_obj(NETOBJ *o, uint8 *newname);
extern int nw_change_obj_security(NETOBJ *o, int newsecurity);
extern int nw_get_obj(NETOBJ *o);
extern int prop_find_member(uint32 obj_id, int prop_id, uint32 member_id);
extern int prop_add_member(uint32 obj_id, int prop_id, uint32 member_id);
extern int prop_delete_member(uint32 obj_id, int prop_id, uint32 member_id);
extern int ins_prop_val(uint32 obj_id, uint8 prop_id, int segment,
uint8 *property_value, int erase_segments);
extern int nw_get_prop_val_by_obj_id(uint32 obj_id,
int segment_nr,
uint8 *prop_name, int prop_namlen,
uint8 *property_value,
uint8 *more_segments,
uint8 *property_flags);
extern int nw_get_prop_val(int object_type,
uint8 *object_name, int object_namlen,
int segment_nr,
uint8 *prop_name, int prop_namlen,
uint8 *property_value,
uint8 *more_segments,
uint8 *property_flags);
extern int nw_delete_property(int object_type,
uint8 *object_name, int object_namlen,
uint8 *prop_name, int prop_namlen);
extern int nw_is_obj_in_set(int object_type,
uint8 *object_name, int object_namlen,
uint8 *prop_name, int prop_namlen,
int member_type,
uint8 *member_name, int member_namlen);
extern int nw_add_obj_to_set(int object_type,
uint8 *object_name, int object_namlen,
uint8 *prop_name, int prop_namlen,
int member_type,
uint8 *member_name, int member_namlen);
extern int nw_delete_obj_from_set(int object_type,
uint8 *object_name, int object_namlen,
uint8 *prop_name, int prop_namlen,
int member_type,
uint8 *member_name, int member_namlen);
extern int nw_write_prop_value(int object_type,
uint8 *object_name, int object_namlen,
int segment_nr, int erase_segments,
uint8 *prop_name, int prop_namlen,
uint8 *property_value);
extern int nw_change_prop_security(int object_type,
uint8 *object_name, int object_namlen,
uint8 *prop_name, int prop_namlen,
int prop_security);
extern int nw_scan_property(NETPROP *prop,
int object_type,
uint8 *object_name,
int object_namlen,
uint8 *prop_name,
int prop_namlen,
uint32 *last_scan);
extern int nw_create_obj(NETOBJ *obj, uint32 wanted_id);
extern int nw_obj_has_prop(NETOBJ *obj);
extern int nw_create_obj_prop(NETOBJ *obj, NETPROP *prop);
extern int nw_create_prop(int object_type,
uint8 *object_name, int object_namlen,
uint8 *prop_name, int prop_namlen,
int prop_flags, int prop_security);
extern uint32 nw_new_create_prop(uint32 wanted_id,
char *objname, int objtype, int objflags, int objsecurity,
char *propname, int propflags, int propsecurity,
char *value, int valuesize);
extern void nw_init_dbm(char *servername, ipxAddr_t *adr);

1014
nwserv.c Normal file

File diff suppressed because it is too large Load Diff

214
tools.c Normal file
View File

@ -0,0 +1,214 @@
/* tools.c 18-Nov-95 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "net.h"
#include <stdarg.h>
#include <sys/vfs.h>
int nw_debug=0;
char *xmalloc(uint size)
{
char *p = (size) ? (char *)malloc(size) : (char*)NULL;
if (p == (char *)NULL && size){
fprintf(stderr, "not enough core, need %d Bytes\n", size);
exit(1);
}
return(p);
}
void x_x_xfree(char **p)
{
if (*p != (char *)NULL){
free(*p);
*p = (char*)NULL;
}
}
int strmaxcpy(char *dest, char *source, int len)
{
int slen = (source != (char *)NULL) ? min(len, strlen(source)) : 0;
if (slen) memcpy(dest, source, slen);
dest[slen] = '\0';
return(slen);
}
int x_x_xnewstr(uint8 **p, uint8 *s)
{
int len = (s == NULL) ? 0 : strlen(s);
if (*p != (uint8 *)NULL) free((char*)*p);
*p = (uint8*)xmalloc(len+1);
if (len) strcpy((char*)(*p), (char*)s);
else **p = '\0';
return (len);
}
void dprintf(char *p, ...)
{
va_list ap;
if (nw_debug){
va_start(ap, p);
vprintf(p, ap);
va_end(ap);
fflush(stdout);
}
}
void xdprintf(int dlevel, char *p, ...)
{
va_list ap;
if (nw_debug >= dlevel) {
va_start(ap, p);
vprintf(p, ap);
va_end(ap);
fflush(stdout);
}
}
FILE *open_nw_ini(void)
{
char *fname=FILENAME_NW_INI;
FILE *f=fopen(fname, "r");
if (f == (FILE*)NULL) fprintf(stderr, "Cannot open ini file `%s`\n", fname);
return(f);
}
int get_ini_entry(FILE *f, int entry, char *str, int strsize)
/* liefert ini_entry zurueck bzw. 0, falls nichts gefunden */
{
char buff[512];
int do_open = ((FILE*) NULL == f);
if (do_open) f = open_nw_ini();
if ((FILE*) NULL != f) {
while (fgets((char*)buff, sizeof(buff), f) != NULL){
int len = strlen(buff);
char *ppi = NULL;
int se = 0;
int j = -1;
while (++j < len){
char *pp=(buff+j);
if (*pp == '#' || *pp == '\r' || *pp == '\n') {
*pp = '\0';
len = j;
break;
} else if ( *pp == 32 || *pp == '\t') {
if (!se) se = j;
} else if ((!ppi) && se) {
ppi = pp;
}
}
if (len > se+1 && se > 0 && se < 4 && ppi){
char sx[10];
int fentry;
strmaxcpy(sx, buff, se);
fentry = atoi(sx);
if (fentry > 0 && ((!entry) || entry == fentry)) {
strmaxcpy(str, ppi, strsize-1);
if (do_open) fclose(f);
return(fentry);
}
}
} /* while */
if (do_open) fclose(f);
}
return(0);
}
char *get_exec_path(char *buff, char *progname)
{
sprintf(buff, "%s/%s", PATHNAME_PROGS, progname);
return(buff);
}
void get_ini_debug(int what)
/* what:
* 1 = nwserv
* 2 = ncpserv
* 3 = nwconn
*/
{
char buff[10];
if (get_ini_entry(NULL, 100+what, buff, sizeof(buff))) {
int debug;
if (1==sscanf(buff, "%d", &debug)) nw_debug=debug;
}
}
uint8 down_char(uint8 ch)
{
if (ch > 64 && ch < 91) return(ch + 32);
switch(ch){
case 142: ch = 132; break;
case 153: ch = 148; break;
case 154: ch = 129; break;
default :break;
}
return(ch);
}
uint8 up_char(uint8 ch)
{
if (ch > 96 && ch < 123) return(ch - 32);
switch(ch) {
case 132: ch = 142; break;
case 148: ch = 153; break;
case 129: ch = 154; break;
default : break;
}
return(ch);
}
uint8 *upstr(uint8 *s)
{
if (!s) return((uint8*)NULL);
for (;*s;s++) *s=up_char(*s);
return(s);
}
uint8 *downstr(uint8 *s)
{
if (!s) return((uint8*)NULL);
for (;*s;s++) *s=down_char(*s);
return(s);
}
/* next is stolen from GNU-fileutils */
static long adjust_blocks (long blocks, int fromsize, int tosize)
{
if (fromsize == tosize) /* E.g., from 512 to 512. */
return blocks;
else if (fromsize > tosize) /* E.g., from 2048 to 512. */
return blocks * (fromsize / tosize);
else /* E.g., from 256 to 512. */
return (blocks + (blocks < 0 ? -1 : 1)) / (tosize / fromsize);
}
int get_fs_usage(char *path, struct fs_usage *fsp)
{
struct statfs fsd;
if (statfs (path, &fsd) < 0) return (-1);
#define convert_blocks(b) adjust_blocks ((b), fsd.f_bsize, 512)
fsp->fsu_blocks = convert_blocks (fsd.f_blocks);
fsp->fsu_bfree = convert_blocks (fsd.f_bfree);
fsp->fsu_bavail = convert_blocks (fsd.f_bavail);
fsp->fsu_files = fsd.f_files;
fsp->fsu_ffree = fsd.f_ffree;
return(0);
}

61
tools.h Normal file
View File

@ -0,0 +1,61 @@
/* tools.h : 14-Nov-95 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
extern void x_x_xfree(char **p);
extern int x_x_xnewstr(uint8 **p, uint8 *s);
#define xfree(p) x_x_xfree((char **)&(p))
#define new_str(p, s) x_x_xnewstr((uint8 **)&(p), s)
extern char *xmalloc(uint size);
extern int strmaxcpy(char *dest, char *source, int len);
extern void dprintf(char *p, ...);
extern void xdprintf(int dlevel, char *p, ...);
extern FILE *open_nw_ini(void);
extern int get_ini_entry(FILE *f, int entry, char *str, int strsize);
extern char *get_exec_path(char *buff, char *progname);
extern void get_ini_debug(int what);
extern uint8 down_char(uint8 ch);
extern uint8 up_char(uint8 ch);
extern uint8 *downstr(uint8 *s);
extern uint8 *upstr(uint8 *s);
/* stolen from GNU-fileutils */
/* Space usage statistics for a filesystem. Blocks are 512-byte. */
struct fs_usage {
long fsu_blocks; /* Total blocks. */
long fsu_bfree; /* Free blocks available to superuser. */
long fsu_bavail; /* Free blocks available to non-superuser. */
long fsu_files; /* Total file nodes. */
long fsu_ffree; /* Free file nodes. */
};
extern int get_fs_usage(char *path, struct fs_usage *fsp);
extern int nw_debug;
#ifdef DB
# define DPRINTF(x) dprintf x
# define XDPRINTF(x) xdprintf x
#else
# define DPRINTF(x) /* */
# define XDPRINTF(x) /* */
#endif