Why did NETCONF over SSH replace the ]]>]]> end-of-message delimiter with chunked framing, and when does a session use each?
answer
- a delimiter XML can contain
- attributes, comments, processing instructions
- length before data
- hello always old-style
- both peers must list it
basics
~20 sThe ]]>]]> delimiter assumed that sequence never occurs in well-formed XML, but it can, inside attributes, comments or processing instructions. Chunked framing length-prefixes each chunk instead. Hellos always end with ]]>]]>; chunked framing follows only when both hellos list :base:1.1.
solid answer
~40 sThe first SSH mapping, RFC 4742, ended every message with `]]>]]>`, on the assumption that the sequence cannot appear in well-formed XML. It can: in attribute values, comments and processing instructions. A message containing it is cut early, which RFC 6242 calls an operational problem and an opening for injection. RFC 6242 (which obsoletes RFC 4742) added **chunked framing**: each chunk is `\n#<size>\n` followed by exactly that many octets, and `\n##\n` ends the message, so the receiver counts bytes instead of scanning the content. For compatibility the `<hello>` is **always** followed by `]]>]]>`; after that, chunked framing is used only if **both** hellos advertise `:base:1.1`, otherwise end-of-message framing continues. A bad chunk header is a decoding error, and the peer must close the SSH channel. NETCONF over TLS (RFC 7589) adopts the same rules.
code
pseudocode · 14 lines// RFC 6242 Section 4.2: read one chunked message
message = empty
loop:
expect byte LF, then byte HASH // else decoding error
if next byte is HASH:
expect byte LF // end-of-chunks: LF HASH HASH LF
if message is empty: decoding error // at least one chunk required
return message
size = decimal digits read up to LF
if size is empty or starts with '0': decoding error
if size > 4294967295: decoding error
message = message + read exactly size octets
on decoding error:
close the SSH channel // MUST end the sessiongo deeper
Recall that NETCONF over SSH needs framing because SSH is a byte stream, and that there are two kinds: the ]]>]]> marker and length-prefixed chunks.
Explain why ]]>]]> broke, the chunk header format with its size limits, and the selection rule: hello always old-style, chunked only when both hellos list base:1.1.
Treat framing as a failure surface: a decoding error closes the channel, a peer that switches framing on one hello alone hangs or breaks the session, and TLS uses the same rules.
Note the compatibility pattern: keep the legacy delimiter only for the message that negotiates, then switch every later message to a self-describing format.
## What framing is for An SSH channel carries a **byte stream**, not separate messages. NETCONF sends whole XML documents (`<hello>`, `<rpc>`, `<rpc-reply>`, `<notification>`), so the transport must mark where one document ends and the next begins. That marking is **framing**, and RFC 6242 Section 4 defines two kinds for NETCONF over SSH. ## The problem with end-of-message framing **End-of-message (EOM) framing** puts the six characters `]]>]]>` after every message. The receiver scans the stream and hands everything before the marker to the XML parser. RFC 4742 chose it on the assumption that the sequence could not appear in well-formed XML. RFC 6242 Section 4.1 records that the assumption is false: the characters can legally appear in: - **attribute values**; - **comments**; - **processing instructions**. A message carrying the sequence in one of those places is split early: the receiver passes a truncated document to the parser and treats the rest as the start of the next message. RFC 6242's security section says this "can cause operational problems and open space for attacks if sent deliberately in RPC messages", while judging the threat not very high. ## The chunked format **Chunked framing** (RFC 6242 Section 4.2) puts a byte count in front of the data, so the content is never searched for a marker. | Part | Bytes on the wire | Rule | |---|---|---| | Chunk header | `\n#` + size + `\n` | size is decimal, **no leading zeros**, from 1 up to **4294967295** | | Chunk data | exactly *size* octets | any octet values; the transport does not interpret the XML | | End of message | `\n##\n` | follows one or more chunks | Here `\n` is a single line-feed byte (0x0A) and `#` is 0x23. A message is one or more chunks then the end marker; a sender may split a document anywhere, even mid-tag, because the receiver concatenates the chunk data before parsing. ## A worked encoding Take the 90-octet message `<rpc message-id="7" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><close-session/></rpc>` and send it as two chunks: 1. `\n#68\n` then the 68 octets `<rpc message-id="7" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">`. 2. `\n#22\n` then the 22 octets `<close-session/></rpc>`. 3. `\n##\n` to end the message. The receiver reads 68 + 22 = **90** octets of XML. The framing adds 5 + 5 + 4 = **14** octets; as one chunk it would add 5 + 4 = **9**, against **6** for `]]>]]>`. The overhead is trivial; what changes is that no content can end a message early. ## How a session picks its framing 1. Each peer sends its `<hello>` followed by `]]>]]>`. This is **mandatory** in every session, because neither side knows the other's version until it has read the other's hello. 2. Each peer reads the other's hello. 3. If **both** hellos advertise `:base:1.1`, chunked framing is used for **the remainder of the session**. 4. Otherwise EOM framing continues for the whole session. | Client hello lists | Server hello lists | Framing after the hellos | |---|---|---| | base:1.1 | base:1.1 | chunked | | base:1.0 and base:1.1 | base:1.0 and base:1.1 | chunked | | base:1.0 only | base:1.0 and base:1.1 | end-of-message | | base:1.1 | base:1.0 only | end-of-message | RFC 6241 requires current peers to advertise `base:1.1`, so EOM after the hello now matters mainly when talking to implementations of the original NETCONF (RFC 4741, obsoleted by RFC 6241). The choice is made once per session, never per message. ## What a decoder must do with bad input If a chunk-size is invalid, or anything else goes wrong while decoding, RFC 6242 says the peer **MUST terminate the NETCONF session by closing the SSH channel**, and implementations **MUST** guard against buffer overruns. There is no error reply: a peer that cannot find the message boundary cannot trust anything that follows. ## The same rules over TLS RFC 7589, NETCONF over TLS (it obsoletes RFC 5539), adopts RFC 6242's framing unchanged: the hello is followed by `]]>]]>`, and chunked framing follows when both peers advertise `:base:1.1`. ## Misreadings to avoid - **"One side offering 1.1 is enough."** Both hellos must list `:base:1.1`; otherwise the whole session keeps `]]>]]>`. - **"The hello is chunked in a 1.1 session."** The hello always ends with `]]>]]>`; chunking starts after it. - **"Chunks follow XML elements."** Chunk boundaries are arbitrary byte positions chosen by the sender. - **"A framing error gets an error reply."** It closes the channel; error replies need a message the receiver could delimit.
- Why must the hello still end with ]]>]]> in a session where both peers support base:1.1?Because a peer cannot know the other side supports chunked framing until it has read the other side's hello. Ending every hello with ]]>]]> lets an RFC 4742-era peer and a current one both find the end of the first message; only after both hellos are read does the session switch to chunked framing.
- Can a sender split a chunked NETCONF message in the middle of an XML tag?Yes. Chunk data is any sequence of octets, and the receiver concatenates every chunk before handing the document to the XML parser. RFC 6242's own example splits an rpc element between chunks. Chunk boundaries are transport detail with no XML meaning.
End-of-message framing is like a radio operator ending each message with the word STOP: it works until a message legitimately contains STOP, and the listener cuts it short. Chunked framing is like announcing "the next 68 words are message" before reading them: the listener counts, so nothing in the text can end the message early.
saying these in an interview costs you the question
- ]]>]]> cannot occur in well-formed XML, so end-of-message framing is safe.
- When both peers support base:1.1, the hello itself is sent chunked.
- One peer advertising base:1.1 is enough to switch the session to chunked framing.
- Chunk boundaries must line up with XML element boundaries.
- A bad chunk header earns a malformed-message rpc-error and the session continues.