Skip to content

Conversation

bkayranci
Copy link

The pcapng format specification explicitly allows for multiple comments to be associated with a packet via repeated opt_comment fields. This change brings Scapy closer to that standard, making it easier to work with multi-comment pcapng traces and enabling richer annotations in packet analysis.

Checklist:

  • If you are new to Scapy: I have checked CONTRIBUTING.md (esp. section submitting-pull-requests)
  • I squashed commits belonging together
  • I added unit tests or explained why they are not relevant
  • I executed the regression tests (using cd test && ./run_tests or tox)
  • If the PR is still not finished, please create a Draft Pull Request

@bkayranci
Copy link
Author

Hi @gpotter2 , this is my first contribution to the repo. Could you please review this PR? Let me know if there's anything I should fix. Thanks!

Copy link

codecov bot commented Jul 21, 2025

Codecov Report

❌ Patch coverage is 91.66667% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.91%. Comparing base (b54fdb7) to head (6f2593c).
⚠️ Report is 19 commits behind head on master.

Files with missing lines Patch % Lines
scapy/utils.py 86.95% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4798      +/-   ##
==========================================
+ Coverage   80.08%   80.91%   +0.83%     
==========================================
  Files         365      366       +1     
  Lines       89027    90147    +1120     
==========================================
+ Hits        71296    72942    +1646     
+ Misses      17731    17205     -526     
Files with missing lines Coverage Δ
scapy/packet.py 84.66% <100.00%> (+0.10%) ⬆️
scapy/utils.py 73.54% <86.95%> (-0.33%) ⬇️

... and 48 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bkayranci
Copy link
Author

Hi again @gpotter2, just following up on this PR. We have a need for this feature in our project, so I’d really appreciate a review when you have the time. Please let me know if any changes are needed. Thanks in advance!

scapy/utils.py Outdated

def __init__(self, filename, fdesc=None, magic=None): # type: ignore
# type: (str, IO[bytes], bytes) -> None
def __init__(self, filename, fdesc=None, magic=None, comments=None): # type: ignore
Copy link
Member

Choose a reason for hiding this comment

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

This looks weird. I don't understand why you would be passing comments to the reader?

Copy link
Author

Choose a reason for hiding this comment

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

This was likely my oversight — it’s not actually necessary. I’ll go ahead and remove it.

@@ -1802,7 +1803,12 @@ def _read_options(self, options):
"%d !" % len(options))
raise EOFError
if code != 0 and 4 + length <= len(options):
opts[code] = options[4:4 + length]
if code in [1, 2988, 2989, 19372, 19373]:
Copy link
Member

Choose a reason for hiding this comment

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

What are those?

Copy link
Author

Choose a reason for hiding this comment

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

These are option codes defined in the pcapng file format docs, and it's possible for multiple codes to be present.

Copy link
Member

Choose a reason for hiding this comment

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

Got it. Could you add the link you just sent as a comment? Thanks.

Copy link
Author

Choose a reason for hiding this comment

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

Added it as a comment just now 👍

scapy/utils.py Outdated
p.comment = comment
p.comments = comments
if p.comments is None:
p.comment = comment
Copy link
Member

Choose a reason for hiding this comment

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

I don't get this. I would expect to only set comments (?)

Copy link
Author

Choose a reason for hiding this comment

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

This part is included for backward compatibility. If comments is None, we assign comment = comment to ensure existing usage doesn't break.

Copy link
Member

Choose a reason for hiding this comment

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

If I understand it well you're already using a property for comment to take the last value of comments. this should already take care of compatibility, so I don't understand why it's necessary to put the two.

Copy link
Author

Choose a reason for hiding this comment

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

You're right. this isn't necessary anymore, so I'm removing it. Thanks for pointing it out!

@gpotter2
Copy link
Member

Thanks for the PR and sorry for the delay of review. I have a few questions regarding the code.
Cheers !

@bkayranci
Copy link
Author

Thanks for the PR and sorry for the delay of review. I have a few questions regarding the code.
Cheers !

Let me know if there's anything else I should take care of before this can be merged. Appreciate your time!

scapy/utils.py Outdated
@@ -2211,7 +2225,8 @@ def write_packet(self,
comment=comment,
Copy link
Member

Choose a reason for hiding this comment

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

Remove?

scapy/utils.py Outdated
@@ -2194,6 +2207,7 @@ def write_packet(self,
wirelen = caplen

comment = getattr(packet, "comment", None)
Copy link
Member

Choose a reason for hiding this comment

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

Remove?

scapy/utils.py Outdated
@@ -2366,6 +2381,7 @@ def _write_packet(self,
comment=None, # type: Optional[bytes]
Copy link
Member

Choose a reason for hiding this comment

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

Remove?

scapy/utils.py Outdated
@@ -2600,6 +2617,7 @@ def _write_packet(self, # type: ignore
comment=None, # type: Optional[bytes]
Copy link
Member

Choose a reason for hiding this comment

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

Remove?

@gpotter2
Copy link
Member

gpotter2 commented Aug 1, 2025

I also personally would have kept comments in the same argument index as comment, rather than adding it at the end.

@bkayranci
Copy link
Author

I also personally would have kept comments in the same argument index as comment, rather than adding it at the end.

That's a fair point, and I understand the value of maintaining positional consistency. In this case, since we changed both the name and the type (comment: Optional[str] to comments: Optional[List[bytes]]), we felt that reusing the same argument position might introduce subtle bugs or make mistakes harder to catch during refactoring. especially if any code still relies on the previous positional usage. Placing comments at the end was a cautious choice to reduce the risk of silent errors. Open to refactor if you think it’s worth aligning for clarity.

@bkayranci
Copy link
Author

@gpotter2 I hope all is well. I wanted to gently follow up on my comment on the PR. I'd be grateful for your thoughts whenever you get a chance.

Copy link
Member

@guedou guedou left a comment

Choose a reason for hiding this comment

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

Thanks for the PR. I made a second review.

gpotter2
gpotter2 previously approved these changes Aug 22, 2025
@gpotter2
Copy link
Member

LGTM although tests don't pass.

@guedou guedou dismissed gpotter2’s stale review August 22, 2025 07:26

A change is still needed

@bkayranci
Copy link
Author

LGTM although tests don't pass.

I fixed typing and linting issues.

I noticed a few # type: ignore lines — that makes sense here since mypy can’t infer the types, but according to the pcapng spec we know they are bytes or List[bytes]

"comment", "ifname", "direction",
"process_information"])
"comments", "ifname", "direction",
"process_information", ])
Copy link
Member

@guedou guedou Aug 28, 2025

Choose a reason for hiding this comment

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

Suggested change
"process_information", ])
"process_information"])

@@ -1802,7 +1802,13 @@ def _read_options(self, options):
"%d !" % len(options))
raise EOFError
if code != 0 and 4 + length <= len(options):
opts[code] = options[4:4 + length]
# https://www.ietf.org/archive/id/draft-tuexen-opsawg-pcapng-05.html#name-options-format
if code in [1, 2988, 2989, 19372, 19373]:
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if code in [1, 2988, 2989, 19372, 19373]:
if code in [1, 2988, 2989, 19372, 19373]: # opt_custom

@@ -1876,11 +1888,13 @@ def _read_block_epb(self, block, size):

process_information = {}
for code, value in options.items():
if code in [0x8001, 0x8003]: # PCAPNG_EPB_PIB_INDEX, PCAPNG_EPB_E_PIB_INDEX
# PCAPNG_EPB_PIB_INDEX, PCAPNG_EPB_E_PIB_INDEX
Copy link
Member

Choose a reason for hiding this comment

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

Please revert changes from line 1891 to 1898 as they are not needed for your PR.

epb_flags_raw = options.get(2, None)
if epb_flags_raw:
if epb_flags_raw and isinstance(epb_flags_raw, bytes):
Copy link
Member

Choose a reason for hiding this comment

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

Is this change needed?

@guedou
Copy link
Member

guedou commented Aug 28, 2025

@bkayranci please keep comments at the same location as comment in the methods.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants