Skip to content

P11: split KILL (D) path into its own parameter and cap it so a long path can't truncate the reason #121

Description

@MrIron-no

Proposal

In the P11 protocol revision, change the server-to-server KILL (D)
syntax so the kill path is its own parameter and the trailing parameter
carries only the reason, and cap the path length so it can no longer
squeeze the reason out of the line.

  • Today: … D <victim> :<path> <reason> — one trailing parameter,
    split on the first space.
  • Proposed (P11): … D <victim> <path> :<reason> — path as a middle
    parameter, reason as a clean trailing, with a bounded path.

The problem

The server relay packs path and reason into a single trailing parameter
separated by the first space (m_kill.c:135):

sendcmdto_serv_butone(sptr, CMD_KILL, cptr, "%C :%s!%s %s",
                      victim, inpath, path, msg);

The receiver reconstructs the two halves positionally
(m_kill.c:194-197):

if (!(msg = strchr(path, ' ')))   /* everything after first space = reason */
  msg = "(No reason supplied)";
else
  *(msg++) = '\0';                /* everything before it = path */

The path grows on every hop — each relaying server prepends its own name
via inpath. Two consequences follow:

  1. The reason is last in the buffer, so it is what gets truncated.
    The whole trailing parameter is bounded by BUFSIZE (512). As the
    accumulated path lengthens across hops (server names up to
    HOSTLEN, and longer still after HIS rewriting), it consumes the
    line from the front and the reason at the tail is clipped — on a wide
    network it can be lost entirely.
  2. The split is positional and fragile. It relies on the path
    containing no spaces (true today only because server names and nicks
    have none) and on the reason being "whatever is left". It is
    parse-by-convention, not by protocol structure.

Why the proposed shape fixes it

  • The reason becomes unclippable by the path. It is its own trailing
    token; capping the path to a fixed budget (e.g. a KILLPATHLEN) makes
    a runaway path truncate itself instead of the reason. This inverts
    today's failure mode.
  • The parse becomes structural. No more split-on-first-space; path
    and reason arrive as distinct parv[] entries, and the reason may
    contain any spaces freely (it already does).
  • Moving the path to a middle parameter is safe. Middle parameters
    cannot contain spaces, but the path (s1!s2!nick) never does.

Wrinkles to plan for

  • Per-link formatting during relay is the real cost. KILL
    propagates across links that may be mixed P10/P11.
    sendcmdto_serv_butone broadcasts one format string to all server
    links, so the relay must emit the P10 combined form to
    Protocol() < 11 links and the P11 split form to Protocol() >= 11
    links — two passes or a per-target format. Same protocol-gating
    discipline feat/p11 already uses (29794e4), applied at a fan-out point.
  • Truncation direction. The path accumulates newest-hop-first
    (inpath prepended). Decide what to keep when capping — likely the
    originating end plus nearest hops, trimming the middle — and whether
    to mark a truncated path (e.g. a trailing marker) so a reader knows it
    is incomplete. The path is informational only (oper snotices at
    m_kill.c:121, kill logging at :125), so lossiness is acceptable.
  • Worth deciding: keep the path at all? With HIS and
    FEAT_HIS_KILLWHO already rewriting or hiding the who/path shown to
    users, the accumulated path is mostly an oper-debugging trace for kill
    loops. A more aggressive option is to drop it and send only the
    originating server plus the reason. The "separate and truncate"
    proposal is the conservative choice that preserves the trace; that is
    the recommended default unless the path is considered vestigial.

Tests

Following the S2S remote-observer convention (assert on the receiving
leaf, not just locally):

  1. Relay a KILL through enough hops to overflow the old combined
    trailing parameter; assert the reason arrives intact on the far side
    (the regression test for the reason-loss bug).
  2. Mixed P10/P11 relay: assert a Protocol() < 11 link receives the
    combined :<path> <reason> form and a >= 11 link receives the split
    <path> :<reason> form.
  3. Path-cap: relay a KILL whose path exceeds the cap; assert the path
    is truncated and the reason is untouched.

Relationship to other P11 work

Companion to the other P11 protocol changes: #114 (mandatory MODE
timestamp), #116 (burst ban setter/timestamp), #118 (deprecating P9),
and #120 (per-member delayed-join state in BURST). Happy to prototype
the relay change on a branch if there's agreement.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions