Skip to content

Commit 059aaf5

Browse files
committed
added bpf_filter
1 parent 4f831d2 commit 059aaf5

File tree

4 files changed

+52
-9
lines changed

4 files changed

+52
-9
lines changed

stenotype/Makefile

+8-9
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ ifneq (,$(wildcard /usr/bin/c++))
2626
CXX=/usr/bin/c++
2727
endif
2828
SHARED_CFLAGS=-std=c++0x -Wall -fno-strict-aliasing $(DEFINES)
29-
SHARED_LDFLAGS=-lleveldb -lrt -laio -lpthread -lsnappy -lseccomp
29+
SHARED_LDFLAGS=-lleveldb -lrt -laio -lpthread -lsnappy -lseccomp -lpcap
3030
ifneq (,$(wildcard /usr/include/testimony.h))
3131
SHARED_LDFLAGS += -ltestimony
3232
endif
@@ -56,12 +56,12 @@ FUZZ_FILES=util index index_bin
5656
SANITIZE=
5757
ifndef SANITIZE
5858
OBJECTS=$(foreach file,$(FILES),$(file)_opt.o)
59-
CFLAGS:=$(CFLAGS) $(SHARED_CFLAGS) $(OPT_CFLAGS)
60-
LDFLAGS:=$(LDFLAGS) $(SHARED_LDFLAGS) $(OPT_LDFLAGS)
59+
CFLAGS=$(SHARED_CFLAGS) $(OPT_CFLAGS)
60+
LDFLAGS=$(SHARED_LDFLAGS) $(OPT_LDFLAGS)
6161
else
6262
OBJECTS=$(foreach file,$(FILES),$(file)_$(SANITIZE)_dbg.o)
63-
CFLAGS:=$(CFLAGS) $(SHARED_CFLAGS) $(DBG_CFLAGS) -fsanitize=$(SANITIZE)
64-
LDFLAGS:=$(LDFLAGS) $(SHARED_LDFLAGS) $(DBG_LDFLAGS)
63+
CFLAGS=$(SHARED_CFLAGS) $(DBG_CFLAGS) -fsanitize=$(SANITIZE)
64+
LDFLAGS=$(SHARED_LDFLAGS) $(DBG_LDFLAGS)
6565
CXX=clang++ # Force clang if we're sanitizing
6666
endif
6767
ifeq "$(SANITIZE)" "memory"
@@ -78,15 +78,15 @@ clean:
7878

7979
# Generate g++ object files.
8080
%_opt.o: %.cc $(DEPS)
81-
$(CXX) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
81+
$(CXX) $(CFLAGS) -c -o $@ $<
8282

8383
# Generate clang object files.
8484
%_$(SANITIZE)_dbg.o: %.cc $(DEPS)
85-
$(CXX) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
85+
$(CXX) $(CFLAGS) -c -o $@ $<
8686

8787
# Generate the stenotype binary itself. You mostly want this :)
8888
stenotype: $(OBJECTS)
89-
$(CXX) $(CFLAGS) $(CPPFLAGS) -o $@ $^ $(LDFLAGS)
89+
$(CXX) $(CFLAGS) -o $@ $^ $(LDFLAGS)
9090

9191

9292

@@ -103,4 +103,3 @@ index_fuzz: $(foreach file,$(FUZZ_FILES),$(file)_afl.o)
103103
# Run afl-fuzz to fuzz the index_fuzz binary.
104104
fuzz: index_fuzz
105105
afl-fuzz -i afl_tests -o afl_findings ./index_fuzz @@
106-

stenotype/packets.cc

+33
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
#include <unistd.h> // close(), getpid()
2929
#include <sys/ioctl.h> // ioctl()
3030

31+
#include <pcap.h> // pcap_compile
32+
33+
3134
#include <memory>
3235
#include <string>
3336
#include <sstream>
@@ -301,6 +304,36 @@ Error PacketsV3::Builder::SetFilter(const std::string& filter) {
301304
return SUCCESS;
302305
}
303306

307+
Error PacketsV3::Builder::SetBPFFilter(const std::string& filter) {
308+
RETURN_IF_ERROR(BadState(), "Builder");
309+
310+
struct bpf_program raw_filter;
311+
int linktype = DLT_EN10MB;
312+
313+
if (pcap_compile_nopcap(0xffff, linktype, &raw_filter, filter.data(), 1, 0) == -1) {
314+
return ERROR("invalid filter: too long");
315+
316+
317+
RETURN_IF_ERROR(Errno(setsockopt(state_.fd, SOL_SOCKET, SO_ATTACH_FILTER, &raw_filter, sizeof(raw_filter))),
318+
"so_attach_filter"); }
319+
320+
321+
#ifdef SO_LOCK_FILTER
322+
int v = 1;
323+
// SO_LOCK_FILTER is available only on kernels >= 3.9, so ignore the
324+
// ENOPROTOOPT
325+
// error here. We use it to make sure that no one can mess with our socket's
326+
// filter, so not having it is not really a big concern.
327+
RETURN_IF_ERROR(
328+
Errno(setsockopt(state_.fd, SOL_SOCKET, SO_LOCK_FILTER, &v, sizeof(v)) ||
329+
errno == ENOPROTOOPT),
330+
"so_lock_filter");
331+
errno = 0;
332+
#endif
333+
pcap_freecode( (struct bpf_program *) &raw_filter);
334+
return SUCCESS;
335+
}
336+
304337
Error PacketsV3::Builder::BadState() {
305338
if (state_.fd < 0) {
306339
return ERROR(

stenotype/packets.h

+3
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,9 @@ class PacketsV3 : public Packets {
200200
// SetFilter sets a BPF filter on the socket.
201201
Error SetFilter(const std::string& filter);
202202

203+
// SetBPFFilter sets a BPF filter on the socket.
204+
Error SetBPFFilter(const std::string& filter);
205+
203206
// Determines whether Bind will set the interface into promiscuous sniffing
204207
// mode.
205208
Error SetPromisc(bool promisc);

stenotype/stenotype.cc

+8
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ namespace {
8686

8787
std::string flag_iface = "eth0";
8888
std::string flag_filter = "";
89+
std::string flag_bpf_filter = "";
8990
std::string flag_dir = "";
9091
int64_t flag_count = -1;
9192
int32_t flag_blocks = 2048;
@@ -199,6 +200,9 @@ int ParseOptions(int key, char* arg, struct argp_state* state) {
199200
case 323:
200201
flag_stats_sec = atoi(arg);
201202
break;
203+
case 324:
204+
flag_bpf_filter = arg;
205+
break;
202206
}
203207
return 0;
204208
}
@@ -243,6 +247,7 @@ void ParseOptions(int argc, char** argv) {
243247
{"no_promisc", 321, 0, 0, "Don't set promiscuous mode"},
244248
{"stats_blocks", 322, n, 0, "Size block stats will be displayed, requires verbose, default 100, 0 disables"},
245249
{"stats_sec", 323, n, 0, "Seconds stats will be displayed, requires verbose, default 60, 0 disables"},
250+
{"bpf_filter", 324, s, 0,"string filer"},
246251
{0},
247252
};
248253
struct argp argp = {options, &ParseOptions};
@@ -614,7 +619,10 @@ int Main(int argc, char** argv) {
614619
}
615620
if (!flag_filter.empty()) {
616621
CHECK_SUCCESS(builder.SetFilter(flag_filter));
622+
} else if (!flag_bpf_filter.empty()) {
623+
CHECK_SUCCESS(builder.SetBPFFilter(flag_bpf_filter));
617624
}
625+
618626
Packets* v3;
619627
CHECK_SUCCESS(builder.Bind(flag_iface, &v3));
620628
sockets.push_back(v3);

0 commit comments

Comments
 (0)