mars-nwe/nwclient.c

747 lines
18 KiB
C

/* nwclient.c: 12-Nov-95 */
/*
* Einfacher Testclient, wird von nwserv (im Client Modus) gestartet
* Dieses Modul hilft dabei, NCP Responses eines
* echten NW Servers zu analysieren.
* Beim 'echten' NW Server muá 'allow unencryted passwords' gesetzt
* sein.
*/
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "net.h"
static ipxAddr_t serv_addr;
static ipxAddr_t my_addr;
static int fd_ipx;
static int fd_wdog;
static int open_socket()
{
int ipx_fd=t_open("/dev/ipx", O_RDWR, NULL);
struct t_bind bind;
if (ipx_fd < 0) {
t_error("t_open !Ok");
return(-1);
}
U16_TO_BE16(0, my_addr.sock);
bind.addr.len = sizeof(ipxAddr_t);
bind.addr.maxlen = sizeof(ipxAddr_t);
bind.addr.buf = (char*)&my_addr;
bind.qlen = 0; /* immer */
if (t_bind(ipx_fd, &bind, &bind) < 0){
t_error("t_bind !OK");
t_close(ipx_fd);
return(-1);
}
XDPRINTF((0,"socket bound TO %s\n", visable_ipx_adr(&my_addr) ));
return(ipx_fd);
}
static int init_client()
{
return( (fd_ipx = open_socket()) > -1
&& (fd_wdog = open_socket()) > -1 ? 0 : 1);
}
/* DATA OUT */
static IPX_DATA ipxdata_out;
static NCPREQUEST *ncprequest =(NCPREQUEST*)&ipxdata_out;
static uint8 *requestdata=((uint8*)&ipxdata_out)+sizeof(NCPREQUEST);
static void ncp_request(int type, int sequence,
int connection, int task,
int reserved, int function,
int data_len, char *komment)
{
U16_TO_BE16(type, ncprequest->type);
ncprequest->sequence = (uint8) sequence;
ncprequest->connection = (uint8) connection;
ncprequest->task = (uint8) task;
ncprequest->reserved = (uint8) reserved;
ncprequest->function = (uint8) function;
{
int j = data_len;
DPRINTF(("NCP REQUEST: type:0x%x, seq:%d, conn:%d, task:%d, reserved:0x%x, func:0x%x\n",
type, sequence, connection, task, reserved, function));
if (j > 0){
uint8 *p=requestdata;
DPRINTF(("len %d, DATA:", j));
while (j--) {
int c = *p++;
if (c > 32 && c < 127) DPRINTF((",\'%c\'", (char) c));
else DPRINTF((",0x%x", c));
}
DPRINTF(("\n"));
}
}
send_ipx_data(fd_ipx, 17, sizeof(NCPREQUEST) + data_len,
(char *) ncprequest,
&serv_addr, komment);
}
/* DATA IN */
static IPX_DATA ipxdata_in;
static NCPRESPONSE *ncpresponse = (NCPRESPONSE*)&ipxdata_in;
static uint8 *responsedata = ((uint8*)&ipxdata_in) + sizeof(NCPRESPONSE);
/* -------------------------------------- */
static int sequence=0;
static int handle_event(void)
{
struct t_unitdata ud;
ipxAddr_t source_adr;
uint8 ipx_pack_typ;
int flags = 0;
ud.opt.len = sizeof(ipx_pack_typ);
ud.opt.maxlen = sizeof(ipx_pack_typ);
ud.opt.buf = (char*)&ipx_pack_typ; /* bekommt aktuellen Typ */
ud.addr.len = sizeof(ipxAddr_t);
ud.addr.maxlen = sizeof(ipxAddr_t);
ud.addr.buf = (char*)&source_adr;
ud.udata.len = sizeof(IPX_DATA);
ud.udata.maxlen = sizeof(IPX_DATA);
ud.udata.buf = (char*)&ipxdata_in;
if (t_rcvudata(fd_ipx, &ud, &flags) < 0){
struct t_uderr uderr;
ipxAddr_t erradr;
uint8 err_pack_typ;
uderr.addr.len = sizeof(ipxAddr_t);
uderr.addr.maxlen = sizeof(ipxAddr_t);
uderr.addr.buf = (char*)&erradr;
uderr.opt.len = sizeof(err_pack_typ);
uderr.opt.maxlen = sizeof(err_pack_typ);
uderr.opt.buf = (char*)&err_pack_typ; /* bekommt aktuellen Typ */
ud.addr.buf = (char*)&source_adr;
t_rcvuderr(fd_ipx, &uderr);
DPRINTF(("Error from %s, Code = 0x%lx\n", visable_ipx_adr(&erradr), uderr.error));
t_error("t_rcvudata !OK");
return(-1);
} else {
int responselen = ud.udata.len - sizeof(NCPRESPONSE);
int j = responselen;
int sequence = (int)ncpresponse->sequence;
int connection = (int)ncpresponse->connection;
int task = (int)ncpresponse->task;
int reserved = (int)ncpresponse->reserved;
int completition = (int)ncpresponse->completition;
int connect_status = (int)ncpresponse->connect_status;
int type = GET_BE16(ncpresponse->type);
DPRINTF(("Ptyp:%d von: %s, len=%d\n", (int)ipx_pack_typ, visable_ipx_adr(&source_adr), responselen));
DPRINTF(("RESPONSE:t:0x%x, seq:%d, conn:%d, task:%d, res:0x%x, complet.:0x%x, connect:0x%x\n",
type, sequence, connection, task, reserved, completition, connect_status));
if (j > 0){
uint8 *p=responsedata;
DPRINTF(("len %d, DATA:", j));
while (j--) {
int c = *p++;
if (c > 32 && c < 127) DPRINTF((",\'%c\'", (char) c));
else DPRINTF((",0x%x", c));
}
DPRINTF(("\n"));
}
}
if (sequence == ncpresponse->sequence) {
sequence++;
return((int)(ncpresponse->completition));
}
return(-1);
}
/* ------------------------------------------------------ */
static int connection=0;
#define RDATA(xdata, xfunc, xcomment) \
memcpy(requestdata, (xdata), sizeof(xdata)); \
ncp_request(0x2222, sequence, connection, 1, 0, \
(xfunc), sizeof(data), (xcomment))
#define ODATA(xfunc, xcomment) \
ncp_request(0x2222, sequence, connection, 1, 0, \
(xfunc), 0, (xcomment))
#define VDATA(xfunc, xsize, xcomment) \
ncp_request(0x2222, sequence, connection, 1, 0, \
(xfunc), (xsize), (xcomment))
static int get_conn_nr(void)
{
ncp_request(0x1111, sequence, 0xff, 0, 0xff, 0,
0, "Get Connection Nr.");
if (!handle_event()) {
connection = ncpresponse->connection;
DPRINTF(("NWCLIENT GOT CONNECTION NR:%d\n", connection));
return(0);
}
return(-1);
}
static int get_pkt_size(void)
{
uint8 data[] = {0x4, 0}; /* wanted ?? SIZE */
RDATA(data, 0x21, "Get Pktsize");
if (!handle_event()) {
DPRINTF(("NWCLIENT GOT PACKET SIZE =:%d\n", (int)GET_BE16(responsedata)));
return(0);
}
return(-1);
}
static int get_server_info(void)
{
uint8 data[] = {0, 1, 0x11};
RDATA(data, 0x17, "Get FileServer Info");
if (!handle_event()) {
DPRINTF(("NWCLIENT GOT SERVER INFO von=:%s\n", responsedata ));
return(0);
}
return(-1);
}
static int do_17_17(void)
{
uint8 data[] = {0, 1, 0x17};
RDATA(data, 0x17, "Do_17_17");
if (!handle_event()) {
return(0);
}
return(-1);
}
static int get_network_serial_number(void)
{
uint8 data[] = {0, 1, 0x12};
RDATA(data, 0x17, "Get Network Serial Number");
if (!handle_event()) return(0);
return(-1);
}
static int get_connect(void)
{
ODATA(0x19, "get CONNECT ??");
if (!handle_event()) {
return(0);
}
return(-1);
}
static int get_server_time(void)
{
ODATA(0x14, "get SERVER TIME");
if (!handle_event()) {
return(0);
}
return(-1);
}
typedef struct {
uint8 volume;
uint8 dir_id[2];
} DIR_IDS;
static int file_search_init(DIR_IDS *di, int dirhandle, char *path)
{
uint8 *p=requestdata;
int pathlen=path ? strlen(path) : 0;
*p++ = (uint8) dirhandle;
*p++ = (uint8) pathlen;
if (pathlen) memcpy(p, path, pathlen);
VDATA(0x3e, pathlen+2, "FILE SEARCH INIT");
if (!handle_event()) {
if (di) memcpy(di, responsedata, 3);
DPRINTF(("NWCLIENT GOT FILES SEARCH INIT HANDLE=:%d\n",
(int)GET_BE16(responsedata+1) ));
return( (int) *(responsedata+3) ); /* access */
}
return(-1);
}
static int file_search_cont(DIR_IDS *di, int seq,
int attrib, char *path)
{
uint8 *p=requestdata;
int pathlen=path ? strlen(path) : 0;
memcpy(p, di, 3);
p+=3;
U16_TO_BE16((uint16)seq, p);
p+=2;
*p++ = (uint8) attrib;
*p++ = (uint8) pathlen;
if (pathlen) memcpy(p, path, pathlen);
VDATA(0x3f, pathlen+7, "FILE SEARCH CONT");
if (!handle_event()) {
int dir_id = GET_BE16(responsedata+2);
seq = GET_BE16(responsedata);
DPRINTF(("GOT SEARCH CONT dir_id=%d, seq=%d\n", dir_id, seq));
return(seq);
}
return(-1);
}
static int allocate_dir_handle(int dirhandle,
int drive,
char *path,
int temp)
{
uint8 *p=requestdata;
uint8 pathlen= (path) ? strlen(path) : 0;
*p++ = 0;
*p++ = pathlen+4;
if (!temp) *p++ = 0x12; /* permanent */
else if (temp == 1) *p++=0x13; /* temp */
else *p++ = 0x16; /* spez. temp */
*p++ = dirhandle;
*p++ = drive;
*p++ = pathlen;
memcpy(p, path, pathlen);
VDATA(0x16, pathlen+6 , "ALLOCATE DIR HANDLE");
if (!handle_event()) return((int) *responsedata);
return(-1);
}
static void scan_irgendwas(int dirhandle, int attrib, char *name)
{
uint8 *p = requestdata;
int namlen = strlen(name);
*p++ = 0;
*p++ = namlen+6;
*p++ = 0x0f;
U16_TO_BE16(MAX_U16, p);
p+=2;
*p++ = dirhandle;
*p++ = attrib;
*p++ = namlen;
memcpy(p, name, namlen);
VDATA(0x16, namlen+8, "SCAN IRGENDWAS");
if (!handle_event()) {
;
}
}
static void scan_file_trustees(int dirhandle, int attrib, char *name)
{
uint8 *p = requestdata;
int namlen = strlen(name);
*p++ = 0;
*p++ = namlen+8;
*p++ = 0x1e;
*p++ = dirhandle;
*p++ = attrib;
U32_TO_BE32(MAX_U32, p);
p+=4;
*p++ = namlen;
memcpy(p, name, namlen);
VDATA(0x16, namlen+10, "SCAN FILE TRUST");
if (!handle_event()) {
;
}
}
static int get_dir_path(int dirhandle)
{
uint8 *p=requestdata;
*p++ = 0;
*p++ = 2;
*p++ = 1;
*p = (uint8) dirhandle;
VDATA(0x16, 4, "GET DIR PATH");
if (!handle_event()) {
;
}
return(0);
}
static void get_connection_info(int conn)
/* liefert Connection INFO */
{
uint8 *p=requestdata;
*p++ = 0;
*p++ = 2;
*p++ = 0x16;
*p = (uint8) conn;
VDATA(0x17, 4, "GET CONNECTION INFO");
if (!handle_event()) {
;;
}
}
static int get_bindery_access(void)
/* liefert ACCESS LEVEL und CONNECTION BIND ID */
{
uint8 data[] = {0, 1, 0x46};
RDATA(data, 0x17, "Get Bindery ACCESS ??");
if (!handle_event()) {
return(0);
}
return(-1);
}
static int scan_bindery_object(int type, char *name, uint32 lastid)
{
uint8 *p = requestdata;
int namlen = strlen(name);
*p++ = 0;
*p++ = namlen+8;
*p++ = 0x37;
U32_TO_BE32(lastid, p);
p+=4;
U16_TO_BE16(type, p);
p+=2;
*p++=namlen;
memcpy(p, name, namlen);
VDATA(0x17, namlen+10,"Scan Bindery Object");
if (!handle_event()) {
;
}
return(0);
}
static int scan_bindery_property(int type, char *name, char *propname, uint32 *lastid)
{
uint8 *p = requestdata;
int namlen = strlen(name);
int propnamlen = strlen(propname);
*p++ = 0;
*p++ = namlen+9 + propnamlen;
*p++ = 0x3c;
U16_TO_BE16(type, p);
p+=2;
*p++ = namlen;
memcpy(p, name, namlen);
U32_TO_BE32(*lastid, (p+=namlen));
*(p+=4) = propnamlen;
memcpy(++p, propname, propnamlen);
VDATA(0x17, namlen+propnamlen+11,"Scan Bindery Property");
if (!handle_event()) {
/*
*lastid = GET_BE32(responsedata + 20);
*/
*lastid = GET_BE32(responsedata + 18);
return(0);
} else return(-1);
}
static int get_bindery_object_id(int type, char *name)
{
uint8 *p = requestdata;
int namlen = strlen(name);
*p++ = 0;
*p++ = namlen+4;
*p++ = 0x35;
U16_TO_BE16(type, p);
p+=2;
*p++=namlen;
memcpy(p, name, namlen);
VDATA(0x17, namlen+6, "GET BINDERY OBJECT ID");
if (!handle_event()) {
DPRINTF(("GOT BIND OBJ ID=0x%lx\n", GET_BE32(responsedata)));
}
return(0);
}
static void send_console_broadcast(char *message)
{
uint8 *p = requestdata;
int len = strlen(message);
*p++ = 0;
*p++ = len+3;
*p++ = 0xd1;
U16_TO_BE16(len, p);
p+=2;
memcpy(p, message, len);
VDATA(0x17, len+5, "SEND CONSOLE BROADCAST");
if (!handle_event()) {
;;
}
}
static int get_bindery_object_name(uint32 id)
{
uint8 *p = requestdata;
*p++ = 0;
*p++ = 5;
*p++ = 0x36;
U32_TO_BE32(id, p);
VDATA(0x17, 7, "GET BINDERY OBJECT NAME");
if (!handle_event()) {
;
}
return(0);
}
static int get_volume_restriction_for_obj(uint32 id, int volnr)
{
uint8 *p = requestdata;
*p++ = 0;
*p++ = 6;
*p++ = 0x29;
*p++ = (uint8)volnr;
U32_TO_BE32(id, p);
VDATA(0x16, 8, "GET VOLUME RESTRICTION FOR OBJ");
if (!handle_event()) {
;
}
return(0);
}
static int login_object(int type, char *name, char *password)
{
uint8 *p = requestdata;
int namlen = strlen(name);
int passlen = (password) ? strlen(password) : 0;
*p++ = 0;
*p++ = namlen+passlen+5;
*p++ = 0x14;
U16_TO_BE16(type, p);
p+=2;
*p++ = namlen;
memcpy(p, name, namlen);
p += namlen;
if (passlen) memcpy(p, password, passlen);
else *p=0;
VDATA(0x17, namlen+7+passlen, "LOGIN OBJECT");
if (!handle_event()) {
;
}
return(0);
}
static void test_xx()
{
uint8 data[] = {0x0,0x1c,0xf,0xff,0xff,0x0,0x0,0x16,'S','Y','S',':','S','Y','S','T','E','M','\\','N','E','T','$','O','B','J','.','O','L','D'} ;
RDATA(data, 0x17, "test_xx");
if (!handle_event()) {
;
}
}
static int open_datei(int dirhandle, int attrib, int ext_attrib, char *name)
{
uint8 *p = requestdata;
int namlen = strlen(name);
*p++ = dirhandle;
*p++ = attrib;
*p++ = ext_attrib;
*p++ = namlen;
memcpy(p, name, namlen);
VDATA(0x4c, namlen+4, "OPEN_DATEI");
if (!handle_event()) {
return( (int) GET_BE32(responsedata));
} else return(-1);
}
static int read_datei(int fh, int offs, int size)
{
uint8 *p = requestdata;
*p++ = 0;
U32_TO_BE32(fh, p);
p+=6;
U32_TO_BE32(offs, p);
p+=4;
U16_TO_BE16(size, p);
VDATA(0x48, 13, "READ_DATEI");
if (!handle_event()) {
return( (int) GET_BE16(responsedata));
} else return(-1);
}
static void test1(void)
{
int dirhandle = allocate_dir_handle(0, 'F', "SYS:PUBLIC", 0);
if (dirhandle > -1) {
scan_file_trustees(dirhandle, 6, "NET$LOG.DAT");
scan_irgendwas(dirhandle, 6, "NET$LOG.DAT");
}
}
static void test2(void)
{
DIR_IDS di;
if (file_search_init(&di, 1, "\\MAIL") > -1) {
file_search_cont(&di, 0xffff, 0x10, "\252");
}
}
static void teste_reads(void)
{
int fh = open_datei(0, 0x4e, 0x11, "SYS:/LOGIN/SLIST.EXE");
int gelesen=0;
if (fh > -1) {
int offs=0;
int size = read_datei(fh, offs, 0x200);
while (size > 0) {
offs +=size;
gelesen+=size;
size = read_datei(fh, offs, 0x200);
}
}
DPRINTF(("%d Bytes readed\n", gelesen));
}
static void test_wdog(void)
{
struct t_unitdata ud;
ipxAddr_t source_adr;
IPX_DATA ipx_data_buff;
uint8 ipx_pack_typ;
int flags = 0;
ud.opt.len = sizeof(ipx_pack_typ);
ud.opt.maxlen = sizeof(ipx_pack_typ);
ud.opt.buf = (char*)&ipx_pack_typ; /* bekommt aktuellen Typ */
ud.addr.len = sizeof(ipxAddr_t);
ud.addr.maxlen = sizeof(ipxAddr_t);
ud.addr.buf = (char*)&source_adr;
ud.udata.len = sizeof(IPX_DATA);
ud.udata.maxlen = sizeof(IPX_DATA);
ud.udata.buf = (char*)&ipx_data_buff;
while (1) {
if (t_rcvudata(fd_wdog, &ud, &flags) < 0){
struct t_uderr uderr;
ipxAddr_t erradr;
uint8 err_pack_typ;
uderr.addr.len = sizeof(ipxAddr_t);
uderr.addr.maxlen = sizeof(ipxAddr_t);
uderr.addr.buf = (char*)&erradr;
uderr.opt.len = sizeof(err_pack_typ);
uderr.opt.maxlen = sizeof(err_pack_typ);
uderr.opt.buf = (char*)&err_pack_typ; /* bekommt aktuellen Typ */
ud.addr.buf = (char*)&source_adr;
t_rcvuderr(fd_ipx, &uderr);
DPRINTF(("Error from %s, Code = 0x%lx\n", visable_ipx_adr(&erradr), uderr.error));
t_error("t_rcvudata !OK");
return;
} else {
DPRINTF(("WDOG Packet von:%s, len=%d connid=%d, status=%d\n",
visable_ipx_adr(&source_adr),
(int)ud.udata.len, (int) ipx_data_buff.wdog.connid,
(int)ipx_data_buff.wdog.status));
if (ipx_data_buff.wdog.status == '?') {
ipx_data_buff.wdog.status = 'Y';
send_ipx_data(fd_wdog, 17, 2,
(char *) &ipx_data_buff,
&source_adr, "WDOG REPLY");
}
}
}
}
/* --------------------------------------------------------- */
int main(int argc, char **argv)
{
nw_debug = 1; /* dieses Modul dient nur zum Debuggen !! */
if (argc != 3) {
fprintf(stderr, "usage: nwclient MY_ADDR SERVER_ADDR\n");
exit(1);
}
DPRINTF(("NWCLIENT MYADDR=%s, SERVER=%s \n", *(argv+1), *(argv+2) ));
adr_to_ipx_addr(&my_addr, *(argv+1));
adr_to_ipx_addr(&serv_addr, *(argv+2));
if (init_client()) exit(1);
/* ------------------------------------------ */
get_conn_nr();
get_server_info();
get_pkt_size();
get_connect();
get_server_time();
file_search_init(NULL, 1, NULL);
get_bindery_access();
get_bindery_object_id(1, "SUPERVISOR");
do_17_17();
login_object(1, "SUPERVISOR", NULL);
get_network_serial_number();
get_bindery_access();
scan_bindery_object(1, "*", MAX_U32);
scan_bindery_object(1, "*", 1);
{
uint32 lastid = MAX_U32;
while (!scan_bindery_property(1, "NOBODY", "*", &lastid));;
}
get_volume_restriction_for_obj(1, 0);
test1();
test2();
get_connection_info(0);
get_connection_info(1);
get_connection_info(2);
get_connection_info(3);
send_console_broadcast("Hello Console !!!!");
teste_reads();
test_wdog();
/*-----------------------------------------------*/
t_unbind(fd_ipx);
t_close(fd_ipx);
t_unbind(fd_wdog);
t_close(fd_wdog);
return(0);
}