mars-nwe/src/net1.c

397 lines
12 KiB
C

/* net1.c, 19.09.99 */
/* (C)opyright (C) 1993-99 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"
#define MAX_SEND_TRIES 5
#define MAX_WAIT_MSEC 1000 /* 1 sec should be enough */
#if HAVE_TLI
void print_t_info(struct t_info *t)
{
XDPRINTF((2,0, "T_INFO:addr %ld, options %ld, tsdu %ld, etsdu %ld",
t->addr, t->options,t->tsdu, t->etsdu));
XDPRINTF((2,0, "connect %ld, discon %ld, servtype %ld",
t->connect, t->discon,t->servtype));
#if 0
struct t_info {
long addr; /* size of protocol address */
long options; /* size of protocol options */
long tsdu; /* size of max transport service data unit */
long etsdu; /* size of max expedited tsdu */
long connect; /* max data for connection primitives */
long discon; /* max data for disconnect primitives */
long servtype; /* provider service type */
#endif
}
#endif
char *xvisable_ipx_adr(ipxAddr_t *p, int modus)
{
static char str[200];
if (p) {
if (!modus) {
sprintf(str,"net=%x:%x:%x:%x, node=%x:%x:%x:%x:%x:%x, sock=%02x:%02x",
(int)p->net[0], (int)p->net[1], (int)p->net[2], (int)p->net[3],
(int)p->node[0], (int)p->node[1], (int)p->node[2], (int)p->node[3],
(int)p->node[4], (int)p->node[5], (int)p->sock[0], (int)p->sock[1]);
} else if (modus== 1) {
sprintf(str,"%02X:%02X:%02X:%02X,%02x:%02x:%02x:%02x:%02x:%02x,%02x:%02x",
(int)p->net[0], (int)p->net[1], (int)p->net[2], (int)p->net[3],
(int)p->node[0], (int)p->node[1], (int)p->node[2], (int)p->node[3],
(int)p->node[4], (int)p->node[5], (int)p->sock[0], (int)p->sock[1]);
} else if (modus== 2) {
sprintf(str,"%02x%02x%02x%02x%02x%02x",
(int)p->node[0], (int)p->node[1], (int)p->node[2], (int)p->node[3],
(int)p->node[4], (int)p->node[5]);
} else strcpy(str, "??");
} else
strcpy(str, "net=UNKOWN(NULLPOINTER)");
return(str);
}
void print_ipx_addr(ipxAddr_t *p)
{
XDPRINTF((2,0,"%s", visable_ipx_adr(p)));
}
void print_ud_data(struct t_unitdata *ud)
{
#if DO_DEBUG
int packet_typ = *(int*)(ud->opt.buf);
int data_len = ud->udata.len;
IPX_DATA *ipxdata = (IPX_DATA *)(ud->udata.buf);
XDPRINTF((2,0,"DATA-LEN %d, PACKET-TYPE %d von: %s",
data_len, packet_typ, visable_ipx_adr((ipxAddr_t *)(ud->addr.buf))));
/* hierin steht nun Addresse u. Node des Senders */
if (packet_typ == PACKT_CORE) {
XDPRINTF((2,0, "Query Type 0x%x, Server Type 0x%xd",
GET_BE16(ipxdata->sqp.query_type),
GET_BE16(ipxdata->sqp.server_type)));
} else if (data_len > sizeof(SIP)){
SAP *sap = &(ipxdata->sap);
SAPS *saps = &(ipxdata->sap.saps);
XDPRINTF((2,0, "SAP-OPERATION %d", (int) GET_BE16(sap->sap_operation) ));
while (data_len >= sizeof(SAPS)){
XDPRINTF((2,0, "Name:%s:, typ:0x%x",saps->server_name,
GET_BE16(saps->server_type)));
print_ipx_addr(&(saps->server_adr));
saps++;
data_len -= sizeof(SAPS);
}
} else print_ipx_data(ipxdata);
#endif
}
void print_ipx_data(IPX_DATA *p)
{
print_sip_data(&(p->sip));
}
void print_sip_data(SIP *sip)
{
XDPRINTF((2,0,"Name:%s:,response_type:0x%x,server_typ:0x%x",sip->server_name,
GET_BE16(sip->response_type), GET_BE16(sip->server_type)));
print_ipx_addr(&(sip->server_adr));
}
void adr_to_ipx_addr(ipxAddr_t *p, char *s)
{
int net0, net1, net2, net3;
int node0, node1, node2, node3, node4, node5;
int sock0, sock1;
sscanf(s, "%x.%x.%x.%x:%x.%x.%x.%x.%x.%x:%x.%x",
&net0, &net1, &net2, &net3,
&node0, &node1, &node2, &node3, &node4, &node5,
&sock0, &sock1);
p->net[0] = net0;
p->net[1] = net1;
p->net[2] = net2;
p->net[3] = net3;
p->node[0] = node0;
p->node[1] = node1;
p->node[2] = node2;
p->node[3] = node3;
p->node[4] = node4;
p->node[5] = node5;
p->sock[0] = sock0;
p->sock[1] = sock1;
}
void ipx_addr_to_adr(char *s, ipxAddr_t *p)
{
sprintf(s, "%x.%x.%x.%x:%x.%x.%x.%x.%x.%x:%x.%x",
(int)p->net[0] ,
(int)p->net[1] ,
(int)p->net[2] ,
(int)p->net[3] ,
(int)p->node[0],
(int)p->node[1],
(int)p->node[2],
(int)p->node[3],
(int)p->node[4],
(int)p->node[5],
(int)p->sock[0],
(int)p->sock[1]);
}
int open_ipx_socket(ipxAddr_t *addr, int sock_nr)
{
struct t_bind bind;
ipxAddr_t addr_buff;
int fd=t_open("/dev/ipx", O_RDWR, NULL);
if (fd < 0) {
t_error("t_open !Ok");
return(-1);
}
if (NULL == addr)
addr = &addr_buff;
memset(addr, 0, sizeof(ipxAddr_t));
U16_TO_BE16(sock_nr, addr->sock);
bind.addr.len = sizeof(ipxAddr_t);
bind.addr.maxlen = sizeof(ipxAddr_t);
bind.addr.buf = (char*)addr;
bind.qlen = 0;
if (t_bind(fd, &bind, &bind) < 0){
t_error("t_bind,open_ipx_socket");
t_close(fd);
return(-1);
}
return(fd);
}
int send_ipx_data(int fd, int pack_typ,
int data_len, char *data,
ipxAddr_t *to_addr, char *comment)
{
int fd_is_dyna=0;
int result=0;
struct t_unitdata ud;
uint8 ipx_pack_typ = (uint8) pack_typ;
ud.opt.len = sizeof(ipx_pack_typ);
ud.opt.maxlen = sizeof(ipx_pack_typ);
ud.opt.buf = (char*)&ipx_pack_typ;
ud.addr.len = sizeof(ipxAddr_t);
ud.addr.maxlen = sizeof(ipxAddr_t);
ud.udata.buf = (char*)data;
ud.udata.len = data_len;
ud.udata.maxlen = data_len;
ud.addr.buf = (char*)to_addr;
if (comment != NULL) XDPRINTF((2,0,"%s TO: ", comment));
if (nw_debug > 1) print_ipx_addr(to_addr);
if (fd < 0) {
if ((fd=open_ipx_socket(NULL, 0)) < 0)
return(-1);
fd_is_dyna++;
}
if ((result=t_sndudata(fd, &ud)) < 0){
if (nw_debug > 1) t_error("t_sndudata !OK");
}
if (fd_is_dyna) {
t_unbind(fd);
t_close(fd);
}
return(result);
}
int receive_ipx_data(int fd, int *pack_typ, IPX_DATA *d,
ipxAddr_t *fromaddr, int waitmsec)
{
int result=-1;
if (waitmsec) {
struct pollfd polls[1];
polls[0].fd = fd;
polls[0].events = POLLIN|POLLPRI;
polls[0].revents = 0;
if (1 == poll(polls, 1, waitmsec))
waitmsec=0;
}
if (!waitmsec) {
struct t_unitdata ud;
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; /* gets actual typ */
ud.addr.len = sizeof(ipxAddr_t);
ud.addr.maxlen = sizeof(ipxAddr_t);
ud.addr.buf = (char*)fromaddr;
ud.udata.len = IPX_MAX_DATA;
ud.udata.maxlen = IPX_MAX_DATA;
ud.udata.buf = (char*)d;
if (t_rcvudata(fd, &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; /* get actual typ */
ud.addr.buf = (char*)&fromaddr;
t_rcvuderr(fd, &uderr);
XDPRINTF((2, 0, "Error from %s, Code = 0x%lx", visable_ipx_adr(&erradr), uderr.error));
if (nw_debug)
t_error("t_rcvudata !OK");
result = -1;
} else {
if (pack_typ)
*pack_typ=(int)ipx_pack_typ;
result=ud.udata.len;
}
}
return(result);
}
int send_own_data(int fd, IPX_DATA *d, ipxAddr_t *toaddr)
/* returns < 0 if senderror or functionresultcode > = 0 */
{
static int lastsequence=0;
int tries = 0;
int sendsize = d->owndata.d.size+sizeof(d->owndata.d.size)+
sizeof(d->owndata.h);
d->owndata.h.type[0] = 0xee;
d->owndata.h.type[1] = 0xee;
d->owndata.h.sequence = (uint8) ++lastsequence;
d->owndata.h.reserved = 0;
while (tries++ < MAX_SEND_TRIES) {
int result=send_ipx_data(fd, 17, sendsize, (char*)d,
toaddr, "send_own_data");
while (result > -1) {
int packet_typ;
IPX_DATA ipxd;
ipxAddr_t fromaddr;
result=receive_ipx_data(fd, &packet_typ, &ipxd, &fromaddr,MAX_WAIT_MSEC);
XDPRINTF((2, 0, "receive_ipx_data, result=%d, typ=0x%x%x, sequence=%d",
result,
(int)ipxd.ownreply.type[0],
(int)ipxd.ownreply.type[1],
(int)ipxd.ownreply.sequence ));
if (sizeof(OWN_REPLY) == result
&& ipxd.ownreply.type[0] == 0xef
&& ipxd.ownreply.type[1] == 0xef
&& ipxd.ownreply.sequence == d->owndata.h.sequence)
return((int)ipxd.ownreply.result);
} /* while */
} /* while */
return(-1);
}
int send_own_reply(int fd, int result, int sequence, ipxAddr_t *toaddr)
{
IPX_DATA ipxd;
IPX_DATA *d=&ipxd;
d->ownreply.type[0] = 0xef;
d->ownreply.type[1] = 0xef;
d->ownreply.sequence = (uint8) sequence;
d->ownreply.result = result;
return(send_ipx_data(fd, 17, sizeof(OWN_REPLY),
(char*)d, toaddr, "send_own_reply"));
}
#if 0
int get_ipx_addr(ipxAddr_t *addr)
{
int fd=t_open("/dev/ipx", O_RDWR, NULL);
struct t_optmgmt optb;
int result = -1;
if (fd < 0) {
t_error("t_open !Ok");
return(-1);
}
optb.opt.maxlen = optb.opt.len = sizeof(ipxAddr_t);
optb.opt.buf = (char*)addr;
optb.flags = 0;
result = t_optmgmt(fd, &optb, &optb);
if (result < 0) t_error("t_optmgmt !Ok");
else result=0;
t_close(fd);
return(result);
}
#else
int get_ipx_addr(ipxAddr_t *addr)
{
int fd=t_open("/dev/ipx", O_RDWR, NULL);
struct t_bind bind;
int result = -1;
if (fd < 0) {
t_error("t_open !Ok");
return(-1);
}
bind.addr.len = sizeof(ipxAddr_t);
bind.addr.maxlen = sizeof(ipxAddr_t);
bind.addr.buf = (char*)addr;
bind.qlen = 0; /* ever */
memset(addr, 0, sizeof(ipxAddr_t));
if (t_bind(fd, &bind, &bind) < 0)
t_error("tbind:get_ipx_addr");
else {
result=0;
t_unbind(fd);
}
t_close(fd);
return(result);
}
#endif
uint8 *station_fn=NULL;
int find_station_match(int entry, ipxAddr_t *addr)
{
int matched = 0;
if (station_fn && *station_fn) {
FILE *f=fopen((char*)station_fn, "r");
if (f) {
uint8 buff[200];
uint8 addrstring[100];
int what;
ipx_addr_to_adr((char*)addrstring, addr);
upstr(addrstring);
while (0 != (what = get_ini_entry(f, 0, buff, sizeof(buff)))){
if (what == entry) {
uint8 *p = buff + strlen((char*)buff);
while (p-- > buff && *p==32) *p='\0';
upstr(buff);
if (name_match(addrstring, buff)) {
matched=1;
break;
}
}
}
fclose(f);
} else {
XDPRINTF((3, 0, "find_station_match, cannot open '%s'",
station_fn));
}
}
XDPRINTF((3, 0, "find_station_match entry=%d, matched=%d, addr=%s",
entry, matched, visable_ipx_adr(addr)));
return(matched);
}