You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(l2tp): the Type enum is inverted against RFC 2661, and make() omits L on control messages #1175
Describe the bug
The L2TP Type enum is inverted against RFC 2661 §3.1, which says the T bit "is set to 0 for a data message and 1 for a control message". On main:
pcapkit/vendor/l2tp/type.py has DATA = {0: 'Control', 1: 'Data'}, and the generated pcapkit/const/l2tp/type.py:23-25 follows it (Control = 0, Data = 1). Regenerating would not fix it.
So the control ZLB ACK c802… (T=1) parses as type=Data, and L2TPv2.make()'s default Enum_Type.Data writes T=1, which is a control header on the wire.
Smaller related gaps in L2TPv2.make():
It emits L=0 for a control message when no total_length is given. §3.1 says L MUST be 1 for control messages.
It writes total_length as given, without checking it against the real size.
A non-zero offset pad is zeroed on rebuild (…0003010203… → …0003000000…). §3.1 calls the pad contents undefined, so this is low severity.
Expected behavior Type.Data == 0 and Type.Control == 1. make() sets L for control messages, and a parse round-trips byte-exactly.
Additional context
Found by the #1174 worker and confirmed by its cross-review. I re-read the vendor mapping myself. Correcting the enum changes public Enum_Type values, so it is breaking. It edits l2tpv2.py, which #1174 also edits, so this waits for #1174.
Two design points on #1183 need your call. Neither blocks the merge.
The new make(length_flag=...) keyword. Without it, a captured control message without L gains a Length field on from_data and no longer round-trips; 6 round-trip cases fail. It defaults to None, so existing callers are unchanged, and the review found no way to carry this that adds no keyword. The alternative is to normalise captured L=0 control messages to L=1, which is RFC-correct but drops byte-exactness. Keep the keyword, or normalise?
info.padding shows in to_dict(). It is None without O and b'' at offset 0, so every parsed L2TPv2 packet's json/tree/plist output gains the key. That matches how offset, ns and nr already show None. Keep it visible, or hide it?
I recommend keeping both: byte-exact rebuilds are the project's rule, and padding follows the existing optional-field pattern.
Ruling recorded: both recommendations accepted. #1183 keeps the make(length_flag=...) keyword so captured L=0 control messages stay byte-exact, and keeps info.padding visible in to_dict(), matching offset/ns/nr.
#1183 at 53f2d0fc1 already implements both, so no further change is needed. needs: decision removed; this stays wip until #1183 merges.
Activity
JarryShaw commentedon Oct 7, 2026
Blocked until #1174 merges, because both edit
pcapkit/protocols/link/l2tpv2.py.JarryShaw commentedon Oct 7, 2026
Unblocked: #1174 merged at 04:00Z. Accepted and unstarted, so this is now
pending.JarryShaw commentedon Oct 7, 2026
A worker is on it now.
JarryShaw commentedon Oct 7, 2026
Two design points on #1183 need your call. Neither blocks the merge.
make(length_flag=...)keyword. Without it, a captured control message without L gains a Length field onfrom_dataand no longer round-trips; 6 round-trip cases fail. It defaults toNone, so existing callers are unchanged, and the review found no way to carry this that adds no keyword. The alternative is to normalise captured L=0 control messages to L=1, which is RFC-correct but drops byte-exactness. Keep the keyword, or normalise?info.paddingshows into_dict(). It isNonewithout O andb''at offset 0, so every parsed L2TPv2 packet's json/tree/plist output gains the key. That matches howoffset,nsandnralready showNone. Keep it visible, or hide it?I recommend keeping both: byte-exact rebuilds are the project's rule, and
paddingfollows the existing optional-field pattern.JarryShaw commentedon Oct 7, 2026
Good take your recommendations
JarryShaw commentedon Oct 7, 2026
Ruling recorded: both recommendations accepted. #1183 keeps the
make(length_flag=...)keyword so captured L=0 control messages stay byte-exact, and keepsinfo.paddingvisible into_dict(), matchingoffset/ns/nr.#1183 at
53f2d0fc1already implements both, so no further change is needed.needs: decisionremoved; this stayswipuntil #1183 merges.fix(l2tpv2): correct the Type enum and L bit against RFC 2661 (#1175) (…