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/ftsc.c

516 lines
11 KiB
C
Raw Normal View History

2009-05-15 20:01:56 +00:00
/*****************************************************************************
*
* $Id: ftsc.c,v 1.22 2007/04/30 19:04:17 mbse Exp $
* Purpose ...............: Fidonet mailer
*
*****************************************************************************
* Copyright (C) 1997-2007
*
* 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, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include "../lib/mbselib.h"
#include "../lib/nodelist.h"
#include "session.h"
#include "ttyio.h"
#include "statetbl.h"
#include "config.h"
#include "ftsc.h"
#include "rdoptions.h"
#include "recvbark.h"
#include "filelist.h"
#include "sendbark.h"
#include "respfreq.h"
#include "xmrecv.h"
#include "xmsend.h"
#include "inbound.h"
extern int master;
extern int made_request;
static int rxftsc(void);
static int txftsc(void);
static int recvfiles(void);
static file_list *tosend;
extern int Loaded;
extern pid_t mypid;
extern char *tempinbound;
extern int session_state;
int rx_ftsc(void)
{
int rc;
IsDoing("FTS-0001 inbound");
session_flags |= SESSION_BARK;
if ((rc = rxftsc())) {
WriteError("Session failed: rc=%d",rc);
PUTCHAR(CAN);
PUTCHAR(CAN);
PUTCHAR(CAN);
} else
Syslog('+', "FTS-0001 session completed");
tidy_filelist(tosend, (rc == 0));
tosend = NULL;
if (rc)
return MBERR_FTSC;
else
return 0;
}
int tx_ftsc(void)
{
int rc;
IsDoing("FTS-0001 to %s", ascfnode(remote->addr, 0x0f));
if ((rc = txftsc())) {
WriteError("Session failed: rc=%d",rc);
PUTCHAR(CAN);
PUTCHAR(CAN);
PUTCHAR(CAN);
} else
Syslog('+', "FTS-0001 session completed");
tidy_filelist(tosend, (rc == 0));
tosend = NULL;
if (rc)
return MBERR_FTSC;
else
return 0;
}
SM_DECL(txftsc,(char *)"txftsc")
SM_STATES
wait_command,
recv_mail,
send_req,
recv_req
SM_NAMES
(char *)"wait_command",
(char *)"recv_mail",
(char *)"send_req",
(char *)"recv_req"
SM_EDECL
int c,rc, mailsent = FALSE, mailrcvd = FALSE;
char *nonhold_mail;
nonhold_mail = (char *)ALL_MAIL;
tosend = create_filelist(remote,nonhold_mail,2);
if ((rc = xmsndfiles(tosend)))
return rc;
mailsent = TRUE;
SM_START(wait_command)
SM_STATE(wait_command)
c = GETCHAR(30);
if (c == TIMEOUT) {
Syslog('+', "timeout waiting for remote action, try receive");
SM_PROCEED(recv_mail);
} else if (c < 0) {
if (mailrcvd && mailsent) {
/*
* Some systems hangup after sending mail, so if we did
* send and receive mail we consider the session OK.
*/
Syslog('+', "Lost carrier, FTS-0001 session looks complete");
SM_SUCCESS;
} else {
Syslog('+', "got error waiting for TSYNC: received %d",c);
SM_ERROR;
}
} else switch (c) {
case TSYNC: SM_PROCEED(recv_mail);
break;
case SYN: SM_PROCEED(recv_req);
break;
case ENQ: SM_PROCEED(send_req);
break;
case 'C':
case NAK: PUTCHAR(EOT);
SM_PROCEED(wait_command);
break;
case CAN: SM_SUCCESS; /* this is not in BT */
break;
default: Syslog('s', "got '%s' waiting command", printablec(c));
PUTCHAR(SUB);
SM_PROCEED(wait_command);
break;
}
SM_STATE(recv_mail)
if (recvfiles()) {
SM_ERROR;
} else {
mailrcvd = TRUE;
SM_PROCEED(wait_command);
}
SM_STATE(send_req)
if (sendbark()) {
SM_ERROR;
} else {
SM_SUCCESS;
}
SM_STATE(recv_req)
if (recvbark()) {
SM_ERROR;
} else {
SM_PROCEED(wait_command);
}
SM_END
SM_RETURN
SM_DECL(rxftsc,(char *)"rxftsc")
SM_STATES
recv_mail,
send_mail,
send_req,
recv_req
SM_NAMES
(char *)"recv_mail",
(char *)"send_mail",
(char *)"send_req",
(char *)"recv_req"
SM_EDECL
int c, count = 0, didwazoo = FALSE, sentmail = FALSE, rcvdmail = FALSE;
file_list *request = NULL, *tmpfl;
SM_START(recv_mail)
SM_STATE(recv_mail)
if (recvfiles()) {
SM_ERROR;
} else {
rcvdmail = TRUE;
SM_PROCEED(send_mail);
}
SM_STATE(send_mail)
Syslog('x', "rxftsc SEND_MAIL count=%d", count);
if (count++ > 45) {
SM_ERROR;
}
/*
* If we got a wazoo request, add files now.
*/
request = respond_wazoo();
if (request != NULL) {
didwazoo = TRUE;
tmpfl = tosend;
tosend = request;
for (; request->next; request = request->next);
request->next = tmpfl;
2009-05-15 20:01:56 +00:00
request = NULL;
}
if (tosend == NULL) {
count = 0;
SM_PROCEED(send_req);
}
PUTCHAR(TSYNC);
c = GETCHAR(1);
Syslog('x', "Got char 0x%02x", c);
if (c == TIMEOUT) {
Syslog('x', " timeout");
SM_PROCEED(send_mail);
} else if (c < 0) {
Syslog('+', "got error waiting for NAK: received %d",c);
SM_ERROR;
} else switch (c) {
case 'C':
case NAK: if (xmsndfiles(tosend)) {
SM_ERROR;
} else {
sentmail = TRUE;
count = 0;
SM_PROCEED(send_req);
}
break;
case CAN: Syslog('+', "Remote refused to pickup mail");
SM_SUCCESS;
break;
case EOT: PUTCHAR(ACK);
SM_PROCEED(send_mail);
break;
default: Syslog('s', "Got '%s' waiting NAK", printablec(c));
SM_PROCEED(send_mail);
break;
}
SM_STATE(send_req)
Syslog('x', "rxftsc SEND_REQ count=%d", count);
if (didwazoo) {
session_state = STATE_UNSECURE;
SM_SUCCESS;
}
if (count > 15) {
SM_ERROR;
}
if (!made_request) {
SM_PROCEED(recv_req);
}
PUTCHAR(SYN);
c = GETCHAR(5);
Syslog('x', "Got char 0x%02x", c);
count++;
if (c == TIMEOUT) {
Syslog('x', " timeout");
SM_PROCEED(send_req);
} else if (c < 0) {
Syslog('+', "got error waiting for ENQ: received %d",c);
SM_ERROR;
} else switch (c) {
case ENQ: if (sendbark()) {
SM_ERROR;
} else {
SM_PROCEED(recv_req);
}
break;
case CAN: Syslog('+', "Remote refused to accept request");
SM_PROCEED(recv_req);
break;
case 'C':
case NAK: PUTCHAR(EOT);
SM_PROCEED(send_req);
break;
case SUB: SM_PROCEED(send_req);
break;
default: Syslog('s', "got '%s' waiting ENQ", printablec(c));
SM_PROCEED(send_req);
break;
}
SM_STATE(recv_req)
if (recvbark()) {
if (sentmail && rcvdmail) {
Syslog('+', "Consider session OK");
session_state = STATE_SECURE;
SM_SUCCESS;
} else {
SM_ERROR;
}
} else {
session_state = STATE_SECURE;
SM_SUCCESS;
}
SM_END
SM_RETURN
SM_DECL(recvfiles,(char *)"recvfiles")
SM_STATES
recv_packet,
scan_packet,
recv_file
SM_NAMES
(char *)"recv_packet",
(char *)"scan_packet",
(char *)"recv_file"
SM_EDECL
int rc = 0, ghc = 0;
char recvpktname[16];
char *fpath, *tpath;
FILE *fp;
faddr f, t;
fa_list **tmpl;
SM_START(recv_packet)
Loaded = FALSE;
SM_STATE(recv_packet)
snprintf(recvpktname,16, "%08x.pkt", sequencer());
if ((rc = xmrecv(recvpktname)) == 1) {
SM_SUCCESS;
} else if (rc == 0) {
if (master) {
SM_PROCEED(recv_file);
} else {
SM_PROCEED(scan_packet);
}
} else {
SM_ERROR;
}
SM_STATE(scan_packet)
/*
* We cannot use the temp inbound per node yet, FTS-0001 does it's
* handshake by sending us a .pkt file, we store this in the old
* style ../tmp/ dir in the unprotected inbound.
*/
fpath = xstrcpy(CFG.inbound);
fpath = xstrcat(fpath,(char *)"/tmp/");
fpath = xstrcat(fpath,recvpktname);
mkdirs(fpath, 0700);
fp = fopen(fpath,"r");
if (fp == NULL) {
WriteError("$cannot open received packet");
free(fpath);
SM_ERROR;
}
switch ((ghc = getheader(&f , &t, fp, recvpktname, TRUE))) {
case 3: Syslog('+', "remote mistook us for %s",ascfnode(&t,0x1f));
fclose(fp);
Syslog('s', "Unlink %s rc=%d", fpath, unlink(fpath));
free(fpath);
SM_ERROR;
case 0:
case 5: fclose(fp);
if (nodelock(&f, mypid)) {
/*
* Lock failed, FTSC-0001 allowes only one aka, so abort session.
*/
Syslog('+', "address : %s is locked, abort", ascfnode(&f, 0x1f));
Syslog('s', "Unlink %s rc=%d", fpath, unlink(fpath));
free(fpath);
SM_ERROR;
}
Syslog('+', "accepting session");
for (tmpl = &remote; *tmpl; tmpl = &((*tmpl)->next));
(*tmpl)=(fa_list*)malloc(sizeof(fa_list));
(*tmpl)->next=NULL;
(*tmpl)->addr=(faddr*)malloc(sizeof(faddr));
(*tmpl)->addr->zone=f.zone;
(*tmpl)->addr->net=f.net;
(*tmpl)->addr->node=f.node;
(*tmpl)->addr->point=f.point;
(*tmpl)->addr->name=NULL;
(*tmpl)->addr->domain=NULL;
Syslog('+', "address : %s",ascfnode((*tmpl)->addr,0x1f));
/*
* With the loaded flag we prevent removing the noderecord
* when the remote presents us an address we don't know about.
*/
if (!Loaded) {
if (noderecord((*tmpl)->addr))
Loaded = TRUE;
}
history.aka.zone = remote->addr->zone;
history.aka.net = remote->addr->net;
history.aka.node = remote->addr->node;
history.aka.point = remote->addr->point;
if (remote->addr->domain && strlen(remote->addr->domain))
snprintf(history.aka.domain, 13, "%s", printable(remote->addr->domain, 0));
if (((nlent=getnlent(remote->addr))) && (nlent->pflag != NL_DUMMY)) {
Syslog('+', "remote is a listed system");
strncpy(history.system_name, nlent->name, 35);
strncpy(history.location, nlent->location, 35);
strncpy(history.sysop, nlent->sysop, 35);
UserCity(mypid, nlent->sysop, nlent->location);
} else {
snprintf(history.system_name, 36, "Unknown");
snprintf(history.location, 36, "Somewhere");
}
if (nlent)
rdoptions(Loaded);
if (ghc == 0) {
Syslog('+', "Password correct, protected FTS-0001 session");
inbound_open(remote->addr, TRUE, FALSE);
session_state = STATE_SECURE;
} else {
Syslog('+', "Unsecure FTS-0001 session");
inbound_open(remote->addr, FALSE, FALSE);
session_state = STATE_UNSECURE;
}
/*
* Move the packet to the temp inbound so the we can later
* move it to the final inbound.
*/
tpath = xstrcpy(tempinbound);
tpath = xstrcat(tpath,(char *)"/");
tpath = xstrcat(tpath,recvpktname);
Syslog('s', "Move %s to %s rc=%d", fpath, tpath, file_mv(fpath, tpath));
free(fpath);
free(tpath);
tosend = create_filelist(remote,(char *)ALL_MAIL,1);
if (rc == 0) {
SM_PROCEED(recv_file);
} else {
SM_SUCCESS;
}
default:
Syslog('+', "received bad packet apparently from",ascfnode(&f,0x1f));
fclose(fp);
Syslog('s', "Unlink %s rc=%d", fpath, unlink(fpath));
free(fpath);
SM_ERROR;
}
SM_STATE(recv_file)
switch (xmrecv(NULL)) {
case 0: SM_PROCEED(recv_file);
break;
case 1: SM_SUCCESS;
break;
default: SM_ERROR;
break;
}
SM_END
SM_RETURN