summaryrefslogtreecommitdiffstats
path: root/sys/kern/tty_snoop.c
diff options
context:
space:
mode:
authorugen <ugen@FreeBSD.org>1995-02-15 16:35:38 +0000
committerugen <ugen@FreeBSD.org>1995-02-15 16:35:38 +0000
commit7d723cb44557edbb4fe6f63c52f51b701f50a053 (patch)
tree74a37d66e149ed9a707fe7ba96a2e68b9a8f9fcb /sys/kern/tty_snoop.c
parent02173ec0ede9651e2d7ca9e70656d38f8465259b (diff)
downloadFreeBSD-src-7d723cb44557edbb4fe6f63c52f51b701f50a053.zip
FreeBSD-src-7d723cb44557edbb4fe6f63c52f51b701f50a053.tar.gz
Fix couple of nasty bugs..
- Overflow now calculated right - Close works ok,does not looses tty - Better overflow handling now the snooping stops on overflow,but programm notified and can reconnect if it want to..Default maximal buffer set to 664 K and this is probably too much..:))) Utility still to come
Diffstat (limited to 'sys/kern/tty_snoop.c')
-rw-r--r--sys/kern/tty_snoop.c440
1 files changed, 224 insertions, 216 deletions
diff --git a/sys/kern/tty_snoop.c b/sys/kern/tty_snoop.c
index 35ee6ea..f852a81 100644
--- a/sys/kern/tty_snoop.c
+++ b/sys/kern/tty_snoop.c
@@ -15,12 +15,12 @@
#include "snp.h"
-#if (defined NSNP) && (NSNP > 0)
+#if NSNP > 0
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/ioctl.h>
-#include <sys/ioctl_compat.h> /* Oooh..We need O/NTTYDISC */
+#include <sys/ioctl_compat.h> /* Oooh..We need O/NTTYDISC */
#include <sys/proc.h>
#define TTYDEFCHARS
#include <sys/tty.h>
@@ -46,8 +46,8 @@
#define NPTY 32
#endif
-extern struct tty pt_tty[];
-#endif /* ST_PTY */
+extern struct tty pt_tty[];
+#endif /* ST_PTY */
#ifdef ST_SIO
@@ -56,48 +56,47 @@ extern struct tty pt_tty[];
*/
#include "sio.h"
-extern struct tty sio_tty[];
-#endif /* ST_SIO */
+extern struct tty sio_tty[];
+#endif /* ST_SIO */
#ifdef ST_VTY
/*
* This should match "i386/isa/sc.c"
*/
-
-#if !defined(MAXCONS)
-#define MAXCONS 16
+
+#if !defined(MAXCONS)
+#define MAXCONS 16
#endif
-extern struct tty sccons[];
-#endif /* ST_VTY */
+extern struct tty sccons[];
+#endif /* ST_VTY */
/*
- * This is local structure to hold
- * data for all tty arrays we serve.
+ * This is local structure to hold data for all tty arrays we serve.
*/
-typedef struct tty tty_arr[];
+typedef struct tty tty_arr[];
struct tty_tab {
- int lt_max;
- tty_arr *lt_tab;
+ int lt_max;
+ tty_arr *lt_tab;
};
-static struct tty_tab tty_tabs[]={
+static struct tty_tab tty_tabs[] = {
#ifdef ST_PTY
- { NPTY , &pt_tty },
+ {NPTY, &pt_tty},
#else
- { -1 , NULL },
+ {-1, NULL},
#endif
#ifdef ST_VTY
- { MAXCONS, &sccons },
+ {MAXCONS, &sccons},
#else
- { -1 , NULL },
+ {-1, NULL},
#endif
#ifdef ST_SIO
- { NSIO , &sio_tty }
+ {NSIO, &sio_tty}
#else
- { -1 , NULL }
+ {-1, NULL}
#endif
};
@@ -111,61 +110,61 @@ static struct snoop snoopsw[NSNP];
int
snpread(dev, uio, flag)
- dev_t dev;
- struct uio *uio;
- int flag;
+ dev_t dev;
+ struct uio *uio;
+ int flag;
{
- int unit = minor(dev),s;
- struct snoop *snp = &snoopsw[unit];
- int len,n,nblen,error = 0;
- caddr_t from;
- char *nbuf;
-
+ int unit = minor(dev), s;
+ struct snoop *snp = &snoopsw[unit];
+ int len, n, nblen, error = 0;
+ caddr_t from;
+ char *nbuf;
+
#ifdef DIAGNOSTIC
- if ((snp->snp_len+snp->snp_base)>snp->snp_blen)
+ if ((snp->snp_len + snp->snp_base) > snp->snp_blen)
panic("snoop buffer error");
#endif
- if (snp->snp_unit==-1)
+ if (snp->snp_unit == -1)
return (EIO);
- snp->snp_flags &= ~SNOOP_RWAIT;
+ snp->snp_flags &= ~SNOOP_RWAIT;
do {
- if (snp->snp_len == 0) {
+ if (snp->snp_len == 0) {
if (snp->snp_flags & SNOOP_NBIO) {
return EWOULDBLOCK;
}
- snp->snp_flags|=SNOOP_RWAIT;
- tsleep((caddr_t)snp,(PZERO+1)|PCATCH,"snoopread",0);
+ snp->snp_flags |= SNOOP_RWAIT;
+ tsleep((caddr_t) snp, (PZERO + 1) | PCATCH, "snoopread", 0);
}
} while (snp->snp_len == 0);
- n = uio->uio_resid;
+ n = snp->snp_len;
- while (snp->snp_len > 0 && uio->uio_resid > 0 && error == 0) {
- len = MIN(uio->uio_resid,snp->snp_len);
- from = (caddr_t)(snp->snp_buf+snp->snp_base);
+ while (snp->snp_len > 0 && uio->uio_resid > 0 && error == 0) {
+ len = MIN(uio->uio_resid, snp->snp_len);
+ from = (caddr_t) (snp->snp_buf + snp->snp_base);
if (len == 0)
break;
- error = uiomove(from,len,uio);
- snp->snp_base+=len;
- snp->snp_len-=len;
+ error = uiomove(from, len, uio);
+ snp->snp_base += len;
+ snp->snp_len -= len;
}
- if (n)
+ if ((snp->snp_flags & SNOOP_OFLOW) && (n < snp->snp_len)) {
snp->snp_flags &= ~SNOOP_OFLOW;
-
- s=spltty();
- nblen=snp->snp_blen;
- if (((nblen/2)>=SNOOP_MINLEN) && (nblen/2)>=snp->snp_len) {
- while (((nblen/2)>=snp->snp_len) && ((nblen/2)>=SNOOP_MINLEN))
- nblen=nblen/2;
- if (nbuf=malloc(nblen,M_TTYS,M_NOWAIT)) {
- bcopy(snp->snp_buf+snp->snp_base,nbuf,snp->snp_len);
- free(snp->snp_buf,M_TTYS);
- snp->snp_buf=nbuf;
- snp->snp_blen=nblen;
- snp->snp_base=0;
+ }
+ s = spltty();
+ nblen = snp->snp_blen;
+ if (((nblen / 2) >= SNOOP_MINLEN) && (nblen / 2) >= snp->snp_len) {
+ while (((nblen / 2) >= snp->snp_len) && ((nblen / 2) >= SNOOP_MINLEN))
+ nblen = nblen / 2;
+ if (nbuf = malloc(nblen, M_TTYS, M_NOWAIT)) {
+ bcopy(snp->snp_buf + snp->snp_base, nbuf, snp->snp_len);
+ free(snp->snp_buf, M_TTYS);
+ snp->snp_buf = nbuf;
+ snp->snp_blen = nblen;
+ snp->snp_base = 0;
}
}
splx(s);
@@ -175,126 +174,109 @@ snpread(dev, uio, flag)
int
-snpin(snp,buf,n)
-struct snoop *snp;
-char *buf;
-int n;
+snpin(snp, buf, n)
+ struct snoop *snp;
+ char *buf;
+ int n;
{
- int s_free,s_tail;
- int s,len,nblen;
- caddr_t from,to;
- char *nbuf;
- struct tty_tab *l_tty;
- struct tty *tp;
+ int s_free, s_tail;
+ int s, len, nblen;
+ caddr_t from, to;
+ char *nbuf;
+ struct tty_tab *l_tty;
+ struct tty *tp;
- if (n == 0)
+ if (n == 0)
return 0;
#ifdef DIAGNOSTIC
if (n < 0)
panic("bad snoop char count");
-#endif
- if (snp->snp_flags&SNOOP_OFLOW) {
- printf("Snoop: buffer overflow \n");
- /*
- * On overflow we just repeat the standart
- * close procedure...yes , this is waste of space but..
- * Then next read from device will fail if one would
- * recall he is snooping and retry...
- */
- snp->snp_flags &= ~SNOOP_OPEN;
- snp->snp_base = 0;
- snp->snp_len = 0;
- snp->snp_blen=0;
- free(snp->snp_buf,M_TTYS);
-
- /*
- * If line disc. changed we do not touch
- * this pointer,SLIP/PPP will change it anyway.
- */
-
- if (snp->snp_unit==-1)
- goto oflow_notty;
-
- l_tty=&(tty_tabs[snp->snp_type]);
- tp=&((*l_tty->lt_tab)[snp->snp_unit]);
-
- if (tp->t_sc == snp && (tp->t_state&TS_SNOOP) &&
- (tp->t_line == OTTYDISC || tp->t_line == NTTYDISC)) {
- tp->t_sc = NULL;
- tp->t_state &=~TS_SNOOP;
- };
- snp->snp_unit=-1;
-
-oflow_notty:
- selwakeup(&snp->snp_sel);
- snp->snp_sel.si_pid = 0;
- return (0);
-}
+ if (!(snp->snp_flags & SNOOP_OPEN)) {
+ printf("Snoop: data coming to closed device.\n");
+ return 0;
+ }
+#endif
+ if (snp->snp_flags & SNOOP_DOWN) {
+ printf("Snoop: more data to down interface.\n");
+ return 0;
+ }
+ if (snp->snp_flags & SNOOP_OFLOW) {
+ printf("Snoop: buffer overflow.\n");
+ /*
+ * On overflow we just repeat the standart close
+ * procedure...yes , this is waste of space but.. Then next
+ * read from device will fail if one would recall he is
+ * snooping and retry...
+ */
+
+ snp->snp_blen = SNOOP_MINLEN;
+ free(snp->snp_buf, M_TTYS);
+ snp->snp_buf = malloc(SNOOP_MINLEN, M_TTYS, M_WAITOK);
+ snp->snp_flags |= SNOOP_DOWN;
+ snp->snp_flags &= ~SNOOP_OFLOW;
- s_free = snp->snp_blen - ( snp->snp_len + snp->snp_base );
- s_tail = snp->snp_blen - snp->snp_len;
+ return (snp_detach(snp));
+ }
+ s_tail = snp->snp_blen - (snp->snp_len + snp->snp_base);
+ s_free = snp->snp_blen - snp->snp_len;
if (n > s_free) {
- s=spltty();
- nblen=snp->snp_blen;
- while ((n > s_free) && ((nblen*2)<=SNOOP_MAXLEN)) {
- nblen=snp->snp_blen*2;
- s_free = nblen - ( snp->snp_len + snp->snp_base );
+ s = spltty();
+ nblen = snp->snp_blen;
+ while ((n > s_free) && ((nblen * 2) <= SNOOP_MAXLEN)) {
+ nblen = snp->snp_blen * 2;
+ s_free = nblen - (snp->snp_len + snp->snp_base);
}
- if ((n<=s_free) && (nbuf=malloc(nblen,M_TTYS,M_NOWAIT))) {
- bcopy(snp->snp_buf+snp->snp_base,nbuf,snp->snp_len);
- free(snp->snp_buf,M_TTYS);
- snp->snp_buf=nbuf;
- snp->snp_blen=nblen;
- snp->snp_base=0;
+ if ((n <= s_free) && (nbuf = malloc(nblen, M_TTYS, M_NOWAIT))) {
+ bcopy(snp->snp_buf + snp->snp_base, nbuf, snp->snp_len);
+ free(snp->snp_buf, M_TTYS);
+ snp->snp_buf = nbuf;
+ snp->snp_blen = nblen;
+ snp->snp_base = 0;
} else {
- snp->snp_flags|=SNOOP_OFLOW;
+ snp->snp_flags |= SNOOP_OFLOW;
if (snp->snp_flags & SNOOP_RWAIT) {
- snp->snp_flags &= ~SNOOP_RWAIT;
- wakeup((caddr_t)snp);
- }
+ snp->snp_flags &= ~SNOOP_RWAIT;
+ wakeup((caddr_t) snp);
+ }
splx(s);
return 0;
}
splx(s);
}
-
if (n > s_tail) {
- from=(caddr_t)(snp->snp_buf+snp->snp_base);
- to=(caddr_t)(snp->snp_buf);
- len=snp->snp_len;
- bcopy(from,to,len);
- snp->snp_base=0;
+ from = (caddr_t) (snp->snp_buf + snp->snp_base);
+ to = (caddr_t) (snp->snp_buf);
+ len = snp->snp_len;
+ bcopy(from, to, len);
+ snp->snp_base = 0;
}
-
-
- to=(caddr_t)(snp->snp_buf+snp->snp_base+snp->snp_len);
- bcopy(buf,to,n);
- snp->snp_len+=n;
+ to = (caddr_t) (snp->snp_buf + snp->snp_base + snp->snp_len);
+ bcopy(buf, to, n);
+ snp->snp_len += n;
if (snp->snp_flags & SNOOP_RWAIT) {
- snp->snp_flags &= ~SNOOP_RWAIT;
- wakeup((caddr_t)snp);
- }
-
+ snp->snp_flags &= ~SNOOP_RWAIT;
+ wakeup((caddr_t) snp);
+ }
selwakeup(&snp->snp_sel);
- snp->snp_sel.si_pid = 0;
+ snp->snp_sel.si_pid = 0;
return n;
}
int
snpopen(dev, flag, mode, p)
- dev_t dev;
- int flag, mode;
- struct proc *p;
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
{
- struct snoop *snp;
- register int unit, error;
+ struct snoop *snp;
+ register int unit, error;
if (error = suser(p->p_ucred, &p->p_acflag))
return (error);
@@ -304,83 +286,100 @@ snpopen(dev, flag, mode, p)
snp = &snoopsw[unit];
if (snp->snp_flags & SNOOP_OPEN)
return (ENXIO);
- snp->snp_flags |= SNOOP_OPEN;
+ /*
+ * We intentionally do not OR flags with SNOOP_OPEN,but set them so
+ * all previous settings (especially SNOOP_OFLOW) will be cleared.
+ */
+ snp->snp_flags = SNOOP_OPEN;
- snp->snp_buf=malloc(SNOOP_MINLEN,M_TTYS,M_WAITOK);
- snp->snp_blen=SNOOP_MINLEN;
- snp->snp_base=0;
- snp->snp_len=0;
+ snp->snp_buf = malloc(SNOOP_MINLEN, M_TTYS, M_WAITOK);
+ snp->snp_blen = SNOOP_MINLEN;
+ snp->snp_base = 0;
+ snp->snp_len = 0;
/*
- * unit == -1 is for inactive snoop
- * devices.
+ * unit == -1 is for inactive snoop devices.
*/
- snp->snp_unit=-1;
+ snp->snp_unit = -1;
return (0);
}
+
int
-snpclose(dev, flag)
- dev_t dev;
- int flag;
+snp_detach(snp)
+ struct snoop *snp;
{
- register int unit = minor(dev);
- struct snoop *snp = &snoopsw[unit];
- struct tty *tp;
- struct tty_tab *l_tty;
+ struct tty *tp;
+ struct tty_tab *l_tty;
+
- snp->snp_flags &= ~SNOOP_OPEN;
snp->snp_base = 0;
snp->snp_len = 0;
- snp->snp_blen=0;
- free(snp->snp_buf,M_TTYS);
/*
- * If line disc. changed we do not touch
- * this pointer,SLIP/PPP will change it anyway.
+ * If line disc. changed we do not touch this pointer,SLIP/PPP will
+ * change it anyway.
*/
- if (snp->snp_unit==-1)
- goto close_notty;
+ if (snp->snp_unit == -1)
+ goto destroy_notty;
+
- l_tty=&tty_tabs[snp->snp_type];
- tp=&((*l_tty->lt_tab)[snp->snp_unit]);
+ l_tty = &tty_tabs[snp->snp_type];
+ tp = &((*l_tty->lt_tab)[snp->snp_unit]);
- if (tp->t_sc == snp && (tp->t_state&TS_SNOOP) &&
- (tp->t_line == OTTYDISC || tp->t_line == NTTYDISC)) {
+ if ((tp->t_sc == snp) && (tp->t_state & TS_SNOOP) &&
+ (tp->t_line == OTTYDISC || tp->t_line == NTTYDISC)) {
tp->t_sc = NULL;
- tp->t_state &=~TS_SNOOP;
- };
- snp->snp_unit=-1;
+ tp->t_state &= ~TS_SNOOP;
+ } else
+ printf("Snoop: bad attached tty data.\n");
-close_notty:
+ snp->snp_unit = -1;
+
+destroy_notty:
selwakeup(&snp->snp_sel);
- snp->snp_sel.si_pid = 0;
+ snp->snp_sel.si_pid = 0;
return (0);
}
+int
+snpclose(dev, flag)
+ dev_t dev;
+ int flag;
+{
+ register int unit = minor(dev);
+ struct snoop *snp = &snoopsw[unit];
+
+ snp->snp_blen = 0;
+ free(snp->snp_buf, M_TTYS);
+ snp->snp_flags &= ~SNOOP_OPEN;
+
+ return (snp_detach(snp));
+}
+
int
snpioctl(dev, cmd, data, flag)
- dev_t dev;
- int cmd;
- caddr_t data;
- int flag;
+ dev_t dev;
+ int cmd;
+ caddr_t data;
+ int flag;
{
- int unit = minor(dev),s;
- int tunit,ttype;
- struct snoop *snp = &snoopsw[unit];
- struct tty *tp,*tpo;
- struct tty_tab *l_tty,*l_otty;
+ int unit = minor(dev), s;
+ int tunit, ttype;
+ struct snoop *snp = &snoopsw[unit];
+ struct tty *tp, *tpo;
+ struct tty_tab *l_tty, *l_otty;
switch (cmd) {
case SNPSTTY:
- tunit=((struct snptty *)data)->st_unit;
- ttype=((struct snptty *)data)->st_type;
+ tunit = ((struct snptty *) data)->st_unit;
+ ttype = ((struct snptty *) data)->st_type;
if (ttype < 0 || ttype > ST_MAXTYPE)
return (EINVAL);
@@ -392,50 +391,53 @@ snpioctl(dev, cmd, data, flag)
if (tunit < 0 || tunit >= l_tty->lt_max)
return (EINVAL);
- tp=&((*l_tty->lt_tab)[tunit]);
+ tp = &((*l_tty->lt_tab)[tunit]);
- if (tp->t_sc!=(caddr_t)snp && (tp->t_state&TS_SNOOP))
+ if (tp->t_sc != (caddr_t) snp && (tp->t_state & TS_SNOOP))
return (EBUSY);
- if (tp->t_line!=OTTYDISC && tp->t_line!=NTTYDISC)
+ if (tp->t_line != OTTYDISC && tp->t_line != NTTYDISC)
return (EBUSY);
- s=spltty();
+ s = spltty();
if (snp->snp_unit != -1) {
- l_otty=&tty_tabs[snp->snp_type];
- tpo=&((*l_otty->lt_tab)[snp->snp_unit]);
- tpo->t_state &=~TS_SNOOP;
+ l_otty = &tty_tabs[snp->snp_type];
+ tpo = &((*l_otty->lt_tab)[snp->snp_unit]);
+ tpo->t_state &= ~TS_SNOOP;
}
-
- tp->t_sc=(caddr_t)snp;
+ tp->t_sc = (caddr_t) snp;
tp->t_state |= TS_SNOOP;
snp->snp_unit = tunit;
+ snp->snp_type = ttype;
+ snp->snp_flags &= ~SNOOP_DOWN;
splx(s);
break;
case SNPGTTY:
- ((struct snptty *)data)->st_unit = snp->snp_unit;
- ((struct snptty *)data)->st_type = snp->snp_type;
+ ((struct snptty *) data)->st_unit = snp->snp_unit;
+ ((struct snptty *) data)->st_type = snp->snp_type;
break;
-
+
case FIONBIO:
- if (*(int *)data)
+ if (*(int *) data)
snp->snp_flags |= SNOOP_NBIO;
else
snp->snp_flags &= ~SNOOP_NBIO;
break;
case FIOASYNC:
- if (*(int *)data)
+ if (*(int *) data)
snp->snp_flags |= SNOOP_ASYNC;
else
snp->snp_flags &= ~SNOOP_ASYNC;
break;
case FIONREAD:
s = spltty();
- if (snp->snp_unit!=-1)
- *(int *)data = snp->snp_len;
- else
- *(int *)data = 0;
+ if (snp->snp_unit != -1)
+ *(int *) data = snp->snp_len;
+ else if (snp->snp_flags & SNOOP_DOWN)
+ *(int *) data = -1;
+ else
+ *(int *) data = 0;
splx(s);
break;
default:
@@ -447,21 +449,27 @@ snpioctl(dev, cmd, data, flag)
int
snpselect(dev, rw, p)
- dev_t dev;
- int rw;
- struct proc *p;
+ dev_t dev;
+ int rw;
+ struct proc *p;
{
- int unit = minor(dev), s;
- struct snoop *snp = &snoopsw[unit];
+ int unit = minor(dev), s;
+ struct snoop *snp = &snoopsw[unit];
- if (rw != FREAD) {
- return 0;
+ if (rw != FREAD) {
+ return 0;
}
-
if (snp->snp_len > 0) {
- return 1;
- }
-
+ return 1;
+ }
+ /*
+ * If snoop is down,we don't want to select() forever so we return 1.
+ * Caller should see if we down via FIONREAD ioctl().The last should
+ * return -1 to indicate down state.
+ */
+ if (snp->snp_flags & SNOOP_DOWN) {
+ return 1;
+ }
selrecord(p, &snp->snp_sel);
return 0;
}
OpenPOWER on IntegriCloud