? usr.sbin/tcpdump/ktrace.out Index: sys/net/bpf.c =================================================================== RCS file: /cvs/src/sys/net/bpf.c,v retrieving revision 1.170 diff -u -p -r1.170 bpf.c --- sys/net/bpf.c 13 Jul 2018 08:51:15 -0000 1.170 +++ sys/net/bpf.c 4 Mar 2019 10:10:14 -0000 @@ -926,9 +926,20 @@ bpfioctl(dev_t dev, u_long cmd, caddr_t *(u_int *)addr = d->bd_fildrop; break; - case BIOCSFILDROP: /* set "filter-drop" flag */ - d->bd_fildrop = *(u_int *)addr ? 1 : 0; + case BIOCSFILDROP: { /* set "filter-drop" flag */ + unsigned int fildrop = *(u_int *)addr; + switch (fildrop) { + case BPF_FILDROP_PASS: + case BPF_FILDROP_CAPTURE: + case BPF_FILDROP_DROP: + d->bd_fildrop = fildrop; + break; + default: + error = EINVAL; + break; + } break; + } case BIOCGDIRFILT: /* get direction filter */ *(u_int *)addr = d->bd_dirfilt; @@ -1261,23 +1272,26 @@ _bpf_mtap(caddr_t arg, const struct mbuf pktlen += m0->m_len; SRPL_FOREACH(d, &sr, &bp->bif_dlist, bd_next) { + struct srp_ref bsr; + struct bpf_program *bf; + struct bpf_insn *fcode = NULL; + atomic_inc_long(&d->bd_rcount); - if ((direction & d->bd_dirfilt) != 0) - slen = 0; - else { - struct srp_ref bsr; - struct bpf_program *bf; - struct bpf_insn *fcode = NULL; - - bf = srp_enter(&bsr, &d->bd_rfilter); - if (bf != NULL) - fcode = bf->bf_insns; - slen = bpf_mfilter(fcode, m, pktlen); - srp_leave(&bsr); - } + if (ISSET(d->bd_dirfilt, direction)) + continue; + + bf = srp_enter(&bsr, &d->bd_rfilter); + if (bf != NULL) + fcode = bf->bf_insns; + slen = bpf_mfilter(fcode, m, pktlen); + srp_leave(&bsr); - if (slen > 0) { + if (slen == 0) + continue; + if (d->bd_fildrop != BPF_FILDROP_PASS) + drop = 1; + if (d->bd_fildrop != BPF_FILDROP_DROP) { if (!gottime++) microtime(&tv); @@ -1285,9 +1299,6 @@ _bpf_mtap(caddr_t arg, const struct mbuf bpf_catchpacket(d, (u_char *)m, pktlen, slen, cpfn, &tv); mtx_leave(&d->bd_mtx); - - if (d->bd_fildrop) - drop = 1; } } SRPL_LEAVE(&sr); Index: sys/net/bpf.h =================================================================== RCS file: /cvs/src/sys/net/bpf.h,v retrieving revision 1.65 diff -u -p -r1.65 bpf.h --- sys/net/bpf.h 3 Feb 2018 13:37:37 -0000 1.65 +++ sys/net/bpf.h 4 Mar 2019 10:10:14 -0000 @@ -126,6 +126,13 @@ struct bpf_version { #define BPF_DIRECTION_IN 1 #define BPF_DIRECTION_OUT (1<<1) +/* + * Values for BIOCGFILDROP/BIOCSFILDROP + */ +#define BPF_FILDROP_PASS 0 /* capture, pass */ +#define BPF_FILDROP_CAPTURE 1 /* capture, drop */ +#define BPF_FILDROP_DROP 2 /* no capture, drop */ + struct bpf_timeval { u_int32_t tv_sec; u_int32_t tv_usec; Index: share/man/man4/bpf.4 =================================================================== RCS file: /cvs/src/share/man/man4/bpf.4,v retrieving revision 1.38 diff -u -p -r1.38 bpf.4 --- share/man/man4/bpf.4 28 Apr 2016 19:07:19 -0000 1.38 +++ share/man/man4/bpf.4 4 Mar 2019 10:10:14 -0000 @@ -391,11 +391,24 @@ This flag is initialized to zero by defa .Pp .It Dv BIOCSFILDROP Fa "u_int *" .It Dv BIOCGFILDROP Fa "u_int *" -Sets or gets the status of the +Sets or gets the .Dq filter drop -flag. -If non-zero, packets matching any filters will be reported to the -associated interface so that they can be dropped. +action. +The supported actions for packets matching the filter are: +.Pp +.Bl -tag -width "BPF_FILDROP_CAPTURE" -compact +.It Dv BPF_FILDROP_PASS +Accept and capture +.It Dv BPF_FILDROP_CAPTURE +Drop and capture +.It Dv BPF_FILDROP_DROP +Drop and do not capture +.El +.Pp +Packets matching any filter configured to drop packets will be +reported to the associated interface so that they can be dropped. +The default action is +.Dv BPF_FILDROP_PASS . .Pp .It Dv BIOCSDIRFILT Fa "u_int *" .It Dv BIOCGDIRFILT Fa "u_int *" Index: usr.sbin/tcpdump/privsep.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/privsep.c,v retrieving revision 1.52 diff -u -p -r1.52 privsep.c --- usr.sbin/tcpdump/privsep.c 17 Nov 2018 16:52:02 -0000 1.52 +++ usr.sbin/tcpdump/privsep.c 4 Mar 2019 10:10:14 -0000 @@ -224,7 +224,7 @@ priv_exec(int argc, char *argv[]) /* parse the arguments for required options */ opterr = 0; while ((i = getopt(argc, argv, - "ac:D:deE:fF:i:lLnNOopPqr:s:StT:vw:xXy:Y")) != -1) { + "aB:c:D:deE:fF:i:lLnNOopPqr:s:StT:vw:xXy:Y")) != -1) { switch (i) { case 'n': nflag++; @@ -366,7 +366,7 @@ static void impl_open_bpf(int fd, int *bpfd) { int snaplen, promisc, err; - u_int dlt, dirfilt; + u_int dlt, dirfilt, fildrop; char device[IFNAMSIZ]; size_t iflen; @@ -376,10 +376,11 @@ impl_open_bpf(int fd, int *bpfd) must_read(fd, &promisc, sizeof(int)); must_read(fd, &dlt, sizeof(u_int)); must_read(fd, &dirfilt, sizeof(u_int)); + must_read(fd, &fildrop, sizeof(fildrop)); 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, dlt, dirfilt, fildrop); 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.11 diff -u -p -r1.11 privsep.h --- usr.sbin/tcpdump/privsep.h 8 Nov 2018 14:06:09 -0000 1.11 +++ usr.sbin/tcpdump/privsep.h 4 Mar 2019 10:10:14 -0000 @@ -45,11 +45,11 @@ __dead void priv_exec(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, u_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, - u_int); + u_int, u_int); pcap_t *priv_pcap_offline(const char *, char *); size_t priv_gethostbyaddr(char *, size_t, int, char *, size_t); Index: usr.sbin/tcpdump/privsep_pcap.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/privsep_pcap.c,v retrieving revision 1.23 diff -u -p -r1.23 privsep_pcap.c --- usr.sbin/tcpdump/privsep_pcap.c 17 Nov 2018 16:52:02 -0000 1.23 +++ usr.sbin/tcpdump/privsep_pcap.c 4 Mar 2019 10:10:14 -0000 @@ -173,7 +173,7 @@ 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) + u_int dirfilt, u_int fildrop) { int fd; struct ifreq ifr; @@ -201,6 +201,9 @@ pcap_live(const char *device, int snaple if (ioctl(fd, BIOCSDIRFILT, &dirfilt) < 0) goto error; + if (ioctl(fd, BIOCSFILDROP, &fildrop) < 0) + goto error; + /* lock the descriptor */ if (ioctl(fd, BIOCLOCK, NULL) < 0) goto error; @@ -218,7 +221,7 @@ pcap_live(const char *device, int snaple */ pcap_t * priv_pcap_live(const char *dev, int slen, int prom, int to_ms, - char *ebuf, u_int dlt, u_int dirfilt) + char *ebuf, u_int dlt, u_int dirfilt, u_int fildrop) { int fd, err; struct bpf_version bv; @@ -247,6 +250,7 @@ priv_pcap_live(const char *dev, int slen must_write(priv_fd, &prom, sizeof(int)); must_write(priv_fd, &dlt, sizeof(u_int)); must_write(priv_fd, &dirfilt, sizeof(u_int)); + must_write(priv_fd, &fildrop, sizeof(fildrop)); write_string(priv_fd, dev); fd = receive_fd(priv_fd); Index: usr.sbin/tcpdump/tcpdump.8 =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/tcpdump.8,v retrieving revision 1.99 diff -u -p -r1.99 tcpdump.8 --- usr.sbin/tcpdump/tcpdump.8 6 Jul 2018 09:59:12 -0000 1.99 +++ usr.sbin/tcpdump/tcpdump.8 4 Mar 2019 10:10:14 -0000 @@ -29,6 +29,7 @@ .Nm tcpdump .Op Fl AadefILlNnOopqStvXx .Op Fl c Ar count +.Op Fl B Ar fildrop .Op Fl D Ar direction .Op Fl E Oo Ar espalg : Oc Ns Ar espkey .Op Fl F Ar file @@ -58,6 +59,23 @@ 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 Ar fildrop +Configure the drop action specified by +.A fildrop +to be used when the filter expression matches a packet. +The actions are: +.Pp +.Bl -tag -width "capture" -offset indent -compact +.It Cm pass +Matching packets are accepted and captured. +.It Cm capture +Matching packets are dropped and captured. +.It Cm drop +Matching packets are dropped and not captured. +.El +.Pp +The default action is +.Cm pass . .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.88 diff -u -p -r1.88 tcpdump.c --- usr.sbin/tcpdump/tcpdump.c 8 Nov 2018 14:06:09 -0000 1.88 +++ usr.sbin/tcpdump/tcpdump.c 4 Mar 2019 10:10:14 -0000 @@ -61,6 +61,7 @@ int Aflag; /* dump ascii */ int aflag; /* translate network and broadcast addresses */ +int Bflag; /* BPF fildrop setting */ int dflag; /* print filter code */ int eflag; /* print ethernet header */ int fflag; /* don't translate "foreign" IP address */ @@ -231,7 +232,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) + "AaB:c:D:deE:fF:i:IlLnNOopqr:s:StT:vw:xXy:Y")) != -1) switch (op) { case 'A': @@ -243,6 +244,19 @@ main(int argc, char **argv) aflag = 1; break; + case 'B': + if (strcasecmp(optarg, "pass") == 0) + Bflag = BPF_FILDROP_PASS; + else if (strcasecmp(optarg, "capture") == 0) + Bflag = BPF_FILDROP_CAPTURE; + else if (strcasecmp(optarg, "drop") == 0) + Bflag = BPF_FILDROP_DROP; + else { + error("invalid BPF fildrop option: %s", + optarg); + } + break; + case 'c': cnt = strtonum(optarg, 1, INT_MAX, &errstr); if (errstr) @@ -440,7 +454,7 @@ main(int argc, char **argv) error("%s", ebuf); } pd = priv_pcap_live(device, snaplen, !pflag, 1000, ebuf, - dlt, dirfilt); + dlt, dirfilt, Bflag); if (pd == NULL) error("%s", ebuf);