Skip to content

Commit

Permalink
issue: #319
Browse files Browse the repository at this point in the history
Merge branch 'master' of https://github.com/solofox/libpcap into solofox-master
  • Loading branch information
mcr committed Feb 15, 2015
2 parents b34ce52 + 3a555d0 commit 186a4f2
Show file tree
Hide file tree
Showing 10 changed files with 446 additions and 3 deletions.
100 changes: 99 additions & 1 deletion optimize.c
Original file line number Diff line number Diff line change
Expand Up @@ -2244,7 +2244,92 @@ install_bpf_program(pcap_t *p, struct bpf_program *fp)

#ifdef BDEBUG
static void
opt_dump(struct block *root)
dot_dump_node(struct block *block, struct bpf_program *prog, FILE *out)
{
int icount, noffset;
int i;

if (block == NULL || isMarked(block))
return;
Mark(block);

icount = slength(block->stmts) + 1 + block->longjt + block->longjf;
noffset = min(block->offset + icount, (int)prog->bf_len);

fprintf(out, "\tblock%d [shape=ellipse, id=\"block-%d\" label=\"BLOCK%d\\n", block->id, block->id, block->id);
for (i = block->offset; i < noffset; i++) {
fprintf(out, "\\n%s", bpf_image(prog->bf_insns + i, i));
}
fprintf(out, "\" tooltip=\"");
for (i = 0; i < BPF_MEMWORDS; i++)
if (block->val[i] != 0)
fprintf(out, "val[%d]=%d ", i, block->val[i]);
fprintf(out, "val[A]=%d ", block->val[A_ATOM]);
fprintf(out, "val[X]=%d", block->val[X_ATOM]);
fprintf(out, "\"");
if (JT(block) == NULL)
fprintf(out, ", peripheries=2");
fprintf(out, "];\n");

dot_dump_node(JT(block), prog, out);
dot_dump_node(JF(block), prog, out);
}
static void
dot_dump_edge(struct block *block, FILE *out)
{
if (block == NULL || isMarked(block))
return;
Mark(block);

if (JT(block)) {
fprintf(out, "\t\"block%d\":se -> \"block%d\":n [label=\"T\"]; \n",
block->id, JT(block)->id);
fprintf(out, "\t\"block%d\":sw -> \"block%d\":n [label=\"F\"]; \n",
block->id, JF(block)->id);
}
dot_dump_edge(JT(block), out);
dot_dump_edge(JF(block), out);
}
/* Output the block CFG using graphviz/DOT language
* In the CFG, block's code, value index for each registers at EXIT,
* and the jump relationship is show.
*
* example DOT for BPF `ip src host 1.1.1.1' is:
digraph BPF {
block0 [shape=ellipse, id="block-0" label="BLOCK0\n\n(000) ldh [12]\n(001) jeq #0x800 jt 2 jf 5" tooltip="val[A]=0 val[X]=0"];
block1 [shape=ellipse, id="block-1" label="BLOCK1\n\n(002) ld [26]\n(003) jeq #0x1010101 jt 4 jf 5" tooltip="val[A]=0 val[X]=0"];
block2 [shape=ellipse, id="block-2" label="BLOCK2\n\n(004) ret #68" tooltip="val[A]=0 val[X]=0", peripheries=2];
block3 [shape=ellipse, id="block-3" label="BLOCK3\n\n(005) ret #0" tooltip="val[A]=0 val[X]=0", peripheries=2];
"block0":se -> "block1":n [label="T"];
"block0":sw -> "block3":n [label="F"];
"block1":se -> "block2":n [label="T"];
"block1":sw -> "block3":n [label="F"];
}
*
* After install graphviz on http://www.graphviz.org/, save it as bpf.dot
* and run `dot -Tpng -O bpf.dot' to draw the graph.
*/
static void
dot_dump(struct block *root)
{
struct bpf_program f;
FILE *out = stdout;

memset(bids, 0, sizeof bids);
f.bf_insns = icode_to_fcode(root, &f.bf_len);

fprintf(out, "digraph BPF {\n");
unMarkAll();
dot_dump_node(root, &f, out);
unMarkAll();
dot_dump_edge(root, out);
fprintf(out, "}\n");

free((char *)f.bf_insns);
}

static void
plain_dump(struct block *root)
{
struct bpf_program f;

Expand All @@ -2254,4 +2339,17 @@ opt_dump(struct block *root)
putchar('\n');
free((char *)f.bf_insns);
}
static void
opt_dump(struct block *root)
{
/* if optimizer debugging is enabled, output DOT graph
* `dflag=4' is equivalent to -dddd to follow -d/-dd/-ddd
* convention in tcpdump command line
*/
if (dflag > 3)
dot_dump(root);
else
plain_dump(root);
}

#endif
2 changes: 2 additions & 0 deletions tests/BPF/1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# common block merging, same block elimination, result propogation
host 192.168.1.1
2 changes: 2 additions & 0 deletions tests/BPF/2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# common block merging
port 80
1 change: 1 addition & 0 deletions tests/BPF/3.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tcp[tcpflags]&tcp-syn != 0 or tcp[tcpflags]&tcp-fin != 0 or tcp[tcpflags]&tcp-rst != 0
2 changes: 2 additions & 0 deletions tests/BPF/4.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# or pullup
ether[12:2] = 0x800 or ether[12:2] = 0x8100 or ether[0] & 0x80 != 0 or ether[12:2] = 0x9100
1 change: 1 addition & 0 deletions tests/BPF/5.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
vlan 186 and ip
1 change: 1 addition & 0 deletions tests/BPF/6.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ip and ((icmp and dst host 1.1.1.1 and not host 2.2.2.2) or (host 1.1.1.1 and src host 3.3.3.3))
1 change: 1 addition & 0 deletions tests/BPF/7.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
not vlan and tcp port 80
30 changes: 28 additions & 2 deletions tests/filtertest.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ static void warn(const char *, ...)
extern int optind;
extern int opterr;
extern char *optarg;
#ifdef BDEBUG
int dflag;
#endif

/*
* On Windows, we need to open the file in binary mode, so that
Expand Down Expand Up @@ -178,7 +181,9 @@ main(int argc, char **argv)
{
char *cp;
int op;
#ifndef BDEBUG
int dflag;
#endif
char *infile;
int Oflag;
long snaplen;
Expand All @@ -193,11 +198,19 @@ main(int argc, char **argv)
if(wsockinit() != 0) return 1;
#endif /* WIN32 */

#ifndef BDEBUG
dflag = 1;
#else
/* if optimizer debugging is enabled, output DOT graph
* `dflag=4' is equivalent to -dddd to follow -d/-dd/-ddd
* convention in tcpdump command line
*/
dflag = 4;
#endif
infile = NULL;
Oflag = 1;
snaplen = 68;

if ((cp = strrchr(argv[0], '/')) != NULL)
program_name = cp + 1;
else
Expand Down Expand Up @@ -258,7 +271,7 @@ main(int argc, char **argv)
if (p == argv[optind] || *p != '\0')
error("invalid data link type %s", argv[optind]);
}

if (infile)
cmdbuf = read_infile(infile);
else
Expand All @@ -270,8 +283,21 @@ main(int argc, char **argv)

if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
error("%s", pcap_geterr(pd));

if (!bpf_validate(fcode.bf_insns, fcode.bf_len))
warn("Filter doesn't pass validation");

#ifdef BDEBUG
// replace line feed with space
for (cp = cmdbuf; *cp != '\0'; ++cp) {
if (*cp == '\r' || *cp == '\n') {
*cp = ' ';
}
}
// only show machine code if BDEBUG defined, since dflag > 3
printf("machine codes for filter: %s\n", cmdbuf);
#endif

bpf_dump(&fcode, dflag);
pcap_close(pd);
exit(0);
Expand Down
Loading

0 comments on commit 186a4f2

Please sign in to comment.