/* nwserv.c 22-Nov-95 */ /* (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 int conn_gid=1; static int conn_uid=1; static int ncpserv_debug=0; static int nwconn_debug=0; #define MY_BROADCAST_SLOT 0 /* Server Broadcast OUT */ #define WDOG_SLOT 1 /* Watchdog send + recv */ #define SAP_SLOT 2 #define RIP_SLOT 3 #define ROUTE_SLOT 4 #define DIAG_SLOT 5 #if 0 #define ECHO_SLOT 6 #define ERR_SLOT 7 #endif uint16 ipx_sock_nummern[]={ 0, /* auto sock */ 0, /* auto sock */ SOCK_SAP, SOCK_RIP, SOCK_ROUTE, SOCK_DIAGNOSE #if 0 , SOCK_ECHO, SOCK_ERROR, #endif }; #define NEEDED_SOCKETS (sizeof(ipx_sock_nummern) / sizeof(uint16)) #define NEEDED_POLLS (NEEDED_SOCKETS+1) static uint16 sock_nummern [NEEDED_SOCKETS]; static int sockfd [NEEDED_SOCKETS]; static struct pollfd polls[NEEDED_POLLS]; static ipxAddr_t my_server_adr; /* Address of this server */ static uint16 spx_diag_socket; /* SPX DIAGNOSE SOCKET */ static ipxAddr_t nw386_adr; /* Address of NW-TEST Server */ static int nw386_found = 0; static int client_mode = 0; static uint32 network = 0x0L; static uint32 internal_net = 0x0L; static char my_nwname[50]; static int ipxdebug = 0; static int pid_ncpserv = -1; static int fd_ncpserv_out = -1; /* ctrl-pipe out to ncpserv */ static int fd_ncpserv_in = -1; /* ctrl-pipe in from ncpserv */ #ifndef LINUX static int frame=0; #else static int frame=IPX_FRAME_8023; static char devname[40]; #endif static time_t akttime_stamp; static int bytes_to_write_to_ncpserv=0; static void inform_ncpserv(void) { if (bytes_to_write_to_ncpserv) { kill(pid_ncpserv, SIGHUP); /* tell ncpserv to read input */ bytes_to_write_to_ncpserv=0; } } static void write_to_ncpserv(int what, int connection, char *data, int data_size) { switch (what) { case 0x5555 : /* kill connection */ bytes_to_write_to_ncpserv += write(fd_ncpserv_out, (char*) &what, sizeof(int)); bytes_to_write_to_ncpserv += write(fd_ncpserv_out, (char*) &connection, sizeof(int)); break; case 0x3333 : /* 'bindery' calls */ bytes_to_write_to_ncpserv += write(fd_ncpserv_out, (char*) &what, sizeof(int)); bytes_to_write_to_ncpserv += write(fd_ncpserv_out, (char*) &data_size, sizeof(int)); bytes_to_write_to_ncpserv += write(fd_ncpserv_out, data, data_size); break; default : break; } if (bytes_to_write_to_ncpserv > 255) inform_ncpserv(); } static void ins_del_bind_net_addr(char *name, ipxAddr_t *adr) { uint8 buf[1024]; uint8 *p = buf; int len = 0; if (NULL != adr) { /* insert */ *p=0x01; p+=2; len+=2; U16_TO_BE16(0x4, p); p+=2; len+=2; *p = strlen(name); 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; U16_TO_BE16(0x4, p); p+=2; len+=2; *p = strlen(name); strmaxcpy(p+1, name, *p); len += (*p+1); p+=(*p + 1); } write_to_ncpserv(0x3333, 0, buf, len); } static int open_ipx_socket(uint16 sock_nr, int nr, int open_mode) { int ipx_fd=t_open("/dev/ipx", open_mode, NULL); struct t_bind bind; if (ipx_fd < 0) { t_error("t_open !Ok"); return(-1); } U16_TO_BE16(sock_nr, my_server_adr.sock); /* actual read socket */ bind.addr.len = sizeof(ipxAddr_t); bind.addr.maxlen = sizeof(ipxAddr_t); bind.addr.buf = (char*)&my_server_adr; bind.qlen = 0; /* immer */ if (t_bind(ipx_fd, &bind, &bind) < 0){ char sxx[200]; sprintf(sxx,"NWSERV:t_bind !OK in open_ipx_socket, sock=%d", sock_nr); t_error(sxx); t_close(ipx_fd); return(-1); } sock_nummern[nr] = GET_BE16(my_server_adr.sock); /* really socket nmbr */ if (nw_debug) print_ipx_addr(&my_server_adr); return(ipx_fd); } static int start_ncpserv(char *nwname, ipxAddr_t *addr) { int fds_out[2]; int fds_in[2]; int pid; if (pipe(fds_out) < 0 || pipe(fds_in) < 0) return(-1); switch (pid=fork()) { case 0 : { /* new Process */ char *progname="ncpserv"; char addrstr[100]; char pathname[300]; char gidstr[10]; char uidstr[10]; char debug1[5]; char debug2[5]; char debug3[5]; int j = FD_NWSERV; close(fds_out[1]); /* no need to write */ dup2(fds_out[0], 0); /* becommes stdin */ close(fds_out[0]); /* no longer needed */ 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 */ ipx_addr_to_adr(addrstr, addr); sprintf(gidstr, "%d", conn_gid); sprintf(uidstr, "%d", conn_uid); sprintf(debug1, "%d", ncpserv_debug); sprintf(debug2, "%d", nwconn_debug); sprintf(debug3, "%d", ipxdebug); execl(get_exec_path(pathname, progname), progname, nwname, addrstr, gidstr, uidstr, debug1, debug2, debug3, NULL); exit(1); } break; case -1: close(fds_out[0]); close(fds_out[1]); close(fds_in[0]); close(fds_in[1]); return(-1); /* error */ } fds_out[0] = -1; fd_ncpserv_out = fds_out[1]; fds_in[1] = -1; fd_ncpserv_in = fds_in[0]; pid_ncpserv = pid; return(0); /* OK */ } static int start_nwclient(void) { switch (fork()){ case 0 : { /* new Process */ 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); case -1: return(-1); /* error */ } return(0); /* OK */ } /* =========================== WDOG =============================== */ static void send_wdog_packet(ipxAddr_t *addr, int conn, int what) { uint8 data[2]; data[0] = (uint8) conn; data[1] = (uint8) what; send_ipx_data(sockfd[WDOG_SLOT], 17, 2, data, addr, "WDOG"); } 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. */ send_ipx_data(sockfd[WDOG_SLOT], 17, 2, data, addr, "BCAST"); } typedef struct { ipxAddr_t addr; /* address of client */ time_t last_time; /* last wdog packet sent */ int counter; /* max. 11 packets */ } CONN; static CONN conns[MAX_CONNECTIONS]; static int hi_conn=0; static void insert_wdog_conn(int conn, ipxAddr_t *adr) { if (conn > 0 && conn <= MAX_CONNECTIONS) { CONN *c; while (hi_conn < conn) { c=&(conns[hi_conn++]); memset(c, 0, sizeof(CONN)); } c=&(conns[--conn]); c->last_time = akttime_stamp; c->counter = 0; if (NULL != adr) memcpy(&(c->addr), adr, sizeof(ipxAddr_t)); } } static void reset_wdog_conn(int conn) { if (conn > 0 && --conn < hi_conn) { CONN *c=&(conns[conn]); c->last_time = akttime_stamp; c->counter = 0; } } static void remove_wdog_conn(int conn) { if (conn > 0 && --conn < hi_conn) { CONN *c=&(conns[conn]); memset(c, 0, sizeof(CONN)); if (conn + 1 == hi_conn) { while (hi_conn) { CONN *c=&(conns[hi_conn-1]); if (!c->last_time) hi_conn--; else break; } } } } #ifdef _WDOG_TESTING_ /* 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 static void send_wdogs(void) { int k = hi_conn; while (k--) { CONN *c = &(conns[k]); if (c->last_time) { time_t t_diff = akttime_stamp - c->last_time; if (c->counter || t_diff > WDOG_TRIE_AFTER_SEC) { /* max. 5 minutes */ 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; c->last_time = akttime_stamp; 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) { CONN *c = &(conns[conn]); 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 */ } } /* =========================== SERVER BROADCAST ======================== */ static int send_broadcast(int fd, int firsttime, int down) /* periodic Broadcast Message */ { IPX_DATA ipx_data; int ipx_pack_typ = 17; ipxAddr_t wild; memset(&wild, 0, sizeof(ipxAddr_t)); U32_TO_BE32(network, wild.net); memset(wild.node, 0xFF, IPX_NODE_SIZE); U16_TO_BE16(SOCK_SAP, wild.sock); memset(&ipx_data, 0, sizeof(ipx_data.sip)); strcpy(ipx_data.sip.server_name, my_nwname); memcpy(&ipx_data.sip.server_adr, &my_server_adr, sizeof(ipxAddr_t)); U16_TO_BE16(SOCK_NCP, ipx_data.sip.server_adr.sock); /* NCP SOCKET verwenden */ if (firsttime && start_ncpserv(ipx_data.sip.server_name, &ipx_data.sip.server_adr)) return(-1); U16_TO_BE16(2, ipx_data.sip.response_type); /* General */ U16_TO_BE16(4, ipx_data.sip.server_type); /* Fileserver */ if (down) { U16_TO_BE16(16, ipx_data.sip.intermediate_networks); } else { U16_TO_BE16(1, ipx_data.sip.intermediate_networks); /* I think 1 is ok here */ } send_ipx_data(fd, ipx_pack_typ, sizeof(ipx_data.sip), (char *)&(ipx_data.sip), &wild, "SIP Broadcast"); return(0); } static void send_server_respons(int fd, uint8 ipx_pack_typ, int respond_typ, int server_typ, ipxAddr_t *to_addr) { IPX_DATA ipx_data; memset(&ipx_data, 0, sizeof(ipx_data.sip)); strcpy(ipx_data.sip.server_name, my_nwname); memcpy(&ipx_data.sip.server_adr, &my_server_adr, sizeof(ipxAddr_t)); U16_TO_BE16(SOCK_NCP, ipx_data.sip.server_adr.sock); /* NCP SOCKET verwenden */ U16_TO_BE16(respond_typ, ipx_data.sip.response_type); U16_TO_BE16(server_typ, ipx_data.sip.server_type); U16_TO_BE16(0, ipx_data.sip.intermediate_networks); send_ipx_data(fd, ipx_pack_typ, sizeof(ipx_data.sip), (char *)&(ipx_data.sip), to_addr, "Server Response"); } void get_server_data(char *name, ipxAddr_t *adr, ipxAddr_t *from_addr) { #ifdef LINUX if (memcmp(adr->net, my_server_adr.net, IPX_NET_SIZE)) /* don't add our own netroute twice */ myipx_route_add(adr->net, from_addr->net, from_addr->node); #endif if (!nw386_found) { memcpy(&nw386_adr, adr, sizeof(ipxAddr_t)); nw386_found++; if (client_mode) { start_nwclient(); client_mode = 0; /* only start once */ } } DPRINTF(("NW386 %s found at:%s\n", name, visable_ipx_adr(adr))); ins_del_bind_net_addr(name, adr); } void handle_sap(int fd, int ipx_pack_typ, int data_len, IPX_DATA *ipxdata, ipxAddr_t *from_addr) { int query_type = GET_BE16(ipxdata->sqp.query_type); int server_type = GET_BE16(ipxdata->sqp.server_type); if (query_type == 3) { DPRINTF(("SAP NEAREST SERVER request typ=%d von %s\n", server_type, visable_ipx_adr(from_addr))); if (server_type == 4) { /* Get Nearest File Server */ send_server_respons(fd, ipx_pack_typ, 4, server_type, from_addr); } } else if (query_type == 1) { /* general Request */ DPRINTF(("SAP GENERAL request server_type =%d\n", server_type)); if (server_type == 4) { /* Get General File Server Request */ send_server_respons(fd, ipx_pack_typ, 4, server_type, from_addr); } } else if (query_type == 2) { /* periodic general or shutdown response */ DPRINTF(("SAP PERIODIC response von %s\n", visable_ipx_adr(from_addr))); if (server_type == 4) { /* from Fileserver */ DPRINTF(("FROM SERVER intermediate=%d\n", GET_BE16(ipxdata->sip.intermediate_networks))); if (16 == GET_BE16(ipxdata->sip.intermediate_networks)) { /* shutdown */ if (memcmp(ipxdata->sip.server_adr.net, my_server_adr.net, IPX_NET_SIZE)) { /* don't kill our own netroute */ DPRINTF(("SERVER %s IS GOING DOWN\n", ipxdata->sip.server_name)); ins_del_bind_net_addr(ipxdata->sip.server_name, NULL); #ifdef LINUX myipx_route_del(ipxdata->sip.server_adr.net); #endif } else { DPRINTF(("SHUTDOWN RESPONSE from SERVER %s\n", ipxdata->sip.server_name)); } } else { get_server_data(ipxdata->sip.server_name, &(ipxdata->sip.server_adr), from_addr); } } } else if (query_type == 4) { /* nearests Service Response */ DPRINTF(("SAP nearest Service response\n")); if (server_type == 4){ get_server_data(ipxdata->sip.server_name, &(ipxdata->sip.server_adr), from_addr); } } else DPRINTF(("UNKNOWN SAP query %x, server %x\n", query_type, server_type)); } static void send_rip(ipxAddr_t *from_addr) { RIP rip; ipxAddr_t to_addr; memset(&rip, 0, sizeof(RIP)); if (from_addr) memcpy(&to_addr, from_addr, sizeof(ipxAddr_t)); else { memset(&to_addr, 0, sizeof(ipxAddr_t)); U32_TO_BE32(network, to_addr.net); memset(to_addr.node, 0xFF, IPX_NODE_SIZE); U16_TO_BE16(SOCK_RIP, to_addr.sock); } memcpy(rip.network, my_server_adr.net, IPX_NET_SIZE); U16_TO_BE16(2, rip.operation); /* rip response or general */ U16_TO_BE16(1, rip.ticks); /* on ethernets allways 1 Tick */ U16_TO_BE16(0, rip.hops); send_ipx_data(sockfd[RIP_SLOT], 1, sizeof(RIP), (char *)&rip, &to_addr, "SEND RIP"); } static void handle_rip(int fd, int ipx_pack_typ, int data_len, IPX_DATA *ipxdata, ipxAddr_t *from_addr) { int operation = GET_BE16(ipxdata->rip.operation); int hops = GET_BE16(ipxdata->rip.hops); int ticks = GET_BE16(ipxdata->rip.ticks); DPRINTF(("Rip %s hops %d, ticks %d, network:%02x.%02x.%02x.%02x\n", (operation == 1) ? "Request" : "Response", hops, ticks, (int)ipxdata->rip.network[0], (int)ipxdata->rip.network[1], (int)ipxdata->rip.network[2], (int)ipxdata->rip.network[3])); if (operation == 1) { /* rip request */ send_rip(from_addr); } else if (operation != 2) /* NICHT RIP response */ DPRINTF(("UNKNOWN RIP operation %d\n", operation)); } /* ** 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 static void response_ipx_diag(int fd, int ipx_pack_typ, ipxAddr_t *to_addr) { 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++; /* Jetzt extended */ *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, datalen, (char*)&ipxdata, to_addr, "DIAG Response"); } static void handle_diag(int fd, int ipx_pack_typ, int data_len, IPX_DATA *ipxdata, ipxAddr_t *from_addr) /* 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) { DPRINTF(("NO RESPONSE TO DIAG\n")); return; } exnodes += IPX_NODE_SIZE; } DPRINTF(("DIAG Request, ipx_pack_typ %d, data_len %d, count %d\n", (int)ipx_pack_typ, data_len, count)); response_ipx_diag(fd, ipx_pack_typ, from_addr); } 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); DPRINTF(("Error from %s, Code = 0x%lx\n", visable_ipx_adr(&erradr), uderr.error)); t_error("t_rcvudata !OK"); return; } DPRINTF(("Ptyp:%d von: %s\n", (int)ipx_pack_typ, visable_ipx_adr(&source_adr) )); if IPXCMPNODE(source_adr.node, my_server_adr.node) { int source_sock = (int) GET_BE16(source_adr.sock); if ( source_sock == sock_nummern[MY_BROADCAST_SLOT] || source_sock == sock_nummern[WDOG_SLOT] || source_sock == SOCK_RIP) { DPRINTF(("OWN Packet, ignored\n")); return; } /* it also can be Packets from DOSEMU OR ncpfs on this machine */ DPRINTF(("Packet from OWN maschine:sock=0x%x\n", source_sock)); } switch (socknr) { case SOCK_SAP : handle_sap( fd, (int) ipx_pack_typ, ud.udata.len, &ipx_data_buff, &source_adr); break; case SOCK_RIP : handle_rip( fd, (int) ipx_pack_typ, ud.udata.len, &ipx_data_buff, &source_adr); break; case SOCK_DIAGNOSE : handle_diag(fd, (int) ipx_pack_typ, ud.udata.len, &ipx_data_buff, &source_adr); break; default : if (WDOG_SLOT == slot) { /* this is a watchdog packet */ DPRINTF(("WDOG Packet len=%d connid=%d, status=%d\n", (int)ud.udata.len, (int) ipx_data_buff.wdog.connid, (int)ipx_data_buff.wdog.status)); if (2 == ud.udata.len) { if ('Y' == ipx_data_buff.wdog.status) reset_wdog_conn(ipx_data_buff.wdog.connid); } } else { uint8 *p = (uint8*)&ipx_data_buff; int k = 0; DPRINTF(("UNKNOWN")); while (k++ < ud.udata.len){ DPRINTF((" %x", (int) *p++)); } DPRINTF(("\n")); /* print_ud_data(&ud); */ } break; } } static void get_server(void) { if (!nw386_found) { /* no other server was found yet. */ SQP sqp; ipxAddr_t wild; memset(&wild, 0, sizeof(ipxAddr_t)); memset(wild.node, 0xFF, IPX_NODE_SIZE); U32_TO_BE32(network, wild.net); U16_TO_BE16(SOCK_SAP, wild.sock); U16_TO_BE16(3, sqp.query_type); U16_TO_BE16(4, sqp.server_type); send_ipx_data(sockfd[SAP_SLOT], 17, sizeof(SQP), (char*)&sqp, &wild, "SERVER Query"); } } static void get_ini(void) { FILE *f=open_nw_ini(); char *frname=NULL; #ifdef LINUX strcpy(devname, "eth0"); /* default */ #endif gethostname(my_nwname, 48); upstr(my_nwname); if (f){ char buff[500]; int what; while (0 != (what =get_ini_entry(f, 0, (char*)buff, sizeof(buff)))) { char inhalt[500]; char inhalt2[500]; char inhalt3[500]; char dummy; int anz; if ((anz=sscanf((char*)buff, "%s %s %s", inhalt, inhalt2, inhalt3)) > 0) { switch (what) { case 2 : strncpy(my_nwname, inhalt, 48); my_nwname[47] = '\0'; upstr(my_nwname); break; #ifdef LINUX case 3 : if (sscanf(inhalt, "%ld%c", &internal_net, &dummy) != 1) sscanf(inhalt, "%lx", &internal_net); break; #endif case 4 : if (sscanf(inhalt, "%ld%c", &network, &dummy) != 1) sscanf(inhalt, "%lx", &network); #ifdef LINUX if (anz > 1) { strncpy(devname, inhalt2, sizeof(devname)); devname[sizeof(devname)-1] = '\0'; } if (anz > 2) { upstr(inhalt3); if (!strcmp(inhalt3, "802.3")) frame=IPX_FRAME_8023; else if (!strcmp(inhalt3, "802.2")) frame=IPX_FRAME_8022; else if (!strcmp(inhalt3, "SNAP")) frame=IPX_FRAME_SNAP; else if (!strcmp(inhalt3, "ETHERNET_II")) frame=IPX_FRAME_ETHERII; } #endif break; case 10 : sscanf(inhalt, "%d", &conn_gid); break; case 11 : sscanf(inhalt, "%d", &conn_uid); break; case 100 : sscanf(inhalt, "%d", &ipxdebug); break; case 101 : sscanf(inhalt, "%d", &nw_debug); break; case 102 : sscanf(inhalt, "%d", &ncpserv_debug); break; case 103 : sscanf(inhalt, "%d", &nwconn_debug); break; default : break; } /* switch */ } /* if */ } /* while */ fclose(f); } #ifdef LINUX switch (frame) { case IPX_FRAME_8022 : frname = "802.2"; break; case IPX_FRAME_8023 : frname = "802.3"; break; case IPX_FRAME_SNAP : frname = "SNAP"; break; case IPX_FRAME_ETHERII : frname = "ETHERNET_II";break; default : break; } /* switch */ #else frname = "ETHERNET_II"; #endif fprintf(stdout, "Servername='%s', NETWORK='0x%lx', NODE='0x%lx'\n", my_nwname, network, internal_net); #ifdef LINUX fprintf(stdout, "Device=%s, Frame=%s\n", devname, frname); init_ipx(devname, &network, internal_net, frame, frname, ipxdebug); fprintf(stdout, "NETWORK is=0x%lx\n", network); #endif } static void send_down_broadcast(void) { int j = 20; while (j--) send_broadcast(sockfd[MY_BROADCAST_SLOT], 0, 1); } static void close_all(void) { int j = NEEDED_SOCKETS; if (pid_ncpserv > 0) { if (fd_ncpserv_out > -1) close(fd_ncpserv_out); if (fd_ncpserv_in > -1) close(fd_ncpserv_in); kill(pid_ncpserv, SIGTERM); /* terminate ncpserv */ kill(pid_ncpserv, SIGKILL); /* kill ncpserv */ } while (j--) { t_unbind(sockfd[j]); t_close(sockfd[j]); } #ifdef LINUX fprintf(stdout, "Close Device=%s\n", devname); exit_ipx(devname, network, frame); #endif } static void sig_quit(int rsig) { signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); signal(SIGTERM, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); send_down_broadcast(); close_all(); exit(1); } static int fl_get_debug=0; static void get_new_debug(void) { get_ini_debug(1); fl_get_debug=0; } static void sig_hup(int rsig) { signal(SIGHUP, SIG_IGN); fl_get_debug++; signal(SIGHUP, sig_hup); } static void set_sigs(void) { signal(SIGTERM, sig_quit); signal(SIGQUIT, sig_quit); signal(SIGINT, sig_quit); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, sig_hup); } int main(int argc, char **argv) { int j = -1; tzset(); if (argc > 1) client_mode++; /* in client mode the testprog 'nwclient' will be startet. */ get_ini(); while (++j < NEEDED_POLLS) { polls[j].events = POLLIN|POLLPRI; polls[j].revents = 0; if (j < NEEDED_SOCKETS) { int fd = open_ipx_socket(ipx_sock_nummern[j], j, O_RDWR); if (fd < 0) { while (j--) { t_unbind(sockfd[j]); t_close(sockfd[j]); } return(1); } else { sockfd[j] = fd; polls[j].fd = fd; } } else { polls[j].fd = -1; } } if (!send_broadcast(sockfd[MY_BROADCAST_SLOT], 1, 0)) { /* Jetzt POLLEN */ time_t broadtime; time(&broadtime); set_sigs(); polls[NEEDED_SOCKETS].fd = fd_ncpserv_in; while (1) { int anz_poll = poll(polls, NEEDED_POLLS, (!client_mode) ? 30000 : 15000); if (fl_get_debug) get_new_debug(); time(&akttime_stamp); if (anz_poll > 0) { /* i have to work */ struct pollfd *p = &polls[0]; j = -1; while (++j < NEEDED_POLLS) { if (p->revents){ if (j < NEEDED_SOCKETS) { /* socket */ /* DPRINTF(("POLL %d, SOCKET %x, ", p->revents, sock_nummern[j])); */ if (p->revents & ~POLLIN) perror("STREAM error"); else handle_event(p->fd, sock_nummern[j], j); } else { /* fd_ncpserv_in */ DPRINTF(("POLL %d, fh=%d\n", p->revents, p->fd)); if (p->revents & ~POLLIN) perror("STREAM error"); else { if (p->fd == fd_ncpserv_in) { int what; int conn; ipxAddr_t adr; if (sizeof(int) == read(fd_ncpserv_in, (char*)&what, sizeof(int))) { DPRINTF(("GOT ncpserv_in what=0x%x\n", what)); switch (what) { case 0x2222 : /* insert wdog connection */ if (sizeof(int) == read(fd_ncpserv_in, (char*)&conn, sizeof(int)) && sizeof(ipxAddr_t) == read(fd_ncpserv_in, (char*)&adr, sizeof(ipxAddr_t))) insert_wdog_conn(conn, &adr); break; case 0x4444 : /* reset wdog connection */ if (sizeof(int) == read(fd_ncpserv_in, (char*)&conn, sizeof(int))) reset_wdog_conn(conn); break; case 0x6666 : /* remove wdog connection */ if (sizeof(int) == read(fd_ncpserv_in, (char*)&conn, sizeof(int))) remove_wdog_conn(conn); break; case 0x8888 : /* bcast message */ if (sizeof(int) == read(fd_ncpserv_in, (char*)&conn, sizeof(int))) send_bcasts(conn); break; default : break; } } } } } if (! --anz_poll) break; } /* if */ p++; } /* while */ } else { /* if (anz_poll < 0) perror("POLL error"); */ if (nw_debug > 2) DPRINTF(("POLLING ...\n")); } if (akttime_stamp - broadtime > 59) { /* ca. 60 seconds */ send_wdogs(); send_broadcast(sockfd[MY_BROADCAST_SLOT], 0, 0); send_rip(NULL); get_server(); inform_ncpserv(); broadtime = akttime_stamp; } else if (client_mode) get_server(); /* Here more often */ } /* while */ send_down_broadcast(); } close_all(); return(0); }