mars-nwe/nwserv.c

1507 lines
46 KiB
C
Raw Normal View History

2011-11-13 00:38:58 +01:00
/* nwserv.c 17-Jul-97 */
2011-11-13 00:38:56 +01:00
/* MAIN Prog for NWSERV + NWROUTED */
2011-11-13 00:38:56 +01:00
/* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany
2011-11-13 00:38:55 +01:00
*
* 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"
2011-11-13 00:38:55 +01:00
#include "nwserv.h"
2011-11-13 00:38:55 +01:00
2011-11-13 00:38:56 +01:00
#ifdef LINUX
# include <netdb.h>
#endif
2011-11-13 00:38:55 +01:00
uint32 internal_net = 0x0L; /* NETWORKNUMMER INTERN (SERVER) */
2011-11-13 00:38:56 +01:00
int no_internal = 0; /* no use of internal net */
2011-11-13 00:38:58 +01:00
int auto_detect_interfaces=0;
2011-11-13 00:38:56 +01:00
2011-11-13 00:38:55 +01:00
ipxAddr_t my_server_adr; /* Address of this server */
char my_nwname[50]; /* Name of this server */
int print_route_tac = 0; /* every x broadcasts print it */
int print_route_mode = 0; /* append */
char *pr_route_info_fn = NULL; /* filename */
int wdogs_till_tics = 0; /* send wdogs to all */
2011-11-13 00:38:58 +01:00
time_t acttime_stamp = 0; /* actual received time (second) */
2011-11-13 00:38:55 +01:00
/* <========== DEVICES ==========> */
2011-11-13 00:38:58 +01:00
int count_net_devices=0;
int max_net_devices=0;
NW_NET_DEVICE **net_devices=NULL;
2011-11-13 00:38:55 +01:00
2011-11-13 00:38:57 +01:00
#if !IN_NWROUTED
uint16 ipx_sock_nummern[]={ SOCK_AUTO /* WDOG */
# ifdef EXTERN_SLOT
,SOCK_EXTERN /* Xmarsmon */
# endif
# ifdef PSERVER_SLOT
2011-11-13 00:38:57 +01:00
,SOCK_PSERVER
2011-11-13 00:38:57 +01:00
# endif
2011-11-13 00:38:57 +01:00
2011-11-13 00:38:57 +01:00
# if INTERNAL_RIP_SAP
2011-11-13 00:38:56 +01:00
,SOCK_SAP
2011-11-13 00:38:57 +01:00
# else
2011-11-13 00:38:56 +01:00
,SOCK_AUTO
2011-11-13 00:38:57 +01:00
# endif
#else
uint16 ipx_sock_nummern[]={SOCK_SAP
2011-11-13 00:38:56 +01:00
#endif
#ifdef RIP_SLOT
,SOCK_RIP
#endif
#ifdef ROUTE_SLOT
,SOCK_ROUTE
2011-11-13 00:38:55 +01:00
#endif
2011-11-13 00:38:56 +01:00
#ifdef DIAG_SLOT
,SOCK_DIAGNOSE
#endif
2011-11-13 00:38:55 +01:00
#ifdef ECHO_SLOT
2011-11-13 00:38:56 +01:00
,SOCK_ECHO
2011-11-13 00:38:55 +01:00
#endif
#ifdef ERROR_SLOT
2011-11-13 00:38:56 +01:00
,SOCK_ERROR
2011-11-13 00:38:55 +01:00
#endif
2011-11-13 00:38:55 +01:00
};
2011-11-13 00:38:55 +01:00
#define NEEDED_SOCKETS (sizeof(ipx_sock_nummern) / sizeof(uint16))
2011-11-13 00:38:57 +01:00
2011-11-13 00:38:56 +01:00
#if IN_NWROUTED
2011-11-13 00:38:56 +01:00
# define NEEDED_POLLS (NEEDED_SOCKETS+1)
2011-11-13 00:38:56 +01:00
#else
# define NEEDED_POLLS (NEEDED_SOCKETS+2)
2011-11-13 00:38:56 +01:00
#endif
2011-11-13 00:38:55 +01:00
static uint16 sock_nummern [NEEDED_SOCKETS];
2011-11-13 00:38:55 +01:00
int sockfd [NEEDED_SOCKETS];
2011-11-13 00:38:55 +01:00
static struct pollfd polls[NEEDED_POLLS];
2011-11-13 00:38:56 +01:00
#if 0
2011-11-13 00:38:55 +01:00
static uint16 spx_diag_socket; /* SPX DIAGNOSE SOCKET */
2011-11-13 00:38:56 +01:00
#endif
2011-11-13 00:38:58 +01:00
#if !IN_NWROUTED
2011-11-13 00:38:55 +01:00
static ipxAddr_t nw386_adr; /* Address of NW-TEST Server */
2011-11-13 00:38:56 +01:00
static int nw386_found = 0;
static int client_mode = 0;
2011-11-13 00:38:58 +01:00
#endif
2011-11-13 00:38:55 +01:00
static int ipxdebug = 0;
static int pid_ncpserv = -1;
2011-11-13 00:38:56 +01:00
static int fd_ncpserv_in = -1; /* ctrl-pipe in from ncpserv */
static int pid_nwbind = -1;
2011-11-13 00:38:58 +01:00
#if !IN_NWROUTED
2011-11-13 00:38:56 +01:00
static int sock_nwbind = -1;
2011-11-13 00:38:58 +01:00
#endif
2011-11-13 00:38:56 +01:00
static int fd_nwbind_in = -1; /* ctrl-pipe in from nnwbind */
2011-11-13 00:38:55 +01:00
2011-11-13 00:38:56 +01:00
static int broadmillisecs = 2000; /* 2 sec */
2011-11-13 00:38:55 +01:00
static time_t server_down_stamp = 0;
2011-11-13 00:38:55 +01:00
static int server_goes_down_secs = 10;
2011-11-13 00:38:56 +01:00
static int server_broadcast_secs = 60;
2011-11-13 00:38:58 +01:00
static int ipx_flags = 0;
2011-11-13 00:38:58 +01:00
static int handle_all_sap_typs=HANDLE_ALL_SAP_TYPS;
2011-11-13 00:38:56 +01:00
static int nearest_request_flag=0;
2011-11-13 00:38:56 +01:00
#if IN_NWROUTED
static char *prog_name_typ="ROUTER";
#define IN_PROG NWROUTED
#else
static char *prog_name_typ="SERVER";
#define IN_PROG NWSERV
#endif
2011-11-13 00:38:57 +01:00
#if !IN_NWROUTED
static int ipx_out_fd=-1;
/* next should be '1', is for testing only */
#define USE_PERMANENT_OUT_SOCKET 1
2011-11-13 00:38:56 +01:00
static void add_wdata(IPX_DATA *d, char *data, int size)
{
memcpy(d->owndata.d.data+d->owndata.d.size, data, size);
d->owndata.d.size+=size;
}
2011-11-13 00:38:56 +01:00
static void write_wdata(IPX_DATA *d, int what, int sock)
2011-11-13 00:38:56 +01:00
{
2011-11-13 00:38:57 +01:00
int fd = (ipx_out_fd > -1) ? ipx_out_fd : open_ipx_socket(NULL, 0);
if (fd > -1) {
ipxAddr_t toaddr;
d->owndata.d.function=what;
d->owndata.d.size +=sizeof(int);
memcpy(&toaddr, &my_server_adr, sizeof(ipxAddr_t));
U16_TO_BE16(sock, toaddr.sock);
if (send_own_data(fd, d, &toaddr)) {
errorp(0, "write_wdata", "to %s",
(sock == SOCK_NCP) ? "NCPSERV" : "NWBIND" );
}
d->owndata.d.size=0;
if (ipx_out_fd != fd) {
t_unbind(fd);
t_close(fd);
}
} else {
errorp(0, "write_wdata", "fd not open");
}
2011-11-13 00:38:56 +01:00
}
2011-11-13 00:38:56 +01:00
static void write_to_sons(int what, int connection,
char *data, int data_size, int sock)
2011-11-13 00:38:55 +01:00
{
2011-11-13 00:38:56 +01:00
IPX_DATA ipxd;
ipxd.owndata.d.size = 0;
2011-11-13 00:38:56 +01:00
XDPRINTF((2, 0, "write_to_sons what=0x%x, conn=%d, data_size=%d",
2011-11-13 00:38:55 +01:00
what, connection, data_size));
2011-11-13 00:38:55 +01:00
switch (what) {
2011-11-13 00:38:56 +01:00
case 0x2222 : /* insert connection */
2011-11-13 00:38:56 +01:00
add_wdata(&ipxd, (char*) &connection, sizeof(int));
2011-11-13 00:38:56 +01:00
add_wdata(&ipxd, (char*) &data_size, sizeof(int));
add_wdata(&ipxd, data, data_size);
2011-11-13 00:38:55 +01:00
break;
case 0x3333 : /* 'bindery' calls */
2011-11-13 00:38:56 +01:00
add_wdata(&ipxd, (char*)&data_size, sizeof(int));
add_wdata(&ipxd, data, data_size);
2011-11-13 00:38:55 +01:00
break;
2011-11-13 00:38:56 +01:00
case 0x5555 : /* kill connection */
add_wdata(&ipxd, (char*) &connection, sizeof(int));
break;
2011-11-13 00:38:55 +01:00
case 0xeeee : /* hup, read init */
break;
case 0xffff : /* 'down server' */
2011-11-13 00:38:56 +01:00
add_wdata(&ipxd, (char*) &what, sizeof(int));
2011-11-13 00:38:55 +01:00
break;
2011-11-13 00:38:55 +01:00
2011-11-13 00:38:56 +01:00
default : return;
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:56 +01:00
write_wdata(&ipxd, what, sock);
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:56 +01:00
2011-11-13 00:38:57 +01:00
#define write_to_ncpserv(what, connection, data, data_size) \
2011-11-13 00:38:56 +01:00
write_to_sons((what), (connection), (data), (data_size), SOCK_NCP)
2011-11-13 00:38:55 +01:00
2011-11-13 00:38:56 +01:00
#define write_to_nwbind(what, connection, data, data_size) \
write_to_sons((what), (connection), (data), (data_size), sock_nwbind)
2011-11-13 00:38:56 +01:00
void ins_del_bind_net_addr(uint8 *name, int styp, ipxAddr_t *adr)
2011-11-13 00:38:55 +01:00
{
uint8 buf[1024];
uint8 *p = buf;
int len = 0;
if (NULL != adr) { /* insert */
*p=0x01;
p+=2; len+=2;
2011-11-13 00:38:56 +01:00
U16_TO_BE16(styp, p);
2011-11-13 00:38:55 +01:00
p+=2; len+=2;
2011-11-13 00:38:56 +01:00
*p = strlen((char*)name);
2011-11-13 00:38:55 +01:00
strmaxcpy(p+1, name, *p);
len += (*p+1); p+=(*p + 1);
memcpy(p, adr, sizeof(ipxAddr_t));
len+=sizeof(ipxAddr_t);
} else { /* delete */
*p=0x02;
p+=2; len+=2;
2011-11-13 00:38:56 +01:00
U16_TO_BE16(styp, p);
2011-11-13 00:38:55 +01:00
p+=2; len+=2;
2011-11-13 00:38:56 +01:00
*p = strlen((char*)name);
2011-11-13 00:38:55 +01:00
strmaxcpy(p+1, name, *p);
len += (*p+1); p+=(*p + 1);
}
2011-11-13 00:38:56 +01:00
write_to_nwbind(0x3333, 0, (char *)buf, len);
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:58 +01:00
#else
# define USE_PERMANENT_OUT_SOCKET 0
# define write_to_ncpserv(what, connection, data, data_size) /* */
# define write_to_nwbind(what, connection, data, data_size) /* */
#endif
2011-11-13 00:38:57 +01:00
static int loc_open_ipx_socket(int sock_nr, int nr)
2011-11-13 00:38:55 +01:00
{
2011-11-13 00:38:57 +01:00
int ipx_fd=open_ipx_socket(&my_server_adr, sock_nr);
if (ipx_fd > -1) {
sock_nummern[nr] = GET_BE16(my_server_adr.sock); /* really socket nmbr */
if (nw_debug)
print_ipx_addr(&my_server_adr);
} else
errorp(0, "loc_open_ipx_socket", "nr=%d", sock_nr);
2011-11-13 00:38:55 +01:00
return(ipx_fd);
}
2011-11-13 00:38:57 +01:00
2011-11-13 00:38:55 +01:00
static int start_ncpserv(char *nwname, ipxAddr_t *addr)
{
2011-11-13 00:38:56 +01:00
#if !IN_NWROUTED
2011-11-13 00:38:55 +01:00
int fds_in[2];
int pid;
2011-11-13 00:38:57 +01:00
if (pipe(fds_in) < 0)
return(-1);
2011-11-13 00:38:56 +01:00
2011-11-13 00:38:55 +01:00
switch (pid=fork()) {
case 0 : { /* new Process */
2011-11-13 00:38:55 +01:00
char *progname="ncpserv";
char addrstr[100];
char pathname[300];
2011-11-13 00:38:56 +01:00
char nwbindsock[20];
2011-11-13 00:38:57 +01:00
char echosock[20];
2011-11-13 00:38:55 +01:00
int j = FD_NWSERV;
close(fds_in[0]); /* no need to read */
dup2(fds_in[1], FD_NWSERV); /* becommes fd FD_NWSERV */
close(fds_in[1]); /* no longer needed */
while (j++ < 100) close(j); /* close all > 4 */
2011-11-13 00:38:56 +01:00
U16_TO_BE16(SOCK_NCP, addr->sock);
2011-11-13 00:38:55 +01:00
ipx_addr_to_adr(addrstr, addr);
2011-11-13 00:38:56 +01:00
sprintf(nwbindsock, "%04x", sock_nwbind);
2011-11-13 00:38:57 +01:00
sprintf(echosock, "%04x", sock_nummern[WDOG_SLOT]);
2011-11-13 00:38:55 +01:00
execl(get_exec_path(pathname, progname), progname,
2011-11-13 00:38:57 +01:00
nwname, addrstr, nwbindsock, echosock, NULL);
2011-11-13 00:38:55 +01:00
exit(1);
}
break;
2011-11-13 00:38:55 +01:00
2011-11-13 00:38:56 +01:00
case -1:
2011-11-13 00:38:55 +01:00
close(fds_in[0]);
close(fds_in[1]);
return(-1); /* error */
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:56 +01:00
close(fds_in[1]);
2011-11-13 00:38:55 +01:00
fd_ncpserv_in = fds_in[0];
pid_ncpserv = pid;
2011-11-13 00:38:57 +01:00
sleep(2);
2011-11-13 00:38:56 +01:00
#endif
return(0); /* OK */
}
2011-11-13 00:38:57 +01:00
static int start_nwbind(char *nwname)
2011-11-13 00:38:56 +01:00
{
2011-11-13 00:38:56 +01:00
#if !IN_NWROUTED
2011-11-13 00:38:57 +01:00
int fds_in[2];
int pid;
ipxAddr_t addr;
int ipx_fd=open_ipx_socket(&addr, 0);
2011-11-13 00:38:56 +01:00
if (ipx_fd < 0) {
2011-11-13 00:38:57 +01:00
errorp(1, "start_nwbind", NULL);
2011-11-13 00:38:56 +01:00
return(-1);
}
if (pipe(fds_in) < 0){
errorp(1, "start_nwbind", "pipe");
t_close(ipx_fd);
return(-1);
}
2011-11-13 00:38:57 +01:00
sock_nwbind = (int) GET_BE16(addr.sock);
2011-11-13 00:38:56 +01:00
switch (pid=fork()) {
case 0 : { /* new Process */
char *progname="nwbind";
char addrstr[100];
char pathname[300];
char nwbindsock[20];
int j = FD_NWSERV;
close(fds_in[0]); /* no need to read */
if (fds_in[1] != FD_NWSERV) {
dup2(fds_in[1], FD_NWSERV); /* becommes fd FD_NWSERV */
close(fds_in[1]); /* no longer needed */
}
dup2(ipx_fd, 0); /* stdin */
close(ipx_fd);
while (j++ < 100) close(j); /* close all > FD_NWSERV */
2011-11-13 00:38:57 +01:00
U16_TO_BE16(SOCK_NCP, addr.sock);
ipx_addr_to_adr(addrstr, &addr);
2011-11-13 00:38:56 +01:00
sprintf(nwbindsock, "%04x", sock_nwbind);
execl(get_exec_path(pathname, progname), progname,
nwname, addrstr, nwbindsock, NULL);
exit(1);
}
break;
case -1: close(fds_in[0]);
close(fds_in[1]);
t_close(ipx_fd);
errorp(1, "start_nwbind", "t_bind");
return(-1); /* error */
}
close(fds_in[1]);
close(ipx_fd);
fd_nwbind_in = fds_in[0];
pid_nwbind = pid;
2011-11-13 00:38:57 +01:00
sleep(2);
2011-11-13 00:38:56 +01:00
#endif
2011-11-13 00:38:55 +01:00
return(0); /* OK */
}
2011-11-13 00:38:56 +01:00
#if !IN_NWROUTED
2011-11-13 00:38:55 +01:00
static int start_nwclient(void)
{
switch (fork()){
case 0 : { /* new Process */
2011-11-13 00:38:55 +01:00
char *progname="nwclient";
char pathname[300];
char my_addrstr[100];
char serv_addrstr[100];
ipx_addr_to_adr(my_addrstr, &my_server_adr);
ipx_addr_to_adr(serv_addrstr, &nw386_adr);
execl(get_exec_path(pathname, progname), progname,
my_addrstr, serv_addrstr, NULL);
}
exit(1);
2011-11-13 00:38:55 +01:00
case -1: return(-1); /* error */
}
return(0); /* OK */
}
/* =========================== WDOG =============================== */
2011-11-13 00:38:56 +01:00
#ifndef _WDOG_TESTING_
#define _WDOG_TESTING_ 0
#endif
2011-11-13 00:38:55 +01:00
2011-11-13 00:38:56 +01:00
#if _WDOG_TESTING_
2011-11-13 00:38:55 +01:00
/* for testing */
# define WDOG_TRIE_AFTER_SEC 1
# define MAX_WDOG_TRIES 1
#else
# define WDOG_TRIE_AFTER_SEC 300 /* ca. 5 min. */
# define MAX_WDOG_TRIES 11 /* Standardtries */
#endif
2011-11-13 00:38:55 +01:00
static void modify_wdog_conn(int conn, int mode);
2011-11-13 00:38:55 +01:00
2011-11-13 00:38:55 +01:00
static void send_wdog_packet(ipxAddr_t *addr, int conn, int what)
{
uint8 data[2];
data[0] = (uint8) conn;
data[1] = (uint8) what;
2011-11-13 00:38:55 +01:00
if (what == '?' && dont_send_wdog(addr)) {
modify_wdog_conn(conn, 0);
XDPRINTF((2,0, "No wdog to %s", visable_ipx_adr(addr)));
} else
2011-11-13 00:38:56 +01:00
send_ipx_data(sockfd[WDOG_SLOT], 17, 2, (char*)data, addr, "WDOG");
2011-11-13 00:38:55 +01:00
}
static void send_bcast_packet(ipxAddr_t *addr, int conn, int signature)
{
uint8 data[2];
data[0] = (uint8) conn;
data[1] = (uint8) signature;
/* signatures
* '!' = broadcast waiting inform
* '@' = sft_iii server change over inform.
*/
2011-11-13 00:38:56 +01:00
send_ipx_data(sockfd[WDOG_SLOT], 17, 2, (char*)data, addr, "BCAST");
2011-11-13 00:38:55 +01:00
}
typedef struct {
2011-11-13 00:38:57 +01:00
ipxAddr_t addr; /* address of client */
time_t last_time; /* time of last wdog packet sent */
int counter; /* max. 11 packets */
2011-11-13 00:38:58 +01:00
} CONNECTION;
2011-11-13 00:38:55 +01:00
2011-11-13 00:38:58 +01:00
static int max_connections=MAX_CONNECTIONS;
static CONNECTION *connections=NULL;
2011-11-13 00:38:55 +01:00
static int hi_conn=0; /* highest connection nr in use */
2011-11-13 00:38:55 +01:00
static void insert_wdog_conn(int conn, ipxAddr_t *adr)
{
2011-11-13 00:38:58 +01:00
if (conn > 0 && conn <= max_connections) {
CONNECTION *c;
2011-11-13 00:38:55 +01:00
while (hi_conn < conn) {
2011-11-13 00:38:58 +01:00
c=&(connections[hi_conn++]);
memset(c, 0, sizeof(CONNECTION));
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:58 +01:00
c=&(connections[conn-1]);
2011-11-13 00:38:58 +01:00
c->last_time = acttime_stamp;
2011-11-13 00:38:55 +01:00
c->counter = 0;
if (NULL != adr) memcpy(&(c->addr), adr, sizeof(ipxAddr_t));
}
}
2011-11-13 00:38:55 +01:00
static void modify_wdog_conn(int conn, int mode)
/* mode = 0 : reset */
2011-11-13 00:38:57 +01:00
/* mode = 1 : activate */
2011-11-13 00:38:55 +01:00
/* mode = 99 : remove wdog */
2011-11-13 00:38:55 +01:00
{
if (conn > 0 && --conn < hi_conn) {
2011-11-13 00:38:58 +01:00
CONNECTION *c=&(connections[conn]);
2011-11-13 00:38:55 +01:00
if (mode < 99) {
switch (mode) {
2011-11-13 00:38:57 +01:00
case 1 : /* activate Wdog */
if (!c->counter) c->counter=1;
c->counter = max(c->counter, MAX_WDOG_TRIES-1);
c->last_time = 1;
2011-11-13 00:38:55 +01:00
break;
2011-11-13 00:38:56 +01:00
default : c->counter = 0; /* reset */
2011-11-13 00:38:58 +01:00
c->last_time = acttime_stamp;
2011-11-13 00:38:55 +01:00
break;
2011-11-13 00:38:55 +01:00
} /* switch */
} else if (mode == 99) { /* remove */
2011-11-13 00:38:58 +01:00
memset(c, 0, sizeof(CONNECTION));
2011-11-13 00:38:55 +01:00
if (conn + 1 == hi_conn) {
while (hi_conn) {
2011-11-13 00:38:58 +01:00
c=&(connections[hi_conn-1]);
2011-11-13 00:38:55 +01:00
if (!c->last_time) hi_conn--;
else break;
}
2011-11-13 00:38:55 +01:00
}
}
}
}
2011-11-13 00:38:57 +01:00
static void send_wdogs()
2011-11-13 00:38:55 +01:00
{
int k = hi_conn;
while (k--) {
2011-11-13 00:38:58 +01:00
CONNECTION *c = &(connections[k]);
2011-11-13 00:38:55 +01:00
if (c->last_time) {
2011-11-13 00:38:58 +01:00
time_t t_diff = acttime_stamp - c->last_time;
2011-11-13 00:38:57 +01:00
if ( (c->counter && t_diff > 50)
2011-11-13 00:38:56 +01:00
|| t_diff > WDOG_TRIE_AFTER_SEC) { /* max. 5 minutes */
2011-11-13 00:38:55 +01:00
if (c->counter > MAX_WDOG_TRIES) {
/* now its enough with trying */
/* clear connection */
write_to_ncpserv(0x5555, k+1, NULL, 0);
} else {
ipxAddr_t adr;
2011-11-13 00:38:58 +01:00
c->last_time = acttime_stamp;
2011-11-13 00:38:55 +01:00
memcpy(&adr, &(c->addr), sizeof(ipxAddr_t));
U16_TO_BE16(GET_BE16(adr.sock)+1, adr.sock);
send_wdog_packet(&adr, k+1, '?');
}
c->counter++;
}
}
}
}
static void send_bcasts(int conn)
{
if (conn > 0 && --conn < hi_conn) {
2011-11-13 00:38:58 +01:00
CONNECTION *c = &(connections[conn]);
2011-11-13 00:38:55 +01:00
ipxAddr_t adr;
memcpy(&adr, &(c->addr), sizeof(ipxAddr_t));
U16_TO_BE16(GET_BE16(adr.sock)+2, adr.sock);
send_bcast_packet(&adr, conn+1, '!'); /* notify */
}
}
2011-11-13 00:38:57 +01:00
#endif
2011-11-13 00:38:55 +01:00
void get_server_data(char *name,
ipxAddr_t *adr,
ipxAddr_t *from_addr)
{
2011-11-13 00:38:56 +01:00
#if !IN_NWROUTED
2011-11-13 00:38:55 +01:00
if (!nw386_found && strcmp(name, my_nwname)) {
2011-11-13 00:38:55 +01:00
memcpy(&nw386_adr, adr, sizeof(ipxAddr_t));
nw386_found++;
if (client_mode) {
start_nwclient();
client_mode = 0; /* only start once */
}
}
2011-11-13 00:38:56 +01:00
#endif
2011-11-13 00:38:55 +01:00
XDPRINTF((2,0,"NW386 %s found at:%s", name, visable_ipx_adr(adr)));
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:55 +01:00
static void handle_sap(int fd,
2011-11-13 00:38:55 +01:00
int ipx_pack_typ,
int data_len,
IPX_DATA *ipxdata,
ipxAddr_t *from_addr)
2011-11-13 00:38:55 +01:00
{
2011-11-13 00:38:55 +01:00
int query_type = GET_BE16(ipxdata->sqp.query_type);
int server_type = GET_BE16(ipxdata->sqp.server_type);
2011-11-13 00:38:58 +01:00
int flag=0;
2011-11-13 00:38:56 +01:00
2011-11-13 00:38:55 +01:00
if (query_type == 3) {
2011-11-13 00:38:57 +01:00
XDPRINTF((2,0,"SAP NEAREST SERVER request typ=%d from %s",
2011-11-13 00:38:55 +01:00
server_type, visable_ipx_adr(from_addr)));
2011-11-13 00:38:56 +01:00
/* Get Nearest File Server */
2011-11-13 00:38:56 +01:00
if (!nearest_request_flag)
send_server_response(4, server_type, from_addr);
#if INTERNAL_RIP_SAP
else {
int do_sent = (nearest_request_flag == 1) ? 1 : 0;
if (find_station_match(1, from_addr)) do_sent = !do_sent;
if (do_sent)
send_server_response(4, server_type, from_addr);
XDPRINTF((3,0, "SAP NEAREST REQUEST =%d, nearest_request_flag=%d",
do_sent, nearest_request_flag));
}
#endif
2011-11-13 00:38:55 +01:00
} else if (query_type == 1) { /* general Request */
2011-11-13 00:38:55 +01:00
XDPRINTF((2,0, "SAP GENERAL request server_type =%d", server_type));
2011-11-13 00:38:56 +01:00
send_server_response(2, server_type, from_addr);
2011-11-13 00:38:55 +01:00
} else if (query_type == 2 || query_type == 4) {
/* periodic general or shutdown response (2)
* or nearests Service Response (4)
*/
int entries = (data_len-2) / sizeof(SAPS);
uint8 *p = ((uint8*)ipxdata)+2;
2011-11-13 00:38:55 +01:00
XDPRINTF((2,0,"SAP PERIODIC (entries=%d) from %s", entries, visable_ipx_adr(from_addr)));
2011-11-13 00:38:55 +01:00
while (entries--) {
int type = GET_BE16(p);
uint8 *name = p+2;
ipxAddr_t *ad = (ipxAddr_t*) (p+50);
int hops = GET_BE16(p+ sizeof(SAPS) -2);
2011-11-13 00:38:56 +01:00
/* if (hops < 16) U16_TO_BE16(hops+1, p+ sizeof(SAPS) -2); */
/* if (hops < 16) hops++; */
2011-11-13 00:38:55 +01:00
XDPRINTF((2,0, "TYP=%2d,hops=%2d, Addr=%s, Name=%s", type, hops,
2011-11-13 00:38:55 +01:00
visable_ipx_adr(ad), name));
2011-11-13 00:38:58 +01:00
2011-11-13 00:38:58 +01:00
if (handle_all_sap_typs || type == 4) { /* from Fileserver */
2011-11-13 00:38:55 +01:00
if (16 == hops) {
/* shutdown */
2011-11-13 00:38:55 +01:00
XDPRINTF((2,0, "SERVER %s IS GOING DOWN", name));
2011-11-13 00:38:55 +01:00
insert_delete_server(name, type, NULL, NULL, 16, 1, 0);
2011-11-13 00:38:55 +01:00
} else {
2011-11-13 00:38:56 +01:00
get_server_data((char*)name, ad, from_addr);
2011-11-13 00:38:55 +01:00
insert_delete_server(name, type, ad, from_addr, hops, 0, 0);
2011-11-13 00:38:58 +01:00
if (type == 4) flag=1;
2011-11-13 00:38:55 +01:00
}
}
2011-11-13 00:38:58 +01:00
2011-11-13 00:38:55 +01:00
p+=sizeof(SAPS);
} /* while */
} else {
2011-11-13 00:38:55 +01:00
XDPRINTF((1,0, "UNKNOWN SAP query %x, server %x", query_type, server_type));
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:58 +01:00
#if INTERNAL_RIP_SAP
if (flag) {
uint32 from_net=GET_BE32(from_addr->net);
if (activate_slow_net(from_net))
send_sap_rip_broadcast(4);
}
#endif
2011-11-13 00:38:55 +01:00
}
/*
** Task state constants (IPX Connection States)
**
**
** IPX_TASK_FREE - Task node is currently on the free list
** IPX_TASK_INUSE - Task has been allocated for use
** IPX_TASK_TRANSMIT - Packet has been transmitted (SendPacket)
** IPX_TASK_TIMEDOUT - Task has been disabled due to watchdog or
** retry fail
** IPX_TASK_DYING - Last NCP Response had Bad Connection Status
** Bit (Server Gone or Connection Gone).
** IPX_TASK_CONNECTED - Task is connected by address to the server
** IPX_TASK_BURST - A Packet Burst transaction is in progress
**
*/
#if 0
#define IPX_TASK_FREE 0 /* Not in use */
#define IPX_TASK_INUSE (1<<0) /* In use */
#define IPX_TASK_TRANSMIT (1<<1) /* Packet on the wire */
#define IPX_TASK_TIMEDOUT (1<<2) /* Connection is timed out */
#define IPX_TASK_DYING (1<<3) /* Connection no longer valid */
#define IPX_TASK_CONNECTED (1<<4) /* Connection in place */
#define IPX_TASK_BURST (1<<5) /* Packet Burst in progress */
#define CONN_STATUS_BAD_CONNECTION 0x01
#define CONN_STATUS_NO_SLOTS_AVAIL 0x04
#define CONN_STATUS_SERVER_DOWN 0x10
#define CONN_STATUS_MESSSAGE_WAITING 0x01
#endif
2011-11-13 00:38:56 +01:00
#ifdef DIAG_SLOT
2011-11-13 00:38:55 +01:00
static void response_ipx_diag(int fd, int ipx_pack_typ,
2011-11-13 00:38:55 +01:00
ipxAddr_t *to_addr)
2011-11-13 00:38:55 +01:00
{
IPX_DATA ipxdata;
DIAGRESP *dia = &ipxdata.diaresp;
uint8 *p = (uint8*) (dia+1);
int datalen = sizeof(DIAGRESP); /* erstmal */
dia->majorversion = 1;
dia->minorversion = 1;
U16_TO_BE16(spx_diag_socket, dia->spx_diag_sock);
dia->anz = 3;
*p++ = 0; /* IPX/SPX */
datalen++;
*p++ = 1; /* Bridge Driver */
datalen++;
2011-11-13 00:38:55 +01:00
/* now extended */
2011-11-13 00:38:55 +01:00
*p++ = 6; /* Fileserver/Bridge (internal) */
datalen++;
*p++ = 1; /* Anz. Networks */
datalen++;
*p++ = 0; /* LAN BOARD */
datalen++;
memcpy(p, my_server_adr.net, IPX_NET_SIZE);
p += IPX_NET_SIZE;
datalen += IPX_NET_SIZE;
memcpy(p, my_server_adr.node, IPX_NODE_SIZE);
datalen += IPX_NODE_SIZE;
send_ipx_data(fd, ipx_pack_typ,
2011-11-13 00:38:55 +01:00
datalen,
(char*)&ipxdata,
to_addr, "DIAG Response");
2011-11-13 00:38:55 +01:00
}
static void handle_diag(int fd, int ipx_pack_typ,
2011-11-13 00:38:55 +01:00
int data_len, IPX_DATA *ipxdata,
ipxAddr_t *from_addr)
2011-11-13 00:38:55 +01:00
/* should handle CONFIGURATION REQUESTS one time */
{
CONFREQ *conf = &(ipxdata->confreq);
int count = (int) conf->count;
int j = count;
uint8 *exnodes = conf->ex_node;
while (j--) {
if IPXCMPNODE(exnodes, my_server_adr.node) {
2011-11-13 00:38:55 +01:00
XDPRINTF((2, 0, "NO RESPONSE TO DIAG"));
2011-11-13 00:38:55 +01:00
return;
}
exnodes += IPX_NODE_SIZE;
}
2011-11-13 00:38:55 +01:00
XDPRINTF((2,0,"DIAG Request, ipx_pack_typ %d, data_len %d, count %d",
2011-11-13 00:38:55 +01:00
(int)ipx_pack_typ, data_len, count));
2011-11-13 00:38:55 +01:00
response_ipx_diag(fd, ipx_pack_typ, from_addr);
}
2011-11-13 00:38:56 +01:00
#endif
2011-11-13 00:38:55 +01:00
2011-11-13 00:38:57 +01:00
#ifdef EXTERN_SLOT
ipxAddr_t auth_addr;
int is_auth=0;
static void handle_extern_call(int fd,
int ipx_pack_typ,
int data_len,
IPX_DATA *ipxdata,
ipxAddr_t *from_addr)
{
if (memcmp(&auth_addr, from_addr, sizeof(ipxAddr_t))){
memcpy(&auth_addr, from_addr, sizeof(ipxAddr_t));
is_auth=0;
}
}
#endif
2011-11-13 00:38:55 +01:00
static void handle_event(int fd, uint16 socknr, int slot)
{
struct t_unitdata ud;
ipxAddr_t source_adr;
uint8 ipx_pack_typ;
IPX_DATA ipx_data_buff;
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*)&source_adr;
ud.udata.len = IPX_MAX_DATA;
ud.udata.maxlen = IPX_MAX_DATA;
ud.udata.buf = (char*)&ipx_data_buff;
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*)&source_adr;
t_rcvuderr(fd, &uderr);
2011-11-13 00:38:55 +01:00
XDPRINTF((2, 0, "Error from %s, Code = 0x%lx", visable_ipx_adr(&erradr), uderr.error));
2011-11-13 00:38:55 +01:00
if (nw_debug) t_error("t_rcvudata !OK");
2011-11-13 00:38:55 +01:00
return;
}
2011-11-13 00:38:55 +01:00
XDPRINTF((3,0,"Ptyp:%d from: %s", (int)ipx_pack_typ, visable_ipx_adr(&source_adr) ));
2011-11-13 00:38:55 +01:00
if (server_down_stamp) return; /* no more interests */
2011-11-13 00:38:56 +01:00
#if INTERNAL_RIP_SAP
2011-11-13 00:38:55 +01:00
if ( IPXCMPNODE(source_adr.node, my_server_adr.node) &&
IPXCMPNET (source_adr.net, my_server_adr.net)) {
2011-11-13 00:38:55 +01:00
int source_sock = (int) GET_BE16(source_adr.sock);
2011-11-13 00:38:57 +01:00
if (
#if !IN_NWROUTED
source_sock == sock_nummern[WDOG_SLOT] ||
#endif
source_sock == SOCK_SAP
2011-11-13 00:38:55 +01:00
|| source_sock == SOCK_RIP) {
2011-11-13 00:38:55 +01:00
XDPRINTF((2,0,"OWN Packet from sock:0x%04x, ignored", source_sock));
2011-11-13 00:38:55 +01:00
return;
}
2011-11-13 00:38:55 +01:00
2011-11-13 00:38:55 +01:00
/* it also can be Packets from DOSEMU OR ncpfs on this machine */
2011-11-13 00:38:55 +01:00
XDPRINTF((2,0,"Packet from OWN maschine:sock=0x%x", source_sock));
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:58 +01:00
if (auto_detect_interfaces && test_ins_device_net(GET_BE32(source_adr.net)))
2011-11-13 00:38:56 +01:00
broadmillisecs = 3000; /* now faster rip/sap to new devices */
2011-11-13 00:38:56 +01:00
#endif
2011-11-13 00:38:55 +01:00
2011-11-13 00:38:56 +01:00
switch (slot) {
2011-11-13 00:38:57 +01:00
#ifdef WDOG_SLOT
case WDOG_SLOT :
if (2 == ud.udata.len) {
XDPRINTF((2,0, "WDOG Packet len=%d connid=%d, status=%d",
(int)ud.udata.len, (int) ipx_data_buff.wdog.connid,
(int)ipx_data_buff.wdog.status));
2011-11-13 00:38:58 +01:00
if ('Y' == ipx_data_buff.wdog.status) {
if (max_connections < 256)
modify_wdog_conn(ipx_data_buff.wdog.connid, 0);
else {
int k=-1;
while (++k < hi_conn) {
CONNECTION *c=&(connections[k]);
if (IPXCMPNODE(c->addr.node, source_adr.node)){
modify_wdog_conn(k+1, 0);
break;
}
}
}
}
2011-11-13 00:38:57 +01:00
} else if ( 2 < ud.udata.len
&& ipx_data_buff.data[0] == 0x11
&& ipx_data_buff.data[1] == 0x11 ) {
/* now we make an echo of this data */
send_ipx_data(sockfd[WDOG_SLOT],
17, ud.udata.len, ud.udata.buf, &source_adr, "ECHO");
2011-11-13 00:38:58 +01:00
} else {
uint8 *p = (uint8*)&ipx_data_buff;
int k = 0;
XDPRINTF((1, 2, "UNKNOWN from WDOG sock"));
while (k++ < ud.udata.len){
XDPRINTF((1, 3, " %x", (int) *p++));
}
XDPRINTF((1, 1, NULL));
2011-11-13 00:38:57 +01:00
}
break;
#endif
#ifdef EXTERN_SLOT
case EXTERN_SLOT : handle_extern_call(fd, (int) ipx_pack_typ, ud.udata.len, &ipx_data_buff, &source_adr); break;
#endif
2011-11-13 00:38:56 +01:00
case SAP_SLOT : handle_sap( fd, (int) ipx_pack_typ, ud.udata.len, &ipx_data_buff, &source_adr); break;
#ifdef RIP_SLOT
case RIP_SLOT : handle_rip( fd, (int) ipx_pack_typ, ud.udata.len, &ipx_data_buff, &source_adr); break;
#endif
#ifdef DIAG_SLOT
case DIAG_SLOT : handle_diag(fd, (int) ipx_pack_typ, ud.udata.len, &ipx_data_buff, &source_adr); break;
#endif
2011-11-13 00:38:55 +01:00
2011-11-13 00:38:58 +01:00
default :
#if DO_DEBUG
{
2011-11-13 00:38:55 +01:00
uint8 *p = (uint8*)&ipx_data_buff;
int k = 0;
2011-11-13 00:38:55 +01:00
XDPRINTF((1, 2, "UNKNOWN"));
2011-11-13 00:38:55 +01:00
while (k++ < ud.udata.len){
2011-11-13 00:38:55 +01:00
XDPRINTF((1, 3, " %x", (int) *p++));
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:55 +01:00
XDPRINTF((1, 1, NULL));
2011-11-13 00:38:55 +01:00
/*
print_ud_data(&ud);
*/
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:58 +01:00
#endif
2011-11-13 00:38:55 +01:00
break;
2011-11-13 00:38:55 +01:00
}
}
2011-11-13 00:38:55 +01:00
static void get_ini(int full)
2011-11-13 00:38:55 +01:00
{
2011-11-13 00:38:55 +01:00
FILE *f = open_nw_ini();
int k;
uint32 node = 1; /* default 1 */
if (full) {
gethostname(my_nwname, 48);
2011-11-13 00:38:56 +01:00
upstr((uint8*)my_nwname);
2011-11-13 00:38:55 +01:00
}
if (f){
2011-11-13 00:38:56 +01:00
uint8 buff[500];
2011-11-13 00:38:55 +01:00
int what;
2011-11-13 00:38:56 +01:00
while (0 != (what=get_ini_entry(f, 0, buff, sizeof(buff)))) {
2011-11-13 00:38:55 +01:00
char inhalt[500];
char inhalt2[500];
char inhalt3[500];
2011-11-13 00:38:55 +01:00
char inhalt4[500];
2011-11-13 00:38:55 +01:00
char dummy;
int anz;
2011-11-13 00:38:55 +01:00
if ((anz=sscanf((char*)buff, "%s %s %s %s", inhalt, inhalt2,
inhalt3, inhalt4)) > 0) {
2011-11-13 00:38:55 +01:00
switch (what) {
2011-11-13 00:38:55 +01:00
case 2 : if (full) {
strncpy(my_nwname, inhalt, 48);
my_nwname[47] = '\0';
2011-11-13 00:38:56 +01:00
upstr((uint8*)my_nwname);
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:55 +01:00
break;
2011-11-13 00:38:56 +01:00
#if INTERNAL_RIP_SAP
2011-11-13 00:38:57 +01:00
case 3 : if (full) {
2011-11-13 00:38:56 +01:00
upstr(inhalt);
if (!strcmp(inhalt, "AUTO")) internal_net = 0;
else {
if (sscanf(inhalt, "%ld%c", &internal_net, &dummy) != 1)
sscanf(inhalt, "%lx", &internal_net);
}
2011-11-13 00:38:55 +01:00
if (anz > 1) {
if (sscanf(inhalt2, "%ld%c", &node, &dummy) != 1)
sscanf(inhalt2, "%lx", &node);
}
2011-11-13 00:38:56 +01:00
if (0 == internal_net) { /* now we try ip number */
char locname[50];
struct hostent *hent;
gethostname(locname, 48);
hent=gethostbyname(locname);
if (NULL != hent && hent->h_length == 4) {
internal_net = GET_BE32(*(hent->h_addr_list));
} else {
2011-11-13 00:38:57 +01:00
errorp(10, "Get_ini", "Cannot gethostbyname from '%s'",
locname);
2011-11-13 00:38:56 +01:00
if (hent) {
XDPRINTF((0, 0, "hent->h_length=%d", hent->h_length));
}
}
2011-11-13 00:38:57 +01:00
if (0==internal_net)
errorp(11, "Get_ini", "Cannot get AUTO internal net with help of gethostbyname");
2011-11-13 00:38:56 +01:00
}
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:55 +01:00
break;
2011-11-13 00:38:58 +01:00
case 4 : if (full && ( (!count_net_devices) || anz > 2) ) {
NW_NET_DEVICE **pnd;
NW_NET_DEVICE *nd;
if (count_net_devices >= max_net_devices)
realloc_net_devices();
pnd=&(net_devices[count_net_devices++]);
nd=*pnd=(NW_NET_DEVICE*)
xcmalloc(sizeof(NW_NET_DEVICE));
nd->ticks = 1;
nd->frame = IPX_FRAME_8023;
new_str(nd->devname, "eth0");
if (sscanf(inhalt, "%ld%c", &nd->net, &dummy) != 1)
sscanf(inhalt, "%lx", &nd->net);
2011-11-13 00:38:56 +01:00
2011-11-13 00:38:58 +01:00
if (nd->net && (nd->net == internal_net)) {
errorp(11, "Get_ini", "device net 0x%lx = internal net", nd->net);
exit(1);
}
if (anz > 1)
new_str(nd->devname, inhalt2);
if (anz > 2) {
upstr(inhalt3);
if (!strcmp(inhalt3, "AUTO"))
nd->frame=-1;
if (!strcmp(inhalt3, "802.3"))
nd->frame=IPX_FRAME_8023;
else if (!strcmp(inhalt3, "802.2"))
nd->frame=IPX_FRAME_8022;
else if (!strcmp(inhalt3, "SNAP"))
nd->frame=IPX_FRAME_SNAP;
else if (!strcmp(inhalt3, "ETHERNET_II"))
nd->frame=IPX_FRAME_ETHERII;
2011-11-13 00:38:56 +01:00
# ifdef IPX_FRAME_TR_8022
2011-11-13 00:38:58 +01:00
else if (!strcmp(inhalt3, "TOKEN"))
nd->frame=IPX_FRAME_TR_8022;
2011-11-13 00:38:56 +01:00
# endif
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:58 +01:00
if (anz > 3) nd->ticks = atoi(inhalt4);
2011-11-13 00:38:55 +01:00
}
break;
2011-11-13 00:38:56 +01:00
2011-11-13 00:38:58 +01:00
case 5 : ipx_flags=hextoi(inhalt);
2011-11-13 00:38:55 +01:00
break;
2011-11-13 00:38:55 +01:00
#endif
2011-11-13 00:38:56 +01:00
2011-11-13 00:38:58 +01:00
case 69 : handle_all_sap_typs=atoi(inhalt);
break;
2011-11-13 00:38:56 +01:00
#if !IN_NWROUTED
2011-11-13 00:38:58 +01:00
case 60 : if (full) { /* connections */
max_connections=atoi(inhalt);
2011-11-13 00:38:58 +01:00
if (max_connections < 1)
2011-11-13 00:38:58 +01:00
max_connections=MAX_CONNECTIONS;
}
break;
2011-11-13 00:38:55 +01:00
case 104 : /* nwclient */
if (client_mode && atoi(inhalt))
client_mode++;
break;
2011-11-13 00:38:56 +01:00
#endif
2011-11-13 00:38:55 +01:00
case 210 : server_goes_down_secs=atoi(inhalt);
if (server_goes_down_secs < 1 ||
server_goes_down_secs > 600)
server_goes_down_secs = 10;
break;
2011-11-13 00:38:55 +01:00
2011-11-13 00:38:56 +01:00
case 211 : server_broadcast_secs=atoi(inhalt);
if (server_broadcast_secs < 10 ||
server_broadcast_secs > 600)
server_broadcast_secs = 60;
break;
2011-11-13 00:38:55 +01:00
case 300 : print_route_tac=atoi(inhalt);
break;
2011-11-13 00:38:56 +01:00
case 301 : new_str(pr_route_info_fn, (uint8*)inhalt);
2011-11-13 00:38:55 +01:00
break;
2011-11-13 00:38:57 +01:00
case 302 : print_route_mode=hextoi(inhalt);
2011-11-13 00:38:55 +01:00
break;
case 310 : wdogs_till_tics=atoi(inhalt);
break;
2011-11-13 00:38:56 +01:00
case 400 : new_str(station_fn, (uint8*)inhalt);
break;
case 401 : nearest_request_flag=atoi(inhalt);
break;
2011-11-13 00:38:55 +01:00
default : break;
} /* switch */
} /* if */
} /* while */
fclose(f);
}
2011-11-13 00:38:58 +01:00
#if !IN_NWROUTED
2011-11-13 00:38:55 +01:00
if (client_mode < 2) client_mode=0;
2011-11-13 00:38:58 +01:00
#endif
2011-11-13 00:38:55 +01:00
if (print_route_tac && !pr_route_info_fn && !*pr_route_info_fn)
print_route_tac = 0;
if (!print_route_tac) xfree(pr_route_info_fn);
2011-11-13 00:38:56 +01:00
#if INTERNAL_RIP_SAP
server_broadcast_secs /= 2;
#endif
2011-11-13 00:38:55 +01:00
if (full) {
2011-11-13 00:38:55 +01:00
#ifdef LINUX
2011-11-13 00:38:56 +01:00
# if INTERNAL_RIP_SAP
2011-11-13 00:38:56 +01:00
no_internal = !internal_net;
2011-11-13 00:38:58 +01:00
if (no_internal && count_net_devices > 1) {
2011-11-13 00:38:56 +01:00
errorp(11, "Get_ini", "No internal net, but more than 1 Device specified");
exit(1);
}
2011-11-13 00:38:58 +01:00
init_ipx(internal_net, node, ipxdebug, ipx_flags);
2011-11-13 00:38:58 +01:00
for (k=0; k < count_net_devices; k++){
2011-11-13 00:38:55 +01:00
NW_NET_DEVICE *nd=net_devices[k];
2011-11-13 00:38:56 +01:00
int result;
uint8 frname[30];
char *sp = "DEVICE=%s, FRAME=%s, NETWORK=0x%lx";
(void) get_frame_name(frname, nd->frame);
XDPRINTF((1, 0, sp, nd->devname, frname, nd->net));
2011-11-13 00:38:58 +01:00
if (nd->devname[0] == '*') nd->wildmask|=1;
if (nd->frame < 0) nd->wildmask|=2;
if (!nd->net) nd->wildmask|=4;
if ((result=init_dev(nd->devname, nd->frame, nd->net, nd->wildmask)) < 0) {
2011-11-13 00:38:56 +01:00
if (result == -99) {
errorp(11, "init_dev", "AUTO device is only in combination with internal net allowed");
exit(1);
} else
errorp(1, "init_dev", sp, nd->devname, frname, nd->net);
2011-11-13 00:38:58 +01:00
} else if (!result) {
2011-11-13 00:38:56 +01:00
nd->is_up = 1;
2011-11-13 00:38:58 +01:00
} else
auto_detect_interfaces=1;
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:56 +01:00
# endif
2011-11-13 00:38:55 +01:00
#endif
2011-11-13 00:38:56 +01:00
2011-11-13 00:38:55 +01:00
if (!get_ipx_addr(&my_server_adr)) {
internal_net = GET_BE32(my_server_adr.net);
2011-11-13 00:38:58 +01:00
} else {
errorp(1, "No ipx-router running !", NULL);
exit(1);
}
2011-11-13 00:38:56 +01:00
#if INTERNAL_RIP_SAP
2011-11-13 00:38:56 +01:00
if (no_internal) {
errorp(10, "WARNING:No use of internal net", NULL);
2011-11-13 00:38:58 +01:00
} else if (!count_net_devices) {
2011-11-13 00:38:56 +01:00
errorp(10, "WARNING:No external devices specified", NULL);
}
2011-11-13 00:38:57 +01:00
print_routing_info(1);
2011-11-13 00:38:56 +01:00
#endif
XDPRINTF((1, 0, "%s name='%s', INTERNAL NET=0x%lx, NODE=0x%02x:%02x:%02x:%02x:%02x:%02x",
prog_name_typ, my_nwname, internal_net,
2011-11-13 00:38:55 +01:00
(int)my_server_adr.node[0],
(int)my_server_adr.node[1],
(int)my_server_adr.node[2],
(int)my_server_adr.node[3],
(int)my_server_adr.node[4],
(int)my_server_adr.node[5]));
} /* if full */
2011-11-13 00:38:55 +01:00
}
static void send_down_broadcast(void)
{
2011-11-13 00:38:55 +01:00
send_sap_rip_broadcast(2);
2011-11-13 00:38:55 +01:00
}
static void close_all(void)
{
int j = NEEDED_SOCKETS;
2011-11-13 00:38:57 +01:00
#if USE_PERMANENT_OUT_SOCKET
if (ipx_out_fd > -1) {
t_unbind(ipx_out_fd);
t_close(ipx_out_fd);
}
#endif
2011-11-13 00:38:55 +01:00
while (j--) {
t_unbind(sockfd[j]);
t_close(sockfd[j]);
}
2011-11-13 00:38:55 +01:00
if (pid_ncpserv > 0) {
int status;
if (fd_ncpserv_in > -1) {
close(fd_ncpserv_in);
fd_ncpserv_in = -1;
}
2011-11-13 00:38:56 +01:00
kill(pid_ncpserv, SIGQUIT); /* terminate ncpserv */
2011-11-13 00:38:55 +01:00
waitpid(pid_ncpserv, &status, 0);
kill(pid_ncpserv, SIGKILL); /* kill ncpserv */
}
2011-11-13 00:38:56 +01:00
if (pid_nwbind > 0) {
int status;
if (fd_nwbind_in > -1) {
close(fd_nwbind_in);
fd_nwbind_in = -1;
}
2011-11-13 00:38:56 +01:00
kill(pid_nwbind, SIGQUIT); /* terminate nwbind */
2011-11-13 00:38:56 +01:00
waitpid(pid_nwbind, &status, 0);
2011-11-13 00:38:56 +01:00
kill(pid_nwbind, SIGKILL); /* kill nwbind */
2011-11-13 00:38:56 +01:00
}
2011-11-13 00:38:55 +01:00
#ifdef LINUX
2011-11-13 00:38:56 +01:00
# if INTERNAL_RIP_SAP
2011-11-13 00:38:58 +01:00
#if 0
if (!(ipx_flags&1)) {
2011-11-13 00:38:58 +01:00
for (j=0; j<count_net_devices;j++) {
2011-11-13 00:38:55 +01:00
NW_NET_DEVICE *nd=net_devices[j];
2011-11-13 00:38:56 +01:00
if (nd->is_up) {
XDPRINTF((1, 0, "Close Device=%s, frame=%d",
2011-11-13 00:38:55 +01:00
nd->devname, nd->frame));
2011-11-13 00:38:56 +01:00
exit_dev(nd->devname, nd->frame);
}
2011-11-13 00:38:55 +01:00
}
}
2011-11-13 00:38:58 +01:00
#endif
exit_ipx(ipx_flags);
2011-11-13 00:38:56 +01:00
# endif
2011-11-13 00:38:55 +01:00
#endif
2011-11-13 00:38:55 +01:00
}
static void down_server(void)
{
if (!server_down_stamp) {
signal(SIGHUP, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
2011-11-13 00:38:57 +01:00
write_to_ncpserv(0xffff, 0, NULL, 0);
write_to_nwbind( 0xffff, 0, NULL, 0);
2011-11-13 00:38:55 +01:00
fprintf(stderr, "\007");
fprintf(stderr, "\n*********************************************\n");
2011-11-13 00:38:56 +01:00
fprintf(stderr, "\nWARNING: NWE-%s shuts down in %3d sec !!!\n",
prog_name_typ, server_goes_down_secs);
2011-11-13 00:38:55 +01:00
fprintf(stderr, "\n*********************************************\n");
sleep(1);
fprintf(stderr, "\007\n");
2011-11-13 00:38:56 +01:00
broadmillisecs = 100;
2011-11-13 00:38:58 +01:00
server_down_stamp = acttime_stamp;
2011-11-13 00:38:55 +01:00
send_down_broadcast();
}
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:57 +01:00
#if !IN_NWROUTED
static int fl_got_sigchld=0;
static void sig_chld(int rsig)
{
fl_got_sigchld++;
}
#endif
2011-11-13 00:38:55 +01:00
static int fl_get_int=0;
2011-11-13 00:38:55 +01:00
static void sig_quit(int rsig)
{
2011-11-13 00:38:55 +01:00
signal(rsig, SIG_IGN);
signal(SIGHUP, SIG_IGN); /* don't want it anymore */
2011-11-13 00:38:56 +01:00
XDPRINTF((2, 0, "Got Signal=%d", rsig));
2011-11-13 00:38:58 +01:00
fl_get_int|=2;
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:55 +01:00
static void handle_hup_reqest(void)
2011-11-13 00:38:55 +01:00
{
2011-11-13 00:38:56 +01:00
get_ini_debug(IN_PROG);
2011-11-13 00:38:55 +01:00
XDPRINTF((2,0, "Got HUP, reading ini."));
2011-11-13 00:38:55 +01:00
get_ini(0);
write_to_ncpserv(0xeeee, 0, NULL, 0); /* inform ncpserv */
2011-11-13 00:38:56 +01:00
write_to_nwbind( 0xeeee, 0, NULL, 0); /* inform nwbind */
2011-11-13 00:38:57 +01:00
send_sap_rip_broadcast(1); /* firsttime broadcast */
2011-11-13 00:38:55 +01:00
}
static void sig_hup(int rsig)
{
2011-11-13 00:38:58 +01:00
fl_get_int|=1;
2011-11-13 00:38:55 +01:00
signal(SIGHUP, sig_hup);
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:58 +01:00
static void handle_usr1_request(void)
{
XDPRINTF((2,0, "Got USR1, update internal devices/routes"));
send_sap_rip_broadcast(3);
}
static void sig_usr1(int rsig)
{
fl_get_int|=4;
signal(rsig, sig_usr1);
}
static void set_sigs(int mode)
2011-11-13 00:38:55 +01:00
{
signal(SIGPIPE, SIG_IGN);
2011-11-13 00:38:58 +01:00
if (!mode) {
signal(SIGTERM, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
signal(SIGINT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGUSR1, SIG_IGN);
} else {
signal(SIGTERM, sig_quit);
signal(SIGQUIT, sig_quit);
signal(SIGINT, sig_quit);
signal(SIGHUP, sig_hup);
signal(SIGUSR1, sig_usr1);
}
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:56 +01:00
static int server_is_down=0;
2011-11-13 00:38:56 +01:00
static int usage(char *prog)
{
#if !IN_NWROUTED
2011-11-13 00:38:58 +01:00
fprintf(stderr, "usage:\t%s [-V|-h|-u|-k|y]\n", prog);
2011-11-13 00:38:56 +01:00
#else
2011-11-13 00:38:58 +01:00
fprintf(stderr, "usage:\t%s [-v|-h|-u|-k]\n", prog);
2011-11-13 00:38:56 +01:00
#endif
2011-11-13 00:38:58 +01:00
fprintf(stderr, "\t-V: print version\n");
2011-11-13 00:38:56 +01:00
fprintf(stderr, "\t-h: send HUP to main process\n");
2011-11-13 00:38:58 +01:00
fprintf(stderr, "\t-u: update int. routing table\n");
2011-11-13 00:38:56 +01:00
fprintf(stderr, "\t-k: stop main process\n");
#if !IN_NWROUTED
fprintf(stderr, "\t y: start testclient code.\n");
#endif
return(1);
}
2011-11-13 00:38:55 +01:00
int main(int argc, char **argv)
{
2011-11-13 00:38:56 +01:00
int j = 0;
int init_mode=0;
2011-11-13 00:38:57 +01:00
if (seteuid(0) < 0 || setuid(0) < 0) {
fprintf(stderr, "You must have root permission !\n");
exit(1);
}
2011-11-13 00:38:55 +01:00
tzset();
2011-11-13 00:38:56 +01:00
while (++j < argc) {
char *a=argv[j];
if (*a == '-') {
while (*(++a)) {
switch (*a) {
case 'h' : init_mode = 1; break;
case 'k' : init_mode = 2; break;
2011-11-13 00:38:58 +01:00
case 'u' : init_mode = 3; break;
case 'v' :
case 'V' : fprintf(stderr, "\n%s:Version %d.%d.pl%d\n",
2011-11-13 00:38:58 +01:00
argv[0], _VERS_H_, _VERS_L_, _VERS_P_ );
return(0);
2011-11-13 00:38:56 +01:00
default : return(usage(argv[0]));
2011-11-13 00:38:56 +01:00
}
}
2011-11-13 00:38:58 +01:00
}
#if !IN_NWROUTED
else if (*a == 'y')
2011-11-13 00:38:56 +01:00
client_mode=1;
2011-11-13 00:38:55 +01:00
/* in client mode the testprog 'nwclient' will be startet. */
2011-11-13 00:38:58 +01:00
#endif
2011-11-13 00:38:56 +01:00
else
return(usage(argv[0]));
2011-11-13 00:38:56 +01:00
}
2011-11-13 00:38:57 +01:00
#if !DO_TESTING
chdir("/");
#endif
2011-11-13 00:38:56 +01:00
setgroups(0, NULL);
2011-11-13 00:38:56 +01:00
init_tools(IN_PROG, init_mode);
2011-11-13 00:38:58 +01:00
set_sigs(0);
2011-11-13 00:38:55 +01:00
get_ini(1);
2011-11-13 00:38:58 +01:00
#if !IN_NWROUTED
2011-11-13 00:38:58 +01:00
if (max_connections < 1)
max_connections=1;
2011-11-13 00:38:58 +01:00
connections=(CONNECTION*)xcmalloc(max_connections*sizeof(CONNECTION));
#endif
2011-11-13 00:38:56 +01:00
j=-1;
2011-11-13 00:38:55 +01:00
while (++j < NEEDED_POLLS) {
polls[j].events = POLLIN|POLLPRI;
polls[j].revents = 0;
if (j < NEEDED_SOCKETS) {
2011-11-13 00:38:57 +01:00
int fd = loc_open_ipx_socket(ipx_sock_nummern[j], j);
2011-11-13 00:38:55 +01:00
if (fd < 0) {
while (j--) {
2011-11-13 00:38:55 +01:00
t_unbind(sockfd[j]);
t_close(sockfd[j]);
2011-11-13 00:38:55 +01:00
}
return(1);
} else {
sockfd[j] = fd;
polls[j].fd = fd;
}
} else {
polls[j].fd = -1;
}
}
2011-11-13 00:38:57 +01:00
2011-11-13 00:38:57 +01:00
#if USE_PERMANENT_OUT_SOCKET
ipx_out_fd=open_ipx_socket(NULL, 0);
#endif
2011-11-13 00:38:57 +01:00
#if !IN_NWROUTED
2011-11-13 00:38:57 +01:00
XDPRINTF((1, 0, "USE_PERMANENT_OUT_SOCKET %s",
(ipx_out_fd > -1) ? "enabled" : "disabled"));
XDPRINTF((1, 0, "IPX_MAX_DATA=%d, RW_BUFFERSIZE =%d",
IPX_MAX_DATA, RW_BUFFERSIZE));
2011-11-13 00:38:57 +01:00
signal(SIGCHLD, sig_chld);
#endif
2011-11-13 00:38:57 +01:00
if ( !start_nwbind(my_nwname)
2011-11-13 00:38:56 +01:00
&& !start_ncpserv(my_nwname, &my_server_adr) ) {
2011-11-13 00:38:55 +01:00
/* now do polling */
2011-11-13 00:38:55 +01:00
time_t broadtime;
time(&broadtime);
2011-11-13 00:38:58 +01:00
set_sigs(1);
2011-11-13 00:38:56 +01:00
polls[NEEDED_SOCKETS].fd = fd_nwbind_in;
2011-11-13 00:38:56 +01:00
2011-11-13 00:38:57 +01:00
U16_TO_BE16(SOCK_NCP, my_server_adr.sock);
2011-11-13 00:38:56 +01:00
#if !IN_NWROUTED
2011-11-13 00:38:56 +01:00
{
ipxAddr_t server_adr_sap;
2011-11-13 00:38:56 +01:00
polls[NEEDED_SOCKETS+1].fd = fd_ncpserv_in;
2011-11-13 00:38:56 +01:00
memcpy(&server_adr_sap, &my_server_adr, sizeof(ipxAddr_t));
U16_TO_BE16(SOCK_SAP, server_adr_sap.sock);
insert_delete_server((uint8*)my_nwname, 0x4,
&my_server_adr, &server_adr_sap, 0, 0, 0);
}
#endif
2011-11-13 00:38:56 +01:00
while (!server_is_down) {
int anz_poll = poll(polls, NEEDED_POLLS, broadmillisecs);
2011-11-13 00:38:58 +01:00
#if !IN_NWROUTED
2011-11-13 00:38:56 +01:00
int call_wdog=0;
2011-11-13 00:38:58 +01:00
#endif
time(&acttime_stamp);
2011-11-13 00:38:57 +01:00
#if !IN_NWROUTED
if (fl_got_sigchld) {
int stat_loc=-1;
int pid;
int status=-1;
fl_got_sigchld=0;
if ((pid =waitpid(-1, &stat_loc, 0)) > -1) {
status=WEXITSTATUS(stat_loc);
if (WIFSIGNALED(stat_loc)) status=-99;
}
if (pid == pid_nwbind || pid == pid_ncpserv) {
2011-11-13 00:38:58 +01:00
errorp(1, "CHILD died", "Child=%s, %s=%d",
(pid==pid_nwbind) ? "NWBIND" : "NCPSERV",
(status==-99) ? "got signal" : "result" ,
(status==-99) ? WTERMSIG(stat_loc) : status);
2011-11-13 00:38:57 +01:00
down_server();
} else
errorp(1, "unknown CHILD died", NULL);
}
#endif
2011-11-13 00:38:55 +01:00
if (fl_get_int) {
2011-11-13 00:38:58 +01:00
if (fl_get_int & 1)
2011-11-13 00:38:57 +01:00
handle_hup_reqest();
2011-11-13 00:38:58 +01:00
else if (fl_get_int & 4)
handle_usr1_request();
if (fl_get_int & 2)
2011-11-13 00:38:57 +01:00
down_server();
2011-11-13 00:38:58 +01:00
fl_get_int=0;
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:55 +01:00
if (anz_poll > 0) { /* i have to work */
2011-11-13 00:38:55 +01:00
struct pollfd *p = &polls[0];
j = -1;
while (++j < NEEDED_POLLS) {
if (p->revents){
2011-11-13 00:38:55 +01:00
if (j < NEEDED_SOCKETS) { /* socket */
2011-11-13 00:38:55 +01:00
XDPRINTF((99, 0,"POLL %d, SOCKET %x", p->revents, sock_nummern[j]));
if (p->revents & ~POLLIN)
errorp(0, "STREAM error", "revents=0x%x", p->revents );
else handle_event(p->fd, sock_nummern[j], j);
2011-11-13 00:38:55 +01:00
} else { /* fd_ncpserv_in */
2011-11-13 00:38:55 +01:00
XDPRINTF((2, 0, "POLL %d, fh=%d", p->revents, p->fd));
2011-11-13 00:38:57 +01:00
#if !IN_NWROUTED
2011-11-13 00:38:55 +01:00
if (p->revents & ~POLLIN)
errorp(0, "STREAM error", "revents=0x%x", p->revents );
2011-11-13 00:38:55 +01:00
else {
2011-11-13 00:38:56 +01:00
if (p->fd > -1) {
2011-11-13 00:38:55 +01:00
int what;
int conn;
2011-11-13 00:38:55 +01:00
int size;
2011-11-13 00:38:56 +01:00
uint8 buf[200];
if (sizeof(int) == read(p->fd,
2011-11-13 00:38:55 +01:00
(char*)&what, sizeof(int))) {
2011-11-13 00:38:56 +01:00
XDPRINTF((2, 0, "GOT %s_in what=0x%x",
(p->fd == fd_ncpserv_in) ? "ncpserv" : "nwbind" , what));
2011-11-13 00:38:55 +01:00
switch (what) {
case 0x2222 : /* insert wdog connection */
2011-11-13 00:38:56 +01:00
if (sizeof(int) == read(p->fd,
2011-11-13 00:38:55 +01:00
(char*)&conn, sizeof(int))
2011-11-13 00:38:56 +01:00
&& sizeof(int) == read(p->fd,
2011-11-13 00:38:55 +01:00
(char*)&size, sizeof(int))
2011-11-13 00:38:56 +01:00
&& sizeof(ipxAddr_t) + sizeof(uint16) + sizeof(uint32)
2011-11-13 00:38:56 +01:00
== read(p->fd,
(char*)buf, size)) {
insert_wdog_conn(conn, (ipxAddr_t*)buf);
write_to_nwbind(what, conn, (char*)buf, size);
}
2011-11-13 00:38:55 +01:00
break;
2011-11-13 00:38:55 +01:00
case 0x4444 : /* reset wdog connection = 0 */
2011-11-13 00:38:57 +01:00
/* activate wdogs = 1 */
2011-11-13 00:38:55 +01:00
/* remove wdog = 99 */
2011-11-13 00:38:56 +01:00
if (sizeof(int) == read(p->fd,
2011-11-13 00:38:55 +01:00
(char*)&conn, sizeof(int))
2011-11-13 00:38:56 +01:00
&& sizeof(int) == read(p->fd,
2011-11-13 00:38:55 +01:00
(char*)&what, sizeof(what)))
2011-11-13 00:38:57 +01:00
if (what == 1) {
while (conn++ < hi_conn) {
2011-11-13 00:38:55 +01:00
modify_wdog_conn(conn, what);
2011-11-13 00:38:57 +01:00
}
call_wdog++;
}
2011-11-13 00:38:55 +01:00
break;
2011-11-13 00:38:56 +01:00
case 0x5555 : /* close connection */
if (sizeof(int) == read(p->fd,
(char*)&conn, sizeof(int)))
modify_wdog_conn(conn, 99);
write_to_nwbind(what, conn, NULL, 0);
break;
2011-11-13 00:38:55 +01:00
case 0x6666 : /* bcast message */
2011-11-13 00:38:56 +01:00
if (sizeof(int) == read(p->fd,
2011-11-13 00:38:55 +01:00
(char*)&conn, sizeof(int)))
send_bcasts(conn);
2011-11-13 00:38:55 +01:00
break;
2011-11-13 00:38:55 +01:00
case 0xffff : /* down file server */
2011-11-13 00:38:56 +01:00
if (sizeof(int) == read(p->fd,
2011-11-13 00:38:55 +01:00
(char*)&conn, sizeof(int)) &&
conn == what) {
down_server();
}
2011-11-13 00:38:55 +01:00
break;
default : break;
}
}
}
}
2011-11-13 00:38:57 +01:00
#endif
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:55 +01:00
if (! --anz_poll) break;
} /* if */
p++;
} /* while */
2011-11-13 00:38:55 +01:00
} else {
2011-11-13 00:38:55 +01:00
XDPRINTF((99,0,"POLLING ..."));
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:56 +01:00
2011-11-13 00:38:55 +01:00
if (server_down_stamp) {
2011-11-13 00:38:58 +01:00
if (acttime_stamp - server_down_stamp > server_goes_down_secs)
2011-11-13 00:38:56 +01:00
server_is_down++;
2011-11-13 00:38:55 +01:00
} else {
2011-11-13 00:38:56 +01:00
int bsecs = broadmillisecs / 1000;
2011-11-13 00:38:58 +01:00
int difftime = acttime_stamp - broadtime;
2011-11-13 00:38:56 +01:00
if (difftime > bsecs) {
send_sap_rip_broadcast((bsecs < 3) ? 1 : 0); /* firsttime broadcast */
if (bsecs < server_broadcast_secs) {
2011-11-13 00:38:55 +01:00
rip_for_net(MAX_U32);
get_servers();
2011-11-13 00:38:56 +01:00
bsecs *= 2;
if (bsecs > server_broadcast_secs)
bsecs=server_broadcast_secs;
broadmillisecs = bsecs*1000+10;
2011-11-13 00:38:55 +01:00
}
2011-11-13 00:38:57 +01:00
#if !IN_NWROUTED
2011-11-13 00:38:57 +01:00
send_wdogs();
2011-11-13 00:38:57 +01:00
#endif
2011-11-13 00:38:58 +01:00
broadtime = acttime_stamp;
2011-11-13 00:38:56 +01:00
} else {
2011-11-13 00:38:57 +01:00
#if !IN_NWROUTED
2011-11-13 00:38:56 +01:00
if (call_wdog) send_wdogs(1);
if (client_mode && difftime > 5) get_servers(); /* Here more often */
2011-11-13 00:38:58 +01:00
#endif
2011-11-13 00:38:56 +01:00
}
2011-11-13 00:38:55 +01:00
}
} /* while */
send_down_broadcast();
2011-11-13 00:38:55 +01:00
sleep(1);
send_down_broadcast();
2011-11-13 00:38:55 +01:00
}
close_all();
2011-11-13 00:38:56 +01:00
fprintf(stderr, "\nNWE-%s is down now !!\n", prog_name_typ);
exit_tools();
2011-11-13 00:38:58 +01:00
#if !IN_NWROUTED
xfree(connections);
#endif
2011-11-13 00:38:55 +01:00
return(0);
}