Hi,
tcpdump feels a bit laggy or slow some times when i use it for live debugging.
The following patch adds a new flag, '-b', to tcpdump. With this flag, tcpdump
sets BIOCIMMEDIATE for the current bpf(4) interface. With BIOCIMMEDIATE set,
the output is fluent.
Index: usr.sbin/tcpdump/privsep.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/privsep.c,v
retrieving revision 1.30
diff -u -p -r1.30 privsep.c
--- usr.sbin/tcpdump/privsep.c 22 Sep 2011 09:12:30 -0000 1.30
+++ usr.sbin/tcpdump/privsep.c 14 Dec 2014 22:40:14 -0000
@@ -318,7 +318,7 @@ priv_init(int argc, char **argv)
static void
impl_open_bpf(int fd, int *bpfd)
{
- int snaplen, promisc, err;
+ int snaplen, promisc, immediate, err;
u_int dlt, dirfilt;
char device[IFNAMSIZ];
size_t iflen;
@@ -327,12 +327,13 @@ impl_open_bpf(int fd, int *bpfd)
must_read(fd, &snaplen, sizeof(int));
must_read(fd, &promisc, sizeof(int));
+ must_read(fd, &immediate, sizeof(int));
must_read(fd, &dlt, sizeof(u_int));
must_read(fd, &dirfilt, sizeof(u_int));
iflen = read_string(fd, device, sizeof(device), __func__);
if (iflen == 0)
errx(1, "Invalid interface size specified");
- *bpfd = pcap_live(device, snaplen, promisc, dlt, dirfilt);
+ *bpfd = pcap_live(device, snaplen, promisc, immediate, dlt, dirfilt);
err = errno;
if (*bpfd < 0)
logmsg(LOG_DEBUG,
Index: usr.sbin/tcpdump/privsep.h
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/privsep.h,v
retrieving revision 1.7
diff -u -p -r1.7 privsep.h
--- usr.sbin/tcpdump/privsep.h 25 Aug 2009 06:59:17 -0000 1.7
+++ usr.sbin/tcpdump/privsep.h 14 Dec 2014 22:40:14 -0000
@@ -47,10 +47,10 @@ int priv_init(int, char **);
void priv_init_done(void);
int setfilter(int, int, char *);
-int pcap_live(const char *, int, int, u_int, u_int);
+int pcap_live(const char *, int, int, int, u_int, u_int);
struct bpf_program *priv_pcap_setfilter(pcap_t *, int, u_int32_t);
-pcap_t *priv_pcap_live(const char *, int, int, int, char *, u_int,
+pcap_t *priv_pcap_live(const char *, int, int, int, int, char *, u_int,
u_int);
pcap_t *priv_pcap_offline(const char *, char *);
Index: usr.sbin/tcpdump/privsep_pcap.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/privsep_pcap.c,v
retrieving revision 1.17
diff -u -p -r1.17 privsep_pcap.c
--- usr.sbin/tcpdump/privsep_pcap.c 14 Nov 2012 03:33:04 -0000 1.17
+++ usr.sbin/tcpdump/privsep_pcap.c 14 Dec 2014 22:40:14 -0000
@@ -172,8 +172,8 @@ priv_pcap_setfilter(pcap_t *hpcap, int o
/* privileged part of priv_pcap_live */
int
-pcap_live(const char *device, int snaplen, int promisc, u_int dlt,
- u_int dirfilt)
+pcap_live(const char *device, int snaplen, int promisc, int immediate,
+ u_int dlt, u_int dirfilt)
{
char bpf[sizeof "/dev/bpf0000000000"];
int fd, n = 0;
@@ -204,6 +204,10 @@ pcap_live(const char *device, int snaple
if (promisc)
/* this is allowed to fail */
ioctl(fd, BIOCPROMISC, NULL);
+
+ if (immediate && ioctl(fd, BIOCIMMEDIATE, &immediate) < 0)
+ goto error;
+
if (ioctl(fd, BIOCSDIRFILT, &dirfilt) < 0)
goto error;
@@ -223,7 +227,7 @@ pcap_live(const char *device, int snaple
* unprivileged part.
*/
pcap_t *
-priv_pcap_live(const char *dev, int slen, int prom, int to_ms,
+priv_pcap_live(const char *dev, int slen, int prom, int imme, int to_ms,
char *ebuf, u_int dlt, u_int dirfilt)
{
int fd, err;
@@ -251,6 +255,7 @@ priv_pcap_live(const char *dev, int slen
write_command(priv_fd, PRIV_OPEN_BPF);
must_write(priv_fd, &slen, sizeof(int));
must_write(priv_fd, &prom, sizeof(int));
+ must_write(priv_fd, &imme, sizeof(int));
must_write(priv_fd, &dlt, sizeof(u_int));
must_write(priv_fd, &dirfilt, sizeof(u_int));
write_string(priv_fd, dev);
Index: usr.sbin/tcpdump/tcpdump.8
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/tcpdump.8,v
retrieving revision 1.83
diff -u -p -r1.83 tcpdump.8
--- usr.sbin/tcpdump/tcpdump.8 3 Jun 2014 02:57:29 -0000 1.83
+++ usr.sbin/tcpdump/tcpdump.8 14 Dec 2014 22:40:15 -0000
@@ -28,7 +28,7 @@
.Sh SYNOPSIS
.Nm tcpdump
.Bk -words
-.Op Fl AadefILlNnOopqStvXx
+.Op Fl AabdefILlNnOopqStvXx
.Op Fl c Ar count
.Op Fl D Ar direction
.Oo Fl E Oo Ar espalg : Oc Ns
@@ -61,6 +61,9 @@ The smaller of the entire packet or
bytes will be printed.
.It Fl a
Attempt to convert network and broadcast addresses to names.
+.It Fl b
+Disables read blocking on the bpf(4) buffer. With this so called
+``immediate mode'' reads return immediately upon packet reception.
.It Fl c Ar count
Exit after receiving
.Ar count
Index: usr.sbin/tcpdump/tcpdump.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/tcpdump.c,v
retrieving revision 1.66
diff -u -p -r1.66 tcpdump.c
--- usr.sbin/tcpdump/tcpdump.c 30 Jun 2014 04:25:11 -0000 1.66
+++ usr.sbin/tcpdump/tcpdump.c 14 Dec 2014 22:40:15 -0000
@@ -60,6 +60,7 @@
int Aflag; /* dump ascii */
int aflag; /* translate network and broadcast addresses */
+int bflag; /* set read on livesession to non-blocking */
int dflag; /* print filter code */
int eflag; /* print ethernet header */
int fflag; /* don't translate "foreign" IP address */
@@ -226,7 +227,7 @@ main(int argc, char **argv)
opterr = 0;
while ((op = getopt(argc, argv,
- "Aac:D:deE:fF:i:IlLnNOopqr:s:StT:vw:xXy:Y")) != -1)
+ "Aabc:D:deE:fF:i:IlLnNOopqr:s:StT:vw:xXy:Y")) != -1)
switch (op) {
case 'A':
@@ -238,6 +239,10 @@ main(int argc, char **argv)
++aflag;
break;
+ case 'b':
+ ++bflag;
+ break;
+
case 'c':
cnt = atoi(optarg);
if (cnt <= 0)
@@ -429,8 +434,8 @@ main(int argc, char **argv)
if (device == NULL)
error("%s", ebuf);
}
- pd = priv_pcap_live(device, snaplen, !pflag, 1000, ebuf,
- dlt, dirfilt);
+ pd = priv_pcap_live(device, snaplen, !pflag, bflag, 1000,
+ ebuf, dlt, dirfilt);
if (pd == NULL)
error("%s", ebuf);