Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Report usage of unsupported display filter protocol #693

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion src/pyshark/capture/capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@
import sys
import logging
import warnings
import difflib

from pyshark import ek_field_mapping
from pyshark.packet.packet import Packet
from pyshark.tshark.output_parser import tshark_ek
from pyshark.tshark.output_parser import tshark_json
from pyshark.tshark.output_parser import tshark_xml
from pyshark.tshark.tshark import get_process_path, get_tshark_display_filter_flag, \
tshark_supports_json, TSharkVersionException, get_tshark_version, tshark_supports_duplicate_keys
tshark_supports_json, TSharkVersionException, get_tshark_version, tshark_supports_duplicate_keys, \
TSharkProtocolNotSupportedException, tshark_supports_protocol, get_supported_protocols


if sys.version_info < (3, 8):
Expand Down Expand Up @@ -323,6 +325,17 @@ def _get_tshark_version(self):
self.__tshark_version = get_tshark_version(self.tshark_path)
return self.__tshark_version

def _suggest_protocol_name(self, input_protocol, tshark_path=None, suggestions=1):
"""Suggests the correct protocol names based on the user's input.

:param input_protocol: Protocol name to match.
:param tshark_path: Custom path to the TShark executable.
:param suggestions: Number of suggestions to return.
:return: list: A list of suggested protocol names.
"""
protocols = get_supported_protocols(tshark_path)
return difflib.get_close_matches(input_protocol.lower(), protocols, n=suggestions)

async def _get_tshark_process(self, packet_count=None, stdin=None):
"""Returns a new tshark process with previously-set parameters."""
self._verify_capture_parameters()
Expand All @@ -344,6 +357,17 @@ async def _get_tshark_process(self, packet_count=None, stdin=None):
parameters = [self._get_tshark_path(), "-l", "-n", "-T", output_type] + \
self.get_parameters(packet_count=packet_count) + output_parameters

if not tshark_supports_protocol(self._display_filter):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH this seems like overkill to check it every time we get the process, since it'll only fail very rarely. Maybe we can check it on a crash to explain it?

suggestions = "or".join(self._suggest_protocol_name(self._display_filter))
if (suggestions == ""):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if not suggestions:?

raise TSharkProtocolNotSupportedException(
f"Protocol {self._display_filter} is not supported by TShark. " + \
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for the + \ here, it'll be concatenated anyway

"Check if protocol is mistyped or it is not loaded to the correct plugins folder")
else:
raise TSharkProtocolNotSupportedException(
f"Protocol {self._display_filter} is not supported by TShark. " + \
f"Did you mean {suggestions}, or the protocol is not loaded to the correct plugins folder")

self._log.debug(
"Creating TShark subprocess with parameters: " + " ".join(parameters))
self._log.debug("Executable: %s", parameters[0])
Expand Down
33 changes: 33 additions & 0 deletions src/pyshark/tshark/tshark.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
class TSharkNotFoundException(Exception):
pass

class TSharkProtocolNotSupportedException(Exception):
pass

class TSharkVersionException(Exception):
pass
Expand Down Expand Up @@ -95,6 +97,37 @@ def tshark_supports_duplicate_keys(tshark_version):
def tshark_supports_json(tshark_version):
return tshark_version >= version.parse("2.2.0")

def get_supported_protocols(tshark_path=None):
"""Fetches a list of all protocols supported by TShark.

:param tshark_path: Optional; custom path to the TShark executable.
:return: A list of supported protocol names.
"""
protocols = []
parameters = [get_process_path(tshark_path), "-G", "protocols"]
result = subprocess.run(parameters, capture_output=True, text=True, check=True)
# List all protocols
for line in result.stdout.splitlines():
columns = line.split('\t')
# Capture the protocol name
if len(columns) >= 3:
protocols.append(columns[2])
return protocols

def tshark_supports_protocol(protocol_name, tshark_path=None):
"""Checks if the specified protocol is supported by TShark.

:param protocol_name: Name of protocol to check.
:param tshark_path: Optional; Custom path to the TShark executable.
:return: True if the protocol is supported, False otherwise
If no protocol is given a True is returned
"""
if not protocol_name:
return True

supported_protocols = get_supported_protocols(tshark_path=tshark_path)
# Exact-match the protocol name against the third column
return protocol_name in supported_protocols

def get_tshark_display_filter_flag(tshark_version):
"""Returns '-Y' for tshark versions >= 1.10.0 and '-R' for older versions."""
Expand Down