The InspIRCd Project
Home | Developers | Wiki | Forums | Bug Tracker | SVN | Download | Blog | Stats
Personal tools

InspIRCd Spanning Tree (1.2)

From the makers of InspIRCd.

Jump to: navigation, search
Development Development Material - Information posted here is for developer reference only. This material is subject to frequent change and may not be applicable to current releases of InspIRCd.

This page will be expanded as we add to the protocol listed here. Protocol changes will be generally backwards-compatible with previous versions (up to a point). Major version changes (e.g. 1.1 to 1.2) usually mean major protocol changes. Any changes to the protocol in minor releases will not usually break previous releases unless absolutely neccessary.

Linking a server into an InspIRCd spanning tree is relatively straightforward for anyone who's handled IRC servers and their protocols before. InspIRCd's protocol is a UID/SID based protocol similar in behaviour to the TS6 protocol used by some other ircds (for example when merging channels and dealing with collisions).

Contents

Connecting a server

To connect to a server (which has our details in a <link> tag) we first proceed with the authentication phase, as detailed in the section below.

The Authentication Phase

During the authentication phase, a three-way handshake is performed where both servers exchange their passwords. Unlike most IRCds (the notable exception being ircu) this must be done in lock-step fashion, e.g. one server sends a request then waits for the other server to reply before sending another. Note that once the authentication phase is complete, the data flow moves to being full duplex and no such restrictions apply once the BURST command is received (see below).

Step One - Connection

Server A, wishing to connect to the network, connects to server B using connect() or equivalent. When the connection is established, it immediately sends the CAPAB and SERVER commands (see the commands list below) to server B which is waiting for inbound connections. Up until this point, server B will do nothing but accept the connection and reply with its CAPAB.

Transport-Layer Handshakes

If there are any transport modules attached to the connection, such as openssl, then this is the point where they perform their handshakes. The server should wait before sending anything to ensure the handshake has completed. The details of what is sent at the transport layer are dependent upon the module, and outside the scope of this page.

Step Two - Inbound Authentication

Server B, after receiving server A's SERVER command, analyzes the parameters (namely server name and password) and if it is not happy with the credentials, should instantly send a suitable ERROR reply, and close its connection. However, if server B deems the credentials correct for server A, server B then sends its own SERVER command, with its own credentials in to authenticate to server A.

Step Three - Outbound Authentication

Server A, upon receiving server B's credentials, analyzes them (again, namely the server name and password), and again, if it is not happy, it can send an ERROR reply, and close its connection. If the details are correct however, server A now sends a BURST command (see the commands list below) and begins its network burst.

Step Four - Network Burst

Upon receiving server A's network burst, server B also sends its own network burst, preceded again by the BURST command. When both servers have finished bursting, they send the ENDBURST command. BURST and ENDBURST are only sent for local bursts.

The order which data is sent during the burst is important, and should be:

  • Firstly, the names of any servers connected to this one, directly or otherwise, with relative hop counts, 1 being a direct connection (these will be re-calculated by the receiving side)
  • Secondly, the nicknames of any users, sent using UID, their OPERTYPE if they are an oper
  • Thirdly, The membership and priviledges of all channels using FJOIN (see the commands list, below) and the modes (Sent using FMODE), topics (sent using FTOPIC) and bans (sent again using FMODE) for each channel in turn (no specific order of channels).
  • Lastly, any module specific data (which may be a combination of FMODE and any other module-specific commands).

Example Authentication Phase

This is an example of a successful authentication using plaintext password authentication:

>> SERVER services-dev.chatspike.net password 0 666 :Description here
<< SERVER test.chatspike.net password 0 491 :ChatSpike InspIRCd test server
>> :066 BURST 1176144272
<< :491 BURST 1176144273

(both servers now operate in duplex mode sending data freely)

Challenge-Response and HMAC authentication

InspIRCd 1.2 series servers support challenge-response HMAC authentication for server passwords. This ensures that the password itself is never transmitted in any usable form across the server link.

To facilitate this in a backwards compatible manner, the challenge string is placed into the CAPAB CAPABILITIES lines of the servers which support it and have it enabled. The CHALLENGE string should be sufficiently random to prevent brute-forcing and mathematical attacks against it. The current InspIRCd implementation collects entropy from /dev/urandom.

A challenge should never be sent to the other server if:

  • HMAC is disabled
  • The m_sha256.so module, required for the cryptographic hash, is not loaded

Here is an example of a HMAC enabled authentication phase, which is described in greater detail below the example:

-> CAPAB START
-> CAPAB MODULES m_alltime.so,m_banexception.so,m_blockcaps.so,m_blockcolor.so,m_botmode.so,m_censor.so
-> CAPAB CAPABILITIES :NICKMAX=32 HALFOP=1 CHANMAX=65 MAXMODES=20 IDENTMAX=12 MAXQUIT=255 PROTOCOL=1105 CHALLENGE=egykq)9ae)ms#se?;gi%
-> CAPAB END
<- CAPAB START
<- CAPAB MODULES m_alltime.so,m_banexception.so,m_blockcaps.so,m_blockcolor.so,m_botmode.so,m_censor.so
<- CAPAB CAPABILITIES :NICKMAX=32 HALFOP=1 CHANMAX=65 MAXMODES=20 IDENTMAX=12 MAXQUIT=255 PROTOCOL=1105 CHALLENGE=yyks7-#c5kwuaqyi-e19
<- CAPAB END
-> SERVER test2.chatspike.net HMAC-SHA256:185ea67956256a3703bae0cb9324a655180f5b7089224539e08cf1003b296f9c 0 666 :Test server
<- SERVER test.chatspike.net HMAC-SHA256:76a7d469c3dcab86067495d1b3407720fce9f7286400835baa2972e75e891a65 0 491 :"Bollocks" Said pooh, as he caught his testicles in the vice.
-> :666 BURST 1176144272
<- :491 BURST 1176144273

When authenticating via HMAC, both sides of the connection should wait for the complete CAPAB information before sending their SERVER line. This is to allow for both sides to send their challenge, which is encapsulated in the CAPAB CAPABILITIES as shown above.

The challenge string is hashed against the password using a simple HMAC algorithm, as shown below, before being sent back to the other side in the password section:

sha256( (p xor 0x5C) + sha256((p xor 0x36) + m) )

Where 'm' is the challenge string given in the other side's CAPAB, and 'p' is the password you wish to send. Each character of 'p' should be exclusive-or'ed against 0x5C or 0x36, and in the above equation, + indicates string concatenation, not integer addition.

Due to limitations inherent in the protocol and CAPAB notation, the = symbol may not form part of the CHALLENGE value. Any = symbols should be translated to non-equals, in the current implementation, they are translated to an underscore (_).

IMPORTANT NOTE: In the current implementation, the SHA256 output is ASCII text, e.g. the hexadecimal hash value and not raw binary data.

When the server replies with its calculated HMAC, it should prepend the value "HMAC-SHA256:" to the hash. This is to distinguish it from a plaintext password, and allow servers which do not support HMAC, such as services and past versions of InspIRCd, to link correctly.

When checking the HMAC against what is expected, the checking server should fall back to plaintext authentication if:

  • The sender has not sent a HMAC password
  • We never sent or received a CHALLENGE
  • HMAC is disabled
  • The m_sha256.so module, required for the cryptographic hash, is not loaded.

Commands

This section documents all valid server to server commands which are specific to InspIRCd. Most commands are similar or identical to RFC 1459 to make adding support to other programs (such as services packages) straightforward. Where commands are not documented here, they are transmitted across the spanning tree in standard form, replacing nicknames with UUIDs for those users:

:<uuid> COMMAND <parameters>

For example:

:497AAAAAB PRIVMSG #chatspike :Moo moo!

or,

:497AAATXV MODE #chatspike +ov 497AAAAAB 497AAAAAB

Where commands are part of the RFC (RFC 1459, RFC 2812), but their behaviour or their syntax is different, the commands are documented here in their InspIRCd form.

Modular commands

Any module which implements a command, for example SAJOIN, may have those commands automatically passed out onto the network as a broadcast.

Any servers which also have this module loaded and handling the same command will be informed of the inbound command coming in off the network.

If a server does not recognise a command, it should close the connection immediately to prevent a desync.

To load a module network wide, configuration files should be edited then then the modules introduced via /rehash *.

Examples of such modular commands are KNOCK and REMOVE.

Not all commands are network-wide. An example of such a command is WATCH which operates solely on local clients. This also means that such modules do not need to be loaded upon all servers for them to function.

NOTE: In the 1.2 implementation all nicknames and lists of nicknames are translated to UUIDs of those nicknames before transmission on the network, and before any retransmission over the network.

Core commands

SERVER

(Broadcast, One-To-One)

SERVER <servername> <password> <hopcount> <id> :<description>

The SERVER command is used to authenticate to the network, or to introduce a new server, once authenticated. The two forms of this command are as follows:

SERVER <servername> <password> 0 <id> :<description>

This version of the command is used when authenticating (see the authentication phase, above). The password must be supplied and must be valid on the remote server, and the hopcount must be zero otherwise an ERROR should be generated by the remote side.

:<local server id> SERVER <remote server> * <distance> <id> :<description>

This version of the command is used after authentication (during bursting and normal operation) to indicate a new server has been introduced. This command will be passed on to all other servers. The password field contains a * as it is unused. The distance field must be one or greater, indicating a non-local connection. The actual value is not important so long as it is greater than zero, as the hopcounts are relative and re-calculated by the recipient to match their local view of the server map.

The ID field in the SERVER command indicates the server's sid, or server ID. You should check this against all already existing servers for collision, and if a collision is found, SQUIT the server or deny the link.

FJOIN

(Broadcast)

:<sid> FJOIN <channel> <timestamp> +[<modes> {mode} {params}] [:<[statusmodes],uuid> {<[statusmodes],uuid>}]

This command is used within a netburst to synchronize all of the users on a channel, and set their permissions upon that channel. Channel restrictions on remote users who are sent in FJOIN or JOIN should be ignored to prevent desyncs, e.g. bans, invite exceptions, keys and invite-only status should not be checked. For example:

:497 FJOIN #staff 1133630884 +ikl mooc0w 10 :oh,497AAAAAB o,497AAAAQZ h,497AAART0 ,497AAAZZH v,497AAAZZ6 ,497AAYU9B ,497AAB67L

Note that the modes built from this should be merged then sent only to local clients, for example, the above FJOIN will queue and send the mode change to be sent after the clients are joined to the channel (assuming of course that the UUIDs above relate to the client nicks below):

:fudge.chatspike.net MODE #staff +ohohvkl Brain Brain Craig Dune Azhrarn mooc0w 10

The timestamp is used to determine which modes are the established modes upon the channel. To prevent splitriding, the losing side (with the highest timestamp) first removes ALL channel modes (+qaohv, simplemodes, bans, exceptions, m_chanfilter lists etc) from the channel, then updates its timestamp to match the timestamp of the winning side, after which all modes from the winning side are accepted. The winning side will then deny all mode changes from the losing side.

For example, if server A sends this:

:497 FJOIN #staff 1230 + :o,497AAAAAB o,497AAAAQZ

and server B sends this:

:320 FJOIN #staff 1234 +i :o,497AAAAQZ ,497AAART0

Then when server A receives the FJOIN from server B, it will deny giving the uid 497AAAAQZ ops, and server B will remove ops from the user ID 497AAAAQZ locally, as well as dropping the invite-only mode.

Note that the TS is updated before processing any users. In the event that a channel is newly created, the timestamp will be set from the FJOIN command when the first user is introduced. Channel creation should never be done via RFC 1459 "JOIN", however there are certain race conditions where this may still occur, which cannot be addressed.

In the 1.2.x implementation, all other modes (exceptions, bans) must be passed through FMODE, therefore they are checked against timestamps anyway and any potential for race conditions in modes, and mode abuse during burst is mitigated. Simple modes (+ilkf whatever) are passed in FJOIN.

The limit of 12 users per FJOIN is lifted due to the fact all the users are encapsulated in the last parameter of the command. This implementation of InspIRCd will still wrap the line at 460-NICKMAX characters however to ensure compatibility with services packages.

The 1.2.x implementation may receive multiple modes per user (in no defined order), and these modes may be core or module implemented modes such as ohv. The modes and the UUID for each user are separated with a comma (,) and if the user has no modes associated with them, the modes field is empty and the section starts with a comma, e.g. ",nickname". For example:

:497 FJOIN #smelly 12345 :oh,497AAAAAB o,497AAAAQZ h,497AAART0 v,497AAAZZ6 a,497AAYU9B oZ,497AAB67L

If a server ever receives a mode which it does not recognise, for example the Z in the example above, it should immediately close the connection (after sending an ERROR message) to prevent a desync. This situation indicates that modules are not configured identically on both sides of the network, and continuing to link the servers could cause problems. Services may relax this restriction somewhat, however it should be noted that they may not know what functionality a mode allows users - and therefore MUST be careful what restrictions they impose on a user with an unknown mode.

Also of note is that FJOIN may come without a nicklist: this is used for permanent channels. In this case, the channel should be created, but left with an empty nicklist. The channel should not be deleted when the number of users reaches 0 if the permanent channels module is loaded.

:0AA FJOIN #permanent 56789

MODE

(Broadcast)

:<sid/uuid> MODE <target> <modes and parameters>

Note that MODE SHOULD NOT be used on a channel. FMODE should be used instead. Any nickname parameters for MODE will appear as UUIDs.


MODENOTICE

(Broadcast)

:<sid> MODENOTICE <mode-set> :<text>

This will cause all servers to send the text to all users (oper or not) who have the modes which match mode-set. For example, if mode-set is "os" this will send to all users with both modes +o and +s. The text will be prepended by "*** From <servername>:" where servername is the same name as the originating server. This is for accountability purposes, and cannot be removed or overridden.

SNONOTICE

(Broadcast)

:<sid> SNONOTICE <snomask-character> :<text>

This will cause all servers to send the text to all opers who have the given snomask character. The text will be prepended by "*** From <servername>:" where servername is the same name as the originating server. This is for accountability purposes, and cannot be removed or overridden. You may only provide one snomask per SNONOTICE command, as allowing a notice to go to multiple snomask sections would degrade the ability of opers to filter notices using the snomask system.

FMODE

(Broadcast)

:<sid or uuid> FMODE <target> <timestamp> <modes and parameters>

This command is used within a netburst (or sometimes after the burst) to synchronize modes on channels and users. For example:

:564 FMODE #opers 115432135 +bb *!user@spy.com *!person@watching.us

The timestamp determines wether the mode is allowed by the receiving server, or bounced. The rules for bouncing of modes are shown in the section below.

1.2 series servers should use FMODE for all mode changes on channels.

Mode-Merging and FMODE TS rules

The rules for bouncing and merging modes in FMODE are as follows:

  • If the timestamp given in an FMODE is equal for both sending and receiving servers, or the timestamp given in FMODE is less than ours, the modes given in FMODE should be applied, merging them into ours, and then the mode changes are passed along to other servers.
  • If the timestamp given in the FMODE is greater than ours, the changes are dropped, and should not be passed on to other servers.

NB: All user nicknames in the FMODE string will be sent as UUIDs.

OPERQUIT

(Broadcast)

:<source uuid> OPERQUIT :<oper only quit message>

The OPERQUIT command is used to specify a quit message for a user which only opers see, which is seperate from the message sent by the normal QUIT command. This is used for example by GLINEs with the <options:hidebans> option enabled. Modules may also use this to cause a different message to be displayed for opers than for normal users for any particular user quit.

The OPERQUIT command may be sent any time before the actual quit for the user, but if it is sent more than once for any specific user, any further OPERQUIT commands for that user will be silently ignored, and only the first message set will be used.

IMPORTANT NOTE: The OPERQUIT command does not actually cause the user to quit. It simply causes the message given to be stored within the user's structure, for the time when they do quit with the normal QUIT command, at which point this message is sent to opers and the message sent by QUIT is sent to everyone else. Services may or may not choose to store and make use of the seperate oper quit message, depending on its design.

This command is new to protocol version 1105 and should not be used on InspIRCd versions prior to this.

SQUIT

(Broadcast)

:<issuing server> SQUIT <quitting server> :<reason>

This command indicates that server <remote server> has disconnected from <local server> with the given reason. When servers receive this command they must update their server maps accordingly, removing any users which existed upon the orphaned section of network. Separate QUIT messages MUST NOT be sent out for the exited users.

Note that remote SQUITs should not attempt to 'route' an SQUIT along to the target server. RSQUIT (see below) should be used for this purpose.

RSQUIT

(One-To-One)

:<server/uuid> RSQUIT <sid> :<reason>

Upon receipt of this command, the local server should do one of two things. If the server given in <sid> is a locally-connected server, it should SQUIT it as if it had received a local SQUIT from the given source using the SQUIT command (see above). If the server is not locally-connected, it should pass the message on verbatim along the route to the server <sid>. This allows routing of remote SQUITs without all other servers acting upon them until they reach their intended destination.

FTOPIC

(Broadcast)

:<server/uuid> FTOPIC <channel> <time-set> <set-by> :<topic>

This command is used during a network burst to synchronize the channel topics. When setting a topic, the newest topic (highest time-set value) is set and the other discarded. The time-set value is a unix epoch time.

BURST

(One-To-One)

:sid BURST {timestamp}
:sid BURST <timestamp> FORCE

This command indicates the start of a network burst.

It should be sent whenever a net healing is made, as well as locally, to indicate the end of the authentication state (see above).

If a timestamp is given, it will be used for synchronization following the same rules as TIMESET. If the remote server decides against your timestamp, it will send a TIMESET command to correct it. If 'FORCE' is specified, the given timestamp is to be used and broadcast.

Note that no remote XLines will be applied until ENDBURST is recieved.

ENDBURST

(One-To-One)

:sid ENDBURST

This command indicates the end of burst from a given serv. This should always be sent at the conclusion of a network burst, initiated by BURST.

The receiving server SHOULD apply XLines in one action upon receipt of the ENDBURST command, to minimise resource usage.

OPERTYPE

(Broadcast)

:<uuid> OPERTYPE <type name>

This command indicates that the specified user is an IRC operator of the given type. Please note that InspIRCd does not let users or remote servers set the +o usermode under any circumstances. Sending OPERTYPE successfully places the +o usermode upon the given user as well as setting their oper type, so should be used to 'oper up' clients.

REHASH

(Broadcast)

:<local server> REHASH <remote server>

This command indicates that all servers matching the given <remote server> mask should immediately rehash their config files. This command is broadcast, meaning that all servers will receive and act upon it.

MODULES

(One-to-one)

:<uuid> MODULES <server name>

This command will cause the given server name to respond with its module list. The detail of the module list will vary depending on if the given user issuing the command is an oper or not. The results are usually returned via PUSH.

UID

(Broadcast)

:<sid of new users server> UID <uid> <timestamp> <nick> <hostname> <displayed-hostname> <ident> +<modes> <ip> <signon time> :<gecos>

This command introduces a new client into the network. If there is a nickname collision, the local server is responsible for changing the nickname of the local client to its UID. The remote server MUST repeat this with its remote client. The ip field is in dotted decimal form, e.g. 1.2.3.4.

The command should deal with nickname collisions using the rules documented in the nickname collision handling section.

JOIN

(Broadcast)

:<uuid> JOIN <#channel>{,<#channel>} <timestamp>

The JOIN command has a timestamp attached to it, so that in case of a desync, servers may still determine the timestamp value for a channel. Consider the situation where a user leaves a channel on one server, at the same time a join is sent from a second - This version of JOIN prevents the timestamp being lost.

USER

(N/A)

The RFC1459 command "USER" is not implemented by InspIRCd between servers, as this functionality (and the NICK command to introduce users) is handled by UID command.

NICK

(Broadcast)

:<uuid> NICK <newnick> <timestamp>

The RFC1459 NICK command differs in InspIRCd for use in a TS6-like environment. The command has an extra parameter, the nickname timestamp, which is used to compare the nickname against any existing instances of that nickname on collision and determine which of the two wins.

See also the nickname collision handling section.

IMPORTANT NOTE: If a 'legacy' nickname change is sent without the timestamp, the server sending it will be quit from the network for a protocol violation.

VERSION

(Broadcast, One-To-One)

:<sid> VERSION :<arbitary version string>

Whereas the RFC version of this command (no pun intended) requires that each time a user requests a remote server version, the server should direct a version request at a local server and wait for a reply, the InspIRCd version of this command operates differently. To save on cross-network bandwidth, instead, the InspIRCd protocol requires that this be sent as part of the network burst. All servers then cache the version strings of all other connected servers and may return them to clients without making any requests to the network. Servers may also update their version strings at any point after the burst.

FHOST

(Broadcast)

:<uuid> FHOST <new displayed host>

The FHOST command is sent out when a server changes the displayed host of a user local to that server.

FNAME

(Broadcast)

:<uuid> FNAME :<new GECOS field>

The FNAME command is sent out when a server changes the GECOS (full name) field of a user local to that server.

ADDLINE

(Broadcast)

:<sid or uuid> ADDLINE <linetype> <mask> <setter> <time set> <duration> :<reason>

The ADDLINE command is used to set an XLine managed line. The setter can be any arbitrary text up to 64 characters in length (so it may be a nick which is not online, or a server name which no longer exists). Servers must use this command to sync Q, Z, E, G and other lines during and after a burst. The GLINE, ZLINE etc commands are no longer supported in the server to server protocol and should not be used.

The core of InspIRCd supports and recognises the following line types (case sensitive):

  • G - GLINE
  • Z - ZLINE
  • E - ELINE
  • Q - QLINE
  • K - KLINE

The linetype field is not a single character field and may contain any arbirary case sensitive line identidier. Each line identifier can be relied upon to store its reason, setter, time set and duration in a uniform manner similar to all other xlines, however the mask is line specific and may contain anything of use to the module which handles the xline. If your implementation does not recognise the xline being sent the connection should be closed to prevent a desync.

DELLINE

(Broadcast)

:<sid or uuid> DELLINE <linetype> <mask>

The DELLINE command is used to delete a previously set XLine managed line. The line type must be a recognised XLine to the rest of the network, supported by a loaded module or the core. See the ADDLINE command for a list of core recognised line types. The mask is specific to the module implementing the XLine.

SVSHOLD

(Broadcast)

:<uuid> SVSHOLD <nickname> <duration> :<reason>
:<uuid> SVSHOLD <nickname>

This command sets or removes a SVSHOLD (the first syntax given is to add, the second to remove). The duration in this command may be formatted in the form: 1y2w3d4h5m6s which means 1 year, 2 weeks, 4 hours, 5 minutes 6 seconds, or simply as a number of seconds.

SVSHOLD's <nickname> parameter MUST NOT be a UUID.

An SVSHOLD is virtually equivilant to a Q:Line, except that it is generally controlled by services, and is held separate from Q:Lines. Commonly used for Services enforcers.

NOTE: Requires m_svshold.so to be loaded.

SVSNICK

(Broadcast)

:<sid> SVSNICK <uuid> <new nick> <timestamp>

This command will forcefully change the nickname of the user identified by <uuid> to <new nick>.

Unlike many other implementations this command may be issued by any server (not just a U-Lined server).

The client's timestamp value will be reset to the timestamp given in the SVSNICK command.

USE WITH CAUTION! There is purposefully no client-side version of SVSNICK for opers, the SANICK module must be used instead for opers to change user nicks, which does not change the user's timestamp.

This command is also sent out on netmerge if a nickname collision occurs to change the nickname of a user to their UUID.

PLEASE NOTE: When using this command, it does not in itself force a nickchange at each server directly that it passes through. The server where the old nickname resides is the only server to directly act upon the SVSNICK, and does so by echoing back a NICK to the rest of the network 'acknowledging' the nickchange. Any other servers where the old nick is not a local user will just pass the SVSNICK on, so long as the old nick exists. This means servers MUST wait for confirmation that the user changed nick.

SVSJOIN

(Broadcast)

:<sid> SVSJOIN <uuid> <channel>

This command is implemented for services compatibility. When given it will force the given user to join the given channel.

Unlike many other implementations this command may be issued by any server (not just a U-Lined server) but there is purposefully no client-side version for opers, the SAJOIN module must be used instead for opers to force users to join channels.

This command is never sent out by InspIRCd servers directly, however it is forwarded from services servers, and should therefore be supported.

SVSPART

(Broadcast)

:<sid> SVSPART <uuid> <channel>

This command is implemented for services compatibility. When given it will force the given user to leave the given channel.

Unlike many other implementations this command may be issued by any server (not just a U-Lined server) but there is purposefully no client-side version for opers, the SAPART module must be used instead for opers to force users to join channels.

This command is never sent out by InspIRCd servers directly, however it is forwarded from services servers, and should therefore be supported.

SVSMODE

(Broadcast)

:<uuid> SVSMODE <target> <modes and parameters>

This command is implemented for services compatibility.

When given it will allow modes to be set on users which are on remote servers, bypassing many checks.

Unlike many other implementations this command may be issued by any server (not just a U-Lined server) but there is purposefully no client-side version for opers, the SAMODE module must be used instead for opers to force user or channel MODEs.

This command is never sent out by InspIRCd servers directly, however it is forwarded from services servers, and should therefore be supported.

METADATA

(Broadcast)

:<sid> METADATA <channel|uuid> <key> :<value>

Because InspIRCd is completely modular, modules require a way of passing messages from server to server, transparent of the actual protocol in use, without two modules competing over resources. To accomplish this, InspIRCd allows modules to extend user and channel 'records' in the ircd itself with arbitary data, known as metadata (in InspIRCd API terms, this is known as the Extensible class). Each extra piece of data is named uniquely using an ASCII key, and each module only modifies its own keys and values. The internal format of this data is module specific.

When two servers sync, the protocol module, m_spanningtree.so, retrieves the list of metadata names for each user or channel as it is synched, and then queries all modules, asking them to submit an ASCII string that represents the given key's metadata. This is then sent to the opposite side of the netburst. The opposite end, upon receiving this metadata, again queries all modules, until one claims it and re-assembles the ASCII <value> field back into its native form, and stores it in the key for that particular user or channel.

Most non-InspIRCd systems can safely ignore METADATA commands (and should do so!), and should NOT send any without knowing exactly which module uses the given key, and what for, and the format of their ASCII data. Please note that the <value> field only has to be meaningful to the module which generated the message, and may not be usable in any other form (e.g. it may be encrypted or otherwise munged).

IDLE

(One-To-One)

:<uuid> IDLE <target uuid>
:<uuid> IDLE <target uuid> <signon> <seconds idle>

When a user issues a remote WHOIS, the IDLE command (in its first form listed above) is sent out.

The user issuing the WHOIS is placed into the <uuid> field and the user being whois'ed is placed into the <target uuid> field

The WHOIS response is then locally delayed, until a remote server responds via the second format of the command.

The user they whois'ed is placed in the <source uuid> field, and the user that issued the WHOIS is placed in the <target uuid> field, along with the signon time and idle time of the source user.

Once the original server receives this information, it is able to then build its entire WHOIS response and send it to the originating user.

PUSH

(One-To-One)

:<sid> PUSH <target uuid> :<any text>

The PUSH command, when sent, will be passed to the server where <target nick> resides, and then the arbitary text contained within <any text> will be dumped to the user's socket. This may be used as an encapsulation mechanism for sending raw lines to users and implementing systems in InspIRCd which the protocol does not directly support.

TIME

(One-To-One)

:<sid> TIME <target server> <uuid>
:<sid> TIME <target server> <uuid> <timestamp>

The TIME command is a more efficient version of the TIME command and numeric used by other ircds. The first form of the command is used to request the time of remote server <target server> on behalf of <uuid>.

When the remote server replies to the request it should use the second form of the command, which has the timestamp appended, and <target server> and <sid> transposed so that the message finds its way back to the issuer.

Once the issuer receives the response they should decode the timestamp using localtime() and asctime() and display it to the user given by <uuid> in the same manner as a local TIME request.

TIMESET

(Broadcast)

:<sid> TIMESET <timestamp>
:<sid> TIMESET <timestamp> FORCE

The TIMESET command is used for time synchronization between servers; unless disabled, servers will send a TIMESET every 12 hours and the lowest timestamp on the network will be adopted by all servers. The 'FORCE' parameter (case sensitive) can be added to force your timestamp to be used by all servers. Time is also synchronized with the BURST command.


CAPAB

(One-To-One)

CAPAB START
CAPAB CAPABILITIES :VAR=VALUE {[VAR=VALUE]}
CAPAB MODULES <module list>
CAPAB END

The capab command, if sent, must be sent in the authentication phase before any other command. If the server is listening for connections, then it must immediately send out this command as its 'banner' after any transport layer handshakes.

Any server which does not understand the CAPAB command should silently ignore all CAPAB commands and their parameters.

CAPAB START

CAPAB START will cause the capaibility list to be cleared ready for negotiation. This is optional when first connecting, but if you wish to re-negotiate CAPAB after you have connected, you must first use CAPAB START.

CAPAB MODULES

CAPAB MODULES should contain a comma separated list of modules in alphabetical order. Because some services packages limit the line length to 512 bytes, this should wrap at 509 bytes and continue the list in further CAPAB MODULES messages if the list is too long to fit onto one line. Module names are case sensitive. To build this list, InspIRCd servers make a list of all modules with the VF_COMMON flag set in their version information, and sort it alphabetically, separating each module name with commas. As windows builds of InspIRCd also use .so as the file extension for modules, this will not effect linking to versions of InspIRCd running on windows, or other non-unix platforms, so long as naming conventions are adhered to.

CAPAB CAPABILITIES

CAPAB CAPABILITIES should contain a space separated list of variables and values in its single parameter. As with CAPAB MODULES, if its length goes over 509 bytes it should wrap and add further values into a second or third (etc) CAPAB CAPABILITIES line. In a CAPAB CAPABILITIES entry, the value cannot contain spaces and the variable name should not be duplicated more than once in the list. Variable names and values are both case sensitive.

Valid CAPAB CAPABILITIES variables

The following variables are recognised by InspIRCd 1.1:

Variable Required Description
PROTOCOL Yes The current protocol version.
List of protocol changes between versions
NICKMAX Yes Maximum length of nicknames including \0
HALFOP No Server supports halfop when defined and set to 1
CHANMAX Yes Maximum length of channel names including \0
MAXMODES Yes Maximum number of parameterized modes per MODE command
IDENTMAX Yes Maximum length of ident including "~" symbol and \0
MAXQUIT Yes Maximum length of quitmessage including \0
MAXTOPIC Yes Maximum length of channel topics including \0
MAXKICK Yes Maximum length of channel kick message including \0
MAXGECOS Yes Maximum length of full name field (GECOS)
MAXAWAY Yes Maximum length of away messages including \0
IP6NATIVE No If this is set, IP6SUPPORT will exist and be set. Signifies this server is IPV6 native
IP6SUPPORT No If this is set, this server can handle users, bans etc which are in IPV6 form
PREFIX No List nick prefixes in 005-numeric RPL_ISUPPORT format
CHANMODES No List channel modes in 005-numeric RPL_ISUPPORT format

CAPAB END

Upon receiving CAPAB END, the server should compare its values and lists to check they match appropriately. If they do not, an error will be generated and the connection closed.

Example CAPAB output

This is example output of CAPAB in 1.1:

CAPAB START
CAPAB CAPABILITIES :NICKMAX=32 HALFOP=1 CHANMAX=65 MAXMODES=20 IDENTMAX=12 MAXQUIT=255
CAPAB CAPABILITIES :MAXTOPIC=307 MAXKICK=255 MAXGECOS=128 MAXAWAY=200 IP6NATIVE=0 IP6SUPPORT=1 PROTOCOL=1105 PREFIX=(ohv)@%+ CHANMODES=b,k,l,imnpst
CAPAB MODULES m_banexception.so,m_blockcolor.so,m_botmode.so,m_censor.so,m_chanfilter.so,m_chanprotect.so,m_cloaking.so
CAPAB MODULES m_globops.so,m_httpd.so,m_httpd_stats.so,m_inviteexception.so,m_joinflood.so
CAPAB MODULES m_kicknorejoin.so,m_knock.so,m_messageflood.so,m_noctcp.so,m_noinvite.so,m_nokicks.so,m_nonicks.so,m_nonotice.so,m_operchans.so
CAPAB MODULES m_redirect.so,m_services.so,m_spanningtree.so,m_stripcolor.so,m_testcommand.so,m_tline.so,m_uninvite.so
CAPAB END

PING

(One-To-One)

:<sid> PING <destination-data>
:<sid> PONG <destination-data>
:<source> PING <sid> :<destination server>
:<source> PONG <sid> :<destination server>

The PING command is implemented in two forms.

The two-parameter version of PING is identical to RFC 1459, and you should refer to RFC 1459 and RFC 2813 for more information on this command. This format of the PING (and PONG) command can traverse servers and can be used for latency and end-of-burst checks.

The short form of the command with one parameter is InspIRCd-specific. If you receive a PING command with one parameter, you must answer with a PONG on the same connection the PING came from.

The contents of the short form PONG reply are not important, however servers SHOULD populate this field with the target server name. If you do not reply to the one-parameter PING with a one-parameter PONG within two times the ping time, the remote server SHOULD close the connection.

NB: The short-form of PING with one parameter can NEVER travel more than one server away from its source. It should only be used for local checks on the health of a connection.

UUIDs (Universally Unique User Identifiers)

Our implementation and definition of SID, ID, and UID closely matches TS6's. That is:

  • SID - A servers unique ID. This is three characters long and must be in the form [0-9][A-Z0-9][A-Z0-9]. InspIRCd servers only ever use server id's in the range 000-999, leaving server id's with letters as reserved for third party servers such as services servers. This can help prevent collisions, as by default the SID is automatically generated by InspIRCd whereas in TS6 it is admin-specified.
  • ID - A clients unique ID. This is six characters long and must be in the form [A-Z][A-Z0-9][A-Z0-9][A-Z0-9][A-Z0-9][A-Z0-9]. The numbers [0-9] at the beginning of an ID are legal characters, but reserved for future use.
  • UID or UUID - An ID concateneted to a SID. This forms the clients UID.

When allocating a UID, InspIRCd will 'increment' the value, e.g. the ID after 001AAAAAA is 001AAAAAB, which is followed by 001AAAAAC, etc etc. When the highest UID is reached, InspIRCd will "wrap around", starting again at 001AAAAAA. Note that if the ID the server tries to allocate already appears to be in use (possible after a wrap-around has occured) then the next ID in the sequence will be tried repeatedly, until a free ID is found. This differs from TS6 implementations, some of which will restart the server once the UID space has been exhausted.

Server ID (SID) auto generation

InspIRCd servers have the capability to automatically generate a server ID. This is done using the hash function for the GNU GCC hash_map against the server name and server GECOS. In pseudocode, this can be represented as:

   SID := 0
   FOR EVERY CHARACTER IN SERVER_NAME:
   BEGIN
       SID := 5 * SID + VALUE_OF_CHARACTER_IN_SERVER_NAME
   END
   FOR EVERY CHARACTER IN SERVER_GECOS
   BEGIN
       SID := 5 * SID + VALUE_OF_CHARACTER_IN_SERVER_GECOS
   END
   SID := SID MODULUS 999

In the remote case that this automatically allocated ID conflicts with other IDs on the network, an ID may be manually specified in the configuration file.

Nickname Collision Handling

The InspIRCd 1.2 spanningtree protocol adopts a TS6-like nickname collision algorithm which minimises the impact of nickname collisions and prevents most if not all KILLs when a collision does occur.


The rules for nickname collision are as follows:

  • If the user@ip of the two colliding users are equal: Force nick change on OLDER client which changed their nickname first (this is to prevent penalizing users who have reconnected, so that their 'ghost' does not win the collision)
  • If the user@ip of the two colliding users differ: Force nick change on NEWER client which changed their nickname last (this is to help prevent users camping on nicknames, causing a collision and stealing that nickname during the resynch)
  • If the nickname change times of the clients are equal: Force a nick change on both.


Where nickname changes are enforced by this algorithm, the nickname is changed to the users UUID. Because the user's UUID contains a leading digit, it is impossible for any user to NICK to their UUID or anyone elses UUID and 'camp' on it. Only a server may force a nickchange to such an 'illegal' nickname.


IMPORTANT NOTE: In a vanilla install of InspIRCd, there is no KILL message here for any collision scenario. However, it is possible that a third party module may deny the nickname change to UID, which will cause a last-resort Nickname collision KILL. Understandably, this is not a desirable situation, so care should be taken not to run such modules if this bothers you.

Message Routing

InspIRCd has four behaviours when it routes a message. These four behaviours are chosen dependent upon the message and the target and source of that message individually. These behaviours are:

One to One routing

This is used to route a message from one server directly to another server, taking a route only through servers which need to process the message in order to pass it straight to its destination. Examples of this are PRIVMSG and NOTICE direct to a user (not to a channel) and any messages exchanged during the initial burst and authentication phase.

Image:Insp-one-to-one.png

One to all (Broadcast)

This is used to broadcast a message to all servers, and each server which receives such a message will then pass it on to its peers using "one to all-but-one" as shown below. This is used for messages which the entire network must see to remain synchronized, e.g. NICK and QUIT.

Image:Insp-one-to-all.png

One to all-but-one

This is used to pass on a "one to all" message which has originated from another server. The message may not be passed on via a second "one to all" message, because doing so would bounce the message back along the network to its source and cause a desync.

Image:Insp-one-to-all-but-one.png

One to group

This is used only by channel PRIVMSG and NOTICE. To cut down on bandwidth, channel PRIVMSG and NOTICE are not broadcast. To achieve routing for these types of message, a list is compiled consisting only of locally connected servers the PRIVMSG or NOTICE must be sent to in order to reach all of its recipients. Each recipient is then responsible for running the message against this algorithm again to ensure it eventually reaches all intended recipients, and no extra servers which do not have users on the channel will receive the message or act upon it.

Image:Insp-one-to-group.png

Server Types

InspIRCd has three types of server. Although the same in design, and speaking the same protocol, their behaviours are different due to the roles they play in maintaining the network. These are:

Hubs

A hub is categorized as any server which has more than one locally connected server. A hub differs from normal operation in that the bandwidth passing through a hub is usually much greater than that passing through a leaf, and it may expend more computing power to run a hub.

Leafs

A leaf is categorized as any server which has only one, or no connected servers. A leaf does not have to route as much information as a hub (see above) but usually because of this is configured to hold many more clients as it has the spare computer power to hold the users.

U-Lines

A U lined server is usually a leaf server, however in InspIRCd, a hub may also be U lined. U lined servers have many extra privilages, which are required for example to operate a services server or similar. U lines must be individually configured on all servers to work, and all servers must be in agreement about the names of the U lined servers. If they are not in agreement, mode changes will be dropped and commands forbidden which should operate normally.

Timestamp Synchronization

Because the InspIRCd spanning tree protocol operates using timestamps based around the UNIX "epoch" value, you must ensure that all clocks are synchronized on your network. This is best done with ntpd or ntpdate. If you do not synchronize the clocks on your servers, you will find that timestamp calculations will exhibit strange results, and users will be randomly deopped in new channels.

The InspIRCd spanning tree protocol should build in a margain of error of up to ten minutes (600 seconds) for FJOINs to new channels only, so that upon the clocks being out of sync, new channels can still be created successfully.

Example Traffic

This is an example of a netburst and some random traffic between InspIRCd 1.2 and Atheme.

[28/08/2007 13:02:08] <- SERVER services.antarctic.com pass 0 00A :Atheme IRC Services
[28/08/2007 13:02:08] -> CAPAB START
[28/08/2007 13:02:08] -> CAPAB MODULES m_services_account.so
[28/08/2007 13:02:08] -> CAPAB CAPABILITIES :NICKMAX=32 HALFOP=1 CHANMAX=65 MAXMODES=20 IDENTMAX=12 MAXQUIT=255 MAXTOPIC=307 MAXKICK=255 MAXGECOS=128 MAXAWAY=200 IP6NATIVE=0 IP6SUPPORT=1 PROTOCOL=1200 PREFIX=(ohv)@%+ CHANMODES=b,k,l,MRimnpst
[28/08/2007 13:02:08] -> CAPAB END
[28/08/2007 13:02:08] -> SERVER penguin.omega.org.za pass 0 497 :Waddle World
[28/08/2007 13:02:08] <- :00A BURST
[28/08/2007 13:02:08] -> :497 BURST 1188302528
[28/08/2007 13:02:08] <- :00A VERSION :atheme-2.3. 00A dFljRn
[28/08/2007 13:02:08] <- :00A UID 00AAAAAAC 1188302525 ChanServ services.int services.int ChanServ +io 0.0.0.0 :Channel Services
[28/08/2007 13:02:08] <- :00AAAAAAC OPERTYPE Services
[28/08/2007 13:02:08] <- :00A UID 00AAAAAAF 1188302525 Global services.int services.int Global +io 0.0.0.0 :Network Announcements
[28/08/2007 13:02:08] <- :00AAAAAAF OPERTYPE Services
[28/08/2007 13:02:08] <- :00A UID 00AAAAAAE 1188302525 MemoServ services.int services.int MemoServ +io 0.0.0.0 :Memo Services
[28/08/2007 13:02:08] <- :00AAAAAAE OPERTYPE Services
[28/08/2007 13:02:08] <- :00A UID 00AAAAAAB 1188302525 NickServ services.int services.int NickServ +io 0.0.0.0 :Nickname Services
[28/08/2007 13:02:08] <- :00AAAAAAB OPERTYPE Services
[28/08/2007 13:02:08] <- :00A UID 00AAAAAAD 1188302525 OperServ services.int services.int OperServ +io 0.0.0.0 :Operator Services
[28/08/2007 13:02:08] <- :00AAAAAAD OPERTYPE Services
[28/08/2007 13:02:08] <- :00A PING :497
[28/08/2007 13:02:08] -> :497 VERSION :InspIRCd-1.2+HorriblyBroken penguin.omega.org.za :Linux emerald 2.6.22-10-generic [FLAGS=7935,epoll,497]
[28/08/2007 13:02:08] -> :497 UID 497AAAAAB 1188302517 w00t 127.0.0.1 127.0.0.1 w00t +s 127.0.0.1 :Robin Burchell
[28/08/2007 13:02:08] -> :497 FJOIN #test 1188302523 :@,497AAAAAB
[28/08/2007 13:02:08] -> :497 FMODE #test 1188302523 +nt
[28/08/2007 13:02:08] -> :497 ADDLINE Z 69.69.69.69 <Config> 1188302479 0 :No porn here thanks.
[28/08/2007 13:02:08] -> :497 ADDLINE Q ChanServ <Config> 1188302479 0 :Reserved For Services
[28/08/2007 13:02:08] -> :497 ADDLINE Q NickServ <Config> 1188302479 0 :Reserved For Services
[28/08/2007 13:02:08] -> :497 ADDLINE Q OperServ <Config> 1188302479 0 :Reserved For Services
[28/08/2007 13:02:08] -> :497 ADDLINE Q MemoServ <Config> 1188302479 0 :Reserved For Services
[28/08/2007 13:02:08] -> :497 ADDLINE E *@ircop.host.com <Config> 1188302479 0 :Opers hostname
[28/08/2007 13:02:08] -> :497 ENDBURST
[28/08/2007 13:02:08] -> :497 PONG 497
[28/08/2007 13:02:08] <- :00AAAAAAF NOTICE 497AAAAAB :Services are presently running in debug mode, attached to a console. You should take extra caution when utilizing your services passwords.
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB :***** NickServ Help *****
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB :Help for REGISTER:
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB : 
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB :This will register your current nickname with NickServ.
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB :This will allow you to assert some form of identity on
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB :the network and to be added to access lists. Furthermore,
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB :NickServ will warn users using your nick without
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB :identifying and allow you to kill ghosts.
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB :The password is a case-sensitive password that you make
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB :up. Please write down or memorize your password! You
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB :will need it later to change settings.
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB : 
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB :You may be required to confirm the email address. To do this,
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB :follow the instructions in the message sent to the email
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB :address.
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB : 
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB :Syntax: REGISTER <password> <email-address>
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB : 
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB :Examples:
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB :    /msg NickServ REGISTER bar foo@bar.com
[28/08/2007 13:03:16] <- :00AAAAAAB NOTICE 497AAAAAB :***** End of Help *****
[28/08/2007 13:03:23] -> :497AAAAAB PRIVMSG 00AAAAAAB :register foobar foo@bar.com
[28/08/2007 13:03:23] <- :00A METADATA 497AAAAAB accountname :w00t
[28/08/2007 13:03:23] <- :00AAAAAAB NOTICE 497AAAAAB :w00t is now registered to foo@bar.com.
[28/08/2007 13:03:23] <- :00AAAAAAB NOTICE 497AAAAAB :The password is foobar. Please write this down for future reference.