aboutsummaryrefslogtreecommitdiff
path: root/pcap-linux.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2014-11-05 11:12:00 -0800
committerGuy Harris <guy@alum.mit.edu>2014-11-05 11:12:00 -0800
commitd8e39a9c306fe393a54029ca28693a63ab487e82 (patch)
treed6963fba4b3294ee1f6ade1cd976fb71f280c39b /pcap-linux.c
parent0a5aeb6a0865c8fb2b26b0ec74c72d0bef215d8f (diff)
parent04660eb1e56102e2369473cae2538e4d3d263607 (diff)
Merge pull request #391 from msekletar/vlan-bpf
[RFC] Fix vlan filtering on Linux
Diffstat (limited to 'pcap-linux.c')
-rw-r--r--pcap-linux.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/pcap-linux.c b/pcap-linux.c
index a48ed40b..101ad942 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -1484,6 +1484,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
int packet_len, caplen;
struct pcap_pkthdr pcap_header;
+ struct bpf_aux_data aux_data;
#ifdef HAVE_PF_PACKET_SOCKETS
/*
* If this is a cooked device, leave extra room for a
@@ -1667,6 +1668,11 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
tag->vlan_tpid = htons(ETH_P_8021Q);
tag->vlan_tci = htons(aux->tp_vlan_tci);
+ /* store vlan tci to bpf_aux_data struct for userland bpf filter */
+#if defined(TP_STATUS_VLAN_VALID)
+ aux_data.vlan_tag = htons(aux->tp_vlan_tci) & 0x0fff;
+ aux_data.vlan_tag_present = (aux->tp_status & TP_STATUS_VLAN_VALID);
+#endif
packet_len += VLAN_TAG_LEN;
}
}
@@ -1711,8 +1717,8 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
/* Run the packet filter if not using kernel filter */
if (handlep->filter_in_userland && handle->fcode.bf_insns) {
- if (bpf_filter(handle->fcode.bf_insns, bp,
- packet_len, caplen) == 0)
+ if (bpf_filter1(handle->fcode.bf_insns, bp,
+ packet_len, caplen, &aux_data) == 0)
{
/* rejected by filter */
return 0;
@@ -4225,10 +4231,15 @@ static int pcap_handle_packet_mmap(
* the filter when the ring became empty, but it can possibly
* happen a lot later... */
bp = frame + tp_mac;
- if (handlep->filter_in_userland && handle->fcode.bf_insns &&
- (bpf_filter(handle->fcode.bf_insns, bp,
- tp_len, tp_snaplen) == 0))
- return 0;
+ if (handlep->filter_in_userland && handle->fcode.bf_insns) {
+ struct bpf_aux_data aux_data;
+
+ aux_data.vlan_tag = tp_vlan_tci & 0x0fff;
+ aux_data.vlan_tag_present = tp_vlan_tci_valid;
+
+ if (bpf_filter1(handle->fcode.bf_insns, bp, tp_len, tp_snaplen, &aux_data) == 0)
+ return 0;
+ }
sll = (void *)frame + TPACKET_ALIGN(handlep->tp_hdrlen);
if (!linux_check_direction(handle, sll))