Skip to main content
Version: 2.0.0 🚧

Server protocol

note

This is a work-in-progress, as such it is largely incomplete.

Introduction#

This specification describes the P10 protocol as implemented by ircd-yeti, which includes various extensions.

It is based on:

  • "Undernet P10 Protocol and Interface Specification",
  • Raw data sent by ircd-yeti, and
  • The ircd-yeti source code

Concepts#

This specification assumes that the reader is already familiar with the concepts inherent in Internet Relay Chat (IRC).

P10 Base64#

The P10 protocol uses a Base64 encoding for "numerics" (discussed below), and the IP address parameter of the NICK message, to maintain human readable data flow while reducing the size of messages. The P10 Base64 character set is included here, which defines all valid characters allowed in a P10 Base64 string, with "A" representing 0 and "]" representing 63.

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789[]

Whenever this specification refers to "Base64" it is referring to "P10 Base64" as defined here, unless otherwise specified.

Numerics#

The P10 protocol uses a scheme of "numerics" to uniquely identify a client (both users and servers) within a network. Each server is assigned its own unique numeric (0 -> 4095), and each user has its own unique numeric within that server (0 -> 262,143). These numerics are encoded into a Base64 string.

Server numerics consist of two characters, with the minimum 0 being represented as "AA", and the maximum 4095 being represented as "]]". User numerics are three characters, with the minimum 0 being represented as "AAA", and the maximum 262,143 being represented as "]]]". The unique identifer for a user on the network consists of the server and user numerics concatenated together in the format SSUUU.

For example, consider the server "irc.example.com" which has been assigned the numeric 10, represented as "AK" in Base64. On this server exists the user "John", which has been allocatted the numeric 63, represented as "AA]" in Base64. The unique identifier, i.e. numeric, for this user within the network would be "AKAA]". From this we can determine which server a message came from, as well as the client who sent it.

Numerics are used to prefix every message issued on the stream, except for the initial PASS and SERVER messages, which are not prefixed.

Tokens#

Message identifiers, also known as commands, have both long and short forms of their name. The short form is known as a "token", and it is what is used in the server<>server protocol. The original aim of tokenization was to reduce the bandwidth used during network communication by reducing the length of common message identifiers. Today, this isn't nearly as important, although use of an identifier's token form has stuck.

When this specification refers to a message identifier, aka command, (e.g. BURST message) in the context of the server<>server protocol, it implies the token form of the identifier unless specifically stated otherwise.

Below is a list of message identifiers used in the server<>server protocol:

Message (command)Token
ACCEPTAP
ACCOUNTAC
ADMINAD
ASLLLL
AWAYA
BURSTB
CERTFPCF
CFEATCT
CHECKCC
CLEARMODECM
CLOAKCK
CLOSECLOSE
CONNECTCO
CPRIVMSGCP
CREATEC
DESTRUCTD
DESYNCHDS
ENCAPEC
END_OF_BURSTEB
EOB_ACKEA
ERRORY
FAKEFA
GLINEGL
INFOF
INVITEI
JOINJ
JUPEJU
KICKK
KILLD
LINKSLI
LUSERSLU
MLOCKML
MODEM
MOTDMO
NAMESE
NICKN
NICKJUPENJ
NOTICEO
OPEROPER
OPMODEOM
PARTL
PASSPA
PINGG
PONGZ
PRIVMSGP
PRIVSPR
PROTOPROTO
QUITQ
REBURSTRB
REHASHRE
RESVRV
RPINGRI
RPONGRO
SERVERS
SETNAMESG
SETTIMESE
SHUNSU
SILENCEU
SNOSNO
SQUITSQ
STATSR
SVSCLASSSC
SVSIDENTSID
SVSJOINSJ
SVSMODESM
SVSNICKSN
SVSPARTSP
SWHOISSW
TAXONOMYTA
TIMETI
TLOCKTL
TOPICT
TRACETR
UPINGUP
WALLCHOPSWC
WALLHOPSWH
WALLOPSWA
WALLUSERSWU
WALLVOICESWV
WHOH
WHOISW
WHOWASX
XQUERYXQ
XREPLYXR

Message format#

The general message format for the server<>protocol is much like that descrbed in RFC 1459, section 2.3.1:

<source> <command> [<parameters>]

The source, command and parameters are separated by spaces (0x20).

The maximum number of parameters is 15, which does not include the source and command.

Implementations (from herein referred to as servers) must only send the token form of a command, except for the initial PASS and SERVER messages; however, a server may choose to parse both the long and token forms of commands, and must treat the two as equivalent if they do.

The command is uppercase and servers must not send lowercase commands; however, a server may parse both uppercase and lowercase commands, and must treat the two as equivalent if they do.

If the source does not exist wirhin the network, and the message is an SQUIT or KILL, the server must still parse the message, with the directly linked server from which the message came as the source; otherwise, the message must be ignored.

If the source of the message exists within the network, but the message came from the wrong direction, then the server must ignore the message.

The last parameter may be prefixed with a colon; this allows the last parameter to have spaces, or to have a length of zero characters: <source> <command> <para1> <paramN> :<last param>. Servers must be able to parse messages with a colon prefixed last parameter and without. For example, "a b c" and "a b :c" are equivalent.

Registration and synchronization#

Server registration and authentication#

After a connection has been established, the initiator sends a PASS message as follows:

PASS :<password>

The password is compared with the password present in the receiving server's configuration file, and is used to confirm credentials after the SERVER message has been received, as shown below. Servers may choose to perform additional verification, such as validating TLS certificates.

1      2            3          4          5          6          7                 8         9SERVER <servername> <hopcount> <boottime> <linktime> <protocol> <numeric/maxconn> [+flags] :<description>

Notes:

  1. The SERVER message, indicating this connections wants to introduce a server to the network.
  2. The name of the server being introduced.
  3. The hop count of the server being introduced, this is always 1 when introducing yourself.
  4. The epoch timestamp of when the ircd was started.
  5. The epoch timestamp of when the server initiated the link to the network.
  6. The protocol identifier for the server:
    • This parameter informs the network which version of the protocol the server is compliant with, e.g. if it's a P10 compliant server, then the value of this parameter would be "P10".
    • If the server being introduced has not successfully synced its database with the network (i.e. completed its net burst), then the value should be prefixed with a "J" instead of a "P" to indicate it is still in the process of joining the network.
    • The value of this parameter is always JXX when the server is introducing itself (e.g. J10).
  7. The numeric, and maximum connections identifier for this server.
    • This parameter is formatted exactly the same as a user numeric. The first two characters identify the server's numeric, but in this situation the final three characters defined the maximum number of users the server can hold (or more importantly, the maximum number of numerics it will generate). This value is always one less than the power of two, as the server uses it as a bitmask. A server can give out a higher numeric than this; however, it will be "AND'ed" with this value to find its entry slot. This is done so that server nearing the maximum number of users can still give out more numerics than it is using to prevent a new user from getting a numeric that was used only seconds ago, which could possibly resilt in that user receiving message destined to the old user.
    • For example, a value of "AK]]]" would indicate that this server has been assigned the numeric 10 and will generate user numerics up to 262,163.
  8. [optional] The flags parameter is used to indicate the server's type and/or capabilities it supports. If present it must be prefixed with a '+'. The flags supported by ircd-yeti are:
    • h - indicates the server is of type "hub"
    • s - indicates the server is of type "service"
    • 6 - indicates the server supports IPv6
    • n - indicates the server supports opernames
  9. The final parameter is a textual description for the server, prefixed by a colon.

Example#

SERVER irc.example.org 1 1597451814 1597451828 J10 AKAP] +h6n :IRC server

Once the recieving server has verified the information it will send its own PASS and SERVER messages. If the initiator's credentials were invalid, the receiving server should issue an SQUIT with the relevant reason.

Network database re-synchronization#

After the connection has been established and authenticated, the next step is to synchronize the database of servers, bans, nicknames, and channels between the two servers. This is commonly referred to as the net burst.

SERVER messages#

Server details are transmitted via SERVER messages, similar to the initial introduction message:

<prefix> S <servername> <hopcount> <boottime> <linktime> <protocol> <numeric/maxconn> [+flags] :<description>

The syntax of this message is nearly identical to the initially received SERVER message; however, in this case the message is numeric prefixed, and uses the token form. The numeric prefix indicates which server sent this message, and therefore, which hub this new server is linked to.

Server collision rules#

If a SERVER message is received and the name or numeric of the new server already exists within the network, there is a server name or numeric collision, which must be resolved by breaking a link:

  1. If there is a name or numeric collision with the local server (i.e. ourselves), or with any UWorld (i.e. services) servers, close the direct connection to the newly introduced server.
  2. If there is an existing server with the same name, but numerics differ, or there is an existing server with the same numric but the names differ, remove the newly introduced server.
  3. If the newly introduced server is a direct connection and has an older or equal link timestamp than the existing link, close the new connection.
  4. If the newly introduced server is a direct connection, remove the existing server (ghost) and mark the direct connection of the server as "caused ghost".
  5. If the direct connection of the newly introduced server is marked as "caused ghost", remove the existing server (ghost loop).
  6. If none of the above criteria fits, break the second youngest link.
Why the second youngest link?#

Consider the following situation, there is a net split with two fragments, A-B-C-D and E-F-G-H. The existing links are old/good links (such as between hubs). Two operators independently make a link, one tries to link A to H, and the other tries to link D to E.

A-B-C-D|     |H-G-F-E

The new SERVER message for A-H propagates from A to D, and from H to E. The new link D-E propagates from D to A, and from E to H. Somewhere in the middle, on servers B/C and G/F there will be a collision, but that is not a great place to break the link; either the link A-H ot D-E needs broken, and in both B/C and G/F the same decision needs to be made.

There are more optimized ways to achieve the same result of getting the second youngest link, but this explanation leaves no doubt:

There is a "loop", the path between the two colliding servers. For example, server A-B-C-D-A, there's four links in the loop. This includes the newly introduced server which caused the loop. To get the second youngest link, sort the links by timestamp from latest to earliest. Get the timestamp of the second link. From any/all links with that timestamp, get the link which has the greatest server name (sorted alphabetically). If multiple links have the same greatest server name, get the link which has the other server name as the greatest.

  • Example 1: loop: A-B/103 B-C/101 C-D/102 D-A/104. Second youngest link is A-B.
  • Example 2: loop: A-B/101 B-C/101 C-D/101 D-A/101. Second youngest link is C-D.

Break the link by sending an SQUIT message for the server on the remote end of the link.

Ban messages#

All unexpired G-lines, Jupes, Resvs and Shuns are transmitted via their respective GLINE, JUPE, RESV and SHUN messages.

NICK messages#

Information for all known users is transmitted via NICK messages:

1        2 3      4          5           6          7      8                     9          10        11<prefix> N <nick> <hopcount> <timestamp> <username> <host> [+modes [parameters]] <base64ip> <numeric> :<realname>

Notes:

  1. The numeric of the server sending this message, thus owning this user.
  2. The NICK token.
  3. The nickname of this user.
  4. The hop count of this user, i.e., how many servers away it is on.
  5. The epoch timestamp indicating when this user last changed their nickname.
  6. The user's username/ident.
  7. The user's real hostname.
  8. [optional] User modes for this user. If present, this parameter must be prefixed with a '+'.
    • The +o usermode is followed by the users's opername, if the server supports opernames.
    • If the user is authenticated to an account, the special +r usermode is sent followed by the account stamp, which is formatted as: accountname:account_timestamp:account_id:account_flags.
    • If the user has a fakehost, the special +f usermode is sent followed by the fakehost.
    • If the user has a cloak, the special +C usermode is sent followed by the cloak.
  9. The real IP address, Base64 encoded.
  10. The user's numeric.
  11. Free format real info line, also referred to as gecos.
Example#
AK N ClientA 1 1597452760 ~user userhost.example.com +oiws opername B]AAAB AKAAA :realname

The NICK message may possibly be followed by AWAY, SWHOIS, PRIVS, CERTFP and/or FAKE messages.

Nickname collision rules#

If a server receives a NICK message for a new user and another user already exists within the network with the same nickname, there is a nickname collision.

  1. Both users are killed if their timestamps are equal.
  2. The user with the higher timestamp is killed if the user@host are different.
  3. The user with the lower timestamp is killed if the user@host are equal.

BURST messages#

Channel details and membership information is synchronized in one or more BURST messages for each known channel. The first two parameters are always the name and creation timestamp. The other parameters are optional. Servers must be able to parse modes, membership lists, and ban-like lists in any sequence.

1         2 3         4           5       6     7        8         9<numeric> B <channel> <timestamp> [+modes [key] [limit]] <members> [:%bans]

Notes:

  1. The numeric of the server sending this message.
  2. The BURST token.
  3. The name of channel to which this data belongs.
  4. The epoch timestamp of when this channel was created.
  5. [optional] Channel modes. If present, this parameter is always prefixed with a '+'.
  6. [optional] Channel key. This parameter is present if the channel modes parameter contains a "k" mode.
  7. [optional] Channel limit. This parameter is present if the channel modes parameter contains an "l" mode.
  8. [optional] A comma separated list of user numerics (see formatting rules below).
  9. [optional] A space separated list of bans, ban exceptions, quiets, and invite exceptions (see formatting rules below).

There may be at most one modes parameter (and its extra parameters), and it must be before any members or bans. There may be at most one members parameter and it must be after any modes and before any bans. There may be at most one bans parameter and it must be the last parameter.

If the length of a BURST message exceeds the maximum line length (512), then the remaining members and/or bans are sent in subsequent messages, which are only used to add additional members or bans to the channel, if necessary. There will be no modes parameter present for susbequent BURST messages for the same channel.

Numerics in members parameter must be sorted by mode status: first users without modes; then users with voice; then users with halfop; then users with chanop; then users with voice and halfop; then users with voice and chanop; then users with voice, halfop and chanop: num,num:v,num:h,num:o,num:vh,num:vo,num:vho. This mode state applies to the numeric it is attached to and all subsequent numerics until another state is encountered.

For example, consider the following membership list:

AAABA,AAABB:v,AAABC,AAABD:h,AAABE:vo,AAABZ

In the above example, AAABA has no status in the channel. AAABB and AAABC are both voiced, while AAABD is halfopped, leaving AAABE and AAABZ as voiced and opped.

If the BURST message contains a bans parameter, the first character of the parameter is a '%', then a space separated list of bans. This parameter is also used to burst ban exceptions, quiets, and invite exceptions:

  • The first ban that begins with a ~ (without a mask of its own) indicates that the masks that follow are ban exceptions
  • The first ban that begins with a & (without a mask of its own) indicates that the masks that follow are quiets
  • The first ban that begins with a ^ (without a mask of its own) indicates that the masks that follow are invite exceptions

For example, consider a BURST message containing the following bans parameter:

:%*!*@pos1.example.com another!ban@pos2.example.com ~ *!fred@pos1.example.com & ^ $a:frank

In the above example, the following bans, ban exceptions and invite exceptions would be added to the channel:

  • Ban: *!*@pos1.example.com
  • Ban: another!ban@pos2.example.com
  • Ban exception: *!fred@pos1.example.com
  • Invite exception: $a:frank

While the '&' prefix is present in the above example, no masks followed it indicating there were no quiets. A server may choose to omit a prefix for ban exceptions, quiets, and/or invite exceptions, respectively, if such lists contain no masks. If the bans parameter is present, it MUST always be prefixed with '%', even if it doesn't contain any bans.

The BURST message may be possibly followed by TOPIC and/or CFEAT messages.

Channel TS rules#

The timestamp is compared with the timestamp of the existing channel:

  • If the incoming timestamp is older than the existing timestamp, all modes, member status, bans, ban exceptions, quiets, and invite exceptions on the channel must be cleared before adding the new items in the burst to the channel. The topic and invite list must be cleared as well.
  • If the existing timestamp is older than the incoming timestamp, all modes, member status, bans, ban exceptions, quiets, and invite exceptions from the burst must be ignored and not propagated, only the membership list.
  • If the timestamps are equal, the modes, bans, ban exceptions, quiets, and invite exceptions are merged. A mode that is set wins over a mode that is not set. If both the incoming and existing modes contain a limit/key, a lower limit wins, and a key that is first alphabetically wins.

Messages#

ACCEPT#

  • Syntax: AP <user numeric> <mask(s)>
  • Source: server

Modifies a client's accept list.

ACCOUNT#

  • Syntax: AC <user numeric> <name> <timestamp> <id> [flags]
  • Source: server

Sets account information for a user.

Servers must not allow account information to be modified once set, with the following exceptions:

  • Flags may be modified, only if all other parameters exactly match account information already set for the user.

ACCOUNT messages with an account name that exceeds the configured account name length (currently 30 characters in ircd-yeti) are a protocol violation, and the server must not apply the account information for the user.

note

During net bursts, a user's account information is propagated in the NICK message using the special usermode +r followed by the user's "account stamp".

ADMIN#

  • Syntax: `AD

  • Token: AD

  • Source: user

  • Parameters: hunted

Remote ADMIN request.

ASLL#

  • Token: LL
  • Source: user
  • Parameters: server mask, hunted

Remote Asymmetric Link Latency (AsLL) request.

AWAY#

  • Token: A
  • Source: user
  • Parameters: opt. away reason

Propagates away status of a client.

If the away reason is empty or not present, mark the client as not away; otherwise, mark the client as away.

Implementations MAY choose not to propagate a client's away reason when the client is changing the away reason from one non-empty string to another non-empty string.

CERTFP#

  • Token: CF
  • Source: server
  • Parameters: client numeric, fingerprint

The CERTFP message provides a way for servers to propagate the certificate fingerprint that is associated with a client.

CFEAT#

  • Token: CT
  • Source: user
  • Parameters: channel, timestamp, feature setting(s)

The CFEAT message is used to propagate channel feature settings for a channel. The first two parameters are always the channel name and timestamp. The other parameters contain space separated feature=value pairs.

Rules for generating a CFEAT message are as follows:

  • One or more feature=value pairs may be present
  • Features that allow values that contain spaces must be the last parameter

If a CFEAT message is parsed, the timestamp is compared with the timestamp of the existing channel. If the existing timestamp is older than the incoming timestamp, implementations MUST ignore and not propagate the message. Otherwise, the existing feature values are updated with the incoming values and propagated.

CHECK#

  • Token: CC
  • Source: user
  • Parameters: channel|user|servername

Remote CHECK request.

CLEARMODE#

  • Token: CM
  • Source: any
  • Parameters: channel, control string

The CLEARMODE message propagates a clear mode request for a channel.

Implementations SHOULD verify that the source has the necessary privileges to perform the action.

CLOAK#

  • Token: CK
  • Source: server
  • Parameters: mechanism name, key

The CLOAK message propagates a cloak key change for the specified cloaking mechanism.

CONNECT#

  • Token: CO
  • Source: any
  • Parameters: server to connect to, port number, hunted

Remote connect request. The port can be 0 to use the default port.

Implementations MAY verify connection rules and jupes.