From c01b504c272ecb821e53037815147a606d7fe87d Mon Sep 17 00:00:00 2001 From: Michiel Broek Date: Sun, 16 Jun 2002 16:44:38 +0000 Subject: [PATCH] Binkp receiver supports CRC --- ChangeLog | 4 + mbcico/binkp.c | 1571 +++++++++++++++++++++++++----------------------- 2 files changed, 814 insertions(+), 761 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5e1d23d9..0e9fae74 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,8 @@ $Id$ v0.35.01 05-Jun-2002 +DO NOT USE THIS VERSION, IT WON'T WORK !!!!!! + general: Added structures for netmail routing file. Expanded nodes structures for FTP and Directory transfers. @@ -23,6 +25,8 @@ v0.35.01 05-Jun-2002 The binkd version string now includes the OS and CPU type. If a transmitted file via binkp is skipped by the remote it will stay in the queue for the next session. + The binkp receiver now supports the CRC option. + The binkp transmitter doesn't right now, sessions will fail!!!!! mbfile: Added -v commandline switch to supress virus checking for the diff --git a/mbcico/binkp.c b/mbcico/binkp.c index 8680ae7d..d2f65d90 100644 --- a/mbcico/binkp.c +++ b/mbcico/binkp.c @@ -87,7 +87,7 @@ static int CRAMflag = FALSE; static int CRCflag = FALSE; unsigned long nethold, mailhold; int transferred = FALSE; -int batchnr = 0; +int batchnr = 0, crc_errors = 0; @@ -297,7 +297,7 @@ to: void binkp_settimer(int interval) { - Timer = time((time_t*)NULL) + interval; + Timer = time((time_t*)NULL) + interval; } @@ -318,19 +318,19 @@ int binkp_expired(void) void b_banner(int); void b_banner(int originate) { - time_t t; + time_t t; - binkp_send_control(MM_NUL,"SYS %s", CFG.bbs_name); - binkp_send_control(MM_NUL,"ZYZ %s", CFG.sysop_name); - binkp_send_control(MM_NUL,"LOC %s", CFG.location); - binkp_send_control(MM_NUL,"NDL %s", CFG.Flags); - t = time(NULL); - binkp_send_control(MM_NUL,"TIME %s", rfcdate(t)); - binkp_send_control(MM_NUL,"VER mbcico/%s/%s-%s binkp/1.0", VERSION, OsName(), OsCPU()); - if (strlen(CFG.Phone)) - binkp_send_control(MM_NUL,"PHN %s", CFG.Phone); - if (strlen(CFG.comment)) - binkp_send_control(MM_NUL,"OPM %s", CFG.comment); + binkp_send_control(MM_NUL,"SYS %s", CFG.bbs_name); + binkp_send_control(MM_NUL,"ZYZ %s", CFG.sysop_name); + binkp_send_control(MM_NUL,"LOC %s", CFG.location); + binkp_send_control(MM_NUL,"NDL %s", CFG.Flags); + t = time(NULL); + binkp_send_control(MM_NUL,"TIME %s", rfcdate(t)); + binkp_send_control(MM_NUL,"VER mbcico/%s/%s-%s binkp/1.0", VERSION, OsName(), OsCPU()); + if (strlen(CFG.Phone)) + binkp_send_control(MM_NUL,"PHN %s", CFG.Phone); + if (strlen(CFG.comment)) + binkp_send_control(MM_NUL,"OPM %s", CFG.comment); } @@ -338,43 +338,45 @@ void b_banner(int originate) void b_nul(char *); void b_nul(char *msg) { - if (strncmp(msg, "SYS ", 4) == 0) { - Syslog('+', "System : %s", msg+4); - strncpy(history.system_name, msg+4, 35); - } else if (strncmp(msg, "ZYZ ", 4) == 0) { - Syslog('+', "Sysop : %s", msg+4); - strncpy(history.sysop, msg+4, 35); - } else if (strncmp(msg, "LOC ", 4) == 0) { - Syslog('+', "Location: %s", msg+4); - strncpy(history.location, msg+4, 35); - } else if (strncmp(msg, "NDL ", 4) == 0) - Syslog('+', "Flags : %s", msg+4); - else if (strncmp(msg, "TIME ", 5) == 0) - Syslog('+', "Time : %s", msg+5); - else if (strncmp(msg, "VER ", 4) == 0) - Syslog('+', "Uses : %s", msg+4); - else if (strncmp(msg, "PHN ", 4) == 0) - Syslog('+', "Phone : %s", msg+4); - else if (strncmp(msg, "OPM ", 4) == 0) - Syslog('+', "Remark : %s", msg+4); - else if (strncmp(msg, "TRF ", 4) == 0) - Syslog('+', "Binkp: remote has %s mail/files for us", msg+4); - else if (strncmp(msg, "OPT ", 4) == 0) { - Syslog('+', "Options : %s", msg+4); - if (strstr(msg, (char *)"NR") != NULL) - NRflag = TRUE; - if (strstr(msg, (char *)"MB") != NULL) - MBflag = TRUE; - if (strstr(msg, (char *)"ND") != NULL) - NDflag = TRUE; - if (strstr(msg, (char *)"CRYPT") != NULL) - CRYPTflag = TRUE; - if (strstr(msg, (char *)"CRAM-") != NULL) - CRAMflag = TRUE; - if (strstr(msg, (char *)"CRC") != NULL) - CRCflag = TRUE; - } else - Syslog('+', "M_NUL \"%s\"", msg); + if (strncmp(msg, "SYS ", 4) == 0) { + Syslog('+', "System : %s", msg+4); + strncpy(history.system_name, msg+4, 35); + } else if (strncmp(msg, "ZYZ ", 4) == 0) { + Syslog('+', "Sysop : %s", msg+4); + strncpy(history.sysop, msg+4, 35); + } else if (strncmp(msg, "LOC ", 4) == 0) { + Syslog('+', "Location: %s", msg+4); + strncpy(history.location, msg+4, 35); + } else if (strncmp(msg, "NDL ", 4) == 0) + Syslog('+', "Flags : %s", msg+4); + else if (strncmp(msg, "TIME ", 5) == 0) + Syslog('+', "Time : %s", msg+5); + else if (strncmp(msg, "VER ", 4) == 0) + Syslog('+', "Uses : %s", msg+4); + else if (strncmp(msg, "PHN ", 4) == 0) + Syslog('+', "Phone : %s", msg+4); + else if (strncmp(msg, "OPM ", 4) == 0) + Syslog('+', "Remark : %s", msg+4); + else if (strncmp(msg, "TRF ", 4) == 0) + Syslog('+', "Binkp: remote has %s mail/files for us", msg+4); + else if (strncmp(msg, "OPT ", 4) == 0) { + Syslog('+', "Options : %s", msg+4); + if (strstr(msg, (char *)"NR") != NULL) + NRflag = TRUE; + if (strstr(msg, (char *)"MB") != NULL) + MBflag = TRUE; + if (strstr(msg, (char *)"ND") != NULL) + NDflag = TRUE; + if (strstr(msg, (char *)"CRYPT") != NULL) + CRYPTflag = TRUE; + if (strstr(msg, (char *)"CRAM-") != NULL) + CRAMflag = TRUE; + if (strstr(msg, (char *)"CRC") != NULL) { + CRCflag = TRUE; + Syslog('b', "Switching to CRC32 mode"); + } + } else + Syslog('+', "M_NUL \"%s\"", msg); } @@ -384,188 +386,185 @@ void b_nul(char *msg) */ SM_DECL(orgbinkp, (char *)"orgbinkp") SM_STATES - waitconn, - sendpass, - waitaddr, - authremote, - waitok + waitconn, + sendpass, + waitaddr, + authremote, + waitok SM_NAMES - (char *)"waitconn", - (char *)"sendpass", - (char *)"waitaddr", - (char *)"authremote", - (char *)"waitok" + (char *)"waitconn", + (char *)"sendpass", + (char *)"waitaddr", + (char *)"authremote", + (char *)"waitok" SM_EDECL - faddr *primary; - char *p, *q; - int i, rc, bufl, cmd; - fa_list **tmp, *tmpa; - int SendPass = FALSE; - faddr *fa, ra; + faddr *primary; + char *p, *q; + int i, rc, bufl, cmd; + fa_list **tmp, *tmpa; + int SendPass = FALSE; + faddr *fa, ra; SM_START(waitconn) SM_STATE(waitconn) - Loaded = FALSE; - Syslog('+', "Start binkp session with %s", ascfnode(remote->addr, 0x1f)); - b_banner(TRUE); -// binkp_send_control(MM_NUL,"OPT NR"); - binkp_send_control(MM_NUL,"OPT MB"); + Loaded = FALSE; + Syslog('+', "Start binkp session with %s", ascfnode(remote->addr, 0x1f)); + b_banner(TRUE); + binkp_send_control(MM_NUL,"OPT MB CRC"); - /* - * Build a list of aka's to send, the primary aka first. - */ - ra.zone = remote->addr->zone; - ra.net = remote->addr->net; - ra.node = remote->addr->node; - ra.point = remote->addr->point; + /* + * Build a list of aka's to send, the primary aka first. + */ + ra.zone = remote->addr->zone; + ra.net = remote->addr->net; + ra.node = remote->addr->node; + ra.point = remote->addr->point; - primary = bestaka_s(remote->addr); - p = xstrcpy(ascfnode(primary, 0x1f)); + primary = bestaka_s(remote->addr); + p = xstrcpy(ascfnode(primary, 0x1f)); - /* - * Add all other aka's exept primary aka. - */ - for (i = 0; i < 40; i++) - if ((CFG.aka[i].zone) && (CFG.akavalid[i]) && - ((CFG.aka[i].zone != primary->zone) || (CFG.aka[i].net != primary->net) || - (CFG.aka[i].node != primary->node) || (CFG.aka[i].point!= primary->point))) { - p = xstrcat(p, (char *)" "); - p = xstrcat(p, aka2str(CFG.aka[i])); - } + /* + * Add all other aka's exept primary aka. + */ + for (i = 0; i < 40; i++) + if ((CFG.aka[i].zone) && (CFG.akavalid[i]) && + ((CFG.aka[i].zone != primary->zone) || (CFG.aka[i].net != primary->net) || + (CFG.aka[i].node != primary->node) || (CFG.aka[i].point!= primary->point))) { + p = xstrcat(p, (char *)" "); + p = xstrcat(p, aka2str(CFG.aka[i])); + } - binkp_send_control(MM_ADR, "%s", p); - free(p); - tidy_faddr(primary); - SM_PROCEED(sendpass) + binkp_send_control(MM_ADR, "%s", p); + free(p); + tidy_faddr(primary); + SM_PROCEED(sendpass) SM_STATE(sendpass) - if (strlen(nodes.Spasswd)) { - SendPass = TRUE; - binkp_send_control(MM_PWD, "%s", nodes.Spasswd); - } else { - binkp_send_control(MM_PWD, "-"); - } + if (strlen(nodes.Spasswd)) { + SendPass = TRUE; + binkp_send_control(MM_PWD, "%s", nodes.Spasswd); + } else { + binkp_send_control(MM_PWD, "-"); + } - SM_PROCEED(waitaddr) + SM_PROCEED(waitaddr) SM_STATE(waitaddr) - for (;;) { - if ((rc = binkp_recv_frame(rbuf, &bufl, &cmd))) { - Syslog('!', "Error receiving remote info"); - SM_ERROR; - } - - if (cmd) { - if (rbuf[0] == MM_ADR) { - p = xstrcpy(&rbuf[1]); - tidy_falist(&remote); - remote = NULL; - tmp = &remote; - - for (q = strtok(p, " "); q; q = strtok(NULL, " ")) - if ((fa = parsefnode(q))) { - *tmp = (fa_list*)malloc(sizeof(fa_list)); - (*tmp)->next = NULL; - (*tmp)->addr = fa; - tmp = &((*tmp)->next); - } else { - Syslog('!', "Bad remote address: \"%s\"", printable(q, 0)); - binkp_send_control(MM_ERR, "Bad address"); - } - - for (tmpa = remote; tmpa; tmpa = tmpa->next) { - Syslog('+', "Address : %s", ascfnode(tmpa->addr, 0x1f)); - if (nodelock(tmpa->addr)) { - binkp_send_control(MM_BSY, "Address %s locked", ascfnode(tmpa->addr, 0x1f)); - SM_ERROR; - } - - /* - * 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(tmpa->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; - sprintf(history.aka.domain, "%s", remote->addr->domain); - - SM_PROCEED(authremote) - - } else if (rbuf[0] == MM_BSY) { - Syslog('!', "Remote is busy"); - SM_ERROR; - - } else if (rbuf[0] == MM_ERR) { - Syslog('!', "Remote error: %s", &rbuf[1]); - SM_ERROR; - - } else if (rbuf[0] == MM_NUL) { - b_nul(&rbuf[1]); - } - } + for (;;) { + if ((rc = binkp_recv_frame(rbuf, &bufl, &cmd))) { + Syslog('!', "Error receiving remote info"); + SM_ERROR; } + if (cmd) { + if (rbuf[0] == MM_ADR) { + p = xstrcpy(&rbuf[1]); + tidy_falist(&remote); + remote = NULL; + tmp = &remote; + + for (q = strtok(p, " "); q; q = strtok(NULL, " ")) + if ((fa = parsefnode(q))) { + *tmp = (fa_list*)malloc(sizeof(fa_list)); + (*tmp)->next = NULL; + (*tmp)->addr = fa; + tmp = &((*tmp)->next); + } else { + Syslog('!', "Bad remote address: \"%s\"", printable(q, 0)); + binkp_send_control(MM_ERR, "Bad address"); + } + + for (tmpa = remote; tmpa; tmpa = tmpa->next) { + Syslog('+', "Address : %s", ascfnode(tmpa->addr, 0x1f)); + if (nodelock(tmpa->addr)) { + binkp_send_control(MM_BSY, "Address %s locked", ascfnode(tmpa->addr, 0x1f)); + SM_ERROR; + } + + /* + * 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(tmpa->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; + sprintf(history.aka.domain, "%s", remote->addr->domain); + + SM_PROCEED(authremote) + + } else if (rbuf[0] == MM_BSY) { + Syslog('!', "Remote is busy"); + SM_ERROR; + + } else if (rbuf[0] == MM_ERR) { + Syslog('!', "Remote error: %s", &rbuf[1]); + SM_ERROR; + + } else if (rbuf[0] == MM_NUL) { + b_nul(&rbuf[1]); + } + } + } + SM_STATE(authremote) - rc = 0; - for (tmpa = remote; tmpa; tmpa = tmpa->next) { - if ((tmpa->addr->zone == ra.zone) && - (tmpa->addr->net == ra.net) && - (tmpa->addr->node == ra.node) && - (tmpa->addr->point == ra.point)) { - rc = 1; - } + rc = 0; + for (tmpa = remote; tmpa; tmpa = tmpa->next) { + if ((tmpa->addr->zone == ra.zone) && (tmpa->addr->net == ra.net) && + (tmpa->addr->node == ra.node) && (tmpa->addr->point == ra.point)) { + rc = 1; } + } - if (rc) { - SM_PROCEED(waitok) - } else { - Syslog('!', "Error: the wrong node is reached"); - binkp_send_control(MM_ERR, "No AKAs in common or all AKAs busy"); - SM_ERROR; - } + if (rc) { + SM_PROCEED(waitok) + } else { + Syslog('!', "Error: the wrong node is reached"); + binkp_send_control(MM_ERR, "No AKAs in common or all AKAs busy"); + SM_ERROR; + } SM_STATE(waitok) - for (;;) { - if ((rc = binkp_recv_frame(rbuf, &bufl, &cmd))) { - Syslog('!', "Error waiting for remote acknowledge"); - SM_ERROR; - } - - if (cmd) { - if (rbuf[0] == MM_OK) { - if (SendPass) - Syslog('+', "Password protected BINKP session"); - else - Syslog('+', "Unprotected BINKP session"); - SM_SUCCESS; - - } else if (rbuf[0] == MM_BSY) { - Syslog('!', "Remote is busy"); - SM_ERROR; - - } else if (rbuf[0] == MM_ERR) { - Syslog('!', "Remote error: %s", &rbuf[1]); - SM_ERROR; - - } else if (rbuf[0] == MM_NUL) { - b_nul(&rbuf[1]); - } - } + for (;;) { + if ((rc = binkp_recv_frame(rbuf, &bufl, &cmd))) { + Syslog('!', "Error waiting for remote acknowledge"); + SM_ERROR; } + if (cmd) { + if (rbuf[0] == MM_OK) { + if (SendPass) + Syslog('+', "Password protected BINKP session"); + else + Syslog('+', "Unprotected BINKP session"); + SM_SUCCESS; + + } else if (rbuf[0] == MM_BSY) { + Syslog('!', "Remote is busy"); + SM_ERROR; + + } else if (rbuf[0] == MM_ERR) { + Syslog('!', "Remote error: %s", &rbuf[1]); + SM_ERROR; + + } else if (rbuf[0] == MM_NUL) { + b_nul(&rbuf[1]); + } + } + } + SM_END SM_RETURN @@ -576,162 +575,166 @@ SM_RETURN */ SM_DECL(ansbinkp, (char *)"ansbinkp") SM_STATES - waitconn, - waitaddr, - waitpwd, - pwdack + waitconn, + waitaddr, + waitpwd, + pwdack SM_NAMES - (char *)"waitconn", - (char *)"waitaddr", - (char *)"waitpwd", - (char *)"pwdack" + (char *)"waitconn", + (char *)"waitaddr", + (char *)"waitpwd", + (char *)"pwdack" SM_EDECL - char *p, *q; - int i, rc, bufl, cmd; - fa_list **tmp, *tmpa; - faddr *fa; + char *p, *q; + int i, rc, bufl, cmd; + fa_list **tmp, *tmpa; + faddr *fa; SM_START(waitconn) SM_STATE(waitconn) - Loaded = FALSE; - b_banner(FALSE); - p = xstrcpy((char *)""); + Loaded = FALSE; + b_banner(FALSE); + p = xstrcpy((char *)""); - for (i = 0; i < 40; i++) - if ((CFG.aka[i].zone) && (CFG.akavalid[i])) { - p = xstrcat(p, (char *)" "); - p = xstrcat(p, aka2str(CFG.aka[i])); - } + for (i = 0; i < 40; i++) + if ((CFG.aka[i].zone) && (CFG.akavalid[i])) { + p = xstrcat(p, (char *)" "); + p = xstrcat(p, aka2str(CFG.aka[i])); + } - binkp_send_control(MM_ADR, "%s", p); - free(p); - SM_PROCEED(waitaddr) + binkp_send_control(MM_ADR, "%s", p); + free(p); + SM_PROCEED(waitaddr) SM_STATE(waitaddr) - for (;;) { - if ((rc = binkp_recv_frame(rbuf, &bufl, &cmd))) { - Syslog('!', "Error waiting for remote info"); - SM_ERROR; - } - - if (cmd) { - if (rbuf[0] == MM_ADR) { - p = xstrcpy(&rbuf[1]); - tidy_falist(&remote); - remote = NULL; - tmp = &remote; - - for (q = strtok(p, " "); q; q = strtok(NULL, " ")) - if ((fa = parsefnode(q))) { - *tmp = (fa_list*)malloc(sizeof(fa_list)); - (*tmp)->next = NULL; - (*tmp)->addr = fa; - tmp = &((*tmp)->next); - } else { - Syslog('!', "Bad remote address: \"%s\"", printable(q, 0)); - binkp_send_control(MM_ERR, "Bad address"); - } - - for (tmpa = remote; tmpa; tmpa = tmpa->next) { - Syslog('+', "Address : %s", ascfnode(tmpa->addr, 0x1f)); - if (nodelock(tmpa->addr)) { - binkp_send_control(MM_BSY, "Address %s locked", ascfnode(tmpa->addr, 0x1f)); - SM_ERROR; - } - - /* - * 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(tmpa->addr)) - Loaded = TRUE; - } - } - - for (tmpa = remote; tmpa; tmpa = tmpa->next) { - if (((nlent = getnlent(tmpa->addr))) && - (nlent->pflag != NL_DUMMY)) { - Syslog('+', "Remote is a listed system"); - if (inbound) - free(inbound); - inbound = xstrcpy(CFG.inbound); - break; - } - } - if (nlent) - rdoptions(Loaded); - - if (MBflag) { - Syslog('b', "Remote supports MB"); - binkp_send_control(MM_NUL,"OPT MB"); - } - - history.aka.zone = remote->addr->zone; - history.aka.net = remote->addr->net; - history.aka.node = remote->addr->node; - history.aka.point = remote->addr->point; - sprintf(history.aka.domain, "%s", remote->addr->domain); - - SM_PROCEED(waitpwd) - - } else if (rbuf[0] == MM_ERR) { - Syslog('!', "Remote error: %s", &rbuf[1]); - SM_ERROR; - - } else if (rbuf[0] == MM_NUL) { - b_nul(&rbuf[1]); - } - } + for (;;) { + if ((rc = binkp_recv_frame(rbuf, &bufl, &cmd))) { + Syslog('!', "Error waiting for remote info"); + SM_ERROR; } + if (cmd) { + if (rbuf[0] == MM_ADR) { + p = xstrcpy(&rbuf[1]); + tidy_falist(&remote); + remote = NULL; + tmp = &remote; + + for (q = strtok(p, " "); q; q = strtok(NULL, " ")) + if ((fa = parsefnode(q))) { + *tmp = (fa_list*)malloc(sizeof(fa_list)); + (*tmp)->next = NULL; + (*tmp)->addr = fa; + tmp = &((*tmp)->next); + } else { + Syslog('!', "Bad remote address: \"%s\"", printable(q, 0)); + binkp_send_control(MM_ERR, "Bad address"); + } + + for (tmpa = remote; tmpa; tmpa = tmpa->next) { + Syslog('+', "Address : %s", ascfnode(tmpa->addr, 0x1f)); + if (nodelock(tmpa->addr)) { + binkp_send_control(MM_BSY, "Address %s locked", ascfnode(tmpa->addr, 0x1f)); + SM_ERROR; + } + + /* + * 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(tmpa->addr)) + Loaded = TRUE; + } + } + + for (tmpa = remote; tmpa; tmpa = tmpa->next) { + if (((nlent = getnlent(tmpa->addr))) && (nlent->pflag != NL_DUMMY)) { + Syslog('+', "Remote is a listed system"); + if (inbound) + free(inbound); + inbound = xstrcpy(CFG.inbound); + break; + } + } + if (nlent) + rdoptions(Loaded); + + if (MBflag) { + Syslog('b', "Remote supports MB"); + binkp_send_control(MM_NUL,"OPT MB"); + } + if (CRCflag) { + Syslog('b', "Remote supports CRC32"); + binkp_send_control(MM_NUL,"OPT CRC"); + } + + history.aka.zone = remote->addr->zone; + history.aka.net = remote->addr->net; + history.aka.node = remote->addr->node; + history.aka.point = remote->addr->point; + sprintf(history.aka.domain, "%s", remote->addr->domain); + + SM_PROCEED(waitpwd) + + } else if (rbuf[0] == MM_ERR) { + Syslog('!', "Remote error: %s", &rbuf[1]); + SM_ERROR; + + } else if (rbuf[0] == MM_NUL) { + b_nul(&rbuf[1]); + } + } + } + SM_STATE(waitpwd) - for (;;) { - if ((rc = binkp_recv_frame(rbuf, &bufl, &cmd))) { - Syslog('!', "Error waiting for password"); - SM_ERROR; - } - - if (cmd) { - if (rbuf[0] == MM_PWD) { - SM_PROCEED(pwdack) - - } else if (rbuf[0] == MM_ERR) { - Syslog('!', "Remote error: %s", &rbuf[1]); - SM_ERROR; - - } else if (rbuf[0] == MM_NUL) { - b_nul(&rbuf[1]); - } - } + for (;;) { + if ((rc = binkp_recv_frame(rbuf, &bufl, &cmd))) { + Syslog('!', "Error waiting for password"); + SM_ERROR; } + if (cmd) { + if (rbuf[0] == MM_PWD) { + SM_PROCEED(pwdack) + + } else if (rbuf[0] == MM_ERR) { + Syslog('!', "Remote error: %s", &rbuf[1]); + SM_ERROR; + + } else if (rbuf[0] == MM_NUL) { + b_nul(&rbuf[1]); + } + } + } + SM_STATE(pwdack) - if ((strcmp(&rbuf[1], "-") == 0) && !Loaded) { - Syslog('+', "Node not in setup, unprotected BINKP session"); - binkp_send_control(MM_OK, ""); - SM_SUCCESS; - } else if ((strcmp(&rbuf[1], "-") == 0) && Loaded && !strlen(nodes.Spasswd)) { - Syslog('+', "Node in setup but no session password, unprotected BINKP session"); - binkp_send_control(MM_OK, ""); - SM_SUCCESS; - } else if ((strcmp(&rbuf[1], nodes.Spasswd) == 0) && Loaded) { - Syslog('+', "Password OK, protected BINKP session"); - if (inbound) - free(inbound); - inbound = xstrcpy(CFG.pinbound); - binkp_send_control(MM_OK, ""); - SM_SUCCESS; - } else { - Syslog('?', "Password error: expected \"%s\", got \"%s\"", nodes.Spasswd, &rbuf[1]); - binkp_send_control(MM_ERR, "*** Password error, check setup ***"); - SM_ERROR; - } + + if ((strcmp(&rbuf[1], "-") == 0) && !Loaded) { + Syslog('+', "Node not in setup, unprotected BINKP session"); + binkp_send_control(MM_OK, ""); + SM_SUCCESS; + } else if ((strcmp(&rbuf[1], "-") == 0) && Loaded && !strlen(nodes.Spasswd)) { + Syslog('+', "Node in setup but no session password, unprotected BINKP session"); + binkp_send_control(MM_OK, ""); + SM_SUCCESS; + } else if ((strcmp(&rbuf[1], nodes.Spasswd) == 0) && Loaded) { + Syslog('+', "Password OK, protected BINKP session"); + if (inbound) + free(inbound); + inbound = xstrcpy(CFG.pinbound); + binkp_send_control(MM_OK, ""); + SM_SUCCESS; + } else { + Syslog('?', "Password error: expected \"%s\", got \"%s\"", nodes.Spasswd, &rbuf[1]); + binkp_send_control(MM_ERR, "*** Password error, check setup ***"); + SM_ERROR; + } SM_END SM_RETURN @@ -791,443 +794,489 @@ void debug_binkp_list(binkp_list **bll) int binkp_batch(file_list *to_send) { - int rc = 0, NotDone; - static char *txbuf, *rxbuf; - FILE *txfp = NULL; - FILE *rxfp = NULL; - int rxlen = 0, txlen = 0; - long txpos = 0, rxpos = 0; - long stxpos = 0; - int sverr, cmd = FALSE, GotFrame = FALSE; - int blklen = 0, c, Found = FALSE; - unsigned short header = 0; - char *rname, *lname, *gname, *rcrc; - long rsize, roffs, lsize, gsize, goffset; - time_t rtime, ltime, gtime; - off_t rxbytes; - long written; - binkp_list *bll = NULL, *tmp, *tmpg, *cursend = NULL; - file_list *tsl; - struct timeval rxtvstart, rxtvend; - struct timeval txtvstart, txtvend; - struct timezone tz; + int rc = 0, NotDone, rxlen = 0, txlen = 0, rxerror = FALSE; + static char *txbuf, *rxbuf; + FILE *txfp = NULL, *rxfp = NULL; + long txpos = 0, rxpos = 0, stxpos = 0, written, rsize, roffs, lsize, gsize, goffset; + int sverr, cmd = FALSE, GotFrame = FALSE, blklen = 0, c, Found = FALSE; + unsigned short header = 0; + char *rname, *lname, *gname; + time_t rtime, ltime, gtime; + unsigned long rcrc = 0, tcrc = 0, rxcrc = 0; + off_t rxbytes; + binkp_list *bll = NULL, *tmp, *tmpg, *cursend = NULL; + file_list *tsl; + struct timeval rxtvstart, rxtvend; + struct timeval txtvstart, txtvend; + struct timezone tz; - rxtvstart.tv_sec = rxtvstart.tv_usec = 0; - rxtvend.tv_sec = rxtvend.tv_usec = 0; - txtvstart.tv_sec = txtvstart.tv_usec = 0; - txtvend.tv_sec = txtvend.tv_usec = 0; - tz.tz_minuteswest = tz.tz_dsttime = 0; + rxtvstart.tv_sec = rxtvstart.tv_usec = 0; + rxtvend.tv_sec = rxtvend.tv_usec = 0; + txtvstart.tv_sec = txtvstart.tv_usec = 0; + txtvend.tv_sec = txtvend.tv_usec = 0; + tz.tz_minuteswest = tz.tz_dsttime = 0; - batchnr++; - Syslog('+', "Binkp: starting batch %d", batchnr); - txbuf = calloc(MAX_BLKSIZE + 3, sizeof(unsigned char)); - rxbuf = calloc(MAX_BLKSIZE + 3, sizeof(unsigned char)); - rname = calloc(512, sizeof(char)); - rcrc = calloc(512, sizeof(char)); - lname = calloc(512, sizeof(char)); - gname = calloc(512, sizeof(char)); - TfState = Switch; - RxState = RxWaitFile; - TxState = TxGetNextFile; - binkp_settimer(BINKP_TIMEOUT); - nethold = mailhold = 0L; - transferred = FALSE; + batchnr++; + Syslog('+', "Binkp: starting batch %d", batchnr); + txbuf = calloc(MAX_BLKSIZE + 3, sizeof(unsigned char)); + rxbuf = calloc(MAX_BLKSIZE + 3, sizeof(unsigned char)); + rname = calloc(512, sizeof(char)); + lname = calloc(512, sizeof(char)); + gname = calloc(512, sizeof(char)); + TfState = Switch; + RxState = RxWaitFile; + TxState = TxGetNextFile; + binkp_settimer(BINKP_TIMEOUT); + nethold = mailhold = 0L; + transferred = FALSE; - /* - * Build a new filelist from the existing filelist. - * This one is special for binkp behaviour. - */ - for (tsl = to_send; tsl; tsl = tsl->next) { - if (tsl->remote != NULL) - fill_binkp_list(&bll, tsl, 0L); - } - debug_binkp_list(&bll); + /* + * Build a new filelist from the existing filelist. + * This one is special for binkp behaviour. + */ + for (tsl = to_send; tsl; tsl = tsl->next) { + if (tsl->remote != NULL) + fill_binkp_list(&bll, tsl, 0L); + } + debug_binkp_list(&bll); - Syslog('+', "Binkp: mail %ld, files %ld bytes", nethold, mailhold); - binkp_send_control(MM_NUL, "TRF %ld %ld", nethold, mailhold); + Syslog('+', "Binkp: mail %ld, files %ld bytes", nethold, mailhold); + binkp_send_control(MM_NUL, "TRF %ld %ld", nethold, mailhold); - while ((RxState != RxDone) || (TxState != TxDone)) { + while ((RxState != RxDone) || (TxState != TxDone)) { - Nopper(); - if (binkp_expired()) { - Syslog('!', "Binkp: Transfer timeout"); - Syslog('b', "Binkp: TxState=%d, RxState=%d, rxlen=%d", TxState, RxState, rxlen); - RxState = RxDone; - TxState = TxDone; - binkp_send_control(MM_ERR, "Transfer timeout"); - rc = -2; - break; - } - - /* - * Receiver binkp frame - */ - for (;;) { - if (GotFrame) { - Syslog('b', "WARNING: frame not processed"); - break; - } else { - c = GETCHAR(0); - if (c < 0) { - c = -c; - if (c == STAT_TIMEOUT) { - usleep(1); - break; - } - Syslog('?', "Binkp: receiver status %s", ttystat[c]); - TxState = TxDone; - RxState = RxDone; - rc = -c; - break; - } else { - switch (rxlen) { - case 0: header = c << 8; - break; - case 1: header += c; - break; - default:rxbuf[rxlen-2] = c; - } - if (rxlen == 1) { - cmd = header & 0x8000; - blklen = header & 0x7fff; - } - if ((rxlen == (blklen + 1) && (rxlen >= 1))) { - GotFrame = TRUE; - binkp_settimer(BINKP_TIMEOUT); - rxbuf[rxlen-1] = '\0'; - break; - } - rxlen++; - } - } - } - - /* - * Transmitter state machine - */ - switch (TxState) { - case TxGetNextFile: - for (tmp = bll; tmp; tmp = tmp->next) { - if (tmp->state == NoState) { - /* - * There is something to send - */ - struct flock txflock; - - txflock.l_type = F_RDLCK; - txflock.l_whence = 0; - txflock.l_start = 0L; - txflock.l_len = 0L; - - txfp = fopen(tmp->local, "r"); - if (txfp == NULL) { - sverr = errno; - if ((sverr == ENOENT) || (sverr == EINVAL)) { - Syslog('+', "Binkp: file %s doesn't exist, removing", MBSE_SS(tmp->local)); - tmp->state = Got; - } else { - WriteError("$Binkp: can't open %s, skipping", MBSE_SS(tmp->local)); - tmp->state = Skipped; - } - break; - } - - if (fcntl(fileno(txfp), F_SETLK, &txflock) != 0) { - WriteError("$Binkp: can't lock file %s, skipping", MBSE_SS(tmp->local)); - fclose(txfp); - tmp->state = Skipped; - break; - } - - txpos = stxpos = tmp->offset; - Syslog('+', "Binkp: send \"%s\" as \"%s\"", MBSE_SS(tmp->local), MBSE_SS(tmp->remote)); - Syslog('+', "Binkp: size %lu bytes, dated %s", (unsigned long)tmp->size, date(tmp->date)); - binkp_send_control(MM_FILE, "%s %lu %ld %ld", MBSE_SS(tmp->remote), - (unsigned long)tmp->size, (long)tmp->date, (unsigned long)tmp->offset); - gettimeofday(&txtvstart, &tz); - tmp->state = Sending; - cursend = tmp; - TxState = TxTryRead; - transferred = TRUE; - break; - } /* if state == NoState */ - } /* for */ - - if (tmp == NULL) { - /* - * No more files to send - */ - TxState = TxWaitLastAck; - Syslog('b', "Binkp: transmitter to WaitLastAck"); - } - break; - - case TxTryRead: - /* - * Check if there is room in the output buffer - */ - if ((WAITPUTGET(-1) & 2) != 0) - TxState = TxReadSend; - break; - - case TxReadSend: - fseek(txfp, txpos, SEEK_SET); - txlen = fread(txbuf, 1, SND_BLKSIZE, txfp); - - if (txlen == 0) { - - if (ferror(txfp)) { - WriteError("$Binkp: error reading from file"); - TxState = TxGetNextFile; - cursend->state = Skipped; - debug_binkp_list(&bll); - break; - } - - /* - * Send empty dataframe, most binkp mailers need it to detect EOF. - */ - binkp_send_data(txbuf, 0); - - /* - * calculate time needed and bytes transferred - */ - gettimeofday(&txtvend, &tz); - - /* - * Close transmitter file - */ - fclose(txfp); - - if (txpos >= 0) { - stxpos = txpos - stxpos; - Syslog('+', "Binkp: OK %s", transfertime(txtvstart, txtvend, stxpos, TRUE)); - } else { - Syslog('+', "Binkp: transmitter skipped file after %ld seconds", - txtvend.tv_sec - txtvstart.tv_sec); - } - - cursend->state = IsSent; - TxState = TxGetNextFile; - break; - } else { - txpos += txlen; - sentbytes += txlen; - binkp_send_data(txbuf, txlen); - } - - TxState = TxTryRead; - break; - - case TxWaitLastAck: - debug_binkp_list(&bll); - NotDone = FALSE; - for (tmp = bll; tmp; tmp = tmp->next) - if ((tmp->state != Got) && (tmp->state != Skipped)) { - NotDone = TRUE; - break; - } - if (tmp == NULL) { - TxState = TxDone; - binkp_send_control(MM_EOB, ""); - Syslog('+', "Binkp: sending EOB"); - } - break; - - case TxDone: - break; - } - - /* - * Process received frame - */ - if (GotFrame) { - if (cmd) { - switch (rxbuf[0]) { - case MM_ERR: Syslog('+', "Binkp: got ERR: %s", rxbuf+1); - RxState = RxDone; - TxState = TxDone; - break; - - case MM_BSY: Syslog('+', "Binkp: got BSY: %s", rxbuf+1); - RxState = RxDone; - TxState = TxDone; - break; - - case MM_SKIP: Syslog('+', "Got SKIP frame"); - Syslogp('+', printable(rxbuf+1, 0)); - break; - - case MM_GET: Syslog('+', "Got GET frame"); - sscanf(rxbuf+1, "%s %ld %ld %ld", gname, &gsize, >ime, &goffset); - for (tmpg = bll; tmpg; tmpg = tmpg->next) { - if (strcasecmp(tmpg->remote, gname) == 0) { - tmpg->state = NoState; - tmpg->offset = goffset; - Syslog('+', "Remote wants %s again, offset %ld", gname, goffset); - TxState = TxGetNextFile; - } - } - break; - - case MM_GOT: sscanf(rxbuf+1, "%s %ld %ld", lname, &lsize, <ime); - Found = FALSE; - for (tmp = bll; tmp; tmp = tmp->next) - if ((strcmp(lname, tmp->remote) == 0) && - (lsize == tmp->size) && (ltime == tmp->date)) { - Syslog('+', "Binkp: remote GOT \"%s\"", tmp->remote); - tmp->state = Got; - Found = TRUE; - } - if (!Found) { - Syslog('!', "Binkp: unexpected GOT \"%s\"", rxbuf+1); - } - break; - - case MM_NUL: b_nul(rxbuf+1); - break; - - case MM_EOB: Syslog('+', "Binkp: received EOB"); - RxState = RxEndOfBatch; - break; - - case MM_FILE: if ((RxState == RxWaitFile) || (RxState == RxEndOfBatch)) { - RxState = RxAcceptFile; - Syslog('b', "MM_FILE %s", rxbuf+1); - if (strlen(rxbuf) < 512) { - /* - * Check against buffer overflow - */ - if (CRCflag) - sscanf(rxbuf+1, "%s %ld %ld %ld %s", rname, &rsize, &rtime, &roffs, rcrc); - else - sscanf(rxbuf+1, "%s %ld %ld %ld", rname, &rsize, &rtime, &roffs); - } else { - Syslog('+', "Got corrupted FILE frame, size %d bytes", strlen(rxbuf)); - } - } else { - Syslog('+', "Binkp: got unexpected FILE frame %s", rxbuf+1); - } - break; - - default: Syslog('+', "Binkp: Unexpected frame %d", rxbuf[0]); - } - } else { - if (blklen) { - if (RxState == RxReceData) { - written = fwrite(rxbuf, 1, blklen, rxfp); - if (!written && blklen) { - Syslog('+', "Binkp: file write error"); - RxState = RxDone; - } - rxpos += written; - if (rxpos == rsize) { - binkp_send_control(MM_GOT, "%s %ld %ld", rname, rsize, rtime); - closefile(TRUE); - rxpos = rxpos - rxbytes; - gettimeofday(&rxtvend, &tz); - Syslog('+', "Binkp: OK %s", transfertime(rxtvstart, rxtvend, rxpos, FALSE)); - rcvdbytes += rxpos; - RxState = RxWaitFile; - transferred = TRUE; - } - } else { - Syslog('+', "Binkp: unexpected DATA frame %d", rxbuf[0]); - } - } - } - GotFrame = FALSE; - rxlen = 0; - header = 0; - blklen = 0; - } - - switch (RxState) { - case RxWaitFile: - break; - - case RxAcceptFile: - Syslog('+', "Binkp: receive file \"%s\" date %s size %ld offset %ld", rname, date(rtime), rsize, roffs); - rxfp = openfile(rname, rtime, rsize, &rxbytes, resync); - gettimeofday(&rxtvstart, &tz); - rxpos = 0; - - if (!diskfree(CFG.freespace)) { - Syslog('+', "Binkp: low diskspace, sending BSY"); - binkp_send_control(MM_BSY, "Low diskspace, try again later"); - RxState = RxDone; - TxState = TxDone; - break; - } - - if (rsize == rxbytes) { - /* - * We already got this file, send GOT so it will - * be deleted at the remote. - */ - Syslog('+', "Binkp: already got %s, sending GOT", rname); - binkp_send_control(MM_GOT, "%s %ld %ld", rname, rsize, rtime); - RxState = RxWaitFile; - rxfp = NULL; - } else if (!rxfp) { - /* - * Some error, request to skip it - */ - Syslog('+', "Binkp: error file %s, sending SKIP", rname); - binkp_send_control(MM_SKIP, "%s %ld %ld", rname, rsize, rtime); - RxState = RxWaitFile; - } else { - RxState = RxReceData; - } - break; - - case RxReceData: - break; - - case RxEndOfBatch: - if (TxState == TxDone) - RxState = RxDone; - break; - - case RxDone: - break; - } + Nopper(); + if (binkp_expired()) { + Syslog('!', "Binkp: Transfer timeout"); + Syslog('b', "Binkp: TxState=%d, RxState=%d, rxlen=%d", TxState, RxState, rxlen); + RxState = RxDone; + TxState = TxDone; + binkp_send_control(MM_ERR, "Transfer timeout"); + rc = -2; + break; } - debug_binkp_list(&bll); - /* - * Process all send files. + * Receiver binkp frame */ - for (tsl = to_send; tsl; tsl = tsl->next) { - if (tsl->remote == NULL) { - execute_disposition(tsl); + for (;;) { + if (GotFrame) { + Syslog('b', "WARNING: frame not processed"); + break; + } else { + c = GETCHAR(0); + if (c < 0) { + c = -c; + if (c == STAT_TIMEOUT) { + usleep(1); + break; + } + Syslog('?', "Binkp: receiver status %s", ttystat[c]); + TxState = TxDone; + RxState = RxDone; + rc = -c; + break; } else { - for (tmp = bll; tmp; tmp = tmp->next) { - if ((strcmp(tmp->local, tsl->local) == 0) && (tmp->state == Got)) { - execute_disposition(tsl); - } - } + switch (rxlen) { + case 0: header = c << 8; + break; + case 1: header += c; + break; + default:rxbuf[rxlen-2] = c; + } + if (rxlen == 1) { + cmd = header & 0x8000; + blklen = header & 0x7fff; + } + if ((rxlen == (blklen + 1) && (rxlen >= 1))) { + GotFrame = TRUE; + binkp_settimer(BINKP_TIMEOUT); + rxbuf[rxlen-1] = '\0'; + break; + } + rxlen++; } + } } - for (tmp = bll; bll; bll = tmp) { - tmp = bll->next; - if (bll->local) - free(bll->local); - if (bll->remote) - free(bll->remote); - free(bll); + /* + * Transmitter state machine + */ + switch (TxState) { + case TxGetNextFile: + for (tmp = bll; tmp; tmp = tmp->next) { + if (tmp->state == NoState) { + /* + * There is something to send + */ + struct flock txflock; + + txflock.l_type = F_RDLCK; + txflock.l_whence = 0; + txflock.l_start = 0L; + txflock.l_len = 0L; + + if (CRCflag) + tcrc = file_crc(tmp->local, FALSE); + else + tcrc = 0; + Syslog('b', "File CRC is %lx", tcrc); + + txfp = fopen(tmp->local, "r"); + if (txfp == NULL) { + sverr = errno; + if ((sverr == ENOENT) || (sverr == EINVAL)) { + Syslog('+', "Binkp: file %s doesn't exist, removing", MBSE_SS(tmp->local)); + tmp->state = Got; + } else { + WriteError("$Binkp: can't open %s, skipping", MBSE_SS(tmp->local)); + tmp->state = Skipped; + } + break; + } + + if (fcntl(fileno(txfp), F_SETLK, &txflock) != 0) { + WriteError("$Binkp: can't lock file %s, skipping", MBSE_SS(tmp->local)); + fclose(txfp); + tmp->state = Skipped; + break; + } + + txpos = stxpos = tmp->offset; + Syslog('+', "Binkp: send \"%s\" as \"%s\"", MBSE_SS(tmp->local), MBSE_SS(tmp->remote)); + if (CRCflag && tcrc) { + Syslog('+', "Binkp: size %lu bytes, dated %s, crc %lx", (unsigned long)tmp->size, date(tmp->date), tcrc +5); + binkp_send_control(MM_FILE, "%s %lu %ld %ld %lx", MBSE_SS(tmp->remote), + (unsigned long)tmp->size, (long)tmp->date, (unsigned long)tmp->offset), tcrc; + } else { + Syslog('+', "Binkp: size %lu bytes, dated %s", (unsigned long)tmp->size, date(tmp->date)); + binkp_send_control(MM_FILE, "%s %lu %ld %ld", MBSE_SS(tmp->remote), + (unsigned long)tmp->size, (long)tmp->date, (unsigned long)tmp->offset); + } + gettimeofday(&txtvstart, &tz); + tmp->state = Sending; + cursend = tmp; + TxState = TxTryRead; + transferred = TRUE; + break; + } /* if state == NoState */ + } /* for */ + + if (tmp == NULL) { + /* + * No more files to send + */ + TxState = TxWaitLastAck; + Syslog('b', "Binkp: transmitter to WaitLastAck"); + } + break; + + case TxTryRead: + /* + * Check if there is room in the output buffer + */ + if ((WAITPUTGET(-1) & 2) != 0) + TxState = TxReadSend; + break; + + case TxReadSend: + fseek(txfp, txpos, SEEK_SET); + txlen = fread(txbuf, 1, SND_BLKSIZE, txfp); + + if (txlen == 0) { + + if (ferror(txfp)) { + WriteError("$Binkp: error reading from file"); + TxState = TxGetNextFile; + cursend->state = Skipped; + debug_binkp_list(&bll); + break; + } + + /* + * Send empty dataframe, most binkp mailers need it to detect EOF. + */ + binkp_send_data(txbuf, 0); + + /* + * calculate time needed and bytes transferred + */ + gettimeofday(&txtvend, &tz); + + /* + * Close transmitter file + */ + fclose(txfp); + + if (txpos >= 0) { + stxpos = txpos - stxpos; + Syslog('+', "Binkp: OK %s", transfertime(txtvstart, txtvend, stxpos, TRUE)); + } else { + Syslog('+', "Binkp: transmitter skipped file after %ld seconds", txtvend.tv_sec - txtvstart.tv_sec); + } + + cursend->state = IsSent; + TxState = TxGetNextFile; + break; + } else { + txpos += txlen; + sentbytes += txlen; + binkp_send_data(txbuf, txlen); + } + + TxState = TxTryRead; + break; + + case TxWaitLastAck: + debug_binkp_list(&bll); + NotDone = FALSE; + for (tmp = bll; tmp; tmp = tmp->next) + if ((tmp->state != Got) && (tmp->state != Skipped)) { + NotDone = TRUE; + break; + } + if (tmp == NULL) { + TxState = TxDone; + binkp_send_control(MM_EOB, ""); + Syslog('+', "Binkp: sending EOB"); + } + break; + + case TxDone: + break; } - free(txbuf); - free(rxbuf); - free(rname); - free(rcrc); - free(lname); - free(gname); - Syslog('+', "Binkp: batch %d completed rc=%d", batchnr, rc); - return rc; + /* + * Process received frame + */ + if (GotFrame) { + if (cmd) { + switch (rxbuf[0]) { + case MM_ERR: Syslog('+', "Binkp: got ERR: %s", rxbuf+1); + RxState = RxDone; + TxState = TxDone; + break; + + case MM_BSY: Syslog('+', "Binkp: got BSY: %s", rxbuf+1); + RxState = RxDone; + TxState = TxDone; + break; + + case MM_SKIP: Syslog('+', "Got SKIP frame"); + Syslogp('+', printable(rxbuf+1, 0)); + break; + + case MM_GET: Syslog('+', "Got GET frame"); + sscanf(rxbuf+1, "%s %ld %ld %ld", gname, &gsize, >ime, &goffset); + for (tmpg = bll; tmpg; tmpg = tmpg->next) { + if (strcasecmp(tmpg->remote, gname) == 0) { + tmpg->state = NoState; + tmpg->offset = goffset; + Syslog('+', "Remote wants %s again, offset %ld", gname, goffset); + TxState = TxGetNextFile; + } + } + break; + + case MM_GOT: sscanf(rxbuf+1, "%s %ld %ld", lname, &lsize, <ime); + Found = FALSE; + for (tmp = bll; tmp; tmp = tmp->next) + if ((strcmp(lname, tmp->remote) == 0) && (lsize == tmp->size) && (ltime == tmp->date)) { + Syslog('+', "Binkp: remote GOT \"%s\"", tmp->remote); + tmp->state = Got; + Found = TRUE; + } + if (!Found) { + Syslog('!', "Binkp: unexpected GOT \"%s\"", rxbuf+1); + } + break; + + case MM_NUL: b_nul(rxbuf+1); + break; + + case MM_EOB: Syslog('+', "Binkp: received EOB"); + RxState = RxEndOfBatch; + break; + + case MM_FILE: if ((RxState == RxWaitFile) || (RxState == RxEndOfBatch)) { + RxState = RxAcceptFile; + Syslog('b', "MM_FILE %s", rxbuf+1); + if (strlen(rxbuf) < 512) { + /* + * Check against buffer overflow + */ + rcrc = 0; + if (CRCflag) { + sscanf(rxbuf+1, "%s %ld %ld %ld %lx", rname, &rsize, &rtime, &roffs, &rcrc); + } else { + sscanf(rxbuf+1, "%s %ld %ld %ld", rname, &rsize, &rtime, &roffs); + } + Syslog('b', "Expecting CRC %lx", rcrc); + } else { + Syslog('+', "Got corrupted FILE frame, size %d bytes", strlen(rxbuf)); + } + } else { + Syslog('+', "Binkp: got unexpected FILE frame %s", rxbuf+1); + } + break; + + default: Syslog('+', "Binkp: Unexpected frame %d", rxbuf[0]); + } + } else { + if (blklen) { + if (RxState == RxReceData) { + written = fwrite(rxbuf, 1, blklen, rxfp); + if (CRCflag) + rxcrc = upd_crc32(rxbuf, rxcrc, blklen); + if (!written && blklen) { + Syslog('+', "Binkp: file write error"); + RxState = RxDone; + } + rxpos += written; + if (rxpos == rsize) { + if (CRCflag && rcrc) { + rxcrc = rxcrc ^ 0xffffffff; + Syslog('b', "File received crc %lx, expected %lx", rxcrc, rcrc); + if (rcrc == rxcrc) { + binkp_send_control(MM_GOT, "%s %ld %ld %lx", rname, rsize, rtime, rcrc); + } else { + rxerror = TRUE; + crc_errors++; + if (crc_errors < 3) { + binkp_send_control(MM_SKIP, "%s %ld %ld %lx", rname, rsize, rtime, rcrc); + WriteError("File CRC error nr %d, sending SKIP frame", crc_errors); + } else { + WriteError("File CRC error nr %d, aborting session", crc_errors); + binkp_send_control(MM_ERR, "Too much CRC errors, aborting session"); + RxState = RxDone; + } + } + } else { + /* + * ACK without CRC check + */ + binkp_send_control(MM_GOT, "%s %ld %ld", rname, rsize, rtime); + } + closefile(TRUE); + rxpos = rxpos - rxbytes; + gettimeofday(&rxtvend, &tz); + Syslog('+', "Binkp: %s %s", rxerror?"ERROR":"OK", transfertime(rxtvstart, rxtvend, rxpos, FALSE)); + rcvdbytes += rxpos; + RxState = RxWaitFile; + transferred = TRUE; + } + } else { + Syslog('+', "Binkp: unexpected DATA frame %d", rxbuf[0]); + } + } + } + GotFrame = FALSE; + rxlen = 0; + header = 0; + blklen = 0; + } + + /* + * Receiver state machine + */ + switch (RxState) { + case RxWaitFile: + break; + + case RxAcceptFile: + if (CRCflag) + Syslog('+', "Binkp: receive file \"%s\" date %s size %ld offset %ld crc %lx", + rname, date(rtime), rsize, roffs, rcrc); + else + Syslog('+', "Binkp: receive file \"%s\" date %s size %ld offset %ld", + rname, date(rtime), rsize, roffs); + rxfp = openfile(rname, rtime, rsize, &rxbytes, resync); + gettimeofday(&rxtvstart, &tz); + rxpos = 0; + rxcrc = 0xffffffff; + rxerror = FALSE; + + if (!diskfree(CFG.freespace)) { + Syslog('+', "Binkp: low diskspace, sending BSY"); + binkp_send_control(MM_BSY, "Low diskspace, try again later"); + RxState = RxDone; + TxState = TxDone; + break; + } + + if (rsize == rxbytes) { + /* + * We already got this file, send GOT so it will + * be deleted at the remote. + */ + Syslog('+', "Binkp: already got %s, sending GOT", rname); + if (CRCflag &rcrc) + binkp_send_control(MM_GOT, "%s %ld %ld %lx", rname, rsize, rtime, rcrc); + else + binkp_send_control(MM_GOT, "%s %ld %ld", rname, rsize, rtime); + RxState = RxWaitFile; + rxfp = NULL; + } else if (!rxfp) { + /* + * Some error, request to skip it + */ + Syslog('+', "Binkp: error file %s, sending SKIP", rname); + if (CRCflag && rcrc) + binkp_send_control(MM_SKIP, "%s %ld %ld %lx", rname, rsize, rtime, rcrc); + else + binkp_send_control(MM_SKIP, "%s %ld %ld", rname, rsize, rtime); + RxState = RxWaitFile; + } else { + RxState = RxReceData; + } + break; + + case RxReceData: + break; + + case RxEndOfBatch: + if (TxState == TxDone) + RxState = RxDone; + break; + + case RxDone: + break; + } + } + + debug_binkp_list(&bll); + + /* + * Process all send files. + */ + for (tsl = to_send; tsl; tsl = tsl->next) { + if (tsl->remote == NULL) { + execute_disposition(tsl); + } else { + for (tmp = bll; tmp; tmp = tmp->next) { + if ((strcmp(tmp->local, tsl->local) == 0) && (tmp->state == Got)) { + execute_disposition(tsl); + } + } + } + } + + for (tmp = bll; bll; bll = tmp) { + tmp = bll->next; + if (bll->local) + free(bll->local); + if (bll->remote) + free(bll->remote); + free(bll); + } + + free(txbuf); + free(rxbuf); + free(rname); + free(lname); + free(gname); + Syslog('+', "Binkp: batch %d completed rc=%d", batchnr, rc); + return rc; }