This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-mbse/mbcico/opentcp.c
2003-01-02 16:44:28 +00:00

306 lines
7.2 KiB
C

/*****************************************************************************
*
* $Id$
* Purpose ...............: Fidonet mailer
*
*****************************************************************************
* Copyright (C) 1997-2003
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS 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, or (at your option) any
* later version.
*
* MBSE BBS 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 MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*****************************************************************************/
#include "../config.h"
#include "../lib/libs.h"
#include "../lib/memwatch.h"
#include "../lib/structs.h"
#include "../lib/users.h"
#include "../lib/records.h"
#include "../lib/common.h"
#include "../lib/clcomm.h"
#include "../lib/nodelist.h"
#include "../lib/dbnode.h"
#include "session.h"
#include "ttyio.h"
#include "openport.h"
#include "opentcp.h"
#define BINKPORT 24554
#define TELNPORT 23
#define FIDOPORT 60179 /* Eugene G. Crossers birthday */
static int fd=-1;
extern int f_flags;
extern int tcp_mode;
extern time_t c_start;
extern time_t c_end;
extern int online;
extern int master;
extern int carrier;
extern long sentbytes;
extern long rcvdbytes;
extern int Loaded;
char telnet_options[256];
char do_dont_resp[256];
char will_wont_resp[256];
void tel_enter_binary(int rw);
void tel_leave_binary(int rw);
void send_do(register int);
void send_dont(register int);
void send_will(register int);
void send_wont(register int);
static int tcp_is_open = FALSE;
/* opentcp() was rewritten by Martin Junius */
/* telnet mode was written by T.Tanaka */
int opentcp(char *name)
{
struct servent *se;
struct hostent *he;
int a1, a2, a3, a4, Fd, GotPort = FALSE;
char *errmsg, *portname;
short portnum;
struct sockaddr_in server;
Syslog('+', "Open TCP connection to \"%s\"", MBSE_SS(name));
tcp_is_open = FALSE;
memset(&telnet_options, 0, sizeof(telnet_options));
server.sin_family = AF_INET;
/*
* Get port number from name argument if there is a : part
*/
if ((portname = strchr(name,':'))) {
*portname++='\0';
if ((portnum = atoi(portname))) {
server.sin_port=htons(portnum);
GotPort = TRUE;
} else if ((se = getservbyname(portname, "tcp"))) {
server.sin_port = se->s_port;
GotPort = TRUE;
}
}
/*
* If not a forced port number, get the defaults.
*/
if (! GotPort) {
switch (tcp_mode) {
case TCPMODE_IFC: if ((se = getservbyname("fido", "tcp")))
server.sin_port = se->s_port;
else
server.sin_port = htons(FIDOPORT);
break;
case TCPMODE_ITN: if ((se = getservbyname("telnet", "tcp")))
server.sin_port = se->s_port;
else
server.sin_port = htons(TELNPORT);
break;
case TCPMODE_IBN: if ((se = getservbyname("binkd", "tcp")))
server.sin_port = se->s_port;
else
server.sin_port = htons(BINKPORT);
break;
default: server.sin_port = htons(FIDOPORT);
}
}
/*
* Get IP address for the hostname
*/
if (sscanf(name,"%d.%d.%d.%d",&a1,&a2,&a3,&a4) == 4)
server.sin_addr.s_addr = inet_addr(name);
else if ((he = gethostbyname(name)))
memcpy(&server.sin_addr,he->h_addr,he->h_length);
else {
switch (h_errno) {
case HOST_NOT_FOUND: errmsg = (char *)"Authoritative: Host not found"; break;
case TRY_AGAIN: errmsg = (char *)"Non-Authoritive: Host not found"; break;
case NO_RECOVERY: errmsg = (char *)"Non recoverable errors"; break;
default: errmsg = (char *)"Unknown error"; break;
}
Syslog('+', "No IP address for %s: %s\n", name, errmsg);
return -1;
}
signal(SIGPIPE,linedrop);
fflush(stdin);
fflush(stdout);
setbuf(stdin,NULL);
setbuf(stdout,NULL);
close(0);
close(1);
if ((Fd = socket(AF_INET,SOCK_STREAM,0)) != 0) {
WriteError("$Cannot create socket (got %d, expected 0");
open("/dev/null",O_RDONLY);
open("/dev/null",O_WRONLY);
return -1;
}
if (dup(Fd) != 1) {
WriteError("$Cannot dup socket");
open("/dev/null",O_WRONLY);
return -1;
}
clearerr(stdin);
clearerr(stdout);
if (connect(Fd,(struct sockaddr *)&server,sizeof(server)) == -1) {
Syslog('+', "Cannot connect %s",inet_ntoa(server.sin_addr));
return -1;
}
f_flags=0;
if (tcp_mode == TCPMODE_ITN)
tel_enter_binary(3);
Syslog('+', "Established %s/TCP connection with %s, port %d",
(tcp_mode == TCPMODE_ITN) ? "ITN":(tcp_mode == TCPMODE_IFC) ? "IFC":(tcp_mode == TCPMODE_IBN) ? "IBN":"Unknown",
inet_ntoa(server.sin_addr), (int)ntohs(server.sin_port));
c_start = time(NULL);
carrier = TRUE;
tcp_is_open = TRUE;
return 0;
}
void closetcp(void)
{
FILE *fph;
char *tmp;
if (!tcp_is_open)
return;
if (tcp_mode == TCPMODE_ITN)
tel_leave_binary(3);
shutdown(fd, 2);
signal(SIGPIPE,SIG_DFL);
if (carrier) {
c_end = time(NULL);
online += (c_end - c_start);
Syslog('+', "Closing TCP connection, connected %s", t_elapsed(c_start, c_end));
carrier = FALSE;
history.offline = c_end;
history.online = c_start;
history.sent_bytes = sentbytes;
history.rcvd_bytes = rcvdbytes;
history.inbound = ~master;
tmp = calloc(PATH_MAX, sizeof(char));
sprintf(tmp, "%s/var/mailer.hist", getenv("MBSE_ROOT"));
if ((fph = fopen(tmp, "a")) == NULL)
WriteError("$Can't open %s", tmp);
else {
fwrite(&history, sizeof(history), 1, fph);
fclose(fph);
}
free(tmp);
memset(&history, 0, sizeof(history));
if (Loaded) {
nodes.LastDate = time(NULL);
UpdateNode();
}
}
tcp_is_open = FALSE;
}
void tel_enter_binary(int rw)
{
Syslog('d', "Telnet enter binary %d", rw);
if (rw & 1)
send_do(TELOPT_BINARY);
if (rw & 2)
send_will(TELOPT_BINARY);
send_dont(TELOPT_ECHO);
send_do(TELOPT_SGA);
send_dont(TELOPT_RCTE);
send_dont(TELOPT_TTYPE);
send_wont(TELOPT_ECHO);
send_will(TELOPT_SGA);
send_wont(TELOPT_RCTE);
send_wont(TELOPT_TTYPE);
}
void tel_leave_binary(int rw)
{
Syslog('d', "Telnet leave binary %d", rw);
if (rw & 1)
send_dont(TELOPT_BINARY);
if (rw & 2)
send_wont(TELOPT_BINARY);
}
/*
* These routines are in charge of sending option negotiations
* to the other side.
* The basic idea is that we send the negotiation if either side
* is in disagreement as to what the current state should be.
*/
void send_do(register int c)
{
NET2ADD(IAC, DO);
NETADD(c);
}
void send_dont(register int c)
{
NET2ADD(IAC, DONT);
NETADD(c);
}
void send_will(register int c)
{
NET2ADD(IAC, WILL);
NETADD(c);
}
void send_wont(register int c)
{
NET2ADD(IAC, WONT);
NETADD(c);
}