2816 lines
112 KiB
C
2816 lines
112 KiB
C
/* nwconn.c 18-Apr-00 */
|
||
/* one process / connection */
|
||
|
||
/* (C)opyright (C) 1993,2000 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.
|
||
*/
|
||
|
||
/* history since 21-Apr-00
|
||
*
|
||
* mst:25-Apr-00: added routines for sending nwconn data to nwbind
|
||
*
|
||
*/
|
||
|
||
|
||
#include "net.h"
|
||
#if 1
|
||
# define LOC_RW_BUFFERSIZE RW_BUFFERSIZE
|
||
#else
|
||
# define LOC_RW_BUFFERSIZE 512
|
||
#endif
|
||
#include <dirent.h>
|
||
#if !CALL_NWCONN_OVER_SOCKET
|
||
#include <sys/ipc.h>
|
||
#include <sys/shm.h>
|
||
#endif
|
||
|
||
#include "nwvolume.h"
|
||
#include "nwfile.h"
|
||
#include "connect.h"
|
||
#include "nwqconn.h"
|
||
#include "namspace.h"
|
||
#include "nwshare.h"
|
||
#include "nwconn.h"
|
||
|
||
int act_pid = 0;
|
||
|
||
#define FD_NCP_OUT 3
|
||
|
||
static int father_pid = -1;
|
||
static ipxAddr_t from_addr;
|
||
static ipxAddr_t my_addr;
|
||
static struct t_unitdata ud;
|
||
static uint8 ipx_pack_typ = PACKT_CORE;
|
||
static int last_sequence = -9999;
|
||
|
||
static IPX_DATA ipxdata;
|
||
static NCPRESPONSE *ncpresponse=(NCPRESPONSE*)&ipxdata;
|
||
static uint8 *responsedata=((uint8*)&ipxdata)+sizeof(NCPRESPONSE);
|
||
|
||
static int requestlen;
|
||
static uint8 readbuff[IPX_MAX_DATA];
|
||
|
||
static uint8 saved_readbuff[IPX_MAX_DATA];
|
||
static int saved_sequence=-1;
|
||
static int rw_buffer_size = LOC_RW_BUFFERSIZE; /* default */
|
||
|
||
static NCPREQUEST *ncprequest = (NCPREQUEST*)readbuff;
|
||
static uint8 *requestdata = readbuff + sizeof(NCPREQUEST);
|
||
static int ncp_type;
|
||
static int sock_nwbind=-1;
|
||
static int sock_echo =-1;
|
||
static char *prog_title;
|
||
|
||
static int req_printed=0;
|
||
|
||
#if !CALL_NWCONN_OVER_SOCKET
|
||
static char* nwconn_state; /* shared memory segment will be
|
||
* attached to this pointer */
|
||
#endif
|
||
|
||
#if ENABLE_BURSTMODE
|
||
typedef struct {
|
||
BURSTPACKET *sendburst; /* buffer for sending burstpacket
|
||
* allocated and prefilled by response to
|
||
* func 0x65
|
||
* max. max_packet_size
|
||
*/
|
||
|
||
uint8 *send_buf; /* we look from servers side
|
||
* complete data buf of burst reply
|
||
* file read status + file read buf
|
||
* sendbuff must be 8 byte more allocated
|
||
* than max_send_size !
|
||
*/
|
||
|
||
int max_send_size; /* send_buf size, complete Burst DATA size */
|
||
|
||
uint32 packet_sequence; /* -> packet_sequence
|
||
* will be increased after every
|
||
* packet
|
||
*/
|
||
int burst_sequence;
|
||
|
||
struct t_unitdata ud;
|
||
ipxAddr_t to_addr;
|
||
|
||
uint8 *recv_buf; /* complete data buf for burst read requests
|
||
* must be 24 byte more allocated
|
||
* than max_recv_size !
|
||
*/
|
||
|
||
int max_recv_size; /* allocated size of recv_buf */
|
||
|
||
int max_burst_data_size; /* size of BURSTDATA, max. IPX_DATA - BURSTHEADER */
|
||
uint8 ipx_pack_typ;
|
||
} BURST_W;
|
||
|
||
static BURST_W *burst_w=NULL;
|
||
#endif
|
||
|
||
void nwconn_set_program_title(char *s)
|
||
{
|
||
memset(prog_title, 0, 49);
|
||
if (s&&*s)
|
||
strmaxcpy(prog_title, s, 48);
|
||
else
|
||
strcpy(prog_title, "()");
|
||
}
|
||
|
||
|
||
static int ncp_response(int sequence, int task,
|
||
int completition, int data_len)
|
||
{
|
||
ncpresponse->sequence = (uint8) sequence;
|
||
ncpresponse->task = (uint8) task;
|
||
ncpresponse->completition = (uint8) completition;
|
||
last_sequence = sequence;
|
||
|
||
if (req_printed) {
|
||
XDPRINTF((0,0, "NWCONN NCP_RESP seq:%d, conn:%d, compl=0x%x task=%d TO %s",
|
||
(int)ncpresponse->sequence,
|
||
(int)ncpresponse->connection
|
||
| (((int)ncpresponse->high_connection) << 8),
|
||
(int)completition,
|
||
(int)ncpresponse->task, visable_ipx_adr((ipxAddr_t *) ud.addr.buf)));
|
||
}
|
||
ud.udata.len = ud.udata.maxlen = sizeof(NCPRESPONSE) + data_len;
|
||
if (t_sndudata(FD_NCP_OUT, &ud) < 0){
|
||
if (nw_debug) t_error("t_sndudata in NWCONN !OK");
|
||
return(-1);
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
static int call_nwbind(int mode)
|
||
/* modes 0: 'standard' call
|
||
* 1: activate wdog
|
||
*/
|
||
{
|
||
ipxAddr_t to_addr;
|
||
int result;
|
||
memcpy(&to_addr, &my_addr, sizeof(ipxAddr_t));
|
||
U16_TO_BE16(sock_nwbind, to_addr.sock);
|
||
ud.addr.buf = (char*)&to_addr;
|
||
if (mode==1) { /* reset wdogs */
|
||
NCPREQUEST buf;
|
||
buf.type[0] = buf.type[1]=0x22;
|
||
buf.sequence = ncprequest->sequence;
|
||
buf.connection = ncprequest->connection;
|
||
buf.task = ncprequest->task;
|
||
buf.high_connection = ncprequest->high_connection;
|
||
buf.function = 0;
|
||
ud.udata.len = ud.udata.maxlen = sizeof(buf);
|
||
ud.udata.buf = (char*)&buf;
|
||
XDPRINTF((3, 0, "send wdog reset"));
|
||
result=t_sndudata(FD_NCP_OUT, &ud);
|
||
} else {
|
||
ud.udata.len = ud.udata.maxlen = sizeof(NCPREQUEST) + requestlen;
|
||
ud.udata.buf = (char*)&readbuff;
|
||
result=t_sndudata(FD_NCP_OUT, &ud);
|
||
}
|
||
ud.addr.buf = (char*)&from_addr;
|
||
ud.udata.buf = (char*)&ipxdata;
|
||
if (result< 0){
|
||
if (nw_debug) t_error("t_sndudata in NWCONN !OK");
|
||
return(-1);
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
static void pr_debug_request()
|
||
{
|
||
if (req_printed++) return;
|
||
if (ncp_type == 0x2222) {
|
||
int ufunc = 0;
|
||
switch (ncprequest->function) {
|
||
case 0x16 :
|
||
case 0x17 : ufunc = (int) *(requestdata+2); break;
|
||
case 0x57 : ufunc = (int) *(requestdata); break;
|
||
default : break;
|
||
} /* switch */
|
||
XDPRINTF((1, 0, "NCP REQUEST: func=0x%02x, ufunc=0x%02x, seq:%03d, task:%02d",
|
||
(int)ncprequest->function, ufunc,
|
||
(int)ncprequest->sequence,
|
||
(int)ncprequest->task));
|
||
} else {
|
||
XDPRINTF((1, 0, "Got NCP:type:0x%x, seq:%d, task:%d, func=0x%x",
|
||
ncp_type,
|
||
(int)ncprequest->sequence,
|
||
(int)ncprequest->task,
|
||
(int)ncprequest->function));
|
||
}
|
||
if (requestlen > 0){
|
||
int j = requestlen;
|
||
uint8 *p=requestdata;
|
||
XDPRINTF((0, 2, "len %d, DATA:", j));
|
||
while (j--) {
|
||
int c = *p++;
|
||
if (c > 32 && c < 127) XDPRINTF((0, 3,",\'%c\'", (char) c));
|
||
else XDPRINTF((0,3, ",0x%x", c));
|
||
}
|
||
XDPRINTF((0,1,NULL));
|
||
}
|
||
}
|
||
#if TEST_FNAME
|
||
static int test_handle = -1;
|
||
#endif
|
||
|
||
static void handle_nwbind_request(void) /* mst:25-Apr-00 */
|
||
{
|
||
int result = 0;
|
||
char buf[IPX_MAX_DATA];
|
||
char *data = &(buf[sizeof(NCPRESPONSE)]);
|
||
int data_len = 0;
|
||
|
||
switch (ncprequest->function) {
|
||
case 0x1: { /* get number and handles of open files */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 offset[4]; /* handle offset */
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
struct XDATA {
|
||
uint8 count_handles[4];
|
||
uint8 handles[4];
|
||
} *xdata = (struct XDATA*) data;
|
||
int handles = nw_get_count_open_files(xdata->handles, GET_BE32(input->offset));
|
||
U32_TO_BE32(handles, xdata->count_handles);
|
||
data_len = (handles+1) * 4;
|
||
}
|
||
break;
|
||
|
||
default :
|
||
result = 0xfb;
|
||
}
|
||
|
||
{
|
||
NCPRESPONSE *resp = (NCPRESPONSE*)&buf;
|
||
ipxAddr_t to_addr;
|
||
memcpy(&to_addr, &my_addr, sizeof(ipxAddr_t));
|
||
U16_TO_BE16(sock_nwbind, to_addr.sock);
|
||
ud.addr.buf = (char*)&to_addr;
|
||
|
||
resp->type[0] = resp->type[1]=0x32;
|
||
resp->sequence = ncprequest->sequence;
|
||
resp->connection = ncprequest->connection;
|
||
resp->task = ncprequest->task;
|
||
resp->high_connection = ncprequest->high_connection;
|
||
resp->completition = result;
|
||
resp->connect_status = 0;
|
||
ud.udata.len = ud.udata.maxlen = sizeof(NCPRESPONSE) + data_len;
|
||
ud.udata.buf = (char*)resp;
|
||
XDPRINTF((3, 0, "send reply to nwbind"));
|
||
result = t_sndudata(FD_NCP_OUT, &ud);
|
||
ud.addr.buf = (char*)&from_addr;
|
||
ud.udata.buf = (char*)&ipxdata;
|
||
}
|
||
}
|
||
|
||
static int handle_ncp_serv(void)
|
||
{
|
||
int function = (int)ncprequest->function;
|
||
int completition = 0; /* first set */
|
||
int org_nw_debug = nw_debug;
|
||
int do_druck = 0;
|
||
int data_len = 0;
|
||
|
||
if (last_sequence == (int)ncprequest->sequence
|
||
&& ncp_type != 0x1111){ /* send the same again */
|
||
if (t_sndudata(FD_NCP_OUT, &ud) < 0) {
|
||
if (nw_debug) t_error("t_sndudata !OK");
|
||
}
|
||
XDPRINTF((3,0, "Sequence %d is written twice", (int)ncprequest->sequence));
|
||
return(0);
|
||
}
|
||
req_printed=0;
|
||
|
||
if (nw_debug > 1){
|
||
if (nw_debug < 10
|
||
&& (function==0x48 || function == 0x49)) /* read or write */
|
||
nw_debug=1;
|
||
if (nw_debug < 15
|
||
&& (function==0x48)) /* read */
|
||
nw_debug=1;
|
||
}
|
||
|
||
if (nw_debug > 5) pr_debug_request();
|
||
|
||
if (ncp_type == 0x2222) {
|
||
|
||
switch (function) {
|
||
|
||
/* 0.99.pl18, 25-Sep-99
|
||
* these log/lock functions are not well tested and perhaps not
|
||
* ok .
|
||
*/
|
||
case 0x3 : { /* Log File */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 dir_handle;
|
||
uint8 lock_flag; /* 0 = log, 1 = lock excl */
|
||
/* 3 = lock shared */
|
||
uint8 timeout[2]; /* HI LO */
|
||
uint8 len;
|
||
uint8 path[2];
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
int result = nw_log_file( input->lock_flag,
|
||
GET_BE16(input->timeout),
|
||
input->dir_handle,
|
||
input->len,
|
||
input->path);
|
||
if (result) completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
#if 0
|
||
case 0x4 : { /* Lock File Set */
|
||
|
||
}
|
||
break;
|
||
#endif
|
||
|
||
case 0x5 : /* Release File */
|
||
case 0x7 : { /* Clear File, removes file from logset */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 dir_handle;
|
||
uint8 len;
|
||
uint8 path[2];
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
int result = nw_log_file( (function==0x7)
|
||
? -2 /* unlock and unlog */
|
||
: -1, /* unlock */
|
||
0,
|
||
input->dir_handle,
|
||
input->len,
|
||
input->path);
|
||
if (result) completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
case 0x6 : /* Release File Set */
|
||
case 0x8 : { /* Clear File Set */
|
||
int result = share_handle_lock_sets(
|
||
1, /* File Set */
|
||
(function==0x8)
|
||
? -2 /* Clear */
|
||
: -1, /* Release */
|
||
0);
|
||
|
||
if (result) completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
case 0x9 : { /* Log Logical Record */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 lock_flag; /* 0 = log */
|
||
/* 1 = exclusive lock */
|
||
/* 3 = shared ro lock */
|
||
uint8 timeout[2]; /* HI LO */
|
||
uint8 len; /* synch name len */
|
||
uint8 name[2]; /* synch name */
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
int result = nw_log_logical_record(
|
||
(int) input->lock_flag,
|
||
(int) GET_BE16(input->timeout),
|
||
(int) input->len,
|
||
input->name);
|
||
if (result) completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
case 0xa : { /* Log Logical Record Set */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 lock_flag; /* 0 = log */
|
||
/* 1 = exclusive lock */
|
||
/* 3 = shared ro lock */
|
||
uint8 timeout[2]; /* HI LO */
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
int result = share_handle_lock_sets(
|
||
2, /* Logical Record Set */
|
||
(int) input->lock_flag,
|
||
(int) GET_BE16(input->timeout) );
|
||
if (result) completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
case 0xb : /* Clear Logical Record ?? */
|
||
/* case 0xc :*/ { /* Release Logical Record ?? */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 len; /* synch name len */
|
||
uint8 name[2]; /* synch name */
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
int result = nw_log_logical_record(
|
||
(function == 0xb)
|
||
? -2 /* unlock + unlog */
|
||
: -1, /* unlock */
|
||
0,
|
||
(int) input->len,
|
||
input->name);
|
||
if (result) completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
case 0xe : /* Clear Logical Record Set */
|
||
case 0xd : { /* Release Logical Record Set */
|
||
int result = share_handle_lock_sets(
|
||
2, /* Logical Record Set */
|
||
(function==0xe)
|
||
? -2 /* Clear */
|
||
: -1, /* Release */
|
||
0);
|
||
if (result) completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
case 0x12 : { /* Get Volume Info with Number */
|
||
int volume = (int)*requestdata;
|
||
struct XDATA {
|
||
uint8 sec_per_block[2];
|
||
uint8 total_blocks[2];
|
||
uint8 avail_blocks[2];
|
||
uint8 total_dirs[2];
|
||
uint8 avail_dirs[2];
|
||
uint8 name[16];
|
||
uint8 removable[2];
|
||
} *xdata = (struct XDATA*) responsedata;
|
||
int result;
|
||
memset(xdata, 0, sizeof(struct XDATA));
|
||
if ((result = nw_get_volume_name(volume, xdata->name, sizeof(xdata->name)))>-1){
|
||
struct fs_usage fsp;
|
||
if (!nw_get_fs_usage(xdata->name, &fsp,
|
||
entry8_flags&0x40 )) {
|
||
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) & VOL_OPTION_REMOUNT) {
|
||
U16_TO_BE16(1, xdata->removable);
|
||
} else {
|
||
U16_TO_BE16(0, xdata->removable);
|
||
}
|
||
}
|
||
data_len = sizeof(struct XDATA);
|
||
} else completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
case 0x13 : { /* Get connection ?? */
|
||
/* TODO !!!!!!! */
|
||
*responsedata=(uint8) act_connection;
|
||
data_len = 1;
|
||
}
|
||
break;
|
||
|
||
case 0x14 : { /* GET DATE und TIME */
|
||
struct SERVER_DATE {
|
||
uint8 year;
|
||
uint8 mon;
|
||
uint8 day;
|
||
uint8 std;
|
||
uint8 min;
|
||
uint8 sec;
|
||
uint8 day_of_week;
|
||
} *mydate = (struct SERVER_DATE*) responsedata;
|
||
struct tm *s_tm;
|
||
time_t timer;
|
||
time(&timer);
|
||
s_tm = localtime(&timer);
|
||
mydate->year = (uint8) s_tm->tm_year;
|
||
mydate->mon = (uint8) s_tm->tm_mon+1;
|
||
mydate->day = (uint8) s_tm->tm_mday;
|
||
|
||
mydate->std = (uint8) s_tm->tm_hour;
|
||
mydate->min = (uint8) s_tm->tm_min;
|
||
mydate->sec = (uint8) s_tm->tm_sec;
|
||
mydate->day_of_week = (uint8) s_tm->tm_wday; /* Wochentag */
|
||
data_len = sizeof(struct SERVER_DATE);
|
||
}
|
||
break;
|
||
|
||
case 0x15 :
|
||
return(-1); /* nwbind must do this call */
|
||
|
||
case 0x16 : {
|
||
/* uint8 len = *(requestdata+1); */
|
||
uint8 *p = requestdata +2;
|
||
|
||
switch (*p) {
|
||
|
||
case 0 : {
|
||
/******** SetDirektoryHandle *************/
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 div[3]; /* 0x0, dlen, ufunc */
|
||
uint8 target_dir_handle; /* to change */
|
||
uint8 source_dir_handle;
|
||
uint8 pathlen;
|
||
uint8 path[2];
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
completition =
|
||
(uint8)-nw_set_dir_handle((int)input->target_dir_handle,
|
||
(int)input->source_dir_handle,
|
||
input->path,
|
||
(int)input->pathlen,
|
||
(int)(ncprequest->task));
|
||
}
|
||
break;
|
||
|
||
case 0x1 : {
|
||
/******** GetDirektoryPATH ***************/
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 div[3]; /* 0x0, dlen, ufunc */
|
||
uint8 dir_handle;
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
struct XDATA {
|
||
uint8 len;
|
||
uint8 name[256];
|
||
} *xdata = (struct XDATA*) responsedata;
|
||
int result = nw_get_directory_path((int)input->dir_handle,
|
||
xdata->name, sizeof(xdata->name));
|
||
if (result > -1){
|
||
xdata->len = (uint8) result;
|
||
data_len = result + 1;
|
||
xdata->name[result] = '\0';
|
||
XDPRINTF((5,0, "GetDirektoryPATH=%s", xdata->name));
|
||
} else completition = (uint8)-result;
|
||
}
|
||
break;
|
||
|
||
case 0x2 : { /* Scan Direktory Information */
|
||
/******** Scan Dir Info ****************/
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 div[3]; /* 0x0, dlen, ufunc */
|
||
uint8 dir_handle; /* Verzeichnis Handle */
|
||
uint8 sub_dir_nmbr[2]; /* HI LOW */
|
||
/* firsttime 1 */
|
||
uint8 len; /* kann auch 0 sein */
|
||
uint8 path[2];
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
struct XDATA {
|
||
uint8 sub_dir_name[16];
|
||
uint8 create_date_time[4];
|
||
uint8 owner_id[4]; /* HI LOW */
|
||
uint8 max_right_mask; /* inherited right mask */
|
||
uint8 reserved; /* Reserved by Novell */
|
||
uint8 sub_dir_nmbr[2]; /* HI LOW */
|
||
} *xdata = (struct XDATA*) responsedata;
|
||
int result;
|
||
memcpy(xdata->sub_dir_nmbr, input->sub_dir_nmbr, 2);
|
||
result = nw_scan_dir_info((int)input->dir_handle,
|
||
input->path, (int)input->len,
|
||
xdata->sub_dir_nmbr, xdata->sub_dir_name,
|
||
xdata->create_date_time, xdata->owner_id);
|
||
if (result > -1){
|
||
xdata->max_right_mask = (uint8)result;
|
||
data_len = sizeof(struct XDATA);
|
||
XDPRINTF((5,0,"Scan Dir Info max_right_mask=%d", (int)result));
|
||
} else completition = (uint8)-result;
|
||
}
|
||
break;
|
||
|
||
case 0x3 : { /* Get Direktory Rights */
|
||
/******** Get Eff Dir Rights ****************/
|
||
struct XDATA {
|
||
uint8 eff_right_mask; /* Effektive Right to Dir, old! */
|
||
} *xdata = (struct XDATA*) responsedata;
|
||
int result = nw_get_eff_dir_rights(
|
||
(int)*(p+1),
|
||
p+3,
|
||
(int)*(p+2), 0);
|
||
if (result > -1) {
|
||
xdata->eff_right_mask = (uint8) result;
|
||
data_len = 1;
|
||
XDPRINTF((5,0,"Got eff Dir Rights=%d", (int)result));
|
||
} else completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
case 0x4 : { /* Modify Max Right MAsk */
|
||
/******** MODIFY MAX RIGHT MASK ****************/
|
||
/* NO REPLY !! */
|
||
completition = 0xfb; /* TODO */
|
||
}
|
||
break;
|
||
|
||
case 0x5 : { /* Get Volume Number 0 .. 31 */
|
||
/******** GetVolume Number ***************/
|
||
/* p+1 = namelen */
|
||
/* p+2 = data z.b 'SYS' */
|
||
struct XDATA {
|
||
uint8 volume; /* Nummer */
|
||
} *xdata = (struct XDATA*) responsedata;
|
||
int result = nw_get_volume_number(p+2, (int)*(p+1));
|
||
if (result > -1) {
|
||
xdata->volume = (uint8) result;
|
||
data_len = 1;
|
||
} else completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
case 0x6 : { /* Get Volume Name from 0 .. 31 */
|
||
/******** Get Volume Name ***************/
|
||
struct XDATA {
|
||
uint8 namelen;
|
||
uint8 name[16];
|
||
} *xdata = (struct XDATA*) responsedata;
|
||
int result = nw_get_volume_name((int)*(p+1),
|
||
xdata->name, sizeof(xdata->name));
|
||
if (result > -1) {
|
||
xdata->namelen = (uint8) result;
|
||
data_len = result+1;
|
||
} else completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
case 0xa : { /* create directory */
|
||
/******** Create Dir *********************/
|
||
int dir_handle = (int) *(p+1);
|
||
#if 0
|
||
int rightmask = (int) *(p+2);
|
||
#endif
|
||
int pathlen = (int) *(p+3);
|
||
uint8 *path = p+4;
|
||
int code = nw_mk_rd_dir(dir_handle, path, pathlen, 1);
|
||
if (code) completition = (uint8) -code;
|
||
}
|
||
break;
|
||
|
||
case 0xb : { /* delete dirrctory */
|
||
/******** Delete DIR *********************/
|
||
int dir_handle = (int) *(p+1);
|
||
#if 0
|
||
int reserved = (int) *(p+2); /* Res. by NOVELL */
|
||
#endif
|
||
int pathlen = (int) *(p+3);
|
||
uint8 *path = p+4;
|
||
int code = nw_mk_rd_dir(dir_handle, path, pathlen, 0);
|
||
if (code) completition = (uint8) -code;
|
||
}
|
||
break;
|
||
|
||
case 0xd : { /* Add Trustees to DIR */
|
||
/******** AddTrustesstoDir ***************/
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 div[3]; /* 0x0, dlen, ufunc */
|
||
uint8 dir_handle; /* Verzeichnis Handle */
|
||
uint8 trustee_id[4]; /* Trustee Object ID */
|
||
uint8 trustee_right_mask;
|
||
uint8 pathlen;
|
||
uint8 path[2];
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
int result = nw_add_trustee(
|
||
input->dir_handle,
|
||
input->path, input->pathlen,
|
||
GET_BE32(input->trustee_id),
|
||
(int)input->trustee_right_mask,
|
||
0);
|
||
if (result) completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
case 0xe : { /* remove trustees */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 div[3]; /* 0x0, dlen, ufunc */
|
||
uint8 dir_handle; /* Handle */
|
||
uint8 trustee_id[4]; /* Trustee Object ID */
|
||
uint8 reserved;
|
||
uint8 pathlen;
|
||
uint8 path[2];
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
int result = nw_del_trustee(
|
||
input->dir_handle,
|
||
input->path, input->pathlen,
|
||
GET_BE32(input->trustee_id),
|
||
0); /* normal */
|
||
if (result) completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
case 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;
|
||
}
|
||
break;
|
||
|
||
case 0x12 : /* Allocate Permanent Dir Handle */
|
||
/******** Allocate Permanent DIR Handle **/
|
||
case 0x13 : /* Allocate Temp Dir Handle */
|
||
/******** Allocate Temp DIR Handle **/
|
||
case 0x16 : { /* Allocate Special Temp Dir Handle */
|
||
/******** Allocate spez temp DIR Handle **/
|
||
|
||
struct XDATA {
|
||
uint8 dirhandle; /* new Dir Handle */
|
||
uint8 right_mask; /* 0xff effektive Right MAsk ? */
|
||
} *xdata = (struct XDATA*) responsedata;
|
||
int eff_rights;
|
||
int dirhandle = nw_alloc_dir_handle(
|
||
(int) *(p+1),
|
||
p+4,
|
||
(int)*(p+3),
|
||
(int)*(p+2),
|
||
(*p==0x12) ? 0
|
||
: ((*p==0x13) ? 1 : 2),
|
||
(int)(ncprequest->task),
|
||
&eff_rights);
|
||
if (dirhandle > -1){
|
||
xdata->dirhandle = (uint8) dirhandle;
|
||
xdata->right_mask = eff_rights;
|
||
data_len = sizeof(struct XDATA);
|
||
} else completition = (uint8) -dirhandle;
|
||
|
||
}
|
||
break;
|
||
|
||
case 0x14 : { /* deallocate Dir Handle */
|
||
/******** Free DIR Handle ****************/
|
||
int err_code = nw_free_dir_handle((int)*(p+1),
|
||
(int)(ncprequest->task));
|
||
if (err_code) completition = (uint8) -err_code;
|
||
}
|
||
break;
|
||
|
||
case 0x15 : { /* liefert Volume Information */
|
||
/******** Get Volume Info with Handle ****/
|
||
struct XDATA {
|
||
uint8 sectors[2];
|
||
uint8 total_blocks[2];
|
||
uint8 avail_blocks[2];
|
||
uint8 total_dirs[2]; /* anz dirs */
|
||
uint8 avail_dirs[2]; /* free dirs */
|
||
uint8 name[16]; /* SYS Name */
|
||
uint8 removable[2];
|
||
} *xdata = (struct XDATA*)responsedata;
|
||
int result = nw_get_vol_number((int)*(p+1));
|
||
memset(xdata, 0, sizeof(struct XDATA));
|
||
if (result > -1) {
|
||
int volume = result;
|
||
result = nw_get_volume_name(volume,
|
||
xdata->name, sizeof(xdata->name) );
|
||
if (result > -1) {
|
||
struct fs_usage fsp;
|
||
if (!nw_get_fs_usage(xdata->name, &fsp,
|
||
entry8_flags&0x40 )) {
|
||
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) & VOL_OPTION_REMOUNT) {
|
||
U16_TO_BE16(1, xdata->removable);
|
||
} else {
|
||
U16_TO_BE16(0, xdata->removable);
|
||
}
|
||
}
|
||
data_len = sizeof(struct XDATA);
|
||
XDPRINTF((5,0,"GIVE VOLUME INFO from :%s:", xdata->name));
|
||
result = 0;
|
||
}
|
||
}
|
||
completition = (uint8)-result;
|
||
}
|
||
break;
|
||
|
||
#if 0
|
||
case 0x18 : { /* restore directory handle */
|
||
?????????
|
||
}
|
||
break;
|
||
#endif
|
||
case 0x19 : {
|
||
/* Set Directory Information
|
||
* Modifies basic directory information as creation date and
|
||
* directory rights mask. DOS namespace.
|
||
*/
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 div[3]; /* 0x0, dlen, ufunc */
|
||
uint8 dir_handle;
|
||
uint8 creation_date[2];
|
||
uint8 creation_time[2];
|
||
uint8 owner_id[4];
|
||
uint8 new_max_rights;
|
||
uint8 pathlen;
|
||
uint8 path[2];
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
int result = nw_set_dir_info(
|
||
input->dir_handle,
|
||
input->path, input->pathlen,
|
||
GET_BE32(input->owner_id),
|
||
(int)input->new_max_rights,
|
||
input->creation_date,
|
||
input->creation_time);
|
||
if (result<0) completition = (uint8) -result;
|
||
/* No REPLY */
|
||
}
|
||
break;
|
||
|
||
case 0x1a : { /* Get Pathname of A Volume Dir Pair */
|
||
#if 0
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 div[3]; /* 0x0, dlen, ufunc */
|
||
uint8 volume;
|
||
uint8 dir_entry[2];
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
struct XDATA {
|
||
uint8 pathlen;
|
||
uint8 pathname;
|
||
} *xdata = (struct XDATA*)responsedata;
|
||
#endif
|
||
completition = 0xfb; /* !!!!! TODO !!!! */
|
||
}
|
||
break;
|
||
|
||
case 0x1e : { /* SCAN a Directory, e.g. used by ndir.exe */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 div[3]; /* 0x0, dlen, ufunc */
|
||
uint8 dir_handle; /* Verzeichnis Handle */
|
||
uint8 attrib; /* Search Attrib z.B. 0x6 */
|
||
uint8 searchsequence[4]; /* 32 bit */
|
||
uint8 len;
|
||
uint8 data[2];
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
int result = nw_scan_a_directory(
|
||
responsedata,
|
||
input->dir_handle,
|
||
input->data,
|
||
input->len,
|
||
input->attrib,
|
||
GET_BE32(input->searchsequence));
|
||
|
||
if (result > -1) data_len = result;
|
||
else completition = (uint8) (-result);
|
||
}
|
||
break;
|
||
|
||
case 0x1f : { /* SCAN a root dir ???? */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 div[3]; /* 0x0, dlen, ufunc */
|
||
uint8 dir_handle; /* Verzeichnis Handle */
|
||
uint8 dont_know1; /* ???? 0xc0 */
|
||
uint8 dont_know2; /* ???? 0xfa */
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
int result = nw_scan_a_root_dir(
|
||
responsedata,
|
||
input->dir_handle);
|
||
if (result > -1) data_len = result;
|
||
else completition = (uint8) (-result);
|
||
}
|
||
break;
|
||
|
||
case 0x20 : { /* scan volume user disk restrictions */
|
||
uint8 volnr = *(p+1);
|
||
/* uint32 sequence = GET_BE32(p+2); */
|
||
struct XDATA {
|
||
uint8 entries; /* 0x0 */
|
||
/*--- per entry (max.entries = 12) ----*/
|
||
uint8 id[4];
|
||
uint8 restriction[4];
|
||
} *xdata = (struct XDATA*) responsedata;
|
||
int result = nw_get_volume_name(volnr, NULL, 0);
|
||
if (result > -1) {
|
||
xdata->entries = 0x0;
|
||
data_len = (8 * xdata->entries) + 1;
|
||
} else completition = (uint8) (-result);
|
||
}
|
||
break;
|
||
|
||
case 0x21 : { /* change Vol restrictions for Obj */
|
||
XDPRINTF((5, 0, "Change vol restrictions"));
|
||
}
|
||
return(-2); /* nwbind must do prehandling */
|
||
|
||
case 0x22 : { /* remove Vol restrictions for Obj */
|
||
XDPRINTF((5, 0, "Remove vol restrictions"));
|
||
}
|
||
return(-2); /* nwbind must do prehandling */
|
||
|
||
case 0x25 : { /* Set Entry, Set Directory File Information
|
||
* sets or changes the file or directory information to the
|
||
* values entered in 'Change Bits'.
|
||
* NO REPLY
|
||
* used by ncopy.exe, flag.exe
|
||
*/
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 div[3]; /* 0x0, dlen, ufunc */
|
||
uint8 dir_handle;
|
||
uint8 attrib;
|
||
NW_SET_DIR_INFO f;
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
int result = nw_set_a_directory_entry(
|
||
input->dir_handle,
|
||
input->f.u.f.name,
|
||
input->f.u.f.namlen,
|
||
input->attrib,
|
||
GET_BE32(input->f.searchsequence),
|
||
&(input->f));
|
||
if (result<0)
|
||
do_druck++;
|
||
/* TODO !!!!!!! */
|
||
}
|
||
break;
|
||
|
||
case 0x26 : { /* Scan file or Dir for ext trustees */
|
||
int sequence = (int)*(p+2); /* trustee sequence */
|
||
struct XDATA {
|
||
uint8 entries;
|
||
uint8 ids[80]; /* 20 id's */
|
||
uint8 trustees[40]; /* 20 trustees's */
|
||
} *xdata = (struct XDATA*) responsedata;
|
||
uint32 ids[20];
|
||
int trustees[20];
|
||
int result = nw_scan_for_trustee(
|
||
(int)*(p+1), /* dir handle */
|
||
sequence,
|
||
p+4, /* path */
|
||
(int)*(p+3), /* pathlen */
|
||
20, /* max entries */
|
||
ids,
|
||
trustees,
|
||
1); /* extended */
|
||
if (result > -1) {
|
||
int i = -1;
|
||
uint8 *idsp = xdata->ids;
|
||
uint8 *trp = xdata->trustees;
|
||
memset(xdata, 0, sizeof(*xdata));
|
||
xdata->entries = result;
|
||
while(++i < result) {
|
||
U32_TO_BE32(ids[i], idsp);
|
||
idsp+=4;
|
||
U16_TO_16(trustees[i], trp); /* LO - HI */
|
||
trp+=2;
|
||
}
|
||
data_len = sizeof(struct XDATA);
|
||
} else completition = (uint8) (-result);
|
||
}
|
||
break;
|
||
|
||
case 0x27 : { /* Add Ext Trustees to DIR or File */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 div[3]; /* 0x0, dlen, ufunc */
|
||
uint8 dir_handle; /* Handle */
|
||
uint8 trustee_id[4]; /* Trustee Object ID */
|
||
uint8 trustee_rights[2]; /* lo - hi */
|
||
uint8 pathlen;
|
||
uint8 path[2];
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
int result = nw_add_trustee(
|
||
input->dir_handle,
|
||
input->path, input->pathlen,
|
||
GET_BE32(input->trustee_id),
|
||
GET_16(input->trustee_rights),
|
||
1); /* extended */
|
||
if (result) completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
case 0x28 : { /* Scan File Physical ??? */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 div[3]; /* 0x0, dlen, ufunc */
|
||
uint8 dir_handle; /* directory handle */
|
||
uint8 attrib; /* Search Attrib ?? 0x2f */
|
||
uint8 searchsequence[4]; /* 32 bit */
|
||
uint8 len;
|
||
uint8 data[2];
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
/* we try, whether this is ok ????? */
|
||
int result = nw_scan_a_directory(
|
||
responsedata,
|
||
input->dir_handle,
|
||
input->data,
|
||
input->len,
|
||
input->attrib,
|
||
GET_BE32(input->searchsequence));
|
||
if (result > -1) data_len = result;
|
||
else completition = (uint8) (-result);
|
||
}
|
||
break;
|
||
|
||
case 0x29 : { /* read volume restrictions for an object */
|
||
#if QUOTA_SUPPORT
|
||
XDPRINTF((5, 0, "Read vol restrictions"));
|
||
return(-2); /* nwbind must do prehandling */
|
||
#else
|
||
#if DO_DEBUG
|
||
uint8 volnr = *(p+1);
|
||
uint32 id = GET_BE32(p+2);
|
||
#endif
|
||
struct XDATA {
|
||
uint8 restriction[4];
|
||
uint8 inuse[4];
|
||
} *xdata = (struct XDATA*) responsedata;
|
||
XDPRINTF((5,0, "Get vol restriction (DUMMY) vol=%d, id=0x%lx",
|
||
(int)volnr, id));
|
||
U32_TO_32(0x40000000, xdata->restriction);
|
||
U32_TO_32(0x0, xdata->inuse);
|
||
data_len=sizeof(struct XDATA);
|
||
#endif
|
||
}
|
||
break;
|
||
|
||
case 0x2a : { /* Get Eff. Rights of DIR's and Files */
|
||
struct XDATA {
|
||
uint8 eff_rights[2]; /* LO-HI */
|
||
} *xdata = (struct XDATA*) responsedata;
|
||
int result = nw_get_eff_dir_rights(
|
||
(int)*(p+1),
|
||
p+3,
|
||
(int)*(p+2), 1);
|
||
if (result > -1){
|
||
U16_TO_16(result, xdata->eff_rights);
|
||
data_len = sizeof(struct XDATA);
|
||
} else completition = (uint8) (-result);
|
||
}
|
||
break;
|
||
|
||
case 0x2b : { /* remove ext trustees */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 div[3]; /* 0x0, dlen, ufunc */
|
||
uint8 dir_handle; /* Handle */
|
||
uint8 trustee_id[4]; /* Trustee Object ID */
|
||
uint8 reserved;
|
||
uint8 pathlen;
|
||
uint8 path[2];
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
int result = nw_del_trustee(
|
||
input->dir_handle,
|
||
input->path, input->pathlen,
|
||
GET_BE32(input->trustee_id),
|
||
1); /* extended */
|
||
if (result) completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
case 0x2c : { /* Get Volume and Purge Information */
|
||
/* new Call since V3.11 */
|
||
/* ncpfs need this call */
|
||
int volume = (int) *(p+1);
|
||
struct XDATA {
|
||
uint8 total_blocks[4]; /* LOW-HI !! */
|
||
uint8 avail_blocks[4];
|
||
uint8 purgeable_blocks[4];
|
||
uint8 not_purgeable_blocks[4];
|
||
uint8 total_dirs[4];
|
||
uint8 avail_dirs[4];
|
||
uint8 reserved_by_novell[4];
|
||
uint8 sec_per_block;
|
||
uint8 namlen;
|
||
uint8 name[1];
|
||
} *xdata = (struct XDATA*) responsedata;
|
||
uint8 name[100];
|
||
int result = nw_get_volume_name(volume, name, sizeof(name));
|
||
if (result > -1){
|
||
struct fs_usage fsp;
|
||
memset(xdata, 0, sizeof(struct XDATA));
|
||
if (!nw_get_fs_usage(name, &fsp, 0)) {
|
||
xdata->sec_per_block = 8; /* hard coded */
|
||
U32_TO_32(fsp.fsu_blocks/8, xdata->total_blocks);
|
||
U32_TO_32(fsp.fsu_bavail/8, xdata->avail_blocks);
|
||
U32_TO_32(fsp.fsu_files, xdata->total_dirs);
|
||
U32_TO_32(fsp.fsu_ffree, xdata->avail_dirs);
|
||
}
|
||
xdata->namlen = strlen((char*)name);
|
||
strmaxcpy(xdata->name, name, xdata->namlen);
|
||
data_len = xdata->namlen + 30;
|
||
} else completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
case 0x2d : { /* Get Direktory Information */
|
||
int dir_handle = (int) *(p+1);
|
||
struct XDATA {
|
||
uint8 total_blocks[4];
|
||
uint8 avail_blocks[4];
|
||
uint8 total_dirs[4];
|
||
uint8 avail_dirs[4];
|
||
uint8 reserved_by_novell[4];
|
||
uint8 sec_per_block;
|
||
uint8 namlen;
|
||
uint8 name[1]; /* Volume Name */
|
||
} *xdata = (struct XDATA*) responsedata;
|
||
int result = nw_get_vol_number(dir_handle);
|
||
uint8 name[100];
|
||
if (result > -1)
|
||
result = nw_get_volume_name(result, name, sizeof(name));
|
||
if (result > -1) {
|
||
struct fs_usage fsp;
|
||
memset(xdata, 0, sizeof(struct XDATA));
|
||
if (!nw_get_fs_usage(name, &fsp, 0)) {
|
||
xdata->sec_per_block = 8; /* hard coded */
|
||
U32_TO_32(fsp.fsu_blocks/8, xdata->total_blocks);
|
||
U32_TO_32(fsp.fsu_bavail/8, xdata->avail_blocks);
|
||
U32_TO_32(fsp.fsu_files, xdata->total_dirs);
|
||
U32_TO_32(fsp.fsu_ffree, xdata->avail_dirs);
|
||
}
|
||
xdata->namlen = strlen((char*)name);
|
||
strmaxcpy(xdata->name, name, xdata->namlen);
|
||
data_len = xdata->namlen + 22;
|
||
} else completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
case 0x2e : { /* rename file */
|
||
completition = 0xfb; /* TODO: !!! */
|
||
}
|
||
break;
|
||
|
||
#if WITH_NAME_SPACE_CALLS
|
||
|
||
case 0x2f : { /* Fill namespace buffer */
|
||
/* ncopy use this call */
|
||
int volume = (int) *(p+1);
|
||
/* (p+2) == 0xe4 or 0xe2 sometimes ???? */
|
||
int result=fill_namespace_buffer(
|
||
volume, responsedata);
|
||
if (result > -1) {
|
||
data_len = result;
|
||
} else completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
case 0x30 : { /* Get Name Space Directory Entry */
|
||
int volume = (int) *(p+1);
|
||
uint32 basehandle = GET_32(p+2);
|
||
int namespace = (int) *(p+6);
|
||
int result=get_namespace_dir_entry(
|
||
volume, basehandle, namespace,
|
||
responsedata);
|
||
if (result > -1) {
|
||
data_len = result;
|
||
} else completition = (uint8) -result;
|
||
}
|
||
break;
|
||
#endif
|
||
|
||
case 0x33 : { /* Get Extended Volume Information */
|
||
#if 0
|
||
int volume = (int) *(p+1);
|
||
/* next 3 byte are low bytes of volume */
|
||
#endif
|
||
completition = 0xfb; /* not known yet */
|
||
}
|
||
break;
|
||
|
||
|
||
default:
|
||
completition = 0xfb; /* unkwown request */
|
||
break;
|
||
} /* switch *p */
|
||
}
|
||
break;
|
||
|
||
|
||
case 0x17 : { /* FILE SERVER ENVIRONMENT */
|
||
/* uint8 len = *(requestdata+1); */
|
||
uint8 ufunc = *(requestdata+2);
|
||
uint8 *rdata = requestdata+3;
|
||
|
||
switch (ufunc) {
|
||
#if FUNC_17_02_IS_DEBUG
|
||
case 0x02 : {
|
||
/* I hope this call isn't used */
|
||
/* now missused as a debug switch :) */
|
||
struct XDATA {
|
||
uint8 nw_debug; /* old level */
|
||
} *xdata = (struct XDATA*) responsedata;
|
||
if (*rdata == NWCONN) {
|
||
xdata->nw_debug = (uint8)org_nw_debug;
|
||
nw_debug = org_nw_debug = (int) *(rdata+1);
|
||
data_len = 1;
|
||
} else return(-1);
|
||
}
|
||
break;
|
||
#endif
|
||
|
||
case 0x14: /* Login Objekt, unencrypted passwords */
|
||
case 0x18: /* crypt_keyed LOGIN */
|
||
return(-2); /* nwbind must do prehandling */
|
||
|
||
|
||
case 0x0f: { /* Scan File Information */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 div[3]; /* 0, len + ufunc */
|
||
uint8 sequence[2]; /* z.B. 0xff, 0xff */
|
||
uint8 dir_handle;
|
||
uint8 search_attrib; /* 0: NONE */
|
||
/* 02: HIDDEN */
|
||
/* 04: SYSTEM */
|
||
/* 06: BOTH */
|
||
/* 0x10: DIR */
|
||
uint8 len;
|
||
uint8 data[2]; /* Name */
|
||
} *input = (struct INPUT *)ncprequest;
|
||
|
||
struct XDATA {
|
||
uint8 sequence[2]; /* next sequence */
|
||
/* NW_FILE_INFO f; */
|
||
uint8 f[sizeof(NW_FILE_INFO)];
|
||
uint8 owner_id[4];
|
||
uint8 archive_date[2];
|
||
uint8 archive_time[2];
|
||
uint8 reserved[56];
|
||
} *xdata = (struct XDATA*)responsedata;
|
||
int len = input->len;
|
||
int searchsequence;
|
||
NW_FILE_INFO f;
|
||
uint32 owner;
|
||
|
||
memset(xdata, 0, sizeof(struct XDATA));
|
||
searchsequence = nw_search( (uint8*) &f,
|
||
&owner,
|
||
(int)input->dir_handle,
|
||
(int) GET_BE16(input->sequence),
|
||
(int) input->search_attrib & ~0x10,
|
||
/* this routine is only for scanning files ^^^^^^ */
|
||
input->data, len);
|
||
if (searchsequence > -1) {
|
||
memcpy(xdata->f, &f, sizeof(NW_FILE_INFO));
|
||
U16_TO_BE16((uint16) searchsequence, xdata->sequence);
|
||
U32_TO_BE32(owner, xdata->owner_id);
|
||
data_len = sizeof(struct XDATA);
|
||
} else completition = (uint8) (- searchsequence);
|
||
}
|
||
break;
|
||
|
||
case 0x10: { /* Set File Information */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 div[3]; /* 0, len + ufunc */
|
||
uint8 f[sizeof(NW_FILE_INFO) - 14]; /* no name */
|
||
uint8 owner_id[4];
|
||
uint8 archive_date[2];
|
||
uint8 archive_time[2];
|
||
uint8 reserved[56];
|
||
uint8 dir_handle;
|
||
uint8 search_attrib; /* 0: NONE */
|
||
/* 02: HIDDEN */
|
||
/* 04: SYSTEM */
|
||
/* 06: BOTH */
|
||
/* 0x10: DIR */
|
||
uint8 len;
|
||
uint8 data[2]; /* Name */
|
||
} *input = (struct INPUT *)ncprequest;
|
||
NW_FILE_INFO f;
|
||
int result;
|
||
memcpy(((uint8*)&f)+14, input->f, sizeof(NW_FILE_INFO)-14);
|
||
result = nw_set_file_information((int)input->dir_handle,
|
||
input->data,
|
||
(int)input->len,
|
||
(int)input->search_attrib, &f);
|
||
/* no reply packet */
|
||
if (result <0) completition = (uint8)-result;
|
||
}
|
||
break;
|
||
|
||
case 0x47 : { /* SCAN BINDERY OBJECT TRUSTEE PATH */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 div[3]; /* 0x0, dlen, ufunc */
|
||
uint8 volume;
|
||
uint8 sequence[2]; /* trustee searchsequence */
|
||
uint8 id[4]; /* Trustee Object ID */
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
struct XDATA {
|
||
uint8 nextsequence[2];
|
||
uint8 id[4];
|
||
uint8 access_mask;
|
||
uint8 pathlen;
|
||
uint8 path[1];
|
||
} *xdata = (struct XDATA*) responsedata;
|
||
int sequence=GET_BE16(input->sequence);
|
||
int access_mask=0;
|
||
uint32 id=GET_BE32(input->id);
|
||
int result=nw_scan_user_trustee(
|
||
input->volume, &sequence, id, &access_mask, xdata->path);
|
||
if (result > 0) {
|
||
U16_TO_BE16(sequence, xdata->nextsequence);
|
||
memcpy(xdata->id, input->id, 4);
|
||
xdata->access_mask=(uint8)access_mask;
|
||
xdata->pathlen=result;
|
||
data_len = 8+result;
|
||
} else if (!result) {
|
||
memset(xdata, 0, 8);
|
||
data_len = 8;
|
||
} else
|
||
completition = (uint8)(-result);
|
||
}
|
||
break;
|
||
|
||
case 0x64: { /* create queue */
|
||
#if 0
|
||
int q_typ = GET_BE16(rdata);
|
||
#endif
|
||
int q_name_len = *(rdata+2);
|
||
#if 0
|
||
uint8 *q_name = rdata+3;
|
||
#endif
|
||
uint8 *dirhandle = rdata+3+q_name_len;
|
||
int pathlen = *(rdata+3+q_name_len+1);
|
||
uint8 *path = rdata+3+q_name_len+2;
|
||
uint8 new_path[257];
|
||
int result = conn_get_full_path(*dirhandle,
|
||
path, pathlen, new_path,
|
||
sizeof(new_path));
|
||
if (result > -1) {
|
||
int diffsize = result - pathlen;
|
||
*dirhandle = 0;
|
||
memcpy(path, new_path, result);
|
||
if (diffsize)
|
||
requestlen+=diffsize; /* !!!!!! */
|
||
return(-1); /* nwbind must do the rest */
|
||
} else
|
||
completition = (uint8)(-result);
|
||
}
|
||
break;
|
||
|
||
case 0x68: /* create queue job and file old */
|
||
case 0x79: /* create queue job and file */
|
||
return(-2); /* nwbind must do prehandling */
|
||
|
||
case 0x6C: /* Get Queue Job Entry old */
|
||
case 0x7A: { /* Read Queue Job Entry */
|
||
uint32 q_id = GET_BE32(rdata);
|
||
int job_id = GET_BE16(rdata+4);
|
||
uint32 fhandle = get_queue_job_fhandle(q_id, job_id);
|
||
U32_TO_BE32(fhandle, rdata+8);
|
||
requestlen+=6; /* !!!!!! */
|
||
}
|
||
return(-1); /* nwbind must do the rest */
|
||
|
||
case 0x69: /* close file and start queue old ?? */
|
||
case 0x7f: { /* close file and start queue */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 packetlen[2]; /* lo - hi */
|
||
uint8 func; /* 0x7f or 0x69 */
|
||
uint8 queue_id[4]; /* Queue ID */
|
||
uint8 job_id[4]; /* result from creat queue */
|
||
/* if 0x69 then only first 2 byte ! */
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
uint32 q_id = GET_BE32(input->queue_id);
|
||
int job_id = (ufunc==0x69) ? GET_BE16(input->job_id)
|
||
: GET_BE16(input->job_id);
|
||
int result = close_queue_job(q_id, job_id);
|
||
if (result < 0) {
|
||
completition = (uint8)-result;
|
||
} else {
|
||
return(-2); /* nwbind must do next */
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 0x71 : /* service queue job (old) */
|
||
case 0x7c : /* service queue job */
|
||
return(-2); /* nwbind must do prehandling */
|
||
|
||
case 0x72 : /* finish queue job (old) */
|
||
case 0x73 : /* abort queue job (old) */
|
||
case 0x83 : /* finish queue job */
|
||
case 0x84 : { /* abort queue job */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 packetlen[2]; /* low high */
|
||
uint8 func; /* 0x7f or 0x69 */
|
||
uint8 queue_id[4]; /* Queue ID */
|
||
uint8 job_id[4]; /* result from creat queue */
|
||
/* if 0x69 then only first 2 byte ! */
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
uint32 q_id = GET_BE32(input->queue_id);
|
||
int job_id = GET_BE16(input->job_id);
|
||
int result = finish_abort_queue_job(q_id, job_id);
|
||
if (result <0)
|
||
completition=(uint8) -result;
|
||
else
|
||
return(-1); /* nwbind must do the rest */
|
||
}
|
||
break;
|
||
|
||
case 0xf3: { /* Map Direktory Number TO PATH */
|
||
XDPRINTF((2,0, "TODO: Map Directory Number TO PATH"));
|
||
completition = 0xff;
|
||
}
|
||
break;
|
||
|
||
case 0xf4: { /* Map PATH TO Dir Entry */
|
||
XDPRINTF((2,0, "TODO: Map PATH TO Dir Entry"));
|
||
completition = 0xff;
|
||
}
|
||
break;
|
||
|
||
default : return(-1);
|
||
break;
|
||
} /* switch (ufunc) */
|
||
} /* case 0x17 */
|
||
break;
|
||
|
||
case 0x18 : /* End of Job */
|
||
if (!(entry8_flags&0x200)) /* pcz: 14-Apr-00 */
|
||
free_connection_task_jobs(ncprequest->task);
|
||
nw_free_handles(ncprequest->task);
|
||
return(-1); /* nwbind must do a little rest */
|
||
break;
|
||
|
||
case 0x19 : /* logout, some of this call is handled in ncpserv. */
|
||
free_queue_jobs();
|
||
nw_free_handles(-1);
|
||
set_nw_user(-1, -1,
|
||
0,
|
||
0, NULL,
|
||
-1, NULL,
|
||
0, NULL);
|
||
return(-1); /* nwbind must do a little rest */
|
||
break;
|
||
|
||
case 0x1a : /* Log Physical Record */
|
||
case 0x1e : /* Clear Physical Record */
|
||
{
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 lock_flag; /* 0=log, 1=excl */
|
||
/* 3=shared */
|
||
uint8 ext_fhandle[2]; /* all zero */
|
||
uint8 fhandle[4]; /* Filehandle */
|
||
uint8 offset[4];
|
||
uint8 size[4];
|
||
uint8 timeout[2];
|
||
} *input = (struct INPUT *)ncprequest;
|
||
int fhandle = GET_32 (input->fhandle);
|
||
uint32 offset= GET_BE32(input->offset);
|
||
uint32 size = GET_BE32(input->size);
|
||
uint16 timeout = GET_BE16(input->timeout);
|
||
if (function == 0x1a) /* lockfile */
|
||
completition = (uint8)(-nw_log_physical_record(
|
||
fhandle,
|
||
offset,
|
||
size,
|
||
timeout,
|
||
(int)input->lock_flag));
|
||
else
|
||
completition = (uint8)(-nw_log_physical_record(
|
||
fhandle,
|
||
offset,
|
||
size,
|
||
timeout,
|
||
-2 /* unlock + unlog */
|
||
));
|
||
}
|
||
break;
|
||
|
||
case 0x1f : /* Clear Physical Record Set, DUMMY */
|
||
XDPRINTF((1,0,"Clear Physical Record Set called, still DUMMY"));
|
||
break;
|
||
|
||
case 0x20 : /* Semaphore */
|
||
return(-1); /* handled by nwbind */
|
||
|
||
case 0x21 : { /* Negotiate Buffer Size, Packetsize */
|
||
uint8 *getsize=responsedata;
|
||
int buffer_size = (int) (GET_BE16((uint8*)requestdata));
|
||
/* Der Novell-Client der PAM's Net/E-Ethernetkarte
|
||
f<>r Atari ST/TT meldet ein Packetsize von 0 wenn
|
||
nwserv NACH dem Novell Client NET_S1.PRG
|
||
gestartet wird. Da 0 in jedem Falle ein unsinniger
|
||
Wert ist, wird rw_buffer_size nicht verwendet.
|
||
Hayo Schmidt <100305.1424@compuserve.com>, 7-Dec-97
|
||
*/
|
||
if (buffer_size >= 512) {
|
||
rw_buffer_size = min(LOC_RW_BUFFERSIZE, buffer_size);
|
||
XDPRINTF((3,0, "Negotiate Buffer size = 0x%04x,(%d)",
|
||
(int) rw_buffer_size, (int) rw_buffer_size));
|
||
} else {
|
||
XDPRINTF((1,0, "Invalid Packetsize = %d, "
|
||
"Negotiate Buffer Size is set to %d",
|
||
buffer_size, rw_buffer_size));
|
||
}
|
||
U16_TO_BE16(rw_buffer_size, getsize);
|
||
data_len = 2;
|
||
}
|
||
break;
|
||
|
||
case 0x22 : { /* div TTS Calls */
|
||
int ufunc = (int) *requestdata;
|
||
if (!ufunc) completition=0; /* TTS not availible */
|
||
else completition=0xfb; /* request not known */
|
||
} break;
|
||
|
||
case 0x23 : { /* div AFP Calls */
|
||
#if 0
|
||
int ufunc = (int) *requestdata;
|
||
#endif
|
||
completition=0xbf; /* we say invalid namespace here */
|
||
} break;
|
||
|
||
case 0x3b : /* commit file to disk */
|
||
case 0x3d : /* commit file */
|
||
{
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 reserve;
|
||
uint8 ext_fhandle[2]; /* all zero */
|
||
uint8 fhandle[4]; /* filehandle */
|
||
} *input = (struct INPUT *)ncprequest;
|
||
uint32 fhandle = GET_32(input->fhandle);
|
||
int result=nw_commit_file(fhandle);
|
||
if (result<0)
|
||
completition=(uint8)-result;
|
||
}
|
||
break;
|
||
|
||
case 0x3e : { /* FILE SEARCH INIT */
|
||
/* returns dhandle for searchings */
|
||
int dir_handle = (int)*requestdata;
|
||
int len = (int)*(requestdata+1); /* pathlen */
|
||
uint8 *p = requestdata+2; /* path */
|
||
struct XDATA {
|
||
uint8 volume; /* Volume */
|
||
uint8 dir_id[2]; /* Direktory ID */
|
||
uint8 searchsequence[2];
|
||
uint8 dir_rights; /* Rights */
|
||
} *xdata= (struct XDATA*) responsedata;
|
||
int volume;
|
||
int searchsequence;
|
||
int dir_id;
|
||
int rights = nw_open_dir_handle(dir_handle, p, len,
|
||
&volume, &dir_id, &searchsequence);
|
||
if (rights >-1) {
|
||
xdata->volume = (uint8)volume;
|
||
U16_TO_BE16((uint16)dir_id, xdata->dir_id);
|
||
U16_TO_BE16((uint16)searchsequence, xdata->searchsequence);
|
||
xdata->dir_rights = (uint8)rights;
|
||
data_len = sizeof(struct XDATA);
|
||
} else completition = (uint8) -rights;
|
||
} break;
|
||
|
||
case 0x3f : { /* file search continue */
|
||
/* Dir_id is from file search init */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 volume; /* Volume ID */
|
||
uint8 dir_id[2]; /* from File Search Init */
|
||
uint8 searchsequence[2]; /* sequence FFFF = first entry */
|
||
uint8 search_attrib; /* Attribute */
|
||
/* 0 none,
|
||
2 HIDDEN,
|
||
* 4 System ,
|
||
6 Both,
|
||
* 0x10 Dir
|
||
*/
|
||
uint8 len; /* fnname len */
|
||
uint8 data[2]; /* fnname with wildcards */
|
||
} *input = (struct INPUT *) ncprequest;
|
||
int len=input->len ; /* FN Length */
|
||
|
||
struct XDATA {
|
||
uint8 searchsequence[2]; /* same as request sequence */
|
||
uint8 dir_id[2]; /* Direktory ID */
|
||
/* is correct !! */
|
||
union {
|
||
NW_DIR_INFO d;
|
||
NW_FILE_INFO f;
|
||
} u;
|
||
} *xdata = (struct XDATA*)responsedata;
|
||
|
||
int searchsequence = nw_dir_search(
|
||
(uint8*) &(xdata->u),
|
||
(int) GET_BE16(input->dir_id),
|
||
(int) GET_BE16(input->searchsequence),
|
||
(int) input->search_attrib,
|
||
input->data, len);
|
||
if (searchsequence > -1) {
|
||
U16_TO_BE16((uint16) searchsequence, xdata->searchsequence);
|
||
memcpy(xdata->dir_id, input->dir_id, 2);
|
||
data_len = sizeof(struct XDATA);
|
||
} else completition = (uint8) (- searchsequence);
|
||
}
|
||
break;
|
||
|
||
case 0x40 : /* Search for a File */
|
||
{
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 sequence[2]; /* z.B. 0xff, 0xff */
|
||
uint8 dir_handle; /* z.B 0x1 */
|
||
uint8 search_attrib; /* z.B. 0x6 */
|
||
uint8 len;
|
||
uint8 data[2]; /* Name */
|
||
} *input = (struct INPUT *)ncprequest;
|
||
struct XDATA {
|
||
uint8 sequence[2]; /* answer sequence */
|
||
uint8 reserved[2]; /* z.B 0x0 0x0 */
|
||
union {
|
||
NW_DIR_INFO d;
|
||
NW_FILE_INFO f;
|
||
} u;
|
||
} *xdata = (struct XDATA*)responsedata;
|
||
int len = input->len;
|
||
uint8 my_sequence[2];
|
||
int searchsequence;
|
||
uint32 owner;
|
||
memcpy(my_sequence, input->sequence, 2);
|
||
searchsequence = nw_search( (uint8*) &(xdata->u),
|
||
&owner,
|
||
(int)input->dir_handle,
|
||
(int) GET_BE16(my_sequence),
|
||
(int) input->search_attrib,
|
||
input->data, len);
|
||
if (searchsequence > -1) {
|
||
U16_TO_BE16((uint16) searchsequence, xdata->sequence);
|
||
data_len = sizeof(struct XDATA);
|
||
} else completition = (uint8) (- searchsequence);
|
||
}
|
||
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 XDATA {
|
||
uint8 ext_fhandle[2]; /* all zero */
|
||
uint8 fhandle[4]; /* File Handle */
|
||
uint8 reserved[2]; /* reserved by novell */
|
||
NW_FILE_INFO fileinfo;
|
||
} *xdata= (struct XDATA*)responsedata;
|
||
int fhandle=nw_creat_open_file((int)input->dirhandle,
|
||
input->data, input->len,
|
||
&(xdata->fileinfo),
|
||
(int)input->attrib,
|
||
0x1, /* read access */
|
||
0,
|
||
(int)(ncprequest->task));
|
||
|
||
if (fhandle > -1){
|
||
U32_TO_32(fhandle, xdata->fhandle);
|
||
xdata->ext_fhandle[0]=0;
|
||
xdata->ext_fhandle[1]=0;
|
||
xdata->reserved[0]=0;
|
||
xdata->reserved[1]=0;
|
||
data_len = sizeof(struct XDATA);
|
||
} else completition = (uint8) (-fhandle);
|
||
}
|
||
break;
|
||
|
||
case 0x42 : /* close file */
|
||
{
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 reserve;
|
||
uint8 ext_fhandle[2]; /* all zero */
|
||
uint8 fhandle[4]; /* filehandle */
|
||
} *input = (struct INPUT *)ncprequest;
|
||
uint32 fhandle = GET_32(input->fhandle);
|
||
completition = (uint8)(-nw_close_file(fhandle,
|
||
0, (int)(ncprequest->task)));
|
||
|
||
#if TEST_FNAME
|
||
if (!completition && fhandle == test_handle) {
|
||
do_druck++;
|
||
test_handle = -1;
|
||
}
|
||
#endif
|
||
}
|
||
break;
|
||
|
||
case 0x43 : /* creat file, overwrite if exist */
|
||
case 0x4D : /* create new file */
|
||
{
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 dirhandle;
|
||
uint8 attribute; /* creat Attribute */
|
||
uint8 len;
|
||
uint8 data[1]; /* Name */
|
||
} *input = (struct INPUT *)ncprequest;
|
||
struct XDATA {
|
||
uint8 ext_fhandle[2];
|
||
uint8 fhandle[4]; /* Filehandle */
|
||
uint8 reserved[2]; /* reserved by NOVELL */
|
||
NW_FILE_INFO fileinfo;
|
||
} *xdata= (struct XDATA*)responsedata;
|
||
int fhandle=nw_creat_open_file(
|
||
(int)input->dirhandle,
|
||
input->data,
|
||
(int)input->len,
|
||
&(xdata->fileinfo),
|
||
(int)input->attribute,
|
||
/* 0, 0x2, mst: 26-Sep-99 */
|
||
0x13, /* pcz: 14-Nov-99 */
|
||
(function==0x43) ? 1 : 2,
|
||
(int)(ncprequest->task));
|
||
if (fhandle > -1){
|
||
data_len = sizeof(struct XDATA);
|
||
U32_TO_32 (fhandle, xdata->fhandle);
|
||
xdata->ext_fhandle[0]=0;
|
||
xdata->ext_fhandle[1]=0;
|
||
xdata->reserved[0]=0;
|
||
xdata->reserved[1]=0;
|
||
|
||
#ifdef TEST_FNAME
|
||
input->data[input->len] = '\0';
|
||
if (strstr(input->data, TEST_FNAME)){
|
||
test_handle = fhandle;
|
||
do_druck++;
|
||
}
|
||
#endif
|
||
} else completition = (uint8) (-fhandle);
|
||
}
|
||
break;
|
||
|
||
case 0x44 : /* file(s) delete */
|
||
{
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 dirhandle; /* 0x0 */
|
||
uint8 searchattributes;
|
||
/* 0 none, 2 Hidden, 4 System, 6 Both */
|
||
uint8 len;
|
||
uint8 data[2]; /* Name */
|
||
} *input = (struct INPUT *)ncprequest;
|
||
int err_code = nw_delete_files((int)input->dirhandle,
|
||
(int)input->searchattributes,
|
||
input->data, (int)input->len);
|
||
if (err_code < 0)
|
||
completition = (uint8) -err_code;
|
||
}
|
||
break;
|
||
|
||
case 0x45 : /* rename file */
|
||
{
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 dir_handle;
|
||
uint8 searchattrib;
|
||
uint8 len;
|
||
uint8 data[2]; /* Name */
|
||
} *input = (struct INPUT *)ncprequest;
|
||
uint8 *p = input->data+input->len; /* reserve z.B. 0x1 */
|
||
/* + 1 = len2 */
|
||
/* + 1 = data2 */
|
||
int errcode = nw_mv_files(
|
||
(int)input->searchattrib,
|
||
(int)input->dir_handle, input->data,(int)input->len,
|
||
(int)input->dir_handle, p+2, (int)*(p+1) );
|
||
|
||
if (errcode < 0) completition = (uint8) -errcode;
|
||
}
|
||
break;
|
||
|
||
case 0x46 : /* set file attributes */
|
||
{
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 access; /* 0x80, od 0x0 */
|
||
/* 0x80 for example is shared */
|
||
uint8 dir_handle;
|
||
uint8 attrib; /* search attrib */
|
||
uint8 len;
|
||
uint8 data[2]; /* filename */
|
||
} *input = (struct INPUT *)ncprequest;
|
||
completition =
|
||
(uint8) (-nw_set_file_attributes((int)input->dir_handle,
|
||
input->data, (int)input->len,
|
||
(int)input->attrib,
|
||
(int)input->access));
|
||
}
|
||
break;
|
||
|
||
case 0x47 : /* move pointer to end of file ???? */
|
||
/* and return filesize ? */
|
||
{
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 filler;
|
||
uint8 ext_filehandle[2]; /* all zero */
|
||
uint8 fhandle[4]; /* Dateihandle */
|
||
} *input = (struct INPUT *)ncprequest;
|
||
struct XDATA {
|
||
uint8 size[4]; /* Position ??? */
|
||
} *xdata=(struct XDATA*)responsedata;
|
||
int fhandle = GET_32(input->fhandle);
|
||
int size = nw_seek_file(fhandle, 0);
|
||
if (size > -1) {
|
||
data_len = sizeof(struct XDATA);
|
||
U32_TO_BE32(size, xdata->size);
|
||
}
|
||
else completition = (uint8) -size;
|
||
}
|
||
break;
|
||
|
||
case 0x48 : /* read file */
|
||
{
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 filler;
|
||
uint8 ext_fhandle[2]; /* all zero */
|
||
uint8 fhandle[4]; /* filehandle */
|
||
uint8 offset[4];
|
||
uint8 max_size[2]; /* byte to readd */
|
||
} *input = (struct INPUT *)ncprequest;
|
||
struct XDATA {
|
||
uint8 size[2]; /* read bytes */
|
||
uint8 data[2]; /* read data */
|
||
} *xdata=(struct XDATA*)responsedata;
|
||
int fhandle = GET_32 (input->fhandle);
|
||
int max_size = GET_BE16(input->max_size);
|
||
off_t offset = GET_BE32(input->offset);
|
||
int zusatz = (offset & 1) ? 1 : 0;
|
||
int size;
|
||
if (max_size > rw_buffer_size) {
|
||
XDPRINTF((1,0, "wanted read=%d byte > %d",
|
||
max_size, rw_buffer_size));
|
||
size = -0x88; /* we say wrong filehandle */
|
||
} else
|
||
size = nw_read_file(fhandle,
|
||
xdata->data+zusatz,
|
||
max_size,
|
||
offset);
|
||
if (size > -1) {
|
||
U16_TO_BE16(size, xdata->size);
|
||
data_len=size+zusatz+2;
|
||
} else completition = (uint8) -size;
|
||
}
|
||
break;
|
||
|
||
case 0x49 : { /* write file */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 filler; /* 0 Filler ?? */
|
||
uint8 ext_handle[2];
|
||
uint8 fhandle[4]; /* Dateihandle */
|
||
uint8 offset[4]; /* SEEK OFFSET */
|
||
uint8 size[2]; /* Datasize */
|
||
uint8 data[2]; /* Schreibdaten */
|
||
} *input = (struct INPUT *)ncprequest;
|
||
off_t offset = GET_BE32(input->offset);
|
||
int fhandle = GET_32 (input->fhandle);
|
||
int input_size = GET_BE16(input->size);
|
||
int size = nw_write_file(fhandle,
|
||
input->data,
|
||
input_size,
|
||
offset);
|
||
if (size < 0)
|
||
completition = (uint8) -size;
|
||
else if (size < input_size)
|
||
completition = (uint8)0xff;
|
||
}
|
||
break;
|
||
|
||
|
||
case 0x4a : { /* File SERVER COPY */
|
||
/* should be OK */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 reserved; /* Reserved by Novell */
|
||
uint8 qext_fhandle[2]; /* ext Filehandle */
|
||
uint8 qfhandle[4]; /* Quellfile */
|
||
uint8 zext_fhandle[2]; /* ext Filehandle */
|
||
uint8 zfhandle[4]; /* Zielfile */
|
||
uint8 qoffset[4]; /* SourceFile Offset */
|
||
uint8 zoffset[4]; /* DestFile Offset */
|
||
uint8 size[4]; /* copysize */
|
||
} *input = (struct INPUT *)ncprequest;
|
||
int qfhandle = GET_32 (input->qfhandle);
|
||
int zfhandle = GET_32 (input->zfhandle);
|
||
off_t qoffset = GET_BE32(input->qoffset);
|
||
off_t zoffset = GET_BE32(input->zoffset);
|
||
uint32 input_size = GET_BE32(input->size);
|
||
int size = nw_server_copy(qfhandle, qoffset,
|
||
zfhandle, zoffset,
|
||
input_size);
|
||
if (size < 0) completition = (uint8) -size;
|
||
else {
|
||
struct XDATA {
|
||
uint8 zsize[4]; /* real transfered Bytes */
|
||
} *xdata= (struct XDATA*)responsedata;
|
||
U32_TO_BE32(size, xdata->zsize);
|
||
data_len = sizeof(struct XDATA);
|
||
}
|
||
}
|
||
break;
|
||
|
||
|
||
case 0x4b : { /* set date of file, file will be closed later */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 filler;
|
||
uint8 reserve[2]; /* ext Filehandle */
|
||
uint8 fhandle[4]; /* Dateihandle */
|
||
uint8 zeit[2]; /* time */
|
||
uint8 datum[2]; /* date */
|
||
} *input = (struct INPUT *)ncprequest;
|
||
int result = nw_set_fdate_time(GET_32(input->fhandle),
|
||
input->datum, input->zeit);
|
||
if (result <0) completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
case 0x4c : { /* open file */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 dirhandle; /* Dirhandle */
|
||
uint8 attrib; /* z.B. 0x6 od. 0x4e */
|
||
/* O_RDWR|TRUNC 0x6, O_RDONLY 0x6 */
|
||
|
||
uint8 access; /* z.B. 0x9 od 0x11 od. 0x13 */
|
||
/* O_RDWR|TRUNC 0x13, O_RDONLY 0x11 */
|
||
/* O_RDWR|TRUNC|O_DENYNONE 0x3 */
|
||
/* 0x10 BINAERMODUS ?? */
|
||
/* 0x02 do write */
|
||
uint8 len; /* namelaenge */
|
||
uint8 data[2]; /* Name */
|
||
} *input = (struct INPUT *)ncprequest;
|
||
struct XDATA {
|
||
uint8 ext_fhandle[2]; /* all zero */
|
||
uint8 fhandle[4]; /* Dateihandle */
|
||
uint8 reserved[2]; /* reserved by Novell */
|
||
NW_FILE_INFO fileinfo;
|
||
} *xdata= (struct XDATA*)responsedata;
|
||
int fhandle=nw_creat_open_file((int)input->dirhandle,
|
||
input->data, input->len,
|
||
&(xdata->fileinfo),
|
||
(int)input->attrib,
|
||
(int)input->access, 0,
|
||
(int)(ncprequest->task));
|
||
|
||
if (fhandle > -1){
|
||
U32_TO_32 (fhandle, xdata->fhandle);
|
||
xdata->ext_fhandle[0]=0;
|
||
xdata->ext_fhandle[1]=0;
|
||
xdata->reserved[0]=0;
|
||
xdata->reserved[1]=0;
|
||
data_len = sizeof(struct XDATA);
|
||
#ifdef TEST_FNAME
|
||
input->data[input->len] = '\0';
|
||
if (strstr(input->data, TEST_FNAME)){
|
||
test_handle = fhandle;
|
||
do_druck++;
|
||
}
|
||
#endif
|
||
|
||
} else completition = (uint8) (-fhandle);
|
||
}
|
||
break;
|
||
|
||
#if WITH_NAME_SPACE_CALLS
|
||
case 0x56 : /* some extended atrribute calls */
|
||
{
|
||
int result = handle_func_0x56(requestdata, responsedata, ncprequest->task);
|
||
if (result > -1) data_len = result;
|
||
else completition=(uint8)-result;
|
||
}
|
||
break;
|
||
|
||
case 0x57 : /* some new namespace calls */
|
||
{
|
||
int result = handle_func_0x57(requestdata, responsedata, ncprequest->task);
|
||
if (result > -1) data_len = result;
|
||
else completition=(uint8)-result;
|
||
}
|
||
break;
|
||
#endif
|
||
|
||
#ifdef _MAR_TESTS_XX
|
||
case 0x5f : { /* ????????????? UNIX Client */
|
||
/* a 4.1 Server also do not know this call */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 unknown[4]; /* 0x10, 0,0,0 */
|
||
} *input = (struct INPUT *)ncprequest;
|
||
completition = 0;
|
||
}
|
||
break;
|
||
|
||
#endif
|
||
|
||
case 0x61 :
|
||
#if ENABLE_BURSTMODE
|
||
if (server_version_flags&1) { /* enable Burstmode */
|
||
/* Negotiate Buffer Size, Packetsize new ? */
|
||
int wantsize = GET_BE16((uint8*)requestdata);
|
||
/* wantsize is here max.
|
||
* phys. packet size without MAC-header
|
||
* e.g. 1500 if ethernet
|
||
*/
|
||
int flags = (int) *(requestdata+2);
|
||
/**** flags ***********************
|
||
* CHECKSUMMING_REQUESTED 1
|
||
* SIGNATURE_REQUESTED 2
|
||
* COMPLETE_SIGNATURES_REQUESTED 4
|
||
* ENCRYPTION_REQUESTED 8
|
||
* LIP_DISABLED 0x80
|
||
**********************************/
|
||
struct XDATA {
|
||
uint8 getsize[2];
|
||
uint8 socket[2]; /* echo socket */
|
||
uint8 flags; /* zero */
|
||
} *xdata= (struct XDATA*)responsedata;
|
||
memset(xdata, 0, sizeof(*xdata));
|
||
wantsize = min(IPX_MAX_DATA+30, wantsize);
|
||
rw_buffer_size = min(RW_BUFFERSIZE, wantsize-64);
|
||
|
||
U16_TO_BE16(wantsize, xdata->getsize);
|
||
U16_TO_BE16(sock_echo, xdata->socket);
|
||
data_len = sizeof(*xdata);
|
||
XDPRINTF((5,0, "Negotiate Buffer (new) =0x%04x,(%d), flags=0x%x",
|
||
(int) wantsize, (int) wantsize, flags));
|
||
} else
|
||
#endif
|
||
{
|
||
XDPRINTF((2,0, "Function '0x61' (Burst) not enabled"));
|
||
completition = 0xfb; /* unknown request */
|
||
nw_debug=0;
|
||
}
|
||
break;
|
||
|
||
case 0x65 : /* Packet Burst Connection Request */
|
||
#if ENABLE_BURSTMODE
|
||
if (server_version_flags&1) { /* enable burstmode */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 connid[4]; /* RANDOM ID */
|
||
/* build by time() */
|
||
uint8 max_packet_size[4]; /* HI-LO */
|
||
/* max_packet_size is here max.
|
||
* phys. packet size without MAC-header
|
||
* e.g. 1500 if ethernet
|
||
*/
|
||
uint8 target_socket[2]; /* HI-LO */
|
||
uint8 max_send_size[4]; /* HI-LO */
|
||
uint8 max_recv_size[4]; /* HI-LO */
|
||
} *input = (struct INPUT *)ncprequest;
|
||
struct XDATA {
|
||
uint8 server_id[4]; /* RANDOM ID */
|
||
/* build by time() */
|
||
uint8 max_packet_size[4]; /* HI-LO */
|
||
uint8 max_send_size[4]; /* HI-LO */
|
||
uint8 max_recv_size[4]; /* HI-LO */
|
||
} *xdata= (struct XDATA*) responsedata;
|
||
int client_socket=GET_BE16(input->target_socket);
|
||
uint32 max_packet_size=min(sizeof(IPX_DATA),
|
||
GET_BE32(input->max_packet_size)-30);
|
||
U32_TO_BE32(max_packet_size + 30,
|
||
xdata->max_packet_size);
|
||
if (!burst_w)
|
||
burst_w=(BURST_W*)xcmalloc(sizeof(BURST_W));
|
||
xfree(burst_w->sendburst);
|
||
xfree(burst_w->send_buf);
|
||
xfree(burst_w->recv_buf);
|
||
|
||
burst_w->max_burst_data_size=
|
||
max_packet_size-sizeof(BURSTPACKET);
|
||
|
||
burst_w->sendburst=
|
||
(BURSTPACKET*)xcmalloc(max_packet_size);
|
||
|
||
burst_w->ud.udata.buf = (char*)(burst_w->sendburst);
|
||
|
||
burst_w->sendburst->type[0]=0x77;
|
||
burst_w->sendburst->type[1]=0x77;
|
||
burst_w->sendburst->streamtyp=2; /* BIG_SEND_BURST */
|
||
|
||
U32_TO_BE32(time(NULL), burst_w->sendburst->source_conn);
|
||
U16_TO_16(act_connection, burst_w->sendburst->source_conn);
|
||
/* we need to identify it */
|
||
|
||
memcpy(xdata->server_id,
|
||
burst_w->sendburst->source_conn, 4);
|
||
memcpy(burst_w->sendburst->dest_conn,
|
||
input->connid, 4);
|
||
|
||
burst_w->max_send_size=
|
||
min(max_burst_send_size,
|
||
GET_BE32(input->max_recv_size));
|
||
burst_w->send_buf=xcmalloc(burst_w->max_send_size+8);
|
||
|
||
burst_w->max_recv_size=
|
||
min(max_burst_recv_size,
|
||
GET_BE32(input->max_send_size));
|
||
#if 1 /* MUST BE REMOVED LATER !!! */
|
||
/* we don't want fragmented receive packets */
|
||
if (burst_w->max_recv_size >
|
||
burst_w->max_burst_data_size-24)
|
||
burst_w->max_recv_size
|
||
=burst_w->max_burst_data_size-24;
|
||
#endif
|
||
burst_w->recv_buf=xcmalloc(burst_w->max_recv_size+24);
|
||
#if 1
|
||
U32_TO_BE32(0x5ff22, burst_w->sendburst->delaytime);
|
||
#endif
|
||
U32_TO_BE32(burst_w->max_recv_size, xdata->max_recv_size);
|
||
U32_TO_BE32(burst_w->max_send_size, xdata->max_send_size);
|
||
|
||
burst_w->ipx_pack_typ = PACKT_CORE;
|
||
burst_w->ud.opt.len = sizeof(uint8);
|
||
burst_w->ud.opt.maxlen = sizeof(uint8);
|
||
burst_w->ud.opt.buf = (char*)&(burst_w->ipx_pack_typ);
|
||
|
||
memcpy(&(burst_w->to_addr), &from_addr, sizeof(ipxAddr_t));
|
||
U16_TO_BE16(client_socket, burst_w->to_addr.sock);
|
||
burst_w->ud.addr.len = sizeof(ipxAddr_t);
|
||
burst_w->ud.addr.maxlen = sizeof(ipxAddr_t);
|
||
burst_w->ud.addr.buf = (char*)&(burst_w->to_addr);
|
||
data_len = sizeof(*xdata);
|
||
} else
|
||
#endif
|
||
{
|
||
XDPRINTF((2,0, "Packet Burst Connection Request not enabled"));
|
||
nw_debug=0;
|
||
completition = 0xfb; /* unknown request */
|
||
}
|
||
break;
|
||
|
||
case 0x68 : /* NDS NCP, NDS Fragger Protokoll ?? */
|
||
XDPRINTF((2,0, "NDS Fragger Protokoll not supportet"));
|
||
nw_debug=0;
|
||
completition = 0xfb; /* unknown request */
|
||
break;
|
||
|
||
default : completition = 0xfb; /* unknown request */
|
||
break;
|
||
|
||
} /* switch function */
|
||
|
||
} else if (ncp_type == 0x1111) {
|
||
free_queue_jobs();
|
||
(void) nw_init_connect();
|
||
last_sequence = -9999;
|
||
} else {
|
||
XDPRINTF((1,0, "WRONG TYPE:0x%x", ncp_type));
|
||
completition = 0xfb;
|
||
}
|
||
|
||
if (nw_debug && (completition == 0xfb || (do_druck == 1))) { /* UNKWON FUNCTION od. TYPE */
|
||
pr_debug_request();
|
||
if (completition == 0xfb)
|
||
XDPRINTF((0,0, "UNKNOWN FUNCTION or TYPE: 0x%x", function));
|
||
else if (data_len){
|
||
int j = data_len;
|
||
uint8 *p = responsedata;
|
||
XDPRINTF((0,2, "RSPONSE: len %d, DATA:", data_len));
|
||
while (j--) {
|
||
int c = *p++;
|
||
if (c > 32 && c < 127) XDPRINTF((0,3,",\'%c\'", (char) c));
|
||
else XDPRINTF((0,3,",0x%x", c));
|
||
}
|
||
XDPRINTF((0,1, NULL));
|
||
}
|
||
}
|
||
ncp_response(ncprequest->sequence, ncprequest->task, completition, data_len);
|
||
nw_debug = org_nw_debug;
|
||
return(0);
|
||
}
|
||
|
||
static void handle_after_bind()
|
||
{
|
||
NCPREQUEST *ncprequest = (NCPREQUEST*) saved_readbuff;
|
||
uint8 *requestdata = saved_readbuff + sizeof(NCPREQUEST);
|
||
uint8 *bindresponse = readbuff + sizeof(NCPRESPONSE);
|
||
int data_len = 0;
|
||
int completition = 0;
|
||
switch (ncprequest->function) {
|
||
/* QUOTA support from: Matt Paley */
|
||
case 0x16 : {
|
||
uint8 ufunc = *(requestdata+2);
|
||
switch (ufunc) {
|
||
case 0x21: {
|
||
/* change Vol restrictions for Obj */
|
||
uint8 volnr = *(requestdata+3);
|
||
uint32 id = GET_BE32(requestdata+4);
|
||
uint32 blocks = GET_32(requestdata+8);
|
||
int gid = ((int *) bindresponse)[0];
|
||
int uid = ((int *) bindresponse)[1];
|
||
int perm = ((int *) bindresponse)[2];
|
||
int result;
|
||
XDPRINTF((5, 0,
|
||
"Change vol rest id=%x vol=%d blocks=%d gid=%d uid=%d p=%d",
|
||
(int) id, (int) volnr, (int) blocks,
|
||
(int) gid, (int) uid, (int) perm));
|
||
if (perm == 0) {
|
||
result = nw_set_vol_restrictions(volnr, uid, blocks);
|
||
} else {
|
||
result = -0x85;
|
||
}
|
||
if (result < 0) completition = (uint8)-result;
|
||
}
|
||
break;
|
||
case 0x22: {
|
||
/* Remove Vol restrictions for Obj */
|
||
uint8 volnr = *(requestdata+3);
|
||
uint32 id = GET_BE32(requestdata+4);
|
||
int gid = ((int *) bindresponse)[0];
|
||
int uid = ((int *) bindresponse)[1];
|
||
int perm = ((int *) bindresponse)[2];
|
||
int result;
|
||
XDPRINTF((1, 0, "Remove vol rest id=%x vol=%d gid=%d uid=%d p=%d",
|
||
(int) id, (int) volnr, (int) gid, (int) uid, (int) perm));
|
||
if (perm == 0) {
|
||
result = nw_set_vol_restrictions(volnr, uid, 0);
|
||
} else {
|
||
result = -0x85;
|
||
}
|
||
if (result < 0) completition = (uint8)-result;
|
||
}
|
||
break;
|
||
case 0x29: {
|
||
/* Get Vol restrictions for Obj */
|
||
uint8 volnr = *(requestdata+3);
|
||
uint32 id = GET_BE32(requestdata+4);
|
||
int gid = ((int *) bindresponse)[0];
|
||
int uid = ((int *) bindresponse)[1];
|
||
int perm = ((int *) bindresponse)[2];
|
||
uint32 quota, used;
|
||
int result;
|
||
struct XDATA {
|
||
uint8 restriction[4];
|
||
uint8 inuse[4];
|
||
} *xdata = (struct XDATA*) responsedata;
|
||
XDPRINTF((5, 0, "Get vol rest id=%x vol=%d gid=%d uid=%d p=%d",
|
||
(int) id, (int) volnr, (int) gid, (int) uid, (int) perm));
|
||
if (perm == 0) {
|
||
result = nw_get_vol_restrictions(volnr, uid, "a, &used);
|
||
} else {
|
||
result = -0x85;
|
||
}
|
||
data_len = 8;
|
||
if (result == 0) {
|
||
U32_TO_32(quota, xdata->restriction);
|
||
U32_TO_32(used, xdata->inuse);
|
||
} else {
|
||
U32_TO_32(0x40000000, xdata->restriction);
|
||
U32_TO_32(0x0, xdata->inuse);
|
||
completition = (uint8) -result;
|
||
}
|
||
}
|
||
break;
|
||
default : completition = 0xfb;
|
||
}
|
||
break;
|
||
}
|
||
case 0x17 : { /* FILE SERVER ENVIRONMENT */
|
||
uint8 ufunc = *(requestdata+2);
|
||
switch (ufunc) {
|
||
case 0x14: /* Login Objekt, unencrypted passwords */
|
||
case 0x18: { /* crypt_keyed LOGIN */
|
||
int grpcount = * (int*)(bindresponse + 4 * sizeof(int));
|
||
uint32 *grps = (uint32*)(bindresponse + 5 * sizeof(int));
|
||
int unxloginlen = (int)*(uint8*)(grps+grpcount);
|
||
uint8 *unxloginname = (uint8*)(grps+grpcount)+1;
|
||
uint8 objname[48];
|
||
/* ncpserv have changed the structure */
|
||
if (ufunc==0x14) {
|
||
xstrmaxcpy(objname, requestdata+6, (int) *(requestdata+5));
|
||
} else if (ufunc==0x18){
|
||
xstrmaxcpy(objname, requestdata+14, (int) *(requestdata+13));
|
||
} else objname[0]='\0';
|
||
set_nw_user(*((int*)bindresponse), /* gid */
|
||
*((int*)(bindresponse+sizeof(int))), /* uid */
|
||
*((int*)(bindresponse + 2 * sizeof(int))), /* id_flags */
|
||
*((uint32*)(bindresponse + 3 * sizeof(int))), /* id */
|
||
objname, /* login name */
|
||
unxloginlen, unxloginname,
|
||
grpcount, grps);
|
||
}
|
||
break;
|
||
|
||
case 0x68: /* create queue job and file old */
|
||
case 0x79: { /* create queue job and file */
|
||
/* nwbind made prehandling */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 packetlen[2]; /* low high */
|
||
uint8 func; /* 0x79 or 0x68 */
|
||
uint8 queue_id[4]; /* Queue ID */
|
||
uint8 queue_job[280]; /* oldsize is 256 */
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
uint32 q_id = GET_BE32(input->queue_id);
|
||
uint8 *qjob = bindresponse;
|
||
int result = creat_queue_job( (int) ncprequest->task,
|
||
q_id, qjob,
|
||
responsedata,
|
||
(ufunc == 0x68) );
|
||
if (result > -1)
|
||
data_len=result;
|
||
else
|
||
completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
case 0x69: /* close file and start queue old ?? */
|
||
case 0x7f: { /* close file and start queue */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 packetlen[2]; /* low high */
|
||
uint8 func; /* 0x7f or 0x69 */
|
||
uint8 queue_id[4]; /* Queue ID */
|
||
uint8 job_id[4]; /* result from creat queue */
|
||
/* if 0x69 then only 2 byte ! */
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
struct RINPUT {
|
||
uint8 client_area[152];
|
||
uint8 prc_len; /* len of printcommand */
|
||
uint8 prc[1]; /* printcommand */
|
||
} *rinput = (struct RINPUT *) (bindresponse);
|
||
uint32 q_id = GET_BE32(input->queue_id);
|
||
int job_id = (ufunc==0x69) ? GET_BE16(input->job_id)
|
||
: GET_BE16(input->job_id);
|
||
|
||
int result = close_queue_job2(q_id, job_id,
|
||
rinput->client_area,
|
||
rinput->prc,
|
||
rinput->prc_len);
|
||
if (result < 0) completition = (uint8)-result;
|
||
}
|
||
break;
|
||
|
||
case 0x71 : /* service queue job (old) */
|
||
case 0x7c : { /* service queue job */
|
||
struct INPUT {
|
||
uint8 header[7]; /* Requestheader */
|
||
uint8 packetlen[2]; /* low high */
|
||
uint8 func; /* 0x7c,0x71 */
|
||
uint8 queue_id[4]; /* Queue ID */
|
||
uint8 job_typ[2]; /* service typ */
|
||
} *input = (struct INPUT *) (ncprequest);
|
||
uint32 q_id = GET_BE32(input->queue_id);
|
||
uint8 *qjob = bindresponse;
|
||
int result = service_queue_job((int)ncprequest->task,
|
||
q_id, qjob,
|
||
responsedata,
|
||
ufunc==0x71);
|
||
if (result > -1)
|
||
data_len=result;
|
||
else
|
||
completition = (uint8) -result;
|
||
}
|
||
break;
|
||
|
||
default : completition = 0xfb;
|
||
}
|
||
}
|
||
break;
|
||
default : completition = 0xfb;
|
||
} /* switch */
|
||
ncp_response(ncprequest->sequence, ncprequest->task, completition, data_len);
|
||
}
|
||
|
||
#if ENABLE_BURSTMODE
|
||
|
||
|
||
static int send_burst(int offset, int datasize, int flags)
|
||
{
|
||
BURSTPACKET *sb=burst_w->sendburst;
|
||
U32_TO_BE32(burst_w->packet_sequence++, sb->packet_sequence);
|
||
U32_TO_BE32(offset, sb->burstoffset);
|
||
U16_TO_BE16(datasize, sb->datasize);
|
||
U16_TO_BE16(0, sb->missing);
|
||
sb->flags = (uint8)flags;
|
||
memcpy(sb+1, burst_w->send_buf+offset, datasize);
|
||
burst_w->ud.udata.len =
|
||
burst_w->ud.udata.maxlen = datasize+sizeof(BURSTPACKET);
|
||
if (t_sndudata(FD_NCP_OUT, &(burst_w->ud)) < 0){
|
||
if (nw_debug) t_error("t_sndudata in NWCONN !OK");
|
||
return(-1);
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
#include <sys/time.h>
|
||
static void sleep_mu(int mu)
|
||
{
|
||
struct timeval t;
|
||
t.tv_sec = 0;
|
||
t.tv_usec = mu;
|
||
(void) select(1, NULL, NULL, NULL, &t);
|
||
}
|
||
|
||
static void handle_burst_response(uint32 offset, int size)
|
||
{
|
||
BURSTPACKET *sb=burst_w->sendburst;
|
||
U16_TO_BE16(burst_w->burst_sequence, sb->burst_seq);
|
||
U16_TO_BE16(burst_w->burst_sequence+1, sb->ack_seq);
|
||
U32_TO_BE32(size, sb->burstsize);
|
||
|
||
while (size) {
|
||
int sendsize=min(size, burst_w->max_burst_data_size);
|
||
int flags=0;
|
||
size-=sendsize;
|
||
if (!size) flags|=0x10; /* EndOfBurst */
|
||
send_burst(offset, sendsize, flags);
|
||
#if 0
|
||
sleep_mu(2);
|
||
#endif
|
||
offset+=sendsize;
|
||
}
|
||
|
||
}
|
||
|
||
static void handle_burst(BURSTPACKET *bp, int len)
|
||
{
|
||
if (burst_w) {
|
||
uint32 burstoffset = GET_BE32(bp->burstoffset);
|
||
int burstsequence = GET_BE16(bp->burst_seq);
|
||
int datasize = GET_BE16(bp->datasize);
|
||
|
||
if (datasize && !(bp->flags & 0x80)) {
|
||
/* copy if no System Packet */
|
||
if (datasize+burstoffset > burst_w->max_recv_size+24) {
|
||
XDPRINTF((1, 0, "recv burstpacket offs=%d+size=%d > max_recv+24=%d",
|
||
burstoffset, datasize, burst_w->max_recv_size+24));
|
||
return;
|
||
}
|
||
memcpy(burst_w->recv_buf+burstoffset, bp+1, datasize);
|
||
}
|
||
|
||
if (bp->flags & 0x10) { /* last packet, now action */
|
||
/* 0x10 = EOB flag */
|
||
struct REQ {
|
||
uint8 function[4]; /* lo-hi 1=READ, 2=WRITE */
|
||
uint8 fhandle[4]; /* from open file */
|
||
uint8 reserved1[4]; /* all zero */
|
||
uint8 reserved2[4]; /* ??? c8,0 od. c9,f0 */
|
||
uint8 file_offset[4]; /* HI-LO */
|
||
uint8 file_size [4]; /* HI-LO */
|
||
uint8 data[2]; /* only Write */
|
||
} *req=(struct REQ*)(burst_w->recv_buf);
|
||
int function=GET_32(req->function);
|
||
|
||
if (function == 1 || function == 2) { /* Read or Write */
|
||
uint32 fhandle = GET_32(req->fhandle);
|
||
uint32 foffset = GET_BE32(req->file_offset);
|
||
uint32 fsize = GET_BE32(req->file_size);
|
||
if (function == 1) { /* Read Request */
|
||
struct XDATA {
|
||
uint8 resultcode[4]; /* lo-hi ,
|
||
* 0=noerror=OK,
|
||
* 1=init-err,
|
||
* 2=IO-err,
|
||
* 3=no data
|
||
*/
|
||
uint8 readbytes[4]; /* hi-lo */
|
||
} *xdata= (struct XDATA*)burst_w->send_buf;
|
||
int zusatz = 0; /* (foffset & 1) ? 1 : 0; */
|
||
int size = nw_read_file(fhandle,
|
||
burst_w->send_buf+sizeof(struct XDATA),
|
||
fsize, foffset);
|
||
if (zusatz) {
|
||
XDPRINTF((1, 0, "foffset=%d, fsize=%d", foffset, fsize));
|
||
}
|
||
if (size > -1) {
|
||
U32_TO_32(0, xdata->resultcode);
|
||
U32_TO_BE32(size, xdata->readbytes);
|
||
} else {
|
||
U32_TO_32(3, xdata->resultcode);
|
||
U32_TO_BE32(0, xdata->readbytes);
|
||
size=0;
|
||
}
|
||
burst_w->burst_sequence = burstsequence;
|
||
handle_burst_response(0, size+sizeof(struct XDATA));
|
||
} else { /* Write Request */
|
||
struct XDATA {
|
||
uint8 resultcode[4]; /* lo-hi ,
|
||
* 0=noerror=OK,
|
||
* 4=write error
|
||
*/
|
||
} *xdata= (struct XDATA*)burst_w->send_buf;
|
||
int size = nw_write_file(fhandle, req->data, fsize, foffset);
|
||
U32_TO_32(size==fsize ? 0 : 4, xdata->resultcode);
|
||
burst_w->burst_sequence = burstsequence;
|
||
handle_burst_response(0, sizeof(struct XDATA));
|
||
}
|
||
} else {
|
||
XDPRINTF((1, 0, "burst unknow function=0x%x", function));
|
||
}
|
||
req->function[0]=0;
|
||
} else if (bp->flags & 0x80) { /* System Flag */
|
||
int missing=GET_BE16(bp->missing);
|
||
uint8 *p=(uint8*)(bp+1);
|
||
burst_w->burst_sequence = burstsequence;
|
||
while (missing--){
|
||
int offs=GET_BE32(p);
|
||
int size=GET_BE16(p+4);
|
||
handle_burst_response(offs, size);
|
||
p+=6;
|
||
}
|
||
}
|
||
} else {
|
||
XDPRINTF((1, 0, "burst_w not allocated"));
|
||
}
|
||
}
|
||
#endif
|
||
|
||
static void close_all(void)
|
||
{
|
||
nw_exit_connect();
|
||
close(0);
|
||
close(FD_NCP_OUT);
|
||
}
|
||
|
||
static int fl_get_int=0;
|
||
/* signals
|
||
* &01 sig_quit
|
||
* &02 sig_hup
|
||
* &04 sig_usr1
|
||
* &08 sig_usr2
|
||
*/
|
||
|
||
static void sig_quit(int rsig)
|
||
{
|
||
XDPRINTF((2, 0, "Got Signal=%d", rsig));
|
||
fl_get_int |= 1;
|
||
}
|
||
|
||
static void sig_pipe(int rsig)
|
||
{
|
||
XDPRINTF((1, 0, "Got SIG_PIPE"));
|
||
signal(SIGPIPE, sig_pipe);
|
||
}
|
||
|
||
static void sig_hup(int rsig)
|
||
{
|
||
fl_get_int |= 2;
|
||
signal(SIGHUP, sig_hup);
|
||
}
|
||
|
||
static void sig_usr1(int rsig)
|
||
{
|
||
fl_get_int |= 4;
|
||
}
|
||
|
||
static void sig_usr2(int rsig)
|
||
{
|
||
fl_get_int |= 8;
|
||
}
|
||
|
||
static void get_new_debug(void)
|
||
{
|
||
get_ini_debug(3);
|
||
fl_get_int &= ~2;
|
||
}
|
||
|
||
static void handle_extern_command(void)
|
||
{
|
||
fl_get_int &= ~4;
|
||
signal(SIGUSR1, sig_usr1);
|
||
}
|
||
|
||
static void handle_sigusr2(void)
|
||
{
|
||
char fn[256];
|
||
FILE *f;
|
||
fl_get_int &= ~8;
|
||
sprintf(fn, "/tmp/nwconn%04d.log", act_connection);
|
||
seteuid(0);
|
||
unlink(fn); /* security: mst:18-Apr-00 */
|
||
f=fopen(fn, "w");
|
||
reseteuid();
|
||
if (f) {
|
||
log_file_module(f);
|
||
fclose(f);
|
||
} else
|
||
errorp(0, "handle_sigusr2", "cannot open %s for writing", fn);
|
||
signal(SIGUSR2, sig_usr2);
|
||
}
|
||
|
||
static void set_sig(void)
|
||
{
|
||
signal(SIGTERM, sig_quit);
|
||
signal(SIGQUIT, sig_quit);
|
||
signal(SIGINT, sig_quit);
|
||
signal(SIGPIPE, sig_pipe);
|
||
signal(SIGHUP, sig_hup);
|
||
signal(SIGUSR1, sig_usr1);
|
||
signal(SIGUSR2, sig_usr2);
|
||
if (use_mmap)
|
||
signal(SIGBUS, sig_bus_mmap); /* in nwfile.c */
|
||
}
|
||
#include <sys/resource.h>
|
||
|
||
int main(int argc, char **argv)
|
||
{
|
||
#if !CALL_NWCONN_OVER_SOCKET
|
||
int shm_id;
|
||
#endif
|
||
time_t last_time=time(NULL);
|
||
#if CALL_NWCONN_OVER_SOCKET
|
||
if (argc != 4 || 3!=sscanf(argv[3], "()INIT-:%x,%x,%x-",
|
||
&father_pid, &sock_nwbind, &sock_echo)) {
|
||
fprintf(stderr, "usage nwconn connid FROM_ADDR ()INIT-:pid,nwbindsock,echosock-\n");
|
||
exit(1);
|
||
}
|
||
#else
|
||
if (argc != 4 || 4!=sscanf(argv[3], "()INIT-:%x,%x,%x,%x-",
|
||
&father_pid, &sock_nwbind, &sock_echo, &shm_id)) {
|
||
fprintf(stderr, "usage nwconn connid FROM_ADDR ()INIT-:pid,nwbindsock,echosock,shm_id-\n");
|
||
exit(1);
|
||
}
|
||
#endif
|
||
prog_title=argv[3];
|
||
setuid(0);
|
||
setgid(0);
|
||
act_connection = atoi(*(argv+1));
|
||
#if !CALL_NWCONN_OVER_SOCKET
|
||
nwconn_state = shmat(shm_id, NULL, SHM_W);
|
||
if ((int )(nwconn_state) == -1) {
|
||
errorp(0, "Can't attach shared memory segment", NULL);
|
||
exit(1);
|
||
}
|
||
#endif
|
||
init_tools(NWCONN, 0);
|
||
memset(saved_readbuff, 0, sizeof(saved_readbuff));
|
||
XDPRINTF((3, 0, "FATHER PID=%d, ADDR=%s CON:%d",
|
||
father_pid, *(argv+2), act_connection));
|
||
adr_to_ipx_addr(&from_addr, *(argv+2));
|
||
|
||
if (nw_init_connect()) exit(1);
|
||
act_pid = getpid();
|
||
|
||
#ifdef LINUX
|
||
set_emu_tli();
|
||
#endif
|
||
last_sequence = -9999;
|
||
if (get_ipx_addr(&my_addr)) exit(1);
|
||
|
||
#if CALL_NWCONN_OVER_SOCKET
|
||
# if 1
|
||
# ifdef SIOCIPXNCPCONN
|
||
{
|
||
int conn = act_connection;
|
||
int result = ioctl(0, SIOCIPXNCPCONN, &conn);
|
||
XDPRINTF((3, 0, "ioctl:SIOCIPXNCPCONN result=%d", result));
|
||
}
|
||
# endif
|
||
# endif
|
||
#endif
|
||
|
||
set_default_guid();
|
||
nwconn_set_program_title(NULL);
|
||
|
||
ud.opt.len = sizeof(uint8);
|
||
ud.opt.maxlen = sizeof(uint8);
|
||
ud.opt.buf = (char*)&ipx_pack_typ;
|
||
|
||
ud.addr.len = sizeof(ipxAddr_t);
|
||
ud.addr.maxlen = sizeof(ipxAddr_t);
|
||
ud.addr.buf = (char*)&from_addr;
|
||
ud.udata.buf = (char*)&ipxdata;
|
||
|
||
U16_TO_BE16(0x3333, ncpresponse->type);
|
||
ncpresponse->task = (uint8) 1; /* allways 1 */
|
||
ncpresponse->connection = (uint8)act_connection;
|
||
ncpresponse->high_connection = (uint8)(act_connection >> 8);
|
||
|
||
set_sig();
|
||
|
||
while ( !(fl_get_int&1) ) {
|
||
int data_len;
|
||
/* We should reply 'Request Being Processed' if request arrived twice
|
||
* or more and nwconn actually busy, if nwconn is free, we are simply
|
||
* resend previous reply.
|
||
* We are set the flag in shared memory indicating what nwconn is busy
|
||
* and check it later in ncpserv. /lenz */
|
||
#if !CALL_NWCONN_OVER_SOCKET
|
||
nwconn_state[act_connection] = 0; /* nwconn is free */
|
||
#endif
|
||
data_len = read(0, readbuff, sizeof(readbuff));
|
||
#if !CALL_NWCONN_OVER_SOCKET
|
||
nwconn_state[act_connection] = 1; /* nwconn is busy */
|
||
#endif
|
||
/* this read is a pipe or a socket read,
|
||
* depending on CALL_NWCONN_OVER_SOCKET
|
||
*/
|
||
|
||
if (fl_get_int) {
|
||
if (fl_get_int & 1) break;
|
||
if (fl_get_int & 2)
|
||
get_new_debug();
|
||
if (fl_get_int & 4)
|
||
handle_extern_command();
|
||
if (fl_get_int & 8)
|
||
handle_sigusr2();
|
||
}
|
||
|
||
if (data_len > 0) {
|
||
XDPRINTF((99, 0, "NWCONN GOT DATA len = %d",data_len));
|
||
ncpresponse->connect_status = (uint8) 0;
|
||
ncpresponse->task = ncprequest->task;
|
||
|
||
if ((ncp_type = (int)GET_BE16(ncprequest->type)) == 0x3333) {
|
||
/* this is a response packet */
|
||
data_len -= sizeof(NCPRESPONSE);
|
||
if (saved_sequence > -1
|
||
&& ((int)(ncprequest->sequence) == saved_sequence)
|
||
&& !ncprequest->function) {
|
||
/* comes from nwbind */
|
||
handle_after_bind();
|
||
} else {
|
||
/* OK for direct sending */
|
||
XDPRINTF((6,0, "NWCONN:direct sending:type 0x3333, completition=0x%x, len=%d",
|
||
(int)(ncprequest->function), data_len));
|
||
if (data_len)
|
||
memcpy(responsedata, readbuff+sizeof(NCPRESPONSE), data_len);
|
||
ncpresponse->connect_status = ((NCPRESPONSE*)readbuff)->connect_status;
|
||
ncp_response(ncprequest->sequence,
|
||
ncprequest->task,
|
||
ncprequest->function, data_len);
|
||
}
|
||
saved_sequence = -1;
|
||
} else { /* this calls I must handle, it is a request */
|
||
act_time=time(NULL);
|
||
act_ncpsequence=(int)(ncprequest->sequence);
|
||
|
||
if (act_time > last_time+60 && saved_sequence == -1) {
|
||
/* ca. 0.5 min. reset wdogs, 5 min as in original is too long for me. /lenz*/
|
||
call_nwbind(1);
|
||
last_time=act_time;
|
||
}
|
||
|
||
#if ENABLE_BURSTMODE
|
||
if (ncp_type == 0x7777) { /* BURST-MODE */
|
||
XDPRINTF((16, 0, "GOT BURSTPACKET"));
|
||
handle_burst((BURSTPACKET*)readbuff, data_len);
|
||
} else
|
||
#endif
|
||
else if (ncp_type == 0x2121) { /* request from nwbind */
|
||
/* mst:25-Apr-00 */
|
||
requestlen = data_len - sizeof(NCPREQUEST);
|
||
handle_nwbind_request();
|
||
} else {
|
||
int result;
|
||
requestlen = data_len - sizeof(NCPREQUEST);
|
||
if (0 != (result = handle_ncp_serv()) ) {
|
||
if (result == -2) {
|
||
/* here the actual call must be saved
|
||
* because we need it later, when the request to nwbind
|
||
* returns.
|
||
*/
|
||
memcpy(saved_readbuff, readbuff, data_len);
|
||
saved_sequence = (int)(ncprequest->sequence);
|
||
} else saved_sequence = -1;
|
||
/* this call must go to nwbind */
|
||
call_nwbind(0);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} /* while */
|
||
|
||
seteuid(0);
|
||
# ifdef SIOCIPXNCPCONN
|
||
{
|
||
int conn = -act_connection;
|
||
(void)ioctl(0, SIOCIPXNCPCONN, &conn);
|
||
}
|
||
# endif
|
||
close_all();
|
||
XDPRINTF((3,0, "leave nwconn pid=%d", getpid()));
|
||
return(0);
|
||
}
|