summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Fenner <fenner@gmail.com>2019-05-01 11:06:03 -0700
committerBill Fenner <fenner@gmail.com>2020-05-19 04:51:22 -0700
commit014e6a0fca0a25ba74242ba76e27afaa5799e0b7 (patch)
tree70d617073680a1dcd83d636e991691864ad00157
parentf2d84366a864f7b41f59ef47334f6a53aa914b32 (diff)
downloadlibpcap-014e6a0fca0a25ba74242ba76e27afaa5799e0b7.tar.gz
New filter "ifindex" for LINUX_SLL2 and live Linux captures
-rw-r--r--gencode.c47
-rw-r--r--gencode.h1
-rw-r--r--grammar.y2
-rw-r--r--pcap-linux.c6
-rw-r--r--scanner.l2
5 files changed, 58 insertions, 0 deletions
diff --git a/gencode.c b/gencode.c
index df00dd8d..4359c102 100644
--- a/gencode.c
+++ b/gencode.c
@@ -8175,6 +8175,53 @@ gen_multicast(compiler_state_t *cstate, int proto)
/*NOTREACHED*/
}
+struct block *
+gen_ifindex(compiler_state_t *cstate, int ifindex)
+{
+ register struct block *b0;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ /*
+ * Only some data link types support ifindex qualifiers.
+ */
+ switch (cstate->linktype) {
+ case DLT_LINUX_SLL2:
+ /* match packets on this interface */
+ b0 = gen_cmp(cstate, OR_LINKHDR, 4, BPF_W, ifindex);
+ break;
+ default:
+#if defined(linux)
+ /*
+ * This is Linux with PF_PACKET support.
+ * If this is a *live* capture, we can look at
+ * special meta-data in the filter expression;
+ * if it's a savefile, we can't.
+ */
+ if (cstate->bpf_pcap->rfile != NULL) {
+ /* We have a FILE *, so this is a savefile */
+ bpf_error(cstate, "ifindex not supported on %s when reading savefiles",
+ pcap_datalink_val_to_description_or_dlt(cstate->linktype));
+ b0 = NULL;
+ /*NOTREACHED*/
+ }
+ /* match ifindex */
+ b0 = gen_cmp(cstate, OR_LINKHDR, SKF_AD_OFF + SKF_AD_IFINDEX, BPF_W,
+ ifindex);
+#else /* defined(linux) */
+ bpf_error(cstate, "ifindex not supported on %s",
+ pcap_datalink_val_to_description_or_dlt(cstate->linktype));
+ /*NOTREACHED*/
+#endif /* defined(linux) */
+ }
+ return (b0);
+}
+
/*
* Filter on inbound (dir == 0) or outbound (dir == 1) traffic.
* Outbound traffic is sent by this machine, while inbound traffic is
diff --git a/gencode.h b/gencode.h
index bffb71b6..dc099f53 100644
--- a/gencode.h
+++ b/gencode.h
@@ -328,6 +328,7 @@ struct block *gen_greater(compiler_state_t *, int);
struct block *gen_byteop(compiler_state_t *, int, int, bpf_u_int32);
struct block *gen_broadcast(compiler_state_t *, int);
struct block *gen_multicast(compiler_state_t *, int);
+struct block *gen_ifindex(compiler_state_t *, int);
struct block *gen_inbound(compiler_state_t *, int);
struct block *gen_llc(compiler_state_t *);
diff --git a/grammar.y b/grammar.y
index b73e44bf..8492378e 100644
--- a/grammar.y
+++ b/grammar.y
@@ -355,6 +355,7 @@ DIAG_OFF_BISON_BYACC
%token ATALK AARP DECNET LAT SCA MOPRC MOPDL
%token TK_BROADCAST TK_MULTICAST
%token NUM INBOUND OUTBOUND
+%token IFINDEX
%token PF_IFNAME PF_RSET PF_RNR PF_SRNR PF_REASON PF_ACTION
%token TYPE SUBTYPE DIR ADDR1 ADDR2 ADDR3 ADDR4 RA TA
%token LINK
@@ -581,6 +582,7 @@ other: pqual TK_BROADCAST { CHECK_PTR_VAL(($$ = gen_broadcast(cstate, $1))); }
| CBYTE NUM byteop NUM { CHECK_PTR_VAL(($$ = gen_byteop(cstate, $3, $2, $4))); }
| INBOUND { CHECK_PTR_VAL(($$ = gen_inbound(cstate, 0))); }
| OUTBOUND { CHECK_PTR_VAL(($$ = gen_inbound(cstate, 1))); }
+ | IFINDEX NUM { CHECK_PTR_VAL(($$ = gen_ifindex(cstate, $2))); }
| VLAN pnum { CHECK_PTR_VAL(($$ = gen_vlan(cstate, $2, 1))); }
| VLAN { CHECK_PTR_VAL(($$ = gen_vlan(cstate, 0, 0))); }
| MPLS pnum { CHECK_PTR_VAL(($$ = gen_mpls(cstate, $2, 1))); }
diff --git a/pcap-linux.c b/pcap-linux.c
index a783aaba..bf0bc812 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -5923,6 +5923,12 @@ fix_offset(pcap_t *handle, struct bpf_insn *p)
* special magic kernel offset for that field.
*/
p->k = SKF_AD_OFF + SKF_AD_PROTOCOL;
+ } else if (p->k == 4) {
+ /*
+ * It's the ifindex field; map it to the
+ * special magic kernel offset for that field.
+ */
+ p->k = SKF_AD_OFF + SKF_AD_IFINDEX;
} else if (p->k == 10) {
/*
* It's the packet type field; map it to the
diff --git a/scanner.l b/scanner.l
index 83091c94..06b9acc1 100644
--- a/scanner.l
+++ b/scanner.l
@@ -337,6 +337,8 @@ len|length return LEN;
inbound return INBOUND;
outbound return OUTBOUND;
+ifindex return IFINDEX;
+
vlan return VLAN;
mpls return MPLS;
pppoed return PPPOED;