mars_nwe-0.96.pl00

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

42
CHANGES Normal file
View File

@ -0,0 +1,42 @@
Sorry, this is in German only. :-(
Aenderungen in mars_nwe bis zum : 20-Dec-95
--------------------------------
Erste 'oeffentliche' Version
^^^^^^^^^^ VERSION 0.94 ^^^^^^^^
???????????????????????????????
^^^^^^^^^^ VERSION 0.95 ^^^^^^^^
- Login's mit Passworteingabe moeglich.
- Benutzer mit verschiedenen Rechten moeglich,
Mapping NW-User -> Linux-User eingebaut.
- nwserv kann zum Daemon werden und logfile wird erzeugt.
- Schalter fuer 'save ipx-routes after server is down' eingebaut.
- Server kann mittels fconsole 'Server-Down' gekillt werden.
---
- Routing Code komplett umgeschrieben. Leider funktioniert
das Einrichten einer internen NETWERK-Number, ala NW 311,
und Einrichten mehrerer IPX-Devices erst nach Patchen des
IPX-Kernel Codes. Wenn der IPX-Kernel Code fuer 1.3.[456]x
wieder ok ist, werde ich das Anpassen bzw. werde ich es mit
dem lwared Kernel Code versuchen.
Falls aber nur ein ipx-interface gebraucht wird, muesste
das IPX-Routing auch ohne IPX-Kernel Patches nun einwandfrei
funktionieren.
---
- Der Server meldet nun allen Workstations, dass er down geht.
Das funktioniert, wenn entweder der *nicht* daemonisierte
nwserv mit ^C abgebrochen wird oder aber der daemonisierte
nwserv ein SIGINT, SIGQUIT od. SIGTERM Signal erhaelt.
- Direktory Scan Fehler korrigiert.
- Ein HUP signal an nwserv bewirkt, dass sowohl nwserv als
auch ncpserv die waerend der Laufzeit sinnvoll veraenderbaren
nw.ini Parameter neu einliest. z.B. :
- Debug Level's
- Print Queues
- User, User passwords
- Server kann sich als 2.15 Server melden oder als 3.11 .
- Drucken mit OLD Job's (pre 3.11) Struktur eingebaut.
^^^^^^^^^^ VERSION 0.96 ^^^^^^^^

49
INSTALL
View File

@ -1,41 +1,34 @@
************** 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 <===================
=========> create programs
1. call make.
2. perhaps you must modify mk.li and config.h
3. call make
=========> configure <===================
=========> configure
modify nw.ini !
=========> install <===================
IMPORTANT !!
Please read examples/nw.ini if you use a new version
of mars_nwe and make the needed changes to your
'ini' or 'conf' file.
=========> 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.
=========> start programs
call nwserv ( as root !! )
tested with Linux Version 1.2.13 and 1.3.32
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.
entry 4 (devices) in the nw.ini file is filled.
=========> stop programs (server down)
If nwserv isn't daemonized, then the server can be stopped
with ^C, otherwise the server must be shut down with a
kill of nwserv or with the right dos client programm
(fconsole server down) as supervisor. Entry 210 in the
nw.ini file gives the time in seconds, before the server
really shuts down.
Viel Erfolg / good Luck :-)
Martin
(mstover@freeway.de)

30
INSTALL.ger Normal file
View File

@ -0,0 +1,30 @@
=========> Programme erzeugen
1. make aufrufen.
2. mk.li und config.h evtl. anpassen
3. make aufrufen.
=========> Konfigurieren
nw.ini bearbeiten !
WICHTIG !!
Bei jeder neuen Version bitte 'examples/nw.ini' kontrollieren
und Aenderungen gegebenfalls in die eigene 'ini' bzw. 'conf'
Datei eintragen.
=========> Installieren
"make install"
evtl. "make install_ini" um eine bereits installierte ini Datei
zu *ueberschreiben* .
=========> Starten
nwserv starten ( als root !! )
mit Linux Version 1.2.13 und 1.3.32 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 Devices (Eintrag 4) enthalten
sind.
=========> Stoppen (server down)
Falls nwserv nicht daemonisiert wurde, kann der Server mit ^C
wieder gestoppt werden, ansonsten muss nwserv per Dos Client
(fconsole server down) gestoppt werden (Supervisor) oder per
'kill' Befehl. Je nach Eintrag 210 in der nw.ini Datei kann
das einige Sekunden dauern.

View File

@ -1,4 +1,4 @@
# Makefile mars_nwe: 16-Nov-95
# Makefile mars_nwe: 06-Dec-95
VPATH=
all: rmeflag mk.li config.h nw.ini
@if [ -r .eflag ] ; then \
@ -64,8 +64,9 @@ 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 $@ ; \
@if [ -r $@ ] ; then echo "NOTE:examples/$@ is newer then $@" > .mk.notes ; \
echo "please compare examples/$@ with $@" >> .mk.notes; \
echo "make the changes you need and touch $@" >> .mk.notes; \
else cp -a examples/$@ . ; \
echo "$@ created (from examples/$@) Please edit $@" > .mk.notes;\
echo "and change it to your requirements." >> .mk.notes ; fi

20
README
View File

@ -18,7 +18,8 @@ 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.
The User SUPERVISOR must be described in the
nw.ini file, entry 12
NETWORK: If there is a real Novell-Server on the
same net-line, then the NETWORK Number of
@ -46,29 +47,20 @@ short description of the processes.
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 - password changings from clients
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)
(mstover@freeway.de)
BTW: The kick to make mars_nwe public was the
publication of linware ( lwared ), the Novell-Server-Emulator

View File

@ -13,9 +13,7 @@ nicht zur Verfuegung, so da
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.
Es werden aber immer weniger. :)
Kernel muss mit IPX Unterstuetzung erzeugt worden sein.
IPX-Routen werden automatisch angelegt.
@ -24,8 +22,8 @@ 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.
gefuellt. Der Supervisor muá in der nw.ini Datei
bestimmt werden (Eintrag 12).
NETWORK: Falls auch ein Novellserver am gleichem
Strang haengt, sollte die NETWORK Nummer
@ -53,38 +51,26 @@ Beschreibung der Prozesse
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 - Passwortaenderungen durch Client ermoeglichen.
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. :)
Viel Spass 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)
(mstover@freeway.de)
PS: Den Anstoss, mars_nwe zu veroeffentlichen, gab die
Veroeffentlichung von linware ( lwared ), dem Novell-Server-Emulator

View File

@ -1,11 +0,0 @@
/* 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_

638
connect.c

File diff suppressed because it is too large Load Diff

399
emutli.c
View File

@ -1,5 +1,4 @@
/* emutli.c 17-Nov-95 */
/* emutli.c 18-Dec-95 */
/*
* One short try to emulate TLI with SOCKETS.
*/
@ -24,7 +23,7 @@
/*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* Some of the Code in this module is stolen from the following
* Programms: ipx_interface, ipx_route, ipx_configure, which was
* Programms: ipx_interface, ipx_route, ipx_configure, which were
* written by Greg Page, Caldera, Inc.
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
@ -58,7 +57,7 @@ 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");
errorp(0, "setsockopt SO_DEBUG", NULL);
}
}
@ -74,194 +73,167 @@ static void ipx2sockadr(struct sockaddr_ipx *so, ipxAddr_t *i)
memcpy(&so->sipx_port, i->sock, 2);
}
void set_emu_tli(int ipx_debug)
void set_emu_tli()
{
locipxdebug = ipx_debug;
int i = get_ini_int(100);
if (i > -1) locipxdebug = i;
}
int init_ipx(char *device,
uint32 *network,
uint32 intnet,
int frame,
char *frame_name,
int ipx_debug)
static int x_ioctl(int sock, int mode, void *id)
{
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);
int result;
int i = 0;
do {
result = ioctl(sock, mode, id);
i++;
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
return(result);
}
void exit_ipx(char *devname, uint32 network, int frame)
static void del_special_net(int special, char *devname, int frame)
/* specials = */
/* IPX_SPECIAL_NONE */
/* IPX_INTERNAL */
/* IPX_PRIMARY */
/* devname + frame only if not IPX_INTERNAL */
{
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);
int sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (sock > -1) {
struct ifreq id;
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
memset(&id, 0, sizeof(struct ifreq));
/* 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);
if (special != IPX_INTERNAL) {
if (devname && *devname) strcpy(id.ifr_name, devname);
sipx->sipx_type = frame;
}
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);
sipx->sipx_network = 0L;
sipx->sipx_special = special;
sipx->sipx_family = AF_IPX;
sipx->sipx_action = IPX_DLTITF;
x_ioctl(sock, SIOCSIFADDR, &id);
close(sock);
}
}
void myipx_route_add(unsigned char *dest_net,
unsigned char *route_net,
unsigned char *route_node)
#define del_internal_net() \
del_special_net(IPX_INTERNAL, NULL, 0)
#define del_interface(devname, frame) \
del_special_net(IPX_SPECIAL_NONE, (devname), (frame))
static void add_special_net(int special,
char *devname, int frame, uint32 netnum, uint32 node)
{
int sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (sock > -1) {
struct ifreq id;
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
memset(&id, 0, sizeof(struct ifreq));
if (special != IPX_INTERNAL){
if (devname && *devname) strcpy(id.ifr_name, devname);
sipx->sipx_type = frame;
} else {
uint32 xx=htonl(node);
memcpy(sipx->sipx_node+2, &xx, 4);
}
sipx->sipx_network = htonl(netnum);
sipx->sipx_special = special;
sipx->sipx_family = AF_IPX;
sipx->sipx_action = IPX_CRTITF;
x_ioctl(sock, SIOCSIFADDR, &id);
close(sock);
}
}
#define add_internal_net(netnum, node) \
add_special_net(IPX_INTERNAL, NULL, 0, (netnum), (node))
#define add_device_net(devname, frame, netnum) \
add_special_net(IPX_SPECIAL_NONE, (devname), (frame), (netnum), 0)
#define add_primary_net(devname, frame, netnum) \
add_special_net(IPX_PRIMARY, (devname), (frame), (netnum), 0)
int init_ipx(uint32 network, uint32 node, int ipx_debug)
{
int result=-1;
int sock=sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (socket < 0) {
errorp(0, "EMUTLI:init_ipx", NULL);
exit(1);
} else {
set_sock_debug(sock);
close(sock);
result=0;
/* makes new internal net */
if (network) {
del_internal_net();
add_internal_net(network, node);
have_ipx_started++;
}
}
return(result);
}
void exit_ipx(int full)
{
int sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (sock > -1) {
/* Switch DEBUG off */
locipxdebug = 0;
set_sock_debug(sock);
close(sock);
}
if (have_ipx_started && full) del_internal_net();
}
int init_dev(char *devname, int frame, uint32 network)
{
if (!network) return(0);
del_interface(devname, frame);
if (!have_ipx_started) {
have_ipx_started++;
add_primary_net(devname, frame, network);
} else
add_device_net(devname, frame, network);
return(0);
}
void exit_dev(char *devname, int frame)
{
del_interface(devname, frame);
}
int get_ipx_addr(ipxAddr_t *addr)
{
int sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
int result=-1;
if (sock > -1) {
struct sockaddr_ipx ipxs;
int maxplen=sizeof(struct sockaddr_ipx);
result=0;
memset((char*)&ipxs, 0, sizeof(struct sockaddr_ipx));
ipxs.sipx_family=AF_IPX;
if (bind(sock, (struct sockaddr*)&ipxs, sizeof(struct sockaddr_ipx))==-1){
errorp(0, "EMUTLI:bind", NULL);
result = -1;
} else {
if (getsockname(sock, (struct sockaddr*)&ipxs, &maxplen) == -1){
errorp(0, "EMUTLI:init_ipx:getsockname", NULL);
result = -1;
} else sock2ipxadr(addr, &ipxs);
}
close(sock);
} else errorp(0, "EMUTLI:bind", NULL);
return(result);
}
void ipx_route_add(uint32 dest_net,
uint32 route_net,
uint8 *route_node)
{
struct rtentry rd;
int i;
int result;
int sock;
/* Router */
@ -270,26 +242,21 @@ void myipx_route_add(unsigned char *dest_net,
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);
st->sipx_network = htonl(dest_net);
sr->sipx_network = htonl(route_net);
memcpy(sr->sipx_node, route_node, IPX_NODE_SIZE);
if ( (sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX)) < 0){
perror("EMUTLI:myipx_route_add");
errorp(0, "EMUTLI:ipx_route_add", NULL);
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) {
if ( 0 != (result = x_ioctl(sock, SIOCADDRT, &rd))) {
switch (errno) {
case ENETUNREACH:
fprintf(stderr, "Router network (%08X) not reachable.\n",
errorp(0, "ROUTE ADD", "Router network (%08X) not reachable.\n",
htonl(sr->sipx_network));
break;
@ -298,39 +265,31 @@ void myipx_route_add(unsigned char *dest_net,
break;
default:
perror("add route ioctl");
errorp(0, "ROUTE ADD", NULL);
break;
}
}
close(sock);
}
void myipx_route_del(unsigned char *net)
void ipx_route_del(uint32 net)
{
struct rtentry rd;
int i;
int result;
int sock;
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);
st->sipx_network = htonl(net);
if ( (sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX)) < 0){
perror("EMUTLI:myipx_route_del");
errorp(0, "EMUTLI:ipx_route_del", NULL);
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 */
x_ioctl(sock, SIOCDELRT, &rd);
close(sock);
}
@ -340,13 +299,11 @@ 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);
set_sock_debug(sock); /* debug switch */
/* NUN DEBUG ein bzw. ausschalten */
set_sock_debug(sock);
/* NUN Broadcast erlauben */
/* Now allow broadcast */
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &opt,sizeof(opt))==-1){
perror("setsockopt SO_BROADCAST");
errorp(0, "setsockopt SO_BROADCAST", NULL);
close(sock);
return(-1);
}
@ -367,18 +324,16 @@ int t_bind(int sock, struct t_bind *a_in, struct t_bind *a_out)
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);
errorp(0, "TLI-BIND", "socket Nr:0x%x", (int)GET_BE16(&(ipxs.sipx_port)));
return(-1);
}
if (a_out != (struct t_bind*) NULL) {
if (getsockname(sock, (struct sockaddr*)&ipxs, &maxplen) == -1){
perror("TLI-GETSOCKNAME");
errorp(0, "TLI-GETSOCKNAME", NULL);
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 ) ));
XDPRINTF((2,"T_BIND ADR=%s\n", visable_ipx_adr((ipxAddr_t *) a_out->addr.buf ) ));
}
return(0);
}
@ -392,7 +347,7 @@ int t_unbind(int sock)
int t_errno=0;
void t_error(char *s)
{
perror(s);
errorp(0, "t_error", s);
t_errno=0;
}
@ -435,8 +390,8 @@ int poll( struct pollfd *fds, unsigned long nfds, int timeout)
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 (0 > (result = select(high_f+1, &readfs, NULL, NULL, &time_out)))
return(-1);
if (result) {
int rest=result;
k = (int)nfds;
@ -444,7 +399,7 @@ int poll( struct pollfd *fds, unsigned long nfds, int timeout)
while (k--){
if (p->fd > -1 && FD_ISSET(p->fd, &readfs)){
p->revents = POLLIN;
if (! --rest) break; /* fertig */
if (! --rest) break; /* ready */
}
p++;
}
@ -487,12 +442,6 @@ int t_sndudata(int fd, struct t_unitdata *ud)
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);
}

View File

@ -42,6 +42,13 @@ typedef struct {
((char *)(a))[5] == ((char*)(b))[5] \
)
#define IPXCMPNET(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] \
)
struct netbuf {
unsigned int maxlen;
unsigned int len;
@ -87,22 +94,22 @@ 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 int init_ipx(uint32 network, uint32 node, int ipx_debug);
extern void exit_ipx(int full);
extern void myipx_route_add(unsigned char *dest_net,
unsigned char *route_net,
unsigned char *route_node);
extern int init_dev(char *devname, int frame, uint32 network);
extern void exit_dev(char *devname, int frame);
extern void myipx_route_del(unsigned char *net);
extern int get_ipx_addr(ipxAddr_t *addr);
extern void set_emu_tli(int ipx_debug);
extern void ipx_route_add(uint32 dest_net,
uint32 route_net,
uint8 *route_node);
extern void ipx_route_del(uint32 net);
extern void set_emu_tli(void);
#ifndef IPX_FRAME_8022
#define OLD_KERNEL_IPX 1

View File

@ -1,9 +1,11 @@
/* 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 */
/* config.h: 10-Dec-95 */
/* some of this config is needed by make, others by cc */
#define FILENAME_NW_INI "/etc/nwserv.conf" /* full name of ini (conf) file */
#define PATHNAME_PROGS "/sbin" /* path location of progs */
#define PATHNAME_BINDERY "/etc" /* path location of bindery */
#define MAX_CONNECTIONS 5 /* max. Number of Connections */
#define MAX_NW_VOLS 10 /* max. Volumes */
#define MAX_CONNECTIONS 5 /* max. Number of Connections */
#define MAX_NW_VOLS 10 /* max. Volumes */
#define MAX_NET_DEVICES 1 /* max. Netdevices, frames */

View File

@ -1,18 +1,19 @@
# (C)opyright 1993, 1995, Martin Stover, Softwareentwicklung, Marburg
# last change: 20-Dec-95
# 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.
# 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 SYS1 /u3/SYS1/ # SYS 2 upshift
#1 TMP /tmp/ k # TMP downshift
#1 CD /cdrom k # CDROM allways downshift
#1 CD /cdrom k # CDROM 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
@ -20,34 +21,68 @@
# 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.
# next entry for later use, not yet supported !!
# the ipx kernel code must changed first, to do good routing !!
# INTERNAL NET [NODE]
###3 0x999999 1 # Node default 1
######################################
# entry 4: # for DEVICE(S)
# if your ipx is allready up, then entry 4 must be removed.
# NETWORK NUMBER, DEVICE, Frame-Typ TICS (default 1)
4 0x10 eth0 802.3 1
# Frames=ethernet_ii, 802.2, 802.3, SNAP (default 802.3)
# testet with 802.3
5 0 # don't = 0, do = 1, save ipx-routes after server is down.
######################################
# some clients are running better, if the server tells
# that it is a 3.11 Server, although many calls
# (namespace services) of a real 3.11 Server are missing yet.
6 0 # tells server version: 2.15=0, 3.11=1
######################################
# GID and UID for _minimal_ rights
# will be used for not logins
10 200 # GID
11 201 # UID
#############################
# entry 21 for simple print queues, dynamic
# the following passwords can be removed after the first
# start, because these entries will be inserted (crypted) into
# the bindery
# one entry 12 for SUPERVISOR
## NW-Name UNIX-Name [PASSWORD]
12 SUPERVISOR root MYPW # Supervisor
#############################
# more entries 13 for other user(s)
## NW-Name UNIX-Name [PASSWORD]
#13 MAR mar # others
#13 ALF mar # others
#############################
# entry 21 for simple print queues
# the queue Directory must exist before printing !!!
# 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)
# >= 100 debug flags,
# 0=nodebug, 1=mindebug(errors), 99=maxdebug
100 0 # debug IPX KERNEL (0 | 1)
101 1 # debug NWSERV
102 0 # debug NCPSERV
103 0 # debug NWCONN
104 0 # debug (start) NWCLIENT
#############################
200 1 # 0 = no logfile and dont daemonize nwserv
# # 1 = daemonize nwserv and use logfile
201 /tmp/nw.log # logfilename
202 1 # creat new logfile=1, append logfile=0
#############################
210 10 # 1 .. 600 (default 10) seconds after server really goes down
# # after a down command

View File

@ -1,13 +1,15 @@
# makefile.unx 15-Nov-95
# makefile.unx 20-Dec-95
VPATH=..
O=.o
C=.c
DEBUG=-DDB
V_H=0
V_L=95
V_L=96
P_L=0
DISTRIB=mars_nwe
PATCHF=$(DISTRIB)p$(V_H).$(V_L)
DISTRIBF=$(DISTRIB)-$(V_H).$(V_L)
PATCHF=$(DISTRIBF).pl$(P_L)
STERN=*
#if 0
@ -77,10 +79,10 @@ M_PATHNAME_PROGS="."
#endif
OBJ1= $(EMUTLIOBJ) net1$(O) tools$(O)
OBJ2= $(OBJ1)
OBJ2= $(OBJ1) nwroute$(O)
#nwdbm$(O)
OBJ3= $(OBJ1) connect$(O)
OBJ4= $(OBJ1) nwdbm$(O)
OBJ3= $(OBJ1) connect$(O) namspace$(O)
OBJ4= $(OBJ1) nwdbm$(O) nwcrypt$(O)
OBJ5= $(OBJ1)
OBJS= net1$(O) tools$(O) connect$(O) nwdbm$(O) \
@ -155,11 +157,14 @@ n_diff: n_clean1
makefile.unx \
Makefile \
COPYING \
CHANGES \
README \
README.ger \
INSTALL \
INSTALL.ger \
$(DISTRIB).lsm \
$(DISTRIB)/. \
; rm -f $(DISTRIB)/config.h \
; ln -f \
examples/$(STERN) \
$(DISTRIB)/examples/. \
@ -169,15 +174,15 @@ n_diff: n_clean1
n_distrib: n_diff
-mkdir /tmp/x
cd .. && (tar cvzf $(DISTRIB).tgz $(DISTRIB) \
; uue $(DISTRIB).tgz \
cd .. && (tar cvzf $(DISTRIBF).tgz $(DISTRIB) \
; uue $(DISTRIBF).tgz; mv -f $(DISTRIB)-$(V_H).uue $(DISTRIBF).uue \
; cp -a $(DISTRIB)/$(DISTRIB).lsm /tmp/yy \
; echo "" >> /tmp/yy \
; echo "" >> /tmp/yy \
; cat $(DISTRIB).uue >> /tmp/yy \
; cat $(DISTRIBF).uue >> /tmp/yy \
; chmod 664 /tmp/yy \
; rm $(DISTRIB).uue \
; mv $(DISTRIB).tgz /tmp/x/. \
; rm $(DISTRIBF).uue \
; mv $(DISTRIBF).tgz /tmp/x/. \
; cp -a $(DISTRIB)/$(DISTRIB).lsm /tmp/x/. \
; cd obj )
@ -186,6 +191,8 @@ n_distrib_bin:
$(PROGS) \
COPYING \
INSTALL \
INSTALL.ger \
CHANGES \
README \
README.ger \
$(DISTRIB).lsm \

View File

@ -1,15 +1,16 @@
Begin3
Title: mars_nwe
Version: 0.95
Entered-date: 22-Nov-95
Version: 0.96
Entered-date: 20-Dec-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)
Keywords: novell, netware, unixware, server, ipx, ncp, tli
Author: mstover@freeway.de (Martin Stover)
Maintained-by: mstover@freeway.de (Martin Stover)
Primary-site: linux01.gwdg.de /pub/ncpfs
80kB mars_nwe-0.96.tgz
Alternate-site: ftp.uni-duisburg.de /pub/linux/ipxware
Platforms: Linux (1.2.xx, 1.3.32 testet, others should work)
Copying-policy: GNU
End

97
namspace.c Normal file
View File

@ -0,0 +1,97 @@
/* namspace.c 26-Nov-95 : NameSpace Services, mars_nwe */
/* (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 nw_generate_dir_path(uint8 *nwpathstruct,
uint8 *ns_dir_base, uint8 *dos_dir_base)
/* returns Volume Number >=0 or errcode < 0 if error */
{
return(-0xfb); /* TODO: complete call */
}
int handle_func_0x57(uint8 *p, uint8 *responsedata)
{
int result = -0xfb; /* unknown request */
int ufunc = (int) *p++; /* now p locates at 4 byte boundary */
int namspace = (int) *p; /* for most calls */
switch (ufunc) {
case 0x02 : /* Initialize Search */
{
/* NW PATH STRUC */
}
break;
case 0x07 : /* Modify File or Dir Info */
{
}
break;
case 0x09 : /* Set short Dir Handle*/
{
}
break;
case 0x15 : /* Get Path String from short dir neu*/
{
}
break;
case 0x16 : /* Generate Dir BASE and VolNumber */
{
uint8 *nwpathstruct = p+3;
struct OUTPUT {
uint8 ns_dir_base[4]; /* BASEHANDLE */
uint8 dos_dir_base[4]; /* BASEHANDLE */
uint8 volume; /* Volumenumber*/
} *xdata= (struct OUTPUT*)responsedata;
result = nw_generate_dir_path(nwpathstruct,
xdata->ns_dir_base, xdata->dos_dir_base);
if (result >-1) {
xdata->volume = result;
result = sizeof(struct OUTPUT);
}
}
break;
case 0x0c : /* alloc short dir Handle */
{
}
break;
case 0x1a : /* Get Huge NS Info new*/
{
}
break;
case 0x1c : /* GetFullPathString new*/
{
}
break;
case 0x1d : /* GetEffDirRights new */
{
}
break;
default : result = -0xfb; /* unknown request */
} /* switch */
return(result);
}

590
ncpserv.c
View File

@ -1,4 +1,4 @@
/* ncpserv.c, 22-Nov-95 */
/* ncpserv.c, 19-Dec-95 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
@ -19,13 +19,7 @@
#include "net.h"
#include "nwdbm.h"
int conn_gid;
int conn_uid;
int nwconn_debug=0;
int ipxdebug=0;
static struct pollfd polls[2];
static int ncp_fd = -1;
static uint8 ipx_in_data[IPX_MAX_DATA+500]; /* space for additional data */
static NCPREQUEST *ncprequest = (NCPREQUEST*)&ipx_in_data;
@ -37,33 +31,66 @@ static ipxAddr_t my_addr;
static int rcv_flags = 0;
static char my_nwname[50];
static time_t akttime;
static int server_goes_down=0;
static void write_to_nwserv(int what, int connection, char *data, int size)
static void write_to_nwserv(int what, int connection, int mode,
char *data, int size)
{
switch (what) {
case 0x2222 : /* insert wdog connection */
write(FD_NWSERV, &what, sizeof(int));
write(FD_NWSERV, &connection, sizeof(int));
write(FD_NWSERV, &size, sizeof(int));
write(FD_NWSERV, data, size); /* ipxAddr_t */
break;
case 0x4444 : /* tell the wdog there's no need to look */
case 0x6666 : /* the connection ist closed */
case 0x8888 : /* send to client that server holds message */
case 0x4444 : /* tell the wdog there's no need to look 0 */
/* fast activate wdog to free connection 1 */
/* slow activate wdog to free connection 2 */
/* the connection ist closed 99 */
write(FD_NWSERV, &what, sizeof(int));
write(FD_NWSERV, &connection, sizeof(int));
write(FD_NWSERV, &mode, sizeof(int));
break;
case 0x6666 : /* send to client that server holds message */
write(FD_NWSERV, &what, sizeof(int));
write(FD_NWSERV, &connection, sizeof(int));
break;
case 0xffff : /* say nwserv to down the server */
write(FD_NWSERV, &what, sizeof(int));
write(FD_NWSERV, &what, sizeof(int));
break;
default : break;
}
}
#define nwserv_insert_wdog(connection, adr) \
write_to_nwserv(0x2222, (connection), 0, (adr), sizeof(ipxAddr_t))
#define nwserv_handle_wdog(connection, mode) \
write_to_nwserv(0x4444, (connection), (mode), NULL, 0)
#define nwserv_reset_wdog(connection) \
write_to_nwserv(0x4444, (connection), 0, NULL, 0)
#define nwserv_close_wdog(connection) \
write_to_nwserv(0x4444, (connection), 99, NULL, 0)
#define nwserv_handle_msg(connection) \
write_to_nwserv(0x6666, (connection), 0, NULL, 0)
#define nwserv_down_server() \
write_to_nwserv(0xffff, 0, 0, NULL, 0)
static int open_ncp_socket()
{
struct t_bind bind;
ncp_fd=t_open("/dev/ipx", O_RDWR, NULL);
if (ncp_fd < 0) {
t_error("t_open !Ok");
if (nw_debug) t_error("t_open !Ok");
return(-1);
}
U16_TO_BE16(SOCK_NCP, my_addr.sock); /* NCP_SOCKET */
@ -72,7 +99,7 @@ static int open_ncp_socket()
bind.addr.buf = (char*)&my_addr;
bind.qlen = 0; /* immer */
if (t_bind(ncp_fd, &bind, &bind) < 0){
t_error("t_bind in open_ncp_socket !OK");
if (nw_debug) t_error("t_bind in open_ncp_socket !OK");
close(ncp_fd);
return(-1);
}
@ -86,7 +113,6 @@ typedef struct {
uint32 object_id; /* logged object */
/* 0 = not logged in */
uint8 crypt_key[8]; /* password generierung */
uint8 message[60]; /* saved BCastmessage */
int sequence; /* previous sequence */
int retry; /* one reply being serviced is sent */
@ -95,12 +121,13 @@ typedef struct {
} CONNECTION;
static CONNECTION connections[MAX_CONNECTIONS];
static int anz_connect=0; /* aktuelle Connections */
static int anz_connect=0; /* actual anz connections */
static int new_conn_nr(void)
{
int j = -1;
if (!anz_connect){ /* alles initialisieren */
int j = -1;
int not_logged=-1;
if (!anz_connect){ /* init all */
j = MAX_CONNECTIONS;
while (j--) {
connections[j].fd = -1;
@ -111,13 +138,26 @@ static int new_conn_nr(void)
}
j = -1;
while (++j < MAX_CONNECTIONS) {
if (connections[j].fd < 0) {
connections[j].message[0] = '\0';
CONNECTION *c=&(connections[j]);
if (c->fd < 0) {
c->message[0] = '\0';
if (++j > anz_connect) anz_connect=j;
return(j);
}
}
return(0); /* nichts frei */
/* nothing free */
j=MAX_CONNECTIONS;
while (j--) {
CONNECTION *c=&(connections[j]);
if (!c->object_id) { /* NOT LOGGED IN */
/* makes wdog test faster */
nwserv_handle_wdog(j+1, 1);
return(0);
}
}
j=0;
while (j++ < MAX_CONNECTIONS) nwserv_handle_wdog(j, 2);
return(0); /* nothing free */
}
int free_conn_nr(int nr)
@ -142,7 +182,7 @@ int find_conn_nr(ipxAddr_t *addr)
void clear_connection(int conn)
{
write_to_nwserv(0x6666, conn, NULL, 0);
nwserv_close_wdog(conn);
if (conn > 0 && --conn < anz_connect) {
CONNECTION *c = &connections[conn];
if (c->fd > -1) {
@ -172,14 +212,14 @@ int find_get_conn_nr(ipxAddr_t *addr)
int fds[2];
memcpy((char*) &(c->client_adr), (char *)addr, sizeof(ipxAddr_t));
if (pipe(fds) < 0) {
perror("find_get_conn_nr, pipe");
errorp(0, "find_get_conn_nr, pipe", NULL);
free_conn_nr(connection);
return(0);
} else {
int akt_pid = getpid();
int pid = fork();
if (pid < 0) {
perror("find_get_conn_nr, fork");
errorp(0, "find_get_conn_nr, fork", NULL);
free_conn_nr(connection);
close(fds[0]);
close(fds[1]);
@ -192,10 +232,6 @@ int find_get_conn_nr(ipxAddr_t *addr)
char pidstr[20];
char connstr[20];
char addrstr[100];
char gidstr[10];
char uidstr[10];
char db_str1[5];
char db_str2[5];
int j = 2;
close(fds[1]); /* no writing */
dup2(fds[0], 0); /* becomes stdin */
@ -205,20 +241,10 @@ int find_get_conn_nr(ipxAddr_t *addr)
sprintf(pidstr, "%d", akt_pid);
sprintf(connstr, "%d", connection);
sprintf(gidstr, "%d", conn_gid);
sprintf(uidstr, "%d", conn_uid);
sprintf(db_str1, "%d", nwconn_debug);
sprintf(db_str2, "%d", ipxdebug);
ipx_addr_to_adr(addrstr, addr);
execl(get_exec_path(pathname, progname), progname,
pidstr, addrstr, connstr,
gidstr, uidstr,
db_str1,
db_str2, NULL);
pidstr, addrstr, connstr, NULL);
exit(1); /* normaly not reached */
}
c->pid = pid;
@ -228,10 +254,23 @@ int find_get_conn_nr(ipxAddr_t *addr)
}
}
}
if (connection) write_to_nwserv(0x2222, connection, (char*)addr, sizeof(ipxAddr_t));
if (connection) nwserv_insert_wdog(connection, (char*)addr);
return(connection);
}
static void sent_down_message(void)
{
int k = -1;
server_goes_down++;
while (++k < anz_connect) {
CONNECTION *cn=&connections[k];
if (cn->fd > -1) {
strmaxcpy(cn->message, "SERVER IS GOING DOWN", 58);
nwserv_handle_msg(k+1);
}
} /* while */
}
static void get_login_time(uint8 login_time[], CONNECTION *cx)
{
struct tm *s_tm = localtime(&(cx->t_login));
@ -262,7 +301,7 @@ static int handle_fxx(CONNECTION *c, int gelen, int func)
uint8 connect_status= 0;
int data_len = 0;
if (nw_debug){
if (nw_debug > 1){
int j = gelen - sizeof(NCPREQUEST);
if (nw_debug){
DPRINTF(("NCP 0x%x REQUEST:ufunc:0x%x\n", func, ufunc));
@ -300,7 +339,7 @@ static int handle_fxx(CONNECTION *c, int gelen, int func)
strmaxcpy(cn->message, msg, min(58, msglen));
result = 0; /* Ok */
} else result = 0xfc; /* server holds message */
write_to_nwserv(0x8888, connr+1, NULL, 0);
nwserv_handle_msg(connr+1);
one_found++;
}
*p++ = (uint8)result;
@ -354,8 +393,8 @@ static int handle_fxx(CONNECTION *c, int gelen, int func)
case 0x11 : { /* Get FileServer Info */
struct XDATA {
uint8 servername[48];
uint8 version; /* 3 */
uint8 subversion; /* 11 */
uint8 version; /* 2 or 3 */
uint8 subversion; /* 15 or 11 */
uint8 maxconnections[2];
uint8 connection_in_use[2];
uint8 max_volumes[2];
@ -372,12 +411,23 @@ static int handle_fxx(CONNECTION *c, int gelen, int func)
uint8 internet_bridge_version;
uint8 reserved[60];
} *xdata = (struct XDATA*) responsedata;
int k, i;
memset(xdata, 0, sizeof(struct XDATA));
strcpy(xdata->servername, my_nwname);
xdata->version = 3;
xdata->subversion = 11;
if (!tells_server_version) {
xdata->version = 2;
xdata->subversion = 15;
} else {
xdata->version = 3;
xdata->subversion = 11;
}
i=0;
for (k=0; k < anz_connect; k++) {
if (connections[k].fd > -1) i++;
}
U16_TO_BE16(i, xdata->connection_in_use);
U16_TO_BE16(MAX_CONNECTIONS, xdata->maxconnections);
U16_TO_BE16(anz_connect, xdata->connection_in_use);
U16_TO_BE16(anz_connect, xdata->peak_connection);
U16_TO_BE16(MAX_NW_VOLS, xdata->max_volumes);
data_len = sizeof(struct XDATA);
} break;
@ -416,15 +466,19 @@ static int handle_fxx(CONNECTION *c, int gelen, int func)
upstr(obj.name);
strmaxcpy(password, (char*)(p1+1),
max(sizeof(password)-1, (int) *p1));
DPRINTF(("LOGIN unencrypted PW NAME='%s', PASSW='%s'\n",
DPRINTF(("TODO:LOGIN unencrypted PW NAME='%s', PASSW='%s'\n",
obj.name, password));
if (0 == (result = find_obj_id(&obj, 0))) {
/* TODO: check password !!!!!!! */
;;
result = 0xff;
}
if (!result) {
c->object_id = obj.id; /* actuell Object ID */
c->t_login = akttime; /* u. login Time */
get_guid(rdata+2, rdata+2+sizeof(int), obj.id);
in_len=12 + 2*sizeof(int);
return(-1); /* nwconn must do the rest */
} else completition = (uint8) -result;
} break;
@ -466,6 +520,8 @@ static int handle_fxx(CONNECTION *c, int gelen, int func)
uint8 *pp = responsedata;
data_len = k;
while (k--) *pp++ = *p++ = (uint8) rand();
/* if all here are same (1 or 2) then the resulting key is */
/* 00000000 */
}
break;
@ -476,14 +532,15 @@ static int handle_fxx(CONNECTION *c, int gelen, int func)
obj.type = GET_BE16(p);
strmaxcpy((char*)obj.name, (char*)(p+3), *(p+2));
upstr(obj.name);
DPRINTF(("LOGIN CRYPTED PW NAME='%s'\n",obj.name));
if (0 == (result = find_obj_id(&obj, 0))) {
/* TODO: check password !!!!!!! */
;;
}
if (!result) {
XDPRINTF((2, "LOGIN CRYPTED PW NAME='%s'\n",obj.name));
if (0 == (result = find_obj_id(&obj, 0)))
result=nw_test_passwd(obj.id, c->crypt_key, rdata);
if (result > -1) {
c->object_id = obj.id; /* actuell Object */
c->t_login = akttime; /* and login time */
get_guid(rdata+2, rdata+2+sizeof(int), obj.id);
in_len=12 + 2*sizeof(int);
return(-1); /* nwconn must do the rest */
} else completition = (uint8) -result;
}
break;
@ -538,15 +595,17 @@ static int handle_fxx(CONNECTION *c, int gelen, int func)
} break;
case 0x34 : { /* rename OBJECT, only SU */
uint8 *p = rdata;
int result;
NETOBJ obj;
uint8 newname[256];
uint8 *p1 = p+3 + *(p+2); /* new Name Length */
obj.type = GET_BE16(p);
strmaxcpy((char*)obj.name, (char*)(p+3), (int) *(p+2));
strmaxcpy((char*)newname, (char*)(p1+1), (int) *(p1));
result = nw_rename_obj(&obj, newname);
int result=-0xff;
if (1 == c->object_id) {
uint8 *p = rdata;
NETOBJ obj;
uint8 newname[256];
uint8 *p1 = p+3 + *(p+2); /* new Name Length */
obj.type = GET_BE16(p);
strmaxcpy((char*)obj.name, (char*)(p+3), (int) *(p+2));
strmaxcpy((char*)newname, (char*)(p1+1), (int) *(p1));
result = nw_rename_obj(&obj, newname);
}
if (result) completition = (uint8) -result;
} break;
@ -622,12 +681,15 @@ static int handle_fxx(CONNECTION *c, int gelen, int func)
case 0x38 : { /* change Bindery Objekt Security */
/* only SU ! */
uint8 *p = rdata;
int result;
NETOBJ obj;
obj.type = GET_BE16(p+1);
strmaxcpy((char*)obj.name, (char*)(p+4), (int) *(p+3));
result = nw_change_obj_security(&obj, (int)*p);
int result= -0xff;
if (1 == c->object_id) {
uint8 *p = rdata;
NETOBJ obj;
obj.type = GET_BE16(p+1);
strmaxcpy((char*)obj.name, (char*)(p+4), (int) *(p+3));
result = nw_change_obj_security(&obj, (int)*p);
}
if (result < 0) completition = (uint8) -result;
} break;
case 0x39 : { /* create Property */
@ -751,9 +813,20 @@ static int handle_fxx(CONNECTION *c, int gelen, int func)
if (result) completition = (uint8) -result;
} break;
case 0x40: { /* change object password */
;
uint8 *p = rdata;
NETOBJ obj;
int result;
obj.type = GET_BE16(p);
strmaxcpy((char*)obj.name, (char*)(p+3), *(p+2));
upstr(obj.name);
if (0 == (result = find_obj_id(&obj, 0))) {
;;
}
if (result < 0) completition = (uint8) -result;
DPRINTF(("TODO: Change Obj PW from OBJECT='%s', result=%d\n",
obj.name, result));
completition=0xff;
} break;
case 0x41 : { /* add Bindery Object to Set */
@ -837,7 +910,7 @@ static int handle_fxx(CONNECTION *c, int gelen, int func)
if (!result) {
*xdata = obj.security;
U32_TO_BE32(obj.id, (xdata+1));
DPRINTF(("ACCESS LEVEL:=0x%x, obj=0x%lx\n",
XDPRINTF((2, "ACCESS LEVEL:=0x%x, obj=0x%lx\n",
(int) obj.security, obj.id));
data_len = 5;
} else completition = (uint8)-result;
@ -882,67 +955,58 @@ static int handle_fxx(CONNECTION *c, int gelen, int func)
break;
case 0x4a : { /* keyed verify password */
uint8 *p = rdata+sizeof(c->crypt_key);
NETOBJ obj;
int result;
uint8 *p = rdata+sizeof(c->crypt_key);
NETOBJ obj;
int result;
obj.type = GET_BE16(p);
strmaxcpy((char*)obj.name, (char*)(p+3), *(p+2));
upstr(obj.name);
DPRINTF(("TODO:Keyed Verify PW from OBJECT='%s'\n",obj.name));
if (0 == (result = find_obj_id(&obj, 0))) {
/* TODO: check password !!!!!!! */
;;
}
if (!result) {
;;;
} else
completition = (uint8) -result;
if (0 == (result = find_obj_id(&obj, 0)))
result=nw_test_passwd(obj.id, c->crypt_key, rdata);
if (result < 0) completition = (uint8) -result;
XDPRINTF((2, "Keyed Verify PW from OBJECT='%s', result=%d\n",
obj.name, result));
}
break;
#if 0
case 0x4b : { /* keyed change pasword */
uint8 *p = rdata+sizeof(c->crypt_key);
uint8 *p = rdata+sizeof(c->crypt_key);
NETOBJ obj;
int result;
uint8 *pw;
int pw_len;
obj.type = GET_BE16(p);
obj.type = GET_BE16(p);
p+=2;
strmaxcpy((char*)obj.name, (char*)(p+1), *p);
upstr(obj.name);
p += (*p+1); /* here is now password */
DPRINTF(("TODO:Keyed Change PW from OBJECT='%s'\n",obj.name));
if (0 == (result = find_obj_id(&obj, 0))) {
/* TODO: check password !!!!!!! */
;;
}
if (!result) {
;;;
/* completition = 0xff; (password not ok) */
} else
completition = 0xff; /* password not ok) */
/* completition = (uint8) -result; */
p += (*p+1); /* here is now password-type ?? 0x60,0x66 */
if (0 == (result = find_obj_id(&obj, 0)))
/*
result=nw_test_passwd(obj.id, c->crypt_key, rdata);
if (result > -1)
*/
result=nw_set_enpasswd(obj.id, p+1);
if (result< 0) completition = (uint8) -result;
DPRINTF(("Keyed Change PW from OBJECT='%s', result=0x%x\n",
obj.name, result));
}
break;
#if 0
case 0x4c : { /* List Relations of an Object */
} break;
#endif
case 0x4c : { /* List Relations of an Object */
DPRINTF(("TODO:List Relations of an Object\n"));
completition=0xfb;
} break;
case 0x64 : { /* Create Queue */
/* !!!!!! TO DO */
DPRINTF(("Create QUEUE ??\n"));
DPRINTF(("TODO:Create QUEUE ??\n"));
} break;
case 0x66 : { /* Read Queue Current Status */
/* !!!!!! TO DO */
NETOBJ obj;
obj.id = GET_BE32(rdata);
DPRINTF(("READ QUEUE STATUS von Q=0x%lx\n", obj.id));
DPRINTF(("TODO:READ QUEUE STATUS von Q=0x%lx\n", obj.id));
completition=0xd5; /* no Queue Job */
}break;
@ -950,7 +1014,7 @@ static int handle_fxx(CONNECTION *c, int gelen, int func)
/* !!!!!! TO DO */
NETOBJ obj;
obj.id = GET_BE32(rdata);
DPRINTF(("GET QUEUE JOB LIST von Q=0x%lx\n", obj.id));
DPRINTF(("TODO:GET QUEUE JOB LIST von Q=0x%lx\n", obj.id));
completition=0xd5; /* no Queue Job */
}break;
@ -962,6 +1026,7 @@ static int handle_fxx(CONNECTION *c, int gelen, int func)
completition=0xd5; /* no Queue Job */
}break;
case 0x68: /* creat queue job and file old */
case 0x79: { /* creat queue job and file */
uint32 q_id = GET_BE32(rdata);
uint8 *dir_name = rdata+4+280+1;
@ -974,6 +1039,8 @@ static int handle_fxx(CONNECTION *c, int gelen, int func)
}
break;
case 0x69: /* close file and start queue old ?? */
case 0x7f: { /* close file and start queue */
uint32 q_id = GET_BE32(rdata);
uint8 *prc = rdata+4+4+1;
@ -992,9 +1059,9 @@ static int handle_fxx(CONNECTION *c, int gelen, int func)
} break;
case 0xc9 : { /* GET FILE SERVER DESCRIPTION STRINGs */
char *company = "Mars";
char *company = "Mars :-)";
char *revision = "Version %d.%d";
char *revision_date= "22-Nov-95";
char *revision_date= "20-Dec-95";
char *copyright = "(C)opyright Martin Stover";
int k=strlen(company)+1;
@ -1036,7 +1103,7 @@ static int handle_fxx(CONNECTION *c, int gelen, int func)
CONNECTION *cc= &(connections[conn]);
if (cc->object_id) { /* if logged */
strmaxcpy(cc->message, msg, min(58, msglen));
write_to_nwserv(0x8888, conn+1, NULL, 0);
nwserv_handle_msg(conn+1);
}
}
}
@ -1050,11 +1117,16 @@ static int handle_fxx(CONNECTION *c, int gelen, int func)
case 0xfd : /* Send Console Broadcast (new) */
return(-1); /* nicht erkannt */
break;
#endif
case 0xd3 : { /* down File Server */
if (c->object_id == 1) { /* only SUPERVISOR */
/* inform nwserv */
nwserv_down_server();
} else completition = 0xff;
}
break;
#endif
default : return(-1); /* not known here */
} /* switch */
} else return(-1); /* not kwown here */
@ -1067,7 +1139,7 @@ static int handle_fxx(CONNECTION *c, int gelen, int func)
ncpresponse->connect_status = connect_status;
data_len=write(c->fd, (char*)ncpresponse,
sizeof(NCPRESPONSE) + data_len);
DPRINTF(("0x%x 0x%x compl:0x%x, write to %d, anz = %d\n",
XDPRINTF((2, "0x%x 0x%x compl:0x%x, write to %d, anz = %d\n",
func, (int)ufunc, (int) completition, c->fd, data_len));
return(0); /* ok */
}
@ -1103,28 +1175,45 @@ static void sig_child(int isig)
int k=-1;
int status;
int pid=wait(&status);
while (++k < anz_connect) {
CONNECTION *c = &connections[k];
if (c->pid == pid) {
clear_connection(k+1);
break;
if (pid > -1) {
while (++k < anz_connect) {
CONNECTION *c = &connections[k];
if (c->pid == pid) {
clear_connection(k+1);
break;
}
}
}
signal(SIGCHLD, sig_child);
}
static int fl_got_hup=0;
static void sig_hup(int rsig)
static void close_all(void)
{
signal(SIGHUP, SIG_IGN);
fl_got_hup++;
signal(SIGHUP, sig_hup);
int k=0;
while (k++ < anz_connect) clear_connection(k);
if (ncp_fd > -1) {
t_unbind(ncp_fd);
t_close(ncp_fd);
XDPRINTF((2, "LEAVE ncpserv\n"));
ncp_fd = -1;
}
}
void set_sig(void)
static void sig_quit(int isig)
{
signal(SIGCHLD, sig_child);
signal(SIGHUP, sig_hup);
close_all();
exit(0);
}
static void set_sig(void)
{
signal(SIGTERM, sig_quit);
signal(SIGQUIT, sig_quit);
signal(SIGINT, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
signal(SIGCHLD, sig_child);
signal(SIGHUP, SIG_IGN);
}
static void handle_bind_calls(uint8 *p)
@ -1160,13 +1249,14 @@ static void handle_bind_calls(uint8 *p)
}
static int handle_ctrl(void)
/* reads stdin pipe */
{
int what;
int conn;
int result = 0;
int data_len = read(0, (char*)&what, sizeof(what));
if (data_len == sizeof(what)) {
DPRINTF(("NCPSERV:GOT CTRL what=0x%x\n", what));
XDPRINTF((2, "NCPSERV:GOT CTRL what=0x%x\n", what));
switch (what) {
case 0x5555 : /* clear_connection */
data_len = read(0, (char*)&conn, sizeof(conn));
@ -1186,50 +1276,39 @@ static int handle_ctrl(void)
break;
case 0xeeee:
get_ini_debug(2);
get_ini_debug(NCPSERV);
nw_fill_standard(NULL, NULL);
break;
case 0xffff : /* server down */
data_len = read(0, (char*)&conn, sizeof(conn));
if (sizeof(int) == data_len && conn == what)
sent_down_message();
break;
default : break;
} /* switch */
result++;
} else DPRINTF(("NCPSERV:GOT CTRL size=%d\n", data_len));
} else XDPRINTF((2, "NCPSERV:GOT CTRL size=%d\n", data_len));
return(result);
}
static void handle_hup(void)
{
signal(SIGHUP, SIG_IGN);
XDPRINTF((2, "HANDLE_HUP_BEGIN\n"));
fl_got_hup = handle_ctrl();
XDPRINTF((2, "HANDLE_HUP_END fl_got_hup=%d\n", fl_got_hup));
signal(SIGHUP, sig_hup);
}
int main(int argc, char *argv[])
{
int result;
int type;
if (argc != 8) {
fprintf(stderr, "usage ncpserv address nwname GID UID debug1 debug2 debug3\n");
int result;
int type;
if (argc != 3) {
fprintf(stderr, "usage ncpserv address nwname\n");
exit(1);
}
init_tools(NCPSERV);
strncpy(my_nwname, argv[1], 48);
my_nwname[47] = '\0';
adr_to_ipx_addr(&my_addr, argv[2]);
nw_init_dbm(my_nwname, &my_addr);
sscanf(argv[3], "%d", &conn_gid);
sscanf(argv[4], "%d", &conn_uid);
sscanf(argv[5], "%d", &nw_debug);
sscanf(argv[6], "%d", &nwconn_debug);
sscanf(argv[7], "%d", &ipxdebug);
#ifdef LINUX
set_emu_tli(ipxdebug);
set_emu_tli();
#endif
if (open_ncp_socket()) exit(1);
ud.opt.len = sizeof(ipx_pack_typ);
ud.opt.maxlen = sizeof(ipx_pack_typ);
@ -1243,106 +1322,129 @@ int main(int argc, char *argv[])
ud.udata.maxlen = IPX_MAX_DATA;
ud.udata.buf = (char*)&ipx_in_data;
set_sig();
fcntl(0, F_SETFL, O_NONBLOCK); /* non blocking input pipe */
polls[0].events = polls[1].events = POLLIN|POLLPRI;
polls[0].revents = polls[1].revents= 0;
polls[0].fd = ncp_fd;
polls[1].fd = 0; /* stdin */
while (1) {
int anz_poll = poll(polls, 2, 60000);
time(&akttime);
if ((result = t_rcvudata(ncp_fd, &ud, &rcv_flags)) > -1){
in_len = ud.udata.len;
if (fl_got_hup) handle_hup();
XDPRINTF((10, "NCPSERV-LOOP von %s\n", visable_ipx_adr(&from_addr)));
if ((type = GET_BE16(ncprequest->type)) == 0x2222 || type == 0x5555) {
int connection = (int)ncprequest->connection;
XDPRINTF((10, "GOT 0x%x in NCPSERV connection=%d\n", type, connection));
if ( connection > 0 && connection <= anz_connect) {
CONNECTION *c = &(connections[connection-1]);
if (!memcmp(&from_addr, &(c->client_adr), sizeof(ipxAddr_t))) {
if (c->fd > -1){
if (type == 0x2222) {
int sent_here = 1;
int func = ncprequest->function;
int diff_time = akttime - c->last_access;
c->last_access = akttime;
if (anz_poll > 0) { /* i have to work */
struct pollfd *p = &polls[0];
int j = -1;
while (++j < 2) {
if (diff_time > 50) /* after max. 50 seconds */
write_to_nwserv(0x4444, connection, NULL,0);
/* tell the wdog there's no need to look */
if (p->revents){
if (!j) { /* ncp-socket */
XDPRINTF((99,"POLL %d\n", p->revents));
if (p->revents & ~POLLIN)
errorp(0, "STREAM error", "revents=0x%x", p->revents );
else {
if ((result = t_rcvudata(ncp_fd, &ud, &rcv_flags)) > -1){
in_len = ud.udata.len;
XDPRINTF((10, "NCPSERV-LOOP von %s\n", visable_ipx_adr(&from_addr)));
if ((type = GET_BE16(ncprequest->type)) == 0x2222 || type == 0x5555) {
int connection = (int)ncprequest->connection;
XDPRINTF((10, "GOT 0x%x in NCPSERV connection=%d\n", type, connection));
if ( connection > 0 && connection <= anz_connect) {
CONNECTION *c = &(connections[connection-1]);
if (!memcmp(&from_addr, &(c->client_adr), sizeof(ipxAddr_t))) {
if (c->fd > -1){
if (type == 0x2222) {
int sent_here = 1;
int func = ncprequest->function;
int diff_time = akttime - c->last_access;
c->last_access = akttime;
if (ncprequest->sequence == c->sequence
&& !c->retry++) {
/* perhaps nwconn is busy */
ncp_response(0x9999, ncprequest->sequence,
connection, 0, 0x0, 0, 0);
DPRINTF(("Send Request being serviced to connection:%d\n", connection));
continue;
}
if (diff_time > 50) /* after max. 50 seconds */
nwserv_reset_wdog(connection);
/* tell the wdog there's no need to look */
if (ncprequest->sequence == c->sequence
&& !c->retry++) {
/* perhaps nwconn is busy */
ncp_response(0x9999, ncprequest->sequence,
connection, 0, 0x0, 0, 0);
XDPRINTF((2, "Send Request being serviced to connection:%d\n", connection));
continue;
}
switch (func) {
case 0x15 : /* Messages */
case 0x17 : /* File Server Environment */
sent_here = handle_fxx(c, in_len, func);
break;
default : break;
} /* switch */
switch (func) {
case 0x15 : /* Messages */
case 0x17 : /* File Server Environment */
sent_here = handle_fxx(c, in_len, func);
break;
default : break;
} /* switch */
if (sent_here) {
int anz=write(c->fd, (char*)ncprequest, in_len);
XDPRINTF((10, "write to %d, anz = %d\n", c->fd, anz));
if (func == 0x19) { /* logout */
c->object_id = 0; /* not LOGGED */
}
}
c->sequence = ncprequest->sequence; /* save last sequence */
c->retry = 0;
continue;
} else { /* 0x5555 */
if ( (uint8) (c->sequence+1) == (uint8) ncprequest->sequence) {
clear_connection(ncprequest->connection);
ncp_response(0x3333,
ncprequest->sequence,
connection,
1, 0x0, 0, 0);
continue;
if (sent_here) {
int anz=write(c->fd, (char*)ncprequest, in_len);
XDPRINTF((10, "write to %d, anz = %d\n", c->fd, anz));
if (func == 0x19) { /* logout */
c->object_id = 0; /* not LOGGED */
}
}
c->sequence = ncprequest->sequence; /* save last sequence */
c->retry = 0;
continue;
} else { /* 0x5555, conection beenden */
if ( (uint8) (c->sequence+1) == (uint8) ncprequest->sequence) {
clear_connection(ncprequest->connection);
ncp_response(0x3333,
ncprequest->sequence,
connection,
1, 0x0, 0, 0);
continue;
}
}
}
XDPRINTF((10, "c->fd = %d\n", c->fd));
}
}
/* here someting is wrong */
XDPRINTF((1, "GOT 0x%x connection=%d of %d conns not OK in NCPSERV\n",
type, ncprequest->connection, anz_connect));
ncp_response(0x3333, ncprequest->sequence,
ncprequest->connection,
0, 0xf9, 0, 0);
} else if (type == 0x1111) {
/* GIVE CONNECTION Nr connection */
int connection = (server_goes_down) ? 0 : find_get_conn_nr(&from_addr);
XDPRINTF((2, "GIVE CONNECTION NR=%d in NCPSERV\n", connection));
if (connection) {
CONNECTION *c = &(connections[connection-1]);
int anz;
c->message[0] = '\0';
c->object_id = 0; /* firsttime set 0 for NOT LOGGED */
c->sequence = 0;
anz=write(c->fd, (char*)ncprequest, in_len);
XDPRINTF((10, "write to oldconn %d, anz = %d\n", c->fd, anz));
} else /* no free connection */
ncp_response(0x3333, 0, 0, 0, 0xf9, 0, 0);
} else {
int connection = (int)ncprequest->connection;
int sequence = (int)ncprequest->sequence;
XDPRINTF((1, "NCPSERV:Got UNKNOWN TYPE: 0x%x\n", type));
ncp_response(0x3333, sequence, connection,
1, 0xfb, 0, 0);
}
}
}
XDPRINTF((10, "c->fd = %d\n", c->fd));
} else if (p->fd==0) { /* fd_ncpserv_in */
XDPRINTF((2,"POLL %d, fh=%d\n", p->revents, p->fd));
if (p->revents & ~POLLIN)
errorp(0, "STREAM error", "revents=0x%x", p->revents );
else handle_ctrl();
}
}
/* here someting is wrong */
XDPRINTF((0, "GOT 0x%x connection=%d of %d conns not OK in NCPSERV\n",
type, ncprequest->connection, anz_connect));
ncp_response(0x3333, ncprequest->sequence,
ncprequest->connection,
0, 0xf9, 0, 0);
} else if (type == 0x1111) {
/* GIVE CONNECTION Nr connection */
int connection = find_get_conn_nr(&from_addr);
DPRINTF(("GIVE CONNECTION NR=%d in NCPSERV\n", connection));
if (connection) {
CONNECTION *c = &(connections[connection-1]);
int anz;
c->message[0] = '\0';
c->object_id = 0; /* firsttime set 0 for NOT LOGGED */
c->sequence = 0;
anz=write(c->fd, (char*)ncprequest, in_len);
XDPRINTF((10, "write to oldconn %d, anz = %d\n", c->fd, anz));
} else /* no free connection */
ncp_response(0x3333, 0, 0, 0, 0xf9, 0, 0);
} else {
int connection = (int)ncprequest->connection;
int sequence = (int)ncprequest->sequence;
XDPRINTF((0, "UNKNOWN TYPE: 0x%x\n", type));
ncp_response(0x3333, sequence, connection,
1, 0xfb, 0, 0);
}
if (! --anz_poll) break;
} /* if */
p++;
} /* while */
} else {
if (fl_got_hup) handle_hup();
else t_error("NCPSERV t_rcvudata");
XDPRINTF((3,"NCPSERV:POLLING ...\n"));
}
}
printf("LEAVE ncpserv\n");
t_unbind(ncp_fd);
t_close(ncp_fd);
close_all();
return(0);
}

76
net.h
View File

@ -48,6 +48,8 @@
# include "emutli.h" /* TLI-EMULATION */
#endif
#include <pwd.h>
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
@ -162,7 +164,7 @@ typedef union {
*
*/
} diaresp;
struct S_NCPRESPONSE {
struct S_NCPRESPONSE { /* size = 8 */
uint8 type[2]; /* 0x3333 */
uint8 sequence;
uint8 connection; /* low connection */
@ -171,7 +173,7 @@ typedef union {
uint8 completition; /* bzw. ERROR CODE */
uint8 connect_status;
} ncpresponse;
struct S_NCPREQUEST {
struct S_NCPREQUEST { /* size = 7 */
uint8 type[2]; /* 0x1111 od 0x2222 */
uint8 sequence;
uint8 connection; /* low connection */
@ -229,6 +231,11 @@ typedef struct S_NCPREQUEST NCPREQUEST;
# define MAX_NW_VOLS 10
#endif
#ifndef MAX_NET_DEVICES
# define MAX_NET_DEVICES 5
#endif
#ifndef FILENAME_NW_INI
# define FILENAME_NW_INI "./nw.ini" /* location of ini (conf) file */
#endif
@ -271,8 +278,8 @@ typedef struct {
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 target_execute_time[6]; /* all 0xff */
uint8 job_entry_time[6]; /* all zero */
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 ? */
@ -283,30 +290,57 @@ typedef struct {
/* 0x10 service restart flag */
/* 0x08 autostart flag */
uint8 job_file_name[14]; /* len + DOS filename */
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 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];
uint8 client_connection;
uint8 client_task;
uint8 client_id[4];
uint8 target_id[4]; /* 0xff, 0xff, 0xff, 0xff */
uint8 target_execute_time[6]; /* all 0xff */
uint8 job_entry_time[6]; /* all zero */
uint8 job_id[2]; /* ?? alles 0 HI-LOW */
uint8 job_typ[2]; /* z.B. Printform HI-LOW */
uint8 job_position; /* zero */
uint8 job_control_flags; /* z.B 0x10 */
/* 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[6];
uint8 server_station;
uint8 server_task;
uint8 server_id[4];
uint8 job_bez[50]; /* "LPT1 Catch" */
uint8 client_area[152];
} QUEUE_JOB_OLD; /* before 3.11 */
typedef struct {
uint8 version; /* normal 0x0 */
uint8 tabsize; /* normal 0x8 */
uint8 anz_copies[2]; /* copies 0x0, 0x01 */
uint8 print_flags[2]; /* 0x0, 0xc0 z.B. with banner */
uint8 max_lines[2]; /* 0x0, 0x42 */
uint8 max_chars[2]; /* 0x0, 0x84 */
uint8 form_name[16]; /* "UNKNOWN" */
uint8 reserved[6]; /* all zero */
uint8 banner_user_name[13]; /* "SUPERVISOR" */
uint8 bannner_file_name[13]; /* "LST:" */
uint8 bannner_header_file_name[14]; /* all zero */
uint8 file_path_name[80]; /* all zero */
} QUEUE_PRINT_AREA;
typedef struct {
uint8 volume;
uint8 base[4]; /* Base or Handle */
@ -387,17 +421,13 @@ 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_get_eff_dir_rights(int dir_handle, uint8 *data, int len, int modus);
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);

36
net1.c
View File

@ -1,4 +1,4 @@
/* net1.c, 11-Sep-95 */
/* net1.c, 10-Dec-95 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
@ -22,9 +22,9 @@
#if HAVE_TLI
void print_t_info(struct t_info *t)
{
DPRINTF(("T_INFO:addr %ld, options %ld, tsdu %ld, etsdu %ld\n",
XDPRINTF((2,"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",
XDPRINTF((2,"connect %ld, discon %ld, servtype %ld\n",
t->connect, t->discon,t->servtype));
#if 0
struct t_info {
@ -42,16 +42,20 @@ void print_t_info(struct t_info *t)
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]);
if (p)
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]);
else
strcpy(str, "net=UNKOWN(NULLPOINTER)");
return(str);
}
void print_ipx_addr(ipxAddr_t *p)
{
DPRINTF(("%s\n", visable_ipx_adr(p)));
XDPRINTF((2,"%s\n", visable_ipx_adr(p)));
}
void print_ud_data(struct t_unitdata *ud)
@ -59,21 +63,21 @@ 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:",
XDPRINTF((2,"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",
XDPRINTF((2,"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));
XDPRINTF((2,"SAP-OPERATION %d\n", sap_operation));
while (data_len >= sizeof(SAPS)){
DPRINTF(("Name:%s:, typ:0x%x\n",saps->server_name,
XDPRINTF((2,"Name:%s:, typ:0x%x\n",saps->server_name,
GET_BE16(saps->server_type)));
print_ipx_addr(&(saps->server_adr));
saps++;
@ -89,7 +93,7 @@ void print_ipx_data(IPX_DATA *p)
void print_sip_data(SIP *sip)
{
DPRINTF(("Name:%s:,response_type:0x%x,server_typ:0x%x\n",sip->server_name,
XDPRINTF((2,"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));
}
@ -151,10 +155,10 @@ int send_ipx_data(int fd, int pack_typ,
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 (comment != NULL) XDPRINTF((2,"%s TO: ", comment));
if (nw_debug > 1) print_ipx_addr(to_addr);
if (t_sndudata(fd, &ud) < 0){
t_error("t_sndudata !OK");
if (nw_debug > 1) t_error("t_sndudata !OK");
return(-1);
}
return(0);

433
nwconn.c
View File

@ -1,4 +1,4 @@
/* nwconn.c 20-Nov-95 */
/* nwconn.c 04-Dec-95 */
/* one process / connection */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
@ -19,10 +19,6 @@
*/
#include "net.h"
static int default_uid=-1;
static int default_gid=-1;
static int ipxdebug=0;
static int father_pid = -1;
static ipxAddr_t from_addr;
@ -48,7 +44,7 @@ static int open_ipx_socket()
struct t_bind bind;
ipx_fd=t_open("/dev/ipx", O_RDWR, NULL);
if (ipx_fd < 0) {
t_error("t_open !Ok");
if (nw_debug) t_error("t_open !Ok");
return(-1);
}
U16_TO_BE16(0, my_addr.sock); /* actual write socket */
@ -57,21 +53,15 @@ static int open_ipx_socket()
bind.addr.buf = (char*)&my_addr;
bind.qlen = 0; /* allways */
if (t_bind(ipx_fd, &bind, &bind) < 0){
t_error("t_bind !OK");
if (nw_debug) t_error("t_bind !OK");
close(ipx_fd);
return(-1);
}
DPRINTF(("NWCONN OpenSocket: %s\n",
XDPRINTF((2, "NWCONN OpenSocket: %s\n",
visable_ipx_adr((ipxAddr_t *) bind.addr.buf)));
return(0);
}
static void set_default_guid(void)
{
setgid(default_gid);
setuid(default_uid);
}
static int ncp_response(int sequence,
int completition, int data_len)
@ -79,13 +69,13 @@ static int ncp_response(int sequence,
ncpresponse->sequence = (uint8) sequence;
ncpresponse->completition = (uint8) completition;
last_sequence = sequence;
DPRINTF(("NWCONN NCP_RESP seq:%d, conn:%d, compl=0x%x TO %s\n",
XDPRINTF((2,"NWCONN NCP_RESP seq:%d, conn:%d, compl=0x%x TO %s\n",
(int)ncpresponse->sequence, (int) ncpresponse->connection, (int)completition,
visable_ipx_adr((ipxAddr_t *) ud.addr.buf)));
ud.udata.len = ud.udata.maxlen = sizeof(NCPRESPONSE) + data_len;
if (t_sndudata(ipx_fd, &ud) < 0){
t_error("t_sndudata in NWCONN !OK");
if (nw_debug) t_error("t_sndudata in NWCONN !OK");
return(-1);
}
return(0);
@ -106,12 +96,13 @@ static void handle_ncp_serv()
if (last_sequence == sequence && ncp_type != 0x1111){ /* send the same again */
if (t_sndudata(ipx_fd, &ud) < 0){
t_error("t_sndudata !OK");
if (nw_debug) t_error("t_sndudata !OK");
}
DPRINTF(("Sequence %d is written twice\n", sequence));
XDPRINTF((2,"Sequence %d is written twice\n", sequence));
return;
}
#if 0
if (!nw_debug && (
/*
function == 0x43 ||
@ -121,30 +112,30 @@ static void handle_ncp_serv()
*/
function == 0x11
) ) nw_debug=1;
#endif
if (nw_debug){
int j = requestlen;
if (nw_debug == 1
if (nw_debug < 10
&& (function==0x48 || function == 0x49)) /* read or write */
nw_debug=0;
if (nw_debug == 2
if (nw_debug < 15
&& (function==0x48)) /* read */
nw_debug=0;
if (nw_debug){
if (nw_debug > 1){
do_druck=2;
DPRINTF(("NCP REQUEST:type:0x%x, seq:%d, task:%d, reserved:0x%x, func:0x%x\n",
XDPRINTF((2,"NCP REQUEST:type:0x%x, seq:%d, task:%d, reserved:0x%x, func:0x%x\n",
ncp_type, sequence, task, reserved, function));
if (j > 0){
uint8 *p=requestdata;
DPRINTF(("len %d, DATA:", j));
XDPRINTF((2,"len %d, DATA:", j));
while (j--) {
int c = *p++;
if (c > 32 && c < 127) DPRINTF((",\'%c\'", (char) c));
else DPRINTF((",0x%x", c));
if (c > 32 && c < 127) XDPRINTF((2,",\'%c\'", (char) c));
else XDPRINTF((2,",0x%x", c));
}
DPRINTF(("\n"));
XDPRINTF((2,"\n"));
}
}
}
@ -212,9 +203,7 @@ static void handle_ncp_serv()
/****** * SetDirektoryHandle *************/
struct INPUT {
uint8 header[7]; /* Requestheader */
uint8 filler; /* 0x0 */
uint8 datalen;
uint8 type; /* 0x0 */
uint8 div[3]; /* 0x0, dlen, typ */
uint8 target_dir_handle; /* Verzeichnis Handle zu „ndern */
uint8 source_dir_handle; /* Verzeichnis Handle */
uint8 pathlen;
@ -230,10 +219,8 @@ static void handle_ncp_serv()
/* Dir_handles */
/******** GetDirektoryPATH ***************/
struct INPUT {
uint8 header[7]; /* Requestheader */
uint8 filler; /* 0x0 */
uint8 datalen; /* 0x2 */
uint8 type; /* 0x1 */
uint8 header[7]; /* Requestheader */
uint8 div[3]; /* 0x0, dlen, typ */
uint8 dir_handle; /* Verzeichnis Handle */
} *input = (struct INPUT *) (ncprequest);
struct XDATA {
@ -245,15 +232,13 @@ static void handle_ncp_serv()
xdata->len = (uint8) result;
data_len = result + 1;
xdata->name[result] = '\0';
DPRINTF(("GetDirektoryPATH=%s\n", xdata->name));
XDPRINTF((2,"GetDirektoryPATH=%s\n", xdata->name));
} else completition = (uint8)-result;
} else if (2 == *p){ /* Scan Direktory Information */
/******** Scan Dir Info ****************/
struct INPUT {
uint8 header[7]; /* Requestheader */
uint8 filler; /* 0x0 */
uint8 datalen; /* */
uint8 type; /* 0x2 */
uint8 div[3]; /* 0x0, dlen, typ */
uint8 dir_handle; /* Verzeichnis Handle */
uint8 sub_dir_nmbr[2]; /* HI LOW */
uint8 len; /* kann auch 0 sein */
@ -276,18 +261,21 @@ static void handle_ncp_serv()
if (result > -1){
xdata->max_right_mask = (uint8)result;
data_len = sizeof(struct XDATA);
DPRINTF(("Scan Dir Info max_right_mask=%d\n", (int)result));
XDPRINTF((2,"Scan Dir Info max_right_mask=%d\n", (int)result));
} else completition = (uint8)-result;
} else if (*p == 0x3){ /* Get Direktory Rights */
/******** Get Eff Dir Rights ****************/
struct XDATA {
uint8 eff_right_mask; /* Effektive Right to Dir, old! */
} *xdata = (struct XDATA*) responsedata;
int result = nw_get_eff_dir_rights((int)*(p+1), p+3, (int)*(p+2));
int result = nw_get_eff_dir_rights(
(int)*(p+1),
p+3,
(int)*(p+2), 0);
if (result > -1) {
xdata->eff_right_mask = (uint8) result;
data_len = 1;
DPRINTF(("Get eff Dir Rights=%d\n", (int)result));
XDPRINTF((2,"Got eff Dir Rights=%d\n", (int)result));
} else completition = (uint8) -result;
} else if (*p == 0x4){ /* Modify Max Right MAsk */
/******** MODIFY MAX RIGHT MASK ****************/
@ -336,9 +324,7 @@ static void handle_ncp_serv()
/******** GetDirektoryPATH ***************/
struct INPUT {
uint8 header[7]; /* Requestheader */
uint8 filler; /* 0x0 */
uint8 datalen;
uint8 type;
uint8 div[3]; /* 0x0, dlen, typ */
uint8 dir_handle; /* Verzeichnis Handle */
uint8 trustee_id[4]; /* Trustee Object ID */
uint8 trustee_right_mask;
@ -402,7 +388,7 @@ static void handle_ncp_serv()
U16_TO_BE16(0, xdata->removable);
}
data_len = sizeof(struct XDATA);
DPRINTF(("GIVE VOLUME INFO von :%s:\n", xdata->name));
XDPRINTF((2,"GIVE VOLUME INFO von :%s:\n", xdata->name));
result = 0;
}
}
@ -410,9 +396,7 @@ static void handle_ncp_serv()
} else if (*p == 0x19){ /* Set Directory Information */
struct INPUT {
uint8 header[7]; /* Requestheader */
uint8 filler; /* 0x0 */
uint8 datalen;
uint8 sub_func;
uint8 div[3]; /* 0x0, dlen, typ */
uint8 dir_handle; /* Verzeichnis Handle */
uint8 trustee_id[4]; /* Trustee Object ID */
uint8 trustee_right_mask;
@ -424,9 +408,7 @@ static void handle_ncp_serv()
} else if (*p == 0x1a){ /* Get Pathname of A Volume Dir Pair */
struct INPUT {
uint8 header[7]; /* Requestheader */
uint8 filler; /* 0x0 */
uint8 datalen;
uint8 sub_func;
uint8 div[3]; /* 0x0, dlen, typ */
uint8 volume;
uint8 dir_entry[2];
} *input = (struct INPUT *) (ncprequest);
@ -434,67 +416,95 @@ static void handle_ncp_serv()
uint8 pathlen;
uint8 pathname;
} *xdata = (struct XDATA*)responsedata;
completition = 0xfb; /* !!!!! Machen !!!! */
} else if (*p == 0x1e){ /* liefert Trustees ?? */
/* des Dir_handles + PATH */
completition = 0xfb; /* !!!!! TODO !!!! */
} else if (*p == 0x1e){
/* SCAN a Directory */
struct INPUT {
uint8 header[7]; /* Requestheader */
uint8 filler; /* 0x0 */
uint8 datalen; /* 0x2 */
uint8 type; /* 0x1e */
uint8 dir_handle; /* Verzeichnis Handle */
uint8 attrib; /* Attrib ?? 0x6 */
uint8 reserve1[4]; /* alles 0xff */
uint8 header[7]; /* Requestheader */
uint8 div[3]; /* 0x0, dlen, typ */
uint8 dir_handle; /* Verzeichnis Handle */
uint8 attrib; /* Search Attrib z.B. 0x6 */
uint8 searchsequence[4]; /* 32 bit */
uint8 len;
uint8 data[2];
} *input = (struct INPUT *) (ncprequest);
NW_FILE_INFO f;
int result = nw_scan_a_directory(
responsedata,
input->dir_handle,
input->data,
input->len,
input->attrib,
GET_BE32(input->searchsequence));
if (result > -1) data_len = result;
else completition = (uint8) (-result);
} else if (*p == 0x1f){
/* SCAN a root dir ???? */
struct INPUT {
uint8 header[7]; /* Requestheader */
uint8 div[3]; /* 0x0, dlen, typ */
uint8 dir_handle; /* Verzeichnis Handle */
uint8 dont_know1; /* ???? 0xc0 */
uint8 dont_know2; /* ???? 0xfa */
} *input = (struct INPUT *) (ncprequest);
int result = nw_scan_a_root_dir(
responsedata,
input->dir_handle);
if (result > -1) data_len = result;
else completition = (uint8) (-result);
} else if (*p == 0x20){ /* scan volume user disk restrictions */
uint8 volnr = *(p+1);
uint32 sequenz = GET_BE32(p+2);
struct XDATA {
uint8 unknown[15];
uint8 namlen;
uint8 name[14];
} *xdata = (struct XDATA*)responsedata;
int len=input->len;
int searchsequence = nw_search( (uint8*)
&(f),
(int)input->dir_handle,
MAX_U16,
(int) input->attrib,
input->data, len);
if (searchsequence > -1){
memset(xdata, 0, 132);
xdata->namlen = min(14, strlen(f.name));
memcpy(xdata->name, f.name, xdata->namlen);
} else completition = (uint8) - searchsequence;
} else if (*p == 0x20){ /* testet ??*/
struct XDATA {
uint8 res1; /* 0x0 */
uint8 entries; /* 0x0 */
/*--- per entry (max.entries = 12) ----*/
uint8 id[4];
uint8 restriction[4];
} *xdata = (struct XDATA*) responsedata;
xdata->res1 = 0x0;
data_len = 1;
xdata->entries = 0x0;
data_len = (8 * xdata->entries) + 1;
} else if (*p == 0x21) {
/* change Vol restrictions for Obj */
uint8 volnr = *(p+1);
uint32 id = GET_BE32(p+2);
uint32 blocks = GET_BE32(p+6);
DPRINTF(("Change vol restriction vol=%d, id=0x%lx, Blocks=0x%lx",
XDPRINTF((2,"TODO:Change vol restriction vol=%d, id=0x%lx, Blocks=0x%lx",
(int)volnr, id, blocks));
} else if (*p == 0x22) {
/* remove Vol restrictions for Obj */
uint8 volnr = *(p+1);
uint32 id = GET_BE32(p+2);
DPRINTF(("Renmove vol restriction vol=%d, id=0x%lx",
XDPRINTF((2,"Renmove vol restriction vol=%d, id=0x%lx",
(int)volnr, id));
} else if (*p == 0x25){ /* setting FILE INFO ??*/
/* TODO !!!!!!!!!!!!!!!!!!!! */
do_druck++;
} else if (*p == 0x27){ /* Add Trustees to DIR ?? */
} else if (*p == 0x26) { /* Scan file or Dir for ext trustees */
int sequenz = (int)*(p+2); /* trustee sequenz */
struct XDATA {
uint8 entries;
uint8 ids[80]; /* 20 id's */
uint8 trustees[40]; /* 20 trustees's */
} *xdata = (struct XDATA*) responsedata;
int result = nw_get_eff_dir_rights(
(int)*(p+1),
p+4,
(int)*(p+3), 1);
if (result > -1){
if (!sequenz) {
memset(xdata, 0, sizeof(struct XDATA));
xdata->entries=1;
U32_TO_BE32(1, xdata->ids); /* SUPERVISOR */
xdata->trustees[1] = 0x1; /* Supervisory */
xdata->trustees[0] = 0xff; /* all low */
data_len = sizeof(struct XDATA);
} else completition = 0x9c; /* no more trustees */
} else completition = (uint8) (-result);
} else if (*p == 0x27) { /* Add Trustees to DIR ?? */
struct INPUT {
uint8 header[7]; /* Requestheader */
uint8 filler; /* 0x0 */
uint8 datalen; /* 0x2 */
uint8 type; /* 0x27 */
uint8 div[3]; /* 0x0, dlen, typ */
uint8 dir_handle; /* Verzeichnis Handle */
uint8 trustee_id[4]; /* Trustee Object ID */
uint8 trustee_right_mask;
@ -511,39 +521,25 @@ static void handle_ncp_serv()
struct XDATA {
uint8 weisnicht[8]; /* ?????? */
} *xdata = (struct XDATA*) responsedata;
DPRINTF(("Get vol restriction vol=%d, id=0x%lx",
XDPRINTF((2,"Get vol restriction vol=%d, id=0x%lx",
(int)volnr, id));
memset(xdata, 0, sizeof(struct XDATA));
data_len=sizeof(struct XDATA);
} else if (*p == 0x2a){ /* Get Eff. Dir Rights ??*/
/* from Dir_handles + PATH */
} else if (*p == 0x2a){
/* Get Eff. Rights of DIR's and Files ??*/
struct XDATA {
uint8 eff_rights; /* Effektive Right to Dir */
uint8 unkwown_data; /* 0x1 */
} *xdata = (struct XDATA*) responsedata;
NW_DIR_INFO d;
int len=(int)*(p+2);
int searchsequence;
if (len)
searchsequence = nw_search((uint8*)&(d),
(int)*(p+1), /* dir_handle */
MAX_U16,
(int) 0x10, /* only dirs ?? */
p+3, /* path */
len); /* pathlen */
else {
searchsequence = nw_get_eff_dir_rights(
(int)*(p+1),
p+3,
len);
if (searchsequence > -1)
d.ext_attrib = searchsequence;
}
if (searchsequence > -1){
xdata->eff_rights = d.ext_attrib;
int result = nw_get_eff_dir_rights(
(int)*(p+1),
p+3,
(int)*(p+2), 1);
if (result > -1){
xdata->eff_rights = (uint8)result;
xdata->unkwown_data = 0x1;
data_len = sizeof(struct XDATA);
} else completition = (uint8) - searchsequence;
} else completition = (uint8) (-result);
} else if (*p == 0x2c){
/* Get Volume and Purge Information */
/* new Call since V3.11 */
@ -610,6 +606,8 @@ static void handle_ncp_serv()
} else completition = (uint8) -result;
} else if (*p == 0x2e){ /* RENAME DATEI */
completition = 0xfb; /* TODO: !!! */
} else if (*p == 0x2f){ /* ?????? */
completition = 0xfb; /* TODO: !!! */
} else completition = 0xfb; /* unkwown request */
}
break;
@ -619,15 +617,27 @@ static void handle_ncp_serv()
uint8 len = *(requestdata+1);
uint8 ufunc = *(requestdata+2);
switch (ufunc) {
case 0x14:
case 0x18: { /* ncpserv have change the structure */
struct INPUT {
uint8 header[7]; /* Requestheader */
uint8 div[3]; /* 0, len + ufunc */
uint8 align[2]; /* alignment ncpserv */
int gid; /* ncpserv */
int uid; /* ncpserv */
} *input = (struct INPUT *)ncprequest;
set_guid(input->gid, input->uid);
}
break;
case 0x0f: { /* Scan File Information */
struct INPUT {
uint8 header[7]; /* Requestheader */
uint8 div[3]; /* 0, len + ufunc */
uint8 sequence[2]; /* z.B. 0xff, 0xff */
uint8 dir_handle;
uint8 search_attrib; /* 0: NONE */
/* 02: HIDDEN */
/* 02: HIDDEN */
/* 04: SYSTEM */
/* 06: BOTH */
/* 0x10: DIR */
@ -636,7 +646,7 @@ static void handle_ncp_serv()
} *input = (struct INPUT *)ncprequest;
struct OUTPUT {
uint8 sequence[2]; /* next sequence */
uint8 sequence[2]; /* next sequence */
NW_FILE_INFO f;
uint8 owner_id[4];
uint8 archive_date[2];
@ -666,14 +676,15 @@ static void handle_ncp_serv()
}
break;
case 0x68: /* creat queue job and file old */
case 0x79: { /* creat queue job and file */
/* somme of this call is handled in ncpserv !! */
struct INPUT {
uint8 header[7]; /* Requestheader */
uint8 packetlen[2]; /* low high */
uint8 func; /* 0x79 */
uint8 queue_id[4]; /* Queue ID */
uint8 queue_job[280];
uint8 header[7]; /* Requestheader */
uint8 packetlen[2]; /* low high */
uint8 func; /* 0x79 or 0x68 */
uint8 queue_id[4]; /* Queue ID */
uint8 queue_job[280]; /* oldsize is 256 */
/* this is added by ncpserv */
uint8 dir_nam_len; /* len of dirname */
uint8 dir_name[1];
@ -682,21 +693,24 @@ static void handle_ncp_serv()
input->queue_id,
input->queue_job,
input->dir_name,
(int)input->dir_nam_len);
(int)input->dir_nam_len,
(ufunc == 0x68) );
if (!result) {
data_len = 78;
data_len = (ufunc == 0x68) ? 54 : 78;
memcpy(responsedata, input->queue_job, data_len);
} else completition= (uint8)-result;
}
break;
case 0x69: /* close file and start queue old ?? */
case 0x7f: { /* close file and start queue */
struct INPUT {
uint8 header[7]; /* Requestheader */
uint8 packetlen[2]; /* low high */
uint8 func; /* 0x7f */
uint8 func; /* 0x7f or 0x6f */
uint8 queue_id[4]; /* Queue ID */
uint8 job_id[4]; /* result from creat queue */
uint8 job_id[4]; /* result from creat queue */
/* if 0x69 then only 2 byte ! */
/* this is added by ncpserv */
uint8 prc_len; /* len of printcommand */
uint8 prc[1]; /* printcommand */
@ -710,13 +724,13 @@ static void handle_ncp_serv()
break;
case 0xf3: { /* Map Direktory Number TO PATH */
DPRINTF(("TODO: Map Direktory Number TO PATH\n"));
XDPRINTF((1,"TODO: Map Direktory Number TO PATH\n"));
completition = 0xff;
}
break;
case 0xf4: { /* Map PATH TO Dir Entry */
DPRINTF(("TODO: Map PATH TO Dir Entry\n"));
XDPRINTF((1,"TODO: Map PATH TO Dir Entry\n"));
completition = 0xff;
}
break;
@ -766,11 +780,11 @@ static void handle_ncp_serv()
}
break;
#if 0
case 0x22 : /* div TTS Calls */
break;
#endif
case 0x22 : { /* div TTS Calls */
int ufunc = (int) *requestdata;
if (!ufunc) completition=0; /* TTS not availible */
else completition=0xfb; /* request not known */
} break;
case 0x3e : { /* FILE SEARCH INIT */
/* returns dhandle for searchings */
@ -805,7 +819,7 @@ static void handle_ncp_serv()
uint8 ext_fhandle[2]; /* all zero */
} *input = (struct INPUT *)ncprequest;
uint32 fhandle = GET_BE32(input->fhandle);
DPRINTF(("TODO: COMMIT FILE:fhandle=%ld\n", fhandle));
XDPRINTF((1,"TODO: COMMIT FILE:fhandle=%ld\n", fhandle));
/* TODO */
;
} break;
@ -824,10 +838,11 @@ static void handle_ncp_serv()
6 Both,
* 0x10 Dir
*/
uint8 len; /* Weitere L„nge */
uint8 data[2]; /* Dateiname mit Wild */
} *input = (struct INPUT *) (ncprequest);
uint8 len; /* fnname len */
uint8 data[2]; /* fnname with wildcards */
} *input = (struct INPUT *) ncprequest;
int len=input->len ; /* FN Length */
struct OUTPUT {
uint8 searchsequence[2]; /* FRAGE Sequence */
uint8 dir_id[2]; /* Direktory ID */
@ -838,7 +853,8 @@ static void handle_ncp_serv()
} u;
} *xdata = (struct OUTPUT*)responsedata;
int searchsequence = nw_dir_search( (uint8*) &(xdata->u),
int searchsequence = nw_dir_search(
(uint8*) &(xdata->u),
(int) GET_BE16(input->dir_id),
(int) GET_BE16(input->searchsequence),
(int) input->search_attrib,
@ -1020,7 +1036,6 @@ static void handle_ncp_serv()
}
break;
case 0x48 : /* read file */
{
struct INPUT {
@ -1171,56 +1186,14 @@ static void handle_ncp_serv()
break;
#if 0
case 0x57 : /* some new calls */
{
uint8 ufunc = *(requestdata);
completition = 0xfb; /* erstmal */
if (ufunc == 0x02) { /* Initialize Search */
uint8 namespace=*(requestdata+1);
uint8 reserved=*(requestdata+2);
/* NW PATH STRUC */
} else if (ufunc == 0x07) { /* Modify File or Dir Info */
uint8 namespace=*(requestdata+1);
} else if (ufunc == 0x09) { /* Set short Dir Handle*/
uint8 namespace=*(requestdata+1);
uint8 datastream=*(requestdata+2);
uint8 desthandle=*(requestdata+3);
/* 1 Byte Reserved */
/* NWPATH STRUC */
} else if (ufunc == 0x15) { /* Get Path String from short dir neu*/
uint8 namespace=*(requestdata+1);
uint8 short_dir_handle=*(requestdata+2);
} else if (ufunc == 0x16) {
/* Generate Dir BASE and VolNumber */
uint8 namespace = *(requestdata+1);
uint8 *nwpathstruct = requestdata+4;
struct OUTPUT {
uint8 ns_dir_base[4]; /* BASEHANDLE */
uint8 dos_dir_base[4]; /* BASEHANDLE */
uint8 volume; /* Volumenumber*/
} *xdata= (struct OUTPUT*)responsedata;
int result = nw_generate_dir_path(nwpathstruct,
xdata->ns_dir_base, xdata->dos_dir_base);
if (result >-1) {
data_len = sizeof(struct OUTPUT);
xdata->volume = result;
completition=0;
} else completition = (uint8)(-result);
} else if (ufunc == 0x0c) { /* alloc short dir Handle */
uint8 namespace = *(requestdata+1);
int allocatemode = GET_BE16(requestdata+2);
/* NWPATH STRUC */
} else if (ufunc == 0x1a) { /* Get Huge NS Info neu*/
uint8 namespace=*(requestdata+1);
} else if (ufunc == 0x1c) { /* GetFullPathString neu*/
uint8 snamespace=*(requestdata+1);
uint8 dnamespace=*(requestdata+2);
} else if (ufunc == 0x1d) { /* GetEffDirRights neu*/
uint8 namespace=*(requestdata+1);
}
} break;
case 0x57 : /* some new namespace calls */
int result = handle_func_0x57(requestdata, responsedata);
if (result > -1) data_len = result;
else completition=(uint8)-result;
break;
#endif
#if 0
case 0x61 : { /* Negotiate Buffer Size, Packetsize new ??? */
/* same request as 0x21 */
@ -1238,45 +1211,65 @@ static void handle_ncp_serv()
printf("WRONG TYPE 0x%x IN NWCONN\n", ncp_type);
completition = 0xfb;
}
if (completition == 0xfb || (do_druck == 1)) { /* UNKWON FUNCTION od. TYPE */
if (nw_debug && (completition == 0xfb || (do_druck == 1))) { /* UNKWON FUNCTION od. TYPE */
int x_nw_debug = nw_debug;
if (!nw_debug || do_druck == 1) {
if (nw_debug == 1 || do_druck == 1) {
int j = requestlen;
nw_debug = 1;
DPRINTF(("NCP REQUEST: seq:%d, task:%d, reserved:0x%x, func:0x%x\n",
nw_debug = 2;
XDPRINTF((2,"NCP REQUEST: seq:%d, task:%d, reserved:0x%x, func:0x%x\n",
sequence, task, reserved, function));
if (j > 0){
uint8 *p=requestdata;
DPRINTF(("len %d, DATA:", j));
XDPRINTF((2,"len %d, DATA:", j));
while (j--) {
int c = *p++;
if (c > 32 && c < 127) DPRINTF((",\'%c\'", (char) c));
else DPRINTF((",0x%x", c));
if (c > 32 && c < 127) XDPRINTF((2,",\'%c\'", (char) c));
else XDPRINTF((2,",0x%x", c));
}
DPRINTF(("\n"));
XDPRINTF((2,"\n"));
}
}
if (completition == 0xfb)
DPRINTF(("UNKNOWN FUNCTION od. TYPE: 0x%x\n", function));
XDPRINTF((1,"UNKNOWN FUNCTION od. TYPE: 0x%x\n", function));
else if (data_len){
int j = data_len;
uint8 *p = responsedata;
DPRINTF(("RSPONSE: len %d, DATA:", data_len));
XDPRINTF((2,"RSPONSE: len %d, DATA:", data_len));
while (j--) {
int c = *p++;
if (c > 32 && c < 127) DPRINTF((",\'%c\'", (char) c));
else DPRINTF((",0x%x", c));
if (c > 32 && c < 127) XDPRINTF((2,",\'%c\'", (char) c));
else XDPRINTF((2,",0x%x", c));
}
DPRINTF(("\n"));
XDPRINTF((2,"\n"));
}
nw_debug = x_nw_debug;
}
ncp_response(sequence, completition, data_len);
if (nw_debug != 99 && nw_debug != -99) nw_debug = org_nw_debug;
else if (nw_debug == -99) nw_debug = 0;
}
extern int t_errno;
static void close_all(void)
{
nw_init_connect();
close(0);
if (ipx_fd > -1){
while (t_unbind(ipx_fd) < 0) {
if (t_errno != TOUTSTATE) break;
}
t_close(ipx_fd);
}
}
static void sig_quit(int rsig)
{
close_all();
exit(0);
}
static int fl_get_debug=0;
static void get_new_debug(void)
{
@ -1291,27 +1284,35 @@ static void sig_hup(int rsig)
signal(SIGHUP, sig_hup);
}
extern int t_errno;
static void set_sig(void)
{
signal(SIGTERM, sig_quit);
signal(SIGQUIT, sig_quit);
signal(SIGHUP, sig_hup);
signal(SIGINT, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
}
int main(int argc, char **argv)
{
int completition = 0;
if (argc != 8) {
printf("usage nwconn PID FROM_ADDR Connection UID GID Debug1 Debugipx\n");
if (argc != 4) {
fprintf(stderr, "usage nwconn PID FROM_ADDR Connection\n");
exit(1);
} else father_pid = atoi(*(argv+1));
setuid(0);
setgid(0);
init_tools(NWCONN);
DPRINTF(("FATHER PID=%d, ADDR=%s CON:%s\n", father_pid, *(argv+2), *(argv+3)));
adr_to_ipx_addr(&from_addr, *(argv+2));
adr_to_ipx_addr(&from_addr, *(argv+2));
default_gid = atoi(*(argv+4));
default_uid = atoi(*(argv+5));
nw_debug = atoi(*(argv+6));
ipxdebug = atoi(*(argv+7));
if (nw_init_connect()) exit(1);
#ifdef LINUX
set_emu_tli(ipxdebug);
set_emu_tli();
#endif
if (nw_init_connect()) exit(1);
last_sequence = -9999;
if (open_ipx_socket()) exit(1);
@ -1331,7 +1332,7 @@ int main(int argc, char **argv)
ncpresponse->reserved = (uint8) 0; /* allways 0 */
ncpresponse->connection = (uint8) atoi(*(argv+3));
signal(SIGHUP, sig_hup);
set_sig();
while (1) {
int data_len = read(0, readbuff, sizeof(readbuff));
@ -1352,19 +1353,11 @@ int main(int argc, char **argv)
requestlen = data_len - sizeof(NCPREQUEST);
handle_ncp_serv();
}
} else if (data_len < 0) {
if (fl_get_debug) get_new_debug();
else break;
}
}
close(0);
if (ipx_fd > -1){
while ((completition = t_unbind(ipx_fd)) < 0) {
if (t_errno != TOUTSTATE) break;
}
t_close(ipx_fd);
}
close_all();
return(0);
}

213
nwcrypt.c Normal file
View File

@ -0,0 +1,213 @@
/*$*********************************************************
$*
$* This code has been taken from DDJ 11/93, from an
$* article by Pawel Szczerbina.
$*
$* Password encryption routines follow.
$* Converted to C from Barry Nance's Pascal
$* prog published in the March -93 issue of Byte.
$*
$* Adapted to be useable for ncpfs by
$* Volker Lendecke <lendecke@namu01.gwdg.de> in
$* October 1995.
$*
$* Stolen to be useable for mars_nwe by
$* Martin Stover <mstover@freeway.de> in
$* Dezember 1995.
$**********************************************************/
/****************************************************************************
I read that Novell is not very open when it comes to technical details
of the Netware Core Protocol. This might be especially true for the
encryption stuff. I took the necessary code from Dr. Dobb's Journal
11/93, Undocumented Corner. I asked Jon Erickson <jon@ddj.com> about
the legal status of this piece of code:
---
Date: Thu, 12 Oct 1995 13:44:18 +0100
From: Volker Lendecke <lendecke>
To: jon@ddj.com
Subject: legal status of your source code?
Hello!
I hope that you're the right one to write to, you are the first on your WWW
server. If you are not, could you please forward this message to the right
person? Thanks.
I'm currently exploring the possibility to write a free (in the GNU GPL
sense) NCP filesystem, which would allow me to access a novell server
transparently. For that I would like to use the encryption functions you
published in DDJ 11/93, Undocumented Corner. I would make some cosmetic
changes, such as other indentations, minor code changes and so on. But I do
not know if that allows me to publish this code under GPL. One alternative
would be to publish a diff against your listing, but that would probably
contain much of your code as well, and it would be very inconvenient for
the average user.
I think that you have some kind of standard procedure for such a
case. Please tell me what I should do.
Many thanks in advance,
Volker
+=================================================================+
! Volker Lendecke Internet: lendecke@namu01.gwdg.de !
! D-37081 Goettingen, Germany !
+=================================================================+
--
I got the following answer:
---
From: Jon Erickson <jon@ddj.com>
X-Mailer: SCO System V Mail (version 3.2)
To: lendecke@namu01.gwdg.de
Subject: Re: legal status of your source code?
Date: Thu, 12 Oct 95 5:42:56 PDT
Volker,
Code from Dr. Dobb's Journal related articles is provided for
anyone to use. Clearly, the author of the article should be
given credit.
Jon Erickson
---
With this answer in mind, I took the code and made it a bit more
C-like. The original seemed to be translated by a mechanical pascal->c
translator. Jon's answer encouraged me to publish nwcrypt.c under the
GPL. If anybody who knows more about copyright and sees any problems
with this, please tell me.
****************************************************************************/
/******************* Data types ***************************/
typedef unsigned char buf32[32];
typedef unsigned char buf16[16];
typedef unsigned char buf8[8];
typedef unsigned char buf4[4];
typedef unsigned char u8;
static u8 encrypttable[256] =
{0x7,0x8,0x0,0x8,0x6,0x4,0xE,0x4,0x5,0xC,0x1,0x7,0xB,0xF,0xA,0x8,
0xF,0x8,0xC,0xC,0x9,0x4,0x1,0xE,0x4,0x6,0x2,0x4,0x0,0xA,0xB,0x9,
0x2,0xF,0xB,0x1,0xD,0x2,0x1,0x9,0x5,0xE,0x7,0x0,0x0,0x2,0x6,0x6,
0x0,0x7,0x3,0x8,0x2,0x9,0x3,0xF,0x7,0xF,0xC,0xF,0x6,0x4,0xA,0x0,
0x2,0x3,0xA,0xB,0xD,0x8,0x3,0xA,0x1,0x7,0xC,0xF,0x1,0x8,0x9,0xD,
0x9,0x1,0x9,0x4,0xE,0x4,0xC,0x5,0x5,0xC,0x8,0xB,0x2,0x3,0x9,0xE,
0x7,0x7,0x6,0x9,0xE,0xF,0xC,0x8,0xD,0x1,0xA,0x6,0xE,0xD,0x0,0x7,
0x7,0xA,0x0,0x1,0xF,0x5,0x4,0xB,0x7,0xB,0xE,0xC,0x9,0x5,0xD,0x1,
0xB,0xD,0x1,0x3,0x5,0xD,0xE,0x6,0x3,0x0,0xB,0xB,0xF,0x3,0x6,0x4,
0x9,0xD,0xA,0x3,0x1,0x4,0x9,0x4,0x8,0x3,0xB,0xE,0x5,0x0,0x5,0x2,
0xC,0xB,0xD,0x5,0xD,0x5,0xD,0x2,0xD,0x9,0xA,0xC,0xA,0x0,0xB,0x3,
0x5,0x3,0x6,0x9,0x5,0x1,0xE,0xE,0x0,0xE,0x8,0x2,0xD,0x2,0x2,0x0,
0x4,0xF,0x8,0x5,0x9,0x6,0x8,0x6,0xB,0xA,0xB,0xF,0x0,0x7,0x2,0x8,
0xC,0x7,0x3,0xA,0x1,0x4,0x2,0x5,0xF,0x7,0xA,0xC,0xE,0x5,0x9,0x3,
0xE,0x7,0x1,0x2,0xE,0x1,0xF,0x4,0xA,0x6,0xC,0x6,0xF,0x4,0x3,0x0,
0xC,0x0,0x3,0x6,0xF,0x8,0x7,0xB,0x2,0xD,0xC,0x6,0xA,0xA,0x8,0xD};
static buf32 encryptkeys =
{0x48,0x93,0x46,0x67,0x98,0x3D,0xE6,0x8D,
0xB7,0x10,0x7A,0x26,0x5A,0xB9,0xB1,0x35,
0x6B,0x0F,0xD5,0x70,0xAE,0xFB,0xAD,0x11,
0xF4,0x47,0xDC,0xA7,0xEC,0xCF,0x50,0xC0};
static void
shuffle1(buf32 temp, unsigned char *target)
{
short b4;
unsigned char b3;
int s, b2, i;
b4 = 0;
for (b2 = 0; b2 <= 1; ++b2)
{
for (s = 0; s <= 31; ++s)
{
b3 = (temp[s]+b4) ^ (temp[(s+b4)&31] - encryptkeys[s]);
b4 = b4 + b3;
temp[s] = b3;
}
}
for (i = 0; i <= 15; ++i) {
target[i] = encrypttable[temp[ 2*i ]]
| (encrypttable[temp[ 2*i + 1]] << 4);
}
}
void
shuffle(unsigned char *lon, const unsigned char *buf, int buflen,
unsigned char *target)
{
int b2, d, s;
buf32 temp;
while ( (buflen > 0)
&& (buf[buflen - 1] == 0)) {
buflen = buflen - 1;
}
for (s = 0; s < 32; s++) {
temp[s] = 0;
}
d = 0;
while (buflen >= 32)
{
for (s = 0; s <= 31; ++s)
{
temp[s] = temp[s] ^ buf[d];
d = d + 1;
}
buflen = buflen - 32;
}
b2 = d;
if (buflen > 0)
{
for (s = 0; s <= 31; ++s)
{
if (d + buflen == b2)
{
b2 = d;
temp[s] = temp[s] ^ encryptkeys[s];
} else {
temp[s] = temp[s] ^ buf[b2];
b2 = b2 + 1;
}
}
}
for (s = 0; s <= 31; ++s)
temp[s] = temp[s] ^ lon[s & 3];
shuffle1(temp,target);
}
void
nw_encrypt(unsigned char *fra,unsigned char *buf,unsigned char *til)
{
buf32 k;
int s;
shuffle(&(fra[0]), buf, 16, &(k[ 0]));
shuffle(&(fra[4]), buf, 16, &(k[16]));
for (s = 0; s <= 15; ++s)
k[s] = k[s] ^ k[31 - s];
for (s = 0; s <= 7; ++s)
til[s] = k[s] ^ k[15 - s];
}

338
nwdbm.c
View File

@ -1,4 +1,4 @@
/* nwdbm.c 22-Nov-95 data base for mars_nwe */
/* nwdbm.c 05-Dec-95 data base for mars_nwe */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
@ -29,6 +29,8 @@
# include </usr/ucbinclude/ndbm.h>
#endif
int tells_server_version=0;
static char *fnprop = "nwprop";
static char *fnval = "nwval";
static char *fnobj = "nwobj";
@ -87,7 +89,7 @@ static int name_match(uint8 *s, uint8 *p)
int find_obj_id(NETOBJ *o, uint32 last_obj_id)
{
int result = -0xfc; /* no Object */
DPRINTF(("findobj_id OBJ=%s, type=0x%x, lastid=0x%lx \n",
XDPRINTF((2, "findobj_id OBJ=%s, type=0x%x, lastid=0x%lx \n",
o->name, (int)o->type, last_obj_id));
if (!dbminit(fnobj)){
@ -107,7 +109,7 @@ int find_obj_id(NETOBJ *o, uint32 last_obj_id)
NETOBJ *obj = (NETOBJ*)data.dptr;
if ( ( ((int)obj->type == (int)o->type) || o->type == MAX_U16) &&
name_match(obj->name, o->name)) {
DPRINTF(("found OBJ=%s, id=0x%lx\n", obj->name, obj->id));
XDPRINTF((2, "found OBJ=%s, id=0x%lx\n", obj->name, obj->id));
result = 0;
memcpy((char *)o, (char*)obj, sizeof(NETOBJ));
} else {
@ -131,7 +133,7 @@ static int loc_delete_property(uint32 obj_id, uint8 *prop_name, uint8 prop_id)
int result = -0xfb; /* no property */
memset(xset, 0, sizeof(xset));
if (!prop_id) {
DPRINTF(("loc_delete_property obj_id=%d, prop=%s\n", obj_id, prop_name));
XDPRINTF((2, "loc_delete_property obj_id=%d, prop=%s\n", obj_id, prop_name));
if (!dbminit(fnprop)){
for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) {
NETPROP *p=(NETPROP*)key.dptr;
@ -139,7 +141,7 @@ static int loc_delete_property(uint32 obj_id, uint8 *prop_name, uint8 prop_id)
data = fetch(key);
p = (NETPROP*)data.dptr;
if (p != NULL && name_match(p->name, prop_name)){
DPRINTF(("found prop: %s, id=%d for deleting\n", p->name, (int)p->id));
XDPRINTF((2, "found prop: %s, id=%d for deleting\n", p->name, (int)p->id));
if ((int)(p->id) > result) result = (int)(p->id);
xset[p->id]++;
}
@ -148,7 +150,7 @@ static int loc_delete_property(uint32 obj_id, uint8 *prop_name, uint8 prop_id)
} else result = -0xff;
dbmclose();
} else {
DPRINTF(("loc_delete_property obj_id=%d, prop_id=%d\n", obj_id, (int)prop_id));
XDPRINTF((2, "loc_delete_property obj_id=%d, prop_id=%d\n", obj_id, (int)prop_id));
xset[prop_id]++;
result = prop_id;
}
@ -211,7 +213,7 @@ static int loc_delete_obj(uint32 objid)
int nw_delete_obj(NETOBJ *obj)
{
int result = find_obj_id(obj, 0);
DPRINTF(("nw_delete_obj obj_id=%d, obj_name=%s\n", obj->id, obj->name));
XDPRINTF((2, "nw_delete_obj obj_id=%d, obj_name=%s\n", obj->id, obj->name));
if (!result) result=loc_delete_obj(obj->id);
return(result);
}
@ -228,7 +230,7 @@ int nw_rename_obj(NETOBJ *o, uint8 *newname)
data = fetch(key);
if (data.dptr != NULL){
NETOBJ *obj=(NETOBJ*)data.dptr;
DPRINTF(("rename_obj:got OBJ name=%s, id = 0x%x,\n", obj->name, (int)obj->id));
XDPRINTF((2, "rename_obj:got OBJ name=%s, id = 0x%x,\n", obj->name, (int)obj->id));
strncpy(obj->name, newname, 48);
if (!store(key, data)) result=0;
}
@ -250,7 +252,7 @@ int nw_change_obj_security(NETOBJ *o, int newsecurity)
data = fetch(key);
if (data.dptr != NULL){
NETOBJ *obj=(NETOBJ*)data.dptr;
DPRINTF(("change_obj_security:got OBJ name=%s, id = 0x%x,\n", obj->name, (int)obj->id));
XDPRINTF((2, "change_obj_security:got OBJ name=%s, id = 0x%x,\n", obj->name, (int)obj->id));
obj->security = (uint8) newsecurity;
if (!store(key, data)) result=0;
}
@ -263,14 +265,14 @@ int nw_change_obj_security(NETOBJ *o, int newsecurity)
int nw_get_obj(NETOBJ *o)
{
int result = -0xfc; /* no Object */
DPRINTF(("nw_get_obj von OBJ id = 0x%x,\n", (int)o->id));
XDPRINTF((2, "nw_get_obj von OBJ id = 0x%x,\n", (int)o->id));
if (!dbminit(fnobj)){
key.dsize = NETOBJ_KEY_SIZE;
key.dptr = (char*)o;
data = fetch(key);
if (data.dptr != NULL){
NETOBJ *obj=(NETOBJ*)data.dptr;
DPRINTF(("got OBJ name=%s, id = 0x%x,\n", obj->name, (int)obj->id));
XDPRINTF((2, "got OBJ name=%s, id = 0x%x,\n", obj->name, (int)obj->id));
memcpy(o, data.dptr, sizeof(NETOBJ));
result = 0;
}
@ -282,7 +284,7 @@ int nw_get_obj(NETOBJ *o)
static int find_prop_id(NETPROP *p, uint32 obj_id, int last_prop_id)
{
int result = -0xfb; /* no Property */
DPRINTF(("find Prop id von name=0x%x:%s, lastid=%d\n",
XDPRINTF((2, "find Prop id von name=0x%x:%s, lastid=%d\n",
obj_id, p->name, last_prop_id));
if (!dbminit(fnprop)){
int flag = (last_prop_id) ? 0 : 1;
@ -294,7 +296,7 @@ static int find_prop_id(NETPROP *p, uint32 obj_id, int last_prop_id)
data = fetch(key);
prop = (NETPROP*)data.dptr;
if (data.dptr != NULL && name_match(prop->name, p->name) ) {
DPRINTF(("found PROP %s, id=0x%x\n", prop->name, (int) prop->id));
XDPRINTF((2, "found PROP %s, id=0x%x\n", prop->name, (int) prop->id));
result = 0;
memcpy(p, prop, sizeof(NETPROP));
break;
@ -314,7 +316,7 @@ static int find_prop_id(NETPROP *p, uint32 obj_id, int last_prop_id)
static int loc_change_prop_security(NETPROP *p, uint32 obj_id)
{
int result = -0xfb; /* no Property */
DPRINTF(("loc_change_prop_security Prop id von name=0x%x:%s\n", obj_id, p->name));
XDPRINTF((2, "loc_change_prop_security Prop id von name=0x%x:%s\n", obj_id, p->name));
if (!dbminit(fnprop)){
for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) {
NETPROP *prop=(NETPROP*)key.dptr;
@ -323,7 +325,7 @@ static int loc_change_prop_security(NETPROP *p, uint32 obj_id)
prop = (NETPROP*)data.dptr;
if (data.dptr != NULL && name_match(prop->name, p->name) ) {
uint8 security = p->security;
DPRINTF(("found PROP %s, id=0x%x\n", prop->name, (int) prop->id));
XDPRINTF((2, "found PROP %s, id=0x%x\n", prop->name, (int) prop->id));
result = 0;
memcpy(p, prop, sizeof(NETPROP));
p->security = security;
@ -357,7 +359,7 @@ static int loc_get_prop_val(uint32 obj_id, int prop_id, int segment,
if (data.dptr != NULL){
NETVAL *v = (NETVAL*)data.dptr;
if (NULL != property_value) memcpy(property_value, v->value, 128);
DPRINTF(("found VAL 0x%x, %d, %d\n", obj_id, prop_id, segment));
XDPRINTF((2, "found VAL 0x%x, %d, %d\n", obj_id, prop_id, segment));
result = 0;
val.segment++;
data = fetch(key);
@ -385,7 +387,7 @@ int prop_find_member(uint32 obj_id, int prop_id, uint32 member_id)
NETVAL *v = (NETVAL*)data.dptr;
uint8 *p=v->value;
int k=0;
DPRINTF(("found VAL 0x%x, %d\n", obj_id, prop_id));
XDPRINTF((2, "found VAL 0x%x, %d\n", obj_id, prop_id));
while (k++ < 32){
uint32 id = GET_BE32(p);
if (id == member_id) {
@ -522,7 +524,7 @@ int nw_get_prop_val_by_obj_id(uint32 obj_id,
NETPROP prop;
int result=-0xff;
strmaxcpy((char*)prop.name, (char*)prop_name, prop_namlen);
DPRINTF(("nw_get_prop_val_by_obj_id,id=0x%x, prop=%s, segment=%d\n",
XDPRINTF((2, "nw_get_prop_val_by_obj_id,id=0x%x, prop=%s, segment=%d\n",
obj_id, prop.name, segment_nr));
if ((result=find_first_prop_id(&prop, obj_id))==0){
@ -566,7 +568,7 @@ int nw_delete_property(int object_type,
int result=-0xff;
strmaxcpy((char*)obj.name, (char*)object_name, object_namlen);
strmaxcpy((char*)prop_name_x, (char*)prop_name, prop_namlen);
DPRINTF(("nw_delete_property obj=%s, prop=%s, type=0x%x\n",
XDPRINTF((2, "nw_delete_property obj=%s, prop=%s, type=0x%x\n",
obj.name, prop_name_x, object_type));
obj.type = (uint16) object_type;
if ((result = find_obj_id(&obj, 0)) == 0){
@ -588,7 +590,7 @@ int nw_is_obj_in_set(int object_type,
strmaxcpy((char*)obj.name, (char*)object_name, object_namlen);
strmaxcpy((char*)mobj.name, (char*)member_name, member_namlen);
strmaxcpy((char*)prop.name, (char*)prop_name, prop_namlen);
DPRINTF(("nw_is_obj_in_set obj=%s,0x%x, member=%s,0x%x, prop=%s\n",
XDPRINTF((2, "nw_is_obj_in_set obj=%s,0x%x, member=%s,0x%x, prop=%s\n",
obj.name, object_type, mobj.name, member_type, prop.name));
obj.type = (uint16) object_type;
mobj.type = (uint16) member_type;
@ -615,7 +617,7 @@ int nw_add_obj_to_set(int object_type,
strmaxcpy((char*)obj.name, (char*)object_name, object_namlen);
strmaxcpy((char*)mobj.name, (char*)member_name, member_namlen);
strmaxcpy((char*)prop.name, (char*)prop_name, prop_namlen);
DPRINTF(("nw_add_obj_to_set obj=%s,0x%x, member=%s,0x%x, prop=%s\n",
XDPRINTF((2, "nw_add_obj_to_set obj=%s,0x%x, member=%s,0x%x, prop=%s\n",
obj.name, object_type, mobj.name, member_type, prop.name));
obj.type = (uint16) object_type;
mobj.type = (uint16) member_type;
@ -642,7 +644,7 @@ int nw_delete_obj_from_set(int object_type,
strmaxcpy((char*)obj.name, (char*)object_name, object_namlen);
strmaxcpy((char*)mobj.name, (char*)member_name, member_namlen);
strmaxcpy((char*)prop.name, (char*)prop_name, prop_namlen);
DPRINTF(("nw_delete_obj_from_set obj=%s,0x%x, member=%s,0x%x, prop=%s\n",
XDPRINTF((2, "nw_delete_obj_from_set obj=%s,0x%x, member=%s,0x%x, prop=%s\n",
obj.name, object_type, mobj.name, member_type, prop.name));
obj.type = (uint16) object_type;
mobj.type = (uint16) member_type;
@ -668,7 +670,7 @@ int nw_write_prop_value(int object_type,
int result=-0xff;
strmaxcpy((char*)obj.name, (char*)object_name, object_namlen);
strmaxcpy((char*)prop.name, (char*)prop_name, prop_namlen);
DPRINTF(("nw_write_prop_value obj=%s, prop=%s, type=0x%x, segment=%d\n",
XDPRINTF((2, "nw_write_prop_value obj=%s, prop=%s, type=0x%x, segment=%d\n",
obj.name, prop.name, object_type, segment_nr));
obj.type = (uint16) object_type;
@ -694,7 +696,7 @@ int nw_change_prop_security(int object_type,
strmaxcpy((char*)obj.name, (char*)object_name, object_namlen);
strmaxcpy((char*)prop.name, (char*)prop_name, prop_namlen);
prop.security = (uint8)prop_security;
DPRINTF(("nw_change_prop_security obj=%s,0x%x, prop=%s\n",
XDPRINTF((2, "nw_change_prop_security obj=%s,0x%x, prop=%s\n",
obj.name, object_type, prop.name));
obj.type = (uint16) object_type;
if ((result = find_obj_id(&obj, 0)) == 0){
@ -715,7 +717,7 @@ int nw_scan_property(NETPROP *prop,
int result;
strmaxcpy((char*)obj.name, (char*)object_name, object_namlen);
strmaxcpy((char*)prop->name, (char*)prop_name, prop_namlen);
DPRINTF(("nw_scan_property obj=%s, prop=%s, type=0x%x, last_scan=0x%lx\n",
XDPRINTF((2, "nw_scan_property obj=%s, prop=%s, type=0x%x, last_scan=0x%lx\n",
obj.name, prop->name, object_type, *last_scan));
obj.type = (uint16) object_type;
@ -742,9 +744,9 @@ int nw_get_prop_val_str(uint32 q_id, char *propname, uint8 *buff)
buff, &more_segments, &property_flags);
if (result > -1) {
result=strlen(buff);
DPRINTF(("nw_get_prop_val_str:%s len=%d, name=`%s`\n", propname, result, buff));
XDPRINTF((2, "nw_get_prop_val_str:%s strlen=%d\n", propname, result));
} else
DPRINTF(("nw_get_prop_val_str:%s, result=0x%x\n", propname, result));
XDPRINTF((2, "nw_get_prop_val_str:%s, result=0x%x\n", propname, result));
return(result);
}
@ -757,7 +759,7 @@ int nw_create_obj(NETOBJ *obj, uint32 wanted_id)
*/
{
int result = 0; /* OK */
DPRINTF(("creat OBJ=%s,type=0x%x\n", obj->name, (int)obj->type));
XDPRINTF((2, "creat OBJ=%s,type=0x%x\n", obj->name, (int)obj->type));
if (!dbminit(fnobj)){
for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) {
data = fetch(key);
@ -771,7 +773,8 @@ int nw_create_obj(NETOBJ *obj, uint32 wanted_id)
}
}
if (!result){
obj->id = (wanted_id) ? wanted_id -1 : 0;
obj->id = (wanted_id) ? wanted_id -1 : (obj->type << 16) + 1;
/* 1 is reserved for supervisor !!!! */
key.dsize = NETOBJ_KEY_SIZE;
key.dptr = (char*)obj;
while(1) {
@ -854,7 +857,7 @@ int nw_create_prop(int object_type,
int result=-0xff;
strmaxcpy((char*)obj.name, (char*)object_name, object_namlen);
strmaxcpy((char*)prop.name, (char*)prop_name, prop_namlen);
DPRINTF(("nw_create_prop obj=%s, prop=%s, type=0x%x\n",
XDPRINTF((2, "nw_create_prop obj=%s, prop=%s, type=0x%x\n",
obj.name, prop.name, object_type));
obj.type = (uint16) object_type;
if ((result = find_obj_id(&obj, 0)) == 0){
@ -898,6 +901,114 @@ uint32 nw_new_create_prop(uint32 wanted_id,
return(obj.id);
}
struct passwd *nw_getpwnam(uint32 obj_id)
{
static struct passwd pwstat;
char buff[200];
if (nw_get_prop_val_str(obj_id, "UNIX_USER", buff) > 0){
struct passwd *pw = getpwnam(buff);
if (NULL != pw) {
memcpy(&pwstat, pw, sizeof(struct passwd));
XDPRINTF((2, "FOUND obj_id=0x%x, pwnam=%s, gid=%d, uid=%d\n",
obj_id, buff, pw->pw_gid, pw->pw_uid));
endpwent ();
return(&pwstat);
}
endpwent ();
}
XDPRINTF((2, "NOT FOUND PWNAM of obj_id=0x%x\n", obj_id));
return(NULL);
}
int get_guid(int *gid, int *uid, uint32 obj_id)
/* searched for gid und uid of actual obj */
{
struct passwd *pw = nw_getpwnam(obj_id);
if (NULL != pw) {
*gid = pw->pw_gid;
*uid = pw->pw_uid;
return(0);
} else {
*gid = -1;
*uid = -1;
return(-0xff);
}
}
int nw_test_passwd(uint32 obj_id, uint8 *vgl_key, uint8 *akt_key)
/* returns 0, if password ok and -0xff if not ok */
{
char buf[200];
if (nw_get_prop_val_str(obj_id, "PASSWORD", buf) > 0) {
uint8 keybuff[8];
memcpy(keybuff, vgl_key, sizeof(keybuff));
nw_encrypt(keybuff, buf, keybuff);
return (memcmp(akt_key, keybuff, sizeof(keybuff)) ? -0xff : 0);
} else return(0); /* no password */
}
int nw_set_enpasswd(uint32 obj_id, uint8 *passwd)
{
nw_new_create_prop(obj_id, NULL, 0, 0, 0,
"PASSWORD", P_FL_STAT|P_FL_ITEM, 0x44,
passwd, 16);
return(0);
}
int nw_set_passwd(uint32 obj_id, char *password)
{
uint8 passwd[200];
uint8 s_uid[4];
U32_TO_BE32(obj_id, s_uid);
shuffle(s_uid, password, strlen(password), passwd);
#if 0
XDPRINTF((2, "password %s->0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n",
password,
(int)passwd[0],
(int)passwd[1],
(int)passwd[2],
(int)passwd[3],
(int)passwd[4],
(int)passwd[5],
(int)passwd[6],
(int)passwd[7],
(int)passwd[8],
(int)passwd[9],
(int)passwd[10],
(int)passwd[11],
(int)passwd[12],
(int)passwd[13],
(int)passwd[14],
(int)passwd[15]));
#endif
return(nw_set_enpasswd(obj_id, passwd));
}
int prop_add_new_member(uint32 obj_id, int prop_id, uint32 member_id)
/* addiert member to set, if member not in set */
{
int result = prop_find_member(obj_id, prop_id, member_id);
if (-0xea == result)
return(prop_add_member(obj_id, prop_id, member_id));
else if (!result) result = -0xee; /* already exist */
return(result);
}
int nw_new_add_prop_member(uint32 obj_id, char *propname, uint32 member_id)
/* addiert member to set, if member not in set */
{
NETPROP prop;
int result;
strmaxcpy(prop.name, propname, sizeof(prop.name));
result = find_prop_id(&prop, obj_id, 0);
if (!result) {
if (-0xea == (result=prop_find_member(obj_id, prop.id, member_id)))
return(prop_add_member(obj_id, prop.id, member_id));
else if (!result) result = -0xee; /* already exist */
}
return(result);
}
static void create_nw_db(char *fn, int allways)
{
char fname[200];
@ -920,7 +1031,7 @@ static void add_pr_queue(uint32 q_id,
uint32 su_id, uint32 ge_id)
{
uint8 buff[12];
DPRINTF(("ADD Q=%s, V=%s, C=%s\n", q_name, q_directory, q_command));
XDPRINTF((2, "ADD Q=%s, V=%s, C=%s\n", q_name, q_directory, q_command));
U32_TO_BE32(su_id, buff);
q_id =
nw_new_create_prop(q_id, q_name, 0x3, O_FL_DYNA, 0x31,
@ -950,114 +1061,57 @@ static void add_pr_queue(uint32 q_id,
}
static void nw_fill_standard(char *servername, ipxAddr_t *adr)
static uint32 add_user(uint32 u_id, uint32 g_id,
char *name, char *unname, char *password)
{
uint8 buff[4];
U32_TO_BE32(g_id, buff);
u_id = /* Typ Flags Security */
nw_new_create_prop(u_id, name, 0x1 , 0x0, 0x33,
"GROUPS_I'M_IN", P_FL_SET, 0x31,
(char*)buff, 4);
nw_new_create_prop(u_id, NULL, 0 , 0 , 0 ,
"SECURITY_EQUALS", P_FL_SET, 0x32,
(char*)buff, 4);
nw_new_add_prop_member(g_id, "GROUP_MEMBERS", u_id);
if (unname && *unname)
nw_new_create_prop(u_id, NULL, 0 , 0 , 0 ,
"UNIX_USER", P_FL_ITEM, 0x33,
(char*)unname, strlen(unname));
if (password && *password) nw_set_passwd(u_id, password);
}
void nw_fill_standard(char *servername, ipxAddr_t *adr)
/* fills the Standardproperties */
{
char serverna[50];
char serverna[50];
uint8 buff[12];
uint32 su_id = 0x00000001;
uint32 su_id = 0x00000001;
uint32 ge_id = 0x01000001;
uint32 guest_id = 0x02000001;
uint32 serv_id = 0x03000001;
uint32 nbo_id = 0x0B000001;
uint32 ngr_id = 0x0C000001;
uint32 ps1_id = 0x0D000001;
uint32 q1_id = 0x0E000001;
struct {
uint8 account_exp_date[3];
uint8 account_disable_flag;
uint8 password_exp_date[3];
uint8 grace_logins_remain;
uint8 password_exp_internal[2];
uint8 grace_login_reset;
uint8 minimum_password;
uint8 max_connections[2];
uint8 login_time_map[42];
uint8 last_log_time[6];
uint8 restriction_flags;
uint8 reserved;
uint8 max_disk_usage[4];
uint8 bad_logins[2];
uint8 next_reset_time[4];
uint8 bad_logins_address[12];
} login_control;
U32_TO_BE32(ge_id, buff);
su_id = /* Typ Flags Security */
nw_new_create_prop(su_id, "SUPERVISOR", 0x1 , 0x0, 0x33,
"GROUPS_I'M_IN", P_FL_SET, 0x31,
(char*)buff, 4);
nw_new_create_prop(su_id, NULL, 0x1, 0, 0,
"IDENTIFICATION", P_FL_ITEM, 0x31,
"SUPERVISOR LONG", 15);
nw_new_create_prop(su_id, NULL , 0 , 0 , 0 ,
"SECURITY_EQUALS", P_FL_SET, 0x32,
(char*)buff, 4);
memset(&login_control, 0, sizeof(login_control));
login_control.grace_logins_remain = 0xff;
login_control.grace_login_reset = 0xff;
memset(login_control.login_time_map, 0xff,
sizeof(login_control.login_time_map));
login_control.max_disk_usage[0] = 0x7f;
login_control.max_disk_usage[1] = 0xff;
login_control.max_disk_usage[2] = 0xff;
login_control.max_disk_usage[3] = 0xff;
nw_new_create_prop(su_id, NULL , 0 , 0 , 0 ,
"LOGIN_CONTROL", P_FL_ITEM, 0x32,
NULL, 0);
#if 0
(char*)&login_control, sizeof(login_control));
#endif
#if 0
nw_new_create_prop(su_id, NULL , 0 , 0 , 0 ,
"USER_DEFAULTS", P_FL_ITEM, 0x31,
((char*)(&login_control))+4,
sizeof(login_control) -4);
#endif
U32_TO_BE32(ge_id, buff);
guest_id =
nw_new_create_prop(guest_id, "GUEST", 0x1, 0x0, 0x31,
"GROUPS_I'M_IN", P_FL_SET, 0x31,
(char*)buff, 4);
nw_new_create_prop(guest_id, NULL , 0, 0, 0,
"SECURITY_EQUALS", P_FL_SET, 0x32,
(char*)buff, 4);
nbo_id =
nw_new_create_prop(nbo_id, "NOBODY", 0x1, 0x0, 0x31,
"GROUPS_I'M_IN", P_FL_SET, 0x31,
(char*)buff, 4);
nw_new_create_prop(nbo_id, NULL , 0, 0, 0,
"SECURITY_EQUALS", P_FL_SET, 0x32,
(char*)buff, 4);
U32_TO_BE32(su_id, buff);
U32_TO_BE32(guest_id, buff+4);
U32_TO_BE32(nbo_id, buff+8);
FILE *f = open_nw_ini();
ge_id =
nw_new_create_prop(ge_id, "EVERYONE", 0x2, 0x0, 0x31,
"GROUP_MEMBERS", P_FL_SET, 0x31,
(char*)buff, 12);
ngr_id =
nw_new_create_prop(ngr_id, "NOGROUP", 0x2, 0x0, 0x31,
"GROUP_MEMBERS", P_FL_SET, 0x31,
NULL, 0);
{
FILE *f=open_nw_ini();
if (f){
char buff[500];
int what;
while (0 != (what =get_ini_entry(f, 21, (char*)buff, sizeof(buff)))) {
"GROUP_MEMBERS", P_FL_SET, 0x31,
NULL, 0);
if (f){
char buff[500];
int what;
while (0 != (what =get_ini_entry(f, 0, (char*)buff, sizeof(buff)))) {
if (6 == what) { /* Server Version */
tells_server_version = atoi(buff);
} else if (21 == what) { /* QUEUES */
char name[100];
char directory[200];
char command[200];
@ -1091,15 +1145,29 @@ static void nw_fill_standard(char *servername, ipxAddr_t *adr)
add_pr_queue(q1_id, name, directory, command, su_id, ge_id);
q1_id++;
}
} /* while */
fclose(f);
}
} else if (12 == what || 13 == what) { /* SUPERVISOR, OTHERS */
char nname[100];
char uname[100];
char password[100];
int anz=sscanf((char*)buff, "%s %s %s", nname, uname, password);
if (anz > 1) {
upstr(nname);
if (anz > 2) upstr(password);
else password[0] = '\0';
add_user((12 == what) ? su_id : 0L, ge_id, nname,
uname, password);
}
}
} /* while */
fclose(f);
}
if (servername && adr) {
strmaxcpy(serverna, servername, 48);
upstr(serverna);
nw_new_create_prop(serv_id, serverna, 0x4, O_FL_DYNA, 0x40,
"NET_ADDRESS", P_FL_ITEM | P_FL_DYNA, 0x40,
(char*)adr, sizeof(ipxAddr_t));
}
strmaxcpy(serverna, servername, 48);
upstr(serverna);
nw_new_create_prop(serv_id, serverna, 0x4, O_FL_DYNA, 0x40,
"NET_ADDRESS", P_FL_ITEM | P_FL_DYNA, 0x40,
(char*)adr, sizeof(ipxAddr_t));
}
void nw_init_dbm(char *servername, ipxAddr_t *adr)

View File

@ -58,6 +58,8 @@ typedef struct {
#define P_FL_ITEM 0x0
#define P_FL_SET 0x2
extern int tells_server_version;
extern int nw_get_prop(int object_type,
uint8 *object_name, int object_namlen,
int segment_nr,
@ -166,5 +168,6 @@ extern uint32 nw_new_create_prop(uint32 wanted_id,
char *propname, int propflags, int propsecurity,
char *value, int valuesize);
extern void nw_fill_standard(char *servername, ipxAddr_t *adr);
extern void nw_init_dbm(char *servername, ipxAddr_t *adr);

335
nwroute.c Normal file
View File

@ -0,0 +1,335 @@
/* nwroute.c 20-Dec-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 "nwserv.h"
#define MAX_NW_ROUTES 50 /* max. 1 complete RIP packet should be enough */
typedef struct {
uint32 net; /* destnet */
uint16 hops; /* hops to net */
uint16 ticks; /* ticks to net, ether 1/hop, isdn 7/hop */
uint32 rnet; /* net of forw. router */
uint8 rnode[IPX_NODE_SIZE]; /* node of forw. router */
} NW_ROUTES;
static int anz_routes=0;
static NW_ROUTES *nw_routes[MAX_NW_ROUTES];
static void insert_delete_net(uint32 destnet,
uint32 rnet, /* routernet */
uint8 *rnode, /* routernode */
uint16 hops,
uint16 ticks,
int do_delete) /* delete == 1 */
{
int k=-1;
int freeslot=-1;
NW_ROUTES *nr=NULL;
XDPRINTF((3,"%s net:0x%X, over 0x%X, 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
(do_delete) ? "DEL" : "INS", destnet, rnet,
(int)rnode[0], (int)rnode[1], (int)rnode[2],
(int)rnode[3], (int)rnode[4], (int)rnode[5]));
if (!destnet || destnet == internal_net) return;
while (++k < anz_net_devices) {
NW_NET_DEVICE *nd=net_devices[k];
if (nd->net == destnet && (do_delete || (nd->ticks <= ticks))) return;
}
k=-1;
while (++k < anz_routes && nw_routes[k]->net != destnet) {
XDPRINTF((3,"NET 0x%X is routed\n", nw_routes[k]->net));
if (freeslot < 0 && !nw_routes[k]->net) freeslot=k;
}
if (k == anz_routes) { /* no route slot found */
if (do_delete) return; /* nothing to delete */
if (freeslot < 0) {
if (anz_routes == MAX_NW_ROUTES) return;
nw_routes[k] = (NW_ROUTES*)xmalloc(sizeof(NW_ROUTES));
anz_routes++;
} else k=freeslot;
nr=nw_routes[k];
memset(nr, 0, sizeof(NW_ROUTES));
nr->net = destnet;
nr->ticks = 0xffff;
nr->hops = 0xffff;
} else if (do_delete) {
nr=nw_routes[k];
if (nr->rnet == rnet &&
IPXCMPNODE(nr->rnode, rnode) ) {
/* only delete the routes, which we have inserted */
XDPRINTF((2,"ROUTE DEL NET=0x%X over Router NET 0x%X\n",
nr->net, rnet));
ipx_route_del(nr->net);
nr->net = 0L;
} else {
XDPRINTF((3,"ROUTE NOT deleted NET=0x%X, RNET=0X%X\n",
nr->net, rnet));
}
return;
} else nr=nw_routes[k];
if (ticks <= nr->ticks) {
if (ticks > nr->ticks) return;
if (ticks == nr->ticks && hops > nr->hops) return;
nr->hops = hops;
nr->ticks = ticks;
nr->rnet = rnet;
memcpy(nr->rnode, rnode, IPX_NODE_SIZE);
XDPRINTF((2,"ADD ROUTE NET=0x%X, over 0x%X, 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
nr->net, nr->rnet,
(int)nr->rnode[0], (int)nr->rnode[1], (int)nr->rnode[2],
(int)nr->rnode[3], (int)nr->rnode[4], (int)nr->rnode[5]));
ipx_route_add(nr->net, nr->rnet, nr->rnode);
}
}
static uint32 rnet=0L;
static int rentries=0;
static int rmode; /* 0=normal, 1=shutdown, 10=request */
static uint8 rip_buff[402]; /* operation + max. 50 RIPS */
static void init_rip_buff(uint32 net, int mode)
{
rnet=net;
rentries=0;
rmode=mode;
U16_TO_BE16((mode > 9) ? 1 : 2, rip_buff); /* rip request or response */
}
static void ins_rip_buff(uint32 net, uint16 hops, uint16 ticks)
{
if ( net && rentries < 50 &&
(net != rnet || (!rentries && net == internal_net))) {
uint8 *p=rip_buff+2+(rentries*8);
U32_TO_BE32(net, p);
U16_TO_BE16(hops, p+4);
U16_TO_BE16(ticks, p+6);
rentries++;
}
}
static void build_rip_buff(uint32 destnet)
{
int is_wild = (destnet==MAX_U32);
int is_response = (rmode < 10);
int k;
if (!destnet) return;
if (is_wild) rentries=0;
if (is_response) {
if (is_wild || internal_net == destnet) {
ins_rip_buff(internal_net, (rmode==1) ? 16 : 1,
(rnet==internal_net) ? 1 : 2);
}
k=-1;
while (++k < anz_net_devices) {
NW_NET_DEVICE *nd=net_devices[k];
if (is_wild || nd->net == destnet)
ins_rip_buff(nd->net, (rmode==1) ? 16 : 1, nd->ticks+1);
}
}
k=-1;
while (++k < anz_routes) {
NW_ROUTES *nr=nw_routes[k];
if ((is_wild || nr->net == destnet) && rmode==1 || nr->hops < 2)
ins_rip_buff(nr->net, (rmode==1) ? 16 : nr->hops, nr->ticks);
}
}
static void send_rip_buff(ipxAddr_t *from_addr)
{
if (rentries > 0) {
int datasize=(rentries*8)+2;
ipxAddr_t to_addr;
if (from_addr) memcpy(&to_addr, from_addr, sizeof(ipxAddr_t));
else {
memset(&to_addr, 0, sizeof(ipxAddr_t));
U32_TO_BE32(rnet, to_addr.net);
memset(to_addr.node, 0xFF, IPX_NODE_SIZE);
U16_TO_BE16(SOCK_RIP, to_addr.sock);
}
if (nw_debug) {
uint8 *p = rip_buff;
int operation = GET_BE16(p);
XDPRINTF((2,"Send Rip %s entries=%d\n",
(operation==1) ? "Request" : "Response", rentries));
p+=2;
while (rentries--) {
uint32 net = GET_BE32(p);
uint16 hops = GET_BE16(p+4);
uint16 ticks = GET_BE16(p+6);
XDPRINTF((2,"hops=%3d, ticks %3d, network:%02x.%02x.%02x.%02x\n",
(int)hops, (int)ticks, (int)*(p), (int)*(p+1), (int)*(p+2), (int)*(p+3)));
p+=8;
}
}
send_ipx_data(sockfd[RIP_SLOT], 1,
datasize,
(char *)rip_buff,
&to_addr, "SEND RIP");
rentries=0;
}
}
void send_rip_broadcast(int mode)
/* mode=0, standard broadcast */
/* mode=1, first trie */
/* mode=2, shutdown */
{
int k=-1;
while (++k < anz_net_devices) {
NW_NET_DEVICE *nd=net_devices[k];
if (nd->ticks < 7) { /* isdn devices should not get RIP broadcasts everytime */
init_rip_buff(nd->net, (mode == 2) ? 1 : 0);
build_rip_buff(MAX_U32);
send_rip_buff(NULL);
}
}
}
void rip_for_net(uint32 net)
{
int k=-1;
while (++k < anz_net_devices) {
NW_NET_DEVICE *nd=net_devices[k];
if (nd->ticks < 7) { /* isdn devices should not get RIP broadcasts everytime */
init_rip_buff(nd->net, 10);
ins_rip_buff(net, MAX_U16, MAX_U16);
send_rip_buff(NULL);
}
}
}
void handle_rip(int fd, int ipx_pack_typ,
int data_len, IPX_DATA *ipxdata,
ipxAddr_t *from_addr)
{
int operation = GET_BE16(ipxdata->rip.operation);
int entries = (data_len-2) / 8;
uint8 *p = ((uint8*)ipxdata)+2;
int is_response = operation==2;
XDPRINTF((2,"Got Rip %s entries=%d from: %s\n",
(!is_response) ? "Request" : "Response", entries,
visable_ipx_adr(from_addr)));
if (!is_response) {
if (operation != 1) {
XDPRINTF((1,"UNKNOWN RIP operation %d\n", operation));
return;
}
init_rip_buff(GET_BE32(from_addr->net), 0);
}
while (entries--) {
uint32 net = GET_BE32(p);
uint16 hops = GET_BE16(p+4);
uint16 ticks = GET_BE16(p+6);
XDPRINTF((2,"hops=%3d, ticks %3d, network:%02x.%02x.%02x.%02x\n",
(int)hops, (int)ticks, (int)*(p), (int)*(p+1), (int)*(p+2), (int)*(p+3)));
if (is_response) {
insert_delete_net(net, GET_BE32(from_addr->net),
from_addr->node, hops+1, ticks+1, (hops > 15) ? 1 : 0);
} else { /* rip request */
build_rip_buff(net);
if (net == MAX_U32) break;
}
p+=8;
}
if (!is_response) /* rip request */
send_rip_buff(from_addr);
}
/* <========================= SAP ============================> */
void send_sap_broadcast(int mode)
/* mode=0, standard broadcast */
/* mode=1, first trie */
/* mode=2, shutdown */
{
int k=-1;
while (++k < anz_net_devices) {
NW_NET_DEVICE *nd=net_devices[k];
if (nd->ticks < 7 || mode) { /* isdn devices should not get SAP broadcasts everytime */
IPX_DATA ipx_data;
ipxAddr_t wild;
memset(&wild, 0, sizeof(ipxAddr_t));
U32_TO_BE32(nd->net, wild.net);
memset(wild.node, 0xFF, IPX_NODE_SIZE);
U16_TO_BE16(SOCK_SAP, wild.sock);
memset(&ipx_data, 0, sizeof(ipx_data.sip));
strcpy(ipx_data.sip.server_name, my_nwname);
memcpy(&ipx_data.sip.server_adr, &my_server_adr, sizeof(ipxAddr_t));
U16_TO_BE16(SOCK_NCP, ipx_data.sip.server_adr.sock);
/* use NCP SOCKET */
U16_TO_BE16(2, ipx_data.sip.response_type); /* General */
U16_TO_BE16(4, ipx_data.sip.server_type); /* Fileserver */
if (mode == 2) {
U16_TO_BE16(16, ipx_data.sip.intermediate_networks);
} else {
U16_TO_BE16(1, ipx_data.sip.intermediate_networks);
/* I hope 1 is ok here */
}
send_ipx_data(sockfd[MY_BROADCAST_SLOT], 0,
sizeof(ipx_data.sip),
(char *)&(ipx_data.sip),
&wild, "SIP Broadcast");
}
}
}
static void query_sap_on_net(uint32 net)
/* searches for the next server on this network */
{
SQP sqp;
ipxAddr_t wild;
memset(&wild, 0, sizeof(ipxAddr_t));
memset(wild.node, 0xFF, IPX_NODE_SIZE);
U32_TO_BE32(net, wild.net);
U16_TO_BE16(SOCK_SAP, wild.sock);
U16_TO_BE16(3, sqp.query_type);
U16_TO_BE16(4, sqp.server_type);
send_ipx_data(sockfd[SAP_SLOT], 17, sizeof(SQP),
(char*)&sqp, &wild, "SERVER Query");
}
void get_servers(void)
{
int k=-1;
while (++k < anz_net_devices) {
NW_NET_DEVICE *nd=net_devices[k];
if (nd->ticks < 7) query_sap_on_net(nd->net); /* only fast routes */
}
if (!anz_net_devices) query_sap_on_net(internal_net);
}

731
nwserv.c

File diff suppressed because it is too large Load Diff

58
nwserv.h Normal file
View File

@ -0,0 +1,58 @@
/* nwserv.h 09-Dec-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 uint32 internal_net; /* NETWORKNUMMER INTERN (SERVER) */
extern ipxAddr_t my_server_adr; /* Address of this server */
extern char my_nwname[50]; /* Name of this server */
typedef struct {
char *devname; /* "eth0" or "isdnX" */
int frame; /* frametyp */
int ticks; /* ether:ticks=1, isdn:ticks=7 */
uint32 net; /* NETWORK NUMBER */
} NW_NET_DEVICE;
/* <========== DEVICES ==========> */
extern int anz_net_devices;
extern NW_NET_DEVICE *net_devices[];
/* <======== SOCKETS =========> */
#define MY_BROADCAST_SLOT 0 /* Server Broadcast OUT */
#define WDOG_SLOT 1 /* Watchdog send + recv */
#define SAP_SLOT 2
#define RIP_SLOT 3
#define ROUTE_SLOT 4
#define DIAG_SLOT 5
#if 0
#define ECHO_SLOT 6
#define ERR_SLOT 7
#endif
extern int sockfd[];
extern void send_rip_broadcast(int mode);
extern void send_sap_broadcast(int mode);
extern void rip_for_net(uint32 net);
extern void get_servers(void);
extern void handle_rip(int fd, int ipx_pack_typ,
int data_len, IPX_DATA *ipxdata,
ipxAddr_t *from_addr);

111
tools.c
View File

@ -1,4 +1,4 @@
/* tools.c 18-Nov-95 */
/* tools.c 06-Dec-95 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
@ -21,12 +21,13 @@
#include <sys/vfs.h>
int nw_debug=0;
FILE *logfile=stdout;
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);
fprintf(logfile, "not enough core, need %d Bytes\n", size);
exit(1);
}
return(p);
@ -63,9 +64,9 @@ void dprintf(char *p, ...)
va_list ap;
if (nw_debug){
va_start(ap, p);
vprintf(p, ap);
vfprintf(logfile, p, ap);
va_end(ap);
fflush(stdout);
fflush(logfile);
}
}
@ -74,22 +75,39 @@ void xdprintf(int dlevel, char *p, ...)
va_list ap;
if (nw_debug >= dlevel) {
va_start(ap, p);
vprintf(p, ap);
vfprintf(logfile, p, ap);
va_end(ap);
fflush(stdout);
fflush(logfile);
}
}
void errorp(int mode, char *what, char *p, ...)
{
va_list ap;
int errnum = errno;
if (errnum >= 0 && errnum < _sys_nerr)
fprintf(logfile, "%s:%s\n", what, _sys_errlist[errnum]);
else
fprintf(logfile, "%s:errno=%d\n", what, errnum);
if (p) {
va_start(ap, p);
vfprintf(logfile, p, ap);
va_end(ap);
fprintf(logfile, "\n");
}
fflush(logfile);
}
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);
if (f == (FILE*)NULL) fprintf(logfile, "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 */
/* returns ini_entry or 0 if nothing found */
{
char buff[512];
int do_open = ((FILE*) NULL == f);
@ -98,18 +116,20 @@ int get_ini_entry(FILE *f, int entry, char *str, int strsize)
while (fgets((char*)buff, sizeof(buff), f) != NULL){
int len = strlen(buff);
char *ppi = NULL;
char *ppe = NULL;
int se = 0;
int j = -1;
while (++j < len){
char *pp=(buff+j);
if (*pp == '#' || *pp == '\r' || *pp == '\n') {
*pp = '\0';
len = j;
len = j;
break;
} else if ( *pp == 32 || *pp == '\t') {
if (!se) se = j;
} else if ((!ppi) && se) {
ppi = pp;
} else {
if ((!ppi) && se) ppi = pp;
ppe=pp;
}
}
if (len > se+1 && se > 0 && se < 4 && ppi){
@ -118,6 +138,7 @@ int get_ini_entry(FILE *f, int entry, char *str, int strsize)
strmaxcpy(sx, buff, se);
fentry = atoi(sx);
if (fentry > 0 && ((!entry) || entry == fentry)) {
if (ppe) *(ppe+1) = '\0';
strmaxcpy(str, ppi, strsize-1);
if (do_open) fclose(f);
return(fentry);
@ -135,18 +156,71 @@ char *get_exec_path(char *buff, char *progname)
return(buff);
}
int get_ini_int(int what)
{
char buff[30];
int i;
if (get_ini_entry(NULL, what, buff, sizeof(buff))
&& 1==sscanf(buff, "%d", &i) ) return(i);
return(-1);
}
void get_ini_debug(int what)
void get_ini_debug(int module)
/* 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;
int debug = get_ini_int(100+module);
if (debug > -1) nw_debug = debug;
}
void init_tools(int module)
{
char buff[300];
char logfilename[300];
FILE *f=open_nw_ini();
int withlog=0;
int dodaemon=0;
int new_log=0;
if (f) {
int what;
while (0 != (what=get_ini_entry(f, 0, buff, sizeof(buff)))) { /* daemonize */
if (200 == what) dodaemon = atoi(buff);
else if (201 == what) {
strmaxcpy(logfilename, buff, sizeof(logfilename)-1);
withlog++;
} else if (202 == what) {
new_log = atoi(buff);
} else if (100+module == what) nw_debug=atoi(buff);
}
fclose(f);
}
if (dodaemon) {
if (!withlog) strcpy(logfilename, "./nw.log");
if (NWSERV == module) { /* now make daemon */
int fd=fork();
if (fd) exit((fd > 0) ? 0 : 1);
}
if (NULL == (logfile = fopen(logfilename,
(new_log && NWSERV == module) ? "w" : "a"))) {
char sxx[100];
sprintf(sxx, "\n\nOpen logfile `%s`", logfilename);
perror(sxx);
logfile = stdout;
fprintf(stderr, "\n!! ABORTED !!\n");
exit(1);
}
if (NWSERV == module) setsid();
}
}
void exit_tools(int what)
{
if (logfile != stdout) {
if (logfile != NULL) fclose(logfile);
logfile=stdout;
}
}
@ -199,11 +273,14 @@ static long adjust_blocks (long blocks, int fromsize, int tosize)
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);
XDPRINTF((2,
"blocks=%d, bfree=%d, bavail=%d, files=%d, ffree=%d, bsize=%d\n",
fsd.f_blocks, fsd.f_bfree, fsd.f_bavail,
fsd.f_files, fsd.f_ffree, fsd.f_bsize));
#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);

11
tools.h
View File

@ -17,6 +17,12 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Prozesse die tools verwenden */
#define NWSERV 1
#define NCPSERV 2
#define NWCONN 3
extern FILE *logfile;
extern void x_x_xfree(char **p);
extern int x_x_xnewstr(uint8 **p, uint8 *s);
@ -27,10 +33,13 @@ 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 void errorp(int mode, char *what, 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 char *get_exec_path(char *buff, char *progname);
extern int get_ini_int(int what);
extern void get_ini_debug(int what);
extern void init_tools(int module);
extern uint8 down_char(uint8 ch);
extern uint8 up_char(uint8 ch);