diff --git a/README b/README index 5f825a7..bd92245 100644 --- a/README +++ b/README @@ -1,71 +1,25 @@ -(C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany +This is Mars_nwe, a free NetWare(tm) emulator for Linux and UnixWare, +written by Martin Stover, Marburg, Germany. -to compile and install, please read INSTALL ! +There is not yet too much documentation available, look into the doc/ +subdirectory. As Martin's native tongue is german, the documentation, +as well as a lot of the code comments are a mixture of english and +german. This will certainly converge to english in the future. -This is a little try to emulate some functions from -a NOVELL-SERVER under UNIX (LINUX). -The first version I have written 1993 on a USL1.1 -with TLI-Code. -1994 I have ported it to LINUX. This was easy, because -I only have to write a small TLI->SOCKET emu. - -Unfortunately I had no full description of the NCP-calls, -so many of the calls based on trying. :-( - -WARNING: this code has still many BUG's !! - -BINDERY: this are the *.pag and *.dir files. - These files are generated by the first starting - of mars_nwe and are filled with the minimal - needed Objects and Properties. - 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 - the network device in nw.ini should match - the NETWORK Number of the Novell-Server. - -LINUX -KERNEL: the only linux-kernel depending files - are emutli.[hc]. - -short description of the processes. -1) nwserv : the main program.Initiates all and starts 'ncpserv'. - sends broadcasts, wdogs, sap and rip packets. - If nwserv is started with a parameter, then the simple - test client 'nwclient', only for debugging, is started. - -2) ncpserv: opens NCP-Socket and handles NCP-Requests. - When there comes NCP-Request 0x1111 (Get Connection Nr) - then there will be started a new process 'nwconn'. - Every client-ncp-request reaches nwconn over - ncpserv. - -3) nwconn: will be started for every connection. Is connected - to ncpserv with a pipe. - -Problems and TODO: -Many:-( - -Here is a short list. -o - password changings from clients -o - make routing better. -o - making printing better. -o - clean the code !!! -o - make bindery code more complete. -o - and much more ... - -Have luck with trying. :) +INSTALLATION +look in doc/INSTALL or doc/INSTALL.ger - Martin -(mstover@freeway.de) +HELP -BTW: The kick to make mars_nwe public was the -publication of linware ( lwared ), the Novell-Server-Emulator -from Ales Dryak (A.Dryak@sh.cvut.cz). -I hope both products can make profit from each other. ------> SuperNOS ala Linux ;-) -Novell don't want to make it anymore. :-( +To get help you can mail to and/or subscribe to LinWare mailing list: +Topics for the list: +- discussing LinWare server, its features, installation problems and bugs +- using IPX protocol under Linux +- IPX routing and router daemons under Linux +- mars_nwe + +You can subscribe to the list by sending command "add linware" in mail +message body to address: "listserv@sh.cvut.cz". +Your list postings should be sent to address: "linware@sh.cvut.cz". diff --git a/connect.c b/connect.c index 0eba2f5..a666f76 100644 --- a/connect.c +++ b/connect.c @@ -1,4 +1,4 @@ -/* connect.c 23-Jan-96 */ +/* connect.c 10-Mar-96 */ /* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany * * This program is free software; you can redistribute it and/or modify @@ -30,6 +30,9 @@ extern int errno; static int test_handle=-1; #endif +#define DONT_KNOW_IF_OK 1 + + static int default_uid=-1; static int default_gid=-1; @@ -158,8 +161,8 @@ 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); + errorp(1, "set_default_guid, !! Abort !!", + "Cannot set default gid=%d and uid=%d" , default_gid, default_uid); exit(1); } } @@ -680,6 +683,7 @@ static int build_verz_name(NW_PATH *nwpath, /* gets complete path */ return(completition); } +static int lastdirhandle=0; int conn_get_kpl_path(NW_PATH *nwpath, int dirhandle, uint8 *data, int len, int only_dir) /* @@ -687,7 +691,15 @@ int conn_get_kpl_path(NW_PATH *nwpath, int dirhandle, * else a negativ errcode will be returned */ { - int completition = build_path(nwpath, data, len, only_dir); + int completition; +#if DONT_KNOW_IF_OK + if (!dirhandle && len > 1 && *data== ':' && *(data+1) == '/') { + --len; + data++; + dirhandle = lastdirhandle; + } else if (dirhandle) lastdirhandle = dirhandle; +#endif + completition = build_path(nwpath, data, len, only_dir); if (!completition) completition = build_verz_name(nwpath, dirhandle); return(completition); } @@ -810,6 +822,13 @@ int nw_chmod_datei(int dir_handle, uint8 *data, int len, int modus) struct stat stbuff; int completition=-0x9c; NW_PATH nwpath; +#if DONT_KNOW_IF_OK + if (!dir_handle && len > 1 && *data== ':' && *(data+1) == '/') { + --len; + data++; + dir_handle = lastdirhandle; + } else if (dir_handle) lastdirhandle = dir_handle; +#endif build_path(&nwpath, data, len, 0); if (nwpath.fn[0] != '.') { /* Files with . at the beginning are not ok */ completition = build_verz_name(&nwpath, dir_handle); @@ -924,6 +943,13 @@ static int change_dir_entry( NW_DIR *dir, int volume, } } +void nw_exit_connect(void) +{ + if (connect_is_init) { + init_file_module(); + } +} + int nw_init_connect(void) /* Cann be called when ever you want */ { @@ -971,12 +997,12 @@ int nw_init_connect(void) fclose(f); if (used_nw_volumes < 1) { - errorp(0, "No Volumes defined. Look at ini file entry 1, Abort !!", NULL); + errorp(1, "No Volumes defined. Look at ini file entry 1, Abort !!", NULL); return(-1); } if (stat(build_unix_name(&nwlogin, 0), &stbuff)) { - errorp(0, "Stat error LOGIN Directory, Abort !!", + errorp(1, "Stat error LOGIN Directory, Abort !!", "UnixPath=`%s`", build_unix_name(&nwlogin, 0)); return(-1); } @@ -1052,7 +1078,7 @@ int nw_search(uint8 *info, { NW_PATH nwpath; - int completition = conn_get_kpl_path(&nwpath, dirhandle, data, len, 0); + int completition= conn_get_kpl_path(&nwpath, dirhandle, data, len, 0); XDPRINTF((5,0,"nw_search path:%s:, fn:%s:, completition:0x%x", nwpath.path, nwpath.fn, completition)); if (completition > -1) { diff --git a/connect.h b/connect.h index 4230957..0d69a77 100644 --- a/connect.h +++ b/connect.h @@ -1,4 +1,4 @@ -/* connect.h 28-Jan-96 */ +/* connect.h 10-Mar-96 */ #ifndef _CONNECT_H_ #define _CONNECT_H_ typedef struct { @@ -53,6 +53,8 @@ typedef struct { extern int nw_init_connect(void); +extern void nw_exit_connect(void); + extern int nw_free_handles(int task); extern int nw_creat_open_file(int dir_handle, uint8 *data, int len, diff --git a/CHANGES b/doc/CHANGES similarity index 87% rename from CHANGES rename to doc/CHANGES index 70b98e8..1a2aa44 100644 --- a/CHANGES +++ b/doc/CHANGES @@ -83,7 +83,15 @@ Erste 'oeffentliche' Version - Passwort Strategy erweitert. Nun ist es auch moeglich ueber entry '7' in der ini Datei System-Passwoerter zu verwenden. Es werden dann unencryted Passwoerter verwendet. - - - - +- Neuer Eintrag '15' in ini Datei eingebaut zwecks automatischen + Einlesen von User in die Bindery. +- Moeglichkeit zum Testen/Anlegen der Standarddirs beim Starten + eingebaut. +- Bindery Code veraendert, Dateien bleiben nun geoeffnet. +- Kommunikation ncpserv <-> nwconn von Pipe auf Socket abgeaendert. +- Moeglichkeit zu Leistungssteigerung mittels modifizierten ipx-kernel + eingebaut. +- entry '6' erweitert. Nun ist 3.12 Angabe moeglich. +- Moeglichkeit der stationsabhaengigen Steuerung von + Nearest Server Response eingebaut. +^^^^^^^^^^ VERSION 0.97 ^^^^^^^^ diff --git a/INSTALL b/doc/INSTALL similarity index 100% rename from INSTALL rename to doc/INSTALL diff --git a/INSTALL.ger b/doc/INSTALL.ger similarity index 100% rename from INSTALL.ger rename to doc/INSTALL.ger diff --git a/NEWS b/doc/NEWS similarity index 68% rename from NEWS rename to doc/NEWS index fb9553f..a49d30b 100644 --- a/NEWS +++ b/doc/NEWS @@ -1,4 +1,21 @@ -------13-Feb-96--------- +# in this files are important notes for user of mars_nwe. +------10-Mar-96--- 0.97.pl0 ---------- +New Conf-file entry '211' for broadcast periods. +Entries 400, 401 for special handling of the nearest server request. +- +Conf-file entry '6' enlarged. +- +New Entries '15' + '16' in conf-file. +With entry '15' you can allow mars_nwe insert all not yet known +users from /etc/passwd to mars_nwe bindery. But be carefully, +all new inserted users will get the same password from entry '15'. +- +If entry '16' is enabled ( '1' ) then mars_nwe will make some +checks for bindery and 'SYS:' directory. +For every user a MAIL/XXXXX dir will also be created. +- +Much more better bindery performance. :) +------13-Feb-96--- 0.96.pl9 ---------- New alternative password strategy in mars_nwe: There is an new entry '7' in ini/conf file. diff --git a/doc/README b/doc/README new file mode 100644 index 0000000..5f825a7 --- /dev/null +++ b/doc/README @@ -0,0 +1,71 @@ +(C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany + +to compile and install, please read INSTALL ! + +This is a little try to emulate some functions from +a NOVELL-SERVER under UNIX (LINUX). +The first version I have written 1993 on a USL1.1 +with TLI-Code. +1994 I have ported it to LINUX. This was easy, because +I only have to write a small TLI->SOCKET emu. + +Unfortunately I had no full description of the NCP-calls, +so many of the calls based on trying. :-( + +WARNING: this code has still many BUG's !! + +BINDERY: this are the *.pag and *.dir files. + These files are generated by the first starting + of mars_nwe and are filled with the minimal + needed Objects and Properties. + 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 + the network device in nw.ini should match + the NETWORK Number of the Novell-Server. + +LINUX +KERNEL: the only linux-kernel depending files + are emutli.[hc]. + +short description of the processes. +1) nwserv : the main program.Initiates all and starts 'ncpserv'. + sends broadcasts, wdogs, sap and rip packets. + If nwserv is started with a parameter, then the simple + test client 'nwclient', only for debugging, is started. + +2) ncpserv: opens NCP-Socket and handles NCP-Requests. + When there comes NCP-Request 0x1111 (Get Connection Nr) + then there will be started a new process 'nwconn'. + Every client-ncp-request reaches nwconn over + ncpserv. + +3) nwconn: will be started for every connection. Is connected + to ncpserv with a pipe. + +Problems and TODO: +Many:-( + +Here is a short list. +o - password changings from clients +o - make routing better. +o - making printing better. +o - clean the code !!! +o - make bindery code more complete. +o - and much more ... + +Have luck with trying. :) + + + Martin +(mstover@freeway.de) + +BTW: The kick to make mars_nwe public was the +publication of linware ( lwared ), the Novell-Server-Emulator +from Ales Dryak (A.Dryak@sh.cvut.cz). +I hope both products can make profit from each other. +-----> SuperNOS ala Linux ;-) +Novell don't want to make it anymore. :-( + diff --git a/README.ger b/doc/README.ger similarity index 100% rename from README.ger rename to doc/README.ger diff --git a/mars_nwe.lsm b/doc/mars_nwe.lsm similarity index 85% rename from mars_nwe.lsm rename to doc/mars_nwe.lsm index 316d798..c42f75d 100644 --- a/mars_nwe.lsm +++ b/doc/mars_nwe.lsm @@ -1,7 +1,7 @@ Begin3 Title: mars_nwe -Version: 0.96pl9 -Entered-date: 13-Feb-96 +Version: 0.97 +Entered-date: 10-Mar-96 Description: full novell-server-emulator (src),beta supports file-services, bindery-services, printing-services, routing-services @@ -9,7 +9,7 @@ Keywords: novell, netware, server, ipx, ncp, tli Author: mstover@freeway.de (Martin Stover) Maintained-by: mstover@freeway.de (Martin Stover) Primary-site: linux01.gwdg.de /pub/ncpfs - 110kB mars_nwe-0.96.pl9.tgz + 110kB mars_nwe-0.97.tgz Alternate-site: ftp.uni-duisburg.de /pub/linux/ipxware Platforms: Linux (1.2.xx, 1.3.32, > 1.3.55 tested, others should work) Copying-policy: GNU diff --git a/emutli.h b/emutli.h index 0a9c7b9..547aaba 100644 --- a/emutli.h +++ b/emutli.h @@ -36,6 +36,11 @@ typedef struct { uint8 sock[IPX_SOCK_SIZE]; } ipxAddr_t; +#define IPXCMPSOCK(a, b) ( \ + ((char *)(a))[0] == ((char*)(b))[0] && \ + ((char *)(a))[1] == ((char*)(b))[1] \ +) + #define IPXCMPNODE(a, b) ( \ ((char *)(a))[0] == ((char*)(b))[0] && \ ((char *)(a))[1] == ((char*)(b))[1] && \ diff --git a/examples/README.dosemu b/examples/README.dosemu index c89e02b..b920218 100644 --- a/examples/README.dosemu +++ b/examples/README.dosemu @@ -1,3 +1,4 @@ +!! this dosemupatch is _not_ needed for kernel >= 1.3.71 :) !! If dosemu don't work together with mars_nwe you should apply the dirty dosemu-patch to the dosemu program. In 1.3.6? the changing of an existing route over the internal net diff --git a/examples/README.patch b/examples/README.patch index 30e7fa9..586f198 100644 --- a/examples/README.patch +++ b/examples/README.patch @@ -1,4 +1,4 @@ -!! this kernelpatch is not needed for kernel >= 1.3.60 :) !! +!! this kernelpatch is _not_ needed for kernel >= 1.3.60 :) !! this kernelpatch for clean kernels 1.3.56,57,58, pur 59 makes 3 things. diff --git a/examples/config.h b/examples/config.h index 8a12a86..c0822a9 100644 --- a/examples/config.h +++ b/examples/config.h @@ -1,9 +1,17 @@ -/* config.h: 08-Feb-96 */ +/* config.h: 01-Mar-96 */ /* some of this config is needed by make, others by cc */ -#define DO_DEBUG 1 /* Debugging einschalten */ -#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 DO_DEBUG 1 /* Compile in debug code */ +#define DO_TESTING 0 + +#if DO_TESTING +# 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 */ +#else +# 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 */ +#endif #define NETWORK_SERIAL_NMBR 0x44444444L /* Serial Number 4 Byte */ #define NETWORK_APPL_NMBR 0x2222 /* Applikation Number 2 Byte */ @@ -13,21 +21,21 @@ #define MAX_NW_VOLS 10 /* max. Volumes */ #define IPX_DATA_GR_546 1 /* allow ipx packets > 546+30 Byte */ -#define WITH_NAME_SPACE_CALLS 0 /* Namespace Calls are only badly */ +#define WITH_NAME_SPACE_CALLS 0 /* Namespace Calls are only minimal */ /* supported till now. */ /* to enable testing of them this */ /* entry must be changed to '1' and */ /* entry '6' in ini file must be set */ - /* to '1', too. */ + /* to > '0', too. */ #define MAX_NW_SERVERS 40 /* max. count of servers */ /* <--------------- next is for linux only -------------------> */ -#define INTERNAL_RIP_SAP 1 /* use internal/own rip/sap process */ +#define INTERNAL_RIP_SAP 1 /* use internal/own rip/sap routines */ #define MAX_NET_DEVICES 5 /* max. Netdevices, frames */ #define MAX_NW_ROUTES 50 /* max. networks (internal + external) */ /* this is for very special use of mars_nwe to only act as a router */ -#define FILE_SERVER_INACTIV 0 /* 1 = ncpserv will not be startet */ +#define FILE_SERVER_INACTIV 0 /* 1 = don't start ncpserv */ diff --git a/examples/nw.ini b/examples/nw.ini index d764313..59b18ef 100644 --- a/examples/nw.ini +++ b/examples/nw.ini @@ -1,5 +1,5 @@ -# (C)opyright 1993, 1995, Martin Stover, Softwareentwicklung, Marburg -# last change: 13-Feb-96 +# (C)opyright 1993, 1996, Martin Stover, Softwareentwicklung, Marburg +# last change: 08-Mar-96 # MAR.S NW-Server Emulator # Einfache Konfiguration, alles ab # ist Kommentar. # Jeder Eintrag beginnt mit einer Zahl und dann folgt der Inhalt. @@ -52,16 +52,16 @@ # simple namespace services are implemented for testing # since V 0.96pl8. To test them, this entry must be set to '1'. # and config.h must be altered to allow namespace calls. -6 0 # tells server version: 2.15=0, 3.11=1 +6 0 # tells server version: 0=2.15, 1=3.11, 2=3.12 # Password handling 7 0 # 0 = use only encrypted passwords stuff (default) # 1 = allow the unencrypted change password routine. # 8 = allow all unencrypted stuff. # 9 = use all unencryted calls + get crypt key will allways fail - # so the login program will use the old unencryted calls. + # so the login program will use the old unencryted calls. ###################################### # GID and UID for _minimal_ rights -# will be used for not logins +# will be used for not logins or not assigned mars_nwe users. 10 200 # GID 11 201 # UID ############################# @@ -77,6 +77,17 @@ ## NW-Name UNIX-Name [PASSWORD] #13 MAR mar # others #13 ALF mar # others +##### +# Read UnixUsers automaticly from passwd into bindery +# switch password +15 0 secure11 +# ^^^ 0=off (default), 1=on, 99=overwrite existing users. +# !!! IMPORTANT !!! +# If you enable this feature you should chose a secure +# password for the users, because all not existent +# mars_nwe users will be inserted into bindery with this password. +############### +16 1 # enable some bindery and sys dir tests/creats after starting. ############################# # entry 21 for simple print queues # the queue Directory must exist before printing !!! @@ -85,7 +96,7 @@ #21 Q2 SYS:/PRINT/Q2 lpr -C printer2 ############################# # >= 100 debug flags, -# 0=nodebug, 1=mindebug(errors), 99=maxdebug +# 0=nodebug, 1=mindebug(errors+notes), 99=maxdebug 100 0 # debug IPX KERNEL (0 | 1) 101 1 # debug NWSERV 102 0 # debug NCPSERV @@ -95,17 +106,24 @@ 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 +202 1 # 1=creat new logfile, 0=append to logfile ############################# -210 10 # 1 .. 600 (default 10) seconds after server really goes down +210 10 # 1 .. 600 (default 10) seconds after server really goes down # # after a down command +211 60 # 10 .. 600 (default 60) broadcasts every x seconds ############################# -300 0 # > 0 print routing info to file every x broadcasts. ( minutes ) +300 0 # > 0 print routing info to file every x broadcasts. ( normally minutes ) 301 /tmp/nw.routes # filename. 302 1 # creat new filename=1, append to file=0 ############################# 310 7 # send wdog's only to device net < x tics. - # 0 = allways send wdogs. < 0 = never send wdogs - - + # 0 = allways send wdogs. < 0 = never send wdogs +############################## +# station file for special handling of stations. +400 /etc/nwserv.stations # for syntax see file in the examples directory. +# for special handling of the 'get nearest server request'. +401 0 # 0 = ignore entry 400, get nearest response ever enabled. + # 1 = 400 are excludes, get nearest response normally enabled. + # 2 = 400 are includes, get nearest response normally disabled. +### diff --git a/examples/nwserv.stations b/examples/nwserv.stations new file mode 100644 index 0000000..3c4e00a --- /dev/null +++ b/examples/nwserv.stations @@ -0,0 +1,14 @@ +# you can put station id's into this file for special handlings +# syntax: EntryNr net:node:socket (in hex notation or wildcards '?' and '*' ) +# it will be only a very simple matchcoded string compare, therefore you +# must use the correct syntax. +# +#1 0.0.0.22:0.80.48.55.3f.33:50.3 # one special client socket +#1 0.0.0.22:0.80.48.55.3f.33:40.* # one special client socket >= 0x4000 +#1 0.0.0.22:0.80.48.55.3f.32:* # one special client +#1 0.0.0.22:0.80.48.55.3f.2?:* # some clients 20 .. 29 +#1 0.0.0.21:* # one special net +# entry 1: is for get nearest server request handling. +# look also into the examples/nw.ini file. + + diff --git a/makefile.unx b/makefile.unx index dfdfa3d..a9aaebe 100644 --- a/makefile.unx +++ b/makefile.unx @@ -1,5 +1,5 @@ #if 0 -#makefile.unx 10-Feb-96 +#makefile.unx 08-Mar-96 #endif VPATH=$(V_VPATH) @@ -8,9 +8,9 @@ O=.o C=.c V_H=0 -V_L=96 -P_L=9 -#define D_P_L 1 +V_L=97 +P_L=0 +#define D_P_L 0 DISTRIB=mars_nwe #if D_P_L DISTRIBF=$(DISTRIB)-$(V_H).$(V_L).pl$(P_L) @@ -128,10 +128,11 @@ $(HOBJ3): namspace.h connect.h nwvolume.h nwfile.h $(OBJS): net.h config.h $(C)$(O): - $(CC) -c $(CFLAGS) $(HOSTCFLAGS) \ + $(CC) -c $(CFLAGS) $(HOSTCFLAGS)\ -D_VERS_H_=$(V_H) -D_VERS_L_=$(V_L) -D_VERS_P_=$(P_L) $< n_all: $(PROGS) + @echo "don't forget to do a 'make install' as root !" >> $(VPATH)/.mk.notes n_install_ini: cd $(VPATH) && $(INSTALL) -m 664 nw.ini $(M_FILENAME_NW_INI) && cd $(OBJDIR) @@ -160,7 +161,10 @@ echo ""; \ fi; cd $(OBJDIR) ) n_clean1: - cd $(VPATH) && (rm -f ~* examples/~* examples/.e.pck; cd $(OBJDIR)) + cd $(VPATH) && (\ + find . \( -name .e.pck -o -name '~*' -o -name '*~' -o -name core \) \ + -exec rm {} \; \ + ; cd $(OBJDIR)) n_clean: n_clean1 rm -f *.o @@ -173,23 +177,21 @@ n_make_dir: n_clean1 cd $(VPATH) && (rm -rf $(OBJDIR)/$(VPATH)/$(DISTRIB) \ ; mkdir $(DISTRIB) \ ; mkdir $(DISTRIB)/examples \ +; mkdir $(DISTRIB)/doc \ ; ln -f \ $(STERN).[ch] \ makefile.unx \ Makefile \ COPYING \ - NEWS \ - CHANGES \ README \ - README.ger \ - INSTALL \ - INSTALL.ger \ - $(DISTRIB).lsm \ $(DISTRIB)/. \ ; rm -f $(DISTRIB)/config.h \ ; ln -f \ examples/$(STERN) \ $(DISTRIB)/examples/. \ +; ln -f \ + doc/$(STERN) \ + $(DISTRIB)/doc/. \ ; cd $(OBJDIR) ) n_diff: n_make_dir @@ -202,28 +204,22 @@ n_distrib: n_diff -mkdir /tmp/x cd $(VPATH) && (tar cvzf $(DISTRIBF).tgz $(DISTRIB) \ ; uue $(DISTRIBF).tgz; mv -f $(DISTRIB)-$(V_H).uue $(DISTRIBF).uue \ -; cp -a $(DISTRIB)/$(DISTRIB).lsm /tmp/yy \ +; cp -a $(DISTRIB)/doc/$(DISTRIB).lsm /tmp/yy \ ; echo "" >> /tmp/yy \ ; echo "" >> /tmp/yy \ ; cat $(DISTRIBF).uue >> /tmp/yy \ ; chmod 664 /tmp/yy \ ; rm $(DISTRIBF).uue \ ; mv $(DISTRIBF).tgz /tmp/x/. \ -; cp -a $(DISTRIB)/$(DISTRIB).lsm /tmp/x/. \ +; cp -a $(DISTRIB)/doc/$(DISTRIB).lsm /tmp/x/. \ ; cd $(OBJDIR) ) n_distrib_bin: cd $(VPATH) && (tar cvzf /tmp/$(DISTRIB).bin.tgz \ $(PROGS) \ COPYING \ - INSTALL \ - INSTALL.ger \ - NEWS \ - CHANGES \ README \ - README.ger \ - $(DISTRIB).lsm \ examples \ + doc \ ; cd $(OBJDIR)) - diff --git a/ncpserv.c b/ncpserv.c index d2fd163..4da2c7c 100644 --- a/ncpserv.c +++ b/ncpserv.c @@ -1,5 +1,5 @@ /* ncpserv.c */ -#define REVISION_DATE "13-Feb-96" +#define REVISION_DATE "10-Mar-96" /* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany * * This program is free software; you can redistribute it and/or modify @@ -19,7 +19,11 @@ #include "net.h" #include "nwdbm.h" + +#if !CALL_NCPSERV_OVER_SOCKET static struct pollfd polls[2]; +#endif + 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; @@ -32,6 +36,10 @@ static int rcv_flags = 0; static char my_nwname[50]; static time_t akttime; static int server_goes_down=0; +static int ipx_out_fd=-1; + +/* next should be '1', is for testing only */ +#define USE_PERMANENT_OUT_SOCKET 1 static void write_to_nwserv(int what, int connection, int mode, char *data, int size) @@ -58,7 +66,7 @@ static void write_to_nwserv(int what, int connection, int mode, write(FD_NWSERV, &connection, sizeof(int)); break; - case 0xffff : /* say nwserv to down the server */ + case 0xffff : /* tell nwserv to down the server */ write(FD_NWSERV, &what, sizeof(int)); write(FD_NWSERV, &what, sizeof(int)); break; @@ -85,12 +93,12 @@ static void write_to_nwserv(int what, int connection, int mode, #define nwserv_down_server() \ write_to_nwserv(0xffff, 0, 0, NULL, 0) -static int open_ncp_socket() +static int open_ipx_sockets() { struct t_bind bind; ncp_fd=t_open("/dev/ipx", O_RDWR, NULL); if (ncp_fd < 0) { - if (nw_debug) t_error("t_open !Ok"); + t_error("t_open !Ok"); return(-1); } U16_TO_BE16(SOCK_NCP, my_addr.sock); /* NCP_SOCKET */ @@ -99,15 +107,30 @@ static int open_ncp_socket() bind.addr.buf = (char*)&my_addr; bind.qlen = 0; /* immer */ if (t_bind(ncp_fd, &bind, &bind) < 0){ - if (nw_debug) t_error("t_bind in open_ncp_socket !OK"); + t_error("t_bind in open_ipx_sockets !OK"); close(ncp_fd); return(-1); } +#if USE_PERMANENT_OUT_SOCKET + ipx_out_fd=t_open("/dev/ipx", O_RDWR, NULL); + if (ipx_out_fd > -1) { + U16_TO_BE16(0, my_addr.sock); /* dynamic socket */ + if (t_bind(ipx_out_fd, &bind, &bind) < 0) { + if (nw_debug) t_error("2. t_bind in open_ipx_sockets !OK"); + t_close(ipx_out_fd); + ipx_out_fd = -1; + } + } else { + if (nw_debug) t_error("2. t_open !Ok"); + } +#endif return(0); } typedef struct { - int fd; /* writepipe */ + int fd; /* writepipe */ + /* or if CALL_NWCONN_OVER_SOCKET then sock_nr of nwconn */ + int pid; /* pid from son */ ipxAddr_t client_adr; /* address client */ uint32 object_id; /* logged object */ @@ -126,43 +149,53 @@ static int anz_connect=0; /* actual anz connections */ static int new_conn_nr(void) { int j = -1; + int one_found=0; if (!anz_connect){ /* init all */ j = MAX_CONNECTIONS; while (j--) { connections[j].fd = -1; + connections[j].pid = -1; connections[j].message[0] = '\0'; } anz_connect++; return(1); } + j = -1; while (++j < MAX_CONNECTIONS) { CONNECTION *c=&(connections[j]); - if (c->fd < 0) { + if (c->fd < 0 && c->pid < 0) { c->message[0] = '\0'; if (++j > anz_connect) anz_connect=j; return(j); } } + /* nothing free */ j=MAX_CONNECTIONS; - while (j--) { + while (j-- && one_found < 3) { CONNECTION *c=&(connections[j]); if (!c->object_id) { /* NOT LOGGED IN */ /* makes wdog test faster */ nwserv_handle_wdog(j+1, 1); - return(0); + one_found++; } } - j=0; - while (j++ < MAX_CONNECTIONS) nwserv_handle_wdog(j, 2); + + if (!one_found) { + j=0; + while (j++ < MAX_CONNECTIONS) + nwserv_handle_wdog(j, 2); /* slow activate wdog */ + } + return(0); /* nothing free */ } static int free_conn_nr(int nr) { if (nr && --nr < anz_connect) { - connections[nr].fd = -1; + connections[nr].fd = -1; + connections[nr].pid = -1; return(0); } return(-1); @@ -185,21 +218,43 @@ static void clear_connection(int conn) if (conn > 0 && --conn < anz_connect) { CONNECTION *c = &connections[conn]; if (c->fd > -1) { +#if !CALL_NWCONN_OVER_SOCKET close(c->fd); +#endif c->fd = -1; - if (c->pid > -1) { - kill(c->pid, SIGTERM); /* kill it */ - c->pid = -1; - } + if (c->pid > -1) kill(c->pid, SIGTERM); /* kill it */ } c->object_id = 0; - conn = anz_connect; + } +} + +static void kill_connections(void) +/* here the connections will really removed */ +{ + int conn; + int stat_loc; + int pid; + while ((pid=waitpid(-1, &stat_loc, WNOHANG)) > 0) { + conn = anz_connect; while (conn--) { CONNECTION *c = &connections[conn]; - if (c->fd < 0) anz_connect--; - else break; + if (c->pid == pid) clear_connection(conn+1); } } + conn = anz_connect; + while (conn--) { + CONNECTION *c = &connections[conn]; + if (c->fd < 0 && c->pid > -1) { + kill(c->pid, SIGKILL); /* kill it */ + c->pid = -1; + } + } + conn = anz_connect; + while (conn--) { + CONNECTION *c = &connections[conn]; + if (c->fd < 0 && c->pid < 0) anz_connect--; + else break; + } } static int find_get_conn_nr(ipxAddr_t *addr) @@ -214,6 +269,7 @@ static int find_get_conn_nr(ipxAddr_t *addr) if (!connection){ if ((connection = new_conn_nr()) > 0){ CONNECTION *c=&(connections[connection-1]); +#if !CALL_NWCONN_OVER_SOCKET int fds[2]; memcpy((char*) &(c->client_adr), (char *)addr, sizeof(ipxAddr_t)); if (pipe(fds) < 0) { @@ -221,15 +277,50 @@ static int find_get_conn_nr(ipxAddr_t *addr) free_conn_nr(connection); return(0); } else { +#else + int ipx_fd=-1; + struct t_bind bind; + memcpy((char*) &(c->client_adr), (char *)addr, sizeof(ipxAddr_t)); + ipx_fd=t_open("/dev/ipx", O_RDWR, NULL); + if (ipx_fd > -1) { + U16_TO_BE16(0, my_addr.sock); /* actual write socket */ + bind.addr.len = sizeof(ipxAddr_t); + bind.addr.maxlen = sizeof(ipxAddr_t); + bind.addr.buf = (char*)&my_addr; + bind.qlen = 0; /* allways */ + if (t_bind(ipx_fd, &bind, &bind) < 0){ + if (nw_debug) t_error("t_bind !OK"); + t_close(ipx_fd); + ipx_fd = -1; + } else { + ; +#if 0 + t_unbind(ipx_fd); + t_close(ipx_fd); + ipx_fd = (int) GET_BE16(my_addr.sock); +#endif + } + } else { + if (nw_debug) t_error("t_open !Ok"); + } + if (ipx_fd < 0) { + errorp(0, "find_get_conn_nr, socket", NULL); + free_conn_nr(connection); + return(0); + } else { +#endif int akt_pid = getpid(); int pid = fork(); if (pid < 0) { errorp(0, "find_get_conn_nr, fork", NULL); free_conn_nr(connection); +#if !CALL_NWCONN_OVER_SOCKET close(fds[0]); close(fds[1]); +#endif return(0); } + if (pid == 0) { /* new process */ char *progname="nwconn"; @@ -238,10 +329,14 @@ static int find_get_conn_nr(ipxAddr_t *addr) char connstr[20]; char addrstr[100]; int j = 2; +#if !CALL_NWCONN_OVER_SOCKET close(fds[1]); /* no writing */ dup2(fds[0], 0); /* becomes stdin */ close(fds[0]); /* not needed */ - +#else + dup2(ipx_fd, 0); /* becomes stdin */ + close(ipx_fd); +#endif while (j++ < 100) close(j); /* close all > stderr */ sprintf(pidstr, "%d", akt_pid); @@ -253,8 +348,13 @@ static int find_get_conn_nr(ipxAddr_t *addr) exit(1); /* normaly not reached */ } c->pid = pid; +#if CALL_NWCONN_OVER_SOCKET + c->fd = (int) GET_BE16(my_addr.sock); + close(ipx_fd); +#else c->fd = fds[1]; close(fds[0]); /* no need to read */ +#endif XDPRINTF((5,0, "AFTER FORK new PROCESS =%d, connection=%d", pid, connection)); } } @@ -290,6 +390,16 @@ static void get_login_time(uint8 login_time[], CONNECTION *cx) login_time[6] = s_tm->tm_wday; } +#if CALL_NWCONN_OVER_SOCKET +static void send_to_nwconn(int nwconn_sock, char *data, int size) +{ + ipxAddr_t nwconn_addr; + memcpy(&nwconn_addr, &my_addr, sizeof(ipxAddr_t)); + U16_TO_BE16(nwconn_sock, nwconn_addr.sock); + send_ipx_data(ipx_out_fd, 17, size, data, &nwconn_addr, NULL); +} +#endif + static int handle_fxx(CONNECTION *c, int gelen, int func) /* here are handled the global 0x15, 0x17, 0x57 functions */ @@ -426,7 +536,9 @@ static int handle_fxx(CONNECTION *c, int gelen, int func) xdata->subversion = 15; } else { xdata->version = 3; - xdata->subversion = 11; + xdata->subversion = (tells_server_version == 2) + ? 12 + : 11; } i=0; @@ -888,7 +1000,7 @@ static int handle_fxx(CONNECTION *c, int gelen, int func) newpassword)); if (c->object_id == 1 || 0 == (result=nw_test_unenpasswd(obj.id, oldpassword))) - result=nw_set_passwd(obj.id, newpassword); + result=nw_set_passwd(obj.id, newpassword, 0); } if (result < 0) completition = (uint8) -result; } else { @@ -1232,10 +1344,16 @@ static int handle_fxx(CONNECTION *c, int gelen, int func) ncpresponse->completition = completition; if (c->message[0]) connect_status |= 0x40; ncpresponse->connect_status = connect_status; +#if CALL_NWCONN_OVER_SOCKET + data_len+=sizeof(NCPRESPONSE); + send_to_nwconn(c->fd, (char*)ncpresponse, data_len); +#else data_len=write(c->fd, (char*)ncpresponse, sizeof(NCPRESPONSE) + data_len); +#endif XDPRINTF((2, 0, "0x%x 0x%x compl:0x%x, write to %d, anz = %d", func, (int)ufunc, (int) completition, c->fd, data_len)); + return(0); /* ok */ } @@ -1256,20 +1374,24 @@ static void ncp_response(int type, int sequence, if (nw_debug){ char comment[80]; sprintf(comment, "NCP-RESP compl=0x%x ", completition); - send_ipx_data(-1, 17, sizeof(NCPRESPONSE) + data_len, + send_ipx_data(ipx_out_fd, 17, sizeof(NCPRESPONSE) + data_len, (char *) ncpresponse, &from_addr, comment); } else - send_ipx_data(-1, 17, sizeof(NCPRESPONSE) + data_len, + send_ipx_data(ipx_out_fd, 17, sizeof(NCPRESPONSE) + data_len, (char *) ncpresponse, &from_addr, NULL); } +#if 0 static void sig_child(int isig) { int k=-1; int status; - int pid=wait(&status); + int pid; + signal(SIGCHLD, sig_child); + pid=wait(&status); + XDPRINTF((1,0, "GOT conn pid=%d", pid)); if (pid > -1) { while (++k < anz_connect) { CONNECTION *c = &connections[k]; @@ -1278,9 +1400,10 @@ static void sig_child(int isig) break; } } + kill(pid, SIGKILL); /* kill it */ } - signal(SIGCHLD, sig_child); } +#endif static void close_all(void) { @@ -1291,20 +1414,32 @@ static void close_all(void) t_close(ncp_fd); XDPRINTF((2,0, "LEAVE ncpserv")); ncp_fd = -1; + if (ipx_out_fd > -1) { + t_unbind(ipx_out_fd); + t_close(ipx_out_fd); + ipx_out_fd = -1; + } } + sync_dbm(); } +static int server_is_down=0; static void sig_quit(int isig) { - close_all(); - exit(0); + server_is_down++; } +static int got_sig_child=0; +static void sig_child(int isig) +{ + got_sig_child++; + signal(SIGCHLD, sig_child); +} static void set_sig(void) { - signal(SIGTERM, sig_quit); signal(SIGQUIT, sig_quit); + signal(SIGTERM, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGCHLD, sig_child); @@ -1323,7 +1458,7 @@ static void handle_bind_calls(uint8 *p) p += 2; strmaxcpy(obj.name, p+1, *p); p += (*p+1); - nw_new_create_prop(0, obj.name, obj.type, O_FL_DYNA, 0x40, + nw_new_obj_prop(0, obj.name, obj.type, O_FL_DYNA, 0x40, "NET_ADDRESS", P_FL_DYNA|P_FL_ITEM, 0x40, (char *)p, sizeof(ipxAddr_t)); } @@ -1343,26 +1478,68 @@ static void handle_bind_calls(uint8 *p) } } -static int handle_ctrl(void) -/* reads stdin pipe */ +static int xread(IPX_DATA *ipxd, int *offs, uint8 *data, int size) { + if (*offs == 0) { +#if CALL_NCPSERV_OVER_SOCKET + memcpy(ipxd, &ipx_in_data, ud.udata.len); +#else + if (read(0, (char*)&(ipxd->owndata.d), sizeof(int)) == sizeof(int)) { + if (ipxd->owndata.d.size >= size && + ipxd->owndata.d.size < IPX_MAX_DATA - sizeof(ipxd->owndata)) { + + if (ipxd->owndata.d.size > + read(0, (char*)&(ipxd->owndata.d.function), + ipxd->owndata.d.size) ) { + size=-1; + } + + } else { + errorp(1, "xread:", "datasize = %d", ipxd->owndata.d.size); + size=-1; + } + } else size = -1; +#endif + } + if (size > -1 && *offs + size > ipxd->owndata.d.size) { + errorp(1, "xread:", "prog error: *offs=%d + size=%d > d.size=%d", + *offs, size, ipxd->owndata.d.size); + size = -1; + } + + if (size > -1) { + memcpy(data, ((uint8 *)&(ipxd->owndata.d.function)) + *offs, size); + *offs+=size; + } else { + errorp(1, "xread:", "readerror"); + } + return(size); +} + +static int handle_ctrl(void) +/* reads stdin pipe or packets from nwserv */ +{ + IPX_DATA ipxd; int what; int conn; int result = 0; - int data_len = read(0, (char*)&what, sizeof(what)); - if (data_len == sizeof(what)) { - XDPRINTF((2, 0, "GOT CTRL what=0x%x", what)); + int offs=0; + int data_len = xread(&ipxd, &offs, (uint8*)&(what), sizeof(int)); + if (data_len == sizeof(int)) { + XDPRINTF((2, 0, "GOT CTRL what=0x%x, len=%d", what, ipxd.owndata.d.size)); switch (what) { case 0x5555 : /* clear_connection */ - data_len = read(0, (char*)&conn, sizeof(conn)); - if (sizeof(int) == data_len) clear_connection(conn); + if (sizeof (int) == + xread(&ipxd, &offs, (uint8*)&(conn), sizeof(int))) + clear_connection(conn); break; case 0x3333 : /* 'bindery' calls */ - if (sizeof(conn) == read(0, (char*)&conn, sizeof(conn))) { + if (sizeof (int) == + xread(&ipxd, &offs, (uint8*)&(conn), sizeof(int))) { uint8 *buff = (uint8*) xmalloc(conn+10); XDPRINTF((2,0, "0x3333 len=%d", conn)); - if (conn == read(0, (char*)buff, conn)) + if (conn == xread(&ipxd, &offs, buff, conn)) handle_bind_calls(buff); else XDPRINTF((1, 1, "0x3333 protokoll error:len=%d", conn)); @@ -1372,11 +1549,12 @@ static int handle_ctrl(void) case 0xeeee: get_ini_debug(NCPSERV); - nw_fill_standard(NULL, NULL); + (void)nw_fill_standard(NULL, NULL); + sync_dbm(); break; case 0xffff : /* server down */ - data_len = read(0, (char*)&conn, sizeof(conn)); + data_len = xread(&ipxd, &offs, (char*)&conn, sizeof(int)); if (sizeof(int) == data_len && conn == what) sent_down_message(); break; @@ -1384,27 +1562,175 @@ static int handle_ctrl(void) default : break; } /* switch */ result++; - } else XDPRINTF((2, 0, "GOT CTRL size=%d", data_len)); + } else { + errorp(1, "handle_ctrl", "wrong data len=%d", data_len); + } return(result); } +static void handle_ncp_request(void) +{ + if (t_rcvudata(ncp_fd, &ud, &rcv_flags) > -1){ + int type; + in_len = ud.udata.len; + time(&akttime); + XDPRINTF((10, 0, "NCPSERV-LOOP von %s", visable_ipx_adr(&from_addr))); + if ((type = GET_BE16(ncprequest->type)) == 0x2222 || type == 0x5555) { + int connection = (int)ncprequest->connection; + XDPRINTF((10,0, "GOT 0x%x in NCPSERV connection=%d", 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 (diff_time > 50) /* after max. 50 seconds */ + nwserv_reset_wdog(connection); + /* tell the wdog there's no need to look */ +#if !CALL_NWCONN_OVER_SOCKET + if (ncprequest->sequence == c->sequence + && !c->retry++) { + /* perhaps nwconn is busy */ + ncp_response(0x9999, ncprequest->sequence, + connection, 0, 0x0, 0, 0); + XDPRINTF((2, 0, "Send Request being serviced to connection:%d", connection)); + return; + } +#endif + switch (func) { + case 0x15 : /* Messages */ + case 0x17 : /* File Server Environment */ + sent_here = handle_fxx(c, in_len, func); + break; + + case 0x57 : if (!tells_server_version) { + /* 2.15 er don't have namespace_calls */ + sent_here = handle_fxx(c, in_len, func); + } + break; + + default : break; + } /* switch */ + + if (sent_here) { + int anz= +#if CALL_NWCONN_OVER_SOCKET + in_len; + send_to_nwconn(c->fd, (char*)ncprequest, in_len); +#else + write(c->fd, (char*)ncprequest, in_len); +#endif + XDPRINTF((10,0, "write to %d, anz = %d", c->fd, anz)); + if (func == 0x19) { /* logout */ + c->object_id = 0; /* not LOGIN */ + } + } + c->sequence = ncprequest->sequence; /* save last sequence */ + c->retry = 0; + return; + } else { /* 0x5555, close connection */ +#if !CALL_NWCONN_OVER_SOCKET + if ( (uint8) (c->sequence+1) == (uint8) ncprequest->sequence) +#endif + { + clear_connection(ncprequest->connection); + ncp_response(0x3333, + ncprequest->sequence, + connection, + 1, /* task */ + 0x0, /* completition */ + 0, /* conn status */ + 0); + return; + } + } + } + XDPRINTF((10,0, "c->fd = %d", c->fd)); + } + } + /* here someting is wrong */ + XDPRINTF((1,0, "GOT 0x%x connection=%d of %d conns not OK", + type, ncprequest->connection, anz_connect)); + + ncp_response(0x3333, ncprequest->sequence, + ncprequest->connection, + 0, /* task */ + 0xff, /* completition */ + 0xff, /* conn status */ + 0); + + } else if (type == 0x1111) { + /* GIVE CONNECTION Nr connection */ + int connection = (server_goes_down) ? 0 : find_get_conn_nr(&from_addr); + XDPRINTF((2, 0, "GIVE CONNECTION NR=%d", connection)); + if (connection) { + CONNECTION *c = &(connections[connection-1]); + int anz; + c->message[0] = '\0'; + c->object_id = 0; /* firsttime set 0 for NOT LOGIN */ + c->sequence = 0; +#if CALL_NWCONN_OVER_SOCKET + anz = in_len; + send_to_nwconn(c->fd, (char*)ncprequest, in_len); +#else + anz=write(c->fd, (char*)ncprequest, in_len); +#endif + XDPRINTF((10, 0, "write to oldconn %d, anz = %d", c->fd, anz)); + } else /* no free connection */ + ncp_response(0x3333, 0, 0, 0, + 0xf9, /* completition */ + 0, /* conn status */ + 0); +#if CALL_NCPSERV_OVER_SOCKET + } else if (type == 0xeeee + && ((OWN_DATA*)(&ipx_in_data))->type1[0] == 0xee + && ((OWN_DATA*)(&ipx_in_data))->type1[1] == 0xee + && IPXCMPNODE(from_addr.node, my_addr.node) + && IPXCMPNET (from_addr.net, my_addr.net)) { + /* comes from nwserv */ + handle_ctrl(); +#endif + } else { + int connection = (int)ncprequest->connection; + int sequence = (int)ncprequest->sequence; + XDPRINTF((1,0, "Got UNKNOWN TYPE: 0x%x", type)); + ncp_response(0x3333, sequence, connection, + 1, 0xfb, 0, 0); + } + } +} + int main(int argc, char *argv[]) { - int result; - int type; if (argc != 3) { fprintf(stderr, "usage ncpserv address nwname\n"); exit(1); } - init_tools(NCPSERV); + init_tools(NCPSERV, 0); 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); + + if (nw_init_dbm(my_nwname, &my_addr) <0) { + errorp(1, "nw_init_dbm", NULL); + exit(1); + } + #ifdef LINUX set_emu_tli(); #endif - if (open_ncp_socket()) exit(1); + if (open_ipx_sockets()) { + errorp(1, "open_ipx_sockets", NULL); + exit(1); + } + + XDPRINTF((1, 0, "USE_PERMANENT_OUT_SOCKET %s", + (ipx_out_fd > -1) ? "enabled" : "disabled")); + ud.opt.len = sizeof(ipx_pack_typ); ud.opt.maxlen = sizeof(ipx_pack_typ); ud.opt.buf = (char*)&ipx_pack_typ; /* gets actual Typ */ @@ -1418,133 +1744,32 @@ int main(int argc, char *argv[]) ud.udata.buf = (char*)&ipx_in_data; set_sig(); +#if CALL_NCPSERV_OVER_SOCKET + while (!server_is_down) { + handle_ncp_request(); + if (got_sig_child) { + kill_connections(); + got_sig_child=0; + } + } +#else 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) { + while (!server_is_down) { int anz_poll = poll(polls, 2, 60000); - time(&akttime); if (anz_poll > 0) { /* i have to work */ struct pollfd *p = &polls[0]; int j = -1; while (++j < 2) { - if (p->revents){ if (!j) { /* ncp-socket */ XDPRINTF((99,0, "POLL revents=%d", 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, 0, "NCPSERV-LOOP von %s", visable_ipx_adr(&from_addr))); - if ((type = GET_BE16(ncprequest->type)) == 0x2222 || type == 0x5555) { - int connection = (int)ncprequest->connection; - XDPRINTF((10,0, "GOT 0x%x in NCPSERV connection=%d", 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 (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, 0, "Send Request being serviced to connection:%d", connection)); - continue; - } - - switch (func) { - case 0x15 : /* Messages */ - case 0x17 : /* File Server Environment */ - sent_here = handle_fxx(c, in_len, func); - break; - - case 0x57 : if (!tells_server_version) { - /* 2.15 er has no namespace_calls */ - 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,0, "write to %d, anz = %d", c->fd, anz)); - if (func == 0x19) { /* logout */ - c->object_id = 0; /* not LOGIN */ - } - } - c->sequence = ncprequest->sequence; /* save last sequence */ - c->retry = 0; - continue; - } else { /* 0x5555, close connection */ - if ( (uint8) (c->sequence+1) == (uint8) ncprequest->sequence) { - clear_connection(ncprequest->connection); - ncp_response(0x3333, - ncprequest->sequence, - connection, - 1, /* task */ - 0x0, /* completition */ - 0, /* conn status */ - 0); - continue; - } - } - } - XDPRINTF((10,0, "c->fd = %d", c->fd)); - } - } - /* here someting is wrong */ - XDPRINTF((1,0, "GOT 0x%x connection=%d of %d conns not OK", - type, ncprequest->connection, anz_connect)); - - ncp_response(0x3333, ncprequest->sequence, - ncprequest->connection, - 0, /* task */ - 0xff, /* completition */ - 0xff, /* conn status */ - 0); - - } else if (type == 0x1111) { - /* GIVE CONNECTION Nr connection */ - int connection = (server_goes_down) ? 0 : find_get_conn_nr(&from_addr); - XDPRINTF((2, 0, "GIVE CONNECTION NR=%d", connection)); - if (connection) { - CONNECTION *c = &(connections[connection-1]); - int anz; - c->message[0] = '\0'; - c->object_id = 0; /* firsttime set 0 for NOT LOGIN */ - c->sequence = 0; - anz=write(c->fd, (char*)ncprequest, in_len); - XDPRINTF((10, 0, "write to oldconn %d, anz = %d", c->fd, anz)); - } else /* no free connection */ - ncp_response(0x3333, 0, 0, 0, - 0xf9, /* completition */ - 0, /* conn status */ - 0); - - } else { - int connection = (int)ncprequest->connection; - int sequence = (int)ncprequest->sequence; - XDPRINTF((1,0, "Got UNKNOWN TYPE: 0x%x", type)); - ncp_response(0x3333, sequence, connection, - 1, 0xfb, 0, 0); - } - } - } + else + handle_ncp_request(); } else if (p->fd==0) { /* fd_ncpserv_in */ XDPRINTF((2,0,"POLL %d, fh=%d", p->revents, p->fd)); if (p->revents & ~POLLIN) @@ -1558,7 +1783,12 @@ int main(int argc, char *argv[]) } else { XDPRINTF((3,0,"POLLING ...")); } + if (got_sig_child) { + kill_connections(); + got_sig_child=0; + } } +#endif close_all(); return(0); } diff --git a/net.h b/net.h index 9f3bd89..a6863df 100644 --- a/net.h +++ b/net.h @@ -1,4 +1,4 @@ -/* net.h 11-Feb-96 */ +/* net.h 01-Mar-96 */ /* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany * @@ -93,8 +93,25 @@ /* ===================> config.h <======================= */ +#ifdef CALL_NWCONN_OVER_SOCKET +# undef CALL_NWCONN_OVER_SOCKET +#endif + +#ifdef CALL_NCPSERV_OVER_SOCKET +# undef CALL_NCPSERV_OVER_SOCKET +#endif + + #include "config.h" +#ifndef CALL_NWCONN_OVER_SOCKET +# define CALL_NWCONN_OVER_SOCKET 0 +#endif + +#ifndef CALL_NCPSERV_OVER_SOCKET +# define CALL_NCPSERV_OVER_SOCKET 1 +#endif + #ifndef DO_DEBUG # define DO_DEBUG 1 #endif @@ -270,6 +287,15 @@ typedef union { uint8 reserved; /* high connection */ uint8 function; /* Function */ } ncprequest; + struct S_OWN_DATA { + uint8 type[2]; /* 0xeeee */ + uint8 type1[2]; /* 0xeeee */ + struct { + int size; /* size of next two entries */ + int function; + uint8 data[1]; + } d; + } owndata; char data[IPX_MAX_DATA]; } IPX_DATA; @@ -283,6 +309,7 @@ typedef struct S_CONFREQ CONFREQ; typedef struct S_DIAGRESP DIAGRESP; typedef struct S_NCPRESPONSE NCPRESPONSE; typedef struct S_NCPREQUEST NCPREQUEST; +typedef struct S_OWN_DATA OWN_DATA; /* SOCKETS */ #define SOCK_AUTO 0x0000 /* Autobound Socket */ diff --git a/net1.c b/net1.c index 2ab78e4..55d3125 100644 --- a/net1.c +++ b/net1.c @@ -108,7 +108,7 @@ void adr_to_ipx_addr(ipxAddr_t *p, char *s) int net0, net1, net2, net3; int node0, node1, node2, node3, node4, node5; int sock0, sock1; - sscanf(s, "%x.%x.%x.%x,%x.%x.%x.%x.%x.%x,%x.%x", + sscanf(s, "%x.%x.%x.%x:%x.%x.%x.%x.%x.%x:%x.%x", &net0, &net1, &net2, &net3, &node0, &node1, &node2, &node3, &node4, &node5, &sock0, &sock1); @@ -128,7 +128,7 @@ void adr_to_ipx_addr(ipxAddr_t *p, char *s) void ipx_addr_to_adr(char *s, ipxAddr_t *p) { - sprintf(s, "%x.%x.%x.%x,%x.%x.%x.%x.%x.%x,%x.%x", + sprintf(s, "%x.%x.%x.%x:%x.%x.%x.%x.%x.%x:%x.%x", (int)p->net[0] , (int)p->net[1] , (int)p->net[2] , diff --git a/netn.c b/netn.c deleted file mode 100644 index 7a05174..0000000 --- a/netn.c +++ /dev/null @@ -1,34 +0,0 @@ -/* netr.c 11-Sep-95 */ - -/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#include "net.h" - -int main() -{ - int ipx_fd = test1(SOCK_NCP); - if (ipx_fd > -1) { - if (t_unbind(ipx_fd) < 0){ - t_error("t_unbind !OK"); - } - t_close(ipx_fd); - } - return(0); -} - diff --git a/nwclient.c b/nwclient.c index 1e78ab3..8cc3f5a 100644 --- a/nwclient.c +++ b/nwclient.c @@ -702,7 +702,7 @@ static void test_wdog(void) /* --------------------------------------------------------- */ int main(int argc, char **argv) { - init_tools(NWCLIENT); + init_tools(NWCLIENT, 0); if (argc != 3) { fprintf(stderr, "usage: nwclient MY_ADDR SERVER_ADDR\n"); diff --git a/nwconn.c b/nwconn.c index e753c9a..cff5934 100644 --- a/nwconn.c +++ b/nwconn.c @@ -1,4 +1,4 @@ -/* nwconn.c 10-Feb-96 */ +/* nwconn.c 01-Mar-96 */ /* one process / connection */ /* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany @@ -44,7 +44,7 @@ static NCPREQUEST *ncprequest = (NCPREQUEST*)readbuff; static uint8 *requestdata = readbuff + sizeof(NCPREQUEST); static int ncp_type; -static int open_ipx_socket() +static int open_ipx_socket(int wanted_sock) { struct t_bind bind; ipx_fd=t_open("/dev/ipx", O_RDWR, NULL); @@ -52,7 +52,7 @@ static int open_ipx_socket() if (nw_debug) t_error("t_open !Ok"); return(-1); } - U16_TO_BE16(0, my_addr.sock); /* actual write socket */ + U16_TO_BE16(wanted_sock, my_addr.sock); /* actual write socket */ bind.addr.len = sizeof(ipxAddr_t); bind.addr.maxlen = sizeof(ipxAddr_t); bind.addr.buf = (char*)&my_addr; @@ -67,9 +67,7 @@ static int open_ipx_socket() return(0); } - static int req_printed=0; - static int ncp_response(int sequence, int completition, int data_len) @@ -1282,7 +1280,7 @@ extern int t_errno; static void close_all(void) { - nw_init_connect(); + nw_exit_connect(); close(0); if (ipx_fd > -1){ while (t_unbind(ipx_fd) < 0) { @@ -1292,69 +1290,81 @@ static void close_all(void) } } +static int fl_get_int=0; + static void sig_quit(int rsig) { - close_all(); - exit(0); -} - -static int fl_get_debug=0; -static void get_new_debug(void) -{ - get_ini_debug(3); - fl_get_debug=0; + XDPRINTF((2, 0, "Got Signal=%d", rsig)); + fl_get_int=2; } static void sig_hup(int rsig) { - signal(SIGHUP, SIG_IGN); - fl_get_debug++; + fl_get_int=1; signal(SIGHUP, sig_hup); } -#if 0 -static void sig_child(int isig) +static void get_new_debug(void) { - int status; - int pid=wait(&status); - if (pid > -1) kill(pid, SIGKILL); /* evtl Toechter killen */ - signal(SIGCHLD, sig_child); + get_ini_debug(3); + fl_get_int=0; } -#endif static void set_sig(void) { signal(SIGTERM, sig_quit); signal(SIGQUIT, sig_quit); + signal(SIGINT, sig_quit); + signal(SIGPIPE, sig_quit); signal(SIGHUP, sig_hup); - signal(SIGINT, SIG_IGN); - signal(SIGPIPE, SIG_IGN); - /* signal(SIGCHLD, sig_child); */ } int main(int argc, char **argv) { +#if CALL_NWCONN_OVER_SOCKET + uint8 i_ipx_pack_typ; + ipxAddr_t x_from_addr; + ipxAddr_t client_addr; + struct t_unitdata iud; +#endif + int wanted_sock = (argc==5) ? atoi(*(argv+4)) : 0; + if (argc == 5) argc--; if (argc != 4) { - fprintf(stderr, "usage nwconn PID FROM_ADDR Connection\n"); + fprintf(stderr, "usage nwconn PID FROM_ADDR Connection [sock]\n"); exit(1); } else father_pid = atoi(*(argv+1)); setuid(0); setgid(0); - init_tools(NWCONN); + init_tools(NWCONN, atoi(*(argv+3))); - XDPRINTF((1, 0, "FATHER PID=%d, ADDR=%s CON:%s", father_pid, *(argv+2), *(argv+3))); + XDPRINTF((2, 0, "FATHER PID=%d, ADDR=%s CON:%s", father_pid, *(argv+2), *(argv+3))); - adr_to_ipx_addr(&from_addr, *(argv+2)); + adr_to_ipx_addr(&from_addr, *(argv+2)); +#if CALL_NWCONN_OVER_SOCKET + adr_to_ipx_addr(&client_addr, *(argv+2)); +#endif if (nw_init_connect()) exit(1); #ifdef LINUX set_emu_tli(); #endif - last_sequence = -9999; - if (open_ipx_socket()) exit(1); +#if !CALL_NWCONN_OVER_SOCKET + if (open_ipx_socket(wanted_sock)) exit(1); +#else + ipx_fd =0; +# if 1 +# ifdef SIOCIPXNCPCONN + { + int conn = atoi(*(argv+3)); + int result = ioctl(ipx_fd, SIOCIPXNCPCONN, &conn); + XDPRINTF((2, 0, "ioctl:SIOCIPXNCPCONN result=%d", result)); + } +# endif +# endif +#endif set_default_guid(); @@ -1371,15 +1381,39 @@ int main(int argc, char **argv) ncpresponse->reserved = (uint8) 0; /* allways 0 */ ncpresponse->connection = (uint8) atoi(*(argv+3)); +#if CALL_NWCONN_OVER_SOCKET + iud.opt.len = sizeof(i_ipx_pack_typ); + iud.opt.maxlen = sizeof(i_ipx_pack_typ); + iud.opt.buf = (char*)&i_ipx_pack_typ; /* gets actual Typ */ + + iud.addr.len = sizeof(ipxAddr_t); + iud.addr.maxlen = sizeof(ipxAddr_t); + iud.addr.buf = (char*)&x_from_addr; + + iud.udata.len = IPX_MAX_DATA; + iud.udata.maxlen = IPX_MAX_DATA; + iud.udata.buf = (char*)readbuff; +#endif + set_sig(); while (1) { +#if CALL_NWCONN_OVER_SOCKET + int rcv_flags = 0; + int data_len = (t_rcvudata(ipx_fd, &iud, &rcv_flags) > -1) + ? iud.udata.len : -1; +#else int data_len = read(0, readbuff, sizeof(readbuff)); +#endif ncpresponse->connect_status = (uint8) 0; - if (data_len > 0) { - if (fl_get_debug) get_new_debug(); - XDPRINTF((99, 0, "NWCONN GOT DATA len = %d",data_len)); + if (fl_get_int) { + if (fl_get_int == 1) get_new_debug(); + else if (fl_get_int == 2) break; + } + + if (data_len > 0) { + XDPRINTF((99, 0, "NWCONN GOT DATA len = %d",data_len)); if ((ncp_type = (int)GET_BE16(ncprequest->type)) == 0x3333) { /* OK for direct sending */ data_len -= sizeof(NCPRESPONSE); @@ -1390,13 +1424,23 @@ int main(int argc, char **argv) ncp_response((int)(ncprequest->sequence), (int)(ncprequest->function), data_len); } else { /* this calls I must handle */ requestlen = data_len - sizeof(NCPREQUEST); +#if 0 /* CALL_NWCONN_OVER_SOCKET */ +#ifdef SIOCIPXNCPCONN + if (ncp_type == 0x2222 && + (0x17 == ncprequest->function || 0x15 == ncprequest->function) + && IPXCMPSOCK (from_addr.sock, client_addr.sock) + && IPXCMPNODE (from_addr.node, client_addr.node) + && IPXCMPNET (from_addr.net, client_addr.net) { + /* this call must be prehandled by ncpserv */ + XDPRINTF((2,0, "SEND TO NCPSERV")); + } else +#endif +#endif handle_ncp_serv(); } - } else if (data_len < 0) { - if (fl_get_debug) get_new_debug(); - else break; } - } + } /* while */ close_all(); + XDPRINTF((2,0, "leave nwconn pid=%d", getpid())); return(0); } diff --git a/nwdbm.c b/nwdbm.c index 0ae18a6..6e96b2b 100644 --- a/nwdbm.c +++ b/nwdbm.c @@ -1,4 +1,4 @@ -/* nwdbm.c 12-Feb-96 data base for mars_nwe */ +/* nwdbm.c 22-Feb-96 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 @@ -36,18 +36,26 @@ # include #endif +#define DBM_REMAINS_OPEN 1 + int tells_server_version=0; int password_scheme=0; -static char *fnprop = "nwprop"; -static char *fnval = "nwval"; -static char *fnobj = "nwobj"; - static datum key; static datum data; static DBM *my_dbm=NULL; -static int dbminit(char *s) +#define FNPROP 0 +#define FNVAL 1 +#define FNOBJ 2 + +static char *dbm_fn[3] = { "nwprop", "nwval", "nwobj" }; + +#if DBM_REMAINS_OPEN +static DBM *my_dbms[3] = { NULL, NULL, NULL }; +#endif + +static int x_dbminit(char *s) { char buff[256]; sprintf(buff, "%s/%s", PATHNAME_BINDERY, s); @@ -55,15 +63,45 @@ static int dbminit(char *s) return( (my_dbm == NULL) ? -1 : 0); } +static int dbminit(int what_dbm) +{ +#if DBM_REMAINS_OPEN + int result = 0; + if (NULL == my_dbms[what_dbm]) { + result = x_dbminit(dbm_fn[what_dbm]); + if (!result) my_dbms[what_dbm] = my_dbm; + } else my_dbm = my_dbms[what_dbm]; + return(result); +#else + return(x_dbminit(dbm_fn[what_dbm])); +#endif +} + static int dbmclose() { if (my_dbm != NULL) { +#if !DBM_REMAINS_OPEN dbm_close(my_dbm); +#endif my_dbm = NULL; } return(0); } +void sync_dbm() +{ +#if DBM_REMAINS_OPEN + int k = 3; + while (k--) { + if (NULL != my_dbms[k]) { + dbm_close(my_dbms[k]); + my_dbms[k] = NULL; + } + } +#endif +} + + #define firstkey() dbm_firstkey(my_dbm) #define nextkey(key) dbm_nextkey(my_dbm) #define delete(key) dbm_delete(my_dbm, key) @@ -100,7 +138,7 @@ int find_obj_id(NETOBJ *o, uint32 last_obj_id) XDPRINTF((2, 0,"findobj_id OBJ=%s, type=0x%x, lastid=0x%lx", o->name, (int)o->type, last_obj_id)); - if (!dbminit(fnobj)){ + if (!dbminit(FNOBJ)){ key = firstkey(); if (last_obj_id && (last_obj_id != MAX_U32)){ @@ -142,7 +180,7 @@ static int loc_delete_property(uint32 obj_id, uint8 *prop_name, uint8 prop_id) memset(xset, 0, sizeof(xset)); if (!prop_id) { XDPRINTF((2,0, "loc_delete_property obj_id=%d, prop=%s", obj_id, prop_name)); - if (!dbminit(fnprop)){ + if (!dbminit(FNPROP)){ for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { NETPROP *p=(NETPROP*)key.dptr; if (p->obj_id == obj_id) { @@ -163,7 +201,7 @@ static int loc_delete_property(uint32 obj_id, uint8 *prop_name, uint8 prop_id) result = prop_id; } if (result > 0) { - if (!dbminit(fnval)){ + if (!dbminit(FNVAL)){ int k; NETVAL val; key.dptr = (char*)&val; @@ -182,7 +220,7 @@ static int loc_delete_property(uint32 obj_id, uint8 *prop_name, uint8 prop_id) } else result=-0xff; dbmclose(); if (result > 0) { - if (!dbminit(fnprop)){ /* now delete properties */ + if (!dbminit(FNPROP)){ /* now delete properties */ int k; NETPROP prop; key.dptr = (char*)∝ @@ -209,7 +247,7 @@ static int loc_delete_obj(uint32 objid) { int result=0; (void)loc_delete_property(objid, (uint8*)"*", 0); - if (!dbminit(fnobj)){ + if (!dbminit(FNOBJ)){ key.dptr = (char*)&objid; key.dsize = NETOBJ_KEY_SIZE; if (delete(key)) result = -0xff; @@ -232,7 +270,7 @@ int nw_rename_obj(NETOBJ *o, uint8 *newname) int result = find_obj_id(o, 0); if (!result) { result = -0xff; - if (!dbminit(fnobj)){ + if (!dbminit(FNOBJ)){ key.dsize = NETOBJ_KEY_SIZE; key.dptr = (char*)o; data = fetch(key); @@ -254,7 +292,7 @@ int nw_change_obj_security(NETOBJ *o, int newsecurity) int result = find_obj_id(o, 0); if (!result) { result = -0xff; - if (!dbminit(fnobj)){ + if (!dbminit(FNOBJ)){ key.dsize = NETOBJ_KEY_SIZE; key.dptr = (char*)o; data = fetch(key); @@ -274,7 +312,7 @@ int nw_get_obj(NETOBJ *o) { int result = -0xfc; /* no Object */ XDPRINTF((2,0, "nw_get_obj von OBJ id = 0x%x", (int)o->id)); - if (!dbminit(fnobj)){ + if (!dbminit(FNOBJ)){ key.dsize = NETOBJ_KEY_SIZE; key.dptr = (char*)o; data = fetch(key); @@ -294,7 +332,7 @@ static int find_prop_id(NETPROP *p, uint32 obj_id, int last_prop_id) int result = -0xfb; /* no Property */ XDPRINTF((2,0, "find Prop id von name=0x%x:%s, lastid=%d", obj_id, p->name, last_prop_id)); - if (!dbminit(fnprop)){ + if (!dbminit(FNPROP)){ int flag = (last_prop_id) ? 0 : 1; for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { NETPROP *prop=(NETPROP*)key.dptr; @@ -325,7 +363,7 @@ static int loc_change_prop_security(NETPROP *p, uint32 obj_id) { int result = -0xfb; /* no Property */ XDPRINTF((2,0, "loc_change_prop_security Prop id von name=0x%x:%s", obj_id, p->name)); - if (!dbminit(fnprop)){ + if (!dbminit(FNPROP)){ for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { NETPROP *prop=(NETPROP*)key.dptr; if (prop->obj_id == obj_id) { @@ -357,7 +395,7 @@ static int loc_get_prop_val(uint32 obj_id, int prop_id, int segment, { int result = -0xec; /* no such Segment */ NETVAL val; - if (!dbminit(fnval)){ + if (!dbminit(FNVAL)){ key.dsize = NETVAL_KEY_SIZE; key.dptr = (char*)&val; val.obj_id = obj_id; @@ -384,7 +422,7 @@ int prop_find_member(uint32 obj_id, int prop_id, uint32 member_id) { int result = -0xea; /* no such member */ NETVAL val; - if (!dbminit(fnval)){ + if (!dbminit(FNVAL)){ key.dsize = NETVAL_KEY_SIZE; key.dptr = (char*)&val; val.obj_id = obj_id; @@ -413,7 +451,7 @@ int prop_add_member(uint32 obj_id, int prop_id, uint32 member_id) { int result = 0; /* OK */ NETVAL val; - if (!dbminit(fnval)){ + if (!dbminit(FNVAL)){ key.dsize = NETVAL_KEY_SIZE; key.dptr = (char*)&val; val.obj_id = obj_id; @@ -456,7 +494,7 @@ int prop_delete_member(uint32 obj_id, int prop_id, uint32 member_id) { int result = -0xea; /* no such member */ NETVAL val; - if (!dbminit(fnval)){ + if (!dbminit(FNVAL)){ key.dsize = NETVAL_KEY_SIZE; key.dptr = (char*)&val; val.obj_id = obj_id; @@ -492,7 +530,7 @@ int ins_prop_val(uint32 obj_id, uint8 prop_id, int segment, uint8 *property_value, int erase_segments) { int result = -0xec; /* no such Segment */ - if (!dbminit(fnval)){ + if (!dbminit(FNVAL)){ NETVAL val; int flag = 1; key.dsize = NETVAL_KEY_SIZE; @@ -748,8 +786,12 @@ int nw_get_prop_val_str(uint32 q_id, char *propname, uint8 *buff) { uint8 more_segments; uint8 property_flags; - int result=nw_get_prop_val_by_obj_id(q_id, 1, propname, strlen(propname), + uint8 loc_buff[200]; + int result; + if (NULL == buff) buff=loc_buff; + result=nw_get_prop_val_by_obj_id(q_id, 1, propname, strlen(propname), buff, &more_segments, &property_flags); + if (result > -1) { result=strlen(buff); XDPRINTF((2,0, "nw_get_prop_val_str:%s strlen=%d", propname, result)); @@ -768,7 +810,7 @@ int nw_create_obj(NETOBJ *obj, uint32 wanted_id) { int result = 0; /* OK */ XDPRINTF((2,0, "creat OBJ=%s,type=0x%x", obj->name, (int)obj->type)); - if (!dbminit(fnobj)){ + if (!dbminit(FNOBJ)){ for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { data = fetch(key); if (data.dptr){ @@ -801,7 +843,7 @@ int nw_create_obj(NETOBJ *obj, uint32 wanted_id) int nw_obj_has_prop(NETOBJ *obj) { - int result = (dbminit(fnprop)) ? -0xff : 0; + int result = (dbminit(FNPROP)) ? -0xff : 0; if (!result){ for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { NETPROP *p=(NETPROP*)key.dptr; @@ -819,7 +861,7 @@ int nw_obj_has_prop(NETOBJ *obj) int nw_create_obj_prop(NETOBJ *obj, NETPROP *prop) { int result=0; - if (!dbminit(fnprop)){ + if (!dbminit(FNPROP)){ uint8 founds[256]; memset((char*)founds, 0, sizeof(founds) ); for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { @@ -853,7 +895,6 @@ int nw_create_obj_prop(NETOBJ *obj, NETPROP *prop) return(result); } - int nw_create_prop(int object_type, uint8 *object_name, int object_namlen, uint8 *prop_name, int prop_namlen, @@ -876,35 +917,51 @@ int nw_create_prop(int object_type, return(result); } -uint32 nw_new_create_prop(uint32 wanted_id, +static int nw_new_obj(uint32 *wanted_id, + char *objname, int objtype, + int objflags, int objsecurity) +{ + NETOBJ obj; + int result; + xstrcpy(obj.name, objname); + obj.type = (uint16) objtype; + obj.flags = (uint8) objflags; + obj.security = (uint8) objsecurity; + obj.id = 0L; + result = nw_create_obj(&obj, *wanted_id); + *wanted_id = obj.id; + return(result); +} + +uint32 nw_new_obj_prop(uint32 wanted_id, char *objname, int objtype, int objflags, int objsecurity, char *propname, int propflags, int propsecurity, char *value, int valuesize) /* * creats new property value, if needed creats Object - * and the property, if valuesize == 0, then only obj or property + * and the property, + * if propname == NULL only object will be created. + * if valuesize == 0, then only obj or property * will be created, returns obj-id */ { NETOBJ obj; NETPROP prop; - if (objname && *objname){ - strmaxcpy(obj.name, objname, sizeof(obj.name)); - obj.type = (uint8)objtype; - obj.flags = (uint8)objflags; - obj.security = (uint8)objsecurity; - obj.id = 0; /* Erstmal */ - nw_create_obj(&obj, wanted_id); - } else obj.id = wanted_id; - strmaxcpy(prop.name, propname, sizeof(prop.name)); - prop.flags = (uint8)propflags; - prop.security = (uint8)propsecurity; - nw_create_obj_prop(&obj, &prop); - if (valuesize){ - uint8 locvalue[128]; - memset(locvalue, 0, sizeof(locvalue)); - memcpy(locvalue, value, min(sizeof(locvalue), valuesize)); - ins_prop_val(obj.id, prop.id, 1, locvalue, 0xff); + if (objname && *objname) + nw_new_obj(&wanted_id, objname, objtype, + objflags, objsecurity); + obj.id = wanted_id; + if (propname && *propname) { + strmaxcpy(prop.name, propname, sizeof(prop.name)); + prop.flags = (uint8)propflags; + prop.security = (uint8)propsecurity; + nw_create_obj_prop(&obj, &prop); + if (valuesize){ + uint8 locvalue[128]; + memset(locvalue, 0, sizeof(locvalue)); + memcpy(locvalue, value, min(sizeof(locvalue), valuesize)); + ins_prop_val(obj.id, prop.id, 1, locvalue, 0xff); + } } return(obj.id); } @@ -1012,19 +1069,20 @@ int nw_test_unenpasswd(uint32 obj_id, uint8 *password) } else return(-0xff); } -int nw_set_enpasswd(uint32 obj_id, uint8 *passwd) +static int nw_set_enpasswd(uint32 obj_id, uint8 *passwd, int dont_ch) { uint8 *prop_name=(uint8*)"PASSWORD"; if (passwd && *passwd) { - nw_new_create_prop(obj_id, NULL, 0, 0, 0, + if ((!dont_ch) || (nw_get_prop_val_str(obj_id, prop_name, NULL) < 1)) + nw_new_obj_prop(obj_id, NULL, 0, 0, 0, prop_name, P_FL_STAT|P_FL_ITEM, 0x44, passwd, 16); - } else + } else if (!dont_ch) (void)loc_delete_property(obj_id, prop_name, 0); return(0); } -int nw_set_passwd(uint32 obj_id, char *password) +int nw_set_passwd(uint32 obj_id, char *password, int dont_ch) { if (password && *password) { uint8 passwd[200]; @@ -1051,9 +1109,9 @@ int nw_set_passwd(uint32 obj_id, char *password) (int)passwd[14], (int)passwd[15])); #endif - return(nw_set_enpasswd(obj_id, passwd)); + return(nw_set_enpasswd(obj_id, passwd, dont_ch)); } else - return(nw_set_enpasswd(obj_id, NULL)); + return(nw_set_enpasswd(obj_id, NULL, dont_ch)); } @@ -1107,62 +1165,137 @@ static void add_pr_queue(uint32 q_id, XDPRINTF((2,0, "ADD Q=%s, V=%s, C=%s", 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, + nw_new_obj_prop(q_id, q_name, 0x3, O_FL_DYNA, 0x31, "Q_OPERATORS", P_FL_SET, 0x31, (char*)buff, 4); - nw_new_create_prop(q_id ,NULL, 0 , 0 , 0 , + nw_new_obj_prop(q_id ,NULL, 0 , 0 , 0 , "Q_DIRECTORY", P_FL_ITEM, 0x33, q_directory, strlen(q_directory)); /* this is a own property to handler the print job !!! */ - nw_new_create_prop(q_id ,NULL, 0 , 0 , 0 , + nw_new_obj_prop(q_id ,NULL, 0 , 0 , 0 , "Q_UNIX_PRINT", P_FL_ITEM| P_FL_DYNA, 0x33, q_command, strlen(q_command)); U32_TO_BE32(ge_id, buff); - nw_new_create_prop(q_id , NULL, 0 , 0 , 0 , + nw_new_obj_prop(q_id , NULL, 0 , 0 , 0 , "Q_USERS", P_FL_SET, 0x31, (char*)buff, 4); #if 0 - nw_new_create_prop(q_id , NULL, 0 , 0 , 0 , + nw_new_obj_prop(q_id , NULL, 0 , 0 , 0 , "Q_SERVERS", P_FL_SET, 0x31, NULL, 0); #endif - - } - -static void add_user(uint32 u_id, uint32 g_id, - char *name, char *unname, char *password) +static void add_user_to_group(uint32 u_id, uint32 g_id) { 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, + /* Typ Flags Security */ + nw_new_obj_prop(u_id, NULL, 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); + nw_new_obj_prop(u_id, NULL, 0 , 0 , 0 , + "SECURITY_EQUALS", P_FL_SET, 0x32, + (char*)buff, 4); + +} + +static void add_user(uint32 u_id, uint32 g_id, + char *name, char *unname, + char *password, int dont_ch) +{ + /* Typ Flags Security */ + if (nw_new_obj(&u_id, name, 0x1 , 0x0, 0x33) + && dont_ch) return; + XDPRINTF((1, 0, "Add/Change User='%s', UnixUser='%s'", + name, unname)); + add_user_to_group(u_id, g_id); if (unname && *unname) - nw_new_create_prop(u_id, NULL, 0 , 0 , 0 , + nw_new_obj_prop(u_id, NULL, 0 , 0 , 0 , "UNIX_USER", P_FL_ITEM, 0x33, (char*)unname, strlen(unname)); if (password && *password) { if (*password == '-') *password='\0'; - nw_set_passwd(u_id, password); + nw_set_passwd(u_id, password, dont_ch); } } -void nw_fill_standard(char *servername, ipxAddr_t *adr) +static void add_group(char *name, char *unname, char *password) +{ + /* Typ Flags Security */ + uint32 g_id = 0L; + (void) nw_new_obj(&g_id, name, 0x2 , 0x0, 0x31); + if (unname && *unname) + nw_new_obj_prop(g_id, NULL, 0 , 0 , 0 , + "UNIX_GROUP", P_FL_ITEM, 0x33, + (char*)unname, strlen(unname)); +} + +static int get_sys_unixname(uint8 *unixname, uint8 *sysentry) +{ + uint8 sysname[256]; + char optionstr[256]; + int founds = sscanf((char*)sysentry, "%s %s %s",sysname, unixname, optionstr); + if (founds > 1 && *unixname) { + struct stat statb; + int result = 0; + uint8 *pp = unixname + strlen(unixname); + if (founds > 2) { + uint8 *p; + for (p=optionstr; *p; p++) { + if (*p=='k') { + result=1; + break; + } + } /* for */ + } /* if */ + if (*(pp-1) != '/') *pp++ = '/'; + *pp = '.'; + *(pp+1) = '\0'; + if (stat(unixname, &statb) < 0) { + errorp(1, "stat error:unix dir for SYS:", "fname='%s'", unixname); + return(-1); + } + *pp = '\0'; + return(result); + } else return(-1); +} + +static uint8 *test_add_dir(uint8 *unixname, uint8 *pp, int shorten, + int downshift, int permiss, int gid, int uid, char *fn) +{ + struct stat stb; + strcpy((char*)pp, fn); + if (downshift) downstr(pp); + else upstr(pp); + if (stat(unixname, &stb) < 0) { + if (mkdir(unixname, 0777)< 0) + errorp(1, "mkdir error", "fname='%s'", unixname); + else { + chmod(unixname, permiss); + if (uid >-1 && gid > -1) chown(unixname, uid, gid); + XDPRINTF((1, 0, "Created dir '%s'", unixname)); + } + } + if (shorten) *pp='\0'; + else { + pp += strlen(pp); + *pp++='/'; + *pp = '\0'; + } + return(pp); +} + + +int nw_fill_standard(char *servername, ipxAddr_t *adr) /* fills the Standardproperties */ { char serverna[MAX_SERVER_NAME+2]; @@ -1176,16 +1309,22 @@ void nw_fill_standard(char *servername, ipxAddr_t *adr) uint32 ngr_id = 0x0C000001; uint32 ps1_id = 0x0D000001; #endif - FILE *f = open_nw_ini(); - ge_id = - nw_new_create_prop(ge_id, "EVERYONE", 0x2, 0x0, 0x31, - "GROUP_MEMBERS", P_FL_SET, 0x31, - NULL, 0); + FILE *f = open_nw_ini(); + int auto_ins_user = 0; + char auto_ins_passwd[100]; + int make_tests = 0; + char sysentry[256]; + sysentry[0] = '\0'; + ge_id = nw_new_obj_prop(ge_id, "EVERYONE", 0x2, 0x0, 0x31, + "GROUP_MEMBERS", P_FL_SET, 0x31, + NULL, 0); if (f){ - char buff[500]; + char buff[256]; int what; while (0 != (what =get_ini_entry(f, 0, (char*)buff, sizeof(buff)))) { - if (6 == what) { /* Server Version */ + if (1 == what && !*sysentry) { + xstrcpy(sysentry, buff); + } if (6 == what) { /* Server Version */ tells_server_version = atoi(buff); } else if (7 == what) { /* password_scheme */ int pwscheme = atoi(buff); @@ -1232,7 +1371,8 @@ void nw_fill_standard(char *servername, ipxAddr_t *adr) add_pr_queue(q1_id, name, directory, command, su_id, ge_id); q1_id++; } - } else if (12 == what || 13 == what) { /* SUPERVISOR, OTHERS */ + } else if (12 == what || 13 == what || 14 == what) { + /* SUPERVISOR, OTHERS and GROUPS*/ char nname[100]; char uname[100]; char password[100]; @@ -1241,9 +1381,19 @@ void nw_fill_standard(char *servername, ipxAddr_t *adr) upstr(nname); if (anz > 2) upstr(password); else password[0] = '\0'; - add_user((12 == what) ? su_id : 0L, ge_id, nname, - uname, password); + if (what == 14) + add_group(nname, uname, password); + else + add_user((12 == what) ? su_id : 0L, ge_id, nname, + uname, password, 0); } + } else if (15 == what) { + char buf[100]; + int anz=sscanf((char*)buff, "%s %s", buf, auto_ins_passwd); + auto_ins_user = ((anz == 2) && atoi(buf) && *auto_ins_passwd); + if (auto_ins_user) auto_ins_user = atoi(buf); + } else if (16 == what) { + make_tests = atoi(buff); } } /* while */ fclose(f); @@ -1251,13 +1401,73 @@ void nw_fill_standard(char *servername, ipxAddr_t *adr) if (servername && adr) { strmaxcpy(serverna, servername, MAX_SERVER_NAME); upstr(serverna); - nw_new_create_prop(serv_id, serverna, 0x4, O_FL_DYNA, 0x40, + nw_new_obj_prop(serv_id, serverna, 0x4, O_FL_DYNA, 0x40, "NET_ADDRESS", P_FL_ITEM | P_FL_DYNA, 0x40, (char*)adr, sizeof(ipxAddr_t)); } + if (auto_ins_user) { + struct passwd *pw; + upstr(auto_ins_passwd); + while (NULL != (pw=getpwent())) { + char nname[100]; + xstrcpy(nname, pw->pw_name); + upstr(nname); + add_user(0L, ge_id, nname, pw->pw_name, auto_ins_passwd, + (auto_ins_user == 99) ? 0 : 99); + } + endpwent(); + } + if (*sysentry) { + int result = 0; + if (make_tests) { + uint8 unixname[512]; + result = get_sys_unixname(unixname, sysentry); + if (result > -1) { + uint32 objs[2000]; /* max. 2000 User should be enough :) */ + int ocount=0; + int downshift = (result & 1); + uint8 *pp = unixname+strlen(unixname); + uint8 *ppp; + test_add_dir(unixname, pp, 1, downshift,0777, 0,0, "LOGIN"); + test_add_dir(unixname, pp, 1, downshift,0777, 0,0, "SYSTEM"); + test_add_dir(unixname, pp, 1, downshift,0777, 0,0, "PUBLIC"); + ppp=test_add_dir(unixname, pp, 0, downshift,0777, 0,0, "MAIL"); + if (!dbminit(FNOBJ)){ + for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { + data = fetch(key); + if (data.dptr) { + NETOBJ *obj=(NETOBJ*)data.dptr; + if (obj->type == 1) { + objs[ocount++] = obj->id; + if (ocount == 2000) break; + } + } + } + } + dbmclose(); + while (ocount--) { + char sx[20]; + int gid; + int uid; + sprintf(sx, "%lx", objs[ocount]); + if (!get_guid(&gid, &uid, objs[ocount])) + test_add_dir(unixname, ppp, 1, downshift, 0770, gid, uid, sx); + else { + NETOBJ obj; + obj.id = objs[ocount]; + nw_get_obj(&obj); + errorp(0, "Cannot get unix uid/gid", "User=`%s`", obj.name); + } + } + result = 0; + } + } + return(result); + } + return(-1); } -void nw_init_dbm(char *servername, ipxAddr_t *adr) +int nw_init_dbm(char *servername, ipxAddr_t *adr) /* * routine inits bindery * all dynamic objects and properties will be deletet. @@ -1269,24 +1479,27 @@ void nw_init_dbm(char *servername, ipxAddr_t *adr) uint32 objs[10000]; /* max.10000 Objekte */ uint8 props[10000]; /* max 10000 Properties */ - create_nw_db(fnobj, 0); - create_nw_db(fnprop, 0); - create_nw_db(fnval, 0); + create_nw_db(dbm_fn[FNOBJ], 0); + create_nw_db(dbm_fn[FNPROP], 0); + create_nw_db(dbm_fn[FNVAL], 0); - if (!dbminit(fnobj)){ + if (!dbminit(FNOBJ)){ for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { data = fetch(key); if (data.dptr) { NETOBJ *obj=(NETOBJ*)data.dptr; - if (obj->flags & O_FL_DYNA) /* Dynamisch */ + if ((obj->flags & O_FL_DYNA) || !obj->name[0]) { + /* dynamic or without name */ objs[anz++] = obj->id; + if (anz == 10000) break; + } } } } dbmclose(); while (anz--) loc_delete_obj(objs[anz]); /* Now delete */ anz = 0; - if (!dbminit(fnprop)){ + if (!dbminit(FNPROP)){ for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { data = fetch(key); if (data.dptr) { @@ -1294,13 +1507,16 @@ void nw_init_dbm(char *servername, ipxAddr_t *adr) if (prop->flags & P_FL_DYNA) { /* Dynamisch */ objs[anz] = prop->obj_id; props[anz++] = prop->id; + if (anz == 10000) break; } } } } dbmclose(); while (anz--) loc_delete_property(objs[anz], (char*)NULL, props[anz]); /* now delete */ - nw_fill_standard(servername, adr); + anz = nw_fill_standard(servername, adr); + sync_dbm(); + return(anz); } /* ============> this should becomes queue.c or similar < ============== */ diff --git a/nwdbm.h b/nwdbm.h index 7b5663f..65a03ef 100644 --- a/nwdbm.h +++ b/nwdbm.h @@ -1,4 +1,4 @@ -/* nwdbm.h 12-Feb-96 */ +/* nwdbm.h 22-Feb-96 */ /* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany * * This program is free software; you can redistribute it and/or modify @@ -67,6 +67,7 @@ extern int password_scheme; #define PW_SCHEME_LOGIN 2 #define PW_SCHEME_GET_KEY_FAIL 4 +extern void sync_dbm(void); extern int nw_get_prop(int object_type, uint8 *object_name, int object_namlen, @@ -171,7 +172,7 @@ extern int nw_create_prop(int object_type, int prop_flags, int prop_security); -extern uint32 nw_new_create_prop(uint32 wanted_id, +extern uint32 nw_new_obj_prop(uint32 wanted_id, char *objname, int objtype, int objflags, int objsecurity, char *propname, int propflags, int propsecurity, char *value, int valuesize); @@ -180,11 +181,11 @@ extern int get_guid(int *gid, int *uid, uint32 obj_id); extern int nw_test_passwd(uint32 obj_id, uint8 *vgl_key, uint8 *akt_key); extern int nw_test_unenpasswd(uint32 obj_id, uint8 *password); -extern int nw_set_passwd(uint32 obj_id, char *password); +extern int nw_set_passwd(uint32 obj_id, char *password, int dont_ch); extern int nw_get_q_dirname(uint32 q_id, uint8 *buff); extern int nw_get_q_prcommand(uint32 q_id, uint8 *buff); -extern void nw_fill_standard(char *servername, ipxAddr_t *adr); -extern void nw_init_dbm(char *servername, ipxAddr_t *adr); +extern int nw_fill_standard(char *servername, ipxAddr_t *adr); +extern int nw_init_dbm(char *servername, ipxAddr_t *adr); #endif diff --git a/nwroute.c b/nwroute.c index ce48897..d869070 100644 --- a/nwroute.c +++ b/nwroute.c @@ -1,4 +1,4 @@ -/* nwroute.c 08-Feb-96 */ +/* nwroute.c 09-Mar-96 */ /* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany * * This program is free software; you can redistribute it and/or modify @@ -190,10 +190,12 @@ void insert_delete_server(uint8 *name, /* Server Name */ nr->hops = 0xffff; } else if (do_delete) { nr=nw_servers[k]; + #if !FILE_SERVER_INACTIV if (!IPXCMPNODE(nr->addr.node, my_server_adr.node) || !IPXCMPNET (nr->addr.net, my_server_adr.net) ) #endif + { ins_del_bind_net_addr(nr->name, nr->typ, NULL); xfree(nr->name); @@ -394,7 +396,7 @@ void send_server_response(int respond_typ, /* respond_typ 2 = general, 4 = nearest service respond */ { IPX_DATA ipx_data; - int j=-1; + int j=-1; int tics=99; int hops=15; int entry = -1; @@ -450,8 +452,14 @@ static void send_sap_broadcast(int mode) U16_TO_BE16(SOCK_SAP, wild.sock); while (++j < anz_servers) { NW_SERVERS *nw=nw_servers[j]; - if (!nw->typ || (nw->net == nd->net && nw->hops) - || (mode == 2 && nw->hops) ) continue; /* no SAP to this NET */ + if ( !nw->typ /* server has no typ */ + || ( nw->net == nd->net && nw->hops) /* server has same net but */ + /* hops */ + || ( mode == 2 && nw->hops) ) { /* no SAP to this NET */ + XDPRINTF((3, 0, "No SAP mode=%d, to net=0x%lx for server '%s'", + mode, nd->net, nw->name)); + continue; + } memset(&ipx_data, 0, sizeof(ipx_data.sip)); strcpy(ipx_data.sip.server_name, nw->name); memcpy(&ipx_data.sip.server_adr, &(nw->addr), sizeof(ipxAddr_t)); @@ -495,10 +503,10 @@ void send_sap_rip_broadcast(int mode) /* mode=1, first trie */ /* mode=2, shutdown */ { -static int flipflop=0; +static int flipflop=1; if (mode) { - send_sap_broadcast(mode); send_rip_broadcast(mode); + send_sap_broadcast(mode); } else { if (flipflop) { send_rip_broadcast(mode); diff --git a/nwserv.c b/nwserv.c index d37a475..b75cdeb 100644 --- a/nwserv.c +++ b/nwserv.c @@ -1,4 +1,4 @@ -/* nwserv.c 10-Feb-96 */ +/* nwserv.c 10-Mar-96 */ /* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany * * This program is free software; you can redistribute it and/or modify @@ -71,49 +71,81 @@ static struct pollfd polls[NEEDED_POLLS]; static uint16 spx_diag_socket; /* SPX DIAGNOSE SOCKET */ #endif static ipxAddr_t nw386_adr; /* Address of NW-TEST Server */ -static int nw386_found = 0; -static int client_mode = 0; +static int nw386_found = 0; +static int client_mode = 0; static int ipxdebug = 0; static int pid_ncpserv = -1; +#if !CALL_NCPSERV_OVER_SOCKET static int fd_ncpserv_out = -1; /* ctrl-pipe out to ncpserv */ +#endif static int fd_ncpserv_in = -1; /* ctrl-pipe in from ncpserv */ static time_t akttime_stamp = 0; -static int broadsecs = 2048; +static int broadmillisecs = 2000; /* 2 sec */ static time_t server_down_stamp = 0; static int server_goes_down_secs = 10; +static int server_broadcast_secs = 60; static int save_ipx_routes = 0; +static uint8 *station_fn=NULL; +static int nearest_request_flag=0; + #if !FILE_SERVER_INACTIV +static void add_wdata(IPX_DATA *d, char *data, int size) +{ + memcpy(d->owndata.d.data+d->owndata.d.size, data, size); + d->owndata.d.size+=size; +} + +static void write_wdata(IPX_DATA *d, int what) +{ +#if CALL_NCPSERV_OVER_SOCKET + ipxAddr_t toaddr; +#endif + d->owndata.d.function=what; + d->owndata.d.size +=sizeof(int); +#if CALL_NCPSERV_OVER_SOCKET + memset(d->owndata.type, 0xee, 4); + memcpy(&toaddr, &my_server_adr, sizeof(ipxAddr_t)); + U16_TO_BE16(SOCK_NCP, toaddr.sock); + send_ipx_data(-1, 17, + 4 + sizeof(int)+d->owndata.d.size, (char*)d, + &toaddr, "TO NCPSERV"); +#else + write(fd_ncpserv_out, (char*) &(d->owndata.d), + sizeof(int)+d->owndata.d.size); +#endif + d->owndata.d.size=0; +} + static void write_to_ncpserv(int what, int connection, char *data, int data_size) { + IPX_DATA ipxd; + ipxd.owndata.d.size = 0; XDPRINTF((2, 0, "write_to_ncpserv what=0x%x, conn=%d, data_size=%d", what, connection, data_size)); switch (what) { case 0x5555 : /* kill connection */ - write(fd_ncpserv_out, (char*) &what, sizeof(int)); - write(fd_ncpserv_out, (char*) &connection, sizeof(int)); + add_wdata(&ipxd, (char*) &connection, sizeof(int)); break; case 0x3333 : /* 'bindery' calls */ - write(fd_ncpserv_out, (char*) &what, sizeof(int)); - write(fd_ncpserv_out, (char*) &data_size, sizeof(int)); - write(fd_ncpserv_out, data, data_size); + add_wdata(&ipxd, (char*)&data_size, sizeof(int)); + add_wdata(&ipxd, data, data_size); break; case 0xeeee : /* hup, read init */ - write(fd_ncpserv_out, (char*) &what, sizeof(int)); break; case 0xffff : /* 'down server' */ - write(fd_ncpserv_out, (char*) &what, sizeof(int)); - write(fd_ncpserv_out, (char*) &what, sizeof(int)); + add_wdata(&ipxd, (char*) &what, sizeof(int)); break; - default : break; + default : return; } + write_wdata(&ipxd, what); } #else static void write_to_ncpserv(int what, int connection, @@ -180,11 +212,15 @@ static int open_ipx_socket(uint16 sock_nr, int nr, int open_mode) static int start_ncpserv(char *nwname, ipxAddr_t *addr) { #if !FILE_SERVER_INACTIV +#if !CALL_NCPSERV_OVER_SOCKET int fds_out[2]; +#endif int fds_in[2]; int pid; - if (pipe(fds_out) < 0 || pipe(fds_in) < 0) return(-1); - +#if !CALL_NCPSERV_OVER_SOCKET + if (pipe(fds_out) < 0) return(-1); +#endif + if (pipe(fds_in) < 0) return(-1); switch (pid=fork()) { case 0 : { /* new Process */ @@ -192,10 +228,11 @@ static int start_ncpserv(char *nwname, ipxAddr_t *addr) char addrstr[100]; char pathname[300]; int j = FD_NWSERV; +#if !CALL_NCPSERV_OVER_SOCKET close(fds_out[1]); /* no need to write */ dup2(fds_out[0], 0); /* becommes stdin */ close(fds_out[0]); /* no longer needed */ - +#endif close(fds_in[0]); /* no need to read */ dup2(fds_in[1], FD_NWSERV); /* becommes fd FD_NWSERV */ close(fds_in[1]); /* no longer needed */ @@ -207,14 +244,19 @@ static int start_ncpserv(char *nwname, ipxAddr_t *addr) } break; - case -1: close(fds_out[0]); + case -1: +#if !CALL_NCPSERV_OVER_SOCKET + close(fds_out[0]); close(fds_out[1]); +#endif close(fds_in[0]); close(fds_in[1]); return(-1); /* error */ } +#if !CALL_NCPSERV_OVER_SOCKET fds_out[0] = -1; fd_ncpserv_out = fds_out[1]; +#endif fds_in[1] = -1; fd_ncpserv_in = fds_in[0]; pid_ncpserv = pid; @@ -243,8 +285,11 @@ static int start_nwclient(void) } /* =========================== WDOG =============================== */ +#ifndef _WDOG_TESTING_ +#define _WDOG_TESTING_ 0 +#endif -#ifdef _WDOG_TESTING_ +#if _WDOG_TESTING_ /* for testing */ # define WDOG_TRIE_AFTER_SEC 1 # define MAX_WDOG_TRIES 1 @@ -314,15 +359,13 @@ static void modify_wdog_conn(int conn, int mode) if (mode < 99) { c->last_time = akttime_stamp; switch (mode) { - case 1 : c->counter = MAX_WDOG_TRIES; /* quick test */ - broadsecs = 4096; + case 1 : c->counter = MAX_WDOG_TRIES; /* quick test */ break; - case 2 : c->counter = 1; /* slow test (activate)*/ - broadsecs = 4096; + case 2 : c->counter = max(2, MAX_WDOG_TRIES); /* slow test (activate)*/ break; - default : c->counter = 0; /* reset */ + default : c->counter = 0; /* reset */ break; } /* switch */ } else if (mode == 99) { /* remove */ @@ -338,14 +381,15 @@ static void modify_wdog_conn(int conn, int mode) } } -static void send_wdogs(void) +static void send_wdogs(int force) { int k = hi_conn; while (k--) { CONN *c = &(conns[k]); if (c->last_time) { time_t t_diff = akttime_stamp - c->last_time; - if (c->counter || t_diff > WDOG_TRIE_AFTER_SEC) { /* max. 5 minutes */ + if ( (c->counter && (t_diff > 50 || force)) + || t_diff > WDOG_TRIE_AFTER_SEC) { /* max. 5 minutes */ if (c->counter > MAX_WDOG_TRIES) { /* now its enough with trying */ /* clear connection */ @@ -389,6 +433,61 @@ void get_server_data(char *name, XDPRINTF((2,0,"NW386 %s found at:%s", name, visable_ipx_adr(adr))); } +static int name_match(uint8 *s, uint8 *p) +{ + uint8 pc; + while ( (pc = *p++) != 0){ + switch (pc) { + case '?' : if (!*s++) return(0); /* simple char */ + break; + + case '*' : if (!*p) return(1); /* last star */ + while (*s) { + if (name_match(s, p) == 1) return(1); + ++s; + } + return(0); + + default : if (pc != *s++) return(0); /* normal char */ + break; + } /* switch */ + } /* while */ + return ( (*s) ? 0 : 1); +} + +static int find_station_match(int entry, ipxAddr_t *addr) +{ + int matched = 0; + if (station_fn && *station_fn) { + FILE *f=fopen(station_fn, "r"); + if (f) { + char buff[200]; + char addrstring[100]; + int what; + ipx_addr_to_adr(addrstring, addr); + upstr(addrstring); + while (0 != (what = get_ini_entry(f, 0, buff, sizeof(buff)))){ + if (what == entry) { + char *p = buff + strlen(buff); + while (p-- > buff && *p==32) *p='\0'; + upstr(buff); + if (name_match(addrstring, buff)) { + matched=1; + break; + } + } + } + fclose(f); + } else { + XDPRINTF((3, 0, "find_station_match, cannot open '%s'", + station_fn)); + } + } + XDPRINTF((3, 0, "find_station_match entry=%d, matched=%d, addr=%s", + entry, matched, visable_ipx_adr(addr))); + return(matched); +} + static void handle_sap(int fd, int ipx_pack_typ, int data_len, @@ -402,7 +501,19 @@ static void handle_sap(int fd, XDPRINTF((2,0,"SAP NEAREST SERVER request typ=%d von %s", server_type, visable_ipx_adr(from_addr))); /* Get Nearest File Server */ - send_server_response(4, server_type, from_addr); + if (!nearest_request_flag) + send_server_response(4, server_type, from_addr); +#if INTERNAL_RIP_SAP + else { + int do_sent = (nearest_request_flag == 1) ? 1 : 0; + if (find_station_match(1, from_addr)) do_sent = !do_sent; + + if (do_sent) + send_server_response(4, server_type, from_addr); + XDPRINTF((3,0, "SAP NEAREST REQUEST =%d, nearest_request_flag=%d", + do_sent, nearest_request_flag)); + } +#endif } else if (query_type == 1) { /* general Request */ XDPRINTF((2,0, "SAP GENERAL request server_type =%d", server_type)); send_server_response(2, server_type, from_addr); @@ -755,6 +866,12 @@ static void get_ini(int full) server_goes_down_secs = 10; break; + case 211 : server_broadcast_secs=atoi(inhalt); + if (server_broadcast_secs < 10 || + server_broadcast_secs > 600) + server_broadcast_secs = 60; + break; + case 300 : print_route_tac=atoi(inhalt); break; @@ -767,6 +884,12 @@ static void get_ini(int full) case 310 : wdogs_till_tics=atoi(inhalt); break; + case 400 : new_str(station_fn, (uint8*)inhalt); + break; + + case 401 : nearest_request_flag=atoi(inhalt); + break; + default : break; } /* switch */ } /* if */ @@ -777,6 +900,11 @@ static void get_ini(int full) if (print_route_tac && !pr_route_info_fn && !*pr_route_info_fn) print_route_tac = 0; if (!print_route_tac) xfree(pr_route_info_fn); + +#if INTERNAL_RIP_SAP + server_broadcast_secs /= 2; +#endif + if (full) { #ifdef LINUX # if INTERNAL_RIP_SAP @@ -828,15 +956,17 @@ static void close_all(void) if (pid_ncpserv > 0) { int status; +#if !CALL_NCPSERV_OVER_SOCKET if (fd_ncpserv_out > -1) { close(fd_ncpserv_out); fd_ncpserv_out =-1; } +#endif if (fd_ncpserv_in > -1) { close(fd_ncpserv_in); fd_ncpserv_in = -1; } - kill(pid_ncpserv, SIGTERM); /* terminate ncpserv */ + kill(pid_ncpserv, SIGQUIT); /* terminate ncpserv */ waitpid(pid_ncpserv, &status, 0); kill(pid_ncpserv, SIGKILL); /* kill ncpserv */ } @@ -869,7 +999,7 @@ static void down_server(void) fprintf(stderr, "\n*********************************************\n"); sleep(1); fprintf(stderr, "\007\n"); - broadsecs=100; + broadmillisecs = 100; server_down_stamp = akttime_stamp; send_down_broadcast(); } @@ -908,6 +1038,8 @@ static void set_sigs(void) signal(SIGHUP, sig_hup); } +static int server_is_down=0; + int main(int argc, char **argv) { int j = -1; @@ -915,7 +1047,7 @@ int main(int argc, char **argv) if (argc > 1) client_mode=1; /* in client mode the testprog 'nwclient' will be startet. */ - init_tools(NWSERV); + init_tools(NWSERV, 0); get_ini(1); while (++j < NEEDED_POLLS) { @@ -955,12 +1087,12 @@ int main(int argc, char **argv) &my_server_adr, &server_adr_sap, 0, 0, 0); } #endif - - while (1) { - int anz_poll = poll(polls, NEEDED_POLLS, broadsecs); + while (!server_is_down) { + int anz_poll = poll(polls, NEEDED_POLLS, broadmillisecs); + int call_wdog=0; time(&akttime_stamp); if (fl_get_int) { - if (fl_get_int == 1) handle_hup_reqest(); + if (fl_get_int == 1) handle_hup_reqest(); else if (fl_get_int == 2) down_server(); } if (anz_poll > 0) { /* i have to work */ @@ -1006,6 +1138,7 @@ int main(int argc, char **argv) && sizeof(int) == read(fd_ncpserv_in, (char*)&what, sizeof(what))) modify_wdog_conn(conn, what); + if (what > 0 && what < 99) call_wdog++; break; case 0x6666 : /* bcast message */ @@ -1035,25 +1168,29 @@ int main(int argc, char **argv) } else { XDPRINTF((99,0,"POLLING ...")); } + if (server_down_stamp) { - if (akttime_stamp - server_down_stamp > server_goes_down_secs) break; + if (akttime_stamp - server_down_stamp > server_goes_down_secs) + server_is_down++; } else { - if (akttime_stamp - broadtime > (broadsecs / 1000)) { /* ca. 30 seconds */ - send_sap_rip_broadcast((broadsecs<3000) ? 1 :0); /* firsttime broadcast */ - if (broadsecs < 30000) { + int bsecs = broadmillisecs / 1000; + int difftime = akttime_stamp - broadtime; + if (difftime > bsecs) { + send_sap_rip_broadcast((bsecs < 3) ? 1 : 0); /* firsttime broadcast */ + if (bsecs < server_broadcast_secs) { rip_for_net(MAX_U32); get_servers(); - broadsecs *= 2; - if (broadsecs > 30000) -#if INTERNAL_RIP_SAP - broadsecs = 30000; /* every 30 sec. */ -#else - broadsecs = 60000; /* every 60 sec. */ -#endif + bsecs *= 2; + if (bsecs > server_broadcast_secs) + bsecs=server_broadcast_secs; + broadmillisecs = bsecs*1000+10; } - send_wdogs(); + send_wdogs(call_wdog); broadtime = akttime_stamp; - } else if (client_mode) get_servers(); /* Here more often */ + } else { + if (call_wdog) send_wdogs(1); + if (client_mode && difftime > 5) get_servers(); /* Here more often */ + } } } /* while */ send_down_broadcast(); diff --git a/tools.c b/tools.c index 467ea23..d4d7a53 100644 --- a/tools.c +++ b/tools.c @@ -1,4 +1,4 @@ -/* tools.c 22-Jan-96 */ +/* tools.c 09-Mar-96 */ /* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany * * This program is free software; you can redistribute it and/or modify @@ -29,7 +29,8 @@ extern char _sys_errlist[]; int nw_debug=0; FILE *logfile=stdout; -static int in_module=0; /* in which process i am ? */ +static int in_module=0; /* in which process i am ? */ +static int connection=0; /* which connection (nwconn) */ static char *modnames[] = { "???????", "NWSERV ", @@ -46,7 +47,7 @@ char *xmalloc(uint size) { char *p = (size) ? (char *)malloc(size) : (char*)NULL; if (p == (char *)NULL && size){ - fprintf(logfile, "not enough core, need %d Bytes\n", size); + errorp(1, "xmalloc", "not enough core, need %d Bytes\n", size); exit(1); } return(p); @@ -67,7 +68,7 @@ void x_x_xfree(char **p) } } -int strmaxcpy(uint8 *dest, uint8 *source, int len) +int strmaxcpy(uint8 *dest, uint8 *source, int len) { int slen = (source != (uint8 *)NULL) ? min(len, strlen((char*)source)) : 0; if (slen) memcpy(dest, source, slen); @@ -103,7 +104,7 @@ void xdprintf(int dlevel, int mode, char *p, ...) { va_list ap; if (nw_debug >= dlevel) { - if (!(mode & 1)) fprintf(logfile, "%s:", get_modstr()); + if (!(mode & 1)) fprintf(logfile, "%s %d:", get_modstr(), connection); if (p) { va_start(ap, p); vfprintf(logfile, p, ap); @@ -117,18 +118,24 @@ void xdprintf(int dlevel, int mode, char *p, ...) void errorp(int mode, char *what, char *p, ...) { va_list ap; - int errnum = errno; - if (errnum >= 0 && errnum < _sys_nerr) - fprintf(logfile, "%s:%s:%s\n", get_modstr(), what, _sys_errlist[errnum]); - else - fprintf(logfile, "%s:%s:errno=%d\n", get_modstr(), what, errnum); - if (p) { - va_start(ap, p); - vfprintf(logfile, p, ap); - va_end(ap); - fprintf(logfile, "\n"); + int errnum = errno; + FILE *lologfile = logfile; + while (1) { + if (mode) fprintf(lologfile, "\n!! %s %d:PANIC !!\n", get_modstr(), connection); + if (errnum >= 0 && errnum < _sys_nerr) + fprintf(lologfile, "%s %d:%s:%s\n", get_modstr(), connection, what, _sys_errlist[errnum]); + else + fprintf(lologfile, "%s %d:%s:errno=%d\n", get_modstr(), connection, what, errnum); + if (p) { + va_start(ap, p); + vfprintf(lologfile, p, ap); + va_end(ap); + fprintf(lologfile, "\n"); + } + fflush(lologfile); + if ((!mode) || (lologfile == stderr)) break; + else lologfile = stderr; } - fflush(logfile); } FILE *open_nw_ini(void) @@ -218,7 +225,7 @@ static void sig_segv(int isig) exit(99); } -void init_tools(int module) +void init_tools(int module, int conn) { char buff[300]; char logfilename[300]; @@ -226,7 +233,8 @@ void init_tools(int module) int withlog=0; int dodaemon=0; int new_log=0; - in_module = module; + in_module = module; + connection = conn; if (f) { int what; while (0 != (what=get_ini_entry(f, 0, buff, sizeof(buff)))) { /* daemonize */ diff --git a/tools.h b/tools.h index 529bec9..970445c 100644 --- a/tools.h +++ b/tools.h @@ -1,4 +1,4 @@ -/* tools.h : 10-Feb-96 */ +/* tools.h : 10-Mar-96 */ /* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany * @@ -46,7 +46,7 @@ extern int get_ini_entry(FILE *f, int entry, char *str, int strsize); 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 void init_tools(int module, int conn); extern uint8 down_char(uint8 ch); extern uint8 up_char(uint8 ch);