mars_nwe-0.97.pl03

This commit is contained in:
Mario Fetka 2011-11-13 00:38:56 +01:00
parent 55682d7171
commit da30e32a01
53 changed files with 3233 additions and 1225 deletions

View File

@ -7,7 +7,7 @@ VPATH=
V_VPATH=..
OBJDIR=obj
all: rmeflag mk.li config.h nw.ini
all: rmeflag mk.li config.h nw.ini
@if [ -r .eflag ] ; then \
echo ""; \
echo "********************************************************"; \
@ -26,6 +26,9 @@ all: rmeflag mk.li config.h nw.ini
echo "********************************************************" ; \
echo ""; echo "" ; fi ) fi
routed:
./mk.li $@
install:
./mk.li $@

4
README
View File

@ -23,3 +23,7 @@ Topics for the list:
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".

329
connect.c
View File

@ -1,4 +1,4 @@
/* connect.c 20-Mar-96 */
/* connect.c 04-May-96 */
/* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
@ -17,13 +17,11 @@
*/
#include "net.h"
#include "unxfile.h"
#include <dirent.h>
#include <utime.h>
#include <sys/errno.h>
extern int errno;
/* #define TEST_FNAME "PRINT.000"
*/
#ifdef TEST_FNAME
@ -61,9 +59,10 @@ static char *build_unix_name(NW_PATH *nwpath, int modus)
static char unixname[300]; /* must be big enouugh */
int volume = nwpath->volume;
char *p, *pp;
if (volume < 0 || volume >= used_nw_volumes) {
fprintf(stderr, "build_unix_name volume=%d not ok\n", volume);
strcpy(unixname, "ZZZZZZZZZZZZ"); /* vorsichthalber */
if (volume < 0 || volume >= used_nw_volumes
|| !nw_volumes[volume].unixnamlen) {
errorp(0, "build_unix_name", "volume=%d not ok\n", volume);
strcpy(unixname, "Z/Z/Z/Z"); /* */
return(unixname);
}
strcpy(unixname, (char*)nw_volumes[volume].unixname); /* first UNIXNAME VOLUME */
@ -73,8 +72,14 @@ static char *build_unix_name(NW_PATH *nwpath, int modus)
p += strlen((char*)nwpath->path);
if ( (!(modus & 1)) && nwpath->fn[0])
strcpy(p, (char*)nwpath->fn); /* and now fn */
else if ((modus & 2) && (*(p-1) == '/')) *(p-1) = '\0';
if (nw_volumes[volume].options & 1) downstr((uint8*)pp);
else if ((modus & 2) && (*(p-1) == '/')) {
if (p > unixname+1) *(--p) = '\0';
else {
*p++ = '.';
*p = '\0';
}
}
if (nw_volumes[volume].options & VOL_OPTION_DOWNSHIFT) downstr((uint8*)pp);
return(unixname);
}
@ -201,7 +206,7 @@ static int x_str_match(uint8 *s, uint8 *p)
switch (state){
case 0 :
switch (pc) {
case 255: if (*p == '*' || *p == '?') continue;
case 255: if (*p == '*' || *p == '?' || *p==0xaa || *p==0xae) continue;
break;
case '\\': /* beliebiges Folgezeichen */
@ -273,7 +278,7 @@ static int x_str_match(uint8 *s, uint8 *p)
return ( (*s) ? 0 : 1);
}
int fn_match(uint8 *s, uint8 *p, uint8 options)
int fn_match(uint8 *s, uint8 *p, int options)
{
uint8 *ss=s;
int len=0;
@ -284,7 +289,7 @@ int fn_match(uint8 *s, uint8 *p, uint8 options)
len=0;
} else {
if ((pf && len > 3) || len > 8) return(0);
if (options & 1){ /* only downshift chars */
if (options & VOL_OPTION_DOWNSHIFT){ /* only downshift chars */
if (*ss >= 'A' && *ss <= 'Z') return(0);
} else { /* only upshift chars */
if (*ss >= 'a' && *ss <= 'z') return(0);
@ -312,7 +317,7 @@ static int func_search_entry(NW_PATH *nwpath, int attrib,
char xkpath[256];
uint8 entry[256];
int volume = nwpath->volume;
uint8 soptions;
int soptions;
FUNC_SEARCH fs_local;
if (!fs) {
fs = &fs_local;
@ -322,7 +327,7 @@ static int func_search_entry(NW_PATH *nwpath, int attrib,
if (volume < 0 || volume >= used_nw_volumes) return(-1); /* something wrong */
else soptions = nw_volumes[volume].options;
strcpy((char*)entry, (char*)nwpath->fn);
if (soptions & 1) downstr(entry); /* now downshift chars */
if (soptions & VOL_OPTION_DOWNSHIFT) downstr(entry); /* now downshift chars */
nwpath->fn[0] = '\0';
strcpy(xkpath, build_unix_name(nwpath, 1|2));
@ -347,7 +352,7 @@ static int func_search_entry(NW_PATH *nwpath, int attrib,
|| ( ( (fs->statb.st_mode & S_IFMT) != S_IFDIR) && !(attrib & 0x10)));
if (okflag){
strcpy((char*)nwpath->fn, (char*)name);
if (soptions & 1) upstr(nwpath->fn);
if (soptions & VOL_OPTION_DOWNSHIFT) upstr(nwpath->fn);
XDPRINTF((5,0,"FOUND=:%s: attrib=0x%x", nwpath->fn, fs->statb.st_mode));
result = (*fs_func)(nwpath, fs);
if (result < 0) break;
@ -376,11 +381,11 @@ static int get_dir_entry(NW_PATH *nwpath,
char xkpath[256];
uint8 entry[256];
int volume = nwpath->volume;
uint8 soptions;
int soptions;
if (volume < 0 || volume >= used_nw_volumes) return(0); /* something wrong */
else soptions = nw_volumes[volume].options;
strcpy((char*)entry, (char*)nwpath->fn);
if (soptions & 1) downstr(entry); /* now downshift chars */
if (soptions & VOL_OPTION_DOWNSHIFT) downstr(entry); /* now downshift chars */
nwpath->fn[0] = '\0';
strcpy(xkpath, build_unix_name(nwpath, 1|2));
@ -409,7 +414,7 @@ static int get_dir_entry(NW_PATH *nwpath,
|| ( ( (statb->st_mode & S_IFMT) != S_IFDIR) && !(attrib & 0x10)));
if (okflag){
strcpy((char*)nwpath->fn, (char*)name);
if (soptions & 1) upstr(nwpath->fn);
if (soptions & VOL_OPTION_DOWNSHIFT) upstr(nwpath->fn);
XDPRINTF((5,0,"FOUND=:%s: attrib=0x%x", nwpath->fn, statb->st_mode));
break; /* ready */
}
@ -457,7 +462,7 @@ static int get_dh_entry(DIR_HANDLE *dh,
uint8 entry[256];
strmaxcpy(entry, search, 255);
if (dh->vol_options & 1) downstr(entry);
if (dh->vol_options & VOL_OPTION_DOWNSHIFT) downstr(entry);
if ( (uint16)*sequence == MAX_U16) *sequence = 0;
seekdir(f, (long) *sequence);
@ -483,7 +488,7 @@ static int get_dh_entry(DIR_HANDLE *dh,
|| (((statb->st_mode & S_IFMT) != S_IFDIR) && !(attrib & 0x10)));
if (okflag){
strcpy((char*)search, (char*)name);
if (dh->vol_options & 1) upstr(search);
if (dh->vol_options & VOL_OPTION_DOWNSHIFT) upstr(search);
break; /* ready */
}
} else okflag = 0;
@ -907,7 +912,7 @@ int nw_mk_rd_dir(int dir_handle, uint8 *data, int len, int mode)
d++;
}
completition = 0;
} else if (errno & EEXIST)
} else if (errno == EEXIST)
completition = -0xa0; /* dir not empty */
else completition = -0x8a; /* No privilegs */
}
@ -942,9 +947,9 @@ int mv_file(int qdirhandle, uint8 *q, int qlen,
unlink(unziel);
}
} else {
if (errno & EEXIST)
completition=-0x91; /* allready exist */
else if (errno & EXDEV)
if (errno == EEXIST)
completition=-0x92; /* allready exist */
else if (errno == EXDEV)
completition=-0x9a; /* cross devices */
else completition=-0x9c; /* wrong path */
}
@ -953,6 +958,42 @@ int mv_file(int qdirhandle, uint8 *q, int qlen,
return(completition);
}
int mv_dir(int dir_handle, uint8 *q, int qlen,
uint8 *z, int zlen)
{
NW_PATH quellpath;
NW_PATH zielpath;
int completition=conn_get_kpl_path(&quellpath, dir_handle, q, qlen, 0);
if (!completition > -1){
memcpy(&zielpath, &quellpath, sizeof(NW_PATH));
strmaxcpy(zielpath.fn, z, zlen);
if (completition > -1) {
if (get_volume_options(quellpath.volume, 1) &
VOL_OPTION_IS_PIPE)
completition = -0x9c;
}
if (completition > -1){
int result;
char unquelle[256];
char unziel[256];
strcpy(unquelle, build_unix_name(&quellpath, 0));
strcpy(unziel, build_unix_name(&zielpath, 0));
result = unx_mvdir((uint8 *)unquelle, (uint8 *)unziel);
XDPRINTF((2,0, "rendir result=%d, '%s'->'%s'",
result, unquelle, unziel));
if (!result)
completition = 0;
else {
if (result == EEXIST)
completition=-0x92; /* allready exist */
else if (result == EXDEV)
completition=-0x9a; /* cross devices */
else completition=-0x9c; /* wrong path */
}
}
}
return(completition);
}
static int change_dir_entry( NW_DIR *dir, int volume,
uint8 *path, ino_t inode,
@ -1077,7 +1118,7 @@ int nw_free_handles(int task)
return(0);
}
int insert_new_dir(NW_PATH *nwpath, int inode, int drive, int is_temp, int task)
int xinsert_new_dir(int volume, uint8 *path, int inode, int drive, int is_temp, int task)
{
int j = 0;
time_t lowtime = time(NULL);
@ -1088,7 +1129,7 @@ int insert_new_dir(NW_PATH *nwpath, int inode, int drive, int is_temp, int task)
for (j = 0; j < (int)used_dirs; j++) {
NW_DIR *d = &(dirs[j]);
if (d->inode && !is_temp && !d->is_temp && (int)d->drive == drive) {
(void)change_dir_entry(d, nwpath->volume, nwpath->path, inode, drive, is_temp, 1, task);
(void)change_dir_entry(d, volume, path, inode, drive, is_temp, 1, task);
return(++j);
} else if (!d->inode) freehandle = j+1;
else if (d->is_temp && d->timestamp < lowtime) {
@ -1100,13 +1141,20 @@ int insert_new_dir(NW_PATH *nwpath, int inode, int drive, int is_temp, int task)
if (!freehandle) freehandle = timedhandle;
if (freehandle){
(void)change_dir_entry(&(dirs[freehandle-1]),
nwpath->volume, nwpath->path, inode,
volume, path, inode,
drive, is_temp, 1, task);
while (used_dirs > freehandle && !dirs[used_dirs-1].inode) used_dirs--;
return(freehandle);
} else return(-0x9d); /* no dir Handles */
}
int insert_new_dir(NW_PATH *nwpath, int inode, int drive, int is_temp, int task)
{
return(xinsert_new_dir(nwpath->volume, nwpath->path,
inode, drive, is_temp, task));
}
int nw_search(uint8 *info,
int dirhandle, int searchsequence,
int search_attrib, uint8 *data, int len)
@ -1556,232 +1604,5 @@ int nw_scan_a_root_dir(uint8 *rdata,
} else return(completition); /* wrong path */
}
/* <======================================================================> */
/* minimal queue handling to enable very simple printing */
/* qick and dirty !!!!!!!!!!!!!!! */
#define MAX_JOBS 5 /* max. open queue jobs for one connection */
static int anz_jobs=0;
typedef struct {
uint32 fhandle;
int old_job; /* is old structure */
union {
QUEUE_JOB n;
QUEUE_JOB_OLD o;
} q;
} INT_QUEUE_JOB;
INT_QUEUE_JOB *queue_jobs[MAX_JOBS];
static INT_QUEUE_JOB *give_new_queue_job(int old_job)
{
int k=-1;
while (++k < anz_jobs) {
INT_QUEUE_JOB *p=queue_jobs[k];
if (!p->fhandle) { /* free slot */
memset(p, 0, sizeof(INT_QUEUE_JOB));
p->old_job = old_job;
if (old_job)
p->q.o.job_id[0] = k+1;
else
p->q.n.job_id[0] = k+1;
return(p);
}
}
if (anz_jobs < MAX_JOBS) {
INT_QUEUE_JOB **pp=&(queue_jobs[anz_jobs++]);
*pp = (INT_QUEUE_JOB *) xmalloc(sizeof(INT_QUEUE_JOB));
memset(*pp, 0, sizeof(INT_QUEUE_JOB));
(*pp)->old_job = old_job;
if (old_job)
(*pp)->q.o.job_id[0] = anz_jobs;
else
(*pp)->q.n.job_id[0] = anz_jobs;
return(*pp);
}
return(NULL);
}
static void free_queue_job(int q_id)
{
if (q_id > 0 && q_id <= anz_jobs) {
INT_QUEUE_JOB **pp=&(queue_jobs[q_id-1]);
uint32 fhandle = (*pp)->fhandle;
if (fhandle > 0) nw_close_datei(fhandle, 1);
if (q_id == anz_jobs) {
xfree(*pp);
--anz_jobs;
} else (*pp)->fhandle=0L;
}
}
static void set_entry_time(uint8 *entry_time)
{
struct tm *s_tm;
time_t timer;
time(&timer);
s_tm = localtime(&timer);
entry_time[0] = (uint8) s_tm->tm_year;
entry_time[1] = (uint8) s_tm->tm_mon+1;
entry_time[2] = (uint8) s_tm->tm_mday;
entry_time[3] = (uint8) s_tm->tm_hour;
entry_time[4] = (uint8) s_tm->tm_min;
entry_time[5] = (uint8) s_tm->tm_sec;
}
static int create_queue_file(uint8 *job_file_name,
uint32 q_id,
int jo_id,
int connection,
uint8 *dirname,
int dir_nam_len,
uint8 *job_bez)
{
int result;
NW_FILE_INFO fnfo;
*job_file_name
= sprintf((char*)job_file_name+1, "%07lX%d.%03d", q_id, jo_id, connection);
result=nw_alloc_dir_handle(0, dirname, dir_nam_len, 99, 2, 1);
if (result > -1)
result = nw_creat_open_file(result, job_file_name+1,
(int) *job_file_name,
&fnfo, 0x6, 0x6, 1 | 4);
XDPRINTF((5,0,"creat queue file bez=`%s` handle=%d",
job_bez, result));
return(result);
}
int nw_creat_queue(int connection, uint8 *queue_id, uint8 *queue_job,
uint8 *dirname, int dir_nam_len, int old_call)
{
INT_QUEUE_JOB *jo = give_new_queue_job(old_call);
uint32 q_id = GET_BE32(queue_id);
int result = -0xff;
XDPRINTF((5,0,"NW_CREAT_Q:dlen=%d, dirname=%s", dir_nam_len, dirname));
if (NULL != jo) {
int jo_id = 0;
if (jo->old_job) {
jo_id = (int) jo->q.o.job_id[0];
memcpy(&(jo->q.o), queue_job, sizeof(QUEUE_JOB_OLD));
jo->q.o.job_id[0] = (uint8) jo_id;
jo->q.o.client_connection = (uint8)connection;
jo->q.o.client_task = (uint8)0xfe; /* ?? */
U32_TO_BE32(1, jo->q.o.client_id); /* SU */
set_entry_time(jo->q.o.job_entry_time);
jo->q.o.job_typ[0] = 0x0; /* 0xd0;*/
jo->q.o.job_typ[1] = 0x0;
jo->q.o.job_position = 0x1;
jo->q.o.job_control_flags |= 0x20;
result = create_queue_file(jo->q.o.job_file_name,
q_id, jo_id, connection,
dirname, dir_nam_len,
jo->q.o.job_bez);
if (result > -1) {
jo->fhandle = (uint32) result;
U16_TO_BE16(0, jo->q.o.job_file_handle);
U32_TO_BE32(jo->fhandle, jo->q.o.job_file_handle+2);
result = 0;
}
jo->q.o.server_station = 0;
jo->q.o.server_task = 0;
U32_TO_BE32(0, jo->q.o.server_id);
if (!result) memcpy(queue_job, &(jo->q.o), sizeof(QUEUE_JOB_OLD));
} else {
jo_id = (int) jo->q.n.job_id[0];
memcpy(&(jo->q.n), queue_job, sizeof(QUEUE_JOB));
jo->q.n.job_id[0] = (uint8) jo_id;
U16_TO_BE16(0xffff, jo->q.n.record_in_use);
U32_TO_BE32(0x0, jo->q.n.record_previous);
U32_TO_BE32(0x0, jo->q.n.record_next);
memset(jo->q.n.client_connection, 0, 4);
jo->q.n.client_connection[0] = (uint8)connection;
memset(jo->q.n.client_task, 0, 4);
jo->q.n.client_task[0] = (uint8)0xfe; /* ?? */
U32_TO_BE32(1, jo->q.n.client_id); /* SU */
set_entry_time(jo->q.n.job_entry_time);
jo->q.n.job_typ[0] = 0x0; /* 0xd0;*/
jo->q.n.job_typ[1] = 0x0;
jo->q.n.job_position[0] = 0x1;
jo->q.n.job_position[1] = 0x0;
jo->q.n.job_control_flags[0] |= 0x20;
jo->q.n.job_control_flags[1] = 0x0;
result = create_queue_file(jo->q.n.job_file_name,
q_id, jo_id, connection,
dirname, dir_nam_len,
jo->q.n.job_bez);
if (result > -1) {
jo->fhandle = (uint32) result;
U32_TO_BE32(jo->fhandle, jo->q.n.job_file_handle);
result = 0;
}
U32_TO_BE32(0, jo->q.n.server_station);
U32_TO_BE32(0, jo->q.n.server_task);
U32_TO_BE32(0, jo->q.n.server_id);
if (!result) memcpy(queue_job, &(jo->q.n), sizeof(QUEUE_JOB));
}
if (result) free_queue_job(jo_id);
}
return(result);
}
int nw_close_file_queue(uint8 *queue_id,
uint8 *job_id,
uint8 *prc, int prc_len)
{
int result = -0xff;
int jo_id = (int) *job_id; /* ever only the first byte */
XDPRINTF((5,0,"nw_close_file_queue JOB=%d", jo_id));
if (jo_id > 0 && jo_id <= anz_jobs){
INT_QUEUE_JOB *jo=queue_jobs[jo_id-1];
int fhandle = (int)jo->fhandle;
char unixname[300];
strmaxcpy((uint8*)unixname, (uint8*)file_get_unix_name(fhandle), sizeof(unixname)-1);
XDPRINTF((5,0,"nw_close_file_queue fhandle=%d", fhandle));
if (*unixname) {
char printcommand[256];
FILE *f=NULL;
strmaxcpy((uint8*)printcommand, prc, prc_len);
nw_close_datei(fhandle, 1);
jo->fhandle = 0L;
if (NULL != (f = fopen(unixname, "r"))) {
int is_ok = 0;
FILE *fout = popen(printcommand, "w");
if (fout) {
char buff[1024];
int k;
is_ok++;
while ((k = fread(buff, 1, sizeof(buff), f)) > 0) {
if (1 != fwrite(buff, k, 1, fout)) {
XDPRINTF((1,0,"Cannot write to pipe `%s`", printcommand));
is_ok=0;
}
}
pclose(fout);
} else
XDPRINTF((1,0,"Cannot open pipe `%s`", printcommand));
fclose(f);
if (is_ok) {
unlink(unixname);
result=0;
}
} else XDPRINTF((1,0,"Cannot open queue-file `%s`", unixname));
} else
XDPRINTF((2,0,"fhandle=%d NOT OK !", fhandle));
free_queue_job(jo_id);
}
return(result);
}

View File

@ -1,4 +1,4 @@
/* connect.h 10-Mar-96 */
/* connect.h 04-May-96 */
#ifndef _CONNECT_H_
#define _CONNECT_H_
typedef struct {
@ -7,8 +7,8 @@ typedef struct {
ino_t inode; /* Unix Inode */
time_t timestamp; /* f<>r letzte Allocierung */
char *kpath; /* Ein Zeichen nach unixname */
uint8 vol_options; /* Suchoptions */
uint8 volume; /* Volume Number */
int vol_options; /* Suchoptions */
int volume; /* Volume Number */
} DIR_HANDLE;
typedef struct {
@ -69,7 +69,8 @@ extern int nw_chmod_datei(int dir_handle, uint8 *data, int len, int modus);
extern int mv_file(int qdirhandle, uint8 *q, int qlen,
int zdirhandle, uint8 *z, int zlen);
extern int mv_dir(int dir_handle, uint8 *q, int qlen,
uint8 *z, int zlen);
extern int nw_mk_rd_dir(int dir_handle, uint8 *data, int len, int mode);
@ -86,6 +87,9 @@ extern int nw_find_dir_handle( int dir_handle,
uint8 *data, /* zus„tzlicher Pfad */
int len); /* L„nge Pfad */
extern int xinsert_new_dir(int volume, uint8 *path,
int inode, int drive, int is_temp, int task);
extern int nw_alloc_dir_handle(
int dir_handle, /* Suche ab Pfad dirhandle */
uint8 *data, /* zus„tzl. Pfad */
@ -145,87 +149,7 @@ extern int nw_scan_a_root_dir(uint8 *rdata,
int dirhandle);
extern int fn_match(uint8 *s, uint8 *p, uint8 options);
/* queues */
typedef struct {
uint8 record_in_use[2];
uint8 record_previous[4];
uint8 record_next[4];
uint8 client_connection[4];
uint8 client_task[4];
uint8 client_id[4];
uint8 target_id[4]; /* 0xff, 0xff, 0xff, 0xff */
uint8 target_execute_time[6]; /* all 0xff */
uint8 job_entry_time[6]; /* all zero */
uint8 job_id[4]; /* ?? alles 0 HI-LOW */
uint8 job_typ[2]; /* z.B. Printform HI-LOW */
uint8 job_position[2]; /* ?? alles 0 low-high ? */
uint8 job_control_flags[2]; /* z.B 0x10, 0x00 */
/* 0x80 operator hold flag */
/* 0x40 user hold flag */
/* 0x20 entry open flag */
/* 0x10 service restart flag */
/* 0x08 autostart flag */
uint8 job_file_name[14]; /* len + DOS filename */
uint8 job_file_handle[4];
uint8 server_station[4];
uint8 server_task[4];
uint8 server_id[4];
uint8 job_bez[50]; /* "LPT1 Catch" */
uint8 client_area[152];
} QUEUE_JOB;
typedef struct {
uint8 client_connection;
uint8 client_task;
uint8 client_id[4];
uint8 target_id[4]; /* 0xff, 0xff, 0xff, 0xff */
uint8 target_execute_time[6]; /* all 0xff */
uint8 job_entry_time[6]; /* all zero */
uint8 job_id[2]; /* ?? alles 0 HI-LOW */
uint8 job_typ[2]; /* z.B. Printform HI-LOW */
uint8 job_position; /* zero */
uint8 job_control_flags; /* z.B 0x10 */
/* 0x80 operator hold flag */
/* 0x40 user hold flag */
/* 0x20 entry open flag */
/* 0x10 service restart flag */
/* 0x08 autostart flag */
uint8 job_file_name[14]; /* len + DOS filename */
uint8 job_file_handle[6];
uint8 server_station;
uint8 server_task;
uint8 server_id[4];
uint8 job_bez[50]; /* "LPT1 Catch" */
uint8 client_area[152];
} QUEUE_JOB_OLD; /* before 3.11 */
typedef struct {
uint8 version; /* normal 0x0 */
uint8 tabsize; /* normal 0x8 */
uint8 anz_copies[2]; /* copies 0x0, 0x01 */
uint8 print_flags[2]; /* 0x0, 0xc0 z.B. with banner */
uint8 max_lines[2]; /* 0x0, 0x42 */
uint8 max_chars[2]; /* 0x0, 0x84 */
uint8 form_name[16]; /* "UNKNOWN" */
uint8 reserved[6]; /* all zero */
uint8 banner_user_name[13]; /* "SUPERVISOR" */
uint8 bannner_file_name[13]; /* "LST:" */
uint8 bannner_header_file_name[14]; /* all zero */
uint8 file_path_name[80]; /* all zero */
} QUEUE_PRINT_AREA;
extern int nw_creat_queue(int connection, uint8 *queue_id, uint8 *queue_job,
uint8 *dirname, int dir_nam_len, int old_call);
extern int nw_close_file_queue(uint8 *queue_id,
uint8 *job_id,
uint8 *prc, int prc_len);
extern int fn_match(uint8 *s, uint8 *p, int options);
extern uint16 un_date_2_nw(time_t time, uint8 *d);

View File

@ -1,5 +1,5 @@
Sorry, this is in German only. :-(
Aenderungen in mars_nwe bis zum : 21-Mar-96
Sorry, this is in German only.
Aenderungen in mars_nwe bis zum : 07-May-96
--------------------------------
Erste 'oeffentliche' Version
^^^^^^^^^^ VERSION 0.94 ^^^^^^^^
@ -102,5 +102,22 @@ Erste 'oeffentliche' Version
OS/2 Client u. evtl. auch andere (Win95 ?) erwarten es. !
- Password Schema leicht veraendert/erweitert.
modus '8' -> modus '7', neuer modus '8'.
- neue Routine 0x17, 0x10 (set file information) codiert.
- neue Routine 0x17, 0x10 (set file information) kodiert.
- ftruncate unter Linux fuer das Verkuerzen von Dateien eingebaut.
- neuen Volumetyp HOME Dir eingebaut.
- Fehler beim Mappen von Volumes auf UNIX Root '/' korrigiert.
- Fehler ftruncate beseitigt, offset statt 0. (Eduardo Crosclaude)
- Token Ring Frame eingebaut. (Guntram Blohm)
- einfache Zugriffrechte fuer Bindery eingebaut.
- Nur noch der Supervisor (OBJ_ID=1) kann root access erlangen.
- RIP/SAP Routinen ueberarbeitet.
- automatisches Anlegen von IPX-Devices ermoeglicht.
- Routine rename dir 0x16,0xf kodiert.
- 16-Bit get Volinfo Routinen korrigiert.
- Volume Flag 'o' eingefuehrt fuer filesysteme die
Inodes > 0xfffffff liefern. (namespace-services)
- utmp und wtmp werden nun gefuellt.
- Parameter -k fuer SIGTERM und -h fuer SIGHUP eingebaut.
- eigene 'pipe' Routine fuer Druck Queue Aufruf eingebaut.
- namespace services call rename file/dir eingebaut.

14
doc/FAQS Normal file
View File

@ -0,0 +1,14 @@
Q: I don't exaclty understand the meaning of some ponits in nw.ini:
12,13
What will happen if I will not put PASSWORD here? Will it take it from
/etc/passwd? I want it to be so.
A: This passwords will be stored (crypted) into bindery to can handle
the crypted login call from a standarrd Novell client.
Q: What role plays: 15?
What if I will no supply passwd here?
A: This is for automatic inserting UNIX Users as mars_nwe users.
All of these automatic inserted users will get the password
as the crypted bindery password.

34
doc/FRAGEN Normal file
View File

@ -0,0 +1,34 @@
Sorry, this is in German only.
einige Fragen und Antworten.
F: Welche original Novell DOS Tools brauche ich.
A: Fuer eine Minimalkonfiguration ist nur das LOGIN.EXE
Programm notwendig.
folgende weitere Programme sind sinnvoll einsetzbar.
MAP.EXE : Zuweisung von Laufwerken.
CAPTURE.EXE : Zuweisung von Druckern.
SYSCON.EXE : Verwaltungstool
es ist z.Z. auch ein DOS Client Programm in Entwicklung, welches
es erlaubt, mars_nwe ohne original NOVELL DOS Tools zu
verwenden.
F: Wird '/dev/ipx' benoetigt. Ich finde Verweise in mars_nwe.
A: Unter Linux Nein. Diese Verweise betreffen nur Systeme mit
TLI-Interfaces. z.B. UnixWare (tm).
F: Ich verstehe Eintrag '12,13' aus der ini/conf Datei nicht.
Was passiert, falls ich hier kein Passwort eintrage ?
Wird es aus der '/etc/passwd' verwendet.
A: Dieses Passwort wird verschluesselt in die Bindery eingetragen.
Passwoerter aus der '/etc/passwd' werden nur verwendet, falls
mit 'unencryted login calls' gearbeitet wird.
F: Welche Rolle spielt Eintrag '15'.
A: Dieser Eintrag steht fuer das Passwort, welches bei
dem automatischen Umwandeln Unix -> mars_nwe User allen *neu*
eingetragenen mars_nwe Benutzern als default zugewiesen
wird.

100
doc/FRAGEN.erik Normal file
View File

@ -0,0 +1,100 @@
Sorry, this is in German only.
folgende Fragen/Antworten stammen von Erik Thiele.
> Heisst das, dass mars_nwe die Novell-Partition lesen kann?
________
* NEIN * dafuer benutzt du ncpfs oder einen neuen HACKER-KERNEL
^^^^^^^^
Novell-Volume
1. 1.2.xx Kernel + NCPFS Packet client
2. 1.3.xx Kernel mit integriertem NCPFS client
3. diverse Kernel u. MARS_NWE server
4. diverse Kernel + patches u. linware server
wobei sich mars_nwe und ncpfs gleichzeitig miteinander vertragen.
> wie funktioniert das Drucken
*** SWITCHING TO THE DOS/NOVELL WORLD ***
das Drucken funktioniert bei Novell so:
jemand druckt in eine PRINT-QUEUE auf einem NOVELL-SERVER.
nun gibt es QUEUE-SERVERs. ein QUEUE-SERVER managed eine
oder mehrere PRINT-QUEUEs. Er kann den Inhalt einer PRINT-QUEUE auf eine
parallele Schnittstelle rausdrucken, oder an einen REMOTE-PRINTER schicken.
QUEUE-SERVER laufen auf DOS als alleiniger systemblockierender Prozess,
d.h. der PC kann derweil nix anderes machen, oder auf einem NOVELL-SERVER,
dort natuerlich nicht blockierenderweisse, iss ja schliesslich Multitasking.
ein REMOTE-PRINTER ist KEIN drucker der ans ethernet angeschlossen ist, sondern
ein auf einer DOS-kiste laufendes TSR (hintergrundprogramm), das ankommende
Bytes auf die parallele schnittstelle schiebt. Der PC kann derweil noch anderes
tun (oder sich aufhaengen *grins* )
*** BACK TO LINUX ***
wenn man nun in eine PRINT-QUEUE drucken will, benutzt man "nprint" aus dem
ncpfs packet. da gibt man den namen der PRINT-QUEUE sowie den Namen des
NOVELL-SERVERS an, auf dem die PRINT-QUEUE rumliegt.
will man einen drucker an eine linux kiste hinhaengen und ihn ins novell-netz
integrieren (ich hab einen DIN A0 Tintenklekser der an einer HP-workstation
haengt ueber einen LINUX rechner ins NOVELL-NETZ integriert...), so muss man
sich zunaechst entscheiden, ob die PRINT-QUEUE auf dem echten NOVELL-SERVER
sein soll, oder auf dem mars_nwe NOVELL-SERVER. Letzteres bringt probleme mit
sich bei software, die nicht in der lage ist auf eine print-queue zu drucken,
die NICHT auf dem benutzten NOVELL-FILE-SERVER ist. (Wordperfect hat das
bei mir nicht kapiert. man kann es nur so konfigurieren, dass es auf
PRINT-QUEUES druckt, die auch auf dem aktuellen NOVELL-FILE-SERVER sind.)
(Anmerkung: mittels capture funktioniert es aber immer.)
also iss es besser, die QUEUE auf dem bereits existierenden NOVELL-SERVER zu
installieren. dann laesst man noch den QUEUE-SERVER auf dem NOVELL-SERVER laufen
(pconsole), da es einen solchigen fuer Linux nicht gibt. nun muss man auf einer
linux-kiste nur noch das aequivalent zum REMOTE-PRINTER starten. ich weiss
leider nicht mehr, wie das heisst, oder wo es ist, aber ich glaube es ist
in ncpfs... (ich bin zuhause...)
(will man die PRINT-QUEUE aufm mars_nwe installieren, ist man in 3 sekunden
fertig, lies die mars_nwe dokus)
naja das ganze iss gar net soooooo schwierig :-) man muss nur kraeftig docus
lesen. und FTP starten :-)
saug dir einfach alle IPX-tools und NETWARE-speziefischen sachen vom sunsite.
>Ich habe mir mal vor kurzem mars_nwe angesehen, leider ist kein Readme dabei,
>welches die Features beschreibt.
stimmt absolut nicht !!! (schau dir mal die configurationsdatei an :-))))
>Kann mars_nwe auch bootserver spielen? Da in unserem Schulrechnerraum nur
>ein einziger >386"-er Rechner da ist, wollte ich unter Linux die restlichen
>10 286'er booten lassen. Kann mars_nwe sich hierbei komplett wie der echte
>Novellserver verhalten?
ich habe aehnliches problem, allerdings vertagt. BOOT-ROM rechner machen unter
umstaenden ein paar calls, die der mars_nwe noch nicht vertraegt. aber
ansonsten loggen sie sich einfach auf dem ding ein und laden dateien
an definierten positionen. -> mars_nwe muesste das auch koennen.
wenn es nicht geht, liegt das an eben diesen calls.
es gibt einen der heisst SAP_GET_NEAREST_SERVER.
diesen kann man beim NEUEN mars_nwe ausschalten, damit nur noch der Original
Novell-server auf diesen call reagiert. wenn man naemlich auf der DOS-kiste
den NETX.COM laedt, dann loggt sich das teil automatisch auf dem server ein,
der als ersten den call beantwortet. (der novell server gewinnt immer das
rennen, aber wenn er mal ein bischen busy ist,.... man weiss ja nie !)
abhilfe schafft da eben die option, den call abzuschaffen, oder bei
NETX die option /PS=eumel hinzufuegen, dann loggt er sich nur auf dem "eumel"
ein.
WENN MAN ABER DEN CALL ABSCHAFFT, DANN KOENNEN DIE BOOT-ROM RECHNER EINEN
NICHT MEHR IM NETZ FINDEN !!!! DAS ist ein saudummes problem.
der author sagte aber er wolle es beheben, durch eine liste von
rechnern im configurationsfile, die den call beantwortet kriegen, und
solche, die ihn nicht beantwortet kriegen. allerdings ist wie oben gesagt
der Novell-server immer schneller, so dass der Novell-server hardwaremaessig
von den boot-rom kisten getrennt werden muss, und dann bringt auch die liste
nix mehr...

View File

@ -7,8 +7,25 @@ You can configure mars_nwe in two ways.
of mars_nwe, dosemu, ncpfs or Caldera's nwclient was tested.
-> you must use kernel < 1.3.60 or use kernel >= 1.3.60 and compile
your kernel with IPX-option CONFIG_IPX_INTERN=N
This do NOT mean 'no internal net' but 'no *full* internal net'.
In mars_nwe/config.h there must exist the following line:
#define INTERNAL_RIP_SAP 1
If you have other IPX/NCP servers in your net you can let
your external nets configured automaticly.
To do this you must use internal net: entry '3' must be filled
with a *UNIQUE* NetNumber and you must place minimal one
entry '4' with '0' as networknumber, device = '*' and frame=auto.
example for conf/ini file: (see also examples/nw.ini):
3 0x77777 # UNIQUE network number for internal net.
4 0x0 * AUTO # autocreat Interfaces
If there is no other IPX/NCP Server on your net then
network number in entry '4' can be any number.
4 0x10 eth0 ethernet_ii # eth0 device with network number '0x10'
# and frame ETHERNET_II.
4 0x20 eth0 802.3 # eth0 device with network number '0x20'
# und frame ETHERNET_802.3.
2. You want to run mars_nwe only as a fileserver and use
special tools to configure ipx and rip/sap routers.
@ -34,7 +51,7 @@ of mars_nwe and make the needed changes to your
=========> start programs
call nwserv ( as root !! )
tested with Linux Version 1.2.13 and 1.3.32
tested with Linux Version 1.2.13 and 1.3.32 and higher
the linux-kernel must be configured with IPX=Y.
ipx-interface and ipx-routes are setup by the program if the
entry 4 (devices) in the nw.ini file is filled.

View File

@ -1,5 +1,5 @@
=========> !! wichtiger HINWEIS !!
Mars_nwe kann auf Arten konfiguriert werden.
Mars_nwe kann auf 2 Arten konfiguriert werden.
1. Mars_nwe soll die IPX-Routen automatisch setzen,
die IPX-Interfaces per ini/conf Datei konfigurieren
und als RIP/SAP Router arbeiten.
@ -10,10 +10,31 @@ Mars_nwe kann auf Arten konfiguriert werden.
dosemu, ncpfs oder Caldera's nwclient getestet.
-> Es muss ein Kernel < 1.3.60 oder aber ein Kernel >= 1.3.60,
kompiliert mit IPX-Option CONFIG_IPX_INTERN=N, verwendet werden.
Diese IPX-Kernel Option bedeutet NICHT 'internal net' sondern
'full internal net'.
In mars_nwe/config.h muss folgende Zeile vorhanden sein.
#define INTERNAL_RIP_SAP 1
In einer Umgebung mit anderen IPX/NCP Servern koennen bei
mars_nwe die Devices automatisch konfiguriert werden.
Hierzu muss mars_nwe mit internal net konfiguriert sein:
Eintrag '3' der 'ini/conf Datei' muss eine im Netz eindeutige
Netwerknummer erhalten.
Es muss ein Eintrag '4' mit Netzwerk Nummer = 0,
Device = '*' und Frame = 'auto' fuer ein 'autocreat' Interface
vorhanden sein.
Beispiel fuer conf/ini Datei: (siehe auch: examples/nw.ini)
3 0x77777 # eindeutige Netzwerk Nummer fuer internal net.
4 0x0 * AUTO # autocreat Interfaces
2. Mars_nwe soll nur als File Server Verwendung finden.
Falls kein anderer IPX/NCP Server im Netz vorhanden ist
kann im Eintrag '4' eine beliebige Netzwerknummer verwendet werden.
4 0x10 eth0 ethernet_ii # eth0 Device mit Netznummer '0x10'
# und Frame ETHERNET_II.
4 0x20 eth0 802.3 # eth0 Device mit Netznummer '0x20'
# und Frame ETHERNET_802.3.
2. Mars_nwe soll nur als File Server Verwendung finden, d.h.
Routing usw. soll von anderen Programmen erledigt werden.
-> Die IPX-Interfaces muessen durch andere Programme/Tools
wie 'ipx-configure' oder aehnliche eingerichtet werden
und es muss ein rip/sap router/daemon eingerichtet sein.

View File

@ -1,4 +1,21 @@
# in this files are important notes for user of mars_nwe.
------05-May-96--- 0.97.pl3 ----------
Now nwserv can be called with parameter '-h' to send SIGHUP
to the main nwserv program or with '-k' to send SIGTERM
to the main nwserv program.
Updating utmp/wtmp files.
Automatic creat of ixp-interfaces in a NetWare
environment enabled.
Entry 1 for volumes enhanced.
Now you can make entries like:
1 HOME ~ k # Unixusers HOME
This means (path = '~') that this will be a volume
which allways point to the actual users homedir.
------21-Mar-96--- 0.97.pl2 ----------
Entry '7' in ini/conf file modified.
Old mode '8' is now mode '7' and mode '8'

70
doc/PIPE-FS Normal file
View File

@ -0,0 +1,70 @@
The PIPE filesystem arose in answer to the question: how can I save
all or part of a Linux system onto/ via a DOS computer or a Novell
fileserver? The PIPE filesystem was designed as a quick attempt to
solve this problem
In the PIPE filesystem either shell scripts or Linux programs can be
stored. These programs are treated on the client side (eg DOS) like
simple files. Opening these files via the client causes a popen of the
programs. The server passes as the first parameter either CREAT READ
or WRITE, depending on the mode of the corresponding openfile
operation. This allows the PIPE filesystem to provide a direct
interface between client applications and Linux programs.
The problem stated above could then be solved with the following
simple shell script, which was stored in the PIPE-filesystem:
#!/bin/sh
case "$1" in
'CREAT')
;;
'WRITE')
cd /u3 && tar -xf - 2>> /tmp/tar.in
# restore directory /u3/mar
;;
'READ')
cd /u3 && tar -cf - mar 2> /dev/null
# save directory /u3/mar
;;
*)
;;
esac
Under DOS this 'Pipe File' can now be 'copied' into a local file using
the Copy command (->save), or the local file can be copied into this
'Pipe File' (->restore).
A simple print operation can be achieved with the following script:
#!/bin/sh
case "$1" in
'WRITE')
/usr/bin/lpr
;;
*)
;;
esac
Various unix programs can be invoked with the following script, after
it has been linked with the required program name.
#!/bin/sh
case "$1" in
'READ')
/usr/bin/`basename $0`
;;
*)
;;
esac
I would appreciate hearing about further documented applications of
the PIPE filesystem or suggestions for other ways of using it.
Martin
(translated by Michael Beddow)

69
doc/PIPE-FS.ger Normal file
View File

@ -0,0 +1,69 @@
/* PIPE- Filesystem */
das 'PIPE Filesystem' entstand urspruenglich aus der Frage heraus:
Wie kann ich ein Linux System oder Teile davon ueber/auf einen
DOS-Rechner oder Novell Fileserver sichern.
Ein schneller Loesungsansatz ergab das 'PIPE Filesystem'.
In dem Pipe Filesystem koennen Shell Scripte oder
Linux Programme hinterlegt werden.
Diese Programme werden bei dem Client (z.B. DOS) wie einfache
Dateien behandelt.
Ein Oeffnen dieser Dateien ueber den Client bewirkt
einen popen dieser Programme. Der Server uebergibt
als 1. Parameter entweder 'CREAT', 'READ' oder 'WRITE'
je nach Modus der jeweiligen Openfile Operation.
Das 'PIPE-Filesystem' bietet damit eine direkte Schnittstelle
zwischen Client Anwendungen und Linux Programmen.
Die Loesung des obigen Problems ergab sich dann mit folgendem einfachen
Shell Script, welches im PIPE-Filesystem hinterlegt wurde.
#!/bin/sh
case "$1" in
'CREAT')
;;
'WRITE')
cd /u3 && tar -xf - 2>> /tmp/tar.in
# restore directory /u3/mar
;;
'READ')
cd /u3 && tar -cf - mar 2> /dev/null
# save directory /u3/mar
;;
*)
;;
esac
Unter DOS kann nun diese 'Pipe Datei' mit dem Copy Befehl in eine
lokale Datei 'kopiert' werden ( -> Sichern ) bzw. es
kann die lokale Datei auf diese 'Pipe Datei' kopiert werden.
( -> Ruecksichern )
Ein einfaches Drucken kann z.B. mit folgendem Script realisiert werden.
#!/bin/sh
case "$1" in
'WRITE')
/usr/bin/lpr
;;
*)
;;
esac
Der Aufruf diverser Unix Programme kann mit folgenden Script
erfolgen das auf die entsprechenden Programmnamen gelinkt wurde.
#!/bin/sh
case "$1" in
'READ')
/usr/bin/`basename $0`
;;
*)
;;
esac
Ueber weitere dokumentierte Anwendungen bzw. Anregungen zu dem
PIPE-Filesystem wuerde ich mich freuen.
Martin

View File

@ -1,16 +1,16 @@
Begin3
Title: mars_nwe
Version: 0.97.pl2
Entered-date: 21-Mar-96
Version: 0.97.pl3
Entered-date: 07-May-96
Description: full novell-server-emulator (src),beta
supports file-services, bindery-services,
printing-services, routing-services
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
120kB mars_nwe-0.97.pl2.tgz
Primary-site: ftp.gwdg.de:/pub/linux/misc/ncpfs
140kB mars_nwe-0.97.pl3.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)
Platforms: Linux (1.2.xx, 1.3.xx), UnixWare 2.0x
Copying-policy: GNU
End

271
emutli.c
View File

@ -1,4 +1,4 @@
/* emutli.c 07-Feb-96 */
/* emutli.c 28-Apr-96 */
/*
* One short try to emulate TLI with SOCKETS.
*/
@ -20,13 +20,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* Some of the Code in this module is stolen from the following
* Programms: ipx_interface, ipx_route, ipx_configure, which were
* written by Greg Page, Caldera, Inc.
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@ -42,32 +35,27 @@
#include <string.h>
#include <errno.h>
static int locipxdebug=0;
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
void set_locipxdebug(int debug)
{
locipxdebug = debug;
}
static int locipxdebug=0;
static int have_ipx_started=0;
static void set_sock_debug(int sock)
void set_sock_debug(int sock)
{
if (setsockopt(sock, SOL_SOCKET, SO_DEBUG, &locipxdebug, sizeof(int))==-1){
errorp(0, "setsockopt SO_DEBUG", NULL);
}
}
static void sock2ipxadr(ipxAddr_t *i, struct sockaddr_ipx *so)
void sock2ipxadr(ipxAddr_t *i, struct sockaddr_ipx *so)
{
memcpy(i->net, &so->sipx_network, IPX_NET_SIZE + IPX_NODE_SIZE);
memcpy(i->sock, &so->sipx_port, 2);
}
static void ipx2sockadr(struct sockaddr_ipx *so, ipxAddr_t *i)
void ipx2sockadr(struct sockaddr_ipx *so, ipxAddr_t *i)
{
memcpy(&so->sipx_network, i->net, IPX_NET_SIZE + IPX_NODE_SIZE);
memcpy(&so->sipx_port, i->sock, 2);
@ -79,241 +67,6 @@ void set_emu_tli()
if (i > -1) locipxdebug = i;
}
static int x_ioctl(int sock, int mode, void *id)
{
int result;
int i = 0;
do {
result = ioctl(sock, mode, id);
i++;
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
return(result);
}
static void del_special_net(int special, char *devname, int frame)
/* specials = */
/* IPX_SPECIAL_NONE */
/* IPX_INTERNAL */
/* IPX_PRIMARY */
/* devname + frame only if not IPX_INTERNAL */
{
int sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (sock > -1) {
struct ifreq id;
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
memset(&id, 0, sizeof(struct ifreq));
sipx->sipx_network = 0L;
sipx->sipx_special = special;
sipx->sipx_family = AF_IPX;
if (special == IPX_PRIMARY) {
FILE *f=fopen("/proc/net/ipx_interface", "r");
if (f) {
char buff[200];
char buff1[200];
char buff2[200];
char buff3[200];
char buff4[200];
char buff5[200];
while (fgets((char*)buff, sizeof(buff), f) != NULL){
if (sscanf(buff, "%s %s %s %s %s",
buff1, buff2, buff3, buff4, buff5) == 5) {
int len = strlen(buff5);
if (!len) continue;
switch (*(buff5+len-1)) {
case '2' : sipx->sipx_type = IPX_FRAME_8022; break;
case '3' : sipx->sipx_type = IPX_FRAME_8023; break;
case 'P' : sipx->sipx_type = IPX_FRAME_SNAP; break;
case 'I' : sipx->sipx_type = IPX_FRAME_ETHERII; break;
default : continue;
}
upstr(buff3);
if (!strcmp(buff3, "YES")) { /* primary */
strcpy(id.ifr_name, buff4);
break;
}
}
}
fclose(f);
}
} else if (special != IPX_INTERNAL) {
if (devname && *devname) strcpy(id.ifr_name, devname);
sipx->sipx_type = frame;
}
sipx->sipx_action = IPX_DLTITF;
x_ioctl(sock, SIOCSIFADDR, &id);
close(sock);
}
}
#define del_internal_net() \
del_special_net(IPX_INTERNAL, NULL, 0)
#define del_interface(devname, frame) \
del_special_net(IPX_SPECIAL_NONE, (devname), (frame))
#define del_primary_net() \
del_special_net(IPX_PRIMARY, NULL, 0)
static void add_special_net(int special,
char *devname, int frame, uint32 netnum, uint32 node)
{
int sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (sock > -1) {
struct ifreq id;
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
memset(&id, 0, sizeof(struct ifreq));
if (special != IPX_INTERNAL){
if (devname && *devname) strcpy(id.ifr_name, devname);
sipx->sipx_type = frame;
} else {
uint32 xx=htonl(node);
memcpy(sipx->sipx_node+2, &xx, 4);
}
sipx->sipx_network = htonl(netnum);
sipx->sipx_special = special;
sipx->sipx_family = AF_IPX;
sipx->sipx_action = IPX_CRTITF;
x_ioctl(sock, SIOCSIFADDR, &id);
close(sock);
}
}
#define add_internal_net(netnum, node) \
add_special_net(IPX_INTERNAL, NULL, 0, (netnum), (node))
#define add_device_net(devname, frame, netnum) \
add_special_net(IPX_SPECIAL_NONE, (devname), (frame), (netnum), 0)
#define add_primary_net(devname, frame, netnum) \
add_special_net(IPX_PRIMARY, (devname), (frame), (netnum), 0)
int init_ipx(uint32 network, uint32 node, int ipx_debug)
{
int result=-1;
int sock=sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (socket < 0) {
errorp(1, "EMUTLI:init_ipx", NULL);
exit(1);
} else {
set_sock_debug(sock);
result=0;
/* makes new internal net */
if (network) {
struct sockaddr_ipx ipxs;
memset((char*)&ipxs, 0, sizeof(struct sockaddr_ipx));
ipxs.sipx_port = htons(SOCK_NCP);
ipxs.sipx_family = AF_IPX;
if (bind(sock, (struct sockaddr*)&ipxs,
sizeof(struct sockaddr_ipx))==-1) {
if (errno == EEXIST || errno == EADDRINUSE) result = -1;
} else result =-1;
close(sock);
if (result) {
errorp(1, "EMUTLI:init_ipx socket 0x451", NULL);
exit(1);
}
del_internal_net();
add_internal_net(network, node);
have_ipx_started++;
} else {
close(sock);
}
}
return(result);
}
void exit_ipx(int full)
{
int sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (sock > -1) {
/* Switch DEBUG off */
locipxdebug = 0;
set_sock_debug(sock);
close(sock);
}
if (have_ipx_started && full) del_internal_net();
}
int init_dev(char *devname, int frame, uint32 network)
{
if (!network) return(0);
del_interface(devname, frame);
if (!have_ipx_started) {
have_ipx_started++;
del_primary_net();
add_primary_net(devname, frame, network);
} else
add_device_net(devname, frame, network);
return(0);
}
void exit_dev(char *devname, int frame)
{
del_interface(devname, frame);
}
void ipx_route_add(uint32 dest_net,
uint32 route_net,
uint8 *route_node)
{
struct rtentry rd;
int result;
int sock;
/* Router */
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
/* Target */
struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rd.rt_dst;
rd.rt_flags = RTF_GATEWAY;
st->sipx_network = htonl(dest_net);
sr->sipx_network = htonl(route_net);
memcpy(sr->sipx_node, route_node, IPX_NODE_SIZE);
if ( (sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX)) < 0){
errorp(0, "EMUTLI:ipx_route_add", NULL);
return;
}
sr->sipx_family = st->sipx_family = AF_IPX;
if ( 0 != (result = x_ioctl(sock, SIOCADDRT, &rd))) {
switch (errno) {
case ENETUNREACH:
errorp(0, "ROUTE ADD", "Router network (%08X) not reachable.\n",
htonl(sr->sipx_network));
break;
case EEXIST:
case EADDRINUSE:
break;
default:
errorp(0, "ROUTE ADD", NULL);
break;
}
}
close(sock);
}
void ipx_route_del(uint32 net)
{
struct rtentry rd;
int sock;
/* Router */
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
/* Target */
struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rd.rt_dst;
rd.rt_flags = RTF_GATEWAY;
st->sipx_network = htonl(net);
if ( (sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX)) < 0){
errorp(0, "EMUTLI:ipx_route_del", NULL);
return;
}
sr->sipx_family = st->sipx_family = AF_IPX;
x_ioctl(sock, SIOCDELRT, &rd);
close(sock);
}
int t_open(char *name, int open_mode, char * p)
{
int opt=1;
@ -421,8 +174,8 @@ int poll( struct pollfd *fds, unsigned long nfds, int timeout)
p = fds;
while (k--){
if (p->fd > -1 && FD_ISSET(p->fd, &readfs)){
p->revents = POLLIN;
if (! --rest) break; /* ready */
p->revents = POLLIN;
if (! --rest) break; /* ready */
}
p++;
}
@ -506,7 +259,7 @@ int t_sndudata(int fd, struct t_unitdata *ud)
ipxs.sipx_type = (ud->opt.len) ? (uint8) *((uint8*)(ud->opt.buf)) : 0;
result = sendto(fd,(void *)ud->udata.buf,
ud->udata.len, 0, (struct sockaddr *) &ipxs, sizeof(ipxs));
ud->udata.len, 0, (struct sockaddr *) &ipxs, sizeof(ipxs));
#if HAVE_IPX_SEND_BUG
alarm(0);

View File

@ -1,4 +1,4 @@
/* emutli.h 30-Jan-96 */
/* emutli.h 28-Apr-96 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
@ -92,6 +92,12 @@ struct pollfd {
#define TOUTSTATE 6 /* out of state */
extern void set_locipxdebug(int debug);
extern void set_sock_debug(int sock);
extern void sock2ipxadr(ipxAddr_t *i, struct sockaddr_ipx *so);
extern void ipx2sockadr(struct sockaddr_ipx *so, ipxAddr_t *i);
extern void set_emu_tli(void);
extern int poll(struct pollfd *fds, unsigned long nfds, int timeout);
extern int t_open(char *name, int open_mode, char *p);
extern int t_bind(int sock, struct t_bind *a_in, struct t_bind *a_out);
@ -103,39 +109,21 @@ extern int t_rcvuderr(int fd, struct t_uderr *ud);
extern int t_sndudata(int fd, struct t_unitdata *ud);
extern int init_ipx(uint32 network, uint32 node, int ipx_debug);
extern void exit_ipx(int full);
extern int init_dev(char *devname, int frame, uint32 network);
extern void exit_dev(char *devname, int frame);
#if 0
extern int get_ipx_addr(ipxAddr_t *addr);
#endif
extern void ipx_route_add(uint32 dest_net,
uint32 route_net,
uint8 *route_node);
extern void ipx_route_del(uint32 net);
extern void set_emu_tli(void);
#ifndef IPX_FRAME_8022
#define OLD_KERNEL_IPX 1
#define IPX_FRAME_8022 IPX_RT_8022
# define OLD_KERNEL_IPX 1
# define IPX_FRAME_8022 IPX_RT_8022
#endif
#ifndef IPX_FRAME_8023
#define IPX_FRAME_8023 0
# define IPX_FRAME_8023 0
#endif
#ifndef IPX_FRAME_SNAP
#define IPX_FRAME_SNAP IPX_RT_SNAP
# define IPX_FRAME_SNAP IPX_RT_SNAP
#endif
#ifndef IPX_FRAME_ETHERII
#define IPX_FRAME_ETHERII IPX_RT_BLUEBOOK
# define IPX_FRAME_ETHERII IPX_RT_BLUEBOOK
#endif
#endif

391
emutli1.c Normal file
View File

@ -0,0 +1,391 @@
/* emutli1.c 28-Apr-96 */
/*
* One short try to emulate TLI with SOCKETS.
*/
/* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* Some of the Code in this module is stolen from the following
* Programms: ipx_interface, ipx_route, ipx_configure, which were
* written by Greg Page, Caldera, Inc.
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/sockios.h>
#include "net.h"
#include <linux/if.h>
#include <linux/route.h>
#include <linux/in.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
static int have_ipx_started=0;
static int auto_interfaces=0;
static int org_auto_interfaces=0;
static int x_ioctl(int sock, int mode, void *id)
{
int result;
int i = 0;
do {
result = ioctl(sock, mode, id);
i++;
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
return(result);
}
static int interface_data(uint8* data, uint32 *rnet, uint8 *node,
int *flags, uint8 *name)
/* returns frame or if error < 0 */
{
uint32 snet;
int frame=-1;
int xflags =0;
uint8 buff1[200];
uint8 buff2[200];
uint8 buff3[200];
uint8 buff4[200];
if (!rnet) rnet =&snet;
if (!flags) flags=&xflags;
else *flags=0;
if (sscanf(data, "%lx %s %s %s %s",
rnet, buff1, buff2, buff3, buff4) == 5 ) {
int len = strlen(buff4);
if (!len) return(-1);
switch (*(buff4+len-1)) {
case '2' : frame = IPX_FRAME_8022; break;
case '3' : frame = IPX_FRAME_8023; break;
case 'P' : frame = IPX_FRAME_SNAP; break;
case 'I' : frame = IPX_FRAME_ETHERII; break;
#ifdef IPX_FRAME_TR_8022
case 'R' : frame = IPX_FRAME_TR_8022; break;
#endif
default : return(-2);
}
if (node) strmaxcpy(node, buff1, 12);
upstr(buff2);
if (!strcmp(buff2, "YES")) /* primary */
*flags |= 1;
if (name) strmaxcpy(name, buff3, 20);
upstr(buff3);
if (!strcmp(buff2, "INTERNAL")) /* internal net */
*flags |= 2;
}
return(frame);
}
int get_interface_frame_name(char *name, uint32 net)
/* returns frame and name of Device of net */
{
int frame = -1;
FILE *f=fopen("/proc/net/ipx_interface", "r");
if (f) {
char buff[200];
while (fgets((char*)buff, sizeof(buff), f) != NULL){
uint32 rnet;
uint8 dname[25];
int fframe = interface_data((uint8*) buff, &rnet, NULL, NULL, dname);
if (fframe < 0) continue;
if (rnet == net) {
if (name) strcpy(name, dname);
frame = fframe;
break;
}
}
fclose(f);
}
return(frame);
}
static void del_special_net(int special, char *devname, int frame)
/* specials = */
/* IPX_SPECIAL_NONE */
/* IPX_INTERNAL */
/* IPX_PRIMARY */
/* devname + frame only if not IPX_INTERNAL */
{
int sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (sock > -1) {
struct ifreq id;
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
memset(&id, 0, sizeof(struct ifreq));
sipx->sipx_network = 0L;
sipx->sipx_special = special;
sipx->sipx_family = AF_IPX;
if (special == IPX_PRIMARY) {
FILE *f=fopen("/proc/net/ipx_interface", "r");
if (f) {
char buff[200];
uint8 name[25];
while (fgets((char*)buff, sizeof(buff), f) != NULL){
int flags = 0;
int frame = interface_data((uint8*) buff, NULL, NULL,
&flags, name);
if (frame < 0) continue;
sipx->sipx_type = frame;
if (flags & 1) { /* primary */
strcpy(id.ifr_name, name);
break;
}
}
fclose(f);
}
} else if (special != IPX_INTERNAL) {
if (devname && *devname) strcpy(id.ifr_name, devname);
sipx->sipx_type = frame;
}
sipx->sipx_action = IPX_DLTITF;
x_ioctl(sock, SIOCSIFADDR, &id);
close(sock);
}
}
#define del_internal_net() \
del_special_net(IPX_INTERNAL, NULL, 0)
#define del_interface(devname, frame) \
del_special_net(IPX_SPECIAL_NONE, (devname), (frame))
#define del_primary_net() \
del_special_net(IPX_PRIMARY, NULL, 0)
static int add_special_net(int special,
char *devname, int frame, uint32 netnum, uint32 node)
{
int result = -1;
int sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (sock > -1) {
struct ifreq id;
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
memset(&id, 0, sizeof(struct ifreq));
if (special != IPX_INTERNAL){
if (devname && *devname) strcpy(id.ifr_name, devname);
sipx->sipx_type = frame;
} else {
uint32 xx=htonl(node);
memcpy(sipx->sipx_node+2, &xx, 4);
}
sipx->sipx_network = htonl(netnum);
sipx->sipx_special = special;
sipx->sipx_family = AF_IPX;
sipx->sipx_action = IPX_CRTITF;
result = x_ioctl(sock, SIOCSIFADDR, &id);
close(sock);
}
return(result);
}
#define add_internal_net(netnum, node) \
add_special_net(IPX_INTERNAL, NULL, 0, (netnum), (node))
#define add_device_net(devname, frame, netnum) \
add_special_net(IPX_SPECIAL_NONE, (devname), (frame), (netnum), 0)
#define add_primary_net(devname, frame, netnum) \
add_special_net(IPX_PRIMARY, (devname), (frame), (netnum), 0)
int get_frame_name(uint8 *framename, int frame)
{
char *frname=0;
switch (frame) {
case -1 : frname = "AUTO"; break;
#ifdef IPX_FRAME_TR_8022
case IPX_FRAME_TR_8022 : frname = "TOKEN"; break;
#endif
case IPX_FRAME_8022 : frname = "802.2"; break;
case IPX_FRAME_8023 : frname = "802.3"; break;
case IPX_FRAME_SNAP : frname = "SNAP"; break;
case IPX_FRAME_ETHERII : frname = "ETHERNET_II";break;
default : framename[0] = '\0';
return(-1);
} /* switch */
strcpy(framename, frname);
return(0);
}
int init_ipx(uint32 network, uint32 node, int ipx_debug)
{
int result=-1;
int sock;
#if INTERNAL_RIP_SAP
# ifdef CONFIG_IPX_INTERN
errorp(11, "!! configuration error !!",
"mars_nwe don't run with kernel 'full internal net'.\n"
"Change kernel option CONFIG_IPX_INTERN=NO (nobody needs it)\n"
"or use 'ipxd' and change mars_nwe INTERNAL_RIP_SAP=0.");
exit(1);
# endif
#endif
if ((sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX)) < 0) {
errorp(1, "EMUTLI:init_ipx", NULL);
exit(1);
} else {
ipx_config_data cfgdata;
ioctl(sock, SIOCIPXCFGDATA, &cfgdata);
org_auto_interfaces =
auto_interfaces = cfgdata.ipxcfg_auto_create_interfaces;
set_sock_debug(sock);
result=0;
/* makes new internal net */
if (network) {
struct sockaddr_ipx ipxs;
memset((char*)&ipxs, 0, sizeof(struct sockaddr_ipx));
ipxs.sipx_port = htons(SOCK_NCP);
ipxs.sipx_family = AF_IPX;
if (bind(sock, (struct sockaddr*)&ipxs,
sizeof(struct sockaddr_ipx))==-1) {
if (errno == EEXIST || errno == EADDRINUSE) result = -1;
}
if (result) {
errorp(1, "EMUTLI:init_ipx socket 0x451", NULL);
exit(1);
}
del_internal_net();
add_internal_net(network, node);
have_ipx_started++;
}
close(sock);
}
return(result);
}
void exit_ipx(int full)
{
int sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (sock > -1) {
/* Switch DEBUG off */
set_locipxdebug(0);
set_sock_debug(sock);
#if 1
if (have_ipx_started && full) org_auto_interfaces = 0;
#endif
if (auto_interfaces != org_auto_interfaces)
ioctl(sock, SIOCAIPXITFCRT, &org_auto_interfaces);
close(sock);
}
if (have_ipx_started && full) del_internal_net();
}
int init_dev(char *devname, int frame, uint32 network)
{
int is_auto = (!network || frame < 0 || devname[0] == '*');
if (frame > -1 && devname[0] != '*') del_interface(devname, frame);
if (!have_ipx_started) {
if (is_auto) return(-99);
have_ipx_started++;
del_primary_net();
add_primary_net(devname, frame, network);
} else {
if (!is_auto)
return(add_device_net(devname, frame, network));
else if (!auto_interfaces) {
int sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (sock < 0) return(-2);
auto_interfaces = 1;
if (ioctl(sock, SIOCAIPXITFCRT, &auto_interfaces) < 0) {
close(sock);
return(-3);
}
close(sock);
}
return(1);
}
return(0);
}
void exit_dev(char *devname, int frame)
{
del_interface(devname, frame);
}
void ipx_route_add(uint32 dest_net,
uint32 route_net,
uint8 *route_node)
{
struct rtentry rd;
int result;
int sock;
/* Router */
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
/* Target */
struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rd.rt_dst;
rd.rt_flags = RTF_GATEWAY;
st->sipx_network = htonl(dest_net);
sr->sipx_network = htonl(route_net);
if (route_node)
memcpy(sr->sipx_node, route_node, IPX_NODE_SIZE);
else
memset(sr->sipx_node, 0, IPX_NODE_SIZE);
if ( (sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX)) < 0){
errorp(0, "EMUTLI:ipx_route_add", NULL);
return;
}
sr->sipx_family = st->sipx_family = AF_IPX;
if ( 0 != (result = x_ioctl(sock, SIOCADDRT, &rd))) {
switch (errno) {
case ENETUNREACH:
errorp(0, "ROUTE ADD", "Router network (%08X) not reachable.\n",
htonl(sr->sipx_network));
break;
case EEXIST:
case EADDRINUSE:
break;
default:
errorp(0, "ROUTE ADD", NULL);
break;
}
}
close(sock);
}
void ipx_route_del(uint32 net)
{
struct rtentry rd;
int sock;
/* Router */
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
/* Target */
struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rd.rt_dst;
rd.rt_flags = RTF_GATEWAY;
st->sipx_network = htonl(net);
if ( (sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX)) < 0){
errorp(0, "EMUTLI:ipx_route_del", NULL);
return;
}
sr->sipx_family = st->sipx_family = AF_IPX;
x_ioctl(sock, SIOCDELRT, &rd);
close(sock);
}

40
emutli1.h Normal file
View File

@ -0,0 +1,40 @@
/* emutli1.h 28-Apr-96 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _EMUTLI1_H_
#define _EMUTLI1_H_
extern void set_locipxdebug(int debug);
extern int get_interface_frame_name(char *name, uint32 net);
extern int get_frame_name(uint8 *framename, int frame);
extern int init_ipx(uint32 network, uint32 node, int ipx_debug);
extern void exit_ipx(int full);
extern int init_dev(char *devname, int frame, uint32 network);
extern void exit_dev(char *devname, int frame);
#if 0
extern int get_ipx_addr(ipxAddr_t *addr);
#endif
extern void ipx_route_add(uint32 dest_net,
uint32 route_net,
uint8 *route_node);
extern void ipx_route_del(uint32 net);
#endif

View File

@ -0,0 +1,7 @@
This is the kernel-ipx patch for the 1.2.13 kernel.
If you have problems with mars_nwe or if you want to
speed up mars_nwe with kernel 1.2.13 you should apply
this patch to kernel 1.2.13
Martin

View File

@ -1,4 +1,6 @@
The kernelpatch kpatch1.3.72 you can use directly for kernels 1.3.72 .. ???
The kernelpatch kpatch1.3.72 you can use directly for kernels 1.3.72 .. 1.3.77
The kernelpatch kpatch1.3.78 you can use directly for kernels 1.3.78,79 .. ??
but it should be easy to apply this patch to all kernels.
By older kernels 'sk->protinfo.af_ipx.' must become 'sk->' .
After applying this patch please rebuild mars_nwe (make clean)

View File

@ -1,8 +1,8 @@
/* config.h: 14-Mar-96 */
/* config.h: 03-May-96 */
/* some of this config is needed by make, others by cc */
#define DO_DEBUG 1 /* Compile in debug code */
#define DO_TESTING 0
#define DO_TESTING 0 /* only for the next choose */
#if DO_TESTING
# define FILENAME_NW_INI "./nw.ini" /* full name of ini (conf) file */
# define PATHNAME_PROGS "." /* path location of progs */
@ -14,30 +14,44 @@
# define PATHNAME_BINDERY "/etc" /* path location of bindery */
# define FUNC_17_02_IS_DEBUG 0
#endif
#define PATHNAME_PIDFILES "/var/run" /* path location of 'pidfiles' */
/* next for utmp/wtmp updates */
#define FILENAME_UTMP UTMP_FILE
/* can be set NULL if you don't want utmp/wtmp updates */
#define FILENAME_WTMP WTMP_FILE
/* can be set NULL if you don't want wtmp updates */
#define NETWORK_SERIAL_NMBR 0x44444444L /* Serial Number 4 Byte */
#define NETWORK_APPL_NMBR 0x2222 /* Applikation Number 2 Byte */
#define MAX_CONNECTIONS 5 /* max. Number of Connections */
#define MAX_CONNECTIONS 5 /* max. Number of Connections */
/* must be < 256 !!! */
#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 minimal */
#define IPX_DATA_GR_546 1 /* allow ipx packets > 546+30 Byte */
/* <-----------------------------------------------------------> */
#define MAX_NW_VOLS 10 /* max. Volumes */
#define MAX_FILE_HANDLES_CONN 80 /* max. open files /connection */
/* <--------------- new namespace services call --------------> */
#define WITH_NAME_SPACE_CALLS 1 /* 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 > '0', too. */
#define MAX_DIR_BASE_ENTRIES 50 /* max. cached base entries/connection */
/* <-----------------------------------------------------------> */
#define MAX_NW_SERVERS 40 /* max. count of servers */
/* <--------------- next is for linux only -------------------> */
#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 = don't start ncpserv */
#define MAX_RIP_ENTRIES 50 /* max. rip responses */
/* -------------------- */
#define SHADOW_PWD 0 /* change to '1' for shadow passwds */

122
examples/kpatch1.2.13 Normal file
View File

@ -0,0 +1,122 @@
Index: include/linux/ipx.h
--- linux.org/include/linux/ipx.h Mon Feb 6 19:25:22 1995
+++ linux/include/linux/ipx.h Fri Mar 22 00:58:02 1996
@@ -74,5 +74,6 @@
#define SIOCAIPXITFCRT (SIOCPROTOPRIVATE)
#define SIOCAIPXPRISLT (SIOCPROTOPRIVATE+1)
#define SIOCIPXCFGDATA (SIOCPROTOPRIVATE+2)
+#define SIOCIPXNCPCONN (SIOCPROTOPRIVATE+3)
#endif
Index: net/inet/ipx.c
--- linux.org/net/inet/ipx.c Tue Apr 18 21:13:26 1995
+++ linux/net/inet/ipx.c Fri Mar 22 01:25:25 1996
@@ -341,6 +341,20 @@
struct sk_buff *skb1 = NULL, *skb2 = NULL;
int ipx_offset;
+ if (intrfc == ipx_primary_net
+ && ntohs(ipx->ipx_dest.sock) == 0x451
+ && *((char*)(ipx+1)) == 0x22
+ && *((char*)(ipx+1)+1) == 0x22) {
+ int connection = (int) *((char*)(ipx+1)+3);
+ /* 255 connections are enough ;) */
+ if (connection) {
+ for (sock1=intrfc->if_sklist;
+ (sock1 != NULL) &&
+ (sock1->ipx_ncp_conn != connection);
+ sock1=sock1->next);;
+ }
+ }
+ if (sock1 == NULL)
sock1 = ipxitf_find_socket(intrfc, ipx->ipx_dest.sock);
/*
@@ -859,6 +873,7 @@
ipxif=ipxitf_find_using_phys(dev, ipx_map_frame_type(sipx->sipx_type));
if(ipxif==NULL)
return -EADDRNOTAVAIL;
+ sipx->sipx_family=AF_IPX;
sipx->sipx_network=ipxif->if_netnum;
memcpy(sipx->sipx_node, ipxif->if_node, sizeof(sipx->sipx_node));
memcpy_tofs(arg,&ifr,sizeof(ifr));
@@ -909,7 +924,8 @@
return -EAGAIN;
rt->ir_next=ipx_routes;
ipx_routes=rt;
- }
+ } else if (intrfc == ipx_internal_net)
+ return(-EEXIST); /* fix for mars_nwe: 11-Jan-96 */
rt->ir_net = network;
rt->ir_intrfc = intrfc;
@@ -983,6 +999,7 @@
int size;
int ipx_offset;
ipx_route *rt = NULL;
+ int snr;
/* Find the appropriate interface on which to send packet */
if ((usipx->sipx_network == 0L) && (ipx_primary_net != NULL)) {
@@ -1017,9 +1034,14 @@
ipx->ipx_tctrl=0;
ipx->ipx_type=usipx->sipx_type;
skb->h.raw = (unsigned char *)ipx;
-
+ if ((snr=ntohs(sk->ipx_port)) == 0x453 || snr == 0x452) {
+ /* RIP/SAP speicial handling for mars_nwe: 11-Jan-96 */
+ ipx->ipx_source.net = intrfc->if_netnum;
+ memcpy(ipx->ipx_source.node, intrfc->if_node, IPX_NODE_LEN);
+ } else {
ipx->ipx_source.net = sk->ipx_intrfc->if_netnum;
memcpy(ipx->ipx_source.node, sk->ipx_intrfc->if_node, IPX_NODE_LEN);
+ }
ipx->ipx_source.sock = sk->ipx_port;
ipx->ipx_dest.net=usipx->sipx_network;
memcpy(ipx->ipx_dest.node,usipx->sipx_node,IPX_NODE_LEN);
@@ -1335,6 +1357,7 @@
return err;
put_fs_long(sizeof(int),(unsigned long *)optlen);
err=verify_area(VERIFY_WRITE,optval,sizeof(int));
+ if (err) return err;
put_fs_long(val,(unsigned long *)optval);
return(0);
}
@@ -1397,6 +1420,8 @@
sk->debug=0;
sk->ipx_intrfc = NULL;
memset(&sk->ipx_dest_addr,'\0',sizeof(sk->ipx_dest_addr));
+ sk->ipx_ncp_conn = 0; /* no ncp socket yet */
+
sk->ipx_port = 0;
sk->mtu=IPX_MTU;
@@ -1835,6 +1860,16 @@
if(err) return err;
return(ipxcfg_get_config_data((void *)arg));
}
+ case SIOCIPXNCPCONN:
+ {
+ if (!suser()) return(-EPERM);
+ err = verify_area(VERIFY_READ, (void *)arg,
+ sizeof(unsigned short));
+ if (err) return err;
+ sk->ipx_ncp_conn = get_fs_word(arg);
+ return 0;
+ }
+
case SIOCGSTAMP:
if (sk)
{
Index: net/inet/sock.h
Prereq: 1.0.4
--- linux.org/net/inet/sock.h Fri Mar 22 01:11:28 1996
+++ linux/net/inet/sock.h Fri Mar 22 01:12:26 1996
@@ -146,6 +146,7 @@
ipx_interface *ipx_intrfc;
unsigned short ipx_port;
unsigned short ipx_type;
+ unsigned short ipx_ncp_conn;
#endif
#ifdef CONFIG_AX25
/* Really we want to add a per protocol private area */

74
examples/kpatch1.3.78 Normal file
View File

@ -0,0 +1,74 @@
diff -rub linux.org/include/linux/ipx.h linux/include/linux/ipx.h
--- linux.org/include/linux/ipx.h Wed Mar 27 18:43:19 1996
+++ linux/include/linux/ipx.h Thu Mar 28 11:15:31 1996
@@ -74,5 +74,6 @@
#define SIOCAIPXITFCRT (SIOCPROTOPRIVATE)
#define SIOCAIPXPRISLT (SIOCPROTOPRIVATE+1)
#define SIOCIPXCFGDATA (SIOCPROTOPRIVATE+2)
+#define SIOCIPXNCPCONN (SIOCPROTOPRIVATE+3)
#endif
diff -rub linux.org/include/net/sock.h linux/include/net/sock.h
--- linux.org/include/net/sock.h Wed Mar 27 23:05:18 1996
+++ linux/include/net/sock.h Thu Mar 28 11:15:31 1996
@@ -112,6 +112,10 @@
* know the connection this socket belongs to.
*/
struct ncp_server *ncp_server;
+/*
+ * To handle special NCP-Sockets for mars_nwe
+ */
+ unsigned short ipx_ncp_conn;
};
#endif
diff -rub linux.org/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
--- linux.org/net/ipx/af_ipx.c Wed Mar 27 17:50:39 1996
+++ linux/net/ipx/af_ipx.c Thu Mar 28 11:15:31 1996
@@ -448,6 +448,20 @@
ipx_socket *sock1 = NULL, *sock2 = NULL;
struct sk_buff *skb1 = NULL, *skb2 = NULL;
+ if (intrfc == ipx_primary_net
+ && ntohs(ipx->ipx_dest.sock) == 0x451
+ && *((char*)(ipx+1)) == 0x22
+ && *((char*)(ipx+1)+1) == 0x22) {
+ int connection = (int) *((char*)(ipx+1)+3);
+ /* 255 connections are enough ;) */
+ if (connection) {
+ for (sock1=intrfc->if_sklist;
+ (sock1 != NULL) &&
+ (sock1->protinfo.af_ipx.ipx_ncp_conn != connection);
+ sock1=sock1->next);;
+ }
+ }
+ if (sock1 == NULL)
sock1 = ipxitf_find_socket(intrfc, ipx->ipx_dest.sock);
/*
@@ -1639,6 +1653,7 @@
sizeof(sk->protinfo.af_ipx.dest_addr));
sk->protinfo.af_ipx.port = 0;
sk->protinfo.af_ipx.ncp_server = 0;
+ sk->protinfo.af_ipx.ipx_ncp_conn = 0; /* no ncp socket yet */
sk->mtu=IPX_MTU;
if(sock!=NULL)
@@ -2142,6 +2157,17 @@
if(err) return err;
return(ipxcfg_get_config_data((void *)arg));
}
+
+ case SIOCIPXNCPCONN:
+ {
+ if (!suser()) return(-EPERM);
+ err = verify_area(VERIFY_READ, (void *)arg,
+ sizeof(unsigned short));
+ if (err) return err;
+ sk->protinfo.af_ipx.ipx_ncp_conn = get_fs_word(arg);
+ return 0;
+ }
+
case SIOCGSTAMP:
if (sk)
{

View File

@ -1,5 +1,5 @@
#!/bin/sh
# mk.li 10-Feb-96 ###
# mk.li 27-Apr-96 ###
# please edit this file !
mk()
@ -11,7 +11,7 @@ mk()
if [ ! -d $OBJDIR ] ; then mkdir $OBJDIR; fi
cd $OBJDIR;
fi
$MAKE -f $V_VPATH/makefile.unx $@ 2>&1 | tee $ERRFILE;
if $MAKE -f $V_VPATH/makefile.unx $@ 2>&1;then true;else kill -HUP $MK_PPID;fi | tee $ERRFILE
if [ $V_VPATH = '..' ] ; then
cd ..;
fi
@ -20,6 +20,9 @@ mk()
TOLOWER='tr "[A-Z]" "[a-z]"'
UNX=`uname -s | $TOLOWER`
MK_PPID=$$
export MK_PPID
trap 'echo "Error: Try again :)" && exit 1' 1
case $UNX in
linux)

View File

@ -1,27 +1,42 @@
# (C)opyright 1993, 1996, Martin Stover, Softwareentwicklung, Marburg
# last change: 08-Mar-96
# last change: 28-Apr-96
# MAR.S NW-Server Emulator
# Einfache Konfiguration, alles ab # ist Kommentar.
# Jeder Eintrag beginnt mit einer Zahl und dann folgt der Inhalt.
# simple configuration, all after # is ignored.
# every entry begins with a number and then the meet follows.
####################################
# entry 1 VOLUMES (max. volumes depend on your config.h)
# Volumename Volumepath Options (k=lowercase,p=pipe,m=removable)
1 SYS /u3/SYS/ # SYS 1
# SYS, der Name darf auch anders lauten, muss
# eingerichtet sein mit den folgenden Verzeichnissen:
# LOGIN, PUBLIC, SYSTEM, MAIL.
# SYS, may be named diffent but must be setup and must
# contains the following Directories: LOGIN, PUBLIC, SYSTEM, MAIL
####################################
# Die folgenden Volumes sind optional.
# the following volumes are optional.
#1 HOME ~ k # Users HOME directory
#.............^^^
# such a 'path' (~) stands for users home dir
# this is an automatic changed volume.
#1 SYS1 /u3/SYS1/ # SYS 2 upshift
#1 TMP /tmp/ k # TMP downshift
#1 CD /cdrom km # CDROM downshift/removable
#1 PIPES /u3/pipes kp # pipecommands
# Falls lowercase nicht gesetzt ist, werden GROSSBUCHSTABEN erwartet.
# If lowercase is not set then all filenames are upshift.
# SYS, der Name darf auch anders lauten, muss
# eingerichtet sein mit den folgenden Verzeichnissen:
# LOGIN, PUBLIC, SYSTEM, MAIL.
# SYS, may be named diffent but must be setup and must
# contains the following Directories: LOGIN, PUBLIC, SYSTEM, MAIL
# all flags for volumes:
# 'k' all is downshift
# 'm' volume is moveable (cdrom)
# 'o' volume has only one filesystem/device/namespace
# this is for filesystems with high inode > 0xFFFFFFF.
# because for namespace services mars_nwe normally use the
# first 4 bit of 32 bit inode for distinguish
# between several devices/namespaces for one volume.
# 'p' 'PIPE' filesystem. All files are pipe commands.
# see 'doc/PIPE-FS'
######################################
# Eintrag 2 fuer den Servername.
# falls nicht gesetzt, wird hostname (in GROSSBUCHSTABEN) verwendet.
@ -31,19 +46,32 @@
######################################
# next entry for configure mars_nwe to use the internal net
# If you have mars_nwe V > 0.96pl5 and a kernel >= 1.3.60
# or the small ipx-kpatch from the examples dir you can use
# or the small ipx-kpatch from the examples dir you should use
# internal net and routing.
# INTERNAL NET [NODE]
#3 0x999999 1 # Node default 1
# NOTE: the internal NET Number must be UNIQUE
# in your IPX-environment. !
# INTERNAL NET [NODE] (default 1)
3 0xABCDEF99 1 # Net Number must be unique.
######################################
# entry 4: # for DEVICE(S)
# if your ipx is allready up, then entry 4 must be removed.
# NETWORK NUMBER, DEVICE, Frame-Typ TICS (default 1)
# NOTE for people with other IPX/NCP servers on the net:
# Your network numbers, frames must be the same as at your
# other servers on the same net.
# You also may choose a network number = '0', device = '*'
# and frame = 'auto' for autosetup of devices.
#
# NETWORK NUMBER, DEVICE, Frame-Typ TICKS (default 1)
4 0x10 eth0 802.3 1
4 0x0 * AUTO 1 # autosetup all devices
# ^^^^...........^^^....^^^^^^^
# NOTE: autosetup can only be choosen if you have other
# IXP/NCP servers on the same net which are setup correctly.
######
#4 0x22 eth0 ethernet_ii 1
#4 0x33 eth0 802.2 1
#4 0x55 isdn2 ethernet_ii 7
# Frames=ethernet_ii, 802.2, 802.3, SNAP (default 802.3)
#4 0x66 tr0 token 1
# Frames=ethernet_ii, 802.2, 802.3, snap, token, auto, (default 802.3),
5 0 # don't = 0, do = 1, save ipx-routes after server is down.
######################################
# some clients are running better, if the server tells
@ -106,9 +134,10 @@
103 0 # debug NWCONN
104 0 # debug (start) NWCLIENT
105 0 # debug NWBIND
106 1 # debug NWROUTED
#############################
200 1 # 0 = no logfile and dont daemonize nwserv
# # 1 = daemonize nwserv and use logfile
200 1 # 0 = no logfile and dont daemonize nwserv/nwrouted
# # 1 = daemonize nwserv/nwrouted and use logfile
201 /tmp/nw.log # logfilename
202 1 # 1=creat new logfile, 0=append to logfile
#############################
@ -116,11 +145,11 @@
# # 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. ( normally minutes )
300 1 # > 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
302 1 # creat new routing info file=1, append to this file=0
#############################
310 7 # send wdog's only to device net < x tics.
310 7 # send wdog's only to device net < x ticks.
# 0 = allways send wdogs. < 0 = never send wdogs
##############################
# station file for special handling of stations.

View File

@ -1,4 +1,5 @@
#!/bin/sh
### !!!!!!! this is only for kernel 1.3.56 !!!!!!!!
ACT_DIR=`pwd`
PATCHFILE=kpatch1.3.56
LINUXDIR=/usr/src/linux

View File

@ -1,5 +1,5 @@
#if 0
#makefile.unx 15-Mar-96
#makefile.unx 22-Mar-96
#endif
VPATH=$(V_VPATH)
@ -9,7 +9,7 @@ C=.c
V_H=0
V_L=97
P_L=2
P_L=3
#define D_P_L 1
DISTRIB=mars_nwe
@ -28,6 +28,9 @@ DESTMAKEFILE=Makefile.o
all: $(DESTMAKEFILE)
$(MAKE) -f $(DESTMAKEFILE) n_$@
routed: $(DESTMAKEFILE)
$(MAKE) -f $(DESTMAKEFILE) n_$@
clean: $(DESTMAKEFILE)
$(MAKE) -f $(DESTMAKEFILE) n_$@
@ -63,6 +66,7 @@ PROG3=nwconn
PROG4=ncpserv
PROG5=nwclient
PROG6=nwbind
PROG7=nwrouted
#include "config.h"
#ifdef FILENAME_NW_INI
@ -83,29 +87,37 @@ M_PATHNAME_PROGS="."
#ifdef LINUX
EMUTLIOBJ=emutli$(O)
EMUTLIOBJ1=emutli1$(O)
# if INTERNAL_RIP_SAP
NWROUTE_O=nwroute$(O)
# else
NWROUTE_O=nwroute1$(O)
NWROUTED=$(PROG7)
# endif
#else
NWROUTE_O=nwroute1$(O)
#endif
PROGS=$(PROG1) $(PROG2) $(PROG3) $(PROG4) $(PROG5) $(PROG6)
PROGS=$(PROG1) $(PROG2) $(PROG3) $(PROG4) $(PROG5) $(PROG6) $(NWROUTED)
OBJ1= $(EMUTLIOBJ) net1$(O) tools$(O)
OBJ2= $(OBJ1) $(NWROUTE_O)
OBJ3= $(OBJ1) connect$(O) namspace$(O) nwvolume$(O) nwfile$(O)
OBJ2= $(OBJ1) $(EMUTLIOBJ1) $(NWROUTE_O)
OBJ3= $(OBJ1) connect$(O) namspace$(O) nwvolume$(O) nwfile$(O) unxfile$(O) \
nwqueue$(O)
OBJ4= $(OBJ1)
OBJ5= $(OBJ1)
OBJ6= $(OBJ1) nwdbm$(O) nwcrypt$(O)
OBJ6= $(OBJ1) nwdbm$(O) nwcrypt$(O) unxlog$(O)
OBJ7= $(OBJ1) $(EMUTLIOBJ1)
OBJS= net1$(O) tools$(O) connect$(O) nwdbm$(O) $(NWROUTE_O) \
namspace$(O) nwvolume$(O) \
$(PROG2)$(O) $(PROG3)$(O) $(PROG4)$(O) $(PROG5)$(O) $(PROG6)$(O)
OBJS= $(EMUTLIOBJ) net1$(O) tools$(O) \
$(EMUTLIOBJ1) $(NWROUTE_O) \
connect$(O) namspace$(O) nwvolume$(O) nwfile$(O) unxfile$(O)\
nwdbm$(O) nwcrypt$(O) unxlog$(O) \
$(PROG2)$(O) $(PROG3)$(O) $(PROG4)$(O) $(PROG5)$(O) $(PROG6)$(O) \
$(PROG7)$(O)
HOBJ3= $(PROG3)$(O) connect$(O) namspace$(O) nwvolume$(O) nwfile$(O)
HOBJ3= $(PROG3)$(O) connect$(O) namspace$(O) nwvolume$(O) nwfile$(O) \
unxfile$(O)
#if 0
#$(PROG1): $(PROG1)$(O) $(OBJ1)
@ -114,6 +126,7 @@ HOBJ3= $(PROG3)$(O) connect$(O) namspace$(O) nwvolume$(O) nwfile$(O)
$(PROG2): $(PROG2)$(O) $(OBJ2)
$(CC) -o $(VPATH)/$(PROG2) $(PROG2)$(O) $(OBJ2) $(NSLLIB)
#if 0
#$(CC) -o $(VPATH)/$(PROG2) $(PROG2)$(O) $(OBJ2) $(NDBMLIB) $(NSLLIB)
#endif
@ -130,6 +143,8 @@ $(PROG5): $(PROG5)$(O) $(OBJ5)
$(PROG6): $(PROG6)$(O) $(OBJ6)
$(CC) -o $(VPATH)/$(PROG6) $(PROG6)$(O) $(OBJ6) $(NDBMLIB) $(CRYPTLIB) $(NSLLIB)
$(PROG7): $(PROG7)$(O) $(OBJ7) nwserv.c nwroute.c
$(CC) -o $(VPATH)/$(PROG7) $(PROG7)$(O) $(OBJ7) $(NSLLIB)
$(HOBJ3): namspace.h connect.h nwvolume.h nwfile.h
$(OBJS): net.h config.h
@ -141,6 +156,8 @@ $(C)$(O):
n_all: $(PROGS)
@echo "don't forget to do a 'make install' as root !" >> $(VPATH)/.mk.notes
n_routed: $(PROG7)
n_install_ini:
cd $(VPATH) && $(INSTALL) -m 664 nw.ini $(M_FILENAME_NW_INI) && cd $(OBJDIR)
@ -175,7 +192,7 @@ clean_d:
n_clean:
rm -f *.o
cd $(VPATH) && (rm -f $(PROGS); cd $(OBJDIR) )
cd $(VPATH) && (rm -f $(PROGS) $(PROG7); cd $(OBJDIR) )
n_distclean: n_clean clean_d
cd $(VPATH) && (rm -f *.dir *.pag; cd $(OBJDIR))

View File

@ -1,4 +1,4 @@
/* namspace.c 07-Feb-96 : NameSpace Services, mars_nwe */
/* namspace.c 06-May-96 : NameSpace Services, mars_nwe */
/* !!!!!!!!!!!! NOTE !!!!!!!!!! */
/* Its very dirty till now. */
@ -31,6 +31,7 @@
#include "nwvolume.h"
#include "connect.h"
#include "nwfile.h"
#include "unxfile.h"
#include "namspace.h"
#if WITH_NAME_SPACE_CALLS
@ -41,27 +42,27 @@
typedef struct {
int volume; /* Volume Number */
int has_wild; /* fn has wildcards */
struct stat statb;
struct stat statb; /* stat buff */
uint8 *fn; /* points to last entry of path */
uint8 path[512]; /* path + fn */
uint8 path[512]; /* path + fn */
} N_NW_PATH;
typedef struct {
DIR *fdir; /* for dir searches */
uint8 *kpath; /* points one after unixname */
uint8 *unixname; /* is allocates fullname of path */
/* + 257 Byte for filename. */
/* + 257 Byte for filename. */
} DIR_SEARCH_STRUCT;
typedef struct {
uint32 basehandle;
int namespace; /* namespace of this entry */
DIR_SEARCH_STRUCT *dir; /* for dir searches */
uint32 basehandle;
int namespace; /* namespace of this entry */
int slot; /* act slot in table */
int locked; /* if locked then do not remove */
DIR_SEARCH_STRUCT *dir; /* for dir searches */
N_NW_PATH nwpath;
} DIR_BASE_ENTRY;
#define MAX_DIR_BASE_ENTRIES 300
static DIR_BASE_ENTRY *dir_base[MAX_DIR_BASE_ENTRIES];
static int anz_dbe = 0;
@ -74,54 +75,74 @@ static void init_nwpath(N_NW_PATH *nwpath)
}
static char *xnwpath_2_unix(N_NW_PATH *nwpath, int modus,
int allocate_extra)
int allocate_extra, uint8 *extra_path)
/*
* returns complete UNIX path
* modus & 1 : ignore fn, (only path)
* modus & 2 : no '/' at end
*
* if allocate_extra > 0, then not the static buffer will be returned
* but a fresh allocated buffer, which must be deallocated later.
* if allocate_extra > 0, then the returned buffer must be
* deallocated later
*/
{
static char unixname[512]; /* should be big enouugh */
static char *last_unixname=NULL;
char *unixname;
int len;
int volume = nwpath->volume;
int volume = nwpath->volume;
int len_extra = (extra_path) ? strlen(extra_path) : 0;
char *p, *pp;
if (volume < 0 || volume >= used_nw_volumes) {
fprintf(stderr, "nwpath_2_unix volume=%d not ok\n", volume);
strcpy(unixname, "Z/Z/Z/Z"); /* */
len = strlen(unixname);
if (volume < 0 || volume >= used_nw_volumes || !nw_volumes[volume].unixnamlen ) {
char *errorstr="Z/Z/Z";
errorp(0, "xnwpath_2_unix", "volume=%d not ok", volume);
len = strlen(errorstr);
unixname=xmalloc(len_extra+allocate_extra+len+10);
strcpy(unixname, errorstr);
} else {
int m = ((modus & 1) && nwpath->fn > nwpath->path) /* last path = fn */
? nwpath->fn - nwpath->path
: strlen((char*)nwpath->path);
len = nw_volumes[volume].unixnamlen;
if (m+len >= sizeof(unixname)) {
fprintf(stderr, "nwpath_2_unix buffer to small, needs %d Byte",
m+len+1);
strcpy(unixname, "Z/Z/Z/Z"); /* */
len = strlen(unixname);
} else {
memcpy(unixname, nw_volumes[volume].unixname, len); /* first UNIXNAME VOLUME */
p = pp = unixname+len;
memcpy(p, nwpath->path, m); /* path or partiell path */
len += m;
p += m;
if ((modus & 2) && *(p-1) == '/' ) *(--p) = '\0';
else *p = '\0';
if (nw_volumes[volume].options & 1) downstr((uint8*)pp);
unixname=xmalloc(len_extra+allocate_extra+m+len+10);
memcpy(unixname, nw_volumes[volume].unixname, len);
/* first UNIXNAME VOLUME */
p = pp = unixname+len;
memcpy(p, nwpath->path, m); /* path or partiell path */
len += m;
p += m;
if ((modus & 2) && *(p-1) == '/' ) {
if (p > unixname+1) {
--p;
--len;
} else {
*p++ = '.';
++len;
}
} else if (len_extra) {
if (*(p-1) != '/') {
*p++='/';
len++;
}
memcpy(p, extra_path, len_extra);
p += len_extra;
len += len_extra;
}
*p = '\0';
if (nw_volumes[volume].options & VOL_OPTION_DOWNSHIFT)
downstr((uint8*)pp);
}
if (allocate_extra) {
char *ret=xmalloc(len+allocate_extra+2);
strcpy(ret, unixname);
return(ret);
if (!allocate_extra) {
xfree(last_unixname);
last_unixname=unixname;
}
return(unixname);
}
#define nwpath_2_unix(nwpath, modus) xnwpath_2_unix((nwpath), (modus), 0)
#define nwpath_2_unix(nwpath, modus) \
xnwpath_2_unix((nwpath), (modus), 0, NULL)
#define nwpath_2_unix1(nwpath, modus, extrabytes) \
xnwpath_2_unix((nwpath), (modus), (extrabytes), NULL)
#define nwpath_2_unix2(nwpath, modus, extrabytes, extrastr) \
xnwpath_2_unix((nwpath), (modus), (extrabytes), extrastr)
static void free_dbe_dir(DIR_BASE_ENTRY *dbe)
{
@ -135,17 +156,19 @@ static void free_dbe_dir(DIR_BASE_ENTRY *dbe)
static int allocate_dbe_dir(DIR_BASE_ENTRY *dbe)
{
DIR_SEARCH_STRUCT *d;
DIR_SEARCH_STRUCT *d=(DIR_SEARCH_STRUCT*) xcmalloc(sizeof(DIR_SEARCH_STRUCT));
if (dbe->dir) free_dbe_dir(dbe);
dbe->dir = d = (DIR_SEARCH_STRUCT*) xcmalloc(sizeof(DIR_SEARCH_STRUCT));
d->unixname = (uint8*)xnwpath_2_unix(&(dbe->nwpath), 2, 258);
if (NULL == (d->fdir = opendir(d->unixname))) {
dbe->dir = d;
d->unixname = (uint8*)nwpath_2_unix1(&(dbe->nwpath), 2, 258);
XDPRINTF((4, 0, "UNIXNAME='%s'", d->unixname));
d->fdir = opendir(d->unixname);
if (NULL == d->fdir) {
free_dbe_dir(dbe);
return(-0xff);
} else {
d->kpath = d->unixname+strlen(d->unixname);
*(d->kpath) = '/';
*(++d->kpath) = '\0';
d->kpath = d->unixname+strlen(d->unixname);
*(d->kpath) = '/';
*(++(d->kpath)) = '\0';
return(0);
}
}
@ -162,8 +185,12 @@ static int base_open_seek_dir(DIR_BASE_ENTRY *dbe, uint32 offset)
{
int result = ((dbe->nwpath.statb.st_mode & S_IFMT) != S_IFDIR) ? -0xff : 0;
if (!result) {
if (offset == MAX_U32) {
free_dbe_dir(dbe);
offset = 0L;
}
if (NULL == dbe->dir) result=allocate_dbe_dir(dbe);
if (result>-1) seekdir(dbe->dir->fdir, offset);
if (result > -1) seekdir(dbe->dir->fdir, offset);
}
if (result < 0 && NULL != dbe->dir) free_dbe_dir(dbe);
XDPRINTF((3, 0, "base_open_seek_dir offset=%d, result=%d", offset, result));
@ -171,59 +198,91 @@ static int base_open_seek_dir(DIR_BASE_ENTRY *dbe, uint32 offset)
}
static int allocate_dbe(int namespace)
static DIR_BASE_ENTRY *allocate_dbe_p(int namespace)
/* returns new allocated dir_base_entry */
{
int j=-1;
int to_use=-1;
DIR_BASE_ENTRY **pdbe=(DIR_BASE_ENTRY**) NULL;
if (namespace) return(-0xff); /* TODO: more namespaces */
while (++j < anz_dbe && NULL != *(pdbe = &(dir_base[j])) ) ;;
if (namespace) return(NULL); /* TODO: more namespaces */
while (++j < anz_dbe && NULL != *(pdbe = &(dir_base[j])) ){
if (to_use < 0 && !(*pdbe)->basehandle && !(*pdbe)->locked) to_use=j;
}
if (j == anz_dbe) {
if (anz_dbe == MAX_DIR_BASE_ENTRIES) { /* return(-0xff); */
pdbe = &(dir_base[--j]);
if (to_use > -1) j=to_use;
else while (j--) {
pdbe = &(dir_base[j]);
if (!(*pdbe)->locked) break; /* remove last not locked from list */
}
free_dbe_ptr(*pdbe);
} else pdbe = &(dir_base[anz_dbe++]);
}
*pdbe = (DIR_BASE_ENTRY*)xcmalloc(sizeof(DIR_BASE_ENTRY));
(*pdbe)->namespace = namespace;
(*pdbe)->slot = j;
init_nwpath(&((*pdbe)->nwpath));
return(j);
return(*pdbe);
}
static void free_dbe(int dbase)
static int allocate_dbe(int namespace)
{
if (dbase > -1 && dbase < anz_dbe) {
free_dbe_ptr(dir_base[dbase]);
dir_base[dbase] = (DIR_BASE_ENTRY*)NULL;
if (dbase+1 == anz_dbe) {
DIR_BASE_ENTRY *dbe=allocate_dbe_p(namespace);
return((NULL != dbe) ? dbe->slot : -1);
}
static void xx_free_dbe_p(DIR_BASE_ENTRY **dbe)
{
if (NULL != dbe && NULL != *dbe) {
int slot = (*dbe)->slot;
free_dbe_ptr(*dbe);
dir_base[slot] = *dbe = (DIR_BASE_ENTRY*)NULL;
if (slot+1 == anz_dbe) {
while (anz_dbe && ((DIR_BASE_ENTRY*)NULL == dir_base[anz_dbe-1]) )
--anz_dbe;
}
}
}
#define free_dbe_p(dbe) xx_free_dbe_p(&(dbe))
int touch_handle_entry(int dbase)
#define free_dbe(dbase) \
xx_free_dbe_p(((dbase) > -1 && (dbase) < anz_dbe) ? &(dir_base[dbase]) : NULL)
static int touch_handle_entry_p(DIR_BASE_ENTRY *dbe)
/* routine touchs this entry and returns the new offset */
{
int dbase = (NULL != dbe) ? dbe->slot : -1;
XDPRINTF((4, 0, "touch_handle_entry entry dbase=%d", dbase));
if (dbase > 2) {
DIR_BASE_ENTRY *dbe=dir_base[dbase];
while (dbase--) dir_base[dbase+1] = dir_base[dbase];
DIR_BASE_ENTRY **dbp=&(dir_base[dbase]);
while (dbase--) {
*dbp = *(dbp-1);
if (*dbp) (*dbp)->slot = dbase+1;
--dbp;
}
dbase=0;
dir_base[0] = dbe;
dbe->slot = 0;
}
XDPRINTF((4, 0, "touch_handle_entry return dbase=%d", dbase));
return(dbase);
}
#define touch_handle_entry(dbase) \
touch_handle_entry_p(((dbase) > -1 && (dbase) < anz_dbe) ? dir_base[dbase] : NULL)
char *debug_nwpath_name(N_NW_PATH *p)
/* for debugging */
/* only for debugging */
{
#if DO_DEBUG
static char nwpathname[512];
static char *nwpathname=NULL;
char volname[300];
if (nw_get_volume_name(p->volume, volname) < 0)
int len;
if (nw_get_volume_name(p->volume, volname) < 1)
sprintf(volname, "<%d=NOT-OK>", (int)p->volume);
len = strlen(volname) + strlen(p->path) + strlen(p->fn) + 30;
xfree(nwpathname);
nwpathname=xmalloc(len);
sprintf(nwpathname, "`%s:%s`,fn=`%s`", volname, p->path, p->fn);
#else
static char nwpathname[2];
@ -233,6 +292,18 @@ char *debug_nwpath_name(N_NW_PATH *p)
return(nwpathname);
}
static int get_comp_pathes_size(NW_HPATH *nwp, uint8 *pp_pathes)
{
int k = -1;
int size = 0;
while (++k < nwp->components) {
int len = (int) *(pp_pathes++);
pp_pathes+= len;
size += len;
size++;
}
return(size);
}
static int add_hpath_to_nwpath(N_NW_PATH *nwpath,
NW_HPATH *nwp, uint8 *pp_pathes)
@ -243,6 +314,9 @@ static int add_hpath_to_nwpath(N_NW_PATH *nwpath,
int result = 0;
int k = -1;
uint8 *pp = nwpath->path+strlen(nwpath->path);
XDPRINTF((2, 0, "entry add_hpath_to_nwpath: %s",
debug_nwpath_name(nwpath)));
while (!result && ++k < nwp->components) {
int len = (int) *(pp_pathes++);
uint8 *p = pp_pathes;
@ -287,25 +361,41 @@ static int add_hpath_to_nwpath(N_NW_PATH *nwpath,
} /* while */
if (nwpath->volume < 0) result=-0x9c;
leave_build_nwpath:
XDPRINTF((2, 0, "add_hpath_to_nwpath: result=0x%x, nwpath=%s",
XDPRINTF((2, 0, "add_hpath_to_nwpath: result=0x%x, %s",
result, debug_nwpath_name(nwpath)));
return(result);
}
static int nwp_stat(N_NW_PATH *nwpath, char *debstr)
{
uint8 *uname=nwpath_2_unix1(nwpath, 2, 1);
int result=stat(uname, &(nwpath->statb));
if (nw_debug) {
char xdebstr[2];
if (!debstr) {
xdebstr[0]='\0';
debstr = xdebstr;
}
XDPRINTF((4, 0, "nwp_stat:%s:%d,`%s`",
debstr,
result,
debug_nwpath_name(nwpath)));
}
xfree(uname);
return(result);
}
static uint32 build_base_handle(N_NW_PATH *nwpath, int namespace)
/* returns basehandle of path, or 0 if not exist !! */
{
uint32 basehandle=0L;
if (!stat(nwpath_2_unix(nwpath, 2), &(nwpath->statb))) {
if (!nwp_stat(nwpath, "build_base_handle")) {
DEV_NAMESPACE_MAP dnm;
dnm.dev = nwpath->statb.st_dev;
dnm.namespace = namespace;
basehandle=nw_vol_inode_to_handle(nwpath->volume,
basehandle = nw_vol_inode_to_handle(nwpath->volume,
nwpath->statb.st_ino,
&dnm);
} else {
XDPRINTF((4,0, "build_base_handle failed:`%s`",
debug_nwpath_name(nwpath)));
}
return(basehandle);
}
@ -322,11 +412,12 @@ static int find_base_entry(int volume, uint32 basehandle)
return(-0x9b);
}
static int insert_get_base_entry(N_NW_PATH *nwpath, int dbase,
static int insert_get_base_entry(DIR_BASE_ENTRY *dbe,
int namespace, int creatmode)
{
N_NW_PATH *nwpath = &(dbe->nwpath);
uint32 basehandle = build_base_handle(nwpath, namespace);
if (!basehandle && creatmode) {
if (!basehandle && creatmode) { /* now creat the entry (file or dir) */
int result = 0;
char *unname = nwpath_2_unix(nwpath, 2);
if (creatmode & FILE_ATTR_DIR) {
@ -342,27 +433,30 @@ static int insert_get_base_entry(N_NW_PATH *nwpath, int dbase,
if (result) return(result);
basehandle = build_base_handle(nwpath, namespace);
}
if (basehandle) {
DIR_BASE_ENTRY *dbe=dir_base[dbase];
int k=-1;
while (++k < anz_dbe) {
DIR_BASE_ENTRY *e=dir_base[k];
if ( (DIR_BASE_ENTRY*)NULL != e
&& basehandle == e->basehandle
&& basehandle == e->basehandle
&& nwpath->volume == e->nwpath.volume) {
free_dbe(dbase);
return(touch_handle_entry(k));
free_dbe_p(e);
dbe->basehandle = basehandle;
return(touch_handle_entry_p(dbe));
}
} /* while */
/* now i know that it's a new base entry */
dbe->basehandle = basehandle;
return(touch_handle_entry(dbase));
return(touch_handle_entry_p(dbe));
}
return(-0x9c);
return(-0xff); /* no files matching */
}
static int build_dos_base(NW_HPATH *nwp, uint8 *pathes,
int dbase, int mode, uint8 *rets)
static int build_dos_base(NW_HPATH *nwp,
uint8 *pathes,
int dbase,
int mode, uint8 *rets)
/* routine returns the actual dbe entry offset or */
/* < 0 if error */
/* if mode == 1, then last_path will be ignored and will be put */
@ -375,8 +469,11 @@ static int build_dos_base(NW_HPATH *nwp, uint8 *pathes,
int dir_handle = nwp->base[0];
if (dir_handle > 0 && --dir_handle < (int)used_dirs
&& dirs[dir_handle].inode) {
int llen = strlen(dirs[dir_handle].path);
nwpath->volume = dirs[dir_handle].volume;
strcpy(nwpath->path, dirs[dir_handle].path);
memcpy(nwpath->path, dirs[dir_handle].path, llen+1);
if (llen && *(nwpath->path + llen -1) == '/')
*(nwpath->path+llen-1) = '\0';
result = (nwpath->volume > -1) ? 0 : -0x98;
} else result = -0x9b;
} else if (nwp->flag == 1) { /* basehandle */
@ -411,7 +508,7 @@ static int build_dos_base(NW_HPATH *nwp, uint8 *pathes,
}
}
if (pp) nwpath->fn=(uint8*)pp+1;
result = insert_get_base_entry(nwpath, dbase, NAME_DOS, 0);
result = insert_get_base_entry(dbe, NAME_DOS, 0);
}
}
return(result);
@ -419,8 +516,8 @@ static int build_dos_base(NW_HPATH *nwp, uint8 *pathes,
int nw_generate_dir_path(int namespace,
NW_HPATH *nwp,
uint8 *ns_dir_base,
uint8 *dos_dir_base)
uint8 *ns_dir_base,
uint8 *dos_dir_base)
/* returns Volume Number >=0 or errcode < 0 if error */
{
@ -530,8 +627,8 @@ static int build_dir_info(DIR_BASE_ENTRY *dbe, uint32 infomask, uint8 *p)
result += (int) *p;
}
}
XDPRINTF((3, 0, "build_dir_info:path=%s, result=%d, basehandle=0x%x",
debug_nwpath_name(nwpath), result, dbe->basehandle));
XDPRINTF((3, 0, "build_dir_info:path=%s, result=%d, basehandle=0x%x, mask=0x%lx",
debug_nwpath_name(nwpath), result, dbe->basehandle, infomask));
return(result);
}
int nw_optain_file_dir_info(int namespace, NW_HPATH *nwp,
@ -547,12 +644,14 @@ int nw_optain_file_dir_info(int namespace, NW_HPATH *nwp,
int result = -0xfb;
if (dbase > -1) {
if ((result = build_dos_base(nwp, nwp->pathes, dbase, 0, NULL)) > -1) {
result = build_dir_info(dir_base[result], infomask, responsedata);
DIR_BASE_ENTRY *dbe=dir_base[result];
nwp_stat(&(dbe->nwpath), "nw_optain_file_dir_info");
result = build_dir_info(dbe, infomask, responsedata);
} else free_dbe(dbase);
}
if (result < 0) {
XDPRINTF((3, 0, "nw_optain_file_dir_info NOT OK dbase=%d, result=0x%x",
dbase, result));
XDPRINTF((3, 0, "nw_optain_file_dir_info NOT OK dbase=%d, result=-0x%x",
dbase, -result));
}
return(result);
}
@ -561,11 +660,11 @@ static int nw_init_search(int namespace,
NW_HPATH *nwp,
uint8 *responsedata)
{
int dbase = allocate_dbe(namespace);
DIR_BASE_ENTRY *dbe=allocate_dbe_p(namespace);
int result = -0xfb;
if (dbase > -1) {
if ((result = build_dos_base(nwp, nwp->pathes, dbase, 0, NULL)) > -1) {
DIR_BASE_ENTRY *dbe=dir_base[result];
if (NULL != dbe) {
if ((result = build_dos_base(nwp, nwp->pathes, dbe->slot, 0, NULL)) > -1) {
dbe=dir_base[result];
result = base_open_seek_dir(dbe, 0L);
if (result > -1) {
*responsedata++ = dbe->nwpath.volume;
@ -576,36 +675,33 @@ static int nw_init_search(int namespace,
}
XDPRINTF((3, 0, "nw_init_search path=%s, result=%d, basehandle=0x%x",
debug_nwpath_name(&(dbe->nwpath)), result, dbe->basehandle));
} else free_dbe(dbase);
} else free_dbe_p(dbe);
}
if (result < 0) {
XDPRINTF((3, 0, "nw_init_search NOT OK dbase=%d, result=%d",
dbase, result));
XDPRINTF((3, 0, "nw_init_search NOT OK result=%d", result));
}
return(result);
}
int get_add_new_entry(DIR_BASE_ENTRY *qbe, uint8 *path, int creatmode)
{
int dbase = allocate_dbe(qbe->namespace);
if (dbase > -1) {
DIR_BASE_ENTRY *dbe=dir_base[dbase];
DIR_BASE_ENTRY *dbe=allocate_dbe_p(qbe->namespace);
if (NULL != dbe) {
N_NW_PATH *nwpath=&(dbe->nwpath);
int result = -0x9c;
nwpath->volume=qbe->nwpath.volume;
nwpath->volume = qbe->nwpath.volume;
strcpy(nwpath->path, qbe->nwpath.path);
nwpath->fn = nwpath->path+strlen(nwpath->path);
if (nwpath->fn > nwpath->path && *(nwpath->fn-1) != '/') {
*(nwpath->fn) = '/';
*(++ nwpath->fn) = '\0';
*(++nwpath->fn) = '\0';
}
strcpy(nwpath->fn, path);
result = insert_get_base_entry(nwpath, dbase, qbe->namespace, creatmode);
if (result < 0) free_dbe(dbase);
result = insert_get_base_entry(dbe, qbe->namespace, creatmode);
if (result < 0) free_dbe_p(dbe);
return(result);
}
return(dbase);
return(-1);
}
int nw_search_file_dir(int namespace, int datastream,
@ -624,6 +720,7 @@ int nw_search_file_dir(int namespace, int datastream,
int dest_entry=-1;
DIR_SEARCH_STRUCT *ds=dbe->dir;
int vol_options = get_volume_options(volume, 0);
dbe->locked++;
strmaxcpy(entry, path, min(255, len));
if (vol_options & VOL_OPTION_DOWNSHIFT) downstr(entry);
XDPRINTF((5,0,"nw_search_file_dir searchpath=%s", entry));
@ -639,13 +736,22 @@ int nw_search_file_dir(int namespace, int datastream,
strcpy(ds->kpath, name);
XDPRINTF((5,0,"nw_search_file_dir Name found=%s unixname=%s",
name, ds->unixname));
if (!stat(ds->unixname, &statb)
&& ( !S_ISDIR(statb.st_mode) ||
(searchattrib & FILE_ATTR_DIR) ) ) {
strcpy(entry, name);
if (vol_options & 1) upstr(entry);
if ((dest_entry = get_add_new_entry(dbe, entry, 0)) > -1)
break;
if (!stat(ds->unixname, &statb)) {
int flag= (searchattrib & W_SEARCH_ATTR_ALL) == W_SEARCH_ATTR_ALL;
if (!flag) {
if (S_ISDIR(statb.st_mode))
flag=(searchattrib & FILE_ATTR_DIR);
else
flag = !(searchattrib & FILE_ATTR_DIR);
}
if (flag) {
strcpy(entry, name);
if (vol_options & VOL_OPTION_DOWNSHIFT) upstr(entry);
if ((dest_entry = get_add_new_entry(dbe, entry, 0)) > -1)
break;
}
} else {
XDPRINTF((5,0,"nw_search_file_dir stat error"));
}
}
} /* if */
@ -653,6 +759,7 @@ int nw_search_file_dir(int namespace, int datastream,
*(ds->kpath) = '\0';
if (dest_entry > -1) {
DIR_BASE_ENTRY *dest_dbe=dir_base[dest_entry];
(void) nwp_stat(&(dest_dbe->nwpath), "nw_search_file_dir");
sequence = (uint32) telldir(ds->fdir);
*responsedata = (uint8) volume;
responsedata++;
@ -666,7 +773,9 @@ int nw_search_file_dir(int namespace, int datastream,
build_dir_info(dest_dbe,
infomask|INFO_MSK_NAME_SPACE_INFO,
responsedata);
} else result=-0xfe; /* no files matching */
} else
result=-0xff; /* no files matching */
dbe->locked=0;
} /* if result */
}
return(result);
@ -714,7 +823,6 @@ static int nw_open_creat_file_or_dir(int namespace,
if ((result = file_creat_open(dbe->nwpath.volume,
nwpath_2_unix(&dbe->nwpath, 2), &(dbe->nwpath.statb),
attrib, access_rights, creatmode)) > -1) {
fhandle = (uint32) result;
actionresult |= OPC_ACTION_OPEN; /* FILE OPEN */
if (exist > -1 && (opencreatmode & OPC_MODE_REPLACE))
@ -745,7 +853,6 @@ static int nw_delete_file_dir(int namespace, int searchattrib,
if ((result = build_dos_base(nwp, nwp->pathes, dbase, 0, NULL)) > -1) {
DIR_BASE_ENTRY *dbe=dir_base[dbase=result];
uint8 *unname=(uint8*)nwpath_2_unix(&(dbe->nwpath), 2);
if (S_ISDIR(dbe->nwpath.statb.st_mode)) result = rmdir(unname);
else result = unlink(unname);
if (result < 0) {
@ -762,11 +869,76 @@ static int nw_delete_file_dir(int namespace, int searchattrib,
return(result);
}
int handle_func_0x57(uint8 *p, uint8 *responsedata)
static int nw_alloc_short_dir_handle(int namespace, int hmode,
NW_HPATH *nwp, int task, int *volume)
{
DIR_BASE_ENTRY *dbe=allocate_dbe_p(namespace);
int result = -0xfb;
if (NULL != dbe) {
if ((result = build_dos_base(nwp, nwp->pathes, dbe->slot, 0, NULL)) > -1) {
dbe=dir_base[result];
if (S_ISDIR(dbe->nwpath.statb.st_mode)) {
result=xinsert_new_dir(dbe->nwpath.volume, dbe->nwpath.path,
dbe->nwpath.statb.st_ino, 300, hmode, task);
*volume=dbe->nwpath.volume;
} else result=-0xff;
} else free_dbe_p(dbe);
}
return(result);
}
static int nw_rename_file_dir(int namespace,
NW_HPATH *nwps, uint8 *pathes_s,
NW_HPATH *nwpd, uint8 *pathes_d,
int searchattrib,
int renameflag)
{
DIR_BASE_ENTRY *dbe_s = allocate_dbe_p(namespace);
DIR_BASE_ENTRY *dbe_d = (NULL != dbe_s) ? allocate_dbe_p(namespace) : NULL;
int result = -0xfb;
if (dbe_d &&
(result = build_dos_base(nwps, pathes_s, dbe_s->slot, 0, NULL)) > -1) {
uint8 last_part[258];
uint8 *unname_s=
(uint8*)nwpath_2_unix1(&((dbe_s=dir_base[result])->nwpath),
2, 1);
if ((result = build_dos_base(nwpd, pathes_d, dbe_d->slot,
1, last_part)) > -1) {
uint8 *unname_d =
(uint8*)nwpath_2_unix2(&((dbe_d=dir_base[result])->nwpath),
0, 1, last_part);
if (S_ISDIR(dbe_s->nwpath.statb.st_mode))
result = unx_mvdir(unname_s, unname_d);
else
result = unx_mvfile(unname_s, unname_d);
XDPRINTF((5, 0, "Rename:%d '%s' -> '%s'", result, unname_s, unname_d));
xfree(unname_d);
switch (result) {
case 0 : break;
case EEXIST : result = -0x92; break;
default : result = -0xff;
}
if (!result) {
free_dbe_p(dbe_s);
if ((result=get_add_new_entry(dbe_d, last_part, 0)) > -1)
result = 0;
}
} else free_dbe_p(dbe_d);
xfree(unname_s);
} else free_dbe_p(dbe_s);
return(result);
}
int handle_func_0x57(uint8 *p, uint8 *responsedata, int task)
{
int result = -0xfb; /* unknown request */
int ufunc = (int) *p++; /* now p locates at 4 byte boundary */
int namespace = (int) *p; /* for most calls */
int namespace = (int) *p; /* for most calls */
XDPRINTF((3, 0, "0x57 call ufunc=0x%x namespace=%d", ufunc, namespace));
switch (ufunc) {
case 0x01 : /* open creat file or subdir */
@ -804,7 +976,7 @@ int handle_func_0x57(uint8 *p, uint8 *responsedata)
uint32 basehandle = GET_32(p+9); /* LOW-HI */
uint32 sequence = GET_32(p+13); /* LOW-HI */
int len = *(p+17);
uint8 *path = p+18;
uint8 *path = p+18;
result = nw_search_file_dir(namespace, datastream,
searchattrib, infomask,
volume, basehandle, sequence,
@ -812,6 +984,21 @@ int handle_func_0x57(uint8 *p, uint8 *responsedata)
}
break;
case 0x04 : /* rename File or Dir */
{
int renameflag = *(p+1);
int searchattrib = (int) GET_16(p+2); /* LOW-HI */
NW_HPATH nwps;
NW_HPATH nwpd;
int size;
p+=4;
memcpy(&nwps, p, 7); p+=7;
memcpy(&nwpd, p, 7); p+=7;
size = get_comp_pathes_size(&nwps, p);
result = nw_rename_file_dir(namespace,
&nwps, p, &nwpd, p+size, searchattrib, renameflag);
}
break;
case 0x06 : /* Obtain File or Subdir Info */
{
@ -830,6 +1017,7 @@ int handle_func_0x57(uint8 *p, uint8 *responsedata)
case 0x07 : /* Modify File or Dir Info */
{
}
break;
@ -841,24 +1029,43 @@ int handle_func_0x57(uint8 *p, uint8 *responsedata)
}
break;
case 0x09 : /* Set short Dir Handle*/
{
}
break;
case 0x0c : /* alloc short dir Handle */
{
int hmode = (int) GET_16(p+2); /* 0=p, 1=temp, 2=speztemp */
NW_HPATH *nwp = (NW_HPATH *)(p+4);
struct OUTPUT {
uint8 dir_handle;
uint8 volume;
uint8 reserved[4];
} *xdata= (struct OUTPUT*)responsedata;
int volume;
result = nw_alloc_short_dir_handle(namespace, hmode, nwp, task,
&volume);
if (result > -1) {
xdata->dir_handle = (uint8) result;
xdata->volume = (uint8) volume;
U32_TO_32(0L, xdata->reserved);
result=sizeof(struct OUTPUT);
}
}
break;
case 0x15 : /* Get Path String from short dir new */
{
int dir_handle=(int) *(p+1);
result=nw_get_directory_path(dir_handle, responsedata+1);
if (result > -1) {
*responsedata=(uint8) result;
result+=1;
}
}
break;

View File

@ -46,11 +46,16 @@ typedef struct {
#define INFO_MSK_DIR_ENTRY_INFO 0x00000400
#define INFO_MSK_RIGHTS_INFO 0x00000800
/* Attributes */
/* File Attributes */
#define FILE_ATTR_NORMAL 0x00000000
#define FILE_ATTR_DIR 0x00000010
#define FILE_ATTR_SHARE 0x00000080
/* Search Attributes */
#define W_SEARCH_ATTR_DIR 0x00008000
#define W_SEARCH_ATTR_ALL 0x00008006
/* OPEN/CREAT Modes */
#define OPC_MODE_OPEN 0x01
#define OPC_MODE_REPLACE 0x02
@ -62,6 +67,6 @@ typedef struct {
#define OPC_ACTION_REPLACE 0x04
extern int handle_func_0x57(uint8 *p, uint8 *responsedata);
extern int handle_func_0x57(uint8 *p, uint8 *responsedata, int task);
#endif

View File

@ -347,7 +347,7 @@ static int find_get_conn_nr(ipxAddr_t *addr)
}
}
if (connection) {
uint8 buff[sizeof(ipxAddr_t)+sizeof(uint16)];
uint8 buff[sizeof(ipxAddr_t)+sizeof(uint16)+sizeof(uint32)];
memcpy(buff, addr, sizeof(ipxAddr_t));
#if CALL_NWCONN_OVER_SOCKET
/* here i can use the nwconn socket */
@ -356,6 +356,8 @@ static int find_get_conn_nr(ipxAddr_t *addr)
/* and in this mode all must be go over ncpserv */
U16_TO_BE16(SOCK_NCP, buff+sizeof(ipxAddr_t));
#endif
U32_TO_BE32(connections[connection-1].pid,
buff+sizeof(ipxAddr_t)+sizeof(uint16));
nwserv_insert_conn(connection, (char*)buff, sizeof(buff));
}
return(connection);
@ -540,11 +542,14 @@ static void handle_ncp_request(void)
c->retry = 0;
return;
} else { /* 0x5555, close connection */
#if !CALL_NWCONN_OVER_SOCKET
if ( (uint8) (c->sequence+1) == (uint8) ncprequest->sequence)
#endif
{
#if 1
clear_connection(connection);
#endif
ncp_response(0x3333,
ncprequest->sequence,
connection,
@ -566,8 +571,8 @@ static void handle_ncp_request(void)
ncp_response(0x3333, ncprequest->sequence,
ncprequest->connection,
0, /* task */
0xff, /* completition */
0xff, /* conn status */
0xfe, /* completition */
0xf0, /* conn status */
0);
#if !CALL_NWCONN_OVER_SOCKET
@ -621,11 +626,11 @@ static void handle_ncp_request(void)
int main(int argc, char *argv[])
{
if (argc != 4) {
fprintf(stderr, "usage ncpserv nwname address nwbindsock\n");
exit(1);
}
init_tools(NCPSERV, 0);
if (argc != 4) {
errorp(1, "Usage:", "ncpserv nwname address nwbindsock");
return(1);
}
get_ini();
strncpy(my_nwname, argv[1], 48);
my_nwname[47] = '\0';
@ -636,7 +641,7 @@ int main(int argc, char *argv[])
#endif
if (open_ipx_sockets()) {
errorp(1, "open_ipx_sockets", NULL);
exit(1);
return(1);
}
XDPRINTF((1, 0, "USE_PERMANENT_OUT_SOCKET %s",

80
net.h
View File

@ -1,4 +1,4 @@
/* net.h 20-Mar-96 */
/* net.h 03-May-96 */
/* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany
*
@ -26,26 +26,33 @@
#ifndef LINUX
/* z.B. USL */
# include "sys/tiuser.h"
# include <sys/tiuser.h>
#endif
#include "sys/fcntl.h"
#include "sys/types.h"
#include "unistd.h"
#include <sys/fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>
#include <sys/wait.h>
#include <utmp.h>
#include <sys/errno.h>
extern int errno;
#ifndef LINUX
# include "stropts.h"
# include "poll.h"
# include "sys/nwctypes.h"
# include "sys/stream.h"
# include <stropts.h>
# include <poll.h>
# include <sys/nwctypes.h>
# include <sys/stream.h>
/* # include "common.h" */
/* # include "portable.h" , needed ??? */
# include "sys/ipx_app.h"
# include <sys/ipx_app.h>
#else
# include <sys/ioctl.h>
# include "emutli.h" /* TLI-EMULATION */
# include "emutli1.h" /* TLI-EMULATION */
#endif
#include <pwd.h>
@ -125,13 +132,18 @@
#endif
#ifndef MAX_CONNECTIONS
# define MAX_CONNECTIONS 5 /* maximum Number of Connections */
# define MAX_CONNECTIONS 5 /* maximum Number of connections */
#endif
#ifndef MAX_NW_VOLS
# define MAX_NW_VOLS 10
# define MAX_NW_VOLS 10 /* maximum Number of volumes */
#endif
#ifndef MAX_FILE_HANDLES_CONN
# define MAX_FILE_HANDLES_CONN 80
#endif
#ifndef MAX_NET_DEVICES
# define MAX_NET_DEVICES 5
#endif
@ -145,6 +157,18 @@
# define PATHNAME_BINDERY "." /* location of bindery files */
#endif
#ifndef PATHNAME_PIDFILES
# define PATHNAME_PIDFILES "/var/run" /* location of pidfiles */
#endif
#ifndef FILENAME_UTMP
# define FILENAME_UTMP UTMP_FILE
#endif
#ifndef FILENAME_WTMP
# define FILENAME_WTMP WTMP_FILE
#endif
#ifndef NETWORK_SERIAL_NMBR
# define NETWORK_SERIAL_NMBR 0x44444444L /* Serial Number 4 Byte */
#endif
@ -157,13 +181,26 @@
#endif
#ifndef WITH_NAME_SPACE_CALLS
# define WITH_NAME_SPACE_CALLS 0
# define WITH_NAME_SPACE_CALLS 1
#endif
#ifndef MAX_DIR_BASE_ENTRIES
# define MAX_DIR_BASE_ENTRIES 50
#endif
#ifndef MAX_NW_ROUTES
# define MAX_NW_ROUTES 50
#endif
#ifndef MAX_RIP_ENTRIES
# define MAX_RIP_ENTRIES 50
#endif
#if MAX_RIP_ENTRIES < 50
# undef MAX_RIP_ENTRIES
# define MAX_RIP_ENTRIES 50
#endif
#ifndef MAX_NW_SERVERS
# define MAX_NW_SERVERS MAX_NW_ROUTES
#endif
@ -175,26 +212,19 @@
#endif
#ifdef LINUX
# ifndef INTERNAL_RIP_SAP
# ifdef IN_NWROUTED
# undef INTERNAL_RIP_SAP
# define INTERNAL_RIP_SAP 1
# endif
# if INTERNAL_RIP_SAP
# ifndef FILE_SERVER_INACTIV
# define FILE_SERVER_INACTIV 0
# endif
# else
# undef FILE_SERVER_INACTIV
# define FILE_SERVER_INACTIV 0
# ifndef INTERNAL_RIP_SAP
# define INTERNAL_RIP_SAP 1
# endif
#else
/* USL has good rip/sap router */
/* USL has rip/sap router builtin */
# undef INTERNAL_RIP_SAP
# define INTERNAL_RIP_SAP 0
# undef FILE_SERVER_INACTIV
# define FILE_SERVER_INACTIV 0
#endif
#define MAX_SERVER_NAME 48
typedef union {

4
net1.c
View File

@ -53,6 +53,10 @@ static char str[200];
(int)p->net[0], (int)p->net[1], (int)p->net[2], (int)p->net[3],
(int)p->node[0], (int)p->node[1], (int)p->node[2], (int)p->node[3],
(int)p->node[4], (int)p->node[5], (int)p->sock[0], (int)p->sock[1]);
} else if (modus== 2) {
sprintf(str,"%02x%02x%02x%02x%02x%02x",
(int)p->node[0], (int)p->node[1], (int)p->node[2], (int)p->node[3],
(int)p->node[4], (int)p->node[5]);
} else strcpy(str, "??");
} else
strcpy(str, "net=UNKOWN(NULLPOINTER)");

171
nwbind.c
View File

@ -1,5 +1,5 @@
/* nwbind.c */
#define REVISION_DATE "21-Mar-96"
#define REVISION_DATE "05-May-96"
/* NCP Bindery SUB-SERVER */
/* authentification and some message handling */
@ -21,6 +21,7 @@
*/
#include "net.h"
#include "nwdbm.h"
#include "unxlog.h"
/* next should be '1', is for testing only */
#define USE_PERMANENT_OUT_SOCKET 1
@ -126,9 +127,39 @@ typedef struct {
uint8 message[60]; /* saved BCastmessage */
int active; /* 0=closed, 1= active */
int send_to_sock; /* this is the receiving sock */
int pid_nwconn; /* pid of user process nwconn */
} CONNECTION;
static CONNECTION connections[MAX_CONNECTIONS];
static CONNECTION *act_c=(CONNECTION*)NULL;
static int act_connection;
static int internal_act=0;
int b_acc(uint32 obj_id, int security, int forwrite)
{
/* security levels
* 0 = anyone have access.
* 1 = all logged have access
* 2 = object logged have access
* 3 = only supervisor has access
* 4 = only internal access.
*/
if (internal_act || !act_c) return(0); /* allways full access to internal routines */
if (forwrite) security >>= 4; /* writesecurity */
security &= 0x4;
if (!security) return(0); /* rights for all */
else if (security == 1) {
if (act_c->object_id > 0) return(0); /* rights for all logged */
} else if (security == 2) {
if ( act_c->object_id == obj_id
|| act_c->object_id == 1 ) return(0); /* rights for the user */
} else if (security == 3 && act_c->object_id == 1) return(0);
XDPRINTF((1, 0, "b_acc no rights for 0x%x to %s property",
act_c->object_id, forwrite ? "read" : "write" ));
return(forwrite ? -0xf8 : -0xfb);
}
static void sent_down_message(void)
{
@ -149,12 +180,16 @@ static void open_clear_connection(int conn, int activate, uint8 *addr)
CONNECTION *c = &connections[conn];
c->active = activate;
c->message[0] = '\0';
c->object_id = 0;
c->t_login = 0;
if (activate && addr) {
memcpy(&(c->client_adr), addr, sizeof(ipxAddr_t));
c->send_to_sock = GET_BE16(addr+sizeof(ipxAddr_t));
c->pid_nwconn = GET_BE32(addr+sizeof(ipxAddr_t)+sizeof(uint16));
} else {
if (c->object_id)
write_utmp(0, conn+1, c->pid_nwconn, &(c->client_adr), NULL);
}
c->object_id = 0;
}
}
@ -172,7 +207,7 @@ static void get_login_time(uint8 login_time[], CONNECTION *cx)
login_time[6] = s_tm->tm_wday;
}
static void handle_fxx(CONNECTION *c, int gelen, int func)
static void handle_fxx(int gelen, int func)
{
IPX_DATA ipxoutdata;
NCPRESPONSE *ncpresponse = (NCPRESPONSE*)&ipxoutdata;
@ -191,6 +226,7 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
if (nw_debug > 1){
int j = gelen - sizeof(NCPREQUEST);
if (nw_debug){
if (func == 0x19) ufunc=0;
XDPRINTF((1, 0, "NCP 0x%x REQUEST:ufunc:0x%x", func, ufunc));
if (j > 0){
uint8 *p=requestdata;
@ -236,8 +272,8 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
break;
case 0x01: { /* Get Broadcast Message (old) */
*responsedata = (uint8) strmaxcpy(responsedata+1, c->message, 58);
c->message[0] = '\0';
*responsedata = (uint8) strmaxcpy(responsedata+1, act_c->message, 58);
act_c->message[0] = '\0';
data_len = (int)(*responsedata) + 1;
}
break;
@ -385,17 +421,24 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
XDPRINTF((1, 0, "Supervisor tried unencrypted LOGIN"));
} else
#endif
internal_act = 1;
result=nw_test_unenpasswd(obj.id, password);
internal_act = 0;
} else {
XDPRINTF((1, 0, "unencryted logins are not enabled"));
result=-0xff;
}
}
if (!result) {
c->object_id = obj.id; /* actuell Object ID */
c->t_login = akttime; /* u. login Time */
get_guid((int*) responsedata, (int*)(responsedata+sizeof(int)), obj.id);
data_len = 2 * sizeof(int);
uint8 pw_name[40];
act_c->object_id = obj.id; /* actuell Object ID */
act_c->t_login = akttime; /* u. login Time */
get_guid((int*) responsedata, (int*)(responsedata+sizeof(int)), obj.id, pw_name);
result = get_home_dir(responsedata + 2*sizeof(int)+1, obj.id);
*(responsedata+ 2 * sizeof(int)) = (uint8) result;
data_len = 2 * sizeof(int) + 1 + (int) *(responsedata+2* sizeof(int));
write_utmp(1, act_connection, act_c->pid_nwconn, &from_addr, pw_name);
} else completition = (uint8) -result;
} break;
@ -457,8 +500,8 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
} break;
case 0x17 : { /* get crypt key */
int k = sizeof(c->crypt_key);
uint8 *p = c->crypt_key;
int k = sizeof(act_c->crypt_key);
uint8 *p = act_c->crypt_key;
uint8 *pp = responsedata;
data_len = k;
while (k--) *pp++ = *p++ =
@ -475,7 +518,7 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
break;
case 0x18 : { /* crypt_keyed LOGIN */
uint8 *p = rdata+sizeof(c->crypt_key);
uint8 *p = rdata+sizeof(act_c->crypt_key);
NETOBJ obj;
int result;
obj.type = GET_BE16(p);
@ -483,13 +526,21 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
xstrmaxcpy(obj.name, (char*)(p+3), *(p+2));
upstr(obj.name);
XDPRINTF((2, 0, "LOGIN CRYPTED PW NAME='%s'",obj.name));
if (0 == (result = find_obj_id(&obj, 0)))
result=nw_test_passwd(obj.id, c->crypt_key, rdata);
if (0 == (result = find_obj_id(&obj, 0))) {
internal_act = 1;
result=nw_test_passwd(obj.id, act_c->crypt_key, rdata);
internal_act = 0;
}
if (result > -1) {
c->object_id = obj.id; /* actuell Object */
c->t_login = akttime; /* and login time */
get_guid((int*)responsedata, (int*)(responsedata+sizeof(int)), obj.id);
data_len = 2 * sizeof(int);
uint8 pw_name[40];
act_c->object_id = obj.id; /* actuell Object */
act_c->t_login = akttime; /* and login time */
get_guid((int*)responsedata, (int*)(responsedata+sizeof(int)), obj.id, pw_name);
result = get_home_dir(responsedata + 2*sizeof(int)+1, obj.id);
*(responsedata+ 2 * sizeof(int)) = (uint8) result;
data_len = 2 * sizeof(int) + 1 + (int) *(responsedata+2* sizeof(int));
write_utmp(1, act_connection, act_c->pid_nwconn,
&from_addr, pw_name);
} else {
#if 0
/* this is not ok */
@ -500,6 +551,10 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
#endif
completition = (uint8) -result;
}
/* completition = 0xde menas login time has expired */
/* completition = 0xdf means good login, but */
/* login time has expired */
/* perhaps I will integrate it later */
}
break;
@ -554,7 +609,7 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
case 0x34 : { /* rename OBJECT, only SU */
int result=-0xff;
if (1 == c->object_id) {
if (1 == act_c->object_id) {
uint8 *p = rdata;
NETOBJ obj;
uint8 newname[256];
@ -642,7 +697,7 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
case 0x38 : { /* change Bindery Objekt Security */
/* only SU ! */
int result= -0xff;
if (1 == c->object_id) {
if (1 == act_c->object_id) {
uint8 *p = rdata;
NETOBJ obj;
obj.type = GET_BE16(p+1);
@ -789,14 +844,17 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
if (0 == (result = find_obj_id(&obj, 0))) {
XDPRINTF((6, 0, "CHPW: OLD=`%s`, NEW=`%s`", oldpassword,
newpassword));
if (c->object_id == 1 ||
internal_act = 1;
if (act_c->object_id == 1 ||
0 == (result=nw_test_unenpasswd(obj.id, oldpassword))){
if ( (c->object_id != 1)
if ( (act_c->object_id != 1)
|| *newpassword
|| !(password_scheme & PW_SCHEME_LOGIN))
result=nw_set_passwd(obj.id, newpassword, 0);
else result = -0xff;
}
internal_act = 0;
}
if (result < 0) completition = (uint8) -result;
} else {
@ -880,7 +938,7 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
#endif
NETOBJ obj;
obj.id = c->object_id;
obj.id = act_c->object_id;
if (0 != obj.id) {
int result = nw_get_obj(&obj);
if (!result) {
@ -930,14 +988,17 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
break;
case 0x4a : { /* keyed verify password */
uint8 *p = rdata+sizeof(c->crypt_key);
uint8 *p = rdata+sizeof(act_c->crypt_key);
NETOBJ obj;
int result;
obj.type = GET_BE16(p);
strmaxcpy((char*)obj.name, (char*)(p+3), *(p+2));
upstr(obj.name);
if (0 == (result = find_obj_id(&obj, 0)))
result=nw_test_passwd(obj.id, c->crypt_key, rdata);
if (0 == (result = find_obj_id(&obj, 0))) {
internal_act = 1;
result=nw_test_passwd(obj.id, act_c->crypt_key, rdata);
internal_act = 0;
}
if (result < 0) completition = (uint8) -result;
XDPRINTF((2,0, "Keyed Verify PW from OBJECT='%s', result=%d",
obj.name, result));
@ -946,7 +1007,7 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
#ifdef _CHANGE_PASSWD_TESTING_
case 0x4b : { /* keyed change pasword */
uint8 *p = rdata+sizeof(c->crypt_key);
uint8 *p = rdata+sizeof(act_c->crypt_key);
NETOBJ obj;
int result;
obj.type = GET_BE16(p);
@ -955,11 +1016,17 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
upstr(obj.name);
p += (*p+1); /* here is now password-type ?? 0x60,0x66 */
if (0 == (result = find_obj_id(&obj, 0)))
result=nw_test_passwd(obj.id, c->crypt_key, rdata);
if (0 == (result = find_obj_id(&obj, 0))) {
internal_act = 1;
result=nw_test_passwd(obj.id, act_c->crypt_key, rdata);
internal_act = 0;
}
#if 0
if (result > -1)
if (result > -1) {
internal_act = 1;
result=nw_set_enpasswd(obj.id, p+1);
internal_act = 0;
}
#endif
if (result< 0) completition = (uint8) -result;
XDPRINTF((1, 0, "Keyed Change PW from OBJECT='%s', result=0x%x",
@ -1066,11 +1133,12 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
case 0xc8 : { /* CHECK CONSOLE PRIVILEGES */
XDPRINTF((1, 0, "TODO: CHECK CONSOLE PRIV"));
/* !!!!!! TODO completition=0xc6 (no rights) */
if (act_c->object_id != 1) completition=0xc6; /* no rights */
} break;
case 0xc9 : { /* GET FILE SERVER DESCRIPTION STRINGs */
char *company = "Mars :-)";
char *revision = "Version %d.%d";
char *revision = "Version %d.%d.pl%d";
char *revision_date = REVISION_DATE;
char *copyright = "(C)opyright Martin Stover";
int k=strlen(company)+1;
@ -1079,7 +1147,7 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
strcpy(responsedata, company);
l = 1 + sprintf(responsedata+k, revision,
_VERS_H_, _VERS_L_ );
_VERS_H_, _VERS_L_, _VERS_P_ );
#if 0
k+=l;
#else
@ -1114,7 +1182,7 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
while (++k < anz_conns) {
int conn= (int) *co++;
if (conn == ncprequest->connection) {
strmaxcpy(c->message, msg, min(58, msglen));
strmaxcpy(act_c->message, msg, min(58, msglen));
connect_status = 0x40; /* don't know why */
} else if (conn && --conn < MAX_CONNECTIONS) {
CONNECTION *cc= &(connections[conn]);
@ -1125,14 +1193,14 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
}
}
} else {
strmaxcpy(c->message, msg, min(58, msglen));
strmaxcpy(act_c->message, msg, min(58, msglen));
connect_status = 0x40; /* don't know why */
}
}
break;
case 0xd3 : { /* down File Server */
if (c->object_id == 1) { /* only SUPERVISOR */
if (act_c->object_id == 1) { /* only SUPERVISOR */
/* inform nwserv */
nwserv_down_server();
} else completition = 0xff;
@ -1148,7 +1216,8 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
default : completition = 0xfb; /* not known here */
} /* switch */
} else if (func == 0x19) { /* logout */
c->object_id = 0; /* not LOGIN */
write_utmp(0, act_connection, act_c->pid_nwconn, &from_addr, NULL);
act_c->object_id = 0; /* not LOGIN */
} else completition = 0xfb;
U16_TO_BE16(0x3333, ncpresponse->type);
@ -1157,10 +1226,10 @@ static void handle_fxx(CONNECTION *c, int gelen, int func)
ncpresponse->reserved = 0;
ncpresponse->completition = completition;
if (c->message[0]) connect_status |= 0x40;
if (act_c->message[0]) connect_status |= 0x40;
ncpresponse->connect_status = connect_status;
data_len+=sizeof(NCPRESPONSE);
U16_TO_BE16(c->send_to_sock, my_addr.sock);
U16_TO_BE16(act_c->send_to_sock, my_addr.sock);
send_ipx_data(ipx_out_fd, 17, data_len, (char*)ncpresponse,
&my_addr, NULL);
@ -1245,10 +1314,10 @@ static void handle_ctrl(void)
int size = 0;
if (sizeof (int) ==
xread(&ipxd, &offs, (uint8*)&(size), sizeof(int))
&& size == sizeof(ipxAddr_t) + sizeof(uint16)) {
&& size == sizeof(ipxAddr_t)
+ sizeof(uint16) + sizeof(uint32) ) {
uint8 buf[100];
if (size ==
xread(&ipxd, &offs, buf, size))
if (size == xread(&ipxd, &offs, buf, size))
open_clear_connection(conn, 1, buf);
}
}
@ -1323,10 +1392,12 @@ int main(int argc, char *argv[])
sscanf(argv[3], "%x", &sock_nwbind);
internal_act = 1;
if (nw_init_dbm(my_nwname, &my_addr) <0) {
errorp(1, "nw_init_dbm", NULL);
exit(1);
}
internal_act = 0;
#ifdef LINUX
set_emu_tli();
@ -1354,31 +1425,35 @@ int main(int argc, char *argv[])
set_sig();
while (got_sig != SIGQUIT) {
act_c = (CONNECTION*)NULL;
if (t_rcvudata(ncp_fd, &ud, &rcv_flags) > -1){
time(&akttime);
XDPRINTF((10, 0, "NWBIND-LOOP from %s", visable_ipx_adr(&from_addr)));
if ( ncprequest->type[0] == 0x22
&& ncprequest->type[1] == 0x22) {
int conn = ((int)ncprequest->connection) - 1;
if (conn > -1 && conn < MAX_CONNECTIONS) {
CONNECTION *c=&(connections[conn]);
if (c->active && IPXCMPNODE(from_addr.node, my_addr.node)
act_connection = ((int)ncprequest->connection);
if (act_connection > 0 && act_connection <= MAX_CONNECTIONS) {
act_c = &(connections[act_connection-1]);
internal_act = 0;
if (act_c->active && IPXCMPNODE(from_addr.node, my_addr.node)
&& IPXCMPNET (from_addr.net, my_addr.net)) {
handle_fxx(c, ud.udata.len, (int)ncprequest->function);
handle_fxx(ud.udata.len, (int)ncprequest->function);
} else {
XDPRINTF((1, 0, "NWBIND-LOOP addr of connection=%d is wrong",
conn+1));
act_connection));
}
} else {
XDPRINTF((1, 0, "NWBIND-LOOP connection=%d is wrong",
conn+1));
act_connection));
}
} else if ( ncprequest->type[0] == 0xee
&& ncprequest->type[1] == 0xee
&& IPXCMPNODE(from_addr.node, my_addr.node)
&& IPXCMPNET (from_addr.net, my_addr.net)) {
/* comes from nwserv, i hope :) */
handle_ctrl();
} else {
XDPRINTF((1, 0, "NWBIND-LOOP got wrong type 0x%x func=0x%x",
(int) GET_BE16(ncprequest->type), (int) ncprequest->function));

View File

@ -1,4 +1,4 @@
/* nwconn.c 21-Mar-96 */
/* nwconn.c 04-May-96 */
/* one process / connection */
/* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany
@ -23,6 +23,7 @@
#include "nwvolume.h"
#include "nwfile.h"
#include "connect.h"
#include "nwqueue.h"
#include "namspace.h"
@ -100,6 +101,7 @@ static void pr_debug_request()
switch (ncprequest->function) {
case 0x16 :
case 0x17 : ufunc = (int) *(requestdata+2); break;
case 0x57 : ufunc = (int) *(requestdata); break;
default : break;
} /* switch */
XDPRINTF((0, 0, "NCP REQUEST: func=0x%02x, ufunc=0x%02x, seq:%03d, task:%02d",
@ -175,9 +177,12 @@ static int handle_ncp_serv(void)
if ((result = nw_get_volume_name(volume, xdata->name))>-1){
struct fs_usage fsp;
if (!nw_get_fs_usage(xdata->name, &fsp)) {
U16_TO_BE16(1000, xdata->sec_per_block); /* hard coded */
U16_TO_BE16(fsp.fsu_blocks/1000, xdata->total_blocks);
U16_TO_BE16(fsp.fsu_bavail/1000, xdata->avail_blocks);
int sector_scale=1;
while (fsp.fsu_blocks/sector_scale > 0xffff)
sector_scale*=2;
U16_TO_BE16(sector_scale, xdata->sec_per_block);
U16_TO_BE16(fsp.fsu_blocks/sector_scale, xdata->total_blocks);
U16_TO_BE16(fsp.fsu_bavail/sector_scale, xdata->avail_blocks);
U16_TO_BE16(fsp.fsu_files, xdata->total_dirs);
U16_TO_BE16(fsp.fsu_ffree, xdata->avail_dirs);
if ( get_volume_options(volume, 1) & VOL_OPTION_REMOUNT) {
@ -360,6 +365,17 @@ static int handle_ncp_serv(void)
} *input = (struct INPUT *) (ncprequest);
/* TODO !!!!!!!!!!!!!!!!!!!! */
do_druck++;
} else if (*p == 0xf){ /* rename dir */
/******** Rename DIR *********************/
int dir_handle = (int) *(p+1);
int oldpathlen = (int) *(p+2);
uint8 *oldpath = p+3;
int newpathlen = (int) *(oldpath + oldpathlen);
uint8 *newpath = oldpath + oldpathlen + 1;
int code = mv_dir(dir_handle,
oldpath, oldpathlen,
newpath, newpathlen);
if (code) completition = (uint8) -code;
} else if (*p == 0x12 /* Allocate Permanent Dir Handle */
/******** Allocate Permanent DIR Handle **/
@ -408,9 +424,12 @@ static int handle_ncp_serv(void)
if (result > -1) {
struct fs_usage fsp;
if (!nw_get_fs_usage(xdata->name, &fsp)) {
U16_TO_BE16(1000, xdata->sectors);
U16_TO_BE16(fsp.fsu_blocks/1000, xdata->total_blocks);
U16_TO_BE16(fsp.fsu_bavail/1000, xdata->avail_blocks);
int sector_scale=1;
while (fsp.fsu_blocks/sector_scale > 0xffff)
sector_scale*=2;
U16_TO_BE16(sector_scale, xdata->sectors);
U16_TO_BE16(fsp.fsu_blocks/sector_scale, xdata->total_blocks);
U16_TO_BE16(fsp.fsu_bavail/sector_scale, xdata->avail_blocks);
U16_TO_BE16(fsp.fsu_files, xdata->total_dirs);
U16_TO_BE16(fsp.fsu_ffree, xdata->avail_dirs);
if (get_volume_options(volume, 1) & VOL_OPTION_REMOUNT) {
@ -672,8 +691,8 @@ static int handle_ncp_serv(void)
break;
#endif
case 0x14:
case 0x18:
case 0x14: /* Login Objekt, unencrypted passwords */
case 0x18: /* crypt_keyed LOGIN */
return(-2); /* nwbind must do prehandling */
@ -781,6 +800,7 @@ static int handle_ncp_serv(void)
case 0x19 : /* logout, some of this call is handled in ncpserv. */
nw_free_handles(0);
set_default_guid();
nw_setup_home_vol(-1, NULL);
return(-1); /* nwbind must do rest */
break;
@ -944,6 +964,36 @@ static int handle_ncp_serv(void)
}
break;
case 0x41 : { /* open file for reading */
struct INPUT {
uint8 header[7]; /* Requestheader */
uint8 dirhandle; /* Dirhandle */
uint8 attrib; /* z.B. 0x6 od. 0x4e */
/* O_RDWR|TRUNC 0x6, O_RDONLY 0x6 */
uint8 len; /* namelaenge */
uint8 data[2]; /* Name */
} *input = (struct INPUT *)ncprequest;
struct OUTPUT {
uint8 ext_fhandle[2]; /* all zero */
uint8 fhandle[4]; /* Dateihandle */
uint8 reserve2[2]; /* z.B 0x0 0x0 */
NW_FILE_INFO fileinfo;
} *xdata= (struct OUTPUT*)responsedata;
int fhandle=nw_creat_open_file((int)input->dirhandle,
input->data, input->len,
&(xdata->fileinfo),
(int)input->attrib,
0x1, 0);
if (fhandle > -1){
U32_TO_BE32(fhandle, xdata->fhandle);
U16_TO_BE16(0, xdata->ext_fhandle);
U16_TO_BE16(0, xdata->reserve2);
data_len = sizeof(struct OUTPUT);
} else completition = (uint8) (-fhandle);
}
break;
case 0x42 : /* close file */
{
struct INPUT {
@ -1086,12 +1136,12 @@ static int handle_ncp_serv(void)
uint8 filler;
uint8 ext_fhandle[2]; /* all zero */
uint8 fhandle[4]; /* filehandle */
uint8 offset[4]; /* alles 0 */
uint8 max_size[2]; /* zu lesende Bytes */
uint8 offset[4];
uint8 max_size[2]; /* byte to readd */
} *input = (struct INPUT *)ncprequest;
struct OUTPUT {
uint8 size[2]; /* Lese Bytes */
uint8 data[1072]; /* max data */
uint8 size[2]; /* read byzes */
uint8 data[1072]; /* max data */
} *xdata=(struct OUTPUT*)responsedata;
int fhandle = GET_BE32(input->fhandle);
int max_size = GET_BE16(input->max_size);
@ -1231,7 +1281,7 @@ static int handle_ncp_serv(void)
#if WITH_NAME_SPACE_CALLS
case 0x57 : /* some new namespace calls */
{
int result = handle_func_0x57(requestdata, responsedata);
int result = handle_func_0x57(requestdata, responsedata, ncprequest->task);
if (result > -1) data_len = result;
else completition=(uint8)-result;
}
@ -1310,9 +1360,12 @@ static void handle_after_bind()
uint8 ufunc = *(requestdata+2);
uint8 *rdata = requestdata+3;
switch (ufunc) {
case 0x14:
case 0x18: { /* ncpserv have change the structure */
case 0x14: /* Login Objekt, unencrypted passwords */
case 0x18: { /* crypt_keyed LOGIN */
int fnlen = (int) *(bindresponse + 2 * sizeof(int));
/* ncpserv have changed the structure */
set_guid(*((int*)bindresponse), *((int*)(bindresponse+sizeof(int))));
nw_setup_home_vol(fnlen, bindresponse + 2 * sizeof(int) +1);
}
break;

86
nwdbm.c
View File

@ -1,4 +1,4 @@
/* nwdbm.c 20-Mar-96 data base for mars_nwe */
/* nwdbm.c 30-Apr-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
@ -26,9 +26,12 @@
#include "nwcrypt.h"
#ifdef LINUX
# include <ndbm.h>
# define SHADOW_PWD 0
# ifndef SHADOW_PWD
# define SHADOW_PWD 0
# endif
#else
# include </usr/ucbinclude/ndbm.h>
# undef SHADOW_PWD
# define SHADOW_PWD 1
#endif
@ -372,14 +375,16 @@ static int loc_change_prop_security(NETPROP *p, uint32 obj_id)
if (data.dptr != NULL && name_match(prop->name, p->name) ) {
uint8 security = p->security;
XDPRINTF((2,0, "found PROP %s, id=0x%x", prop->name, (int) prop->id));
result = 0;
memcpy(p, prop, sizeof(NETPROP));
p->security = security;
data.dptr = (char*)p;
data.dsize = sizeof(NETPROP);
key.dptr = (char *)p;
key.dsize = NETPROP_KEY_SIZE;
if (store(key, data)) result=-0xff;
result = b_acc(obj_id, prop->security, 1);
if (!result) {
memcpy(p, prop, sizeof(NETPROP));
p->security = security;
data.dptr = (char*)p;
data.dsize = sizeof(NETPROP);
key.dptr = (char *)p;
key.dsize = NETPROP_KEY_SIZE;
if (store(key, data)) result=-0xff;
}
break;
}
}
@ -526,17 +531,19 @@ L1:
return(result);
}
int ins_prop_val(uint32 obj_id, uint8 prop_id, int segment,
static int ins_prop_val(uint32 obj_id, NETPROP *prop, int segment,
uint8 *property_value, int erase_segments)
{
int result = -0xec; /* no such Segment */
int result = b_acc(obj_id, prop->security, 1);
if (result) return(result);
if (!dbminit(FNVAL)){
NETVAL val;
int flag = 1;
key.dsize = NETVAL_KEY_SIZE;
key.dptr = (char*)&val;
val.obj_id = obj_id;
val.prop_id = (uint8)prop_id;
val.prop_id = (uint8)prop->id;
result = -0xec; /* no such Segment */
if (segment > 1) {
val.segment = segment-1;
data = fetch(key);
@ -722,7 +729,7 @@ int nw_write_prop_value(int object_type,
if ((result = find_obj_id(&obj, 0)) == 0){
if ((result=find_first_prop_id(&prop, obj.id))==0){
result=ins_prop_val(obj.id, prop.id, segment_nr,
result=ins_prop_val(obj.id, &prop, segment_nr,
property_value, erase_segments);
}
@ -745,10 +752,9 @@ int nw_change_prop_security(int object_type,
XDPRINTF((2,0, "nw_change_prop_security obj=%s,0x%x, prop=%s",
obj.name, object_type, prop.name));
obj.type = (uint16) object_type;
if ((result = find_obj_id(&obj, 0)) == 0){
result=loc_change_prop_security(&prop, obj.id);
}
return(result);
if ((result = find_obj_id(&obj, 0)) == 0)
return(loc_change_prop_security(&prop, obj.id));
return(-0xff);
}
int nw_scan_property(NETPROP *prop,
@ -960,16 +966,18 @@ uint32 nw_new_obj_prop(uint32 wanted_id,
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);
ins_prop_val(obj.id, &prop, 1, locvalue, 0xff);
}
}
return(obj.id);
}
typedef struct {
int pw_uid;
int pw_gid;
char pw_passwd[80];
int pw_uid;
int pw_gid;
char pw_passwd[80];
uint8 pw_dir[257];
uint8 pw_name[20];
} MYPASSWD;
static MYPASSWD *nw_getpwnam(uint32 obj_id)
@ -979,10 +987,13 @@ static MYPASSWD *nw_getpwnam(uint32 obj_id)
if (nw_get_prop_val_str(obj_id, "UNIX_USER", buff) > 0){
struct passwd *pw = getpwnam(buff);
if (NULL != pw) {
memcpy(&pwstat, pw, sizeof(struct passwd));
if (obj_id != 1 && pw->pw_uid == 1)
return(NULL); /* only supervisor -> root */
pwstat.pw_uid = pw->pw_uid;
pwstat.pw_gid = pw->pw_gid;
xstrcpy(pwstat.pw_passwd, pw->pw_passwd);
xstrcpy(pwstat.pw_name, pw->pw_name);
xstrcpy(pwstat.pw_dir, pw->pw_dir);
#if SHADOW_PWD
if (pwstat.pw_passwd[0] == 'x' && pwstat.pw_passwd[1]=='\0') {
struct spwd *spw=getspnam(buff);
@ -998,21 +1009,42 @@ static MYPASSWD *nw_getpwnam(uint32 obj_id)
return(NULL);
}
int get_guid(int *gid, int *uid, uint32 obj_id)
int get_guid(int *gid, int *uid, uint32 obj_id, uint8 *name)
/* searched for gid und uid of actual obj */
{
MYPASSWD *pw = nw_getpwnam(obj_id);
if (NULL != pw) {
*gid = pw->pw_gid;
*uid = pw->pw_uid;
if (name) strmaxcpy(name, pw->pw_name, 20);
return(0);
} else {
*gid = -1;
*uid = -1;
if (name) strcpy(name, "UNKNOWN");
return(-0xff);
}
}
int get_home_dir(uint8 *homedir, uint32 obj_id)
/* searches for UNIX homedir of actual obj */
{
MYPASSWD *pw = nw_getpwnam(obj_id);
if (NULL != pw) {
int len=strlen(pw->pw_dir);
if (!len) {
*homedir++ = '/';
*homedir = '\0';
len =1;
} else
strmaxcpy(homedir, pw->pw_dir, min(255, len));
return(len);
} else {
*homedir='\0';
return(0);
}
}
static int crypt_pw_ok(uint8 *password, char *passwd)
/* returns 0 if not ok */
{
@ -1221,7 +1253,7 @@ static void add_user(uint32 u_id, uint32 g_id,
add_user_to_group(u_id, g_id);
if (unname && *unname)
nw_new_obj_prop(u_id, NULL, 0 , 0 , 0 ,
"UNIX_USER", P_FL_ITEM, 0x33,
"UNIX_USER", P_FL_ITEM, 0x33,
(char*)unname, strlen(unname));
if (password && *password) {
@ -1237,7 +1269,7 @@ static void add_group(char *name, char *unname, char *password)
(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,
"UNIX_GROUP", P_FL_ITEM, 0x33,
(char*)unname, strlen(unname));
}
@ -1453,7 +1485,7 @@ int nw_fill_standard(char *servername, ipxAddr_t *adr)
int gid;
int uid;
sprintf(sx, "%lx", objs[ocount]);
if (!get_guid(&gid, &uid, objs[ocount]))
if (!get_guid(&gid, &uid, objs[ocount], NULL))
test_add_dir(unixname, ppp, 1, downshift, 0770, gid, uid, sx);
else {
NETOBJ obj;

13
nwdbm.h
View File

@ -1,4 +1,4 @@
/* nwdbm.h 22-Feb-96 */
/* nwdbm.h 30-Apr-96 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
@ -68,6 +68,8 @@ extern int password_scheme;
#define PW_SCHEME_GET_KEY_FAIL 4
#define PW_SCHEME_ALLOW_EMPTY_PW 8
/* next routine is in nwbind.c !!!! */
extern int b_acc(uint32 obj_id, int security, int forwrite);
extern void sync_dbm(void);
@ -93,12 +95,6 @@ extern int prop_find_member(uint32 obj_id, int prop_id, uint32 member_id);
extern int prop_add_member(uint32 obj_id, int prop_id, uint32 member_id);
extern int prop_delete_member(uint32 obj_id, int prop_id, uint32 member_id);
extern int ins_prop_val(uint32 obj_id, uint8 prop_id, int segment,
uint8 *property_value, int erase_segments);
extern int nw_get_prop_val_by_obj_id(uint32 obj_id,
int segment_nr,
uint8 *prop_name, int prop_namlen,
@ -179,7 +175,8 @@ extern uint32 nw_new_obj_prop(uint32 wanted_id,
char *propname, int propflags, int propsecurity,
char *value, int valuesize);
extern int get_guid(int *gid, int *uid, uint32 obj_id);
extern int get_guid(int *gid, int *uid, uint32 obj_id, uint8 *name);
extern int get_home_dir(uint8 *homedir, 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);

123
nwfile.c
View File

@ -1,4 +1,4 @@
/* nwfile.c 23-Jan-96 */
/* nwfile.c 01-May-96 */
/* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
@ -27,12 +27,9 @@
#include "nwfile.h"
#include "connect.h"
#define MAX_FILEHANDLES 80
static FILE_HANDLE file_handles[MAX_FILEHANDLES];
static FILE_HANDLE file_handles[MAX_FILE_HANDLES_CONN];
static int anz_fhandles=0;
static int new_file_handle(uint8 *unixname)
{
int rethandle = -1;
@ -45,7 +42,7 @@ static int new_file_handle(uint8 *unixname)
} else fh=NULL;
}
if (fh == NULL) {
if (anz_fhandles < MAX_FILEHANDLES) {
if (anz_fhandles < MAX_FILE_HANDLES_CONN) {
fh=&(file_handles[anz_fhandles]);
rethandle = ++anz_fhandles;
} else return(0); /* no free handle anymore */
@ -69,7 +66,7 @@ static int free_file_handle(int fhandle)
FILE_HANDLE *fh=&(file_handles[fhandle-1]);
if (fh->fd > -1) {
if (fh->flags & 2) {
if (fh->f) pclose(fh->f);
if (fh->f) ext_pclose(fh->f);
fh->f = NULL;
} else close(fh->fd);
if (fh->tmodi > 0L && !(fh->flags & 2)) {
@ -107,7 +104,8 @@ int file_creat_open(int volume, uint8 *unixname, struct stat *stbuff,
/*
* creatmode: 0 = open | 1 = creat | 2 = creatnew & 4 == save handle
* attrib ??
* access: 0x1=read, 0x2=write
* access: 0x1=readonly, 0x2=writeonly, 0x4=deny read, 0x5=deny write
*
*/
{
int fhandle=new_file_handle(unixname);
@ -115,19 +113,20 @@ int file_creat_open(int volume, uint8 *unixname, struct stat *stbuff,
FILE_HANDLE *fh=&(file_handles[fhandle-1]);
int completition = -0xff; /* no File Found */
if (get_volume_options(volume, 1) & VOL_OPTION_IS_PIPE) {
/* this is a PIPE Dir */
/* this is a PIPE Volume */
int statr = stat(fh->fname, stbuff);
if (!statr && (stbuff->st_mode & S_IFMT) != S_IFDIR) {
int dowrite= (access & 2) || creatmode ;
char pipecommand[300];
char *pipeopen = (creatmode || (access & 2)) ? "w" : "r";
char *topipe = "READ";
if (creatmode) topipe = "CREAT";
else if (access & 2) topipe = "WRITE";
char *topipe = "READ";
if (creatmode) topipe = "CREAT";
else if (dowrite) topipe = "WRITE";
sprintf(pipecommand, "%s %s", fh->fname, topipe);
fh->f = popen(pipecommand, pipeopen);
fh->fd = (fh->f) ? fileno(fh->f) : -1;
fh->f = ext_popen(pipecommand, geteuid(), getegid());
fh->fd = (fh->f) ? fileno(fh->f->fildes[1]) : -1;
if (fh->fd > -1) {
fh->flags |= 2;
if (!dowrite) stbuff->st_size = 0x7fffffff;
if (creatmode & 4) fh->flags |= 4;
return(fhandle);
}
@ -158,7 +157,7 @@ int file_creat_open(int volume, uint8 *unixname, struct stat *stbuff,
}
} else {
int statr = stat(fh->fname, stbuff);
int acm = (access & 2) ? (int) O_RDWR /*|O_CREAT*/ : (int)O_RDONLY;
int acm = (access & 2) ? (int) O_RDWR : (int)O_RDONLY;
if ( (!statr && (stbuff->st_mode & S_IFMT) != S_IFDIR)
|| (statr && (acm & O_CREAT))){
XDPRINTF((5,0,"OPEN FILE with attrib:0x%x, access:0x%x, fh->fname:%s: fhandle=%d",attrib,access, fh->fname, fhandle));
@ -203,8 +202,8 @@ int nw_close_datei(int fhandle, int reset_reuse)
int result2;
if (fh->flags & 2) {
if (fh->f) {
result=pclose(fh->f);
if (result) result = -1;
result=ext_pclose(fh->f);
if (result > 0) result = 0;
}
fh->f = NULL;
} else result=close(fh->fd);
@ -241,12 +240,23 @@ int nw_read_datei(int fhandle, uint8 *data, int size, uint32 offset)
if (fhandle > 0 && (--fhandle < anz_fhandles)) {
FILE_HANDLE *fh=&(file_handles[fhandle]);
if (fh->fd > -1) {
if (fh->offd != (long)offset)
fh->offd=lseek(fh->fd, offset, SEEK_SET);
if (fh->offd > -1L) {
size = read(fh->fd, data, size);
fh->offd+=(long)size;
} else size = -1;
if (fh->flags & 2) { /* PIPE */
size = fread(data, 1, size, fh->f->fildes[1]);
} else {
if (fh->offd != (long)offset) {
fh->offd=lseek(fh->fd, offset, SEEK_SET);
if (fh->offd < 0) {
XDPRINTF((5,0,"read-file failed in lseek"));
}
}
if (fh->offd > -1L) {
if ((size = read(fh->fd, data, size)) > -1)
fh->offd+=(long)size;
else {
XDPRINTF((5,0,"read-file failed in read"));
}
} else size = -1;
}
return(size);
}
}
@ -258,12 +268,16 @@ int nw_seek_datei(int fhandle, int modus)
if (fhandle > 0 && (--fhandle < anz_fhandles)) {
FILE_HANDLE *fh=&(file_handles[fhandle]);
if (fh->fd > -1) {
int size=-0xfb;
if (!modus) {
if ( (size=fh->offd=lseek(fh->fd, 0L, SEEK_END)) < 0L)
size = -1;
if (fh->flags & 2) { /* PIPE */
return(0x7fffffff);
} else {
int size=-0xfb;
if (!modus) {
if ( (size=fh->offd=lseek(fh->fd, 0L, SEEK_END)) < 0L)
size = -1;
}
return(size);
}
return(size);
}
}
return(-0x88); /* wrong filehandle */
@ -275,27 +289,35 @@ int nw_write_datei(int fhandle, uint8 *data, int size, uint32 offset)
if (fhandle > 0 && (--fhandle < anz_fhandles)) {
FILE_HANDLE *fh=&(file_handles[fhandle]);
if (fh->fd > -1) {
if (fh->offd != (long)offset)
fh->offd = lseek(fh->fd, offset, SEEK_SET);
if (size) {
if (fh->offd > -1L) {
size = write(fh->fd, data, size);
fh->offd+=(long)size;
} else size = -1;
return(size);
} else { /* strip FILE */
/* TODO: for LINUX */
struct flock flockd;
int result= /* -1 */ 0;
flockd.l_type = 0;
flockd.l_whence = SEEK_SET;
flockd.l_start = offset;
flockd.l_len = 0;
#if HAVE_TLI
result = fcntl(fh->fd, F_FREESP, &flockd);
XDPRINTF((5,0,"File %s is stripped, result=%d", fh->fname, result));
if (fh->flags & 2) { /* PIPE */
if (size)
return(fwrite(data, 1, size, fh->f->fildes[0]));
return(0);
} else {
if (fh->offd != (long)offset)
fh->offd = lseek(fh->fd, offset, SEEK_SET);
if (size) {
if (fh->offd > -1L) {
size = write(fh->fd, data, size);
fh->offd+=(long)size;
} else size = -1;
return(size);
} else { /* truncate FILE */
int result;
#ifdef LINUX
result = ftruncate(fh->fd, offset);
#else
struct flock flockd;
flockd.l_type = 0;
flockd.l_whence = SEEK_SET;
flockd.l_start = offset;
flockd.l_len = 0;
result = fcntl(fh->fd, F_FREESP, &flockd);
#endif
return(result);
XDPRINTF((5,0,"File %s is truncated, result=%d", fh->fname, result));
fh->offd = -1L;
return(result);
}
}
}
}
@ -321,7 +343,7 @@ int nw_server_copy(int qfhandle, uint32 qoffset,
int xsize = read(fhq->fd, buff, min(size, (uint32)sizeof(buff)));
if (xsize > 0){
if ((wsize =write(fhz->fd, buff, xsize)) != xsize) {
retsize = -0x1; /* out of Disk SPace */
retsize = -0x1; /* out of Disk Space */
break;
} else {
size -= (uint32)xsize;
@ -352,6 +374,7 @@ int nw_lock_datei(int fhandle, int offset, int size, int do_lock)
if (fh->fd > -1) {
struct flock flockd;
int result;
if (fh->flags & 2) return(0);
flockd.l_type = (do_lock) ? F_WRLCK : F_UNLCK;
flockd.l_whence = SEEK_SET;
flockd.l_start = offset;

View File

@ -1,12 +1,13 @@
/* nwfile.h 23-Jan-96 */
#ifndef _NWFILE_H_
#define _NWFILE_H_
#include "nwqueue.h"
typedef struct {
int fd; /* filehandle from system open/creat */
long offd; /* aktuell file offset */
time_t tmodi; /* modification TIME */
FILE *f; /* for PIPE */
FILE_PIPE *f; /* for PIPE */
int flags; /* 2 = PIPE */
/* 4 = don't reuse after close */
char fname[256]; /* UNIX filename */

408
nwqueue.c Normal file
View File

@ -0,0 +1,408 @@
/* nwconn.c 04-May-96 */
/* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "net.h"
#include <dirent.h>
#include "connect.h"
#include "nwfile.h"
#include "nwqueue.h"
static char **build_argv(char *buf, int bufsize, char *command)
/* routine returns **argv for use with execv routines */
/* buf will contain the path component */
{
int len = strlen(command);
int offset = ((len+4) / 4) * 4; /* aligned offset for **argv */
int components = (bufsize - offset) / 4;
if (components > 1) { /* minimal argv[0] + NULL */
char **argv = (char **)(buf+offset);
char **pp = argv;
char *p = buf;
char c;
int i=0;
--components;
memcpy(buf, command, len);
memset(buf+len, 0, bufsize - len);
*pp = p;
while ((0 != (c = *p++)) && i < components) {
if (c == 32 || c == '\t') {
*(p-1) = '\0';
if (*p != 32 && *p != '\t') {
*(++pp)=p;
i++;
}
} else if (!i && c == '/') { /* here i must get argv[0] */
*pp=p;
}
}
XDPRINTF((5, 0, "build_argv, path='%s'", buf));
pp=argv;
while (*pp) {
XDPRINTF((5, 0, "build_argv, argv='%s'", *pp));
pp++;
}
return(argv);
}
return(NULL);
}
static void close_piped(int piped[3][2])
{
int j=3;
while (j--) {
int k=2;
while (k--) {
if (piped[j][k] > -1){
close(piped[j][k]);
piped[j][k] = -1;
}
}
}
}
static void err_close_pipe(FILE_PIPE *fp, int lpid, int j, int piped[3][2])
{
while (j--) if (fp->fildes[j]) fclose(fp->fildes[j]);
close_piped(piped);
kill(lpid, SIGTERM);
kill(lpid, SIGQUIT);
waitpid(lpid, NULL, 0);
kill(lpid, SIGKILL);
}
static int x_popen(char *command, int uid, int gid, FILE_PIPE *fp)
{
int piped[3][2];
int lpid=-1;
int j=3;
char buf[300];
char **argv=build_argv(buf, sizeof(buf), command);
if (argv == NULL) return(-1);
while (j--){
int k=2;
while(k--) piped[j][k] = -1;
}
if (! (pipe(&piped[0][0]) > -1 && pipe(&piped[1][0]) > -1
&& pipe(&piped[2][0]) > -1 && (lpid=fork()) > -1)) {
close_piped(piped);
return(-1);
}
if (lpid == 0) { /* Child */
signal(SIGTERM, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
signal(SIGINT, SIG_DFL);
signal(SIGPIPE, SIG_DFL);
signal(SIGHUP, SIG_DFL);
j=3;
while(j--) close(j);
j=3;
while(j--) {
int x = (j) ? 0 : 1;
int x_ = (j) ? 1 : 0;
close(piped[j][x] );
dup2( piped[j][x_], j);
close(piped[j][x_] );
}
if (uid > -1 || gid > -1) {
seteuid(0);
if (gid > -1) setgid(gid);
if (uid > -1) setuid(uid);
if (gid > -1) setegid(gid);
if (uid > -1) seteuid(uid);
}
execvp(buf, argv);
exit(1); /* Never reached I hope */
}
j=-1;
while (++j < 3) {
int x = (j) ? 0 : 1;
int x_ = (j) ? 1 : 0;
close(piped[j][x_]);
piped [j][x_] = -1;
fp->fildes [j] = fdopen(piped[j][x], ( (j) ? "r" : "w") );
if (NULL == fp->fildes[j]){
err_close_pipe(fp, lpid, j+1, piped);
return(-1);
}
}
return(lpid);
}
int ext_pclose(FILE_PIPE *fp)
{
int status=-1;
void (*intsave) (int) = signal(SIGINT, SIG_IGN);
void (*quitsave)(int) = signal(SIGQUIT, SIG_IGN);
void (*hupsave) (int) = signal(SIGHUP, SIG_IGN);
int j = 3;
while (j--) if (fp->fildes[j]) fclose(fp->fildes[j]);
/* kill(fp->command_pid, SIGTERM); */
waitpid(fp->command_pid, &status, 0);
kill(fp->command_pid, SIGKILL);
signal(SIGINT, intsave);
signal(SIGQUIT, quitsave);
signal(SIGHUP, hupsave);
xfree(fp);
return(status);
}
FILE_PIPE *ext_popen(char *command, int uid, int gid)
{
FILE_PIPE *fp=(FILE_PIPE*) xcmalloc(sizeof(FILE_PIPE));
void (*intsave) (int) = signal(SIGINT, SIG_IGN);
void (*quitsave)(int) = signal(SIGQUIT, SIG_IGN);
void (*hupsave) (int) = signal(SIGHUP, SIG_IGN);
if ((fp->command_pid = x_popen(command, uid, gid, fp)) < 0) {
xfree(fp);
fp=NULL;
XDPRINTF((1, 0, "ext_popen failed:command='%s'", command));
}
signal(SIGINT, intsave);
signal(SIGQUIT, quitsave);
signal(SIGHUP, hupsave);
return(fp);
}
/* minimal queue handling to enable simple printing */
#define MAX_JOBS 5 /* max. open queue jobs for one connection */
static int anz_jobs=0;
typedef struct {
uint32 fhandle;
int old_job; /* is old structure */
union {
QUEUE_JOB n;
QUEUE_JOB_OLD o;
} q;
} INT_QUEUE_JOB;
INT_QUEUE_JOB *queue_jobs[MAX_JOBS];
static INT_QUEUE_JOB *give_new_queue_job(int old_job)
{
int k=-1;
while (++k < anz_jobs) {
INT_QUEUE_JOB *p=queue_jobs[k];
if (!p->fhandle) { /* free slot */
memset(p, 0, sizeof(INT_QUEUE_JOB));
p->old_job = old_job;
if (old_job)
p->q.o.job_id[0] = k+1;
else
p->q.n.job_id[0] = k+1;
return(p);
}
}
if (anz_jobs < MAX_JOBS) {
INT_QUEUE_JOB **pp=&(queue_jobs[anz_jobs++]);
*pp = (INT_QUEUE_JOB *) xmalloc(sizeof(INT_QUEUE_JOB));
memset(*pp, 0, sizeof(INT_QUEUE_JOB));
(*pp)->old_job = old_job;
if (old_job)
(*pp)->q.o.job_id[0] = anz_jobs;
else
(*pp)->q.n.job_id[0] = anz_jobs;
return(*pp);
}
return(NULL);
}
static void free_queue_job(int q_id)
{
if (q_id > 0 && q_id <= anz_jobs) {
INT_QUEUE_JOB **pp=&(queue_jobs[q_id-1]);
uint32 fhandle = (*pp)->fhandle;
if (fhandle > 0) nw_close_datei(fhandle, 1);
if (q_id == anz_jobs) {
xfree(*pp);
--anz_jobs;
} else (*pp)->fhandle=0L;
}
}
static void set_entry_time(uint8 *entry_time)
{
struct tm *s_tm;
time_t timer;
time(&timer);
s_tm = localtime(&timer);
entry_time[0] = (uint8) s_tm->tm_year;
entry_time[1] = (uint8) s_tm->tm_mon+1;
entry_time[2] = (uint8) s_tm->tm_mday;
entry_time[3] = (uint8) s_tm->tm_hour;
entry_time[4] = (uint8) s_tm->tm_min;
entry_time[5] = (uint8) s_tm->tm_sec;
}
static int create_queue_file(uint8 *job_file_name,
uint32 q_id,
int jo_id,
int connection,
uint8 *dirname,
int dir_nam_len,
uint8 *job_bez)
{
int result;
NW_FILE_INFO fnfo;
*job_file_name
= sprintf((char*)job_file_name+1, "%07lX%d.%03d", q_id, jo_id, connection);
result=nw_alloc_dir_handle(0, dirname, dir_nam_len, 99, 2, 1);
if (result > -1)
result = nw_creat_open_file(result, job_file_name+1,
(int) *job_file_name,
&fnfo, 0x6, 0x6, 1 | 4);
XDPRINTF((5,0,"creat queue file bez=`%s` handle=%d",
job_bez, result));
return(result);
}
int nw_creat_queue(int connection, uint8 *queue_id, uint8 *queue_job,
uint8 *dirname, int dir_nam_len, int old_call)
{
INT_QUEUE_JOB *jo = give_new_queue_job(old_call);
uint32 q_id = GET_BE32(queue_id);
int result = -0xff;
XDPRINTF((5,0,"NW_CREAT_Q:dlen=%d, dirname=%s", dir_nam_len, dirname));
if (NULL != jo) {
int jo_id = 0;
if (jo->old_job) {
jo_id = (int) jo->q.o.job_id[0];
memcpy(&(jo->q.o), queue_job, sizeof(QUEUE_JOB_OLD));
jo->q.o.job_id[0] = (uint8) jo_id;
jo->q.o.client_connection = (uint8)connection;
jo->q.o.client_task = (uint8)0xfe; /* ?? */
U32_TO_BE32(1, jo->q.o.client_id); /* SU */
set_entry_time(jo->q.o.job_entry_time);
jo->q.o.job_typ[0] = 0x0; /* 0xd0;*/
jo->q.o.job_typ[1] = 0x0;
jo->q.o.job_position = 0x1;
jo->q.o.job_control_flags |= 0x20;
result = create_queue_file(jo->q.o.job_file_name,
q_id, jo_id, connection,
dirname, dir_nam_len,
jo->q.o.job_bez);
if (result > -1) {
jo->fhandle = (uint32) result;
U16_TO_BE16(0, jo->q.o.job_file_handle);
U32_TO_BE32(jo->fhandle, jo->q.o.job_file_handle+2);
result = 0;
}
jo->q.o.server_station = 0;
jo->q.o.server_task = 0;
U32_TO_BE32(0, jo->q.o.server_id);
if (!result) memcpy(queue_job, &(jo->q.o), sizeof(QUEUE_JOB_OLD));
} else {
jo_id = (int) jo->q.n.job_id[0];
memcpy(&(jo->q.n), queue_job, sizeof(QUEUE_JOB));
jo->q.n.job_id[0] = (uint8) jo_id;
U16_TO_BE16(0xffff, jo->q.n.record_in_use);
U32_TO_BE32(0x0, jo->q.n.record_previous);
U32_TO_BE32(0x0, jo->q.n.record_next);
memset(jo->q.n.client_connection, 0, 4);
jo->q.n.client_connection[0] = (uint8)connection;
memset(jo->q.n.client_task, 0, 4);
jo->q.n.client_task[0] = (uint8)0xfe; /* ?? */
U32_TO_BE32(1, jo->q.n.client_id); /* SU */
set_entry_time(jo->q.n.job_entry_time);
jo->q.n.job_typ[0] = 0x0; /* 0xd0;*/
jo->q.n.job_typ[1] = 0x0;
jo->q.n.job_position[0] = 0x1;
jo->q.n.job_position[1] = 0x0;
jo->q.n.job_control_flags[0] |= 0x20;
jo->q.n.job_control_flags[1] = 0x0;
result = create_queue_file(jo->q.n.job_file_name,
q_id, jo_id, connection,
dirname, dir_nam_len,
jo->q.n.job_bez);
if (result > -1) {
jo->fhandle = (uint32) result;
U32_TO_BE32(jo->fhandle, jo->q.n.job_file_handle);
result = 0;
}
U32_TO_BE32(0, jo->q.n.server_station);
U32_TO_BE32(0, jo->q.n.server_task);
U32_TO_BE32(0, jo->q.n.server_id);
if (!result) memcpy(queue_job, &(jo->q.n), sizeof(QUEUE_JOB));
}
if (result) free_queue_job(jo_id);
}
return(result);
}
int nw_close_file_queue(uint8 *queue_id,
uint8 *job_id,
uint8 *prc, int prc_len)
{
int result = -0xff;
int jo_id = (int) *job_id; /* ever only the first byte */
XDPRINTF((5,0,"nw_close_file_queue JOB=%d", jo_id));
if (jo_id > 0 && jo_id <= anz_jobs){
INT_QUEUE_JOB *jo=queue_jobs[jo_id-1];
int fhandle = (int)jo->fhandle;
char unixname[300];
strmaxcpy((uint8*)unixname, (uint8*)file_get_unix_name(fhandle), sizeof(unixname)-1);
XDPRINTF((5,0,"nw_close_file_queue fhandle=%d", fhandle));
if (*unixname) {
char printcommand[256];
FILE *f=NULL;
strmaxcpy((uint8*)printcommand, prc, prc_len);
nw_close_datei(fhandle, 1);
jo->fhandle = 0L;
if (NULL != (f = fopen(unixname, "r"))) {
int is_ok = 0;
FILE_PIPE *fp = ext_popen(printcommand, geteuid(), getegid());
if (fp) {
char buff[1024];
int k;
is_ok++;
while ((k = fread(buff, 1, sizeof(buff), f)) > 0) {
if (1 != fwrite(buff, k, 1, fp->fildes[0])) {
XDPRINTF((1,0,"Cannot write to pipe `%s`", printcommand));
is_ok=0;
}
}
if (ext_pclose(fp)) {
XDPRINTF((1,0,"Error by closing print pipe"));
}
} else
XDPRINTF((1,0,"Cannot open pipe `%s`", printcommand));
fclose(f);
if (is_ok) {
unlink(unixname);
result=0;
}
} else XDPRINTF((1,0,"Cannot open queue-file `%s`", unixname));
} else
XDPRINTF((2,0,"fhandle=%d NOT OK !", fhandle));
free_queue_job(jo_id);
}
return(result);
}

92
nwqueue.h Normal file
View File

@ -0,0 +1,92 @@
/* nwqueue.h 04-May-96 */
#ifndef _NWQUEUE_H_
#define _NWQUEUE_H_
/* enhanced pipe handling */
typedef struct {
FILE *fildes[3]; /* filedescriptor to 0,1,2 of new process */
int command_pid; /* pid of piped command */
} FILE_PIPE;
extern int ext_pclose(FILE_PIPE *fp);
extern FILE_PIPE *ext_popen(char *command, int uid, int gid);
/* queues */
typedef struct {
uint8 record_in_use[2];
uint8 record_previous[4];
uint8 record_next[4];
uint8 client_connection[4];
uint8 client_task[4];
uint8 client_id[4];
uint8 target_id[4]; /* 0xff, 0xff, 0xff, 0xff */
uint8 target_execute_time[6]; /* all 0xff */
uint8 job_entry_time[6]; /* all zero */
uint8 job_id[4]; /* ?? alles 0 HI-LOW */
uint8 job_typ[2]; /* z.B. Printform HI-LOW */
uint8 job_position[2]; /* ?? alles 0 low-high ? */
uint8 job_control_flags[2]; /* z.B 0x10, 0x00 */
/* 0x80 operator hold flag */
/* 0x40 user hold flag */
/* 0x20 entry open flag */
/* 0x10 service restart flag */
/* 0x08 autostart flag */
uint8 job_file_name[14]; /* len + DOS filename */
uint8 job_file_handle[4];
uint8 server_station[4];
uint8 server_task[4];
uint8 server_id[4];
uint8 job_bez[50]; /* "LPT1 Catch" */
uint8 client_area[152];
} QUEUE_JOB;
typedef struct {
uint8 client_connection;
uint8 client_task;
uint8 client_id[4];
uint8 target_id[4]; /* 0xff, 0xff, 0xff, 0xff */
uint8 target_execute_time[6]; /* all 0xff */
uint8 job_entry_time[6]; /* all zero */
uint8 job_id[2]; /* ?? alles 0 HI-LOW */
uint8 job_typ[2]; /* z.B. Printform HI-LOW */
uint8 job_position; /* zero */
uint8 job_control_flags; /* z.B 0x10 */
/* 0x80 operator hold flag */
/* 0x40 user hold flag */
/* 0x20 entry open flag */
/* 0x10 service restart flag */
/* 0x08 autostart flag */
uint8 job_file_name[14]; /* len + DOS filename */
uint8 job_file_handle[6];
uint8 server_station;
uint8 server_task;
uint8 server_id[4];
uint8 job_bez[50]; /* "LPT1 Catch" */
uint8 client_area[152];
} QUEUE_JOB_OLD; /* before 3.11 */
typedef struct {
uint8 version; /* normal 0x0 */
uint8 tabsize; /* normal 0x8 */
uint8 anz_copies[2]; /* copies 0x0, 0x01 */
uint8 print_flags[2]; /* 0x0, 0xc0 z.B. with banner */
uint8 max_lines[2]; /* 0x0, 0x42 */
uint8 max_chars[2]; /* 0x0, 0x84 */
uint8 form_name[16]; /* "UNKNOWN" */
uint8 reserved[6]; /* all zero */
uint8 banner_user_name[13]; /* "SUPERVISOR" */
uint8 bannner_file_name[13]; /* "LST:" */
uint8 bannner_header_file_name[14]; /* all zero */
uint8 file_path_name[80]; /* all zero */
} QUEUE_PRINT_AREA;
extern int nw_creat_queue(int connection, uint8 *queue_id, uint8 *queue_job,
uint8 *dirname, int dir_nam_len, int old_call);
extern int nw_close_file_queue(uint8 *queue_id,
uint8 *job_id,
uint8 *prc, int prc_len);
#endif

351
nwroute.c
View File

@ -1,4 +1,4 @@
/* nwroute.c 09-Mar-96 */
/* nwroute.c 24-Apr-96 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
@ -19,13 +19,12 @@
#include "net.h"
#include "nwserv.h"
typedef struct {
uint32 net; /* destnet */
uint16 hops; /* hops to net */
uint32 net; /* destnet */
uint16 hops; /* hops to net over rnet */
uint16 ticks; /* ticks to net, ether 1/hop, isdn 7/hop */
uint32 rnet; /* net of forw. router */
uint8 rnode[IPX_NODE_SIZE]; /* node of forw. router */
uint32 rnet; /* net of forw. router */
uint8 rnode[IPX_NODE_SIZE]; /* node of forw. router */
} NW_ROUTES;
static int anz_routes=0;
@ -50,9 +49,11 @@ static void insert_delete_net(uint32 destnet,
uint16 ticks,
int do_delete) /* delete == 1 */
{
int k=-1;
int freeslot=-1;
NW_ROUTES *nr=NULL;
int k = -1;
int freeslot = -1;
NW_ROUTES *nr = NULL;
NW_NET_DEVICE *nd_dev = NULL;
int ndticks = 99;
XDPRINTF((3,0,"%s net:0x%X, over 0x%X, 0x%02x:%02x:%02x:%02x:%02x:%02x",
(do_delete) ? "DEL" : "INS", destnet, rnet,
@ -63,20 +64,26 @@ static void insert_delete_net(uint32 destnet,
while (++k < anz_net_devices) {
NW_NET_DEVICE *nd=net_devices[k];
if (nd->net == destnet && (do_delete || (nd->ticks <= ticks))) return;
if (nd->is_up) {
if (nd->net == destnet) {
if (!do_delete) return; /* don't route device */
nd_dev = nd;
}
if (nd->net == rnet) ndticks=nd->ticks;
}
}
if (!do_delete && nd_dev && nd_dev->ticks <= ndticks) return;
k=-1;
while (++k < anz_routes && nw_routes[k]->net != destnet) {
XDPRINTF((3,0, "NET 0x%x is routed", nw_routes[k]->net));
if (freeslot < 0 && !nw_routes[k]->net) freeslot=k;
if (freeslot < 0 && !nw_routes[k]->net) freeslot=k;
}
if (k == anz_routes) { /* no route slot found */
if (do_delete) return; /* nothing to delete */
if (freeslot < 0) {
if (anz_routes == MAX_NW_ROUTES) {
XDPRINTF((1, 0, "too many routes=%d, increase MAX_NW_ROUTES in config.h", anz_routes));
XDPRINTF((1, 0, "too many routes > %d, increase MAX_NW_ROUTES in config.h", anz_routes));
return;
}
nw_routes[k] = (NW_ROUTES*)xmalloc(sizeof(NW_ROUTES));
@ -94,6 +101,12 @@ static void insert_delete_net(uint32 destnet,
XDPRINTF((2,0,"ROUTE DEL NET=0x%x over Router NET 0x%x",
nr->net, rnet));
ipx_route_del(nr->net);
if (nd_dev != NULL) { /* this is net to our device */
/* I must delete and setup new, because there is */
/* no direct way to delete this route from interface :( */
exit_dev(nd_dev->devname, nd_dev->frame);
init_dev(nd_dev->devname, nd_dev->frame, nd_dev->net);
}
nr->net = 0L;
} else {
XDPRINTF((3,0,"ROUTE NOT deleted NET=0x%x, RNET=0x%x",
@ -101,9 +114,10 @@ static void insert_delete_net(uint32 destnet,
}
return;
} else nr=nw_routes[k];
ticks+=ndticks;
if (ticks <= nr->ticks) {
if (ticks > nr->ticks) return;
if (ticks == nr->ticks && hops > nr->hops) return;
if (ticks == nr->ticks && hops >= nr->hops) return;
nr->hops = hops;
nr->ticks = ticks;
nr->rnet = rnet;
@ -122,12 +136,11 @@ NW_NET_DEVICE *find_netdevice(uint32 network)
{
uint32 net=network;
int l=2;
XDPRINTF((3, 0, "find_netdevice of network=%lX", net));
while (l--) {
int k=-1;
while (++k < anz_net_devices) {
NW_NET_DEVICE *nd=net_devices[k];
if (nd->net == net) {
if (nd->is_up && nd->net == net) {
XDPRINTF((3, 0, "found netdevive %s, frame=%d, ticks=%d",
nd->devname, nd->frame, nd->ticks));
return(nd);
@ -142,6 +155,17 @@ NW_NET_DEVICE *find_netdevice(uint32 network)
return(NULL);
}
static NW_NET_DEVICE *find_device_by_net(uint32 net)
/* return the device of this net I hope */
{
int k=-1;
while (++k < anz_net_devices) {
NW_NET_DEVICE *nd=net_devices[k];
if (nd->is_up && nd->net == net) return(nd);
}
return(NULL);
}
void insert_delete_server(uint8 *name, /* Server Name */
int styp, /* Server Typ */
ipxAddr_t *addr, /* Server Addr */
@ -178,7 +202,7 @@ void insert_delete_server(uint8 *name, /* Server Name */
if (freeslot < 0) {
if (anz_servers == MAX_NW_SERVERS) {
XDPRINTF((1, 0, "too many servers=%d, increase MAX_NW_SERVERS in config.h", anz_servers));
XDPRINTF((1, 0, "too many servers > %d, increase MAX_NW_SERVERS in config.h", anz_servers));
return;
}
nw_servers[k] = (NW_SERVERS*)xcmalloc(sizeof(NW_SERVERS));
@ -191,7 +215,7 @@ void insert_delete_server(uint8 *name, /* Server Name */
} else if (do_delete) {
nr=nw_servers[k];
#if !FILE_SERVER_INACTIV
#if !IN_NWROUTED
if (!IPXCMPNODE(nr->addr.node, my_server_adr.node) ||
!IPXCMPNET (nr->addr.net, my_server_adr.net) )
#endif
@ -203,11 +227,12 @@ void insert_delete_server(uint8 *name, /* Server Name */
}
return;
} else nr=nw_servers[k];
/* here now i perhaps must change the entry */
if (nr->hops > 16 || memcmp(&(nr->addr), addr, sizeof(ipxAddr_t))) {
ins_del_bind_net_addr(nr->name, nr->typ, addr);
memcpy(&(nr->addr), addr, sizeof(ipxAddr_t));
#if !FILE_SERVER_INACTIV
#if !IN_NWROUTED
if (IPXCMPNODE(from_addr->node, my_server_adr.node) &&
IPXCMPNET (from_addr->net, my_server_adr.net)
&& GET_BE16(from_addr->sock) == SOCK_SAP) {
@ -216,76 +241,84 @@ void insert_delete_server(uint8 *name, /* Server Name */
#endif
}
if (hops <= nr->hops && 0 != (net = GET_BE32(from_addr->net)) ) {
if (nr->net && nr->net != net && nr->hops >= hops) {
NW_NET_DEVICE *nrd=find_device_by_net(nr->net);
NW_NET_DEVICE *nnd=find_device_by_net(net);
if (nrd && nnd && nrd->ticks < nnd->ticks) return;
}
nr->net = net;
nr->hops = hops;
}
}
static uint32 rnet=0L;
static uint32 rnet=0L; /* Router NET */
static int rmode; /* 0=normal, 1=shutdown response */
/* 10=request */
static int rentries=0;
static int rmode; /* 0=normal, 1=shutdown, 10=request */
static uint8 rip_buff[402]; /* operation + max. 50 RIPS */
static uint8 rip_buff[2 + MAX_RIP_ENTRIES * 8];
/* operation + max. 50 RIPS */
static void init_rip_buff(uint32 net, int mode)
{
rnet=net;
rentries=0;
rmode=mode;
rnet = net;
rentries = 0;
rmode = mode;
U16_TO_BE16((mode > 9) ? 1 : 2, rip_buff); /* rip request or response */
}
static void ins_rip_buff(uint32 net, uint16 hops, uint16 ticks)
{
if ( net && rentries < 50 &&
(net != rnet || (!rentries && net == internal_net))) {
uint8 *p=rip_buff+2+(rentries*8);
U32_TO_BE32(net, p);
U16_TO_BE16(hops, p+4);
U16_TO_BE16(ticks, p+6);
rentries++;
if (!net) return;
if (net != rnet || (!rentries && net == internal_net)) {
if (rentries < MAX_RIP_ENTRIES) {
uint8 *p=rip_buff+2+(rentries*8);
U32_TO_BE32(net, p);
U16_TO_BE16(hops, p+4);
U16_TO_BE16(ticks, p+6);
rentries++;
} else {
XDPRINTF((1, 0, "too many rips > %d, increase MAX_RIP_ENTRIES in config.h", MAX_RIP_ENTRIES));
}
}
}
static void build_rip_buff(uint32 destnet, int to_internal_net)
/* to_internal_net = request from dosemu etc. */
static void build_rip_buff(uint32 destnet)
{
int is_wild = (destnet==MAX_U32);
int is_response = (rmode < 10);
int k;
if (!destnet) return;
if (is_wild) rentries=0;
if (is_response) {
if (is_wild || internal_net == destnet) {
ins_rip_buff(internal_net, (rmode==1) ? 16 : 1,
(rnet==internal_net) ? 1 : 2);
}
k=-1;
while (++k < anz_net_devices) {
NW_NET_DEVICE *nd=net_devices[k];
if (is_wild || nd->net == destnet)
if (nd->is_up && (is_wild || nd->net == destnet))
ins_rip_buff(nd->net, (rmode==1) ? 16 : 1, nd->ticks+1);
}
}
k=-1;
while (++k < anz_routes) {
NW_ROUTES *nr=nw_routes[k];
#if 0
if ( (is_wild || nr->net == destnet) &&
(rmode==1 || nr->hops < 2 || to_internal_net) )
#else
if (is_wild || (nr->net == destnet))
#endif
ins_rip_buff(nr->net, (rmode==1) ? 16 : nr->hops, nr->ticks);
if (nr->rnet != rnet && (is_wild || (nr->net == destnet)) )
ins_rip_buff(nr->net, (rmode==1) ? 16 : nr->hops+1, nr->ticks+1);
}
}
static void send_rip_buff(ipxAddr_t *from_addr)
{
if (rentries > 0) {
int datasize=(rentries*8)+2;
while (rentries > 0) {
int entries = min(rentries, 50);
int datasize = (entries*8)+2;
ipxAddr_t to_addr;
rentries -= entries;
if (from_addr) memcpy(&to_addr, from_addr, sizeof(ipxAddr_t));
else {
memset(&to_addr, 0, sizeof(ipxAddr_t));
@ -298,9 +331,9 @@ static void send_rip_buff(ipxAddr_t *from_addr)
uint8 *p = rip_buff;
int operation = GET_BE16(p);
XDPRINTF((2,0, "Send Rip %s entries=%d",
(operation==1) ? "Request" : "Response", rentries));
(operation==1) ? "Request" : "Response", entries));
p+=2;
while (rentries--) {
while (entries--) {
#if 0
uint32 net = GET_BE32(p);
#endif
@ -311,26 +344,28 @@ static void send_rip_buff(ipxAddr_t *from_addr)
p+=8;
}
}
send_ipx_data(sockfd[RIP_SLOT], 1,
datasize,
(char *)rip_buff,
&to_addr, "SEND RIP");
rentries=0;
}
if (rentries > 0)
memcpy(rip_buff+2, rip_buff+2+50*8, min(50, rentries)*8);
} /* while */
rentries=0;
}
static void send_rip_broadcast(int mode)
/* mode=0, standard broadcast */
/* mode=1, first trie */
/* mode=2, shutdown */
/* mode=2, shutdown */
{
int k=-1;
while (++k < anz_net_devices) {
NW_NET_DEVICE *nd=net_devices[k];
if (nd->ticks < 7) { /* isdn devices should not get RIP broadcasts everytime */
if (nd->is_up && nd->ticks < 7) { /* isdn devices should not get RIP broadcasts everytime */
init_rip_buff(nd->net, (mode == 2) ? 1 : 0);
build_rip_buff(MAX_U32, 0);
build_rip_buff(MAX_U32);
send_rip_buff(NULL);
}
}
@ -341,7 +376,7 @@ void rip_for_net(uint32 net)
int k=-1;
while (++k < anz_net_devices) {
NW_NET_DEVICE *nd=net_devices[k];
if (nd->ticks < 7) { /* isdn devices should not get RIP broadcasts everytime */
if (nd->is_up && nd->ticks < 7) { /* isdn devices should not get RIP broadcasts everytime */
init_rip_buff(nd->net, 10);
ins_rip_buff(net, MAX_U16, MAX_U16);
send_rip_buff(NULL);
@ -350,8 +385,11 @@ void rip_for_net(uint32 net)
}
void handle_rip(int fd, int ipx_pack_typ,
int data_len, IPX_DATA *ipxdata,
ipxAddr_t *from_addr)
int data_len, IPX_DATA *ipxdata,
ipxAddr_t *from_addr)
/* All received rip packeta reach this function */
/* It can be a RIP Request or a RIP Respons */
{
int operation = GET_BE16(ipxdata->rip.operation);
int entries = (data_len-2) / 8;
@ -379,9 +417,9 @@ void handle_rip(int fd, int ipx_pack_typ,
if (is_response) {
insert_delete_net(net, GET_BE32(from_addr->net),
from_addr->node, hops+1, ticks+1, (hops > 15) ? 1 : 0);
from_addr->node, hops, ticks, (hops > 15) ? 1 : 0);
} else { /* rip request */
build_rip_buff(net, GET_BE32(from_addr->net)==internal_net);
build_rip_buff(net);
if (net == MAX_U32) break;
}
p+=8;
@ -420,28 +458,29 @@ void send_server_response(int respond_typ,
NW_SERVERS *nw=nw_servers[entry];
strcpy((char*)ipx_data.sip.server_name, nw->name);
memcpy(&ipx_data.sip.server_adr, &nw->addr, sizeof(ipxAddr_t));
XDPRINTF((4, 0, "NEAREST SERVER=%s, typ=0x%x, tics=%d, hops=%d",
hops++;
XDPRINTF((4, 0, "NEAREST SERVER=%s, typ=0x%x, ticks=%d, hops=%d",
nw->name, styp, tics, hops));
U16_TO_BE16(respond_typ, ipx_data.sip.response_type);
U16_TO_BE16(styp, ipx_data.sip.server_type);
U16_TO_BE16(hops, ipx_data.sip.intermediate_networks);
send_ipx_data(sockfd[SAP_SLOT],
4, /* this is the official packet typ for SAP's */
sizeof(ipx_data.sip),
(char *)&(ipx_data.sip),
to_addr, "Nearest Server Response");
sizeof(ipx_data.sip),
(char *)&(ipx_data.sip),
to_addr, "Nearest Server Response");
}
}
static void send_sap_broadcast(int mode)
/* mode=0, standard broadcast */
/* mode=1, first trie */
/* mode=2, shutdown */
/* mode=2, shutdown */
{
int k=-1;
while (++k < anz_net_devices) {
NW_NET_DEVICE *nd=net_devices[k];
if (nd->ticks < 7 || mode) {
if (nd->is_up && (nd->ticks < 7 || mode)) {
/* isdn devices should not get SAP broadcasts everytime */
IPX_DATA ipx_data;
ipxAddr_t wild;
@ -454,7 +493,7 @@ static void send_sap_broadcast(int mode)
NW_SERVERS *nw=nw_servers[j];
if ( !nw->typ /* server has no typ */
|| ( nw->net == nd->net && nw->hops) /* server has same net but */
/* hops */
/* 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));
@ -475,9 +514,9 @@ static void send_sap_broadcast(int mode)
}
send_ipx_data(sockfd[SAP_SLOT],
4, /* this is the official packet typ for SAP's */
sizeof(ipx_data.sip),
(char *)&(ipx_data.sip),
&wild, "SIP Broadcast");
sizeof(ipx_data.sip),
(char *)&(ipx_data.sip),
&wild, "SIP Broadcast");
}
}
}
@ -498,10 +537,55 @@ static FILE *open_route_info_fn(void)
return(f);
}
void print_routing_info(void)
{
FILE *f= open_route_info_fn();
if (f) {
int k=-1;
fprintf(f, "<--------- Devices ---------------->\n");
fprintf(f, "%-15s %-15s %5s Network Status\n", "DevName", "Frame", "Ticks");
while (++k < anz_net_devices) {
uint8 frname[30];
NW_NET_DEVICE *nd=net_devices[k];
(void) get_frame_name(frname, nd->frame);
fprintf(f, "%-15s %-15s %5d %08lX %s\n",
nd->devname, frname, nd->ticks, nd->net,
(!nd->is_up) ? "DOWN"
: ( (nd->is_up==1) ? "UP"
: "ADDED") );
}
fprintf(f, "<--------- Routing Table ---------->\n");
fprintf(f, "%8s Hops Ticks %9s Router Node\n", "Network", "RouterNet");
k=-1;
while (++k < anz_routes) {
NW_ROUTES *nr = nw_routes[k];
if (nr->net) {
fprintf(f, "%08lX %4d %5d %08lX %02x:%02x:%02x:%02x:%02x:%02x\n",
nr->net, nr->hops, nr->ticks, nr->rnet,
(int)nr->rnode[0], (int)nr->rnode[1], (int)nr->rnode[2],
(int)nr->rnode[3], (int)nr->rnode[4], (int)nr->rnode[5]);
}
}
k=-1;
fprintf(f, "<--------- Server Table ---------->\n");
fprintf(f, "%-20s %4s %9s Hops Server-Address\n","Name", "Typ", "RouterNet");
while (++k < anz_servers) {
NW_SERVERS *ns = nw_servers[k];
if (ns->typ) {
char sname[50];
strmaxcpy(sname, ns->name, 20);
fprintf(f, "%-20s %4d %08lX %4d %s\n", sname, ns->typ,
ns->net, ns->hops, xvisable_ipx_adr(&(ns->addr), 1));
}
} /* while */
fclose(f);
}
}
void send_sap_rip_broadcast(int mode)
/* mode=0, standard broadcast */
/* mode=1, first trie */
/* mode=2, shutdown */
/* mode=2, shutdown */
{
static int flipflop=1;
if (mode) {
@ -516,36 +600,7 @@ static int flipflop=1;
flipflop=1;
}
}
if (!mode && flipflop) { /* jedes 2. mal */
FILE *f= open_route_info_fn();
if (f) {
int k=-1;
fprintf(f, "<--------- Routing Table ---------->\n");
fprintf(f, "%8s Hops Tics %9s Router Node\n", "Network", "RouterNet");
while (++k < anz_routes) {
NW_ROUTES *nr = nw_routes[k];
if (nr->net) {
fprintf(f, "%08lX %4d %4d %08lX %02x:%02x:%02x:%02x:%02x:%02x\n",
nr->net, nr->hops, nr->ticks, nr->rnet,
(int)nr->rnode[0], (int)nr->rnode[1], (int)nr->rnode[2],
(int)nr->rnode[3], (int)nr->rnode[4], (int)nr->rnode[5]);
}
}
k=-1;
fprintf(f, "<--------- Server Table ---------->\n");
fprintf(f, "%-20s %4s %9s Hops Server-Address\n","Name", "Typ", "RouterNet");
while (++k < anz_servers) {
NW_SERVERS *ns = nw_servers[k];
if (ns->typ) {
char sname[50];
strmaxcpy(sname, ns->name, 20);
fprintf(f, "%-20s %4d %08lX %4d %s\n", sname, ns->typ,
ns->net, ns->hops, xvisable_ipx_adr(&(ns->addr), 1));
}
} /* while */
fclose(f);
}
}
if (flipflop) print_routing_info(); /* every second time */
}
static void query_sap_on_net(uint32 net)
@ -568,14 +623,15 @@ void get_servers(void)
int k=-1;
while (++k < anz_net_devices) {
NW_NET_DEVICE *nd=net_devices[k];
if (nd->ticks < 7) query_sap_on_net(nd->net); /* only fast routes */
if (nd->is_up && nd->ticks < 7)
query_sap_on_net(nd->net); /* only fast routes */
}
if (!anz_net_devices) query_sap_on_net(internal_net);
}
int dont_send_wdog(ipxAddr_t *addr)
/* returns != 0 if tics are to high for wdogs */
/* returns != 0 if ticks are to high for wdogs */
{
NW_NET_DEVICE *nd;
if (!wdogs_till_tics) return(0); /* ever send wdogs */
@ -585,3 +641,92 @@ int dont_send_wdog(ipxAddr_t *addr)
return(0);
}
/* ---------------------------------------------------- */
int test_ins_device_net(uint32 rnet)
{
int rnetframe;
uint8 rnetdevname[100];
int k = -1;
int foundfree=-1; /* first matching/free entry */
NW_NET_DEVICE *nd;
if (!rnet || rnet == internal_net) return(0);
while (++k < anz_net_devices) {
nd=net_devices[k];
if (!nd->is_up) {
if (nd->net == rnet) {
foundfree = k;
break;
} else if (foundfree < 0 && !nd->net)
foundfree = k;
} else if (nd->net == rnet) return(0);
}
if ((rnetframe=get_interface_frame_name(rnetdevname, rnet)) < 0)
return(0);
if (foundfree > -1 && (net_devices[foundfree])->net != rnet) {
int devfound = -1;
int framefound = -1;
k = foundfree - 1;
foundfree = -1;
while (++k < anz_net_devices) {
nd = net_devices[k];
if (!nd->is_up && !nd->net) {
int dfound = !strcmp(nd->devname, rnetdevname);
int ffound = nd->frame == rnetframe;
if (dfound && ffound) {
devfound = k;
framefound = k;
break;
} else {
if (dfound) {
if (devfound < 0 && nd->frame < 0)
devfound =k;
} else if (ffound) {
if (framefound < 0 && nd->devname[0] == '*')
framefound=k;
} else if (nd->frame < 0 && nd->devname[0] == '*') {
if (foundfree < 0)
foundfree = k;
}
}
}
}
if (devfound > -1) foundfree = devfound;
else if (framefound > -1) foundfree = framefound;
}
if ( foundfree < 0 ) {
if (anz_net_devices < MAX_NET_DEVICES) {
NW_NET_DEVICE **pnd=&(net_devices[anz_net_devices++]);
nd=*pnd= (NW_NET_DEVICE*)xmalloc(sizeof(NW_NET_DEVICE));
memset(nd, 0, sizeof(NW_NET_DEVICE));
nd->ticks = 1;
} else {
XDPRINTF((1, 0, "too many devices > %d, increase MAX_NET_DEVICES in config.h", anz_net_devices));
return(0);
}
} else {
nd = net_devices[foundfree];
}
nd->net = rnet;
nd->frame = rnetframe;
new_str(nd->devname, rnetdevname);
nd->is_up = 2;
/* now perhaps i must delete an existing route over */
/* another device */
k = -1;
while (++k < anz_routes) {
NW_ROUTES *nr = nw_routes[k];
if (nr->net == rnet) {
ipx_route_del(nr->net);
nr->net = 0L;
/* I must delete and setup new, because there is */
/* no direct way to delete this route from interface :( */
exit_dev(nd->devname, nd->frame);
init_dev(nd->devname, nd->frame, nd->net);
break;
}
}
return(1);
}

View File

@ -125,6 +125,11 @@ void get_servers(void)
#endif
}
void print_routing_info(void)
{
;; /* DUMMY */
}
void send_sap_rip_broadcast(int mode)
/* mode=0, standard broadcast */
/* mode=1, first trie */

4
nwrouted.c Normal file
View File

@ -0,0 +1,4 @@
/* nwrouted.c */
#define IN_NWROUTED 1
#include "nwroute.c"
#include "nwserv.c"

143
nwserv.c
View File

@ -1,4 +1,6 @@
/* nwserv.c 20-Mar-96 */
/* nwserv.c 03-May-96 */
/* MAIN Prog for NWSERV + NWROUTED */
/* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
@ -20,6 +22,9 @@
#include "nwserv.h"
uint32 internal_net = 0x0L; /* NETWORKNUMMER INTERN (SERVER) */
int no_internal = 0; /* no use of internal net */
int auto_creat_interfaces=0;
ipxAddr_t my_server_adr; /* Address of this server */
char my_nwname[50]; /* Name of this server */
int print_route_tac = 0; /* every x broadcasts print it */
@ -57,7 +62,7 @@ uint16 ipx_sock_nummern[]={ SOCK_AUTO /* WDOG */
};
#define NEEDED_SOCKETS (sizeof(ipx_sock_nummern) / sizeof(uint16))
#if FILE_SERVER_INACTIV
#if IN_NWROUTED
# define NEEDED_POLLS (NEEDED_SOCKETS+1)
#else
# define NEEDED_POLLS (NEEDED_SOCKETS+2)
@ -91,6 +96,14 @@ static int save_ipx_routes = 0;
static uint8 *station_fn=NULL;
static int nearest_request_flag=0;
#if IN_NWROUTED
static char *prog_name_typ="ROUTER";
#define IN_PROG NWROUTED
#else
static char *prog_name_typ="SERVER";
#define IN_PROG NWSERV
#endif
static void add_wdata(IPX_DATA *d, char *data, int size)
{
memcpy(d->owndata.d.data+d->owndata.d.size, data, size);
@ -149,7 +162,7 @@ static void write_to_sons(int what, int connection,
write_wdata(&ipxd, what, sock);
}
#if !FILE_SERVER_INACTIV
#if !IN_NWROUTED
# define write_to_ncpserv(what, connection, data, data_size) \
write_to_sons((what), (connection), (data), (data_size), SOCK_NCP)
#else
@ -215,7 +228,7 @@ 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 !IN_NWROUTED
int fds_in[2];
int pid;
if (pipe(fds_in) < 0) return(-1);
@ -255,7 +268,7 @@ static int start_ncpserv(char *nwname, ipxAddr_t *addr)
static int start_nwbind(char *nwname, ipxAddr_t *addr)
{
#if !FILE_SERVER_INACTIV
#if !IN_NWROUTED
int fds_in[2];
int pid;
struct t_bind bind;
@ -322,7 +335,7 @@ static int start_nwbind(char *nwname, ipxAddr_t *addr)
return(0); /* OK */
}
#if !IN_NWROUTED
static int start_nwclient(void)
{
switch (fork()){
@ -342,6 +355,7 @@ static int start_nwclient(void)
}
return(0); /* OK */
}
#endif
/* =========================== WDOG =============================== */
#ifndef _WDOG_TESTING_
@ -481,6 +495,7 @@ void get_server_data(char *name,
ipxAddr_t *adr,
ipxAddr_t *from_addr)
{
#if !IN_NWROUTED
if (!nw386_found && strcmp(name, my_nwname)) {
memcpy(&nw386_adr, adr, sizeof(ipxAddr_t));
nw386_found++;
@ -489,6 +504,7 @@ void get_server_data(char *name,
client_mode = 0; /* only start once */
}
}
#endif
XDPRINTF((2,0,"NW386 %s found at:%s", name, visable_ipx_adr(adr)));
}
@ -588,7 +604,8 @@ static void handle_sap(int fd,
uint8 *name = p+2;
ipxAddr_t *ad = (ipxAddr_t*) (p+50);
int hops = GET_BE16(p+ sizeof(SAPS) -2);
if (hops < 16) U16_TO_BE16(hops+1, p+ sizeof(SAPS) -2);
/* if (hops < 16) U16_TO_BE16(hops+1, p+ sizeof(SAPS) -2); */
/* if (hops < 16) hops++; */
XDPRINTF((2,0, "TYP=%2d,hops=%2d, Addr=%s, Name=%s", type, hops,
visable_ipx_adr(ad), name));
@ -752,6 +769,8 @@ static void handle_event(int fd, uint16 socknr, int slot)
/* it also can be Packets from DOSEMU OR ncpfs on this machine */
XDPRINTF((2,0,"Packet from OWN maschine:sock=0x%x", source_sock));
}
if (auto_creat_interfaces && test_ins_device_net(GET_BE32(source_adr.net)))
broadmillisecs = 3000; /* now faster rip/sap to new devices */
#endif
switch (slot) {
@ -844,11 +863,19 @@ static void get_ini(int full)
if (sscanf(inhalt, "%ld%c", &nd->net, &dummy) != 1)
sscanf(inhalt, "%lx", &nd->net);
if (nd->net == internal_net) {
errorp(11, "Get_ini", "device net 0x%lx = internal net", nd->net);
exit(1);
}
if (anz > 1)
new_str(nd->devname, inhalt2);
if (anz > 2) {
upstr(inhalt3);
if (!strcmp(inhalt3, "AUTO"))
nd->frame=-1;
if (!strcmp(inhalt3, "802.3"))
nd->frame=IPX_FRAME_8023;
else if (!strcmp(inhalt3, "802.2"))
@ -857,6 +884,10 @@ static void get_ini(int full)
nd->frame=IPX_FRAME_SNAP;
else if (!strcmp(inhalt3, "ETHERNET_II"))
nd->frame=IPX_FRAME_ETHERII;
# ifdef IPX_FRAME_TR_8022
else if (!strcmp(inhalt3, "TOKEN"))
nd->frame=IPX_FRAME_TR_8022;
# endif
}
if (anz > 3) nd->ticks = atoi(inhalt4);
}
@ -866,11 +897,13 @@ static void get_ini(int full)
case 5 : save_ipx_routes=atoi(inhalt);
break;
#endif
#if !IN_NWROUTED
case 104 : /* nwclient */
if (client_mode && atoi(inhalt))
client_mode++;
break;
#endif
case 210 : server_goes_down_secs=atoi(inhalt);
if (server_goes_down_secs < 1 ||
server_goes_down_secs > 600)
@ -919,29 +952,47 @@ static void get_ini(int full)
if (full) {
#ifdef LINUX
# if INTERNAL_RIP_SAP
no_internal = !internal_net;
if (no_internal && anz_net_devices > 1) {
errorp(11, "Get_ini", "No internal net, but more than 1 Device specified");
exit(1);
}
init_ipx(internal_net, node, ipxdebug);
for (k=0; k < anz_net_devices; k++){
NW_NET_DEVICE *nd=net_devices[k];
char *frname=NULL;
switch (nd->frame) {
case IPX_FRAME_8022 : frname = "802.2"; break;
case IPX_FRAME_8023 : frname = "802.3"; break;
case IPX_FRAME_SNAP : frname = "SNAP"; break;
case IPX_FRAME_ETHERII : frname = "ETHERNET_II";break;
default : break;
} /* switch */
XDPRINTF((1, 0, "DEVICE=%s, FRAME=%s, NETWORK=0x%lx",
nd->devname, frname, nd->net));
init_dev(nd->devname, nd->frame, nd->net);
int result;
uint8 frname[30];
char *sp = "DEVICE=%s, FRAME=%s, NETWORK=0x%lx";
(void) get_frame_name(frname, nd->frame);
XDPRINTF((1, 0, sp, nd->devname, frname, nd->net));
if ((result= init_dev(nd->devname, nd->frame, nd->net)) < 0) {
if (result == -99) {
errorp(11, "init_dev", "AUTO device is only in combination with internal net allowed");
exit(1);
} else
errorp(1, "init_dev", sp, nd->devname, frname, nd->net);
} else if (!result)
nd->is_up = 1;
else auto_creat_interfaces=1;
}
# endif
#endif
if (!get_ipx_addr(&my_server_adr)) {
internal_net = GET_BE32(my_server_adr.net);
} else exit(1);
XDPRINTF((1, 0, "Servername='%s', INTERNAL NET=0x%lx, NODE=0x%02x:%02x:%02x:%02x:%02x:%02x",
my_nwname, internal_net,
#if LINUX && INTERNAL_RIP_SAP
if (no_internal) {
errorp(10, "WARNING:No use of internal net", NULL);
} else if (!anz_net_devices) {
errorp(10, "WARNING:No external devices specified", NULL);
}
print_routing_info();
#endif
XDPRINTF((1, 0, "%s name='%s', INTERNAL NET=0x%lx, NODE=0x%02x:%02x:%02x:%02x:%02x:%02x",
prog_name_typ, my_nwname, internal_net,
(int)my_server_adr.node[0],
(int)my_server_adr.node[1],
(int)my_server_adr.node[2],
@ -982,9 +1033,9 @@ static void close_all(void)
close(fd_nwbind_in);
fd_nwbind_in = -1;
}
kill(pid_nwbind, SIGQUIT); /* terminate ncpserv */
kill(pid_nwbind, SIGQUIT); /* terminate nwbind */
waitpid(pid_nwbind, &status, 0);
kill(pid_nwbind, SIGKILL); /* kill ncpserv */
kill(pid_nwbind, SIGKILL); /* kill nwbind */
}
#ifdef LINUX
@ -992,9 +1043,11 @@ static void close_all(void)
if (!save_ipx_routes) {
for (j=0; j<anz_net_devices;j++) {
NW_NET_DEVICE *nd=net_devices[j];
XDPRINTF((1, 0, "Close Device=%s, frame=%d",
if (nd->is_up) {
XDPRINTF((1, 0, "Close Device=%s, frame=%d",
nd->devname, nd->frame));
exit_dev(nd->devname, nd->frame);
exit_dev(nd->devname, nd->frame);
}
}
}
exit_ipx(!save_ipx_routes);
@ -1011,8 +1064,8 @@ static void down_server(void)
signal(SIGPIPE, SIG_IGN);
fprintf(stderr, "\007");
fprintf(stderr, "\n*********************************************\n");
fprintf(stderr, "\nWARNING: NWE-SERVER shuts down in %3d sec !!!\n",
server_goes_down_secs);
fprintf(stderr, "\nWARNING: NWE-%s shuts down in %3d sec !!!\n",
prog_name_typ, server_goes_down_secs);
fprintf(stderr, "\n*********************************************\n");
sleep(1);
fprintf(stderr, "\007\n");
@ -1033,7 +1086,7 @@ static void sig_quit(int rsig)
static void handle_hup_reqest(void)
{
get_ini_debug(NWSERV);
get_ini_debug(IN_PROG);
XDPRINTF((2,0, "Got HUP, reading ini."));
get_ini(0);
write_to_ncpserv(0xeeee, 0, NULL, 0); /* inform ncpserv */
@ -1060,14 +1113,25 @@ static int server_is_down=0;
int main(int argc, char **argv)
{
int j = -1;
int j = 0;
int init_mode=0;
tzset();
if (argc > 1) client_mode=1;
while (++j < argc) {
char *a=argv[j];
if (*a == '-') {
while (*(++a)) {
switch (*a) {
case 'h' : init_mode = 1; break;
case 'k' : init_mode = 2; break;
default : break;
}
}
} else if (*a == 'y') client_mode=1;
/* in client mode the testprog 'nwclient' will be startet. */
init_tools(NWSERV, 0);
}
init_tools(IN_PROG, init_mode);
get_ini(1);
j=-1;
while (++j < NEEDED_POLLS) {
polls[j].events = POLLIN|POLLPRI;
polls[j].revents = 0;
@ -1092,10 +1156,13 @@ int main(int argc, char **argv)
/* now do polling */
time_t broadtime;
time(&broadtime);
set_sigs();
creat_pidfile();
polls[NEEDED_SOCKETS].fd = fd_nwbind_in;
#if !FILE_SERVER_INACTIV
#if !IN_NWROUTED
{
ipxAddr_t server_adr_sap;
polls[NEEDED_SOCKETS+1].fd = fd_ncpserv_in;
@ -1106,6 +1173,7 @@ int main(int argc, char **argv)
&my_server_adr, &server_adr_sap, 0, 0, 0);
}
#endif
while (!server_is_down) {
int anz_poll = poll(polls, NEEDED_POLLS, broadmillisecs);
int call_wdog=0;
@ -1144,7 +1212,7 @@ int main(int argc, char **argv)
(char*)&conn, sizeof(int))
&& sizeof(int) == read(p->fd,
(char*)&size, sizeof(int))
&& sizeof(ipxAddr_t) + sizeof(uint16)
&& sizeof(ipxAddr_t) + sizeof(uint16) + sizeof(uint32)
== read(p->fd,
(char*)buf, size)) {
insert_wdog_conn(conn, (ipxAddr_t*)buf);
@ -1228,7 +1296,8 @@ int main(int argc, char **argv)
send_down_broadcast();
}
close_all();
fprintf(stderr, "\nNWE-SERVER is down now !!\n");
fprintf(stderr, "\nNWE-%s is down now !!\n", prog_name_typ);
exit_tools();
return(0);
}

View File

@ -1,4 +1,4 @@
/* nwserv.h 30-Jan-96 */
/* nwserv.h 26-Apr-96 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
@ -15,20 +15,24 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _M_NWSERV_H_
#define _M_NWSERV_H_
extern uint32 internal_net; /* NETWORKNUMMER INTERN (SERVER) */
extern ipxAddr_t my_server_adr; /* Address of this server */
extern char my_nwname[50]; /* Name of this server */
extern int no_internal; /* no use of internal net */
extern int auto_creat_interfaces;
extern ipxAddr_t my_server_adr; /* Address of this server */
extern char my_nwname[50]; /* Name of this server */
extern int print_route_tac; /* every x broadcasts print it */
extern int print_route_mode; /* append */
extern char *pr_route_info_fn; /* filename */
extern int print_route_mode; /* append */
extern char *pr_route_info_fn; /* filename */
extern int wdogs_till_tics;
typedef struct {
char *devname; /* "eth0" or "isdnX" */
int frame; /* frametyp */
char *devname; /* "eth0" or "isdnX" or ?? */
int frame; /* frametyp */
int ticks; /* ether:ticks=1, isdn:ticks=7 */
uint32 net; /* NETWORK NUMBER */
uint32 net; /* NETWORK NUMBER */
int is_up; /* Is this device up ? */
} NW_NET_DEVICE;
/* <========== DEVICES ==========> */
@ -55,13 +59,14 @@ extern void ins_del_bind_net_addr(uint8 *name, int styp, ipxAddr_t *adr);
extern void send_server_response(int respond_typ,
int styp, ipxAddr_t *to_addr);
extern void print_routing_info(void);
extern void send_sap_rip_broadcast(int mode);
extern void rip_for_net(uint32 net);
extern void get_servers(void);
extern void handle_rip(int fd, int ipx_pack_typ,
int data_len, IPX_DATA *ipxdata,
ipxAddr_t *from_addr);
int data_len, IPX_DATA *ipxdata,
ipxAddr_t *from_addr);
extern void insert_delete_server(uint8 *name,
@ -73,4 +78,5 @@ extern void insert_delete_server(uint8 *name,
int flags);
extern int dont_send_wdog(ipxAddr_t *addr);
extern int test_ins_device_net(uint32 rnet);
#endif

View File

@ -1,5 +1,5 @@
/* nwvolume.c 20-Mar-96 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
/* nwvolume.c 22-Apr-96 */
/* (C)opyright (C) 1993,1996 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
@ -62,44 +62,79 @@ void nw_init_volumes(FILE *f)
int len;
int founds = sscanf((char*)buff, "%s %s %s",sysname, unixname, optionstr);
if (founds > 1) {
new_str(nw_volumes[used_nw_volumes].sysname, sysname);
len = strlen((char*)unixname);
if (unixname[len-1] != '/') {
NW_VOL *vol=&(nw_volumes[used_nw_volumes]);
vol->options = 0;
new_str(vol->sysname, sysname);
if (1 == (len = strlen((char*)unixname)) && unixname[0] == '~') {
vol->options |= VOL_OPTION_IS_HOME;
unixname[0] = '\0';
len = 0;
} else if (unixname[len-1] != '/') {
unixname[len++] = '/';
unixname[len] = '\0';
}
nw_volumes[used_nw_volumes].unixnamlen = len;
nw_volumes[used_nw_volumes].options = 0;
new_str(nw_volumes[used_nw_volumes].unixname, unixname);
vol->unixnamlen = len;
new_str(vol->unixname, unixname);
if (founds > 2) {
for (p=optionstr; *p; p++) {
switch (*p) {
case 'k' : nw_volumes[used_nw_volumes].options
|= VOL_OPTION_DOWNSHIFT; break;
case 'k' : vol->options
|= VOL_OPTION_DOWNSHIFT;
break;
case 'p' : nw_volumes[used_nw_volumes].options
|= VOL_OPTION_IS_PIPE; break;
case 'm' : vol->options
|= VOL_OPTION_REMOUNT;
break;
case 'm' : nw_volumes[used_nw_volumes].options
|= VOL_OPTION_REMOUNT; break;
case 'o' : vol->options
|= VOL_OPTION_ONE_DEV;
break;
case 'p' : vol->options
|= VOL_OPTION_IS_PIPE;
break;
default : break;
}
}
}
used_nw_volumes++;
if (vol->options & VOL_OPTION_ONE_DEV) {
vol->max_maps_count = 1;
vol->high_inode = 0xffffffff;
} else {
vol->max_maps_count = MAX_DEV_NAMESPACE_MAPS;
vol->high_inode = 0xfffffff;
}
}
}
} /* while */
}
void nw_setup_home_vol(int len, uint8 *fn)
{
int k=used_nw_volumes;
uint8 unixname[258];
unixname[0] = '\0';
if (len > 0) {
strmaxcpy(unixname, fn, len);
if (unixname[len-1] != '/') {
unixname[len++] = '/';
unixname[len] = '\0';
}
}
while (k--) {
if (nw_volumes[k].options & VOL_OPTION_IS_HOME) {
nw_volumes[k].unixnamlen = len;
new_str(nw_volumes[k].unixname, unixname);
}
}
}
static int look_name_space_map(int volume, DEV_NAMESPACE_MAP *dnm,
static int look_name_space_map(NW_VOL *v, DEV_NAMESPACE_MAP *dnm,
int do_insert)
{
int result=-1;
if (volume > -1 && volume < used_nw_volumes) {
NW_VOL *v= &(nw_volumes[volume]);
DEV_NAMESPACE_MAP *mp;
int k=-1;
while (++k < v->maps_count) {
@ -107,31 +142,35 @@ static int look_name_space_map(int volume, DEV_NAMESPACE_MAP *dnm,
if (mp->dev == dnm->dev && mp->namespace == dnm->namespace)
return(k);
}
if (do_insert && v->maps_count < MAX_DEV_NAMESPACE_MAPS) {
if (do_insert && v->maps_count < v->max_maps_count) {
/* now do insert the new map */
mp = v->dev_namespace_maps[v->maps_count++] =
(DEV_NAMESPACE_MAP*) xmalloc(sizeof(DEV_NAMESPACE_MAP));
memcpy(mp, dnm, sizeof(DEV_NAMESPACE_MAP));
return(k);
}
}
return(result);
return(-1);
}
uint32 nw_vol_inode_to_handle(int volume, ino_t inode,
DEV_NAMESPACE_MAP *dnm)
{
if (inode > 0 && inode < 0x1000000) {
int result = look_name_space_map(volume, dnm, 1);
if (result > -1) {
uint32 handle = (((uint32)result) << 28) | (uint32) inode;
XDPRINTF((3,0, "Handle map inode=%d, dev=%d, namespace=%d to handle 0x%x",
inode, dnm->dev, dnm->namespace, handle));
return(handle);
if (volume > -1 && volume < used_nw_volumes) {
NW_VOL *v= &(nw_volumes[volume]);
if (inode > 0 && inode <= v->high_inode) {
int result = look_name_space_map(v, dnm, 1);
if (result > -1) {
uint32 handle = (v->options & VOL_OPTION_ONE_DEV)
? (uint32)inode
: (((uint32)result) << 28) | (uint32) inode;
XDPRINTF((3,0, "Handle map inode=%d, dev=%d, namespace=%d to handle 0x%x",
inode, dnm->dev, dnm->namespace, handle));
return(handle);
}
}
}
XDPRINTF((1,0, "Cannot map inode=%d, dev=%d, namespace=%d to handle",
inode, dnm->dev, dnm->namespace));
XDPRINTF((1,0, "Cannot map inode=%d, dev=%d, namespace=%d to vol=%d handle",
inode, dnm->dev, dnm->namespace, volume));
return(0L);
}
@ -141,16 +180,17 @@ ino_t nw_vol_handle_to_inode(int volume, uint32 handle,
{
if (handle > 0 && volume > -1 && volume < used_nw_volumes) {
NW_VOL *v= &(nw_volumes[volume]);
int entry = (int) ((handle >> 28) & 0xFF);
int entry = (v->options & VOL_OPTION_ONE_DEV)
? 0
: (int) ((handle >> 28) & 0xF);
if (entry > -1 && entry < v->maps_count) {
if (dnm) memcpy(dnm, v->dev_namespace_maps[entry],
sizeof(DEV_NAMESPACE_MAP));
XDPRINTF((1, 0, "vol=%d, handle=0x%x to ino=%d, dev=%d, namespace=%d",
volume, handle, (int)(handle & 0xFFFFFF),
XDPRINTF((3, 0, "vol=%d, handle=0x%x to ino=%d, dev=%d, namespace=%d",
volume, handle, (int)(handle & v->high_inode),
v->dev_namespace_maps[entry]->dev,
v->dev_namespace_maps[entry]->namespace));
return((ino_t) (handle & 0xFFFFFF));
return((ino_t) (handle & v->high_inode));
}
}
XDPRINTF((1, 0, "Can't vol=%d, handle=0x%x to inode", volume, handle));

View File

@ -1,4 +1,4 @@
/* nwvolume.h 07-Feb-96 */
/* nwvolume.h 29-Mar-96 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
@ -18,7 +18,7 @@
#ifndef _NWVOLUME_H_
#define _NWVOLUME_H_
#define MAX_DEV_NAMESPACE_MAPS 256
#define MAX_DEV_NAMESPACE_MAPS 16
typedef struct {
int dev;
@ -32,17 +32,21 @@ typedef struct {
*/
typedef struct {
uint8 *sysname; /* VOL_NAME */
uint8 *unixname; /* UNIX-DIR */
int unixnamlen; /* len of unixname */
uint8 *sysname; /* VOL_NAME */
uint8 *unixname; /* UNIX-DIR */
int unixnamlen; /* len of unixname */
DEV_NAMESPACE_MAP *dev_namespace_maps[MAX_DEV_NAMESPACE_MAPS];
int maps_count; /* count of dev_namespace_maps */
uint8 options; /* *_1_* all is lowercase */
int max_maps_count; /* may be less than MAX_DEV_NAMESPACE_MAPS */
int maps_count; /* count of dev_namespace_maps */
uint32 high_inode; /* hight inode to can handle correct */
int options; /* *_1_* all is lowercase */
} NW_VOL;
#define VOL_OPTION_DOWNSHIFT 1
#define VOL_OPTION_IS_PIPE 2 /* Volume has only pipes */
#define VOL_OPTION_REMOUNT 4 /* Volume can be remounted (cdroms) */
#define VOL_OPTION_DOWNSHIFT 0x01 /* All downshift */
#define VOL_OPTION_IS_PIPE 0x02 /* Volume contains pipes */
#define VOL_OPTION_REMOUNT 0x04 /* Volume can be remounted (cdroms) */
#define VOL_OPTION_IS_HOME 0x08 /* Volume is USERS HOME */
#define VOL_OPTION_ONE_DEV 0x10 /* Volume has only one filesys */
/* stolen from GNU-fileutils */
/* Space usage statistics for a filesystem. Blocks are 512-byte. */
@ -58,6 +62,7 @@ extern NW_VOL nw_volumes[MAX_NW_VOLS];
extern int used_nw_volumes;
extern void nw_init_volumes(FILE *f);
extern void nw_setup_home_vol(int len, uint8 *fn);
extern int nw_get_volume_number(uint8 *volname, int namelen);
extern int nw_get_volume_name(int volnr, uint8 *volname);
extern int nw_get_fs_usage(uint8 *volname, struct fs_usage *fsu);

173
tools.c
View File

@ -1,4 +1,4 @@
/* tools.c 20-Mar-96 */
/* tools.c 06-May-96 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
@ -20,9 +20,8 @@
#include <stdarg.h>
#ifndef LINUX
#include <errno.h>
extern int _sys_nerr;
extern char _sys_errlist[];
extern int _sys_nerr;
extern char *_sys_errlist[];
#endif
@ -33,13 +32,14 @@ static int in_module=0; /* in which process i am ? */
static int connection=0; /* which connection (nwconn) */
static int my_pid = -1;
static void (*sigsegv_func)(int isig);
static char *modnames[] =
{ "???????",
"NWSERV ",
static char *modnames[] =
{ "?",
"NWSERV",
"NCPSERV",
"NWCONN ",
"NWCLIEN",
"NWBIND " };
"NWCONN",
"NWCLIENT",
"NWBIND",
"NWROUTED" };
static char *get_modstr(void)
{
@ -93,7 +93,7 @@ void dprintf(char *p, ...)
{
va_list ap;
if (nw_debug){
fprintf(logfile, "%s:", get_modstr());
fprintf(logfile, "%-8s:", get_modstr());
va_start(ap, p);
vfprintf(logfile, p, ap);
va_end(ap);
@ -107,7 +107,7 @@ void xdprintf(int dlevel, int mode, char *p, ...)
{
va_list ap;
if (nw_debug >= dlevel) {
if (!(mode & 1)) fprintf(logfile, "%s %d:", get_modstr(), connection);
if (!(mode & 1)) fprintf(logfile, "%-8s %d:", get_modstr(), connection);
if (p) {
va_start(ap, p);
vfprintf(logfile, p, ap);
@ -123,12 +123,20 @@ void errorp(int mode, char *what, char *p, ...)
va_list ap;
int errnum = errno;
FILE *lologfile = logfile;
char errbuf[200];
char *errstr = errbuf;
if (mode > 9) {
errnum = -1;
mode -= 10;
}
if (errnum >= 0 && errnum < _sys_nerr) errstr = _sys_errlist[errnum];
else if (errnum > -1)
sprintf(errbuf, "errno=%d", errnum);
else
errbuf[0] = '\0';
while (1) {
if (mode==1) 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 (mode==1) fprintf(lologfile, "\n!! %-8s %d:PANIC !!\n", get_modstr(), connection);
fprintf(lologfile, "%-8s %d:%s:%s\n", get_modstr(), connection, what, errstr);
if (p) {
va_start(ap, p);
vfprintf(lologfile, p, ap);
@ -193,9 +201,24 @@ int get_ini_entry(FILE *f, int entry, uint8 *str, int strsize)
return(0);
}
char *get_exec_path(char *buff, char *progname)
char *get_div_pathes(char *buff, char *name, int what, char *p, ... )
{
sprintf(buff, "%s/%s", PATHNAME_PROGS, progname);
char *wpath;
int len;
switch (what) {
case 0 : wpath = PATHNAME_PROGS; break;
case 1 : wpath = PATHNAME_BINDERY; break;
case 2 : wpath = PATHNAME_PIDFILES; break;
default : buff[0]='\0';
return(buff);
}
len=sprintf(buff, (name && *name) ? "%s/%s" : "%s/", wpath, name);
if (NULL != p) {
va_list ap;
va_start(ap, p);
vsprintf(buff+len, p, ap);
va_end(ap);
}
return(buff);
}
@ -214,6 +237,8 @@ void get_ini_debug(int module)
* 2 = ncpserv
* 3 = nwconn
* 4 = nwclient
* 5 = nwbind
* 6 = nwrouted
*/
{
int debug = get_ini_int(100+module);
@ -226,42 +251,96 @@ static void sig_segv(int isig)
XDPRINTF((0, 0, s, my_pid));
fprintf(stderr, "\n");
fprintf(stderr, s, my_pid);
#if 1
#if 0
(*sigsegv_func)(isig);
#endif
}
void init_tools(int module, int conn)
static int fn_exist(char *fn)
{
uint8 buff[300];
char logfilename[300];
struct stat stb;
return((stat(fn, &stb) == -1) ? 0 : stb.st_mode);
}
static char *get_pidfilefn(char *buf)
{
char lbuf[100];
strcpy(lbuf, get_modstr());
return(get_div_pathes(buf, downstr((uint8*)lbuf), 2, ".pid"));
}
void creat_pidfile(void)
{
char buf[300];
char *pidfn=get_pidfilefn(buf);
FILE *f=fopen(pidfn, "w");
if (f != NULL) {
fprintf(f, "%d\n", getpid());
fclose(f);
} else {
XDPRINTF((1, 0, "Cannot creat pidfile=%s", pidfn));
}
}
void init_tools(int module, int options)
{
uint8 buf[300];
char logfilename[300];
FILE *f=open_nw_ini();
int withlog=0;
int dodaemon=0;
int new_log=0;
int withlog=0;
int dodaemon=0;
int new_log=0;
in_module = module;
connection = conn;
connection = (NWCONN == module) ? options : 0;
if (NWSERV == module || NWROUTED == module) {
char *pidfn=get_pidfilefn(buf);
if (fn_exist(pidfn)) {
int sig;
FILE *pf;
if (options == 1) { /* kill -HUP prog */
sig = SIGHUP;
} else if (options == 2) { /* kill prog */
sig = SIGTERM;
} else {
errorp(11, "INIT", "Program allways running or pidfn=%s exists" ,
pidfn);
exit(1);
}
if ( NULL != (pf=fopen(pidfn, "r"))) {
int kill_pid=0;
if (1 == fscanf(pf, "%d", &kill_pid) && kill_pid > 1)
kill(kill_pid, sig);
fclose(pf);
exit(0);
}
exit(1);
} else if (options == 1 || options == 2) {
errorp(11, "INIT", "Program not running or pidfn=%s not exists" ,
pidfn);
exit(1);
}
}
if (f) {
int what;
while (0 != (what=get_ini_entry(f, 0, buff, sizeof(buff)))) { /* daemonize */
if (200 == what) dodaemon = atoi((char*)buff);
while (0 != (what=get_ini_entry(f, 0, buf, sizeof(buf)))) { /* daemonize */
if (200 == what) dodaemon = atoi((char*)buf);
else if (201 == what) {
strmaxcpy((uint8*)logfilename, (uint8*)buff, sizeof(logfilename)-1);
strmaxcpy((uint8*)logfilename, (uint8*)buf, sizeof(logfilename)-1);
withlog++;
} else if (202 == what) {
new_log = atoi((char*)buff);
} else if (100+module == what) nw_debug=atoi((char*)buff);
new_log = atoi((char*)buf);
} else if (100+module == what) nw_debug=atoi((char*)buf);
}
fclose(f);
}
if (dodaemon) {
if (!withlog) strcpy(logfilename, "./nw.log");
if (NWSERV == module) { /* now make daemon */
if (NWSERV == module || NWROUTED == module) { /* now make daemon */
int fd=fork();
if (fd) exit((fd > 0) ? 0 : 1);
}
if (NULL == (logfile = fopen(logfilename,
(new_log && NWSERV == module) ? "w" : "a"))) {
(new_log && (NWSERV == module || NWROUTED == module)) ? "w" : "a"))) {
char sxx[100];
sprintf(sxx, "\n\nOpen logfile `%s`", logfilename);
perror(sxx);
@ -269,19 +348,25 @@ void init_tools(int module, int conn)
fprintf(stderr, "\n!! ABORTED !!\n");
exit(1);
}
if (NWSERV == module) setsid();
if (NWSERV == module || NWROUTED == module) setsid();
}
if (NWSERV == module || NCPSERV == module || NWBIND == module ||
nw_debug > 1) {
if ( NWCONN != module || nw_debug > 1 ) {
XDPRINTF((1, 0, "Starting Version: %d.%02dpl%d",
_VERS_H_, _VERS_L_, _VERS_P_ ));
}
sigsegv_func = signal(SIGSEGV, sig_segv);
#if 1
if (nw_debug < 8)
sigsegv_func = signal(SIGSEGV, sig_segv);
#endif
my_pid = getpid();
}
void exit_tools(int what)
void exit_tools(void)
{
if (in_module == NWSERV || in_module == NWROUTED) {
char buf[300];
unlink(get_pidfilefn(buf));
}
if (logfile != stdout) {
if (logfile != NULL) fclose(logfile);
logfile=stdout;
@ -312,17 +397,19 @@ uint8 up_char(uint8 ch)
return(ch);
}
uint8 *upstr(uint8 *s)
uint8 *upstr(uint8 *ss)
{
uint8 *s=ss;
if (!s) return((uint8*)NULL);
for (;*s;s++) *s=up_char(*s);
return(s);
return(ss);
}
uint8 *downstr(uint8 *s)
uint8 *downstr(uint8 *ss)
{
uint8 *s=ss;
if (!s) return((uint8*)NULL);
for (;*s;s++) *s=down_char(*s);
return(s);
return(ss);
}

15
tools.h
View File

@ -1,4 +1,4 @@
/* tools.h : 20-Mar-96 */
/* tools.h : 01-May-96 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
@ -25,6 +25,7 @@
#define NWCONN 3
#define NWCLIENT 4
#define NWBIND 5
#define NWROUTED 6
extern FILE *logfile;
extern void x_x_xfree(char **p);
@ -44,15 +45,19 @@ extern void xdprintf(int dlevel, int mode, char *p, ...);
extern void errorp(int mode, char *what, char *p, ...);
extern FILE *open_nw_ini(void);
extern int get_ini_entry(FILE *f, int entry, uint8 *str, int strsize);
extern char *get_exec_path(char *buff, char *progname);
extern char *get_div_pathes(char *buff, char *name, int what, char *p, ... );
#define get_exec_path(bu, progn) get_div_pathes((bu), (progn), 0, NULL)
extern int get_ini_int(int what);
extern void get_ini_debug(int what);
extern void init_tools(int module, int conn);
extern void creat_pidfile(void);
extern void init_tools(int module, int options);
extern void exit_tools(void);
extern uint8 down_char(uint8 ch);
extern uint8 up_char(uint8 ch);
extern uint8 *downstr(uint8 *s);
extern uint8 *upstr(uint8 *s);
extern uint8 *downstr(uint8 *ss);
extern uint8 *upstr(uint8 *ss);
extern int nw_debug;

54
unxfile.c Normal file
View File

@ -0,0 +1,54 @@
/* unxfile.c: 29-Apr-96*/
/* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "net.h"
#include "unxfile.h"
#if 1
int unx_mvdir(uint8 *oldname, uint8 *newname)
{
struct stat statb;
if (!stat(newname, &statb)) return(EEXIST);
if (stat(oldname, &statb)) return(-1);
else if (!S_ISDIR(statb.st_mode)) return(-1);
return( (rename(oldname, newname) < 0) ? errno : 0);
}
int unx_mvfile(uint8 *oldname, uint8 *newname)
{
struct stat statb;
if (!stat(newname, &statb)) return(EEXIST);
if (stat(oldname, &statb)) return(-1);
else if (S_ISDIR(statb.st_mode)) return(-1);
return( (rename(oldname, newname) < 0) ? errno : 0);
}
#else
int unx_mvdir(uint8 *oldname, uint8 *newname)
{
uint8 command[500];
struct stat statb;
if (!stat(newname, &statb)) return(EEXIST);
if (stat(oldname, &statb)) return(-1);
else if (!S_ISDIR(statb.st_mode)) return(-1);
sprintf(command, "mv %s %s 2>&1 >/dev/null" , oldname, newname);
return(system(command));
}
#endif

22
unxfile.h Normal file
View File

@ -0,0 +1,22 @@
/* unxfile.h: 29-Apr-96*/
/* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
extern int unx_mvdir(uint8 *oldname, uint8 *newname);
extern int unx_mvfile(uint8 *oldname, uint8 *newname);

77
unxlog.c Normal file
View File

@ -0,0 +1,77 @@
/* unxlog.c : 30-Apr-96 */
/* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "net.h"
#include "unxlog.h"
void write_utmp(int dologin, int connection, int pid,
ipxAddr_t *from_addr, uint8 *username)
{
struct utmp loc_ut;
struct utmp *ut;
int fd;
char buff[200];
int found = 0;
char *fn_utmp=FILENAME_UTMP;
char *fn_wtmp=FILENAME_WTMP;
if (NULL == fn_utmp) return;
utmpname(fn_utmp);
setutent();
sprintf(buff, "NCP%03d", connection);
while (NULL != (ut = getutent())) {
if (pid == ut->ut_pid ||
!strncmp(buff, ut->ut_line, sizeof(ut->ut_line))) {
found++;
break;
}
}
if (!found) {
if (!dologin) {
endutent();
return;
} else {
ut=&loc_ut;
memset(ut, 0, sizeof(struct utmp));
}
}
ut->ut_type = dologin ? USER_PROCESS : DEAD_PROCESS;
if (dologin) {
strncpy(ut->ut_line, buff, sizeof(ut->ut_line));
ut->ut_pid = pid;
sprintf(buff, "%d", connection);
strncpy(ut->ut_id, buff, sizeof(ut->ut_id));
if (username) strncpy((char*)ut->ut_user, (char*)username, sizeof(ut->ut_user));
#ifdef LINUX
ut->ut_addr = (long) GET_BE32(from_addr->net);
strncpy(ut->ut_host, xvisable_ipx_adr(from_addr, 2), sizeof(ut->ut_host));
#endif
} else {
memset(ut->ut_user, 0, sizeof(ut->ut_user));
ut->ut_pid = 0;
}
(void)time(&(ut->ut_time));
pututline(ut);
endutent();
if (NULL == fn_wtmp) return;
if ((fd = open(fn_wtmp, O_APPEND|O_WRONLY)) > -1) {
write(fd, (char *)ut, sizeof(struct utmp));
close(fd);
}
}

5
unxlog.h Normal file
View File

@ -0,0 +1,5 @@
/* unxlog.h */
extern void write_utmp(int dologin, int connection, int pid,
ipxAddr_t *from_addr, uint8 *username);