mISDNcapid: ignore incoming B3 data packets until PTY slave sent data

In hijacking mode (CAPIFLAG_HIGHJACKING), a PTY master/slave pair is created to
pass data back and forth between the application and mISDNcapid. However, there
is a small time window between creating the PTY slave and the application
opening the PTY slave. If a B3 data connection is established before the
application has opened the PTY slave, and B3 data is received and written to the
PTY master end, it is immediately read back by the B3 data receiver thread
(BCthread), which then sends the data back to the original sender, causing a
loopback. This e.g. happens when the application is the PPP daemon pppd which
has been configured to not send any data until it receives a valid LCP packet
("silent" option).

In order to fix this, an additional flag called tty_received remembers whether
the B3 data receiver thread has already read data from the PTY at least once.
Only if this is the case B3 data is written to the PTY master end, otherwise it
is discarded as there is no potential receiver at the PTY slave end yet. This
effectively avoids any loopback situations due to an unconnected PTY slave end.

Signed-off-by: Christoph Schulz <develop@kristov.de>
This commit is contained in:
Christoph Schulz 2017-02-08 23:31:39 +01:00
parent 1acabc5db3
commit cf98743fb3
3 changed files with 10 additions and 0 deletions

View File

@ -881,6 +881,8 @@ static int Create_tty(struct BInstance *bi)
dprint(MIDEBUG_CONTROLLER, "close bi[%d]->tty %d\n", bi->nr, bi->tty);
close(bi->tty);
bi->tty = -1;
} else {
bi->tty_received = 0;
}
}
@ -918,6 +920,7 @@ static int recv_tty(struct BInstance *bi)
ret = -EMSGSIZE;
}
if (ret > 0) {
bi->tty_received = 1;
mc->len = ret;
/* Fake length of DATA_B3 REQ to pass offset check */
capimsg_setu16(mc->rb, 0, 22);

View File

@ -176,6 +176,7 @@ struct BInstance {
int proto;
int fd;
int tty;
int tty_received;
int rx_min;
int rx_max;
int org_rx_min;

View File

@ -1073,6 +1073,12 @@ static int ncciDataInd(struct mNCCI *ncci, int pr, struct mc_buf *mc)
pthread_mutex_unlock(&ncci->lock);
hh++;
mc->rp = (unsigned char *)hh;
if (!ncci->BIlink->tty_received) {
wprint("%s: frame with %d bytes discarded to avoid loopback\n",
CAPIobjIDstr(&ncci->cobj), dlen);
dhexprint(MIDEBUG_NCCI_DATA, "Data: ", mc->rp, dlen);
return -EBUSY;
}
ret = write(ncci->BIlink->tty, mc->rp, dlen);
if (ret != dlen)
wprint("%s: frame with %d bytes only %d bytes were written to tty - %s\n",