From 2cbcbbc3e54844ec15530ed001236629e4c2403f Mon Sep 17 00:00:00 2001 From: David Gwynne Date: Mon, 18 Mar 2019 00:09:23 +0000 Subject: support configuring BIOCSFILDROP with tcpdump. this allows tcpdump to be used a quick and dirty firewall. it also looks like an amazing foot-gun, so be careful. for example `tcpdump -B drop -i ix1 udp and port 7` lets you completely drop discard packets in the hardware interrupt handler. ok sthen@ mikeb@ claudio@ visa@ --- usr.sbin/tcpdump/privsep.c | 9 +++++---- usr.sbin/tcpdump/privsep.h | 4 ++-- usr.sbin/tcpdump/privsep_pcap.c | 10 +++++++--- usr.sbin/tcpdump/tcpdump.8 | 22 ++++++++++++++++++++-- usr.sbin/tcpdump/tcpdump.c | 22 ++++++++++++++++++---- 5 files changed, 52 insertions(+), 15 deletions(-) (limited to 'usr.sbin/tcpdump') diff --git a/usr.sbin/tcpdump/privsep.c b/usr.sbin/tcpdump/privsep.c index bb2279968df..6e708216e2a 100644 --- a/usr.sbin/tcpdump/privsep.c +++ b/usr.sbin/tcpdump/privsep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: privsep.c,v 1.52 2018/11/17 16:52:02 brynet Exp $ */ +/* $OpenBSD: privsep.c,v 1.53 2019/03/18 00:09:22 dlg Exp $ */ /* * Copyright (c) 2003 Can Erkin Acar @@ -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, diff --git a/usr.sbin/tcpdump/privsep.h b/usr.sbin/tcpdump/privsep.h index 017b100f9f8..e1b565e675e 100644 --- a/usr.sbin/tcpdump/privsep.h +++ b/usr.sbin/tcpdump/privsep.h @@ -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); diff --git a/usr.sbin/tcpdump/privsep_pcap.c b/usr.sbin/tcpdump/privsep_pcap.c index 7d9366c79e9..3d248ed1eb7 100644 --- a/usr.sbin/tcpdump/privsep_pcap.c +++ b/usr.sbin/tcpdump/privsep_pcap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: privsep_pcap.c,v 1.23 2018/11/17 16:52:02 brynet Exp $ */ +/* $OpenBSD: privsep_pcap.c,v 1.24 2019/03/18 00:09:22 dlg Exp $ */ /* * Copyright (c) 2004 Can Erkin Acar @@ -173,7 +173,7 @@ priv_pcap_setfilter(pcap_t *hpcap, int oflag, u_int32_t netmask) /* 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 snaplen, int promisc, u_int dlt, 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 snaplen, int promisc, u_int dlt, */ 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, int prom, int to_ms, 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); diff --git a/usr.sbin/tcpdump/tcpdump.8 b/usr.sbin/tcpdump/tcpdump.8 index 17aadb43116..4b0b2e809df 100644 --- a/usr.sbin/tcpdump/tcpdump.8 +++ b/usr.sbin/tcpdump/tcpdump.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tcpdump.8,v 1.99 2018/07/06 09:59:12 jmc Exp $ +.\" $OpenBSD: tcpdump.8,v 1.100 2019/03/18 00:09:22 dlg Exp $ .\" .\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996 .\" The Regents of the University of California. All rights reserved. @@ -19,7 +19,7 @@ .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" -.Dd $Mdocdate: July 6 2018 $ +.Dd $Mdocdate: March 18 2019 $ .Dt TCPDUMP 8 .Os .Sh NAME @@ -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 diff --git a/usr.sbin/tcpdump/tcpdump.c b/usr.sbin/tcpdump/tcpdump.c index b4818a38491..60552c8c19c 100644 --- a/usr.sbin/tcpdump/tcpdump.c +++ b/usr.sbin/tcpdump/tcpdump.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcpdump.c,v 1.88 2018/11/08 14:06:09 brynet Exp $ */ +/* $OpenBSD: tcpdump.c,v 1.89 2019/03/18 00:09:22 dlg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 @@ -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); @@ -700,7 +714,7 @@ __dead void usage(void) { (void)fprintf(stderr, -"Usage: %s [-AadefILlNnOopqStvXx] [-c count] [-D direction]\n", +"Usage: %s [-AadefILlNnOopqStvXx] [-B fildrop] [-c count] [-D direction]\n", program_name); (void)fprintf(stderr, "\t [-E [espalg:]espkey] [-F file] [-i interface] [-r file]\n"); -- cgit v1.2.3