Subtype 0x17 — both machines REJECT our reachability announce¶
Date: 2026-08-07
Captured: DOC/captures/XROUT-SERVICES-2026-08-07/d103-asks-us.pcapng and d103-asks-us.log
How: relay node 19999 between D100 and D103, announcing on both links as each reached Active.
The bytes¶
Both machines answer our announce with the same 14-byte frame — header only, no body:
from D100: 21 FE 00 17 4E 1F 00 64 FF FF FF FD 8F 69
from D103: 21 FE 00 17 4E 1F 00 67 FF FF FF FD 8F 66
Field by field, against the 7-word header:
| Word | Bytes | Meaning |
|---|---|---|
| 0 | 21 FE |
Marker 1 = 0x21 as always; Marker 2 = 0xFE, which is neither 0x13 normal nor 0x12 relayed |
| 1 | 00 17 |
packet type 0, subtype 0x17 = 23 |
| 2 | 4E 1F |
destination 19999 — us |
| 3 | 00 64 / 00 67 |
source 100 / 103 |
| 4 | FF FF |
Flags 1 — the broadcast/out-of-sequence marker, same as a reachability request |
| 5 | FF FD |
Flags 2 = 0xFFFD = −3 |
| 6 | 8F 69 / 8F 66 |
header checksum |
What it means¶
−3 is XENIR, which our enum documents from the official ND include as "Network layer
initialization reject (purely internal)".
So this is exactly what it says: the peer is REJECTING our network-layer initialisation. Both machines do it, independently, in reply to the reachability announce this node sends when a link comes up.
That explains the symptom that led here. LIST-ROUTING-INFO on D103 reports:
19999 L: *->19999
T: *, but no access to system 19999
A: *, but no route to system 19999
The local table has the route we asked for, but there is no access — because initialisation was refused. Access is not missing through misconfiguration; it is being actively declined.
What is NEW here¶
- Subtype
0x17is not inSintranPacketSubtype. Known members are0x03Ack,0x07NetworkError,0x0A/0x0Cfragments,0x0EData,0x13ReachabilityReply,0x19ReachabilityRequest. 23 has never been seen in this project. - Marker 2 =
0xFEon this frame type. Every frame in the capture corpus carries0x13or0x12. What0xFEsignifies is UNKNOWN — do not assume it is a third "kind of hop" without evidence. - An error code travels in Flags 2.
SintranPacketSubtype.NetworkError(0x07) already carries a negativeXE*code in Flags 2, so the shape is consistent with that;0x17is a second, distinct subtype doing the same thing for initialisation specifically.
What we do about it today: NOTHING, and that is the bug¶
Our relay logs *** NO REPLY BUILT *** for these frames. That label is misleading here — a reject
is a RESPONSE, not a request, so there is nothing to answer. The real fault is that we do not
RECOGNISE it: the announce is refused, we carry on as though it succeeded, and the operator sees
"no access" with nothing in our logs explaining why.
Why the reject happens is NOT established. Candidates, none verified: - our announce is malformed in a way these machines refuse, - initialisation requires something we do not send first, - or the peer refuses because it already holds state for 19999 from an earlier run.
The third is worth trying first, since it is cheap: restart XMSG on a peer and announce into a clean state. Guessing at the other two would mean inventing protocol, which is what this project has been burned by.
Root-cause work, 2026-08-07¶
Step 1 - our announce is byte-for-byte the right shape. RULED OUT.¶
Pulled our own frame out of the capture and set it beside the real exchange documented in
XMSG-PROTOCOL.md:
real 2113 0019 dst=0066 src=0064 f1=FFFF f2=0001 ck=DE08 -> answered with 0x13 reply
ours 2113 0019 dst=0064 src=4E1F f1=FFFF f2=0001 ck=904F -> answered with 0x17 reject
Marker, subtype, Flags 1 and Flags 2 all identical. The only difference is the node number, and the
checksum difference follows from it (the 0x4E00 high-byte shift that the word-6 correction
already documents). Our frame is not malformed.
Step 2 - the node number is NOT the cause. RULED OUT.¶
19999 is outside even the 9800-9999 virtual range that XMSG-COMMAND refuses outright, so it was the strongest candidate. Re-ran the whole relay announcing as 101, an ordinary small number D103 already knows. Both machines rejected it identically:
103->101 21FE 0017 0065 0067 FFFF FFFD DD20
100->101 21FE 0017 0065 0064 FFFF FFFD DD23
A clean negative result: identity is irrelevant. It also confirms the checksum high byte was purely
a node-number artifact - as 101 we produce DD2x, adjacent to real traffic's DE0x.
What this leaves: the frame is right and the identity is irrelevant, so the cause is STATE or SEQUENCE - the conditions under which a peer will accept an initialisation at all.
Step 3 - the carve. Groundwork done, condition not yet named.¶
XENIR=177775octal confirmed inXMSG-SYMBOL-L03.SYMB(=0xFFFD= -3).- Kernel flattened to
DOC/COSMOS-RE/carve/XMSG-KERNEL-L03_flat.binwithbpun2raw.py XMSG-KERNEL-L03.BPUN <out> --at 131055. 23552 words, span120000..175777octal, which matches what the loader places (NOT the 23833 nd100-dis reports on the raw BPUN). - Base
0120000is verified: disassembling at file word 9347 prints address142203, exactly where the symbol table putsXHINI. - Scanning for the literal
0x21FEor0x0017finds NOTHING. The kernel assembles that header from parts rather than a template, which is why constant scans are useless here - navigate by SYMBOL. - The symbol file has 412 symbols inside the code range, including 30
XH*receive handlers. The relevant cluster:
XHLNK 140566 XHRES 142136 XHSUP 142142 XHSCL 142160 XHCLR 142162
XHINI 142203 XHCHK 142241 XHRRS 142337 XHTRS 142401
XHINI is an initialisation routine - it clears a block of fields - and it carries a GUARD:
142213 LDA -64
142214 JAZ 3 -> 142217
142215 LDA -74
142216 SKP IF DA EQL 0
142217 JMP 2 -> 142221 continue initialising
142220 JMP I -57 -> 142141 bail out
Two conditions are tested and failure jumps to 142141, just before XHSUP. That is the
candidate reject path. What the two tested words at -64 and -74 (B-relative) actually hold is
NOT established - naming them is the next step and needs the surrounding routine read properly,
not guessed.
Step 3b - the carve does NOT corroborate "this is XENIR". Downgrade the claim.¶
Searched BOTH halves of the system for the values this frame would need if a program built it:
| Looking for | XMSG kernel | XROUT |
|---|---|---|
SAA -3 (set A to -3, the XENIR value) |
0 | 0 |
literal word 177775 (-3) |
0 | 0 |
0x21FE (the frame's marker pair) |
0 | 0 |
0x0017 (the subtype word) |
0 | 0 |
XMSG-XROUT-L03.BPUN flattens to 39943 words spanning 0..116006 octal. Neither it nor the
23552-word kernel contains any of the four.
So the identification "Flags 2 = 0xFFFD = -3 = XENIR" is INFERENCE that the carve fails to
support. It rested on name-matching: a negative value in Flags 2, and XENIR = -3 in the include
with a description ("network layer initialization reject") that fits the symptom. That is suggestive,
not evidence, and this is exactly the trap the project already recorded as
"value scans are noise" - a number matching a constant is not proof the constant is what produced it.
Three readings remain open, and NOTHING here distinguishes them:
- It IS XENIR, but assembled arithmetically rather than from a literal - plausible, since the markers and subtype are not literals in either binary either.
- Flags 2 on subtype
0x17is not an error code at all. On a reachability frame Flags 2 is0x0001;0xFFFDmight be a count, a hop value or a sequence delta rather than a status. - The frame is not XMSG's at all. Marker 2
0xFEappears nowhere in the corpus, and the SINTRAN HDLC driver (MP-P2-HDLC-DRIV.NPL) is a third party on that link that neither binary covers.
Do not build code on the XENIR reading. Adding 0x17 to the subtype enum is still right - those
bytes were captured. Labelling it "initialization reject" in the code is not yet earned.
Step 4 - THE MACHINE NAMES IT. Subtype 0x17 is INNAK.¶
LIST-FRAMES on D100, run while the relay was live, prints a Nettype column giving SINTRAN's
own name for every frame in its tables:
Addr. Link HAC Status To From Refno Nettype Cnt1 Buff1 Cnt2 Buff2
163214 0 410I 0 19999 100 65535 INNAK 0 1201061 0 1247221
164600 152164 400I 0 100 19999 65535 INIT 0 1231654 0 1231654
164512 152164 400I 0 100 101 65535 INIT 4 1230472 0 1230472
163247 0 476I 0 103 100 21 ACK 0 1201040 0 1246001
163335 0 477I 0 103 100 23 * <-> 14 1201061 8 1246001
Read by direction:
To 100, From 19999andTo 100, From 101are OUR announces, from this run and the earlier node-101 run. SINTRAN calls themINIT.To 19999, From 100is the0x17frame coming back. SINTRAN calls itINNAK.
So our reachability announce IS an initialisation in SINTRAN's vocabulary, and subtype 0x17 is an
initialisation NEGATIVE ACKNOWLEDGEMENT. Refno 65535 is 0xFFFF, matching Flags 1 on both.
This restores the substance of the reading that step 3b downgraded - but on far better evidence. Step 3b was right to reject name-matching against a constant absent from both binaries; the machine labelling its own traffic is a different and much stronger kind of witness. Both steps stand: the inference was not earned when it was made, and it is earned now.
Also captured, and previously unknown: the Nettype vocabulary itself. Seen so far - INIT,
INNAK, ACK, and * <-> (an established two-way conversation). That is SINTRAN's own
classification of link traffic and nothing in this project modelled it.
Still open: WHY the NAK. Knowing it is a refused initialisation does not say what the peer
objects to. But the question is now sharply framed - "what makes a SINTRAN INIT acceptable?" - and
LIST-FRAMES gives a way to watch every attempt.
Step 5 - real ACCEPTED INITs found in the corpus, and what they have that ours does not¶
device-online-100-102-103.pcapng contains the only INIT exchanges in the whole capture corpus,
and both are ACCEPTED:
frame 2997 19 (INIT) 100 -> 102 F1=FFFF F2=0001 LAPB I N(S)=0 N(R)=0 "ROUTING"
frame 2999 13 (reply) 102 -> 100 F1=FFFF F2=0001 LAPB I N(S)=0 N(R)=1
frame 3030 19 (INIT) 100 -> 103 F1=FFFF F2=0001
frame 3037 13 (reply) 103 -> 100 F1=FFFF F2=0001
No 0x17 anywhere in that capture. Flags 1 and Flags 2 are identical to ours, which closes off the
frame contents for a second time - see step 1.
Two things the accepted INITs show that we did not have:
1. The INIT is the FIRST I-frame on the link. N(S)=0, N(R)=0. Ours is also sent immediately on
link Active, so this may match - but it is worth confirming our N(S) really is 0 rather than assumed.
2. Every INIT in the corpus is sent BY D100, to 102 and to 103 - both machines D100 already has configured as link peers. There is no example anywhere of a machine accepting an INIT from a system it did not already know as a LINK peer.
That sharpens the hypothesis to something testable:
A peer accepts an INIT from a system it has defined as a LINK peer. A ROUTE is not enough.
DEFINE-SYSTEM-ROUTE gave D100 and D103 a route to 19999 - and the route is visibly present in
LIST-ROUTING-INFO - but a route says "to reach X, go this way", not "X is the machine on the other
end of this line". The frames immediately before the accepted INIT are on a different TCP stream
(an operator typing at a console), so that INIT was triggered by a COMMAND, most likely a link
start - which is exactly the step our setup never performed on the peer's side.
Not proven. It fits every observation so far and contradicts none, but the corpus contains no counter-example either way, and the test - defining or starting a link toward 19999 on D100 - changes a real machine's configuration and has not been run.
Step 6 - the LAPB layer matches too. The wire is fully exonerated.¶
Step 5 flagged N(S)=0 as ASSUMED for our own INIT. Checked it, from the capture already on disk,
by reading the LAPB address and control bytes in front of each datagram:
ours 7E 09 00 2113 0019 ... control 00 -> I-frame, N(S)=0, N(R)=0
theirs 7E 09 20 21FE 0017 ... control 20 -> I-frame, N(S)=0, N(R)=1
Against the known-good accepted exchange in device-online-100-102-103.pcapng:
| real (accepted) | ours (NAKed) | |
|---|---|---|
| initiator's frame | I N(S)=0 N(R)=0 |
I N(S)=0 N(R)=0 |
| responder's frame | I N(S)=0 N(R)=1 |
I N(S)=0 N(R)=1 |
| responder's subtype | 0x13 reply |
0x17 INNAK |
Identical at every layer that can be observed. The assumption held.
Where that leaves the investigation¶
Everything checkable on the wire is now eliminated:
- the datagram's markers, subtype, Flags 1 and Flags 2 - identical to an accepted INIT (step 1).
- the node number - re-ran as 101, NAKed the same (step 2).
- the LAPB address, control byte and sequence numbers - identical (step 6).
- the frame is not built from constants in either binary, so there is nothing more to carve for it (step 3b).
The peers answer at exactly the right moment, in the right LAPB position, to a frame that matches a known-good one byte for byte - and refuse it. The remaining variable is not on the wire at all: it is what the peer knows about us before the INIT arrives.
That is the link-peer hypothesis from step 5, now the only survivor rather than merely the best fit. Testing it means defining or starting a link toward our system on D100, which changes a real machine's configuration - deliberately left for Ronny rather than done unattended.
Step 7 (2026-08-08) - the manual says our routes are BACKWARDS, and there is no LINK command¶
Read AFTER the reboot, from a manual that has been in the repo the whole time:
Operations/Cosmos/ND-30.025.02 COSMOS Operator Guide.md, section 2.5.4 "Defining the Route to the
Remote Systems":
"When defining the route to remote systems, it is not necessary to define the route to the adjacent system(s). By adjacent system we mean the system to which the local system has a direct link. In other words, the system that is physically connected to the local system with an HDLC or Megalink cable."
Section 2.5 gives the whole start-up sequence, and it has FOUR steps, not one:
SET-PRIVILEGED
DEFINE-LOCAL-SYSTEM,999 <- optional; XMSG does it at init in this version
DEFINE-REMOTE-NAME,,MAIN,999 <- a NAME for every system, adjacent or not
DEFINE-REMOTE-NAME,,FORMAT,998
DEFINE-REMOTE-NAME,,BATCH,997
DEFINE-REMOTE-NAME,,TEST,996
DEFINE-SYSTEM-ROUTE,,BATCH,FORMAT <- ONLY for the NON-adjacent ones
DEFINE-SYSTEM-ROUTE,,TEST,FORMAT
START-LINK,1360,,,-1,,
In that example FORMAT is the adjacent machine and gets no route at all. Only BATCH and TEST, which sit behind FORMAT, get one.
Two corrections to this document's own step 5.
-
There is no
DEFINE-LINK/DEFINE-SYSTEM-LINKcommand. A grep forDEFINE-[A-Z-]*LINKacrossOperations/Cosmosand the 210373L manual returns nothing. The step-5 phrase "defined as a LINK peer" named a thing that does not exist. What does exist isDEFINE-REMOTE-NAME(identity),DEFINE-SYSTEM-ROUTE(path, non-adjacent only) andSTART-LINK(the physical line). -
Our routes are pointed the wrong way. The topology is
D100 <-> 19999 <-> D103, so 19999 is ADJACENT to both peers. What was configured:Machine Configured What 2.5.4 requires D100 DEFINE-SYSTEM-ROUTE,,D19999 D103none for 19999 (adjacent); DEFINE-SYSTEM-ROUTE,,D103 D19999for the far oneD103 DEFINE-SYSTEM-ROUTE,,D19999 D100none for 19999 (adjacent); DEFINE-SYSTEM-ROUTE,,D100 D19999for the far oneD100 was told "to reach 19999, go via D103" while D103 is only reachable through 19999. That is a loop, and it contradicts the cable D100 can see for itself. A machine holding that route has been told, in its own terms, that 19999 is NOT on the other end of this line - which is precisely the state step 5 concluded produces the NAK.
Also unmodelled here: DEFINE-REMOTE-NAME,,<name>,<number> must exist for every system. Nothing
in the session notes shows 19999 was ever NAMED on D100 or D103, only routed. And section 2.5.5 says
LIST-ROUTING answered with all CRs initialises the network - that is the deliberate operator
trigger for the INIT exchange, which explains step 5's observation that the accepted INIT in the
corpus followed console typing on a separate TCP stream.
Still not proven - it has not been run. But it replaces "define a link (command unknown)" with a concrete, manual-backed sequence, and it explains the NAK without needing anything new on the wire.
The lesson is [[grep-reference-manuals-first]] again: this was in an operator guide already in the repo, while the investigation went to the binaries.
Step 8 (2026-08-08) - RAN IT. D103 now reaches us. INNAK is NOT fatal.¶
A Windows reboot had wiped both machines' XMSG kernel tables (system table down to the local entry,
zero links), so the step 7 sequence was built from scratch rather than unpicked. The XROUT NAME
table SURVIVED while the XMSG kernel tables did not - D100, D102, D103 were still named on
both machines; only D19999 was missing. Two separate stores, worth knowing before a rebuild.
Applied on D100: DEFINE-REMOTE-NAME,,D19999,19999, DEFINE-SYSTEM-ROUTE,,D103,D19999, no route
to 19999, START-LINK LU 1360 with max attempts -1. Mirrored on D103 with
DEFINE-SYSTEM-ROUTE,,D100,D19999.
Result - D103's LIST-ROUTING-INFO, which yesterday said "not accessible":
19999 L: *->19999
T: *->19999
A: *->19999 <- ACTUAL path. It works.
100 L: *->19999->100
T: *->19999, but no access to system 100
A: *->19999->, but no access to system 100
D103 reaches us. It then sent a real ReachabilityRequest (answered), and real Data datagrams
addressed to node 100 - so it is actively trying to route THROUGH us. The INNAK still arrives and
is still unanswered by our node, and it did not stop any of that. So INNAK is not a rejection of
our identity: reachability, naming and routing all completed alongside it. What the frame does mean
is still unproven; what is now settled is that it is not the blocker it was assumed to be.
The remaining failure is one leg only:
[link] hdlc-out:127.0.0.1:10362 SendData refused: link not Active (status Starting)
[relay] DROPPED from hdlc-in:10366 for node 100: outgoing link refused the datagram
Why the D100 leg cannot come up - a wiring fact, not a protocol fault¶
D100's RetroCore.ini has TWO controllers: HDLC 1 --listen=10362 and HDLC 2 --listen=10364.
Its SINTRAN knows exactly ONE link LU: START-LINK,1364 is refused with "Illegal/Reserved Logical
Unit Number (LUN) for link", so LU 1360 is the only one. Socket state shows who owns it:
127.0.0.1:10362 <- 127.0.0.1:6899 pid 33188 = D102 (F:\RC\RonnyTest\HDLC2)
127.0.0.1:10362 <- 127.0.0.1:6140 pid 36900 = our relay
D102 already holds D100's HDLC 1 line. LU 1360 is the D100<->D102 wire; our relay is a second
client on the same listening socket and is ignored. That is why D100 sits in state Call
transmitting SABM with TXData/Retry/RXBad = 0/0/0 - it is not receiving from us at all, and our
LAPB is not at fault (it answers a SABM with UA in any state, LapbLayer.cs:486).
Yesterday's relay reached D100 on 10364; today nothing is listening for a link there because SINTRAN has no LU for HDLC 2. Whether that changed at the reboot or was always luck is UNVERIFIED.
So the D100 leg needs a wiring decision, not more protocol work: free LU 1360 for us, or give D100's SINTRAN a second HDLC link. Left for Ronny - it stops or rewires a running machine.
Step 9 (2026-08-08) - the D100 line WORKS now. Both peers reach us. One bug left.¶
D100's RetroCore.ini was edited to SWAP the two HDLC listen ports, so controller 1 - the only one
LU 1360 can use - sits on 10364 where only our relay dials, instead of 10362 where D102 dials.
Original lines are kept commented directly above; restore them to give D102 its line back. Backup:
F:\RC\RonnyTest\HDLC1\RetroCore.ini.bak-2026-08-08. D100 was restarted and reconfigured.
The outbound link came up on the first attempt, for the first time ever:
[relay] outbound link Starting -> Active (LAPB connected)
[relay] announcing to outbound peer 100
and D100's own LIST-LINKS agreed, having learned who we are:
No Addr. State Sysid Rcv Xmit Lun Timeout Soft-stat-hard TXData/Retry/RXBad
1 152164 Run 19999 41RR 410I 1360 10/Off 0 0 6/4/10
State Run, Sysid 19999. D100's LIST-ROUTING-INFO then answered 19999 A: *->19999. Both
machines now reach our node. Note SET-PRIVILEGED is "Command not recognised" in this build -
the privileged warning is emitted automatically on the first privileged command instead.
The bug this exposed: we advertised a route that loops¶
D100's first path query for 103 came back:
103 L: *->19999->103
T: *->19999->100->19999->100->19999->100->... *Loop suspected*
A: *->19999->100->19999->100->19999->100->... *Loop suspected*
D100's own local table (L:) is right. The looping paths are built from what WE advertised, and we
advertised via [100] for node 103 because topology-d19999.json still describes the OLD Ethernet
arrangement where D103 sat behind D100. Forwarding was never wrong - the runner logs
inbound link on 10366 reaches [103], outbound to 127.0.0.1:10364 reaches [100]. Only the
advertisement was.
Fix committed: SRC/Xmsg.Live.Runner/topology-d19999-relay.json, where both peers are
"reach": "neighbour" with no via, because both are ADJACENT to us - the same section 2.5.4 rule
that fixed the ND side. topology-d19999.json must NOT be used for a relay run.
Where it stopped¶
With the corrected topology both links went Active immediately and both peers were announced to.
Then D100's XMSG degraded: LIST-ROUTING-INFO began repeating the same system block over and over,
reported no route to system 19999 for a route that had just worked, and ended with
Buffer handling error - internal to Command prog. A DEFINE-SYSTEM-ROUTE re-applied cleanly
(Ok) without restoring it.
UNVERIFIED which of these caused it - the repeated querying, the unanswered INNAKs, or the
RXBad 10 on the link. Nothing more was poked; the relay was stopped and D100 left alone. D100
most likely needs STOP-XMSG / START-XMSG and the section 2.5 sequence re-run before the next
attempt.
The one code change this points at: our node answers an INNAK with
*** NO REPLY BUILT *** (this hangs the caller). Both peers send one on every announce and we have
never replied to any of them. That is the most likely thing to fix before the next live run.
Step 10 (2026-08-08) - D100 recovered cleanly; D103's HDLC is stuck TALKING TO ITSELF¶
D100's degraded XMSG from step 9 recovered exactly as the manual says it should:
SINTRAN-SERVICE / STOP-XMSG / START-XMSG, both answering OK. The restart clears the whole
name table - LIST-NAMES afterwards showed only *XM-FIDO, which had re-registered itself, with
even the machine's OWN name gone. So a restart means re-running the entire section 2.5 sequence,
including DEFINE-REMOTE-NAME,,D100,100 for the local name. Both machines were then rebuilt
symmetrically and both accepted every command.
The new blocker is a TCP artefact, not XMSG. D103's RetroCore.ini says
device add HDLC 1 --connect=localhost:10366. When the relay holding that listener is killed, D103
re-dials - and with the listener gone it can complete a TCP simultaneous open against itself:
LocalPort RemotePort State OwningProcess
10366 10366 Established 27996 <- D103 connected to D103
10366 0 Listen 41916 <- our relay, listening, never dialled
D103's own LIST-LINKS proves what that means:
No Addr. State Sysid Rcv Xmit Lun Timeout Soft-stat-hard TXData/Retry/RXBad
1 152164 Run 103 40RR 40RR 1360 10/Off 0 0 0/0/0
Sysid 103 on D103's own link - it brought LAPB up against itself and learned its own system
number as the peer. That is impossible in a real topology, so the field is a reliable detector for
this state. State Run looks healthy, which is exactly why it is worth writing down: everything
reads normal except the one field that gives it away.
Clearing it needs D103's RetroCore process restarted, and D103 is NOT covered by the D100/D102 restart permission, so it was left alone.
Operational rule this earns: start the relay's listener BEFORE the peer that dials it, and when
stopping a relay expect the dialling machine to need a restart afterwards. Check
LIST-LINKS's Sysid against the peer's real number before trusting a Run state.
Next steps, in order¶
-
(2026-08-08) DONE - the section 2.5 sequence was run on both peers; D103 reaches 19999. See step 8. What remains is the D100 wiring decision above, plus deciding what our node should ANSWER an INNAK with (today:
*** NO REPLY BUILT ***). -
Add
0x17toSintranPacketSubtypewith these captured bytes as the evidence — but name it for what was OBSERVED (a header-only frame both peers send in reply to a reachability request), NOT "initialization reject", which step 3b shows is unearned. - Recognise it on receive and report the raw fact — "peer answered our announce with subtype 0x17, Flags 2 = 0xFFFD" — rather than the current silence. That is useful without claiming a meaning.
- To settle what it IS, the next artifact is the SINTRAN HDLC driver, not XMSG:
MP-P2-HDLC-DRIV.NPLis the third party on that link and neither binary searched here covers it. Marker 20xFEappearing nowhere in the XMSG corpus points the same way. - Independently, ask a real machine:
LIST-FRAMESon D100 with tracing enabled shows how SINTRAN itself labels these frames. That is cheaper than any carve and the machine is authoritative about its own traffic.