diff options
author | Guy Harris <guy@alum.mit.edu> | 2014-11-05 11:12:00 -0800 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2014-11-05 11:12:00 -0800 |
commit | d8e39a9c306fe393a54029ca28693a63ab487e82 (patch) | |
tree | d6963fba4b3294ee1f6ade1cd976fb71f280c39b /pcap-linux.c | |
parent | 0a5aeb6a0865c8fb2b26b0ec74c72d0bef215d8f (diff) | |
parent | 04660eb1e56102e2369473cae2538e4d3d263607 (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.c | 23 |
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)) |