[PATCH] mISDNcapid: ignore incoming B3 data packets until PTY slave sent data

Christoph Schulz <[email protected]> Sat, 11 Feb 2017 12:57:12 +0100
Newsgroups gmane.linux.isdn.i4l.user
Message-ID <[email protected]>
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

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 <[email protected]>
- ---
 capi20/daemon.c | 3 +++
 capi20/m_capi.h | 1 +
 capi20/ncci.c   | 6 ++++++
 3 files changed, 10 insertions(+)

diff --git a/capi20/daemon.c b/capi20/daemon.c
index b2ca095..bf25afc 100644
- --- a/capi20/daemon.c
+++ b/capi20/daemon.c
@@ -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);
diff --git a/capi20/m_capi.h b/capi20/m_capi.h
index f0eb106..9558abb 100644
- --- a/capi20/m_capi.h
+++ b/capi20/m_capi.h
@@ -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;
diff --git a/capi20/ncci.c b/capi20/ncci.c
index 1307d20..e23fe01 100644
- --- a/capi20/ncci.c
+++ b/capi20/ncci.c
@@ -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",
- -- 
2.10.2

-----BEGIN PGP SIGNATURE-----

iEYEARECAAYFAlie/BgACgkQL11jCnyQ5OzSvwCeMCPFFF/dDPqcVxB5ZGzXN4L8
9xEAninHv6XI8GUWMZngn7Ti+Lu2sSu9
=3KkM
-----END PGP SIGNATURE-----