Skip to content

nsh: dissect MD-Type 2 variable length context headers - #5096

Open
mmadersbacher wants to merge 1 commit into
secdev:masterfrom
mmadersbacher:nsh-mdtype2-context-headers
Open

nsh: dissect MD-Type 2 variable length context headers#5096
mmadersbacher wants to merge 1 commit into
secdev:masterfrom
mmadersbacher:nsh-mdtype2-context-headers

Conversation

@mmadersbacher

Copy link
Copy Markdown
Contributor

Any NSH MD-Type 2 packet carrying context headers fails to dissect:

>>> NSH(hex_bytes('0fc40203000001ff00010204deadbeef'))
TypeError: 'str' object is not callable

count_from was given the string 'length' instead of a callable, in NSH.vlch and in NSHTLV.metadata.

count_from is also the wrong parameter here. RFC 8300 section 2.2 defines the base header length as "the total length, in 4-byte words, of the NSH", not a count of context headers, and section 2.5.1 defines the TLV length as the metadata length in bytes, padded up to a word boundary. Both become length_from, and the base header length is computed with length_of instead of count_of. NSHTLV also needs extract_padding, otherwise the first TLV swallows the ones behind it.

After the change:

>>> p = NSH(hex_bytes('0fc60203000001ff00010204deadbeef00020104cafebabe'))
>>> len(p.vlch), p.vlch[1].class_, p.vlch[1].metadata
(2, 2, [3405691582])

MD-Type 1 is unaffected. The existing tests stay green because they only exercise the build path, and the one MD-Type 2 case among them carries no context headers.

Validated on Windows with Python 3.13. UTscapy -t test/contrib/nsh.uts -P "load_contrib('nsh')" gives 9 passed, 0 failed, with three cases added: one TLV, two TLVs, and a build check on the computed length. TLV lengths that are not a multiple of 4 dissect correctly when padded as the RFC requires. Malformed base header lengths and truncated context headers do not raise; truncated TLV metadata raises struct.error, same as other truncated layers in scapy. flake8 scapy/ and mypy_check.py (win32 and linux) are clean. The full windows.utsc campaign gives 96 failures, the same count and the same files as on master, all unrelated and caused by missing tcpdump, tshark and libpcap here.

The test vectors are hand-built from RFC 8300, not taken from a capture.

count_from was given the string 'length' instead of a callable, so any
MD-Type 2 packet carrying context headers raised "TypeError: 'str'
object is not callable" in PacketListField.getfield. Only MD-Type 1 and
the empty MD-Type 2 case worked, which is all the tests covered.

count_from is also the wrong parameter here. RFC 8300 section 2.2 makes
the base header length a count of 4-byte words, not of context headers,
and section 2.5.1 makes the TLV length a count of metadata bytes padded
up to a word boundary. Both are length_from now, and the length field is
computed with length_of instead of count_of.

NSHTLV also needs extract_padding, otherwise the first TLV swallows the
ones behind it.

AI-Assisted: yes (Claude Code)
@codecov

codecov Bot commented Aug 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.58%. Comparing base (1f87020) to head (be7c3c2).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5096      +/-   ##
==========================================
+ Coverage   79.42%   80.58%   +1.15%     
==========================================
  Files         372      390      +18     
  Lines       96507    96860     +353     
==========================================
+ Hits        76652    78053    +1401     
+ Misses      19855    18807    -1048     
Files with missing lines Coverage Δ
scapy/contrib/nsh.py 96.15% <100.00%> (+0.32%) ⬆️

... and 304 files with indirect coverage changes

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

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.

2 participants