From cfe799f9df86708ad4c1a9ea86bde2547e1d6e2d Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Sun, 13 Nov 2011 00:38:55 +0100 Subject: [PATCH] mars_nwe-0.96.pl00 --- CHANGES | 42 +++ INSTALL | 49 ++-- INSTALL.ger | 30 ++ Makefile | 7 +- README | 20 +- README.ger | 28 +- config.h | 11 - connect.c | 638 ++++++++++++++++++++++++++++------------ emutli.c | 399 +++++++++++-------------- emutli.h | 29 +- examples/config.h | 16 +- examples/nw.ini | 71 +++-- makefile.unx | 29 +- mars_nwe.lsm | 17 +- namspace.c | 97 ++++++ ncpserv.c | 590 +++++++++++++++++++++---------------- net.h | 76 +++-- net1.c | 36 ++- nwconn.c | 433 ++++++++++++++------------- nwcrypt.c | 213 ++++++++++++++ nwdbm.c | 338 ++++++++++++--------- nwdbm.h | 3 + nwroute.c | 335 +++++++++++++++++++++ nwserv.c | 731 ++++++++++++++++++++++------------------------ nwserv.h | 58 ++++ tools.c | 111 +++++-- tools.h | 11 +- 27 files changed, 2838 insertions(+), 1580 deletions(-) create mode 100644 CHANGES create mode 100644 INSTALL.ger delete mode 100644 config.h create mode 100644 namspace.c create mode 100644 nwcrypt.c create mode 100644 nwroute.c create mode 100644 nwserv.h diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000..c90a596 --- /dev/null +++ b/CHANGES @@ -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 ^^^^^^^^ + diff --git a/INSTALL b/INSTALL index f6b5529..f25dd3d 100644 --- a/INSTALL +++ b/INSTALL @@ -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) diff --git a/INSTALL.ger b/INSTALL.ger new file mode 100644 index 0000000..a582396 --- /dev/null +++ b/INSTALL.ger @@ -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. diff --git a/Makefile b/Makefile index 0c5ed36..37867b9 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/README b/README index 01541ac..c32ae31 100644 --- a/README +++ b/README @@ -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 diff --git a/README.ger b/README.ger index e15e7aa..eb4d7d2 100644 --- a/README.ger +++ b/README.ger @@ -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 diff --git a/config.h b/config.h deleted file mode 100644 index 073d927..0000000 --- a/config.h +++ /dev/null @@ -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_ diff --git a/connect.c b/connect.c index 10ca1f0..d4a1a3e 100644 --- a/connect.c +++ b/connect.c @@ -1,4 +1,4 @@ -/* connect.h 21-Nov-95 */ +/* connect.h 18-Dec-95 */ /* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany * * This program is free software; you can redistribute it and/or modify @@ -28,6 +28,9 @@ extern int errno; #define TEST_FNAME "PRINT.000" static int test_handle=-1; +static int default_uid=-1; +static int default_gid=-1; + typedef struct { int fd; /* von System bei Open bzw. Create */ long offd; /* aktueller File Offset */ @@ -235,6 +238,26 @@ static int free_dir_handle(int dhandle) return(-0x88); /* wrong dir_handle */ } +void set_default_guid(void) +{ + seteuid(0); + if (setegid(default_gid) < 0 || seteuid(default_uid) < 0) { + fprintf(stderr, "Cannot set default gid=%d and uid=%d\nABORTET!!\n" , + default_gid, default_uid); + exit(1); + } +} + +void set_guid(int gid, int uid) +{ + if ( gid < 0 || uid < 0 + || seteuid(0) + || setegid(gid) == -1 + || seteuid(uid) == -1 ) { + DPRINTF(("SET GID=%d, UID=%d failed\n", gid, uid)); + set_default_guid(); + } else XDPRINTF((2,"SET GID=%d, UID=%d OK\n", gid, uid)); +} static char *get_nwpath_name(NW_PATH *p) /* for debugging */ @@ -259,6 +282,9 @@ static int x_str_match(uint8 *s, uint8 *p) switch (state){ case 0 : switch (pc) { + case 255: if (*p == '*' || *p == '?') continue; + break; + case '\\': /* beliebiges Folgezeichen */ if (*p++ != *s++) return(0); break; @@ -271,11 +297,16 @@ static int x_str_match(uint8 *s, uint8 *p) if (*p == '*') return(1); break; - case '*' : if (!*p) { + case '*' : +#if 0 + if (!*p) { uint8 *ss=s; while (*ss) if (*ss++ == '.') return(0); return(1); /* last star */ } +#else + if (!*p) return(1); +#endif while (*s){ if (x_str_match(s, p) == 1) return(1); ++s; @@ -331,7 +362,6 @@ static int str_match(uint8 *s, uint8 *p, uint8 options) int len=0; int pf=0; for (; *ss; ss++){ - len++; if (*ss == '.') { if (pf++) return(0); /* Kein 2. Punkt */ len=0; @@ -368,7 +398,7 @@ static int get_dir_entry(NW_PATH *nwpath, nwpath->fn[0] = '\0'; strcpy(xkpath, build_unix_name(nwpath, 1|2)); - DPRINTF(("get_dir_entry attrib=0x%x path:%s:, xkpath:%s:, entry:%s:\n", + XDPRINTF((2,"get_dir_entry attrib=0x%x path:%s:, xkpath:%s:, entry:%s:\n", attrib, nwpath->path, xkpath, entry)); if ((f=opendir(xkpath)) != (DIR*)NULL) { @@ -394,7 +424,7 @@ static int get_dir_entry(NW_PATH *nwpath, if (okflag){ strcpy(nwpath->fn, name); if (soptions & 1) upstr(nwpath->fn); - DPRINTF(("FOUND=:%s: attrib=0x%x\n", nwpath->fn, statb->st_mode)); + XDPRINTF((2,"FOUND=:%s: attrib=0x%x\n", nwpath->fn, statb->st_mode)); break; /* ready */ } } else okflag = 0; @@ -419,7 +449,7 @@ static int get_dh_entry(DIR_HANDLE *dh, DIR *f = dh->f; int okflag = 0; if (f != (DIR*)NULL) { - struct dirent* dirbuff; + struct dirent *dirbuff; uint8 entry[256]; strmaxcpy(entry, search, 255); @@ -427,7 +457,7 @@ static int get_dh_entry(DIR_HANDLE *dh, if ( (uint16)*sequence == MAX_U16) *sequence = 0; seekdir(f, (long) *sequence); - DPRINTF(("get_dh_entry attrib=0x%x path:%s:, entry:%s:\n", + XDPRINTF((2,"get_dh_entry attrib=0x%x path:%s:, entry:%s:\n", attrib, dh->unixname, entry)); while ((dirbuff = readdir(f)) != (struct dirent*)NULL){ @@ -441,16 +471,16 @@ static int get_dh_entry(DIR_HANDLE *dh, if (okflag) { strcpy(dh->kpath, name); - DPRINTF(("get_dh_entry Name=%s unixname=%s\n", + XDPRINTF((2,"get_dh_entry Name=%s unixname=%s\n", name, dh->unixname)); if (!stat(dh->unixname, statb)) { - okflag = ( (( (statb->st_mode & S_IFMT) == S_IFDIR) && (attrib & 0x10)) + okflag = ( (( (statb->st_mode & S_IFMT) == S_IFDIR) && (attrib & 0x10)) || (((statb->st_mode & S_IFMT) != S_IFDIR) && !(attrib & 0x10))); if (okflag){ strcpy(search, name); if (dh->vol_options & 1) upstr(search); - break; /* Bin fertig */ + break; /* ready */ } } else okflag = 0; } @@ -559,11 +589,11 @@ static int nw_path_ok(NW_PATH *nwpath) } d++; } /* while */ - - if (!stat(build_unix_name(nwpath, 1 | 2 ), &stbuff)){ - if ((stbuff.st_mode & S_IFMT) == S_IFDIR) result=stbuff.st_ino; + if (!stat(build_unix_name(nwpath, 1 | 2 ), &stbuff) + && (stbuff.st_mode & S_IFMT) == S_IFDIR) result=stbuff.st_ino; + else { + XDPRINTF((2, "NW_PATH_OK failed:`%s`\n", get_nwpath_name(nwpath))); } - return(result); } @@ -600,7 +630,7 @@ static int build_verz_name(NW_PATH *nwpath, /* gets complete path */ int state = 0; while ((!completition) && (w = *p++) > 0){ if (!state){ - DPRINTF(("in build_verz_name path=:%s:\n", nwpath->path)); + XDPRINTF((2,"in build_verz_name path=:%s:\n", nwpath->path)); if (w == '.') state = 20; else if (w == '/') state = 30; else state++; @@ -665,7 +695,7 @@ static int get_kpl_path(NW_PATH *nwpath, int dirhandle, return(completition); } -static void un_date_2_nw(time_t time, uint8 *d) +static uint16 un_date_2_nw(time_t time, uint8 *d) { struct tm *s_tm=localtime(&time); uint16 xdate=s_tm->tm_year - 80; @@ -673,7 +703,8 @@ static void un_date_2_nw(time_t time, uint8 *d) xdate |= s_tm->tm_mon+1; xdate <<= 5; xdate |= s_tm->tm_mday; - U16_TO_BE16(xdate, d); + if (d) U16_TO_BE16(xdate, d); + return(xdate); } static time_t nw_2_un_time(uint8 *d, uint8 *t) @@ -697,7 +728,7 @@ static time_t nw_2_un_time(uint8 *d, uint8 *t) return(mktime(&s_tm)); } -static void un_time_2_nw(time_t time, uint8 *d) +static uint16 un_time_2_nw(time_t time, uint8 *d) { struct tm *s_tm=localtime(&time); uint16 xdate=s_tm->tm_hour; @@ -705,18 +736,24 @@ static void un_time_2_nw(time_t time, uint8 *d) xdate |= s_tm->tm_min; xdate <<= 5; xdate |= (s_tm->tm_sec / 2); - U16_TO_BE16(xdate, d); + if (d) U16_TO_BE16(xdate, d); + return(xdate); } static int get_file_attrib(NW_FILE_INFO *f, struct stat *stb, NW_PATH *nwpath) { + XDPRINTF((2, "get_file_attrib of %s\n", get_nwpath_name(nwpath) )); strncpy(f->name, nwpath->fn, sizeof(f->name)); /* Attribute */ /* 0x20 Archive Flag */ /* 0x80 Sharable */ /* TLINK (TCC 2.0) don't like it ???? */ +#if 1 if (!strcmp(nwpath->fn, "TURBOC.$LN")) f->attrib = 0x20; else f->attrib = 0x80; +#else + f->attrib = 0x20; +#endif f->ext_attrib = 0; un_date_2_nw(stb->st_mtime, f->create_date); un_date_2_nw(stb->st_atime, f->acces_date ); @@ -729,7 +766,9 @@ static int get_file_attrib(NW_FILE_INFO *f, struct stat *stb, static int get_dir_attrib(NW_DIR_INFO *d, struct stat *stb, NW_PATH *nwpath) { + XDPRINTF((2, "get_dir_attrib of %s\n", get_nwpath_name(nwpath))); strncpy(d->name, nwpath->fn, sizeof(d->name)); + d->attrib = 0x10; /* Verzeichnis */ d->ext_attrib = 0xff; /* effektive rights ?? */ @@ -777,16 +816,16 @@ int nw_creat_open_file(int dir_handle, uint8 *data, int len, if (creatmode) { /* creat File */ if (creatmode & 0x2) { /* creatnew */ if (!stat(fh->name, &stbuff)) { - DPRINTF(("CREAT File exist!! :%s:\n", fh->name)); + XDPRINTF((2,"CREAT File exist!! :%s:\n", fh->name)); fh->fd = -1; completition = -0x85; /* No Priv */ } else { - DPRINTF(("CREAT FILE:%s: Handle=%d\n", fh->name, fhandle)); + XDPRINTF((2,"CREAT FILE:%s: Handle=%d\n", fh->name, fhandle)); fh->fd = creat(fh->name, 0777); if (fh->fd < 0) completition = -0x84; /* no create Rights */ } } else { - DPRINTF(("CREAT FILE, ever with attrib:0x%x, access:0x%x, fh->name:%s: handle:%d\n", + XDPRINTF((2,"CREAT FILE, ever with attrib:0x%x, access:0x%x, fh->name:%s: handle:%d\n", attrib, access, fh->name, fhandle)); fh->fd = open(fh->name, O_CREAT|O_TRUNC|O_RDWR, 0777); if (fh->fd < 0) completition = -0x85; /* no delete /create Rights */ @@ -803,7 +842,7 @@ int nw_creat_open_file(int dir_handle, uint8 *data, int len, int acm = (access & 2) ? (int) O_RDWR /*|O_CREAT*/ : (int)O_RDONLY; if ( (!statr && (stbuff.st_mode & S_IFMT) != S_IFDIR) || (statr && (acm & O_CREAT))){ - DPRINTF(("OPEN FILE with attrib:0x%x, access:0x%x, fh->name:%s: fhandle=%d\n",attrib,access, fh->name, fhandle)); + XDPRINTF((2,"OPEN FILE with attrib:0x%x, access:0x%x, fh->name:%s: fhandle=%d\n",attrib,access, fh->name, fhandle)); fh->fd = open(fh->name, acm, 0777); fh->offd = 0L; if (fh->fd > -1) { @@ -822,7 +861,7 @@ int nw_creat_open_file(int dir_handle, uint8 *data, int len, } } - DPRINTF(("OPEN FILE not OK ! fh->name:%s: fhandle=%d\n",fh->name, fhandle)); + XDPRINTF((2,"OPEN FILE not OK ! fh->name:%s: fhandle=%d\n",fh->name, fhandle)); free_file_handle(fhandle); #ifdef TEST_FNAME if (got_testfn) { @@ -843,7 +882,7 @@ int nw_delete_datei(int dir_handle, uint8 *data, int len) char unname[256]; struct stat stbuff; strcpy(unname, build_unix_name(&nwpath, 0)); - DPRINTF(("DELETE FILE unname:%s:\n", unname)); + XDPRINTF((2,"DELETE FILE unname:%s:\n", unname)); if (!stat(unname, &stbuff)){ if (!unlink(unname)) return(0); return(-0x8a); /* NO Delete Privileges */ @@ -864,7 +903,7 @@ int nw_chmod_datei(int dir_handle, uint8 *data, int len, int modus) } if (completition < 0) return(completition); strcpy(unname, build_unix_name(&nwpath, 2)); - DPRINTF(("CHMOD DATEI unname:%s:\n", unname)); + XDPRINTF((2,"CHMOD DATEI unname:%s:\n", unname)); if (!stat(unname, &stbuff)){ return(0); } @@ -953,7 +992,7 @@ int nw_write_datei(int fhandle, uint8 *data, int size, uint32 offset) flockd.l_len = 0; #if HAVE_TLI result = fcntl(fh->fd, F_FREESP, &flockd); - DPRINTF(("File %s is stripped, result=%d\n", fh->name, result)); + XDPRINTF((2,"File %s is stripped, result=%d\n", fh->name, result)); #endif return(result); } @@ -1040,11 +1079,11 @@ int nw_mk_rd_dir(int dir_handle, uint8 *data, int len, int mode) #endif if (mode) { - DPRINTF(("MKDIR dirname:%s:\n", unname)); + XDPRINTF((2,"MKDIR dirname:%s:\n", unname)); if (!mkdir(unname, 0777)) return(0); completition = -0x84; /* No Create Priv.*/ /* -0x9f Direktory Aktive */ } else { /* rmdir */ - DPRINTF(("RMDIR dirname:%s:\n", unname)); + XDPRINTF((2,"RMDIR dirname:%s:\n", unname)); if (!rmdir(unname)) { NW_DIR *d=&(dirs[0]); int j = 0; @@ -1120,12 +1159,13 @@ static int change_dir_entry( NW_DIR *dir, int volume, int nw_init_connect(void) /* Cann be called when ever you want */ { - uint8 *login = (uint8*) "LOGIN/"; + uint8 *login = (uint8*) "LOGIN/"; NW_PATH nwlogin; - FILE *f=open_nw_ini(); + FILE *f= open_nw_ini(); if (f != (FILE*) NULL){ uint8 buff[256]; struct stat stbuff; + int what; int k = MAX_NW_DIRS; NW_DIR *d = &(dirs[0]); strcpy(nwlogin.path, login); @@ -1155,27 +1195,16 @@ int nw_init_connect(void) k = 0; while (k++ < anz_dirhandles) free_dir_handle(k); } - used_vols = 0; - - while (fgets((char*)buff, sizeof(buff), f) != NULL && used_vols < MAX_NW_VOLS){ - int len = strlen(buff); - int j =-1; - while (++j < len){ - if (buff[j] == '#') { - buff[j] = '\0'; - len = j; - break; - } - } - if (len > 3){ - int what=0; + used_vols = 0; + while (0 != (what = get_ini_entry(f, 0, (char*)buff, sizeof(buff)))) { + if ( what == 1 && used_vols < MAX_NW_VOLS && strlen(buff) > 3){ uint8 sysname[256]; uint8 unixname[256]; char optionstr[256]; - char *p; - int len; - int founds = sscanf((char*)buff, "%d %s %s %s", &what, sysname, unixname, optionstr); - if (founds > 2 && what == 1) { + char *p; + int len; + int founds = sscanf((char*)buff, "%s %s %s",sysname, unixname, optionstr); + if (founds > 1) { new_str(vols[used_vols].sysname, sysname); len = strlen(unixname); if (unixname[len-1] != '/') { @@ -1184,7 +1213,7 @@ int nw_init_connect(void) } vols[used_vols].options = 0; new_str(vols[used_vols].unixname, unixname); - if (founds > 3) { + if (founds > 2) { for (p=optionstr; *p; p++) { switch (*p) { case 'k' : vols[used_vols].options |= 1; @@ -1194,13 +1223,22 @@ int nw_init_connect(void) } used_vols++; } + } else if (what == 10) { /* GID */ + default_gid = atoi(buff); + } else if (what == 11) { /* UID */ + default_uid = atoi(buff); + } else if (what == 103) { /* Debug */ + nw_debug = atoi(buff); } } fclose(f); + if (stat(build_unix_name(&nwlogin, 0), &stbuff)) { - perror("Stat error in nw_init_connect, Abbruch"); + errorp(0, "Stat error LOGIN Directory, Abort !!", + "UnixPath=`%s`", build_unix_name(&nwlogin, 0)); return(-1); } + (void)change_dir_entry(&(dirs[0]), 0, nwlogin.path, stbuff.st_ino, 0, 0, 1, 0); /* first Handle must be known und must not be temp */ @@ -1274,17 +1312,19 @@ int nw_search(uint8 *info, { NW_PATH nwpath; int completition = get_kpl_path(&nwpath, dirhandle, data, len, 0); - DPRINTF(("nw_search path:%s:, fn:%s:, completition:0x%x\n", + XDPRINTF((2,"nw_search path:%s:, fn:%s:, completition:0x%x\n", nwpath.path, nwpath.fn, completition)); if (completition > -1) { struct stat stbuff; - if (get_dir_entry(&nwpath, &searchsequence, search_attrib, &stbuff)){ - +#if 1 + if ( (stbuff.st_mode & S_IFMT) == S_IFDIR) { +#else if (search_attrib & 0x10) { +#endif get_dir_attrib((NW_DIR_INFO*)info, &stbuff, &nwpath); } else { @@ -1313,18 +1353,17 @@ int nw_dir_search(uint8 *info, search_attrib, &stbuff)){ - /* +#if 1 if ( (stbuff.st_mode & S_IFMT) == S_IFDIR) { - */ - +#else if (search_attrib & 0x10) { - get_dir_attrib((NW_DIR_INFO*)info, &stbuff, - &nwpath); +#endif + get_dir_attrib((NW_DIR_INFO*)info, &stbuff, + &nwpath); } else { get_file_attrib((NW_FILE_INFO*)info, &stbuff, &nwpath); } - return(searchsequence); } else return(-0xff); /* not found */ } else return(completition); /* wrong path */ @@ -1342,7 +1381,7 @@ int nw_alloc_dir_handle( int dir_handle, /* Suche ab Pfad dirhandle */ int inode=get_kpl_path(&nwpath, dir_handle, data, len, 1); if (inode > -1) inode = insert_new_dir(&nwpath, inode, driveletter, is_temphandle, task); - DPRINTF(("Allocate %shandle:%s, Handle=%d, drive=%d, result=0x%x\n", + XDPRINTF((2,"Allocate %shandle:%s, Handle=%d, drive=%d, result=0x%x\n", (is_temphandle) ? "Temp" : "Perm", get_nwpath_name(&nwpath), dir_handle, driveletter, inode)); return(inode); @@ -1357,19 +1396,17 @@ int nw_open_dir_handle( int dir_handle, int *searchsequence) /* - * Routine liefert Handle aehnlich Filehandle. - * Handle kann in der Suchroutine verwendet werden - * RETURN=Fehlercode ( <0 ) od. ACCES Rights + * Routine returns handle to use in searchroutines. + * RETURN=errcode ( <0 ) or ACCES Rights */ { NW_PATH nwpath; int completition = get_kpl_path(&nwpath, dir_handle, data, len, 1); - DPRINTF(("NW_OPEN_DIR: completition = 0x%x; nwpath= %s\n", - (int)completition, - get_nwpath_name(&nwpath) )); - if (completition > -1) { + XDPRINTF((2,"NW_OPEN_DIR: completition = 0x%x; nwpath= %s\n", + (int)completition, get_nwpath_name(&nwpath) )); + completition = new_dir_handle((ino_t)completition, &nwpath); if (completition > -1) { DIR_HANDLE *fh = &(dir_handles[completition-1]); @@ -1378,8 +1415,10 @@ int nw_open_dir_handle( int dir_handle, *searchsequence = MAX_U16; completition = 0xff; /* Alle Rechte */ } - DPRINTF(("NW_OPEN_DIR_2: completition = 0x%x\n", + XDPRINTF((2,"NW_OPEN_DIR_2: completition = 0x%x\n", (int)completition)); + } else { + XDPRINTF((2,"NW_OPEN_DIR failed: completition = 0x%x\n", (int)completition)); } return(completition); } @@ -1406,7 +1445,7 @@ int nw_set_dir_handle(int targetdir, int dir_handle, if (inode > -1){ if (targetdir > 0 && --targetdir < used_dirs && dirs[targetdir].is_temp != 2) { /* not a spez. temphandle */ - DPRINTF(("Change dhandle:%d -> %s:\n", targetdir+1, get_nwpath_name(&nwpath))); + XDPRINTF((2,"Change dhandle:%d -> `%s`\n", targetdir+1, get_nwpath_name(&nwpath))); return(change_dir_entry(&dirs[targetdir], nwpath.volume, nwpath.path, inode, -1, -1, 0, task)); /* here the existing handle is only modified */ } else return(-0x9b); /* BAD DIR Handle */ @@ -1425,7 +1464,7 @@ int nw_get_directory_path(int dir_handle, uint8 *name) if (name[result-1] == '/') name[--result] = '\0'; } else result = -0x98; } - DPRINTF(("nw_get_directory_path:%s: Handle=%d, result=0x%x\n", name, dir_handle+1, result)); + XDPRINTF((2,"nw_get_directory_path:%s: Handle=%d, result=0x%x\n", name, dir_handle+1, result)); return(result); } @@ -1437,7 +1476,7 @@ int nw_get_vol_number(int dir_handle) result = dirs[dir_handle].volume; if (result >= used_vols) result = -0x98; /* Falsches Volume */ } - DPRINTF(("nw_get_vol_number:0x%x: von Handle=%d\n", result, dir_handle+1)); + XDPRINTF((2,"nw_get_vol_number:0x%x: von Handle=%d\n", result, dir_handle+1)); return(result); } @@ -1456,7 +1495,7 @@ int nw_get_volume_number(uint8 *volname, int namelen) break; } } - DPRINTF(("GET_VOLUME_NUMBER of:%s: result = 0x%x\n", vname, result)); + XDPRINTF((2,"GET_VOLUME_NUMBER of:%s: result = 0x%x\n", vname, result)); return(result); } @@ -1468,21 +1507,24 @@ int nw_get_volume_name(int volnr, uint8 *volname) strcpy(volname, vols[volnr].sysname); result = strlen(volname); } else volname[0] = '\0'; - DPRINTF(("GET_VOLUME_NAME von:%d = %s: ,result=0x%x\n", volnr, volname, result)); + XDPRINTF((2,"GET_VOLUME_NAME von:%d = %s: ,result=0x%x\n", volnr, volname, result)); return(result); } -int nw_get_eff_dir_rights(int dir_handle, uint8 *data, int len) +int nw_get_eff_dir_rights(int dir_handle, uint8 *data, int len, int modus) +/* modus 0=only_dir, 1=dirs and files */ { char unname[256]; struct stat stbuff; NW_PATH nwpath; - int completition = get_kpl_path(&nwpath, dir_handle, data, len, 1); + int completition = get_kpl_path(&nwpath, dir_handle, data, len, + (modus) ? 0 : 1); if (completition < 0) return(completition); strcpy(unname, build_unix_name(&nwpath, 0)); - if (stat(unname, &stbuff) || (stbuff.st_mode & S_IFMT) != S_IFDIR) { + if (stat(unname, &stbuff) || + (!modus && (stbuff.st_mode & S_IFMT) != S_IFDIR) ) { completition = -0x9c; - } else completition=0xff; /* alle Rechte */ + } else completition=0xff; /* all rights */ return(completition); } @@ -1505,44 +1547,54 @@ static int s_nw_scan_dir_info(int dir_handle, uint8 *owner, uint8 *wild) { int volume; - int searchsequenz; + int searchsequence; int dir_id; int rights = nw_open_dir_handle(dir_handle, data, len, - &volume, &dir_id, &searchsequenz); + &volume, &dir_id, &searchsequence); - DPRINTF(("SCAN_DIR: rights = 0x%x, subnr = %d\n", - (int)rights, (int)GET_BE16(subnr))); if (rights > -1) { DIR_HANDLE *dh = &(dir_handles[dir_id-1]); struct stat stbuff; int searchsequence = MAX_U16; - uint16 dirsequenz = GET_BE16(subnr); uint16 aktsequenz = 0; uint8 dirname[256]; - if (!dirsequenz) dirsequenz++; strcpy(dirname, wild); - while ( get_dh_entry( dh, - dirname, - &searchsequence, - 0x10, - &stbuff) ) { + XDPRINTF((2,"SCAN_DIR: rights = 0x%x, subnr = %d\n", + (int)rights, (int)GET_BE16(subnr))); - DPRINTF(("SCAN_DIR: von %s, found %s:\n", dh->unixname, dirname)); - if (++aktsequenz == dirsequenz) { /* actual found */ - U16_TO_BE16(aktsequenz, subnr); - strncpy(subname, dirname, 16); - U32_TO_BE32(1L, owner); /* erstmal */ - un_date_2_nw(stbuff.st_mtime, subdatetime); - un_time_2_nw(stbuff.st_mtime, subdatetime+2); - return(0xff); + if (*dirname) { + while ( get_dh_entry( dh, + dirname, + &searchsequence, + 0x10, + &stbuff) ) { + + XDPRINTF((2,"SCAN_DIR: von %s, found %s:\n", dh->unixname, dirname)); + if (++aktsequenz == dirsequenz) { /* actual found */ + U16_TO_BE16(aktsequenz, subnr); + strncpy(subname, dirname, 16); + U32_TO_BE32(1L, owner); /* erstmal */ + un_date_2_nw(stbuff.st_mtime, subdatetime); + un_time_2_nw(stbuff.st_mtime, subdatetime+2); + return(0xff); + } + strcpy(dirname, wild); + } /* while */ + } else { + strcpy(dh->kpath, "."); + if (!stat(dh->unixname, &stbuff)) { + U16_TO_BE16(1, subnr); + memset(subname, 0, 16); + U32_TO_BE32(1L, owner); + un_date_2_nw(stbuff.st_mtime, subdatetime); + un_time_2_nw(stbuff.st_mtime, subdatetime+2); + return(0xff); } - strcpy(dirname, wild); - - } /* while */ + } /* return(-0x9c); NO MORE INFO */ return(-0xff); } @@ -1563,10 +1615,10 @@ int nw_scan_dir_info(int dir_handle, uint8 *data, int len, uint8 *subnr, break; } } - if (len /* && k < len */) { + if (len && k < len) { strmaxcpy(dirname, p, len-k); len = k; - } else strcpy(dirname, "*"); + } else dirname[0] = '\0'; return(s_nw_scan_dir_info(dir_handle, data, len, subnr, subname, subdatetime, owner, dirname)); } @@ -1578,41 +1630,198 @@ int nw_get_fs_usage(char *volname, struct fs_usage *fsu) return((volnr>-1 && !get_fs_usage(vols[volnr].unixname, fsu)) ? 0 : -1); } +typedef struct { + uint8 time[2]; + uint8 date[2]; + uint8 id[4]; +} NW_FILE_DATES_INFO; -/* NAMESPACE routines */ -int nw_generate_dir_path(uint8 *nwpathstruct, - uint8 *ns_dir_base, uint8 *dos_dir_base) -/* returns Volume Number >=0 or errcode < 0 if error */ +typedef struct { + uint8 subdir[4]; + uint8 attributes[4]; /* 0x20,0,0,0 File */ + uint8 uniqueid; /* 0 */ + uint8 flags; /* 0x18 */ + uint8 namespace; /* 0 */ + uint8 namlen; + uint8 name[12]; + NW_FILE_DATES_INFO created; + NW_FILE_DATES_INFO archived; + NW_FILE_DATES_INFO updated; + uint8 size[4]; + uint8 reserved_1[44]; + uint8 inherited_rights_mask[2]; + uint8 last_access_date[2]; + uint8 reserved_2[28]; +} NW_DOS_FILE_INFO; + +static void xun_date_2_nw(time_t time, uint8 *d) { - return(-0xfb); /* TODO: complete call */ + uint16 i = un_date_2_nw(time, NULL); + memcpy(d, &i, 2); } +static void xun_time_2_nw(time_t time, uint8 *d) +{ + uint16 i = un_time_2_nw(time, NULL); + memcpy(d, &i, 2); +} + +static void get_dos_file_attrib(NW_DOS_FILE_INFO *f, + struct stat *stb, + NW_PATH *nwpath) +{ + f->namlen=min(strlen(nwpath->fn), 12); + strncpy(f->name, nwpath->fn, f->namlen); + /* Attribute */ + /* 0x20 Archive Flag */ + /* 0x80 Sharable */ + f->attributes[0] = 0x20; + xun_date_2_nw(stb->st_mtime, f->created.date); + xun_time_2_nw(stb->st_mtime, f->created.time); + U32_TO_BE32(1, f->created.id); + memcpy(&(f->updated), &(f->created), sizeof(NW_DOS_FILE_INFO)); + xun_date_2_nw(stb->st_atime, f->last_access_date); + memcpy(f->size, &(stb->st_size), 4); +} + +typedef struct { + uint8 subdir[4]; + uint8 attributes[4]; /* 0x10,0,0,0 DIR */ + uint8 uniqueid; /* 0 */ + uint8 flags; /* 0x14 or 0x1c */ + uint8 namespace; /* 0 */ + uint8 namlen; + uint8 name[12]; + NW_FILE_DATES_INFO created; + NW_FILE_DATES_INFO archived; + uint8 modify_time[2]; + uint8 modify_date[2]; + uint8 next_trustee[4]; + uint8 reserved_1[48]; + uint8 max_space[4]; + uint8 inherited_rights_mask[2]; + uint8 reserved_2[26]; +} NW_DOS_DIR_INFO; +static void get_dos_dir_attrib(NW_DOS_DIR_INFO *f, + struct stat *stb, + NW_PATH *nwpath) +{ + f->namlen=min(strlen(nwpath->fn), 12); + strncpy(f->name, nwpath->fn, f->namlen); + f->attributes[0] = 0x10; /* Dir */ + xun_date_2_nw(stb->st_mtime, f->created.date); + xun_time_2_nw(stb->st_mtime, f->created.time); + U32_TO_BE32(1, f->created.id); + xun_date_2_nw(stb->st_mtime, f->modify_date); + xun_time_2_nw(stb->st_mtime, f->modify_time); + U32_TO_BE32(MAX_U32, f->max_space); +} +typedef struct { + uint8 searchsequence[4]; + union { + NW_DOS_DIR_INFO d; + NW_DOS_FILE_INFO f; + } u; +} NW_SCAN_DIR_INFO; +int nw_scan_a_directory(uint8 *rdata, + int dirhandle, + uint8 *data, + int len, + int searchattrib, + uint32 searchbeg) /* 32 bit */ +{ + NW_PATH nwpath; + int completition = get_kpl_path(&nwpath, dirhandle, data, len, 0); + XDPRINTF((2,"nw_scan_a_directory path:%s:, fn:%s:, completition:0x%x\n", + nwpath.path, nwpath.fn, completition)); + if (completition > -1) { + struct stat stbuff; + int searchsequence = (searchbeg == MAX_U32) ? MAX_U16 : searchbeg; + if (get_dir_entry(&nwpath, + &searchsequence, + searchattrib, + &stbuff)){ + NW_SCAN_DIR_INFO *scif = (NW_SCAN_DIR_INFO*)rdata; + memset(rdata, 0, sizeof(NW_SCAN_DIR_INFO)); + U32_TO_BE32((uint32)searchsequence, scif->searchsequence); + + if ( (stbuff.st_mode & S_IFMT) == S_IFDIR) { + get_dos_dir_attrib(&(scif->u.d), &stbuff, + &nwpath); + } else { + get_dos_file_attrib(&(scif->u.f), &stbuff, + &nwpath); + } + return(sizeof(NW_SCAN_DIR_INFO)); + } else return(-0xff); /* not found */ + } else return(completition); /* wrong path */ +} + +int nw_scan_a_root_dir(uint8 *rdata, + int dirhandle) +{ + NW_PATH nwpath; + uint8 data[2]; + int completition = get_kpl_path(&nwpath, dirhandle, data, 0, 1); + XDPRINTF((2,"nw_scan_a_directory_2 path:%s:, fn:%s:, completition:0x%x\n", + nwpath.path, nwpath.fn, completition)); + if (completition > -1) { + struct stat stbuff; + if (!stat(build_unix_name(&nwpath, 2), &stbuff)) { + NW_DOS_DIR_INFO *d=(NW_DOS_DIR_INFO*)rdata; + memset(rdata, 0, sizeof(NW_DOS_DIR_INFO)); + get_dos_dir_attrib(d, &stbuff, &nwpath); + return(sizeof(NW_DOS_DIR_INFO)); + } else return(-0xff); /* not found */ + } else return(completition); /* wrong path */ +} /* minimal queue handling to enable very simple printing */ /* qick and dirty !!!!!!!!!!!!!!! */ -#define MAX_JOBS 5 /* max. open queue jobs for one connection */ +#define MAX_JOBS 5 /* max. open queue jobs for one connection */ static int anz_jobs=0; -QUEUE_JOB *queue_jobs[MAX_JOBS]; -static QUEUE_JOB *give_new_queue_job(void) +typedef struct { + uint32 fhandle; + int old_job; /* is old structure */ + union { + QUEUE_JOB n; + QUEUE_JOB_OLD o; + } q; +} INT_QUEUE_JOB; + +INT_QUEUE_JOB *queue_jobs[MAX_JOBS]; + +static INT_QUEUE_JOB *give_new_queue_job(int old_job) { int k=-1; while (++k < anz_jobs) { - QUEUE_JOB *p=queue_jobs[k]; - if (!p->record_in_use[0] && !p->record_in_use[1]) /* free slot */ + INT_QUEUE_JOB *p=queue_jobs[k]; + if (!p->fhandle) { /* free slot */ + memset(p, 0, sizeof(INT_QUEUE_JOB)); + p->old_job = old_job; + if (old_job) + p->q.o.job_id[0] = k+1; + else + p->q.n.job_id[0] = k+1; return(p); + } } if (anz_jobs < MAX_JOBS) { - QUEUE_JOB **pp=&(queue_jobs[anz_jobs++]); - *pp = (QUEUE_JOB *) xmalloc(sizeof(QUEUE_JOB)); - memset(*pp, 0, sizeof(QUEUE_JOB)); - (*pp)->job_id[0] = anz_jobs; + INT_QUEUE_JOB **pp=&(queue_jobs[anz_jobs++]); + *pp = (INT_QUEUE_JOB *) xmalloc(sizeof(INT_QUEUE_JOB)); + memset(*pp, 0, sizeof(INT_QUEUE_JOB)); + (*pp)->old_job = old_job; + if (old_job) + (*pp)->q.o.job_id[0] = anz_jobs; + else + (*pp)->q.n.job_id[0] = anz_jobs; return(*pp); } return(NULL); @@ -1621,96 +1830,149 @@ static QUEUE_JOB *give_new_queue_job(void) static void free_queue_job(int q_id) { if (q_id > 0 && q_id <= anz_jobs) { - QUEUE_JOB **pp=&(queue_jobs[q_id-1]); - uint32 fhandle = (uint32) GET_BE16((*pp)->job_file_handle); + INT_QUEUE_JOB **pp=&(queue_jobs[q_id-1]); + uint32 fhandle = (*pp)->fhandle; if (fhandle > 0) nw_close_datei(fhandle); if (q_id == anz_jobs) { xfree(*pp); --anz_jobs; - } else { - memset(*pp, 0, sizeof(QUEUE_JOB)); - (*pp)->job_id[0] = q_id; - } + } else (*pp)->fhandle=0L; } } -int nw_creat_queue(int connection, uint8 *queue_id, uint8 *queue_job, - uint8 *dirname, int dir_nam_len) +static void set_entry_time(uint8 *entry_time) { - QUEUE_JOB job_buff; - QUEUE_JOB *jo = give_new_queue_job(); - uint32 q_id = GET_BE32(queue_id); + struct tm *s_tm; + time_t timer; + time(&timer); + s_tm = localtime(&timer); + entry_time[0] = (uint8) s_tm->tm_year; + entry_time[1] = (uint8) s_tm->tm_mon+1; + entry_time[2] = (uint8) s_tm->tm_mday; + entry_time[3] = (uint8) s_tm->tm_hour; + entry_time[4] = (uint8) s_tm->tm_min; + entry_time[5] = (uint8) s_tm->tm_sec; +} + +static int create_queue_file(char *job_file_name, + uint32 q_id, + int jo_id, + int connection, + uint8 *dirname, + int dir_nam_len, + uint8 *job_bez) + +{ + int result; NW_FILE_INFO fnfo; + *job_file_name + = sprintf(job_file_name+1, "%07X%d.%03d", q_id, jo_id, connection); + + result=nw_alloc_dir_handle(0, dirname, dir_nam_len, 99, 2, 1); + if (result > -1) + result = nw_creat_open_file(result, job_file_name+1, + (int) *job_file_name, + &fnfo, 0x6, 0x6, 1); + + XDPRINTF((2,"creat queue file bez=`%s` handle=%d\n", + job_bez, result)); + return(result); +} + + +int nw_creat_queue(int connection, uint8 *queue_id, uint8 *queue_job, + uint8 *dirname, int dir_nam_len, int old_call) +{ + QUEUE_JOB job_buff; + INT_QUEUE_JOB *jo = give_new_queue_job(old_call); + uint32 q_id = GET_BE32(queue_id); int result = -0xff; - DPRINTF(("NW_CREAT_Q:dlen=%d, dirname=%s\n", dir_nam_len, dirname)); + XDPRINTF((2,"NW_CREAT_Q:dlen=%d, dirname=%s\n", dir_nam_len, dirname)); + if (NULL != jo) { - struct tm *s_tm; - time_t timer; - int jo_id = (int) jo->job_id[0]; - memcpy(jo, queue_job, sizeof(QUEUE_JOB)); - jo->job_id[0] = (uint8) jo_id; + int jo_id = 0; + if (jo->old_job) { + jo_id = (int) jo->q.o.job_id[0]; + memcpy(&(jo->q.o), queue_job, sizeof(QUEUE_JOB_OLD)); + jo->q.o.job_id[0] = (uint8) jo_id; + jo->q.o.client_connection = (uint8)connection; + jo->q.o.client_task = (uint8)0xfe; /* ?? */ + U32_TO_BE32(1, jo->q.o.client_id); /* SU */ + set_entry_time(jo->q.o.job_entry_time); + jo->q.o.job_typ[0] = 0x0; /* 0xd0;*/ + jo->q.o.job_typ[1] = 0x0; + jo->q.o.job_position = 0x1; + jo->q.o.job_control_flags |= 0x20; - U16_TO_BE16(0xffff, jo->record_in_use); - U32_TO_BE32(0x0, jo->record_previous); - U32_TO_BE32(0x0, jo->record_next); + result = create_queue_file(jo->q.o.job_file_name, + q_id, jo_id, connection, + dirname, dir_nam_len, + jo->q.o.job_bez); - memset(jo->client_connection, 0, 4); - jo->client_connection[0] = (uint8)connection; - memset(jo->client_task, 0, 4); - jo->client_task[0] = (uint8)0xfe; /* ?? */ + if (result > -1) { + jo->fhandle = (uint32) result; + U32_TO_BE32(jo->fhandle, jo->q.o.job_file_handle); + U16_TO_BE16(0, jo->q.o.job_file_handle+4); + result = 0; + } + jo->q.o.server_station = 0; + jo->q.o.server_task = 0; + U32_TO_BE32(0, jo->q.o.server_id); + if (!result) memcpy(queue_job, &(jo->q.o), sizeof(QUEUE_JOB_OLD)); + } else { + jo_id = (int) jo->q.n.job_id[0]; + memcpy(&(jo->q.n), queue_job, sizeof(QUEUE_JOB)); + jo->q.n.job_id[0] = (uint8) jo_id; - U32_TO_BE32(1, jo->client_id); /* SU */ + U16_TO_BE16(0xffff, jo->q.n.record_in_use); + U32_TO_BE32(0x0, jo->q.n.record_previous); + U32_TO_BE32(0x0, jo->q.n.record_next); + memset(jo->q.n.client_connection, 0, 4); + jo->q.n.client_connection[0] = (uint8)connection; + memset(jo->q.n.client_task, 0, 4); + jo->q.n.client_task[0] = (uint8)0xfe; /* ?? */ + U32_TO_BE32(1, jo->q.n.client_id); /* SU */ + set_entry_time(jo->q.n.job_entry_time); - time(&timer); - s_tm = localtime(&timer); - jo->job_entry_time[0] = (uint8) s_tm->tm_year; - jo->job_entry_time[1] = (uint8) s_tm->tm_mon+1; - jo->job_entry_time[2] = (uint8) s_tm->tm_mday; - jo->job_entry_time[3] = (uint8) s_tm->tm_hour; - jo->job_entry_time[4] = (uint8) s_tm->tm_min; - jo->job_entry_time[5] = (uint8) s_tm->tm_sec; + jo->q.n.job_typ[0] = 0x0; /* 0xd0;*/ + jo->q.n.job_typ[1] = 0x0; + jo->q.n.job_position[0] = 0x1; + jo->q.n.job_position[1] = 0x0; + jo->q.n.job_control_flags[0] |= 0x20; + jo->q.n.job_control_flags[1] = 0x0; - jo->job_typ[0] = 0x0; /* 0xd0;*/ - jo->job_typ[1] = 0x0; - jo->job_position[0] = 0x1; - jo->job_position[1] = 0x0; - jo->job_control_flags[0] |= 0x20; - jo->job_control_flags[1] = 0x0; + result = create_queue_file(jo->q.n.job_file_name, + q_id, jo_id, connection, + dirname, dir_nam_len, + jo->q.n.job_bez); - jo->job_file_name[0] - = sprintf(jo->job_file_name+1, "%07X%d.%03d", q_id, jo_id, connection); - result=nw_alloc_dir_handle(0, dirname, dir_nam_len, 99, 2, 1); - - if (result > -1) - result = nw_creat_open_file(result, jo->job_file_name+1, - (int)jo->job_file_name[0], - &fnfo, 0x6, 0x6, 1); - - DPRINTF(("creat print queue bez=`%s` handle=%d\n", jo->job_bez, result)); - - if (result > -1) { - U16_TO_BE16((uint16)result, jo->job_file_handle); - U16_TO_BE16(0, jo->job_file_handle+2); - result = 0; + if (result > -1) { + jo->fhandle = (uint32) result; + U16_TO_BE16((uint16)result, jo->q.n.job_file_handle); + U16_TO_BE16(0, jo->q.n.job_file_handle+2); + result = 0; + } + U32_TO_BE32(0, jo->q.n.server_station); + U32_TO_BE32(0, jo->q.n.server_task); + U32_TO_BE32(0, jo->q.n.server_id); + if (!result) memcpy(queue_job, &(jo->q.n), sizeof(QUEUE_JOB)); } - U32_TO_BE32(0, jo->server_station); - U32_TO_BE32(0, jo->server_task); - U32_TO_BE32(0, jo->server_id); - if (!result) memcpy(queue_job, jo, sizeof(QUEUE_JOB)); - else free_queue_job(jo_id); + if (result) free_queue_job(jo_id); } return(result); } -int nw_close_file_queue(uint8 *queue_id, uint8 *job_id, +int nw_close_file_queue(uint8 *queue_id, + uint8 *job_id, uint8 *prc, int prc_len) { - int result = 0; - int jo_id = (int) *job_id; - DPRINTF(("nw_close_file_queue JOB=%d\n", jo_id)); + int result = -0xff; + int jo_id = (int) *job_id; /* ever only the first byte */ + XDPRINTF((2,"nw_close_file_queue JOB=%d\n", jo_id)); if (jo_id > 0 && jo_id <= anz_jobs){ - QUEUE_JOB *jo=queue_jobs[jo_id-1]; - int fhandle = (int) GET_BE16(jo->job_file_handle); + INT_QUEUE_JOB *jo=queue_jobs[jo_id-1]; + int fhandle = (int)jo->fhandle; + XDPRINTF((2,"nw_close_file_queue fhandle=%d\n", fhandle)); if (fhandle > 0 && fhandle <= anz_fhandles) { FILE_HANDLE *fh=&(file_handles[fhandle-1]); char unixname[300]; @@ -1719,8 +1981,7 @@ int nw_close_file_queue(uint8 *queue_id, uint8 *job_id, strmaxcpy(unixname, fh->name, sizeof(unixname)-1); strmaxcpy(printcommand, prc, prc_len); nw_close_datei(fhandle); - U16_TO_BE16((uint16)0, jo->job_file_handle); - U16_TO_BE16(0xff00, jo->record_in_use); + jo->fhandle = 0L; if (NULL != (f = fopen(unixname, "r"))) { int is_ok = 0; FILE *fout = popen(printcommand, "w"); @@ -1733,13 +1994,16 @@ int nw_close_file_queue(uint8 *queue_id, uint8 *job_id, } pclose(fout); } else - DPRINTF(("Cannot open pipe `%s`\n", "lpr")); + XDPRINTF((1,"Cannot open pipe `%s`\n", "lpr")); fclose(f); - if (is_ok) unlink(unixname); - } else DPRINTF(("Cannot open queue-file `%s`\n", unixname)); + if (is_ok) { + unlink(unixname); + result=0; + } + } else XDPRINTF((1,"Cannot open queue-file `%s`\n", unixname)); } else - DPRINTF(("nw_close_file_queue fhandle=%d\n", fhandle)); + XDPRINTF((2,"nw_close_file_queue fhandle=%d\n", fhandle)); free_queue_job(jo_id); } return(result); diff --git a/emutli.c b/emutli.c index 70045ad..57a8f2b 100644 --- a/emutli.c +++ b/emutli.c @@ -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); } diff --git a/emutli.h b/emutli.h index 6045b5e..5210372 100644 --- a/emutli.h +++ b/emutli.h @@ -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 diff --git a/examples/config.h b/examples/config.h index 6556fe3..c0f0abe 100644 --- a/examples/config.h +++ b/examples/config.h @@ -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 */ diff --git a/examples/nw.ini b/examples/nw.ini index 7428979..b755016 100644 --- a/examples/nw.ini +++ b/examples/nw.ini @@ -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 + + diff --git a/makefile.unx b/makefile.unx index 41f4a70..89ab33b 100644 --- a/makefile.unx +++ b/makefile.unx @@ -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 \ diff --git a/mars_nwe.lsm b/mars_nwe.lsm index 6544507..11cc960 100644 --- a/mars_nwe.lsm +++ b/mars_nwe.lsm @@ -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 diff --git a/namspace.c b/namspace.c new file mode 100644 index 0000000..84e55c8 --- /dev/null +++ b/namspace.c @@ -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); +} diff --git a/ncpserv.c b/ncpserv.c index 259df47..e5a1050 100644 --- a/ncpserv.c +++ b/ncpserv.c @@ -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); } diff --git a/net.h b/net.h index 84df862..81b2494 100644 --- a/net.h +++ b/net.h @@ -48,6 +48,8 @@ # include "emutli.h" /* TLI-EMULATION */ #endif +#include + #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); diff --git a/net1.c b/net1.c index f1d8947..156822c 100644 --- a/net1.c +++ b/net1.c @@ -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); diff --git a/nwconn.c b/nwconn.c index d538ca6..120df6c 100644 --- a/nwconn.c +++ b/nwconn.c @@ -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); } diff --git a/nwcrypt.c b/nwcrypt.c new file mode 100644 index 0000000..c2792f1 --- /dev/null +++ b/nwcrypt.c @@ -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 in +$* October 1995. +$* +$* Stolen to be useable for mars_nwe by +$* Martin Stover 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 about +the legal status of this piece of code: + + +--- +Date: Thu, 12 Oct 1995 13:44:18 +0100 +From: Volker Lendecke +To: jon@ddj.com +Subject: legal status of your source code? + + +Hello! + +I hope that you're the right one to write to, you are the first on your WWW +server. If you are not, could you please forward this message to the right +person? Thanks. + +I'm currently exploring the possibility to write a free (in the GNU GPL +sense) NCP filesystem, which would allow me to access a novell server +transparently. For that I would like to use the encryption functions you +published in DDJ 11/93, Undocumented Corner. I would make some cosmetic +changes, such as other indentations, minor code changes and so on. But I do +not know if that allows me to publish this code under GPL. One alternative +would be to publish a diff against your listing, but that would probably +contain much of your code as well, and it would be very inconvenient for +the average user. + +I think that you have some kind of standard procedure for such a +case. Please tell me what I should do. + +Many thanks in advance, + + Volker + + +=================================================================+ + ! Volker Lendecke Internet: lendecke@namu01.gwdg.de ! + ! D-37081 Goettingen, Germany ! + +=================================================================+ + +-- + + +I got the following answer: + +--- +From: Jon Erickson +X-Mailer: SCO System V Mail (version 3.2) +To: lendecke@namu01.gwdg.de +Subject: Re: legal status of your source code? +Date: Thu, 12 Oct 95 5:42:56 PDT + +Volker, +Code from Dr. Dobb's Journal related articles is provided for +anyone to use. Clearly, the author of the article should be +given credit. +Jon Erickson + +--- + +With this answer in mind, I took the code and made it a bit more +C-like. The original seemed to be translated by a mechanical pascal->c +translator. Jon's answer encouraged me to publish nwcrypt.c under the +GPL. If anybody who knows more about copyright and sees any problems +with this, please tell me. +****************************************************************************/ + +/******************* Data types ***************************/ +typedef unsigned char buf32[32]; +typedef unsigned char buf16[16]; +typedef unsigned char buf8[8]; +typedef unsigned char buf4[4]; +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]; +} + + diff --git a/nwdbm.c b/nwdbm.c index 5096f27..8b89bc4 100644 --- a/nwdbm.c +++ b/nwdbm.c @@ -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 #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) diff --git a/nwdbm.h b/nwdbm.h index 39cf183..d460609 100644 --- a/nwdbm.h +++ b/nwdbm.h @@ -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); diff --git a/nwroute.c b/nwroute.c new file mode 100644 index 0000000..bf7f507 --- /dev/null +++ b/nwroute.c @@ -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); +} + + diff --git a/nwserv.c b/nwserv.c index 1247ea2..7bcf908 100644 --- a/nwserv.c +++ b/nwserv.c @@ -1,4 +1,4 @@ -/* nwserv.c 22-Nov-95 */ +/* nwserv.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 @@ -17,24 +17,15 @@ */ #include "net.h" +#include "nwserv.h" -static int conn_gid=1; -static int conn_uid=1; +uint32 internal_net = 0x0L; /* NETWORKNUMMER INTERN (SERVER) */ +ipxAddr_t my_server_adr; /* Address of this server */ +char my_nwname[50]; /* Name of this server */ -static int ncpserv_debug=0; -static int nwconn_debug=0; - -#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 +/* <========== DEVICES ==========> */ +int anz_net_devices=0; +NW_NET_DEVICE *net_devices[MAX_NET_DEVICES]; uint16 ipx_sock_nummern[]={ 0, /* auto sock */ 0, /* auto sock */ @@ -42,10 +33,11 @@ uint16 ipx_sock_nummern[]={ 0, /* auto sock */ SOCK_RIP, SOCK_ROUTE, SOCK_DIAGNOSE -#if 0 - , - SOCK_ECHO, - SOCK_ERROR, +#ifdef ECHO_SLOT + , SOCK_ECHO +#endif +#ifdef ERROR_SLOT + , SOCK_ERROR #endif }; @@ -54,46 +46,42 @@ uint16 ipx_sock_nummern[]={ 0, /* auto sock */ static uint16 sock_nummern [NEEDED_SOCKETS]; -static int sockfd [NEEDED_SOCKETS]; - +int sockfd [NEEDED_SOCKETS]; static struct pollfd polls[NEEDED_POLLS]; -static ipxAddr_t my_server_adr; /* Address of this server */ static uint16 spx_diag_socket; /* SPX DIAGNOSE SOCKET */ static ipxAddr_t nw386_adr; /* Address of NW-TEST Server */ -static int nw386_found = 0; -static int client_mode = 0; - -static uint32 network = 0x0L; -static uint32 internal_net = 0x0L; -static char my_nwname[50]; - +static int nw386_found = 0; +static int client_mode = 0; static int ipxdebug = 0; static int pid_ncpserv = -1; static int fd_ncpserv_out = -1; /* ctrl-pipe out to ncpserv */ static int fd_ncpserv_in = -1; /* ctrl-pipe in from ncpserv */ -#ifndef LINUX -static int frame=0; -#else -static int frame=IPX_FRAME_8023; -static char devname[40]; -#endif -static time_t akttime_stamp; - -static int bytes_to_write_to_ncpserv=0; +static time_t akttime_stamp = 0; +static int broadsecs = 2048; +static time_t server_down_stamp = 0; +static int server_goes_down_secs = 10; +static int save_ipx_routes = 0; +static int bytes_to_write_to_ncpserv = 0; static void inform_ncpserv(void) { - if (bytes_to_write_to_ncpserv) { - kill(pid_ncpserv, SIGHUP); /* tell ncpserv to read input */ + if (bytes_to_write_to_ncpserv && pid_ncpserv > -1) { +#if 0 + XDPRINTF((2, "inform_ncpserv bytes=%d\n", bytes_to_write_to_ncpserv)); + kill(pid_ncpserv, SIGHUP); /* tell ncpserv to read input */ +#endif bytes_to_write_to_ncpserv=0; } } static void write_to_ncpserv(int what, int connection, - char *data, int data_size) + char *data, int data_size) { + XDPRINTF((2, "write_to_ncpserv what=0x%x, conn=%d, data_size=%d\n", + what, connection, data_size)); + switch (what) { case 0x5555 : /* kill connection */ bytes_to_write_to_ncpserv += @@ -111,6 +99,19 @@ static void write_to_ncpserv(int what, int connection, write(fd_ncpserv_out, data, data_size); break; + case 0xeeee : /* hup, read init */ + bytes_to_write_to_ncpserv += + write(fd_ncpserv_out, (char*) &what, sizeof(int)); + break; + + case 0xffff : /* 'down server' */ + bytes_to_write_to_ncpserv += + write(fd_ncpserv_out, (char*) &what, sizeof(int)); + bytes_to_write_to_ncpserv += + write(fd_ncpserv_out, (char*) &what, sizeof(int)); + inform_ncpserv(); + return; + default : break; } if (bytes_to_write_to_ncpserv > 255) inform_ncpserv(); @@ -155,7 +156,7 @@ static int open_ipx_socket(uint16 sock_nr, int nr, int open_mode) bind.addr.len = sizeof(ipxAddr_t); bind.addr.maxlen = sizeof(ipxAddr_t); bind.addr.buf = (char*)&my_server_adr; - bind.qlen = 0; /* immer */ + bind.qlen = 0; /* ever */ if (t_bind(ipx_fd, &bind, &bind) < 0){ char sxx[200]; sprintf(sxx,"NWSERV:t_bind !OK in open_ipx_socket, sock=%d", sock_nr); @@ -180,14 +181,6 @@ static int start_ncpserv(char *nwname, ipxAddr_t *addr) char *progname="ncpserv"; char addrstr[100]; char pathname[300]; - - char gidstr[10]; - char uidstr[10]; - - char debug1[5]; - char debug2[5]; - char debug3[5]; - int j = FD_NWSERV; close(fds_out[1]); /* no need to write */ dup2(fds_out[0], 0); /* becommes stdin */ @@ -197,20 +190,9 @@ static int start_ncpserv(char *nwname, ipxAddr_t *addr) dup2(fds_in[1], FD_NWSERV); /* becommes fd FD_NWSERV */ close(fds_in[1]); /* no longer needed */ while (j++ < 100) close(j); /* close all > 4 */ - ipx_addr_to_adr(addrstr, addr); - sprintf(gidstr, "%d", conn_gid); - sprintf(uidstr, "%d", conn_uid); - - sprintf(debug1, "%d", ncpserv_debug); - sprintf(debug2, "%d", nwconn_debug); - sprintf(debug3, "%d", ipxdebug); - execl(get_exec_path(pathname, progname), progname, - nwname, addrstr, - gidstr, uidstr, - debug1, debug2, debug3, NULL); - + nwname, addrstr, NULL); exit(1); } break; @@ -250,6 +232,17 @@ static int start_nwclient(void) } /* =========================== WDOG =============================== */ + +#ifdef _WDOG_TESTING_ +/* for testing */ +# define WDOG_TRIE_AFTER_SEC 1 +# define MAX_WDOG_TRIES 1 +#else +# define WDOG_TRIE_AFTER_SEC 300 /* ca. 5 min. */ +# define MAX_WDOG_TRIES 11 /* Standardtries */ +#endif + + static void send_wdog_packet(ipxAddr_t *addr, int conn, int what) { uint8 data[2]; @@ -277,7 +270,7 @@ typedef struct { } CONN; static CONN conns[MAX_CONNECTIONS]; -static int hi_conn=0; +static int hi_conn=0; /* highest connection nr in use */ static void insert_wdog_conn(int conn, ipxAddr_t *adr) { @@ -294,39 +287,41 @@ static void insert_wdog_conn(int conn, ipxAddr_t *adr) } } -static void reset_wdog_conn(int conn) +static void modify_wdog_conn(int conn, int mode) +/* mode = 0 : reset */ +/* mode = 1 : force test 1 */ +/* mode = 2 : force test 2 */ +/* mode = 99 : remove wdog */ { if (conn > 0 && --conn < hi_conn) { CONN *c=&(conns[conn]); - c->last_time = akttime_stamp; - c->counter = 0; - } -} + if (mode < 99) { + c->last_time = akttime_stamp; + switch (mode) { + case 1 : c->counter = MAX_WDOG_TRIES; /* quick test */ + broadsecs = 4096; + break; -static void remove_wdog_conn(int conn) -{ - if (conn > 0 && --conn < hi_conn) { - CONN *c=&(conns[conn]); - memset(c, 0, sizeof(CONN)); - if (conn + 1 == hi_conn) { - while (hi_conn) { - CONN *c=&(conns[hi_conn-1]); - if (!c->last_time) hi_conn--; - else break; + case 2 : c->counter = 1; /* slow test (activate)*/ + broadsecs = 4096; + break; + + default : c->counter = 0; /* reset */ + break; + } /* switch */ + } else if (mode == 99) { /* remove */ + memset(c, 0, sizeof(CONN)); + if (conn + 1 == hi_conn) { + while (hi_conn) { + c=&(conns[hi_conn-1]); + if (!c->last_time) hi_conn--; + else break; + } } } } } -#ifdef _WDOG_TESTING_ -/* for testing */ -# define WDOG_TRIE_AFTER_SEC 1 -# define MAX_WDOG_TRIES 1 -#else -# define WDOG_TRIE_AFTER_SEC 300 /* ca. 5 min. */ -# define MAX_WDOG_TRIES 11 /* Standardtries */ -#endif - static void send_wdogs(void) { int k = hi_conn; @@ -363,43 +358,6 @@ static void send_bcasts(int conn) } } -/* =========================== SERVER BROADCAST ======================== */ -static int send_broadcast(int fd, int firsttime, int down) -/* periodic Broadcast Message */ -{ - IPX_DATA ipx_data; - int ipx_pack_typ = 17; - ipxAddr_t wild; - - memset(&wild, 0, sizeof(ipxAddr_t)); - U32_TO_BE32(network, 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); - /* NCP SOCKET verwenden */ - - if (firsttime && start_ncpserv(ipx_data.sip.server_name, - &ipx_data.sip.server_adr)) return(-1); - - U16_TO_BE16(2, ipx_data.sip.response_type); /* General */ - U16_TO_BE16(4, ipx_data.sip.server_type); /* Fileserver */ - - if (down) { - U16_TO_BE16(16, ipx_data.sip.intermediate_networks); - } else { - U16_TO_BE16(1, ipx_data.sip.intermediate_networks); - /* I think 1 is ok here */ - } - send_ipx_data(fd, ipx_pack_typ, - sizeof(ipx_data.sip), - (char *)&(ipx_data.sip), - &wild, "SIP Broadcast"); - - return(0); -} static void send_server_respons(int fd, uint8 ipx_pack_typ, int respond_typ, int server_typ, @@ -426,11 +384,6 @@ void get_server_data(char *name, ipxAddr_t *adr, ipxAddr_t *from_addr) { -#ifdef LINUX - if (memcmp(adr->net, my_server_adr.net, IPX_NET_SIZE)) - /* don't add our own netroute twice */ - myipx_route_add(adr->net, from_addr->net, from_addr->node); -#endif if (!nw386_found) { memcpy(&nw386_adr, adr, sizeof(ipxAddr_t)); nw386_found++; @@ -439,105 +392,60 @@ void get_server_data(char *name, client_mode = 0; /* only start once */ } } - DPRINTF(("NW386 %s found at:%s\n", name, visable_ipx_adr(adr))); + XDPRINTF((2,"NW386 %s found at:%s\n", name, visable_ipx_adr(adr))); ins_del_bind_net_addr(name, adr); } -void handle_sap(int fd, +static void handle_sap(int fd, int ipx_pack_typ, int data_len, - IPX_DATA *ipxdata, - ipxAddr_t *from_addr) + IPX_DATA *ipxdata, + ipxAddr_t *from_addr) { - int query_type = GET_BE16(ipxdata->sqp.query_type); - int server_type = GET_BE16(ipxdata->sqp.server_type); + int query_type = GET_BE16(ipxdata->sqp.query_type); + int server_type = GET_BE16(ipxdata->sqp.server_type); if (query_type == 3) { - DPRINTF(("SAP NEAREST SERVER request typ=%d von %s\n", server_type, visable_ipx_adr(from_addr))); + XDPRINTF((2,"SAP NEAREST SERVER request typ=%d von %s\n", + server_type, visable_ipx_adr(from_addr))); if (server_type == 4) { /* Get Nearest File Server */ - send_server_respons(fd, ipx_pack_typ, - 4, server_type, from_addr); + send_server_respons(fd, ipx_pack_typ, 4, server_type, from_addr); } } else if (query_type == 1) { /* general Request */ - DPRINTF(("SAP GENERAL request server_type =%d\n", server_type)); + XDPRINTF((2,"SAP GENERAL request server_type =%d\n", server_type)); if (server_type == 4) { /* Get General File Server Request */ - send_server_respons(fd, ipx_pack_typ, - 4, server_type, from_addr); + send_server_respons(fd, ipx_pack_typ, 4, server_type, from_addr); } - } else if (query_type == 2) { /* periodic general or shutdown response */ - DPRINTF(("SAP PERIODIC response von %s\n", visable_ipx_adr(from_addr))); - if (server_type == 4) { /* from Fileserver */ - DPRINTF(("FROM SERVER intermediate=%d\n", - GET_BE16(ipxdata->sip.intermediate_networks))); - if (16 == GET_BE16(ipxdata->sip.intermediate_networks)) { - /* shutdown */ - if (memcmp(ipxdata->sip.server_adr.net, - my_server_adr.net, IPX_NET_SIZE)) { - /* don't kill our own netroute */ - DPRINTF(("SERVER %s IS GOING DOWN\n", ipxdata->sip.server_name)); - ins_del_bind_net_addr(ipxdata->sip.server_name, NULL); -#ifdef LINUX - myipx_route_del(ipxdata->sip.server_adr.net); -#endif + } else if (query_type == 2 || query_type == 4) { + /* periodic general or shutdown response (2) + * or nearests Service Response (4) + */ + int entries = (data_len-2) / sizeof(SAPS); + uint8 *p = ((uint8*)ipxdata)+2; + XDPRINTF((2,"SAP PERIODIC (entries=%d) from %s\n", entries, visable_ipx_adr(from_addr))); + while (entries--) { + int type = GET_BE16(p); + uint8 *name = p+2; + ipxAddr_t *ad = (ipxAddr_t*) (p+50); + int hops = GET_BE16(p+ sizeof(SAPS) -2); + XDPRINTF((2,"TYP=%2d,hops=%2d, Addr=%s, Name=%s\n", type, hops, + visable_ipx_adr(ad), name)); + + if (type == 4 && strcmp(name, my_nwname)) { /* from Fileserver */ + if (16 == hops) { + /* shutdown */ + XDPRINTF((2,"SERVER %s IS GOING DOWN\n", name)); + ins_del_bind_net_addr(name, NULL); } else { - DPRINTF(("SHUTDOWN RESPONSE from SERVER %s\n", ipxdata->sip.server_name)); + get_server_data(name, ad, from_addr); } - } else { - get_server_data(ipxdata->sip.server_name, &(ipxdata->sip.server_adr), - from_addr); } - } - } else if (query_type == 4) { /* nearests Service Response */ - DPRINTF(("SAP nearest Service response\n")); - if (server_type == 4){ - get_server_data(ipxdata->sip.server_name, &(ipxdata->sip.server_adr), - from_addr); - } - } else DPRINTF(("UNKNOWN SAP query %x, server %x\n", query_type, server_type)); -} - -static void send_rip(ipxAddr_t *from_addr) -{ - RIP rip; - ipxAddr_t to_addr; - memset(&rip, 0, sizeof(RIP)); - if (from_addr) memcpy(&to_addr, from_addr, sizeof(ipxAddr_t)); - else { - memset(&to_addr, 0, sizeof(ipxAddr_t)); - U32_TO_BE32(network, to_addr.net); - memset(to_addr.node, 0xFF, IPX_NODE_SIZE); - U16_TO_BE16(SOCK_RIP, to_addr.sock); + p+=sizeof(SAPS); + } /* while */ + } else { + XDPRINTF((1,"UNKNOWN SAP query %x, server %x\n", query_type, server_type)); } - memcpy(rip.network, my_server_adr.net, IPX_NET_SIZE); - U16_TO_BE16(2, rip.operation); /* rip response or general */ - U16_TO_BE16(1, rip.ticks); /* on ethernets allways 1 Tick */ - U16_TO_BE16(0, rip.hops); - send_ipx_data(sockfd[RIP_SLOT], - 1, - sizeof(RIP), - (char *)&rip, - &to_addr, "SEND RIP"); -} - -static 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 hops = GET_BE16(ipxdata->rip.hops); - int ticks = GET_BE16(ipxdata->rip.ticks); - DPRINTF(("Rip %s hops %d, ticks %d, network:%02x.%02x.%02x.%02x\n", - (operation == 1) ? "Request" : "Response", - hops, ticks, - (int)ipxdata->rip.network[0], - (int)ipxdata->rip.network[1], - (int)ipxdata->rip.network[2], - (int)ipxdata->rip.network[3])); - if (operation == 1) { /* rip request */ - send_rip(from_addr); - } else if (operation != 2) /* NICHT RIP response */ - DPRINTF(("UNKNOWN RIP operation %d\n", operation)); } /* @@ -586,7 +494,7 @@ static void response_ipx_diag(int fd, int ipx_pack_typ, datalen++; *p++ = 1; /* Bridge Driver */ datalen++; - /* Jetzt extended */ + /* now extended */ *p++ = 6; /* Fileserver/Bridge (internal) */ datalen++; *p++ = 1; /* Anz. Networks */ @@ -620,7 +528,7 @@ static void handle_diag(int fd, int ipx_pack_typ, } exnodes += IPX_NODE_SIZE; } - DPRINTF(("DIAG Request, ipx_pack_typ %d, data_len %d, count %d\n", + XDPRINTF((2,"DIAG Request, ipx_pack_typ %d, data_len %d, count %d\n", (int)ipx_pack_typ, data_len, count)); response_ipx_diag(fd, ipx_pack_typ, from_addr); } @@ -658,22 +566,28 @@ static void handle_event(int fd, uint16 socknr, int slot) ud.addr.buf = (char*)&source_adr; t_rcvuderr(fd, &uderr); DPRINTF(("Error from %s, Code = 0x%lx\n", visable_ipx_adr(&erradr), uderr.error)); - t_error("t_rcvudata !OK"); + if (nw_debug) t_error("t_rcvudata !OK"); return; } - DPRINTF(("Ptyp:%d von: %s\n", (int)ipx_pack_typ, visable_ipx_adr(&source_adr) )); + XDPRINTF((3,"Ptyp:%d from: %s\n", (int)ipx_pack_typ, visable_ipx_adr(&source_adr) )); + + if (server_down_stamp) return; /* no more interests */ + + if ( IPXCMPNODE(source_adr.node, my_server_adr.node) && + IPXCMPNET (source_adr.net, my_server_adr.net)) { - if IPXCMPNODE(source_adr.node, my_server_adr.node) { int source_sock = (int) GET_BE16(source_adr.sock); - if ( source_sock == sock_nummern[MY_BROADCAST_SLOT] - || source_sock == sock_nummern[WDOG_SLOT] - || source_sock == SOCK_RIP) { - DPRINTF(("OWN Packet, ignored\n")); + if ( source_sock == sock_nummern[MY_BROADCAST_SLOT] + || source_sock == sock_nummern[WDOG_SLOT] + || source_sock == SOCK_SAP + || source_sock == SOCK_RIP) { + XDPRINTF((2,"OWN Packet from sock:0x%04x, ignored\n", source_sock)); return; } + /* it also can be Packets from DOSEMU OR ncpfs on this machine */ - DPRINTF(("Packet from OWN maschine:sock=0x%x\n", source_sock)); + XDPRINTF((2,"Packet from OWN maschine:sock=0x%x\n", source_sock)); } switch (socknr) { @@ -683,12 +597,12 @@ static void handle_event(int fd, uint16 socknr, int slot) default : if (WDOG_SLOT == slot) { /* this is a watchdog packet */ - DPRINTF(("WDOG Packet len=%d connid=%d, status=%d\n", + XDPRINTF((2,"WDOG Packet len=%d connid=%d, status=%d\n", (int)ud.udata.len, (int) ipx_data_buff.wdog.connid, (int)ipx_data_buff.wdog.status)); if (2 == ud.udata.len) { if ('Y' == ipx_data_buff.wdog.status) - reset_wdog_conn(ipx_data_buff.wdog.connid); + modify_wdog_conn(ipx_data_buff.wdog.connid, 0); } } else { uint8 *p = (uint8*)&ipx_data_buff; @@ -706,98 +620,92 @@ static void handle_event(int fd, uint16 socknr, int slot) } } -static void get_server(void) +static void get_ini(int full) { - if (!nw386_found) { /* no other server was found yet. */ - SQP sqp; - ipxAddr_t wild; - memset(&wild, 0, sizeof(ipxAddr_t)); - memset(wild.node, 0xFF, IPX_NODE_SIZE); - U32_TO_BE32(network, 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"); + FILE *f = open_nw_ini(); + int k; + uint32 node = 1; /* default 1 */ + if (full) { + gethostname(my_nwname, 48); + upstr(my_nwname); } -} - -static void get_ini(void) -{ - FILE *f=open_nw_ini(); - char *frname=NULL; -#ifdef LINUX - strcpy(devname, "eth0"); /* default */ -#endif - gethostname(my_nwname, 48); - upstr(my_nwname); if (f){ char buff[500]; int what; - while (0 != (what =get_ini_entry(f, 0, (char*)buff, sizeof(buff)))) { + while (0 != (what=get_ini_entry(f, 0, (char*)buff, sizeof(buff)))) { char inhalt[500]; char inhalt2[500]; char inhalt3[500]; + char inhalt4[500]; char dummy; int anz; - if ((anz=sscanf((char*)buff, "%s %s %s", inhalt, inhalt2, inhalt3)) > 0) { + if ((anz=sscanf((char*)buff, "%s %s %s", inhalt, inhalt2, + inhalt3, inhalt4)) > 0) { switch (what) { - case 2 : strncpy(my_nwname, inhalt, 48); - my_nwname[47] = '\0'; - upstr(my_nwname); + case 2 : if (full) { + strncpy(my_nwname, inhalt, 48); + my_nwname[47] = '\0'; + upstr(my_nwname); + } break; -#ifdef LINUX case 3 : - if (sscanf(inhalt, "%ld%c", &internal_net, &dummy) != 1) - sscanf(inhalt, "%lx", &internal_net); + if (full) { + if (sscanf(inhalt, "%ld%c", &internal_net, &dummy) != 1) + sscanf(inhalt, "%lx", &internal_net); + if (anz > 1) { + if (sscanf(inhalt2, "%ld%c", &node, &dummy) != 1) + sscanf(inhalt2, "%lx", &node); + } + } break; -#endif case 4 : - if (sscanf(inhalt, "%ld%c", &network, &dummy) != 1) - sscanf(inhalt, "%lx", &network); + if (full) { + if (anz_net_devices < MAX_NET_DEVICES && + (!anz_net_devices || anz > 2) ) { + NW_NET_DEVICE **pnd=&(net_devices[anz_net_devices++]); + NW_NET_DEVICE *nd=*pnd= + (NW_NET_DEVICE*)xmalloc(sizeof(NW_NET_DEVICE)); + memset(nd, 0, sizeof(NW_NET_DEVICE)); + nd->ticks = 1; + nd->frame = IPX_FRAME_8023; + new_str(nd->devname, "eth0"); + + if (sscanf(inhalt, "%ld%c", &nd->net, &dummy) != 1) + sscanf(inhalt, "%lx", &nd->net); + if (anz > 1) + new_str(nd->devname, inhalt2); + + if (anz > 2) { + upstr(inhalt3); + if (!strcmp(inhalt3, "802.3")) + nd->frame=IPX_FRAME_8023; + else if (!strcmp(inhalt3, "802.2")) + nd->frame=IPX_FRAME_8022; + else if (!strcmp(inhalt3, "SNAP")) + nd->frame=IPX_FRAME_SNAP; + else if (!strcmp(inhalt3, "ETHERNET_II")) + nd->frame=IPX_FRAME_ETHERII; + } + if (anz > 3) nd->ticks = atoi(inhalt4); + } + } + break; #ifdef LINUX - if (anz > 1) { - strncpy(devname, inhalt2, sizeof(devname)); - devname[sizeof(devname)-1] = '\0'; - } - if (anz > 2) { - upstr(inhalt3); - if (!strcmp(inhalt3, "802.3")) frame=IPX_FRAME_8023; - else if (!strcmp(inhalt3, "802.2")) - frame=IPX_FRAME_8022; - else if (!strcmp(inhalt3, "SNAP")) - frame=IPX_FRAME_SNAP; - else if (!strcmp(inhalt3, "ETHERNET_II")) - frame=IPX_FRAME_ETHERII; - } + case 5 : save_ipx_routes=atoi(inhalt); + break; #endif - break; + case 104 : /* nwclient */ + if (client_mode && atoi(inhalt)) + client_mode++; + break; - case 10 : - sscanf(inhalt, "%d", &conn_gid); - break; - - case 11 : - sscanf(inhalt, "%d", &conn_uid); - break; - - case 100 : - sscanf(inhalt, "%d", &ipxdebug); - break; - - case 101 : - sscanf(inhalt, "%d", &nw_debug); - break; - - case 102 : - sscanf(inhalt, "%d", &ncpserv_debug); - break; - - case 103 : - sscanf(inhalt, "%d", &nwconn_debug); - break; + case 210 : server_goes_down_secs=atoi(inhalt); + if (server_goes_down_secs < 1 || + server_goes_down_secs > 600) + server_goes_down_secs = 10; + break; default : break; } /* switch */ @@ -805,78 +713,123 @@ static void get_ini(void) } /* while */ fclose(f); } - + if (client_mode < 2) client_mode=0; + if (full) { #ifdef LINUX - switch (frame) { - case IPX_FRAME_8022 : frname = "802.2"; break; - case IPX_FRAME_8023 : frname = "802.3"; break; - case IPX_FRAME_SNAP : frname = "SNAP"; break; - case IPX_FRAME_ETHERII : frname = "ETHERNET_II";break; - default : break; - } /* switch */ -#else - frname = "ETHERNET_II"; -#endif - fprintf(stdout, - "Servername='%s', NETWORK='0x%lx', NODE='0x%lx'\n", - my_nwname, network, internal_net); - -#ifdef LINUX - fprintf(stdout, "Device=%s, Frame=%s\n", devname, frname); - init_ipx(devname, &network, internal_net, frame, frname, ipxdebug); - fprintf(stdout, "NETWORK is=0x%lx\n", network); + init_ipx(internal_net, node, ipxdebug); + for (k=0; k < anz_net_devices; k++){ + NW_NET_DEVICE *nd=net_devices[k]; + char *frname=NULL; + switch (nd->frame) { + case IPX_FRAME_8022 : frname = "802.2"; break; + case IPX_FRAME_8023 : frname = "802.3"; break; + case IPX_FRAME_SNAP : frname = "SNAP"; break; + case IPX_FRAME_ETHERII : frname = "ETHERNET_II";break; + default : break; + } /* switch */ + DPRINTF(("DEVICE=%s, FRAME=%s, NETWORK=0x%lx\n", + nd->devname, frname, nd->net)); + init_dev(nd->devname, nd->frame, nd->net); + } #endif + if (!get_ipx_addr(&my_server_adr)) { + internal_net = GET_BE32(my_server_adr.net); + } else exit(1); + DPRINTF(("Servername='%s', INTERNAL NET=0x%lx, NODE=0x%02x:%02x:%02x:%02x:%02x:%02x\n", + my_nwname, internal_net, + (int)my_server_adr.node[0], + (int)my_server_adr.node[1], + (int)my_server_adr.node[2], + (int)my_server_adr.node[3], + (int)my_server_adr.node[4], + (int)my_server_adr.node[5])); + } /* if full */ } static void send_down_broadcast(void) { - int j = 20; - while (j--) send_broadcast(sockfd[MY_BROADCAST_SLOT], 0, 1); + send_sap_broadcast(2); + send_rip_broadcast(2); /* shutdown rip */ } static void close_all(void) { int j = NEEDED_SOCKETS; - if (pid_ncpserv > 0) { - if (fd_ncpserv_out > -1) close(fd_ncpserv_out); - if (fd_ncpserv_in > -1) close(fd_ncpserv_in); - kill(pid_ncpserv, SIGTERM); /* terminate ncpserv */ - kill(pid_ncpserv, SIGKILL); /* kill ncpserv */ - } + while (j--) { t_unbind(sockfd[j]); t_close(sockfd[j]); } + + if (pid_ncpserv > 0) { + int status; + if (fd_ncpserv_out > -1) { + close(fd_ncpserv_out); + fd_ncpserv_out =-1; + } + if (fd_ncpserv_in > -1) { + close(fd_ncpserv_in); + fd_ncpserv_in = -1; + } + kill(pid_ncpserv, SIGTERM); /* terminate ncpserv */ + waitpid(pid_ncpserv, &status, 0); + kill(pid_ncpserv, SIGKILL); /* kill ncpserv */ + } + #ifdef LINUX - fprintf(stdout, "Close Device=%s\n", devname); - exit_ipx(devname, network, frame); + if (!save_ipx_routes) { + for (j=0; jdevname, nd->frame)); + exit_dev(nd->devname, nd->frame); + } + } + exit_ipx(!save_ipx_routes); #endif + } +static void down_server(void) +{ + if (!server_down_stamp) { + write_to_ncpserv(0xffff, 0, NULL, 0); + signal(SIGHUP, SIG_IGN); + signal(SIGPIPE, SIG_IGN); + fprintf(stderr, "\007"); + fprintf(stderr, "\n*********************************************\n"); + fprintf(stderr, "\nWARNING: NWE-SERVER shuts down in %3d sec !!!\n", + server_goes_down_secs); + fprintf(stderr, "\n*********************************************\n"); + sleep(1); + fprintf(stderr, "\007\n"); + broadsecs=100; + server_down_stamp = akttime_stamp; + send_down_broadcast(); + } +} + +static int fl_get_int=0; static void sig_quit(int rsig) { - signal(SIGINT, SIG_IGN); - signal(SIGQUIT, SIG_IGN); - signal(SIGTERM, SIG_IGN); - signal(SIGHUP, SIG_IGN); - signal(SIGPIPE, SIG_IGN); - send_down_broadcast(); - close_all(); - exit(1); + signal(rsig, SIG_IGN); + signal(SIGHUP, SIG_IGN); /* don't want it anymore */ + fl_get_int=2; } -static int fl_get_debug=0; -static void get_new_debug(void) +static void handle_hup_reqest(void) { - get_ini_debug(1); - fl_get_debug=0; + get_ini_debug(NWSERV); + XDPRINTF((2, "NWSERV:Got HUP, reading ini.\n")); + get_ini(0); + write_to_ncpserv(0xeeee, 0, NULL, 0); /* inform ncpserv */ + fl_get_int=0; } static void sig_hup(int rsig) { - signal(SIGHUP, SIG_IGN); - fl_get_debug++; - signal(SIGHUP, sig_hup); + fl_get_int=1; + signal(SIGHUP, sig_hup); } static void set_sigs(void) @@ -892,10 +845,11 @@ int main(int argc, char **argv) { int j = -1; tzset(); - if (argc > 1) client_mode++; + if (argc > 1) client_mode=1; /* in client mode the testprog 'nwclient' will be startet. */ - get_ini(); + init_tools(NWSERV); + get_ini(1); while (++j < NEEDED_POLLS) { polls[j].events = POLLIN|POLLPRI; @@ -917,72 +871,79 @@ int main(int argc, char **argv) } } - if (!send_broadcast(sockfd[MY_BROADCAST_SLOT], 1, 0)) { + U16_TO_BE16(SOCK_NCP, my_server_adr.sock); + if (!start_ncpserv(my_nwname, &my_server_adr)) { /* Jetzt POLLEN */ - time_t broadtime; time(&broadtime); set_sigs(); - polls[NEEDED_SOCKETS].fd = fd_ncpserv_in; - while (1) { - int anz_poll = poll(polls, NEEDED_POLLS, - (!client_mode) ? 30000 : 15000); - - if (fl_get_debug) get_new_debug(); - + int anz_poll = poll(polls, NEEDED_POLLS, broadsecs); time(&akttime_stamp); + if (fl_get_int) { + if (fl_get_int == 1) handle_hup_reqest(); + else if (fl_get_int == 2) down_server(); + } if (anz_poll > 0) { /* i have to work */ struct pollfd *p = &polls[0]; j = -1; while (++j < NEEDED_POLLS) { if (p->revents){ if (j < NEEDED_SOCKETS) { /* socket */ - /* - DPRINTF(("POLL %d, SOCKET %x, ", p->revents, sock_nummern[j])); - */ - if (p->revents & ~POLLIN) perror("STREAM error"); + XDPRINTF((99,"POLL %d, SOCKET %x, ", p->revents, sock_nummern[j])); + if (p->revents & ~POLLIN) + errorp(0, "STREAM error", "revents=0x%x", p->revents ); else handle_event(p->fd, sock_nummern[j], j); } else { /* fd_ncpserv_in */ - DPRINTF(("POLL %d, fh=%d\n", p->revents, p->fd)); - if (p->revents & ~POLLIN) perror("STREAM error"); + 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 { if (p->fd == fd_ncpserv_in) { int what; int conn; + int size; ipxAddr_t adr; - if (sizeof(int) == read(fd_ncpserv_in, (char*)&what, sizeof(int))) { - DPRINTF(("GOT ncpserv_in what=0x%x\n", what)); + XDPRINTF((2,"GOT ncpserv_in what=0x%x\n", what)); switch (what) { case 0x2222 : /* insert wdog connection */ if (sizeof(int) == read(fd_ncpserv_in, (char*)&conn, sizeof(int)) + && sizeof(int) == read(fd_ncpserv_in, + (char*)&size, sizeof(int)) && sizeof(ipxAddr_t) == read(fd_ncpserv_in, - (char*)&adr, sizeof(ipxAddr_t))) + (char*)&adr, size)) insert_wdog_conn(conn, &adr); break; - case 0x4444 : /* reset wdog connection */ + case 0x4444 : /* reset wdog connection = 0 */ + /* force test wdog conn 1 = 1 */ + /* force test wdog conn 2 = 2 */ + /* remove wdog = 99 */ if (sizeof(int) == read(fd_ncpserv_in, - (char*)&conn, sizeof(int))) - reset_wdog_conn(conn); + (char*)&conn, sizeof(int)) + && sizeof(int) == read(fd_ncpserv_in, + (char*)&what, sizeof(what))) + modify_wdog_conn(conn, what); break; - case 0x6666 : /* remove wdog connection */ - if (sizeof(int) == read(fd_ncpserv_in, - (char*)&conn, sizeof(int))) - remove_wdog_conn(conn); - break; - - case 0x8888 : /* bcast message */ + case 0x6666 : /* bcast message */ if (sizeof(int) == read(fd_ncpserv_in, (char*)&conn, sizeof(int))) send_bcasts(conn); break; + case 0xffff : /* down file server */ + if (sizeof(int) == read(fd_ncpserv_in, + (char*)&conn, sizeof(int)) && + conn == what) { + down_server(); + } + break; + default : break; } } @@ -994,21 +955,31 @@ int main(int argc, char **argv) p++; } /* while */ } else { - /* if (anz_poll < 0) perror("POLL error"); */ - if (nw_debug > 2) DPRINTF(("POLLING ...\n")); + XDPRINTF((99,"POLLING ...\n")); + } + if (server_down_stamp) { + if (akttime_stamp - server_down_stamp > server_goes_down_secs) break; + } else { + if (akttime_stamp - broadtime > (broadsecs / 1000)) { /* ca. 60 seconds */ + send_sap_broadcast(broadsecs<3000); /* firsttime broadcast */ + send_rip_broadcast(broadsecs<3000); /* firsttime broadcast */ + if (broadsecs < 32000) { + rip_for_net(MAX_U32); + get_servers(); + broadsecs *= 2; + } + inform_ncpserv(); + send_wdogs(); + broadtime = akttime_stamp; + } else if (client_mode) get_servers(); /* Here more often */ } - if (akttime_stamp - broadtime > 59) { /* ca. 60 seconds */ - send_wdogs(); - send_broadcast(sockfd[MY_BROADCAST_SLOT], 0, 0); - send_rip(NULL); - get_server(); - inform_ncpserv(); - broadtime = akttime_stamp; - } else if (client_mode) get_server(); /* Here more often */ } /* while */ send_down_broadcast(); + sleep(1); + send_down_broadcast(); } close_all(); + fprintf(stderr, "\nNWE-SERVER is down now !!\n"); return(0); } diff --git a/nwserv.h b/nwserv.h new file mode 100644 index 0000000..9a7adae --- /dev/null +++ b/nwserv.h @@ -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); + diff --git a/tools.c b/tools.c index cf10aa6..33f3204 100644 --- a/tools.c +++ b/tools.c @@ -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 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); diff --git a/tools.h b/tools.h index 46853c1..522e1a6 100644 --- a/tools.h +++ b/tools.h @@ -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);