Rewrote binkp inbound handling and error recovery

This commit is contained in:
Michiel Broek 2005-09-12 13:47:09 +00:00
parent a25c4267df
commit c1dc37321d
15 changed files with 320 additions and 82 deletions

View File

@ -14,10 +14,12 @@ v0.71.6 02-Sep-2005
Due to lack of maintainers italian language support is dropped. Due to lack of maintainers italian language support is dropped.
mbcico: mbcico:
Changed compression state logic. Changed binkp compression state logic.
Record previous session state so we can better react on failed Record previous session state so we can better react on failed
sessions. sessions.
Added detection of remote options NR, ND and NDA. Added detection of remote options NR, ND and NDA.
Rewrote inbound handling for binkp sessions so that recovery
from failed sessions works, even with compressed transfers.
mbfido: mbfido:
If some newsarticles are not accepted for post, don't treat If some newsarticles are not accepted for post, don't treat

View File

@ -9,8 +9,8 @@ SRCS = zmmisc.c zmrle.c zmrecv.c zmsend.c binkp.c md5b.c \
answer.c chat.c dial.c dietifna.c emsidat.c filelist.c \ answer.c chat.c dial.c dietifna.c emsidat.c filelist.c \
openfile.c openport.c opentcp.c rdoptions.c yoohoo.c \ openfile.c openport.c opentcp.c rdoptions.c yoohoo.c \
recvbark.c respfreq.c sendbark.c tcp.c tcpproto.c wazoo.c \ recvbark.c respfreq.c sendbark.c tcp.c tcpproto.c wazoo.c \
filetime.c ftsc.c atoul.c portsel.c telnet.c \ filetime.c ftsc.c atoul.c portsel.c telnet.c bopenfile.c \
ttyio.c lutil.c scanout.c emsi.c ulock.c \ ttyio.c lutil.c scanout.c emsi.c ulock.c dirlock.c \
callstat.c session.c call.c mbcico.c \ callstat.c session.c call.c mbcico.c \
outstat.c nlinfo.c mbout.c outstat.c nlinfo.c mbout.c
HDRS = zmodem.h binkp.h config.h statetbl.h md5b.h \ HDRS = zmodem.h binkp.h config.h statetbl.h md5b.h \
@ -18,8 +18,8 @@ HDRS = zmodem.h binkp.h config.h statetbl.h md5b.h \
answer.h chat.h dial.h dietifna.h emsidat.h filelist.h \ answer.h chat.h dial.h dietifna.h emsidat.h filelist.h \
openfile.h openport.h opentcp.h rdoptions.h yoohoo.h \ openfile.h openport.h opentcp.h rdoptions.h yoohoo.h \
recvbark.h respfreq.h sendbark.h tcp.h tcpproto.h wazoo.h \ recvbark.h respfreq.h sendbark.h tcp.h tcpproto.h wazoo.h \
filetime.h ftsc.h atoul.h portsel.h telnet.h \ filetime.h ftsc.h atoul.h portsel.h telnet.h bopenfile.h \
ttyio.h lutil.h scanout.h emsi.h ulock.h \ ttyio.h lutil.h scanout.h emsi.h ulock.h dirlock.h \
callstat.h session.h call.h mbcico.h \ callstat.h session.h call.h mbcico.h \
outstat.h nlinfo.h outstat.h nlinfo.h
MBCICO_OBJS = zmmisc.o zmrle.o zmrecv.o zmsend.o binkp.o md5b.o \ MBCICO_OBJS = zmmisc.o zmrle.o zmrecv.o zmsend.o binkp.o md5b.o \
@ -27,8 +27,8 @@ MBCICO_OBJS = zmmisc.o zmrle.o zmrecv.o zmsend.o binkp.o md5b.o \
answer.o chat.o dial.o dietifna.o emsidat.o filelist.o \ answer.o chat.o dial.o dietifna.o emsidat.o filelist.o \
openfile.o openport.o opentcp.o rdoptions.o yoohoo.o \ openfile.o openport.o opentcp.o rdoptions.o yoohoo.o \
recvbark.o respfreq.o sendbark.o tcp.o tcpproto.o wazoo.o \ recvbark.o respfreq.o sendbark.o tcp.o tcpproto.o wazoo.o \
filetime.o ftsc.o atoul.o portsel.o telnet.o \ filetime.o ftsc.o atoul.o portsel.o telnet.o bopenfile.o \
ttyio.o lutil.o scanout.o emsi.o ulock.o \ ttyio.o lutil.o scanout.o emsi.o ulock.o dirlock.o \
callstat.o session.o call.o mbcico.o callstat.o session.o call.o mbcico.o
MBOUT_OBJS = outstat.o nlinfo.o mbout.o scanout.o callstat.o MBOUT_OBJS = outstat.o nlinfo.o mbout.o scanout.o callstat.o
SLIBS = ../lib/libmbse.a ../lib/libmsgbase.a ../lib/libdbase.a ../lib/libnodelist.a SLIBS = ../lib/libmbse.a ../lib/libmsgbase.a ../lib/libdbase.a ../lib/libnodelist.a
@ -90,14 +90,14 @@ zmmisc.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ttyio.h session.h zmode
zmrle.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ttyio.h session.h zmodem.h zmrle.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ttyio.h session.h zmodem.h
zmrecv.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h lutil.h ttyio.h session.h zmodem.h config.h emsi.h openfile.h filelist.h openport.h zmrecv.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h lutil.h ttyio.h session.h zmodem.h config.h emsi.h openfile.h filelist.h openport.h
zmsend.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ttyio.h session.h zmodem.h lutil.h emsi.h filelist.h zmsend.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ttyio.h session.h zmodem.h lutil.h emsi.h filelist.h
binkp.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/nodelist.h ../lib/mbsedb.h ttyio.h session.h statetbl.h config.h emsi.h openfile.h respfreq.h filelist.h opentcp.h rdoptions.h lutil.h binkp.h config.h md5b.h inbound.h callstat.h binkp.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/nodelist.h ../lib/mbsedb.h ttyio.h session.h statetbl.h config.h emsi.h bopenfile.h respfreq.h filelist.h opentcp.h rdoptions.h lutil.h binkp.h config.h md5b.h inbound.h callstat.h mbcico.h
md5b.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h lutil.h md5b.h md5b.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h lutil.h md5b.h
xmsend.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h session.h ttyio.h statetbl.h xmsend.h m7send.h filelist.h filetime.h xmsend.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h session.h ttyio.h statetbl.h xmsend.h m7send.h filelist.h filetime.h
xmrecv.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h session.h ttyio.h statetbl.h config.h lutil.h openfile.h m7recv.h xmrecv.h filelist.h filetime.h xmrecv.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h session.h ttyio.h statetbl.h config.h lutil.h openfile.h m7recv.h xmrecv.h filelist.h filetime.h
m7recv.o: ../config.h ../lib/mbselib.h statetbl.h ttyio.h m7recv.h m7recv.o: ../config.h ../lib/mbselib.h statetbl.h ttyio.h m7recv.h
m7send.o: ../config.h ../lib/mbselib.h statetbl.h ttyio.h m7send.h m7send.o: ../config.h ../lib/mbselib.h statetbl.h ttyio.h m7send.h
hydra.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h session.h filelist.h filetime.h ttyio.h statetbl.h config.h emsi.h openfile.h lutil.h respfreq.h mbcico.h hydra.h hydra.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h session.h filelist.h filetime.h ttyio.h statetbl.h config.h emsi.h openfile.h lutil.h respfreq.h mbcico.h hydra.h
inbound.o: ../config.h ../lib/mbselib.h inbound.h inbound.o: ../config.h ../lib/mbselib.h dirlock.h inbound.h
answer.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/nodelist.h ../lib/mbsedb.h lutil.h session.h config.h answer.h openport.h portsel.h dial.h rdoptions.h mbcico.h answer.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/nodelist.h ../lib/mbsedb.h lutil.h session.h config.h answer.h openport.h portsel.h dial.h rdoptions.h mbcico.h
chat.o: ../config.h ../lib/mbselib.h config.h chat.h ttyio.h chat.o: ../config.h ../lib/mbselib.h config.h chat.h ttyio.h
dial.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/nodelist.h ../lib/mbsedb.h config.h chat.h ttyio.h session.h dial.h dial.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/nodelist.h ../lib/mbsedb.h config.h chat.h ttyio.h session.h dial.h
@ -120,15 +120,17 @@ ftsc.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h session.h ttyio.h statetb
atoul.o: ../config.h ../lib/mbselib.h atoul.h atoul.o: ../config.h ../lib/mbselib.h atoul.h
portsel.o: ../config.h ../lib/mbselib.h portsel.h portsel.o: ../config.h ../lib/mbselib.h portsel.h
telnet.o: ../config.h ../lib/mbselib.h telnet.h telnet.o: ../config.h ../lib/mbselib.h telnet.h
bopenfile.o: ../config.h ../lib/mbselib.h config.h lutil.h bopenfile.h
ttyio.o: ../config.h ../lib/mbselib.h ttyio.h lutil.h ttyio.o: ../config.h ../lib/mbselib.h ttyio.h lutil.h
lutil.o: ../config.h ../lib/mbselib.h lutil.h lutil.o: ../config.h ../lib/mbselib.h lutil.h
scanout.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/mbsedb.h config.h scanout.h lutil.h scanout.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/mbsedb.h config.h scanout.h lutil.h
emsi.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/nodelist.h ../lib/mbsedb.h ttyio.h session.h statetbl.h config.h emsi.h emsidat.h hydra.h rdoptions.h tcp.h wazoo.h inbound.h callstat.h emsi.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/nodelist.h ../lib/mbsedb.h ttyio.h session.h statetbl.h config.h emsi.h emsidat.h hydra.h rdoptions.h tcp.h wazoo.h inbound.h callstat.h
ulock.o: ../config.h ../lib/mbselib.h ulock.o: ../config.h ../lib/mbselib.h
dirlock.o: ../config.h ../lib/mbselib.h dirlock.h
callstat.o: ../config.h ../lib/mbselib.h callstat.h callstat.o: ../config.h ../lib/mbselib.h callstat.h
session.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ttyio.h statetbl.h emsi.h ftsc.h session.h yoohoo.h mbcico.h binkp.h callstat.h inbound.h opentcp.h telnet.h session.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ttyio.h statetbl.h emsi.h ftsc.h session.h yoohoo.h mbcico.h binkp.h callstat.h inbound.h opentcp.h telnet.h
call.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/nodelist.h ../lib/mbsedb.h session.h callstat.h call.h config.h dial.h lutil.h portsel.h openport.h opentcp.h rdoptions.h inbound.h call.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/nodelist.h ../lib/mbsedb.h session.h callstat.h call.h config.h dial.h lutil.h portsel.h openport.h opentcp.h rdoptions.h inbound.h
mbcico.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ../lib/users.h ../lib/mbsedb.h config.h answer.h call.h lutil.h mbcico.h session.h mbcico.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ../lib/users.h ../lib/mbsedb.h config.h answer.h call.h lutil.h mbcico.h session.h binkp.h
outstat.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ../lib/users.h ../lib/mbsedb.h scanout.h callstat.h outstat.h outstat.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ../lib/users.h ../lib/mbsedb.h scanout.h callstat.h outstat.h
nlinfo.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h nlinfo.h nlinfo.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h nlinfo.h
mbout.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ../lib/users.h ../lib/mbsedb.h outstat.h nlinfo.h mbout.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ../lib/users.h ../lib/mbsedb.h outstat.h nlinfo.h

View File

@ -39,7 +39,7 @@
#include "statetbl.h" #include "statetbl.h"
#include "config.h" #include "config.h"
#include "emsi.h" #include "emsi.h"
#include "openfile.h" #include "bopenfile.h"
#include "respfreq.h" #include "respfreq.h"
#include "filelist.h" #include "filelist.h"
#include "opentcp.h" #include "opentcp.h"
@ -50,6 +50,7 @@
#include "md5b.h" #include "md5b.h"
#include "inbound.h" #include "inbound.h"
#include "callstat.h" #include "callstat.h"
#include "mbcico.h"
/* /*
@ -74,6 +75,9 @@ extern pid_t mypid;
extern struct sockaddr_in peeraddr; extern struct sockaddr_in peeraddr;
extern int most_debug; extern int most_debug;
extern int laststat; extern int laststat;
extern int crashme;
int gotblock = 0;
extern unsigned long sentbytes; extern unsigned long sentbytes;
@ -171,7 +175,6 @@ struct binkprec {
#endif #endif
struct timezone tz; /* Timezone */ struct timezone tz; /* Timezone */
int DidSendGET; /* Receiver send GET status */
char *txbuf; /* Transmitter buffer */ char *txbuf; /* Transmitter buffer */
int txlen; /* Transmitter file length */ int txlen; /* Transmitter file length */
@ -246,7 +249,6 @@ void parse_m_nul(char *); /* Parse M_NUL message */
int binkp_poll_frame(void); /* Poll for a frame */ int binkp_poll_frame(void); /* Poll for a frame */
void binkp_add_message(char *frame); /* Add cmd frame to queue */ void binkp_add_message(char *frame); /* Add cmd frame to queue */
int binkp_process_messages(void); /* Process the queue */ int binkp_process_messages(void); /* Process the queue */
int binkp_resync(off_t); /* File resync */
char *unix2binkp(char *); /* Binkp -> Unix escape */ char *unix2binkp(char *); /* Binkp -> Unix escape */
char *binkp2unix(char *); /* Unix -> Binkp escape */ char *binkp2unix(char *); /* Unix -> Binkp escape */
void fill_binkp_list(binkp_list **, file_list *, off_t); /* Build pending files */ void fill_binkp_list(binkp_list **, file_list *, off_t); /* Build pending files */
@ -281,7 +283,6 @@ int binkp(int role)
bp.rname = calloc(512, sizeof(char)); bp.rname = calloc(512, sizeof(char));
bp.ropts = calloc(512, sizeof(char)); bp.ropts = calloc(512, sizeof(char));
bp.rxfp = NULL; bp.rxfp = NULL;
bp.DidSendGET = FALSE;
bp.local_EOB = FALSE; bp.local_EOB = FALSE;
bp.remote_EOB = FALSE; bp.remote_EOB = FALSE;
bp.msgs_on_queue = 0; bp.msgs_on_queue = 0;
@ -317,7 +318,6 @@ int binkp(int role)
#endif #endif
#endif #endif
bp.buggyIrex = FALSE; bp.buggyIrex = FALSE;
laststat = 0;
bp.NRwe = No; bp.NRwe = No;
bp.NRthey = No; bp.NRthey = No;
bp.NDwe = No; bp.NDwe = No;
@ -653,7 +653,6 @@ SM_STATE(WaitOk)
SM_STATE(Opts) SM_STATE(Opts)
Syslog('b', "Binkp: last session was %d", laststat);
IsDoing("Binkp to %s", ascfnode(remote->addr, 0xf)); IsDoing("Binkp to %s", ascfnode(remote->addr, 0xf));
binkp_set_comp_state(); binkp_set_comp_state();
SM_SUCCESS; SM_SUCCESS;
@ -924,7 +923,7 @@ SM_STATE(PwdAck)
} }
free(pw); free(pw);
Syslog('+', "Binkp: %s%sprotected session", bp.CRAMflag ? "MD5 ":"", bp.Secure ? "":"un"); Syslog('+', "Binkp: %s%sprotected session", bp.CRAMflag ? "MD5 ":"", bp.Secure ? "":"un");
inbound_open(remote->addr, bp.Secure); inbound_open(remote->addr, bp.Secure, TRUE);
binkp_send_command(MM_OK, "%ssecure", bp.Secure ? "":"non-"); binkp_send_command(MM_OK, "%ssecure", bp.Secure ? "":"non-");
SM_PROCEED(Opts) SM_PROCEED(Opts)
@ -952,7 +951,6 @@ SM_STATE(Opts)
binkp_send_comp_opts(); binkp_send_comp_opts();
binkp_set_comp_state(); binkp_set_comp_state();
Syslog('b', "Binkp: last session status %d", laststat);
SM_SUCCESS; SM_SUCCESS;
@ -982,6 +980,7 @@ int file_transfer(void)
bp.TxState = TxGNF; bp.TxState = TxGNF;
bp.FtState = Switch; bp.FtState = Switch;
bp.messages = 0; bp.messages = 0;
Syslog('b', "Binkp: last session was %d", laststat);
break; break;
case Switch: if ((bp.RxState == RxDone) && (bp.TxState == TxDone)) { case Switch: if ((bp.RxState == RxDone) && (bp.TxState == TxDone)) {
@ -1184,21 +1183,24 @@ TrType binkp_receiver(void)
#endif #endif
(void)binkp2unix(bp.rname); (void)binkp2unix(bp.rname);
rxbytes = bp.rxbytes; rxbytes = bp.rxbytes;
bp.rxfp = openfile(binkp2unix(bp.rname), bp.rtime, bp.rsize, &rxbytes, binkp_resync);
/*
* Open file if M_FILE frame has offset 0
* Else the file is already open.
*/
if (bp.roffs && (bp.roffs == rxbytes)) {
Syslog('b', "Binkp: offset == rxbytes, don't open file again");
if (fseek(bp.rxfp, bp.roffs, SEEK_SET) == 0)
Syslog('b', "Binkp: file position set to %ld", bp.roffs);
else
WriteError("$Binkp: can't fseek to %ld", bp.roffs);
} else {
bp.rxfp = bopenfile(binkp2unix(bp.rname), bp.rtime, bp.rsize, &rxbytes);
}
bp.rxbytes = rxbytes; bp.rxbytes = rxbytes;
bp.rxcompressed = 0; bp.rxcompressed = 0;
if (bp.DidSendGET) {
Syslog('b', "Binkp: DidSendGET is set");
/*
* The file was partly received, via the openfile the resync function
* has send a GET command to start this file with a offset. This means
* we will get a new FILE command to open this file with a offset.
*/
bp.RxState = RxWaitF;
return Ok;
}
gettimeofday(&rxtvstart, &bp.tz); gettimeofday(&rxtvstart, &bp.tz);
bp.rxpos = bp.roffs; bp.rxpos = bp.roffs;
@ -1215,7 +1217,7 @@ TrType binkp_receiver(void)
if ((bp.rsize / (sfs.f_bsize + 1)) >= sfs.f_bfree) { if ((bp.rsize / (sfs.f_bsize + 1)) >= sfs.f_bfree) {
Syslog('!', "Binkp: only %lu blocks free (need %lu) in %s for this file", sfs.f_bfree, Syslog('!', "Binkp: only %lu blocks free (need %lu) in %s for this file", sfs.f_bfree,
(unsigned long)(bp.rsize / (sfs.f_bsize + 1)), tempinbound); (unsigned long)(bp.rsize / (sfs.f_bsize + 1)), tempinbound);
closefile(); bclosefile(FALSE);
bp.rxfp = NULL; /* Force SKIP command */ bp.rxfp = NULL; /* Force SKIP command */
} }
} }
@ -1233,6 +1235,14 @@ TrType binkp_receiver(void)
return Failure; return Failure;
else else
return Ok; return Ok;
} else if ((bp.rxbytes < bp.rsize) && (bp.roffs == 0) && bp.rxbytes) {
Syslog('+', "Binkp: partial file present, resync");
rc = binkp_send_command(MM_GET, "%s %ld %ld %ld", bp.rname, bp.rsize, bp.rtime, bp.rxbytes);
bp.RxState = RxWaitF;
if (rc)
return Failure;
else
return Ok;
} else if (!bp.rxfp) { } else if (!bp.rxfp) {
/* /*
* Some error, request to skip it * Some error, request to skip it
@ -1245,7 +1255,7 @@ TrType binkp_receiver(void)
else else
return Ok; return Ok;
} else { } else {
Syslog('b', "rsize=%d, rxbytes=%d, roffs=%d", bp.rsize, bp.rxbytes, bp.roffs); Syslog('b', "Binkp: rsize=%d, rxbytes=%d, roffs=%d, goto RxReceD", bp.rsize, bp.rxbytes, bp.roffs);
bp.RxState = RxReceD; bp.RxState = RxReceD;
return Ok; return Ok;
} }
@ -1278,7 +1288,7 @@ TrType binkp_receiver(void)
return Ok; return Ok;
} else if (bcmd == MM_FILE) { } else if (bcmd == MM_FILE) {
Syslog('+', "Binkp: partial received file, saving"); Syslog('+', "Binkp: partial received file, saving");
closefile(); bclosefile(FALSE);
bp.rxfp = NULL; bp.rxfp = NULL;
bp.RxState = RxAccF; bp.RxState = RxAccF;
return Continue; return Continue;
@ -1371,7 +1381,7 @@ TrType binkp_receiver(void)
if (bp.rxpos == bp.rsize) { if (bp.rxpos == bp.rsize) {
rc = binkp_send_command(MM_GOT, "%s %ld %ld", bp.rname, bp.rsize, bp.rtime); rc = binkp_send_command(MM_GOT, "%s %ld %ld", bp.rname, bp.rsize, bp.rtime);
closefile(); bclosefile(TRUE);
bp.rxpos = bp.rxpos - bp.rxbytes; bp.rxpos = bp.rxpos - bp.rxbytes;
gettimeofday(&rxtvend, &bp.tz); gettimeofday(&rxtvend, &bp.tz);
#if defined(HAVE_ZLIB_H) || defined(HAVE_BZLIB_H) #if defined(HAVE_ZLIB_H) || defined(HAVE_BZLIB_H)
@ -2383,6 +2393,11 @@ int binkp_poll_frame(void)
} }
} else { } else {
Syslog('b', "Binkp: rcvd data (%d)", bp.rxlen -1); Syslog('b', "Binkp: rcvd data (%d)", bp.rxlen -1);
gotblock++;
if (crashme && (gotblock > 10)) {
Syslog('b', "Binkp: will crash now");
die(SIGHUP);
}
} }
binkp_settimer(BINKP_TIMEOUT); binkp_settimer(BINKP_TIMEOUT);
Nopper(); Nopper();
@ -2648,26 +2663,6 @@ int binkp_pendingfiles(void)
/*
* This function is called two times if a partial file exists from openfile.
* 1. A partial file is detected, send a GET to the remote, set DidSendGET flag.
* 2. DidSendGET is set, return 0 and let openfile open the file in append mode.
*/
int binkp_resync(off_t off)
{
Syslog('b', "Binkp: resync(%d) DidSendGET=%s", off, bp.DidSendGET ?"TRUE":"FALSE");
if (!bp.DidSendGET) {
binkp_send_command(MM_GET, "%s %ld %ld %ld", bp.rname, bp.rsize, bp.rtime, off);
bp.DidSendGET = TRUE;
Syslog('+', "Binkp: already %lu bytes received, requested restart with offset", (unsigned long)off);
return -1; /* Signal openfile not to open the file */
}
bp.DidSendGET = FALSE;
return 0; /* Signal openfile to open the file in append mode */
}
/* /*
* Translate string to binkp escaped string, unsafe characters are escaped. * Translate string to binkp escaped string, unsafe characters are escaped.
*/ */
@ -3142,3 +3137,21 @@ int decompress_abort(int type, void *data)
#endif #endif
/*
* Abort, called from die in case there were errors.
* This will reconstruct file data that is still in
* compressed state in memory so that resync works.
*/
void binkp_abort(void)
{
Syslog('b', "Binkp: abort");
#ifdef USE_EXPERIMENT
if ((bp.rmode != CompNone) && z_idata)
decompress_abort(bp.rmode, z_idata);
if ((bp.tmode != CompNone) && z_odata)
compress_abort(bp.tmode, z_odata);
#endif
}

View File

@ -96,6 +96,7 @@ typedef struct _the_queue {
int binkp(int); int binkp(int);
void binkp_abort(void);
#endif #endif

View File

@ -163,7 +163,7 @@ int bclosefile(int success)
* Remove state file. * Remove state file.
*/ */
temp = calloc(PATH_MAX, sizeof(char)); temp = calloc(PATH_MAX, sizeof(char));
snprintf(temp, PATH_MAX, "%s.state", infpath, basename(infpath)); snprintf(temp, PATH_MAX, "%s.state", infpath);
if (unlink(temp)) if (unlink(temp))
WriteError("$Binkp: can't unlink %s", temp); WriteError("$Binkp: can't unlink %s", temp);
else else

9
mbcico/bopenfile.h Normal file
View File

@ -0,0 +1,9 @@
/* $Id$ */
#ifndef _BOPENFILE_H
#define _BOPENFILE_H
FILE *bopenfile(char *, time_t, off_t, off_t *);
int bclosefile(int);
#endif

View File

@ -207,7 +207,7 @@ int call(faddr *addr)
Syslog('?', "Warning: calling non-CM system outside ZMH"); Syslog('?', "Warning: calling non-CM system outside ZMH");
} }
inbound_open(addr, TRUE); /* master sessions are secure */ inbound_open(addr, TRUE, (tcp_mode == TCPMODE_IBN)); /* master sessions are secure */
/* /*
* Call when: * Call when:

149
mbcico/dirlock.c Normal file
View File

@ -0,0 +1,149 @@
/*****************************************************************************
*
* $Id$
* Purpose ...............: Lock a directory
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "dirlock.h"
#define TMPNAME "TMP."
#define LCKNAME "LOCKFILE"
/*
* Put a lock on a directory.
*/
int lockdir(char *directory)
{
char *Tmpfile, *lockfile;
FILE *fp;
pid_t oldpid;
Tmpfile = calloc(PATH_MAX, sizeof(char));
lockfile = calloc(PATH_MAX, sizeof(char));
snprintf(Tmpfile, PATH_MAX, "%s/", directory);
strcpy(lockfile, Tmpfile);
snprintf(Tmpfile + strlen(Tmpfile), PATH_MAX, "%s%u", TMPNAME, getpid());
snprintf(lockfile + strlen(lockfile), PATH_MAX - strlen(lockfile), "%s", LCKNAME);
if ((fp = fopen(Tmpfile, "w")) == NULL) {
WriteError("$Can't create lockfile \"%s\"", Tmpfile);
free(Tmpfile);
free(lockfile);
return FALSE;
}
fprintf(fp, "%10u\n", getpid());
fclose(fp);
while (TRUE) {
if (link(Tmpfile, lockfile) == 0) {
unlink(Tmpfile);
free(Tmpfile);
free(lockfile);
return TRUE;
}
if ((fp = fopen(lockfile, "r")) == NULL) {
WriteError("$Can't open lockfile \"%s\"", Tmpfile);
unlink(Tmpfile);
free(Tmpfile);
free(lockfile);
return FALSE;
}
if (fscanf(fp, "%u", &oldpid) != 1) {
WriteError("$Can't read old pid from \"%s\"", Tmpfile);
fclose(fp);
unlink(Tmpfile);
free(Tmpfile);
free(lockfile);
return FALSE;
}
fclose(fp);
if (kill(oldpid,0) == -1) {
if (errno == ESRCH) {
Syslog('+', "Stale lock found for pid %u", oldpid);
unlink(lockfile);
/* no return, try lock again */
} else {
WriteError("$Kill for %u failed",oldpid);
unlink(Tmpfile);
free(Tmpfile);
free(lockfile);
return FALSE;
}
} else {
Syslog('+', "Already locked by, pid=%u", oldpid);
unlink(Tmpfile);
free(Tmpfile);
free(lockfile);
return FALSE;
}
}
}
/*
* Unlock directory, make extra check to see if it is our own lock.
*/
void ulockdir(char *directory)
{
char *lockfile;
FILE *fp;
pid_t oldpid;
lockfile = calloc(PATH_MAX, sizeof(char));
snprintf(lockfile, PATH_MAX, "%s/", directory);
snprintf(lockfile + strlen(lockfile), PATH_MAX - strlen(lockfile), "%s", LCKNAME);
if ((fp = fopen(lockfile, "r")) == NULL) {
/*
* No lockfile found, so not removed.
*/
free(lockfile);
return;
}
if (fscanf(fp, "%u", &oldpid) != 1) {
WriteError("$Can't read old pid from \"%s\"", lockfile);
} else {
if (getpid() != oldpid) {
WriteError("Attempt to remove lock %s of pid %d", lockfile, oldpid);
} else {
/*
* Only remove our own lock.
*/
unlink(lockfile);
}
}
fclose(fp);
free(lockfile);
}

9
mbcico/dirlock.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef _DIRLOCK_H
#define _DIRLOCK_H
/* $Id$ */
int lockdir(char *);
void ulockdir(char *);
#endif

View File

@ -175,7 +175,7 @@ int rx_emsi(char *data)
Syslog('?', "Unexpected remote password \"%s\"", MBSE_SS(emsi_local_password)); Syslog('?', "Unexpected remote password \"%s\"", MBSE_SS(emsi_local_password));
} }
inbound_open(remote->addr, protect); inbound_open(remote->addr, protect, FALSE);
Syslog('i', "local lcodes 0x%04x, protos 0x%04x, opts 0x%04x", emsi_local_lcodes,emsi_local_protos,emsi_local_opts); Syslog('i', "local lcodes 0x%04x, protos 0x%04x, opts 0x%04x", emsi_local_lcodes,emsi_local_protos,emsi_local_opts);
if ((rc=txemsi())) if ((rc=txemsi()))

View File

@ -461,10 +461,10 @@ SM_STATE(scan_packet)
if (ghc == 0) { if (ghc == 0) {
Syslog('+', "Password correct, protected FTS-0001 session"); Syslog('+', "Password correct, protected FTS-0001 session");
inbound_open(remote->addr, TRUE); inbound_open(remote->addr, TRUE, FALSE);
} else { } else {
Syslog('+', "Unsecure FTS-0001 session"); Syslog('+', "Unsecure FTS-0001 session");
inbound_open(remote->addr, FALSE); inbound_open(remote->addr, FALSE, FALSE);
} }
/* /*
* Move the packet to the temp inbound so the we can later * Move the packet to the temp inbound so the we can later

View File

@ -1,7 +1,6 @@
/***************************************************************************** /*****************************************************************************
* *
* $Id$ * $Id$
* File ..................: mbcico/inbound.c
* Purpose ...............: Fidonet mailer, inbound functions * Purpose ...............: Fidonet mailer, inbound functions
* *
***************************************************************************** *****************************************************************************
@ -31,28 +30,27 @@
#include "../config.h" #include "../config.h"
#include "../lib/mbselib.h" #include "../lib/mbselib.h"
#include "dirlock.h"
#include "inbound.h" #include "inbound.h"
extern char *inbound; extern char *inbound;
extern char *tempinbound; extern char *tempinbound;
extern int gotfiles; extern int gotfiles;
extern int laststat;
/* /*
* Open the inbound directory, set the temp inbound for the node * Open the inbound directory, set the temp inbound for the node
* so that this is true multiline safe. All files received from * so that this is true multiline safe. All files received from
* the node during the session are stored here. * the node during the session are stored here.
* For binkp we add one extra directory to queue incoming files.
*/ */
int inbound_open(faddr *addr, int protected, int binkp_mode)
int inbound_open(faddr *addr, int protected)
{ {
char *temp; char *temp;
DIR *dp;
if (inbound) if (inbound)
free(inbound); free(inbound);
inbound = NULL; inbound = NULL;
@ -63,8 +61,22 @@ int inbound_open(faddr *addr, int protected)
temp = calloc(PATH_MAX, sizeof(char)); temp = calloc(PATH_MAX, sizeof(char));
snprintf(temp, PATH_MAX -1, "%s/tmp.%d.%d.%d.%d", inbound, addr->zone, addr->net, addr->node, addr->point); snprintf(temp, PATH_MAX -1, "%s/tmp.%d.%d.%d.%d", inbound, addr->zone, addr->net, addr->node, addr->point);
/*
* Check if this directory already exist, it should not unless the previous
* session with this node failed for some reason.
*/
if ((dp = opendir(temp))) {
Syslog('s', "Binkp: dir %s already exists, previous session failed", temp);
laststat++;
closedir(dp);
}
tempinbound = xstrcpy(temp); tempinbound = xstrcpy(temp);
snprintf(temp, PATH_MAX -1, "%s/foobar", tempinbound); if (binkp_mode)
snprintf(temp, PATH_MAX, "%s/tmp/foobar", tempinbound);
else
snprintf(temp, PATH_MAX, "%s/foobar", tempinbound);
mkdirs(temp, 0700); mkdirs(temp, 0700);
free(temp); free(temp);
@ -86,7 +98,7 @@ int inbound_close(int success)
struct dirent *de; struct dirent *de;
char *source, *dest; char *source, *dest;
struct stat stb; struct stat stb;
int rc; int i, rc;
Syslog('s', "Closing temp inbound after a %s session", success?"good":"failed"); Syslog('s', "Closing temp inbound after a %s session", success?"good":"failed");
if (! success) { if (! success) {
@ -100,6 +112,24 @@ int inbound_close(int success)
return 0; return 0;
} }
/*
* Try to lock the inbound so we can safely move the files
* to the inbound.
*/
i = 30;
while (TRUE) {
if (lockdir(inbound))
break;
i--;
if (! i) {
WriteError("Can't lock %s", inbound);
return 1;
}
sleep(20);
Nopper();
}
Syslog('s', "inbound_close(): %s locked", inbound);
if ((dp = opendir(tempinbound)) == NULL) { if ((dp = opendir(tempinbound)) == NULL) {
WriteError("$Can't open %s", tempinbound); WriteError("$Can't open %s", tempinbound);
return 1; return 1;
@ -109,8 +139,8 @@ int inbound_close(int success)
dest = calloc(PATH_MAX, sizeof(char)); dest = calloc(PATH_MAX, sizeof(char));
while ((de = readdir(dp))) { while ((de = readdir(dp))) {
snprintf(source, PATH_MAX -1, "%s/%s", tempinbound, de->d_name); snprintf(source, PATH_MAX, "%s/%s", tempinbound, de->d_name);
snprintf(dest, PATH_MAX -1, "%s/%s", inbound, de->d_name); snprintf(dest, PATH_MAX, "%s/%s", inbound, de->d_name);
if ((lstat(source, &stb) == 0) && (S_ISREG(stb.st_mode))) { if ((lstat(source, &stb) == 0) && (S_ISREG(stb.st_mode))) {
if (file_exist(dest, F_OK) == 0) { if (file_exist(dest, F_OK) == 0) {
Syslog('!', "Cannot move %s to %s, file exists", de->d_name, inbound); Syslog('!', "Cannot move %s to %s, file exists", de->d_name, inbound);
@ -126,19 +156,35 @@ int inbound_close(int success)
} }
closedir(dp); closedir(dp);
free(source); ulockdir(inbound);
free(dest); Syslog('s', "inbound_close(): %s unlocked", inbound);
/*
* Try to remove binkp tmp queue. Only log if not empty, else
* don't log anything, this directory doesn't exist for normal
* sessions.
*/
snprintf(source, PATH_MAX, "%s/tmp", tempinbound);
if ((rc = rmdir(source))) {
if (errno == ENOTEMPTY) {
Syslog('+', "Keep binkp temp incoming directory, partial file");
}
} else {
Syslog('s', "inbound_close(): removed %s", source);
}
/* /*
* Try to clean the temp inbound, if it fails log this, maybe the * Try to clean the temp inbound, if it fails log this, maybe the
* next time it will work. * next time it will work.
*/ */
if ((rc = rmdir(tempinbound))) { if ((rc = rmdir(tempinbound))) {
WriteError("Can't remove %s: %s", tempinbound, strerror(rc)); WriteError("$Can't remove %s", tempinbound);
} else { } else {
Syslog('s', "inbound_close(): removed %s", tempinbound); Syslog('s', "inbound_close(): removed %s", tempinbound);
} }
free(source);
free(dest);
free(tempinbound); free(tempinbound);
tempinbound = NULL; tempinbound = NULL;

View File

@ -1,11 +1,10 @@
/***************************************************************************** /*****************************************************************************
* *
* $Id$ * $Id$
* File ..................: mbcico/inbound.h
* Purpose ...............: Fidonet mailer, inbound functions * Purpose ...............: Fidonet mailer, inbound functions
* *
***************************************************************************** *****************************************************************************
* Copyright (C) 1997-2003 * Copyright (C) 1997-2005
* *
* Michiel Broek FIDO: 2:280/2802 * Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10 * Beekmansbos 10
@ -33,8 +32,8 @@
#define _INBOUND_H #define _INBOUND_H
int inbound_open(faddr *, int); /* Open temp inbound */ int inbound_open(faddr *, int, int); /* Open temp inbound */
int inbound_close(int); /* Close temp inbound */ int inbound_close(int); /* Close temp inbound */
long inbound_space(void); /* Get free inbound space */ long inbound_space(void); /* Get free inbound space */
#endif #endif

View File

@ -39,6 +39,8 @@
#include "lutil.h" #include "lutil.h"
#include "mbcico.h" #include "mbcico.h"
#include "session.h" #include "session.h"
#include "binkp.h"
#define IEMSI 1 #define IEMSI 1
@ -59,6 +61,7 @@ unsigned long rcvdbytes = 0;
int tcp_mode = TCPMODE_NONE; int tcp_mode = TCPMODE_NONE;
int Loaded = FALSE; int Loaded = FALSE;
int telnet = FALSE; int telnet = FALSE;
int crashme = FALSE;
extern char *myname; extern char *myname;
@ -116,6 +119,7 @@ void die(int onsig)
WriteError("Terminated on signal %d (%s)", onsig, SigName[onsig]); WriteError("Terminated on signal %d (%s)", onsig, SigName[onsig]);
else else
Syslog('+', "Terminated with error %d", onsig); Syslog('+', "Terminated with error %d", onsig);
binkp_abort();
} }
if (sentbytes || rcvdbytes) { if (sentbytes || rcvdbytes) {
@ -232,7 +236,7 @@ int main(int argc, char *argv[])
setmyname(argv[0]); setmyname(argv[0]);
while ((c = getopt(argc,argv,"r:n:l:t:a:I:h")) != -1) { while ((c = getopt(argc,argv,"r:n:l:t:a:ch")) != -1) {
switch (c) { switch (c) {
case 'r': WriteError("commandline option -r is obsolete"); case 'r': WriteError("commandline option -r is obsolete");
break; break;
@ -265,6 +269,10 @@ int main(int argc, char *argv[])
case 'n': forcedphone = optarg; case 'n': forcedphone = optarg;
break; break;
case 'c': crashme = TRUE;
Syslog('+', "crashme is set");
break;
default: usage(); default: usage();
die(MBERR_COMMANDLINE); die(MBERR_COMMANDLINE);
} }

View File

@ -196,7 +196,7 @@ int rx_yoohoo(void)
} else } else
Syslog('s', "No YooHoo password check"); Syslog('s', "No YooHoo password check");
inbound_open(remote->addr, protect); inbound_open(remote->addr, protect, FALSE);
fillhello(localcaps,pwd); fillhello(localcaps,pwd);