I restored the functionality according to the manpage.
That means that read() on bpf is blocking again. If a
timeout is set read() will block until the timeout is
over.
Maybe asynchronous is also broken, i will look into that later.
Index: sys/net/bpf.c
===================================================================
RCS file: /cvs/src/sys/net/bpf.c,v
retrieving revision 1.103
diff -u -p -r1.103 bpf.c
--- sys/net/bpf.c 12 Jul 2014 18:44:22 -0000 1.103
+++ sys/net/bpf.c 4 Jan 2015 14:22:48 -0000
@@ -433,12 +433,17 @@ bpfread(dev_t dev, struct uio *uio, int
if (d->bd_rtout == -1) {
/* User requested non-blocking I/O */
error = EWOULDBLOCK;
+ } else if (d->bd_rtout == 0) {
+ /* No timeout? let's wait half a second for an
+ * interrupt */
+ error = tsleep((caddr_t)d, PRINET|PCATCH, "bpf",
+ hz / 2);
+ if (error == EWOULDBLOCK)
+ error = 0;
} else {
- if ((d->bd_rdStart + d->bd_rtout) < ticks) {
- error = tsleep((caddr_t)d, PRINET|PCATCH, "bpf",
+ /* User requested timeout */
+ error = tsleep((caddr_t)d, PRINET|PCATCH, "bpf",
d->bd_rtout);
- } else
- error = EWOULDBLOCK;
}
if (error == EINTR || error == ERESTART) {
D_PUT(d);
To test my patch i wrote a small tool. This tool filters 'finger'
packages.
/* BEGINNING */
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <err.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/bpf.h>
#include <net/ethertypes.h>
#include <netinet/in.h>
#include <net/if.h>
void usage();
void handler(int);
u_int BUFFFER_SIZE = 32786;
struct bpf_program bpf_machine = {
13,
(struct bpf_insn []){
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_IP, 0, 10),
BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 23),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_TCP, 0, 8),
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 20),
BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x1fff, 6, 0),
BPF_STMT(BPF_LDX+BPF_B+BPF_MSH, 14),
BPF_STMT(BPF_LD+BPF_H+BPF_IND, 14),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 79, 2, 0),
BPF_STMT(BPF_LD+BPF_H+BPF_IND, 16),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 79, 0, 1),
BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
BPF_STMT(BPF_RET+BPF_K, 0),
},
};
struct timeval timeout = {
(time_t)0,
(suseconds_t)0,
};
struct ifreq interface;
struct sigaction sigact;
int fd, out, pid;
const char *error;
int ch, nflag, tflag, bflag, iflag, dflag, qflag, pflag, aflag;
/* nflag = interface name */
/* tflag = timeout in seconds */
/* blfag = non-blocking */
/* iflag = immediate mode */
/* dflag = bpf devic, absolut path */
/* qflag = buffersize */
/* pflag = promiscius mode */
/* aflag = async mode */
int
main(int argc, char **argv)
{
while ((ch = getopt(argc, argv, "n:t:bid:q:pa")) != -1) {
switch (ch) {
case 'n':
nflag = 1;
strlcpy(interface.ifr_name, optarg,
sizeof(interface.ifr_name));
break;
case 't':
tflag = 1;
timeout.tv_sec = strtonum(optarg, 1, 600, &error);
if (error)
errx(1, "max timeout %s: %s", error, optarg);
break;
case 'b':
bflag = 1;
break;
case 'i':
iflag = 1;
break;
case 'd':
dflag = 1;
if ((fd = open(optarg, O_RDONLY)) < 0)
errx(1, "open: %s", strerror(errno));
break;
case 'q':
qflag = 1;
if (((BUFFFER_SIZE = strtonum(optarg, 1024, 4194304,
&error)) % 1024) != 0)
errx(1, "buffer has to be '% 1024 == 0'");
break;
case 'p':
pflag = 1;
break;
case 'a':
aflag = 1;
sigact.sa_handler = handler;
pid = getpid();
if (sigaction(SIGIO, &sigact, NULL) < 0)
errx(1, "sigaction: %s", strerror(errno));
break;
default:
usage();
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;
u_char buffer[BUFFFER_SIZE];
if (dflag != 1)
errx(1, "no bpfdevice");
if (ioctl(fd, BIOCSBLEN, &BUFFFER_SIZE) < 0)
errx(1, "BIOCSBLEN: %s", strerror(errno));
if (nflag != 1)
errx(1, "no ifname");
if(ioctl(fd, BIOCSETIF, &interface) < 0)
errx(1, "BIOCSETIF: %s", strerror(errno));
printf("Interface: %s\n", interface.ifr_name);
if (pflag == 1)
if (ioctl(fd, BIOCPROMISC) < 0)
errx(1, "BIOCPROMISC: %s", strerror(errno));
if (ioctl(fd, FIONBIO, &bflag) < 0)
errx(1, "FIONBIO: %s", strerror(errno));
if (ioctl(fd, BIOCIMMEDIATE, &iflag) < 0)
errx(1, "BIOCIMMEDIATE: %s", strerror(errno));
if (aflag == 1) {
if (ioctl(fd, FIOSETOWN, &pid) < 0)
errx(1, "FIOSETOWN: %s", strerror(errno));
if (ioctl(fd, FIOASYNC, &aflag) < 0)
errx(1, "FIOASYNC: %s", strerror(errno));
}
if (tflag == 1) {
if (ioctl(fd, BIOCSRTIMEOUT, &timeout) < 0)
errx(1, "BIOCSRTIMEOUT: %s", strerror(errno));
printf("Timeout: %lli\n", timeout.tv_sec);
}
if (ioctl(fd, BIOCSETF, &bpf_machine) < 0)
errx(1, "BIOCSETF: %s", strerror(errno));
out = read(fd, buffer, sizeof(buffer));
if (out < 0)
errx(1, "read: %s", strerror(errno));
printf("read?: %i\n", out);
return 0;
}
void
usage(void)
{
printf("usage: bpf_test [-bipa] [-t timeout] [-q buffersize] -n "
"ifname -d bpfdevice\n");
exit(0);
}
void
handler(int signal)
{
printf("Match!\n");
}
/* END */
BR
Simon