Changed handshake and EMSI timers

This commit is contained in:
Michiel Broek 2003-08-23 21:15:16 +00:00
parent c519afe9dc
commit 4bd3c7dcde
3 changed files with 322 additions and 240 deletions

View File

@ -3,7 +3,15 @@ $Id$
WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!
Inbound file handling is changed, this version is under test and should NOT
be used on production systems
be used on production systems if you don't want to help debugging.
Handshake and EMSI is changed, please run this version with debugging on,
mbsetup 1.14.1 turn 5, 11 and 18 on at least. Report any problems and include
a piece of the logfile.
Before installing, make a copy of /opt/mbse/bin/mbcico so you can go back
if you experience any problems.
As far as I have tested, there should be no problems with this version.
WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!
@ -29,6 +37,11 @@ v0.37.6 10-Aug-2003
systems.
Fixed the binkp escape sequence which is wrong in the FSP.
A light improvement in session handshake setup timers.
Added EMSI handshake timers, this gives a more relaxed EMSI
handshake.
Set the EMSI receive failure count to 20 instead of 6, we can
now even accept buggy maindoor sessions and still display a
banner.
v0.37.5 12-Jul-2003 - 10-Aug-2003

View File

@ -271,196 +271,222 @@ int tx_emsi(char *data)
SM_DECL(rxemsi,(char *)"rxemsi")
SM_STATES
waitpkt,
waitchar,
checkemsi,
getdat,
checkpkt,
checkdat,
sendnak,
sendack
init,
waitpkt,
waitchar,
checkemsi,
getdat,
checkpkt,
checkdat,
sendnak,
sendack
SM_NAMES
(char *)"waitpkt",
(char *)"waitchar",
(char *)"checkemsi",
(char *)"getdat",
(char *)"checkpkt",
(char *)"checkdat",
(char *)"sendnak",
(char *)"sendack"
(char *)"init",
(char *)"waitpkt",
(char *)"waitchar",
(char *)"checkemsi",
(char *)"getdat",
(char *)"checkpkt",
(char *)"checkdat",
(char *)"sendnak",
(char *)"sendack"
SM_EDECL
int c = 0;
unsigned short lcrc, rcrc;
int len;
int standby = 0, tries = 0;
char buf[13], *p;
char *databuf = NULL;
int c = 0;
unsigned short lcrc, rcrc;
int len;
int standby = 0, tries = 0;
char buf[13], *p;
char *databuf = NULL;
p = buf;
databuf = xstrcpy(intro);
p = buf;
databuf = xstrcpy(intro);
SM_START(checkpkt)
Syslog('i', "RXEMSI: start");
SM_START(init)
SM_STATE(init)
Syslog('i', "RXEMSI: init");
RESETTIMERS();
SETTIMER(0, 60);
SETTIMER(1, 20);
SM_PROCEED(checkpkt);
SM_STATE(waitpkt)
standby = 0;
SM_PROCEED(waitchar);
Syslog('i', "RXEMSI: waitpkt");
standby = 0;
SETTIMER(1, 20);
SM_PROCEED(waitchar);
SM_STATE(waitchar)
c = GETCHAR(5);
if (c == TIMEOUT) {
if (++tries > 9) {
Syslog('+', "Too many tries waiting EMSI handshake");
SM_ERROR;
} else {
SM_PROCEED(sendnak);
}
} else if (c < 0) {
SM_ERROR;
} else if ((c >= ' ') && (c <= '~')) {
if (c == '*') {
standby = 1;
p = buf;
*p = '\0';
} else if (standby) {
if ((p - buf) < (sizeof(buf) - 1)) {
*p++ = c;
*p = '\0';
} if ((p - buf) >= (sizeof(buf) - 1)) {
standby = 0;
SM_PROCEED(checkemsi);
}
}
} else switch(c) {
case DC1: break;
case '\n':
case '\r': standby = 0;
break;
default: standby = 0;
break;
}
Syslog('i', "RXEMSI: waitchar, tries=%d", tries);
if (EXPIRED(0)) {
Syslog('+', "EMSI receive 60 seconds timeout");
SM_ERROR;
}
if (EXPIRED(1)) {
Syslog('s', "20 sec timeout");
SM_PROCEED(sendnak);
}
c = GETCHAR(1);
if (c == TIMEOUT) {
SM_PROCEED(waitchar);
} else if (c < 0) {
SM_ERROR;
} else if ((c >= ' ') && (c <= '~')) {
if (c == '*') {
standby = 1;
p = buf;
*p = '\0';
} else if (standby) {
if ((p - buf) < (sizeof(buf) - 1)) {
*p++ = c;
*p = '\0';
} if ((p - buf) >= (sizeof(buf) - 1)) {
standby = 0;
SM_PROCEED(checkemsi);
}
}
} else {
switch(c) {
case DC1: break;
case '\n':
case '\r': standby = 0;
break;
default: standby = 0;
break;
}
}
SM_PROCEED(waitchar);
SM_STATE(checkemsi)
Syslog('i', "RXEMSI: rcvd %s", printable(buf, 0));
Syslog('i', "RXEMSI: rcvd %s", printable(buf, 0));
if (strncasecmp(buf, "EMSI_DAT",8) == 0) {
SM_PROCEED(getdat);
} else if (strncasecmp(buf, "EMSI_",5) == 0) {
if (databuf)
free(databuf);
databuf = xstrcpy(buf);
SM_PROCEED(checkpkt);
} else {
SM_PROCEED(waitpkt);
}
if (strncasecmp(buf, "EMSI_DAT",8) == 0) {
SM_PROCEED(getdat);
} else if (strncasecmp(buf, "EMSI_",5) == 0) {
if (databuf)
free(databuf);
databuf = xstrcpy(buf);
SM_PROCEED(checkpkt);
} else {
SM_PROCEED(waitpkt);
}
SM_STATE(getdat)
if (sscanf(buf+8,"%04x",&len) != 1) {
SM_PROCEED(sendnak);
}
if (sscanf(buf+8,"%04x",&len) != 1) {
SM_PROCEED(sendnak);
}
len += 16; /* strlen("EMSI_DATxxxxyyyy"), include CRC */
if (databuf)
free(databuf);
databuf = malloc(len + 1);
strcpy(databuf, buf);
p = databuf + strlen(databuf);
len += 16; /* strlen("EMSI_DATxxxxyyyy"), include CRC */
if (databuf)
free(databuf);
databuf = malloc(len + 1);
strcpy(databuf, buf);
p = databuf + strlen(databuf);
while (((p-databuf) < len) && ((c=GETCHAR(8)) >= 0)) {
*p++ = c;
*p = '\0';
}
while (((p-databuf) < len) && ((c=GETCHAR(8)) >= 0)) {
*p++ = c;
*p = '\0';
}
Syslog('i', "RXEMSI: rcvd %s (%d bytes)", databuf, len);
Syslog('i', "RXEMSI: rcvd %s (%d bytes)", databuf, len);
if (c == TIMEOUT) {
SM_PROCEED(sendnak);
} else if (c < 0) {
Syslog('+', "Error while reading EMSI_DAT packet");
SM_ERROR;
}
if (c == TIMEOUT) {
SM_PROCEED(sendnak);
} else if (c < 0) {
Syslog('+', "Error while reading EMSI_DAT packet");
SM_ERROR;
}
SM_PROCEED(checkdat);
SM_PROCEED(checkdat);
SM_STATE(checkpkt)
if (strncasecmp(databuf,"EMSI_DAT",8) == 0) {
SM_PROCEED(checkdat);
}
Syslog('i', "RXEMSI: checkpkt");
lcrc = crc16xmodem(databuf, 8);
sscanf(databuf + 8, "%04hx", &rcrc);
if (lcrc != rcrc) {
Syslog('+', "Got EMSI packet \"%s\" with bad crc: %04x/%04x", printable(databuf, 0), lcrc, rcrc);
SM_PROCEED(sendnak);
} if (strncasecmp(databuf, "EMSI_HBT", 8) == 0) {
tries = 0;
SM_PROCEED(waitpkt);
} else if (strncasecmp(databuf, "EMSI_INQ", 8) == 0) {
SM_PROCEED(sendnak);
} else {
SM_PROCEED(waitpkt);
}
if (strncasecmp(databuf,"EMSI_DAT",8) == 0) {
SM_PROCEED(checkdat);
}
lcrc = crc16xmodem(databuf, 8);
sscanf(databuf + 8, "%04hx", &rcrc);
if (lcrc != rcrc) {
Syslog('+', "Got EMSI packet \"%s\" with bad crc: %04x/%04x", printable(databuf, 0), lcrc, rcrc);
SM_PROCEED(sendnak);
} if (strncasecmp(databuf, "EMSI_HBT", 8) == 0) {
tries = 0;
SM_PROCEED(waitpkt);
} else if (strncasecmp(databuf, "EMSI_INQ", 8) == 0) {
SM_PROCEED(sendnak);
} else {
SM_PROCEED(waitpkt);
}
SM_STATE(checkdat)
sscanf(databuf + 8, "%04x", &len);
if (len != (strlen(databuf) - 16)) {
Syslog('+', "Bad EMSI_DAT length: %d/%d", len, strlen(databuf));
SM_PROCEED(sendnak);
}
/* Some FD versions send length of the packet including the
trailing CR. Arrrgh! Dirty overwork follows: */
if (*(p = databuf + strlen(databuf) - 1) == '\r')
*p='\0';
sscanf(databuf + strlen(databuf) - 4, "%04hx", &rcrc);
*(databuf + strlen(databuf) - 4) = '\0';
lcrc = crc16xmodem(databuf, strlen(databuf));
if (lcrc != rcrc) {
Syslog('+', "Got EMSI_DAT packet \"%s\" with bad crc: %04x/%04x", printable(databuf, 0), lcrc, rcrc);
SM_PROCEED(sendnak);
} if (scanemsidat(databuf + 12) == 0) {
SM_PROCEED(sendack);
} else {
Syslog('+', "Could not parse EMSI_DAT packet \"%s\"",databuf);
SM_ERROR;
}
sscanf(databuf + 8, "%04x", &len);
if (len != (strlen(databuf) - 16)) {
Syslog('+', "Bad EMSI_DAT length: %d/%d", len, strlen(databuf));
SM_PROCEED(sendnak);
}
/* Some FD versions send length of the packet including the
trailing CR. Arrrgh! Dirty overwork follows: */
if (*(p = databuf + strlen(databuf) - 1) == '\r')
*p='\0';
sscanf(databuf + strlen(databuf) - 4, "%04hx", &rcrc);
*(databuf + strlen(databuf) - 4) = '\0';
lcrc = crc16xmodem(databuf, strlen(databuf));
if (lcrc != rcrc) {
Syslog('+', "Got EMSI_DAT packet \"%s\" with bad crc: %04x/%04x", printable(databuf, 0), lcrc, rcrc);
SM_PROCEED(sendnak);
} if (scanemsidat(databuf + 12) == 0) {
SM_PROCEED(sendack);
} else {
Syslog('+', "Could not parse EMSI_DAT packet \"%s\"",databuf);
SM_ERROR;
}
SM_STATE(sendnak)
if (++tries > 9) {
Syslog('+', "Too many tries getting EMSI_DAT");
SM_ERROR;
} if (caller) {
PUTSTR((char *)"**EMSI_NAKEEC3\r\021");
Syslog('i', "RXEMSI: send **EMSI_NAKEEC3");
} else {
PUTSTR((char *)"**EMSI_REQA77E\r\021");
Syslog('i', "RXEMSI: send **EMSI_REQA77E");
if (tries > 1) {
PUTSTR((char *)"**EMSI_NAKEEC3\r\021");
Syslog('i', "RXEMSI: send **EMSI_NAKEEC3");
}
/*
* The FSC-0059 says 6 attempts, but to accept maindoor sessions
* we seem to need about 11, we set it to 20 since we also have
* a global 60 seconds timer running.
*/
if (++tries > 19) {
Syslog('+', "Too many tries getting EMSI_DAT");
SM_ERROR;
} if (caller) {
PUTSTR((char *)"**EMSI_NAKEEC3\r\021");
Syslog('i', "RXEMSI: send **EMSI_NAKEEC3");
} else {
PUTSTR((char *)"**EMSI_REQA77E\r\021");
Syslog('i', "RXEMSI: send **EMSI_REQA77E");
if (tries > 1) {
PUTSTR((char *)"**EMSI_NAKEEC3\r\021");
Syslog('i', "RXEMSI: send **EMSI_NAKEEC3");
}
SM_PROCEED(waitpkt);
}
SM_PROCEED(waitpkt);
SM_STATE(sendack)
Syslog('i', "RXEMSI: send **EMSI_ACKA490 (2 times)");
PUTSTR((char *)"**EMSI_ACKA490\r\021");
PUTSTR((char *)"**EMSI_ACKA490\r\021");
SM_SUCCESS;
Syslog('i', "RXEMSI: send **EMSI_ACKA490 (2 times)");
PUTSTR((char *)"**EMSI_ACKA490\r\021");
PUTSTR((char *)"**EMSI_ACKA490\r\021");
SM_SUCCESS;
SM_END
Syslog('i', "RXEMSI: end");
free(databuf);
Syslog('i', "RXEMSI: end");
free(databuf);
SM_RETURN
@ -469,117 +495,132 @@ SM_RETURN
SM_DECL(txemsi,(char *)"txemsi")
SM_STATES
senddata,
waitpkt,
waitchar,
checkpkt,
sendack
senddata,
waitpkt,
waitchar,
checkpkt,
sendack
SM_NAMES
(char *)"senddata",
(char *)"waitpkt",
(char *)"waitchar",
(char *)"checkpkt",
(char *)"sendack"
(char *)"senddata",
(char *)"waitpkt",
(char *)"waitchar",
(char *)"checkpkt",
(char *)"sendack"
SM_EDECL
int c;
unsigned short lcrc, rcrc;
int standby = 0, tries = 0;
char buf[13], *p;
char trailer[8];
int c;
unsigned short lcrc, rcrc;
int standby = 0, tries = 0;
char buf[13], *p;
char trailer[8];
p = buf;
memset(&buf, 0, sizeof(buf));
strncpy(buf, intro, sizeof(buf) - 1);
p = buf;
memset(&buf, 0, sizeof(buf));
strncpy(buf, intro, sizeof(buf) - 1);
RESETTIMERS();
SETTIMER(0, 60);
Syslog('i', "TXEMSI: 60 seconds timer set");
SM_START(senddata)
Syslog('i', "TXEMSI: start");
Syslog('i', "TXEMSI: start");
SM_STATE(senddata)
p = mkemsidat(caller);
PUTCHAR('*');
PUTCHAR('*');
PUTSTR(p);
sprintf(trailer, "%04X\r\021", crc16xmodem(p, strlen(p)));
PUTSTR(trailer);
Syslog('i', "TXEMSI: send **%s%04X", p, crc16xmodem(p, strlen(p)));
free(p);
SM_PROCEED(waitpkt);
p = mkemsidat(caller);
PUTCHAR('*');
PUTCHAR('*');
PUTSTR(p);
sprintf(trailer, "%04X\r\021", crc16xmodem(p, strlen(p)));
PUTSTR(trailer);
Syslog('i', "TXEMSI: send **%s%04X", p, crc16xmodem(p, strlen(p)));
free(p);
SETTIMER(1, 20);
SM_PROCEED(waitpkt);
SM_STATE(waitpkt)
standby = 0;
SM_PROCEED(waitchar);
standby = 0;
SM_PROCEED(waitchar);
SM_STATE(waitchar)
c = GETCHAR(8);
if (c == TIMEOUT) {
if (++tries > 9) {
Syslog('+', "too many tries sending EMSI");
SM_ERROR;
} else {
SM_PROCEED(senddata);
}
} else if (c < 0) {
SM_ERROR;
} else if ((c >= ' ') && (c <= '~')) {
if (c == '*') {
standby = 1;
p = buf;
*p = '\0';
} else if (standby) {
if ((p - buf) < (sizeof(buf) - 1)) {
*p++ = c;
*p = '\0';
} if ((p - buf) >= (sizeof(buf) - 1)) {
standby = 0;
SM_PROCEED(checkpkt);
}
}
} else switch(c) {
case DC1: SM_PROCEED(waitchar);
break;
case '\n':
case '\r': standby = 0;
break;
default: standby = 0;
break;
if (EXPIRED(0)) {
Syslog('+', "EMSI transmit 60 seconds timeout");
SM_ERROR;
}
if (EXPIRED(1)) {
Syslog('i', "TXEMSI: 20 seconds timeout");
if (++tries > 19) {
Syslog('+', "too many tries sending EMSI");
SM_ERROR;
} else {
SM_PROCEED(senddata);
}
}
c = GETCHAR(1);
if (c == TIMEOUT) {
SM_PROCEED(waitchar);
} else if (c < 0) {
SM_ERROR;
} else if ((c >= ' ') && (c <= '~')) {
if (c == '*') {
standby = 1;
p = buf;
*p = '\0';
} else if (standby) {
if ((p - buf) < (sizeof(buf) - 1)) {
*p++ = c;
*p = '\0';
} if ((p - buf) >= (sizeof(buf) - 1)) {
standby = 0;
SM_PROCEED(checkpkt);
}
}
} else
switch(c) {
case DC1: SM_PROCEED(waitchar);
break;
case '\n':
case '\r': standby = 0;
break;
default: standby = 0;
break;
}
SM_PROCEED(waitchar);
SM_STATE(checkpkt)
Syslog('i', "TXEMSI: rcvd %s", buf);
if (strncasecmp(buf, "EMSI_DAT", 8) == 0) {
SM_PROCEED(sendack);
} else if (strncasecmp(buf, "EMSI_", 5) == 0) {
lcrc = crc16xmodem(buf, 8);
sscanf(buf + 8, "%04hx", &rcrc);
if (lcrc != rcrc) {
Syslog('+', "Got EMSI packet \"%s\" with bad crc: %04x/%04x", printable(buf, 0), lcrc, rcrc);
SM_PROCEED(senddata);
} if (strncasecmp(buf, "EMSI_REQ", 8) == 0) {
SM_PROCEED(waitpkt);
} if (strncasecmp(buf, "EMSI_ACK", 8) == 0) {
SM_SUCCESS;
} else {
SM_PROCEED(senddata);
}
Syslog('i', "TXEMSI: rcvd %s", buf);
if (strncasecmp(buf, "EMSI_DAT", 8) == 0) {
SM_PROCEED(sendack);
} else if (strncasecmp(buf, "EMSI_", 5) == 0) {
lcrc = crc16xmodem(buf, 8);
sscanf(buf + 8, "%04hx", &rcrc);
if (lcrc != rcrc) {
Syslog('+', "Got EMSI packet \"%s\" with bad crc: %04x/%04x", printable(buf, 0), lcrc, rcrc);
SM_PROCEED(senddata);
} if (strncasecmp(buf, "EMSI_REQ", 8) == 0) {
SM_PROCEED(waitpkt);
} if (strncasecmp(buf, "EMSI_ACK", 8) == 0) {
SM_SUCCESS;
} else {
SM_PROCEED(waitpkt);
SM_PROCEED(senddata);
}
} else {
SM_PROCEED(waitpkt);
}
SM_STATE(sendack)
Syslog('i', "TXEMSI: send **EMSI_ACKA490 (2 times)");
PUTSTR((char *)"**EMSI_ACKA490\r\021");
PUTSTR((char *)"**EMSI_ACKA490\r\021");
SM_PROCEED(waitpkt);
Syslog('i', "TXEMSI: send **EMSI_ACKA490 (2 times)");
PUTSTR((char *)"**EMSI_ACKA490\r\021");
PUTSTR((char *)"**EMSI_ACKA490\r\021");
SM_PROCEED(waitpkt);
SM_END
Syslog('i', "TXEMSI: end");
Syslog('i', "TXEMSI: end");
SM_RETURN

View File

@ -388,12 +388,14 @@ SM_RETURN
SM_DECL(rx_define_type,(char *)"rx_define_type")
SM_STATES
sendintro,
settimer,
waitchar,
nextchar,
checkemsi,
getdat
SM_NAMES
(char *)"sendintro",
(char *)"settimer",
(char *)"waitchar",
(char *)"nextchar",
(char *)"checkemsi",
@ -413,17 +415,19 @@ SM_EDECL
ep=ebuf;
RESETTIMERS();
SETTIMER(0, 60);
SETTIMER(1, 20);
SM_START(sendintro)
SM_STATE(sendintro)
Syslog('s', "rxdefine_type SENDINTRO count=%d", count);
if (count++ > 6) {
Syslog('+', "Too many tries to get anything from the caller");
SM_ERROR;
}
Syslog('s', "rxdefine_type SENDINTRO count=%d", count);
standby = 0;
ep = ebuf;
ebuf[0] = '\0';
@ -447,9 +451,15 @@ SM_STATE(sendintro)
if (STATUS) {
SM_ERROR;
} else {
SM_PROCEED(waitchar);
SM_PROCEED(settimer);
}
SM_STATE(settimer)
Syslog('s', "Set 20 secs timer");
SETTIMER(1, 20);
SM_PROCEED(waitchar);
SM_STATE(waitchar)
if (EXPIRED(0)) {
@ -457,8 +467,13 @@ SM_STATE(waitchar)
SM_ERROR;
}
if ((c = GETCHAR(20)) == TIMEOUT) {
if (EXPIRED(1)) {
Syslog('s', "20 sec timer timeout");
SM_PROCEED(sendintro);
}
if ((c = GETCHAR(1)) == TIMEOUT) {
SM_PROCEED(waitchar);
} else if (c < 0) {
Syslog('+', "Session setup error");
SM_ERROR;
@ -515,7 +530,18 @@ SM_STATE(nextchar)
if (ebuf[0]) {
SM_PROCEED(checkemsi);
} else {
SM_PROCEED(sendintro);
/*
* If the 20 second timer is expired or after the
* first sendintro, send the intro again. After
* that take it easy.
*/
if (EXPIRED(1) || (count == 1)) {
Syslog('s', "sendintro after eol char");
SM_PROCEED(sendintro);
} else {
Syslog('s', "waitchar after eol char");
SM_PROCEED(waitchar);
}
}
break;
default: standby = 0;
@ -532,6 +558,7 @@ SM_STATE(checkemsi)
Syslog('i', "check \"%s\" for being EMSI inquery or data",ebuf);
if (localoptions & NOEMSI) {
Syslog('s', "Force sendintro");
SM_PROCEED(sendintro);
}
@ -543,11 +570,11 @@ SM_STATE(checkemsi)
standby = 0;
ep = ebuf;
ebuf[0] = '\0';
SM_PROCEED(waitchar);
SM_PROCEED(settimer);
} else if (strncasecmp(ebuf, "EMSI_DAT", 8) == 0) {
SM_PROCEED(getdat);
} else {
SM_PROCEED(sendintro);
SM_PROCEED(settimer);
}
SM_STATE(getdat)
@ -569,6 +596,7 @@ SM_STATE(getdat)
*p= '\0';
}
if (c == TIMEOUT) {
Syslog('s', "c = TIMEOUT -> sendintro");
SM_PROCEED(sendintro);
} else if (c < 0) {
Syslog('+', "Error while reading EMSI_DAT from the caller");