diff --git a/src/pyshark/__init__.py b/src/pyshark/__init__.py index e9e0784b..0133e8c5 100644 --- a/src/pyshark/__init__.py +++ b/src/pyshark/__init__.py @@ -15,3 +15,5 @@ class UnsupportedVersionException(Exception): from pyshark.capture.file_capture import FileCapture from pyshark.capture.remote_capture import RemoteCapture from pyshark.capture.inmem_capture import InMemCapture +from pyshark.capture.pipe_capture import PipeCapture +from pyshark.capture.pipe_ring_capture import PipeRingCapture diff --git a/src/pyshark/capture/live_ring_capture.py b/src/pyshark/capture/live_ring_capture.py index f7c71a37..80622423 100644 --- a/src/pyshark/capture/live_ring_capture.py +++ b/src/pyshark/capture/live_ring_capture.py @@ -9,7 +9,8 @@ class LiveRingCapture(LiveCapture): def __init__(self, ring_file_size=1024, num_ring_files=1, ring_file_name='/tmp/pyshark.pcap', interface=None, bpf_filter=None, display_filter=None, only_summaries=False, decryption_key=None, encryption_type='wpa-pwk', decode_as=None, disable_protocol=None, - tshark_path=None, override_prefs=None, include_raw=False, eventloop=None): + tshark_path=None, override_prefs=None, include_raw=False, use_json=False, eventloop=None): + """ Creates a new live capturer on a given interface. Does not start the actual capture itself. :param ring_file_size: Size of the ring file in kB, default is 1024 @@ -32,7 +33,7 @@ def __init__(self, ring_file_size=1024, num_ring_files=1, ring_file_name='/tmp/p super(LiveRingCapture, self).__init__(interface, bpf_filter=bpf_filter, display_filter=display_filter, only_summaries=only_summaries, decryption_key=decryption_key, encryption_type=encryption_type, tshark_path=tshark_path, decode_as=decode_as, disable_protocol=disable_protocol, - override_prefs=override_prefs, include_raw=include_raw, eventloop=eventloop) + override_prefs=override_prefs, include_raw=include_raw, use_json=use_json, eventloop=eventloop) self.ring_file_size = ring_file_size self.num_ring_files = num_ring_files diff --git a/src/pyshark/capture/pipe_capture.py b/src/pyshark/capture/pipe_capture.py index 34ba2c83..42a623be 100644 --- a/src/pyshark/capture/pipe_capture.py +++ b/src/pyshark/capture/pipe_capture.py @@ -1,6 +1,3 @@ -import trollius as asyncio -from trollius import From, Return - from pyshark.capture.capture import Capture @@ -10,7 +7,7 @@ def __init__(self, pipe, display_filter=None, only_summaries=False, disable_protocol=None, tshark_path=None, override_prefs=None, use_json=False, include_raw=False, eventloop=None): """ - Receives a file-like and reads the packets from there (pcap format). + Receives a string for the filename and reads the packets from there (pcap format). Does not close the pipe. :param bpf_filter: BPF filter to use on packets. :param display_filter: Display (wireshark) filter to use. @@ -40,16 +37,30 @@ def get_parameters(self, packet_count=None): Returns the special tshark parameters to be used according to the configuration of this class. """ params = super(PipeCapture, self).get_parameters(packet_count=packet_count) - params += ['-r', '-'] - return params - - @asyncio.coroutine - def _get_tshark_process(self, packet_count=None): - proc = yield From(super(PipeCapture, self)._get_tshark_process(packet_count=packet_count, - stdin=self._pipe)) - raise Return(proc) + params.extend(['-i{}'.format(self._pipe), '-']) + return params[:-1] def close(self): - # Close pipe - self._pipe.close() + """ + Closes the capture, but not the pipe. + """ + # Close the capture. super(PipeCapture, self).close() + + # Backwards compatibility + sniff = Capture.load_packets + + def sniff_continuously(self, packet_count=None): + """ + Captures from the set interface, returning a generator which returns packets continuously. + + Can be used as follows: + for packet in capture.sniff_continuously(); + print 'Woo, another packet:', packet + + Note: you can also call capture.apply_on_packets(packet_callback) which should have a slight performance boost. + + :param packet_count: an amount of packets to capture, then stop. + """ + # Retained for backwards compatibility and to add documentation. + return self._packets_from_tshark_sync(packet_count=packet_count) diff --git a/src/pyshark/capture/pipe_ring_capture.py b/src/pyshark/capture/pipe_ring_capture.py new file mode 100644 index 00000000..e3f20746 --- /dev/null +++ b/src/pyshark/capture/pipe_ring_capture.py @@ -0,0 +1,64 @@ +from pyshark.capture.pipe_capture import PipeCapture +from pyshark.capture.capture import TSharkCrashException, TSharkVersionException +from pyshark.tshark.tshark import tshark_supports_json +import asyncio +import subprocess +import tempfile + + +class DisplayFilterNotAllowedException(Exception): + """Display Filters are not allowed in PipeRingCapture.""" + + +class PipeRingCapture(PipeCapture): + """ + Represents a live ringbuffer capture on a network interface. + """ + + def __init__(self, pipe, ring_file_size=1024, num_ring_files=2, ring_file_name=None, + only_summaries=False, decryption_key=None, + encryption_type='wpa-pwk', decode_as=None, disable_protocol=None, display_filter=None, + tshark_path=None, override_prefs=None, include_raw=False, use_json=False, eventloop=None): + """ + Creates a new live capturer on a given interface. Does not start the actual capture itself. + :param ring_file_size: Size of the ring file in kB, default is 1024 + :param num_ring_files: Number of ring files to keep, default is 1 + :param ring_file_name: Name of the ring file, default is /tmp/pyshark.pcap + :param interface: Name of the interface to sniff on or a list of names (str). If not given, runs on all interfaces. + :param bpf_filter: BPF filter to use on packets. + :param display_filter: Display (wireshark) filter to use. + :param only_summaries: Only produce packet summaries, much faster but includes very little information + :param decryption_key: Optional key used to encrypt and decrypt captured traffic. + :param encryption_type: Standard of encryption used in captured traffic (must be either 'WEP', 'WPA-PWD', or + 'WPA-PWK'. Defaults to WPA-PWK). + :param decode_as: A dictionary of {decode_criterion_string: decode_as_protocol} that are used to tell tshark + to decode protocols in situations it wouldn't usually, for instance {'tcp.port==8888': 'http'} would make + it attempt to decode any port 8888 traffic as HTTP. See tshark documentation for details. + :param tshark_path: Path of the tshark binary + :param override_prefs: A dictionary of tshark preferences to override, {PREFERENCE_NAME: PREFERENCE_VALUE, ...}. + :param disable_protocol: Tells tshark to remove a dissector for a specifc protocol. + """ + if display_filter is not None: + raise DisplayFilterNotAllowedException("Display Filters are not allowed in PipeRingCapture.") + + super(PipeRingCapture, self).__init__(pipe, display_filter=None, only_summaries=only_summaries, + decryption_key=decryption_key, encryption_type=encryption_type, + tshark_path=tshark_path, decode_as=decode_as, disable_protocol=disable_protocol, + override_prefs=override_prefs, include_raw=include_raw, use_json=use_json, eventloop=eventloop) + + self.ring_file_size = ring_file_size + self.num_ring_files = num_ring_files + if ring_file_name is None: + self.ring_file_name = tempfile.mktemp(suffix=".pcap", prefix="pyshark_") + else: + self.ring_file_name = ring_file_name + + def get_parameters(self, packet_count=None): + """ + Returns the special tshark parameters to be used according to the configuration of this class. + """ + params = super(PipeRingCapture, self).get_parameters()[:-2] + params.extend(['-i', self._pipe]) + params += ['-b', 'filesize:' + str(self.ring_file_size), '-b', 'files:' + str(self.num_ring_files), '-w', + self.ring_file_name, '-P'] + return params