Skip to content

Commit

Permalink
Support (BPF) filter in sniff() with offline parameter set (#394)
Browse files Browse the repository at this point in the history
* Support (BPF) filter in sniff() with offline parameter set

Fixes #393
Also, fixes #355

* Add tests for wrpcap() and sniff(offline=)

as suggested by Guillaume.

Also, cleanup regression.uts since it was a pain to find a place
to add those tests.

* Fix PATH for tcpdump with non-root user

* Do not run tcpdump tests when tcpdump is not available

* Appveyor tests: install WinDump.exe

Thanks @gpotter2
  • Loading branch information
p-l- authored and guedou committed Dec 20, 2016
1 parent 8d78adb commit 7ec0af2
Show file tree
Hide file tree
Showing 5 changed files with 478 additions and 155 deletions.
13 changes: 12 additions & 1 deletion .travis/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,20 @@ fi
# Test AEAD modes in IPsec if available
if [ "$TEST_COMBINED_MODES" != "yes" ]
then
UT_FLAGS+=" -K combined_modes "
UT_FLAGS+=" -K combined_modes"
fi

# Set PATH
for _path in /sbin /usr/sbin /usr/local/sbin; do
[ -d "$_path" ] && echo "$PATH" | grep -qvE "(^|:)$_path(:|$)" && export PATH="$PATH:$_path"
done

# Do we have tcpdump?
which tcpdump >/dev/null 2>&1 || UT_FLAGS+=" -K tcpdump"

# Dump Environment (so that we can check PATH, UT_FLAGS, etc.)
set

# Run unit tests
cd test/

Expand Down
6 changes: 4 additions & 2 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ build: off
install:
# Installing WinPcap directly does not work,
# see http://help.appveyor.com/discussions/problems/2280-winpcap-installation-issue
- choco install -y nmap
# - choco install -y nmap
- choco install -y winpcap
- ps: wget http://www.winpcap.org/windump/install/bin/windump_3_9_5/WinDump.exe -UseBasicParsing -OutFile C:\Windows\System32\windump.exe
- refreshenv

# Install Python modules
Expand All @@ -22,7 +24,7 @@ install:
test_script:
# Set environment variables
- set PYTHONPATH=%APPVEYOR_BUILD_FOLDER%
- set PATH=%APPVEYOR_BUILD_FOLDER%;C:\Windows\System32\Npcap\;%PATH%
- set PATH=%APPVEYOR_BUILD_FOLDER%;%PATH%

# Main unit tests
- "%PYTHON%\\python bin\\UTscapy -f text -t test\\regression.uts -F -K automaton -K mock_read_routes6_bsd || exit /b 42"
Expand Down
31 changes: 28 additions & 3 deletions scapy/arch/windows/compatibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,20 @@
Instanciate part of the customizations needed to support Microsoft Windows.
"""

import itertools
import os
import re
import socket
import subprocess
import sys
import time

from scapy.arch.consts import LOOPBACK_NAME
from scapy.config import conf,ConfClass
from scapy.base_classes import Gen, SetGen
import scapy.plist as plist
from scapy.utils import PcapReader
from scapy.data import MTU, ETH_P_ARP
import os,re,sys,socket,time, itertools

WINDOWS = True

Expand Down Expand Up @@ -171,6 +178,7 @@ def sniff(count=0, store=1, offline=None, prn = None, lfilter=None, L2socket=Non
prn: function to apply to each packet. If something is returned,
it is displayed. Ex:
ex: prn = lambda x: x.summary()
filter: provide a BPF filter
lfilter: python function applied to each packet to determine
if further action may be done
ex: lfilter = lambda x: x.haslayer(Padding)
Expand All @@ -186,8 +194,25 @@ def sniff(count=0, store=1, offline=None, prn = None, lfilter=None, L2socket=Non
L2socket = conf.L2listen
s = L2socket(type=ETH_P_ALL, *arg, **karg)
else:
s = PcapReader(offline)

flt = karg.get('filter')
if flt is not None:
if isinstance(offline, basestring):
s = PcapReader(
subprocess.Popen(
[conf.prog.tcpdump, "-r", offline, "-w", "-", flt],
stdout=subprocess.PIPE
).stdout
)
else:
s = PcapReader(
subprocess.Popen(
[conf.prog.tcpdump, "-r", "-", "-w", "-", flt],
stdin=offline,
stdout=subprocess.PIPE
).stdout
)
else:
s = PcapReader(offline)
lst = []
if timeout is not None:
stoptime = time.time()+timeout
Expand Down
27 changes: 25 additions & 2 deletions scapy/sendrecv.py
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,7 @@ def sniff(count=0, store=1, offline=None, prn=None, lfilter=None,
prn: function to apply to each packet. If something is returned,
it is displayed. Ex:
ex: prn = lambda x: x.summary()
filter: provide a BPF filter
lfilter: python function applied to each packet to determine
if further action may be done
ex: lfilter = lambda x: x.haslayer(Padding)
Expand Down Expand Up @@ -603,8 +604,30 @@ def sniff(count=0, store=1, offline=None, prn=None, lfilter=None,
sniff_sockets = [L2socket(type=ETH_P_ALL, iface=iface, *arg,
**karg)]
else:
sniff_sockets = [PcapReader(offline)]

flt = karg.get('filter')
if flt is not None:
if isinstance(offline, basestring):
sniff_sockets = [
PcapReader(
subprocess.Popen(
[conf.prog.tcpdump, "-r", offline, "-w", "-",
flt],
stdout=subprocess.PIPE
).stdout
)
]
else:
sniff_sockets = [
PcapReader(
subprocess.Popen(
[conf.prog.tcpdump, "-r", "-", "-w", "-", flt],
stdin=offline,
stdout=subprocess.PIPE
).stdout
)
]
else:
sniff_sockets = [PcapReader(offline)]
lst = []
if timeout is not None:
stoptime = time.time()+timeout
Expand Down
Loading

0 comments on commit 7ec0af2

Please sign in to comment.