This site is deprecated; docs have moved to docs.inspircd.org!

Difference between revisions of "Historical:InspIRCd Spanning Tree (1.1)"

From the makers of InspIRCd.
Jump to: navigation, search
(BURST: Added information on timesync)
 
(61 intermediate revisions by 7 users not shown)
Line 3: Line 3:
 
This page will be expanded as we add to the protocol. Protocol changes will be generally backwards-compatible with previous versions (up to a point).
 
This page will be expanded as we add to the protocol. Protocol changes will be generally backwards-compatible with previous versions (up to a point).
  
Linking a server into an InspIRCd spanning tree is relatively straightforward for anyone who's handled irc servers and their protocols before. 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.
+
Linking a server into an InspIRCd spanning tree is relatively straightforward for anyone who's handled IRC servers and their protocols before. 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 ==
 
== 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).
+
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 ===
 
=== 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 SERVER command (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.
+
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 ===
 
=== Step Two - Inbound Authentication ===
Line 23: Line 26:
 
=== Step Four - Network Burst ===
 
=== Step Four - Network Burst ===
  
Upon receiving server A's network burst, server B also sends its own network burst, preceeded 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.
+
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:
 
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)
 
* 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 NICK, their OPERTYPE if they are an oper, and their channel list using FJOIN (see the commands list, below)
+
* Secondly, the nicknames of any users, sent using NICK, their OPERTYPE if they are an oper
* Thirdly, 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).
+
* 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).
 
* Lastly, any module specific data (which may be a combination of FMODE and any other module-specific commands).
  
Line 42: Line 45:
 
   
 
   
 
  (both servers now operate in duplex mode sending data freely)
 
  (both servers now operate in duplex mode sending data freely)
 +
 +
=== Challenge-Response and HMAC authentication (1.1.6 and above) ===
 +
 +
As of 1.1.6, InspIRCd supports [http://en.wikipedia.org/wiki/Challenge-response#Cryptographic_techniques challenge-response] [http://en.wikipedia.org/wiki/HMAC 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:
 +
 +
<pre>
 +
-> 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
 +
:Test server
 +
<- SERVER test.chatspike.net HMAC-SHA256:76a7d469c3dcab86067495d1b3407720fce9f7286400835baa2972e75e891a65 0
 +
:"Bollocks" Said pooh, as he caught his testicles in the vice.
 +
-> BURST 1176144272
 +
<- BURST 1176144273
 +
</pre>
 +
 +
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.
  
 
== Command List ==
 
== Command List ==
  
This section documents all valid server to server commands which are specific to InspIRCd. Most commands are similar or identical to RFC1459 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:
+
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:
  
 
  :<nickname> COMMAND <parameters>
 
  :<nickname> COMMAND <parameters>
Line 57: Line 112:
 
  :Craig MODE #chatspike +ov Brain Brain
 
  :Craig MODE #chatspike +ov Brain Brain
  
Where commands are part of the RFC, but their behaviour or their syntax is different, the commands are documented here in their InspIRCd form.
+
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 ===
 
=== Modular commands ===
  
Any module which implements a command, for example SAJOIN, will 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'''. This ensures transparent operation of modules on the spanning tree, independent of what tasks these modules perform. To load a module network wide, configuration files should be edited then then the modules introduced via ''/rehash *''. Examples of such modular commands are SAJOIN, SAPART, KNOCK, REMOVE, PARK.
+
Any module which implements a command, for example SAJOIN, will 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'''. This ensures transparent operation of modules on the spanning tree, independent of what tasks these modules perform. To load a module network wide, configuration files should be edited then then the modules introduced via ''/rehash *''. Examples of such modular commands are SAJOIN, SAPART, KNOCK, REMOVE.
 +
 
 +
Commands which return CMD_FAILURE are not propogated across the network. CMD_FAILURE and CMD_LOCALONLY results for a command should only be generated by the origin server if the intent is to prevent propogation of the command. An example of such a module is m_watch, which implements the command 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.
  
 
=== SERVER ===
 
=== SERVER ===
Line 83: Line 140:
 
  :<server> FJOIN <channel> <timestamp> :<[prefixes],nickname> {<[prefixes],nickname>}
 
  :<server> FJOIN <channel> <timestamp> :<[prefixes],nickname> {<[prefixes],nickname>}
  
This command is used within a netburst to syncronize 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:
+
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:
  
  :fudge.chatspike.net FJOIN #staff 1133630884 :@%,Brain @,Craig %,Dune +,Azhrarn w00t Elf
+
  :fudge.chatspike.net FJOIN #staff 1133630884 :@%,Brain @,Craig %,Dune +,Azhrarn ,w00t ,Elf
 +
 
 +
'''NB:''' The comma ',' is always part of the introduction of each user to the channel, even if that user has no status modes. A previous revision of these docs did not clearly indicate this, so please be aware of this fact.
  
 
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:
 
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:
Line 91: Line 150:
 
  :fudge.chatspike.net MODE #staff +ohohv Brain Brain Craig Dune Azhrarn
 
  :fudge.chatspike.net MODE #staff +ohohv Brain Brain Craig Dune Azhrarn
  
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''' status modes (+qaohv) from all users upon 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.
+
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.
 
+
The losing side should 'echo' out all mode removals as FMODE, so that all other servers are aware of the privilage modes being cleared.
+
  
 
For example, if server A sends this:
 
For example, if server A sends this:
Line 101: Line 158:
 
and server B sends this:
 
and server B sends this:
  
  :server.b FJOIN #staff 1234 :@,ol typobox43
+
  :server.b FJOIN #staff 1234 :@,ol ,typobox43
 
+
Then when server A receives the FJOIN from server B, it will deny giving ol ops, and server B will remove ops from ol, echoing out the following line:
+
  
:server.b FMODE #staff 1230 -o ol
+
Then when server A receives the FJOIN from server B, it will deny giving ol ops, and server B will remove ops from ol locally.
  
Doing things this way around means that it is not possible for a server to ignore its settings and allow netjoin abuse to occur. Note that the TS is updated before the FMODE lines are echoed, so that they are accepted by the rest of the network including the winning server.
 
  
 +
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 current implementation of the InspIRCd spanningtree protocol.
  
'''NB:''' In the current implementation, if one server has the channel empty, it will emulate an extremely high local timestamp on the empty channel (20 seconds ahead of current time) so that all mode changes will be automatically allowed by the remote server and will not be bounced. When a user is the first user in the channel, the current implementation will send an FJOIN instead of a JOIN to specify clearly that by joining the channel the user has been given ops. This is done for compatibility with services packages.
 
  
In the 1.1.x implementation, all other modes must be passed through [[InspIRCd Spanning Tree (1.1)#FMODE|FMODE]], therefore they are checked against timestamps anyway and this situation is prevented. 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.1.x implementation may receive multiple modes per user (in no defined order), and these modes may be core or module implemented prefixes, including the defaults of @+ and optionally %. The prefixes and the nickname for each user are seperated with a comma (,) and if the user has no prefixes associated with them, the prefix field is empty and the section starts with a comma, e.g. ",nickname". For example:
+
In the 1.1.x implementation, all other modes (exceptions, bans, simplemodes) must be passed through [[InspIRCd Spanning Tree (1.1)#FMODE|FMODE]], therefore they are checked against timestamps anyway and any potential for race conditions in modes, and mode abuse during burst is mitigated. 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.1.x implementation may receive multiple modes per user (in no defined order), and these modes may be core or module implemented prefixes, including the defaults of @+ and optionally %. The prefixes and the nickname for each user are separated with a comma (,) and if the user has no prefixes associated with them, the prefix field is empty and the section starts with a comma, e.g. ",nickname". For example:
  
 
  :server.name FJOIN #smelly 12345 :@%,whifty %,stinky +,larry ,moe +^,herbert
 
  :server.name FJOIN #smelly 12345 :@%,whifty %,stinky +,larry ,moe +^,herbert
Line 123: Line 177:
 
  :<server name> REMSTATUS <channel>
 
  :<server name> REMSTATUS <channel>
  
The REMSTATUS command, when sent, causes all status modes to be removed from all users on the given channel immediately. The receiving server should convert the REMSTATUS command into a group of FMODE and MODE lines (FMODE between servers, server MODE between server and client) and send them out, cancelling any status modes. Status modes are modes (usually with prefixes, but not always) which give permissions to users on channels. Currently, this is the modes +ov, +h (where enabled) and +aq (where loaded).
+
The REMSTATUS command, when sent, causes ''all modes'' to be removed from the given channel immediately. The receiving server should convert the REMSTATUS command into a group of FMODE and MODE lines (FMODE between servers, server MODE between server and client) and send them out, cancelling any modes.
  
 
Note that the REMSTATUS command itself should not be propogated to other servers -- instead, the receiving server should propogate the FMODE commands the REMSTATUS command causes.
 
Note that the REMSTATUS command itself should not be propogated to other servers -- instead, the receiving server should propogate the FMODE commands the REMSTATUS command causes.
  
 
'''NB:''' REMSTATUS will NOT lower (or change) the TS of the channel! If you want to do this, you must send an FJOIN first with a lower TS value.
 
'''NB:''' REMSTATUS will NOT lower (or change) the TS of the channel! If you want to do this, you must send an FJOIN first with a lower TS value.
 +
 +
=== MODE ===
 +
''(Broadcast)''
 +
 +
:<source server or nickname> MODE <target> <modes and parameters>
 +
 +
This is documented in this protocol document because previous versions of InspIRCd did not support MODE from a server origin. The latest 1.1 InspIRCd servers do support this, so the change is documented here.
 +
 +
=== OPERNOTICE ===
 +
''(Broadcast)''
 +
 +
:<source server> OPERNOTICE :<text>
 +
 +
This will cause all servers to send the given text to all opers with +s. This behaviour is duplicated by the command "MODENOTICE os", however OPERNOTICE is faster and consumes less bandwidth, as InspIRCd maintains an internal list of all opers with +s, whereas MODENOTICE has to compile this list based on the given modes for each MODENOTICE command individually. 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.
 +
 +
=== MODENOTICE ===
 +
''(Broadcast)''
 +
 +
:<source server> 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)''
 +
 +
:<source server> 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 ===
 
=== FMODE ===
Line 134: Line 216:
 
  :<source server or nickname> FMODE <target> <timestamp> <modes and parameters>
 
  :<source server or nickname> FMODE <target> <timestamp> <modes and parameters>
  
This command is used within a netburst (or sometimes after the burst) to syncronize modes on channels and users. For example:
+
This command is used within a netburst (or sometimes after the burst) to synchronize modes on channels and users. For example:
  
 
  :irc.mynet.org FMODE #opers 115432135 +bb *[email protected] *[email protected]
 
  :irc.mynet.org FMODE #opers 115432135 +bb *[email protected] *[email protected]
Line 140: Line 222:
 
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.
 
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.1 series servers should use FMODE for all mode changes where possible. It is sometimes not possible (e.g. when sending a mode change from a user origin) to use FMODE, as the TS merging rules could prevent parameterized modes such as +l from being set.'''
+
'''1.1 series servers should use FMODE for all mode changes where possible.'''
  
==== Mode-bouncing and FMODE TS rules ====
+
==== Mode-Merging and FMODE TS rules ====
  
 
The rules for bouncing and merging modes in FMODE are as follows:
 
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, the modes of both servers should be '''merged'''. This is done using the following algorithm:
+
*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.
  
<table style="left: +40px; position: relative" width="90%">
+
'''NB:''' This behaviour was changed in protocol revision 1104, previous versions implemented an over-complex bouncing algorithm which was prone to desyncs.
<tr><td>
+
*Modes being ''added'' without parameters are always accepted by both sides, building a complete set of both sets of modes
+
*Modes which have a parameter, but are not listmodes (e.g. not +o or +v) which are being ''added'' are merged based upon rules dependent on each mode letter. For example, the highest channel limit is accepted and the lower channel limit bounced, and the alphabetically later channel key accepted where the alphabetically earlier channel key bounced. The rules for this are fully documented below:
+
<table style="left: +40px; position: relative" width="90%">
+
<tr><td>
+
*+k (core): Highest value wins, alphabetically (case sensitive)
+
*+l (core): Highest value wins, numerically
+
*+L (module): Highest value wins, alphabetically
+
*+f (module): Highest value wins, case sensitive ASCII comparison
+
*+J (module): Highest  value wins, numerically
+
*+j (module): Highest value wins, case sensitive ASCII comparison
+
</td></tr>
+
</table>
+
*Modes being subtracted are always allowed, regardless of their parameters, as there are no restrictions on the ''removal'' of modes and therefore no desync can occur from doing this.
+
*Modules which implement modes will implement their own rulesets for their parameterized modes to determine which parameter wins when these modes are being ''added''.
+
*Modes which have been 'rejected' should be bounced back to their sending server using an FMODE with a server origin and the winning server's timestamp and parameter. Only the winning server is allowed to reject a mode character ('winning' is determined as stated above, via mode letter specific rulesets). These 'rejected' modes should not be unset, rather 'enforced'. So for example, if two servers have the timestamp '10', and server.a sends '+ntl 10' to server.b, and server.b already has the modes '+ntl 15' set, rather than sending '-l' back to server.a, server.b should send '+l 15' to server.a, so that then both servers remain synchronized.
+
</td></tr>
+
</table>
+
  
*If the timestamp given in an FMODE is '''higher''' than that of the receiving server, the receiving server will bounce the mode change back, using its own timestamp in the bounce, and forcing the mode to be unset. This prevents modehacking during desyncs and net merges. If the timestamp given in an FMODE is equal to, or less than that of the sending server, the receiving server will accept the mode without any bounce. When modes are bounced, the winning server is responsible for bouncing the modes of the losing server. It should examine each mode in turn and check wether it is applied on the winning server already. If it is, to avoid a desync the winning server should ''"reinforce"'' this mode by sending it back as set, otherwise if the mode is not set, it should be ''"inverted"'' (bounced) back at the source, unset. For example, imagine in the following scenario for a fictional channel #sprockets, for which server.a has modes "+ntlL 10 #chan1" and the lower TS of 1163355, and 'wins' against an FMODE sent to it from server.b, containing "-ntl+Lim #foo" with a TS of 1164466. The modes bounced back to server.b by server.a should therefore be:
+
=== OPERQUIT ===
 +
''(Broadcast)''
  
  :server.a FMODE #sprockets 1163355 +ntlL-im 10 #chan1
+
  :<source nickname> OPERQUIT :<oper only quit message>
  
*If the timestamp given in FMODE is '''lower''' than that of the receiving server, all modes should be accepted verbatim, but no TS modification should occur.
+
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.
  
==== Exceptions to the rules ====
+
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.
  
*There is one exception to this rule: If a ''U-Lined server'' sends an FMODE and the timestamp is higher than that of the receiving server, the FMODE will be accepted (Although, the receiving server will complain loudly to its opers) under the assumption that the U-line is '''always overriding and correct in all circumstances''' and that ''our'' clock is probably just incorrect.
+
'''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.
  
*When bouncing a mode sent by a user, the bounced modes must originate from the winning server, not from any user. e.g. use a server 'origin' at all times to bounce mode changes.
+
''This command is new to protocol version 1105 and should not be used on InspIRCd versions prior to this.''
 
+
*Please note that if the clocks on your servers are completely desynched, you could end up with servers fighting over mode changes. This is why it is imperative to keep your clocks synched correctly '''at all times'''.
+
 
+
*Please note that to prevent desyncs there is no checking of channel keys between servers or remote users. A channel key can be set whilst another key is already in place, or removed without providing the correct key. Some form of parameter must still be provided, however. To summarize; if server.a has the key "foo", server.b could send "FMODE #channel -k bar" and this would still be accepted and the key removed.
+
  
 
=== SQUIT ===
 
=== SQUIT ===
 
''(Broadcast)''
 
''(Broadcast)''
  
  :<local server> SQUIT <remote server> :<reason>
+
  :<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 will not and '''should 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/nickname> RSQUIT <server name> :<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. Seperate QUIT messages will not and '''should not''' be sent out for the exited users.
+
Upon receipt of this command, the local server should do one of two things. If the server given in <server name> is a locally-connected server, it should SQUIT it as if it had received a local SQUIT from the given <server/nickname> 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 <server name>. This allows routing of remote SQUITs without all other servers acting upon them until they reach their intended destination.
  
 
=== FTOPIC ===
 
=== FTOPIC ===
Line 196: Line 267:
 
  :<server/nickname> FTOPIC <channel> <time-set> <set-by> :<topic>
 
  :<server/nickname> FTOPIC <channel> <time-set> <set-by> :<topic>
  
This command is used during a network burst to syncronize 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.
+
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 ===
 
=== BURST ===
Line 218: Line 289:
 
  :<nickname> OPERTYPE <type name>
 
  :<nickname> OPERTYPE <type name>
  
This command indicates that the specified user is an IRC operator of the given type. The <type name> given should exist in the configurations of all servers on the network for the oper status to propogate. '''If oper status does not propogate, desyncs can occur.'''
+
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. The exception to this is u-lined servers, as u-lines are a core feature (there is no easy way around doing this) which permit all users with that server name in their record special abilities which negate the need for the +o flag.
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. The exception to this is u-lined servers, as u-lines are a core feature (there is no easy way around doing this) which permit all users with that server name in their record special abilities which negate the need for the +o flag.
+
  
 
=== REHASH ===
 
=== REHASH ===
Line 227: Line 297:
  
 
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.
 
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)''
 +
 +
:<nickname> 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 nickname issuing the command is an oper or not. The results are usually returned via PUSH.
  
 
=== NICK ===
 
=== NICK ===
Line 276: Line 353:
 
  :<source server> ADDLINE [Q|Z|E|G] <mask> <setter> <time set> <duration> :<reason>
 
  :<source server> ADDLINE [Q|Z|E|G] <mask> <setter> <time set> <duration> :<reason>
  
The ADDLINE command is used to (silently) set a GLINE, ZLINE, ELINE or QLINE. Whereas the GLINE, ZLINE, ELINE and QLINE commands can only be sent from a user source, and require that user to be online, ADDLINE may only be sent by a '''server''' (with a valid server name as the source), and the setter can be any arbitary text up to 64 characters in length (so it may be a nick which is not online, or a server name). Servers must use this command to sync Q, Z, E and G lines during a burst. After that point, users may add (or remove) G, Z, E and Q lines using the GLINE, ZLINE, ELINE and QLINE commands as documented below. The duration for ADDLINE may only be represented in seconds, and not the more complex form as shown for the other *LINE commands.
+
The ADDLINE command is used to (silently) set a GLINE, ZLINE, ELINE or QLINE. Whereas the GLINE, ZLINE, ELINE and QLINE commands can only be sent from a user source, and require that user to be online, ADDLINE may only be sent by a '''server''' (with a valid server name as the source), and 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). Servers must use this command to sync Q, Z, E and G lines during a burst. After that point, users may add (or remove) G, Z, E and Q lines using the GLINE, ZLINE, ELINE and QLINE commands as documented below. The duration for ADDLINE may only be represented in seconds, and not the more complex form as shown for the other *LINE commands.
  
 
=== GLINE ===
 
=== GLINE ===
Line 318: Line 395:
 
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.
 
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.
  
An SVSHOLD is virtually equivilant to a Q:Line, except that it is generally controlled by services, and is held seperate from Q:Lines. Commonly used for Services enforcers.
+
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.
 
'''NOTE:''' Requires m_svshold.so to be loaded.
Line 337: Line 414:
  
 
This command is implemented for services compatibility. When given it will force the given nick 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.
 
This command is implemented for services compatibility. When given it will force the given nick 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)''
 +
 +
:<source server> SVSPART <nick> <channel>
 +
 +
This command is implemented for services compatibility. When given it will force the given nick to part 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 ===
 
=== SVSMODE ===
 
''(Broadcast)''
 
''(Broadcast)''
  
  :<source nick> SVSMODE <nick> <channel>
+
  :<source nick> 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 client-side 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.
 
This command is implemented for services compatibility. When given it will allow modes to be set on users which are on remote servers, bypassing client-side 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.
Line 391: Line 475:
 
=== AES ===
 
=== AES ===
 
''(One-To-One)''
 
''(One-To-One)''
 +
 +
'''NOTE: This was removed in protocol version 1003, and is deprecated in favour of transport modules such as m_ssl_openssl and m_ssl_gnutls'''
  
 
  AES <server name>
 
  AES <server name>
Line 412: Line 498:
 
  CAPAB END
 
  CAPAB END
  
The capab command, if sent, must be sent in the authentication phase before any other command (including the optional AES command. If the server is listening for connections, then it must immediately send out this command as its 'banner'.
+
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.
 
Any server which ''does not understand'' the CAPAB command should silently ignore all CAPAB commands and their parameters.
Line 422: Line 508:
 
==== CAPAB MODULES ====
 
==== CAPAB MODULES ====
  
CAPAB MODULES should contain a comma seperated 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, seperating 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 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 ====
  
CAPAB CAPABILITIES should contain a space seperated 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.
+
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 =====
 
===== Valid CAPAB CAPABILITIES variables =====
Line 433: Line 519:
  
 
<center>
 
<center>
<table style="border: 1px solid black">
+
 
<tr><th width='25%'>Variable</th><th width='20%'>Required</th><th width='55%'>Description</th></tr>
+
{| style="border: 1px solid black"
<tr><td>PROTOCOL</td><td>Yes</td><td>The current protocol version.</td></tr>
+
|-----
<tr><td>NICKMAX</td><td>Yes</td><td>Maximum length of nicknames including \0</td></tr>
+
! width="'25%'" | Variable
<tr><td>HALFOP</td><td>No</td><td>Server supports halfop when defined and set to 1</td></tr>
+
! width="'20%'" | Required
<tr><td>CHANMAX</td><td>Yes</td><td>Maximum length of channel names including \0</td></tr>
+
! width="'55%'" | Description
<tr><td>MAXMODES</td><td>Yes</td><td>Maximum number of parameterized modes per MODE command</td></tr>
+
|-----
<tr><td>IDENTMAX</td><td>Yes</td><td>Maximum length of ident including "~" symbol and \0</td></tr>
+
| PROTOCOL || Yes
<tr><td>MAXQUIT</td><td>Yes</td><td>Maximum length of quitmessage including \0</td></tr>
+
| The current protocol version.<br>[[List of protocol changes between versions]]
<tr><td>MAXTOPIC</td><td>Yes</td><td>Maximum length of channel topics including \0</td></tr>
+
|-----
<tr><td>MAXKICK</td><td>Yes</td><td>Maximum length of channel kick message including \0</td></tr>
+
| NICKMAX || Yes
<tr><td>MAXGECOS</td><td>Yes</td><td>Maximum length of full name field (GECOS)</td></tr>
+
| Maximum length of nicknames including \0
<tr><td>MAXAWAY</td><td>Yes</td><td>Maximum length of away messages including \0</td></tr>
+
|-----
<tr><td>IP6NATIVE</td><td>No</td><td>If this is set, IP6SUPPORT will exist and be set. Signifies this server is IPV6 native</td></tr>
+
| HALFOP || No
<tr><td>IP6SUPPORT</td><td>No</td><td>If this is set, this server can handle users, bans etc which are in IPV6 form</td></tr>
+
| Server supports halfop when defined and set to 1
</table>
+
|-----
 +
| 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 [http://www.irc.org/tech_docs/005.html RPL_ISUPPORT] format
 +
|-----
 +
| CHANMODES || No
 +
| List channel modes in 005-numeric [http://www.irc.org/tech_docs/005.html RPL_ISUPPORT] format
 +
|}
 
</center>
 
</center>
  
Line 461: Line 583:
 
  CAPAB START
 
  CAPAB START
 
  CAPAB CAPABILITIES :NICKMAX=32 HALFOP=1 CHANMAX=65 MAXMODES=20 IDENTMAX=12 MAXQUIT=255
 
  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=1100
+
  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_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_globops.so,m_httpd.so,m_httpd_stats.so,m_inviteexception.so,m_joinflood.so
Line 479: Line 601:
  
 
'''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 'liveliness' checks on 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 'liveliness' checks on the connection.
 +
'''NB''': Please note that the long form of PONG uses the same string as last parameter as used in PING. This allows to identify pairs of PING/PONG.
  
 
== Message Routing ==
 
== Message Routing ==
Line 488: Line 611:
 
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.
 
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.
  
<center>[[Image:insp-one-to-one.png]]</center>
+
<center>[[Image:Insp-one-to-one.png]]</center>
  
 
=== One to all (Broadcast) ===
 
=== One to all (Broadcast) ===
Line 494: Line 617:
 
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.
 
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.
  
<center>[[Image:insp-one-to-all.png]]</center>
+
<center>[[Image:Insp-one-to-all.png]]</center>
  
 
=== One to all-but-one ===
 
=== One to all-but-one ===
Line 500: Line 623:
 
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.
 
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.
  
<center>[[Image:insp-one-to-all-but-one.png]]</center>
+
<center>[[Image:Insp-one-to-all-but-one.png]]</center>
  
 
=== One to group ===
 
=== One to group ===
Line 506: Line 629:
 
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.
 
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.
  
<center>[[Image:insp-one-to-group.png]]</center>
+
<center>[[Image:Insp-one-to-group.png]]</center>
  
 
== Server Types ==
 
== Server Types ==
Line 522: Line 645:
 
=== U-Lines ===
 
=== 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.
+
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 privileges, 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 Syncronization ==
+
== 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.
 
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.

Latest revision as of 09:32, 21 May 2015


This page will be expanded as we add to the protocol. Protocol changes will be generally backwards-compatible with previous versions (up to a point).

Linking a server into an InspIRCd spanning tree is relatively straightforward for anyone who's handled IRC servers and their protocols before. 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 NICK, 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:

>> SERVER services-dev.chatspike.net password 0 :Description here
<< SERVER test.chatspike.net password 0 :ChatSpike InspIRCd test server
>> BURST
<< BURST

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

Challenge-Response and HMAC authentication (1.1.6 and above)

As of 1.1.6, InspIRCd supports 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 
:Test server
<- SERVER test.chatspike.net HMAC-SHA256:76a7d469c3dcab86067495d1b3407720fce9f7286400835baa2972e75e891a65 0 
:"Bollocks" Said pooh, as he caught his testicles in the vice.
-> BURST 1176144272
<- 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.

Command List

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:

:<nickname> COMMAND <parameters>

For example:

:Brain PRIVMSG #chatspike :Moo moo!

or,

:Craig MODE #chatspike +ov Brain Brain

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, will 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. This ensures transparent operation of modules on the spanning tree, independent of what tasks these modules perform. To load a module network wide, configuration files should be edited then then the modules introduced via /rehash *. Examples of such modular commands are SAJOIN, SAPART, KNOCK, REMOVE.

Commands which return CMD_FAILURE are not propogated across the network. CMD_FAILURE and CMD_LOCALONLY results for a command should only be generated by the origin server if the intent is to prevent propogation of the command. An example of such a module is m_watch, which implements the command 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.

SERVER

(Broadcast, One-To-One)

SERVER <servername> <password> <hopcount> :<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 :<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> SERVER <remote server> * <distance> :<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.

FJOIN

(Broadcast)

:<server> FJOIN <channel> <timestamp> :<[prefixes],nickname> {<[prefixes],nickname>}

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:

:fudge.chatspike.net FJOIN #staff 1133630884 :@%,Brain @,Craig %,Dune +,Azhrarn ,w00t ,Elf

NB: The comma ',' is always part of the introduction of each user to the channel, even if that user has no status modes. A previous revision of these docs did not clearly indicate this, so please be aware of this fact.

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:

:fudge.chatspike.net MODE #staff +ohohv Brain Brain Craig Dune Azhrarn

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:

:server.a FJOIN #staff 1230 :@,Brain @,Craig

and server B sends this:

:server.b FJOIN #staff 1234 :@,ol ,typobox43

Then when server A receives the FJOIN from server B, it will deny giving ol ops, and server B will remove ops from ol locally.


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 current implementation of the InspIRCd spanningtree protocol.


In the 1.1.x implementation, all other modes (exceptions, bans, simplemodes) 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. 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.1.x implementation may receive multiple modes per user (in no defined order), and these modes may be core or module implemented prefixes, including the defaults of @+ and optionally %. The prefixes and the nickname for each user are separated with a comma (,) and if the user has no prefixes associated with them, the prefix field is empty and the section starts with a comma, e.g. ",nickname". For example:

:server.name FJOIN #smelly 12345 :@%,whifty %,stinky +,larry ,moe +^,herbert

If a server ever receives a prefix which it does not recognise, for example the ^ symbol 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.

REMSTATUS

(Broadcast, special (see notes))

:<server name> REMSTATUS <channel>

The REMSTATUS command, when sent, causes all modes to be removed from the given channel immediately. The receiving server should convert the REMSTATUS command into a group of FMODE and MODE lines (FMODE between servers, server MODE between server and client) and send them out, cancelling any modes.

Note that the REMSTATUS command itself should not be propogated to other servers -- instead, the receiving server should propogate the FMODE commands the REMSTATUS command causes.

NB: REMSTATUS will NOT lower (or change) the TS of the channel! If you want to do this, you must send an FJOIN first with a lower TS value.

MODE

(Broadcast)

:<source server or nickname> MODE <target> <modes and parameters>

This is documented in this protocol document because previous versions of InspIRCd did not support MODE from a server origin. The latest 1.1 InspIRCd servers do support this, so the change is documented here.

OPERNOTICE

(Broadcast)

:<source server> OPERNOTICE :<text>

This will cause all servers to send the given text to all opers with +s. This behaviour is duplicated by the command "MODENOTICE os", however OPERNOTICE is faster and consumes less bandwidth, as InspIRCd maintains an internal list of all opers with +s, whereas MODENOTICE has to compile this list based on the given modes for each MODENOTICE command individually. 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.

MODENOTICE

(Broadcast)

:<source server> 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)

:<source server> 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)

:<source server or nickname> 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:

:irc.mynet.org FMODE #opers 115432135 +bb *[email protected] *[email protected]

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.1 series servers should use FMODE for all mode changes where possible.

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: This behaviour was changed in protocol revision 1104, previous versions implemented an over-complex bouncing algorithm which was prone to desyncs.

OPERQUIT

(Broadcast)

:<source nickname> 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 will not and should 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/nickname> RSQUIT <server name> :<reason>

Upon receipt of this command, the local server should do one of two things. If the server given in <server name> is a locally-connected server, it should SQUIT it as if it had received a local SQUIT from the given <server/nickname> 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 <server name>. This allows routing of remote SQUITs without all other servers acting upon them until they reach their intended destination.

FTOPIC

(Broadcast)

:<server/nickname> 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)

BURST {timestamp}
BURST <timestamp> FORCE

This command indicates the start of the network burst. It should only be sent when the network burst is local to indicate the end of the authentication phase (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.

ENDBURST

(One-To-One)

ENDBURST

This command indicates the end of the network burst. this should always be sent at the end of a network burst. The receiving server should usually apply z/k/q/g lines upon receipt of the ENDBURST command, rather than as it receives each one, saving on cpu time.

OPERTYPE

(Broadcast)

:<nickname> 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. The exception to this is u-lined servers, as u-lines are a core feature (there is no easy way around doing this) which permit all users with that server name in their record special abilities which negate the need for the +o flag.

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)

:<nickname> 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 nickname issuing the command is an oper or not. The results are usually returned via PUSH.

NICK

(Broadcast)

:<local server> NICK <timestamp> <nick> <hostname> <displayed-hostname> <ident> +<modes> <ip> :<gecos>
:<old nick> NICK <new nick>

The first version of this command introduces a new client into the network. If there is a nickname collision, the remote server you send the NICK command to is responsible for generating a KILL message and sending it back to you. The ip field is in dotted decimal form, e.g. 1.2.3.4.

The second version of this command changes an existing user's nickname, as in the RFC.

JOIN

(Broadcast)

:<nickname> 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 is handled by the 8-parameter version of the NICK message.

VERSION

(Broadcast, One-To-One)

:<source server> 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)

:<nickname> 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)

:<nickname> 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)

:<source server> ADDLINE [Q|Z|E|G] <mask> <setter> 

The ADDLINE command is used to (silently) set a GLINE, ZLINE, ELINE or QLINE. Whereas the GLINE, ZLINE, ELINE and QLINE commands can only be sent from a user source, and require that user to be online, ADDLINE may only be sent by a server (with a valid server name as the source), and 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). Servers must use this command to sync Q, Z, E and G lines during a burst. After that point, users may add (or remove) G, Z, E and Q lines using the GLINE, ZLINE, ELINE and QLINE commands as documented below. The duration for ADDLINE may only be represented in seconds, and not the more complex form as shown for the other *LINE commands.

GLINE

(Broadcast)

:<source nickname> GLINE <[email protected]> <duration> :<reason>
:<source nickname> GLINE <[email protected]>

This command sets or removes a GLINE (the first syntax given is to add, the second to remove) and is passed on to servers exactly as it is formatted in our client Commands guide. 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 (as in ADDLINE)

ELINE

(Broadcast)

:<source nickname> ELINE <[email protected]> <duration> :<reason>
:<source nickname> ELINE <[email protected]>

This command sets or removes a ELINE (the first syntax given is to add, the second to remove) and is passed on to servers exactly as it is formatted in our client Commands guide. 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 (as in ADDLINE)

ZLINE

(Broadcast)

:<source nickname> ZLINE <ipmask> <duration> :<reason>
:<source nickname> ZLINE <ipmask>

This command sets or removes a ZLINE (the first syntax given is to add, the second to remove) and is passed on to servers exactly as it is formatted in our client Commands guide. 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 (as in ADDLINE)

QLINE

(Broadcast)

:<source nickname> QLINE <nickmask> <duration> :<reason>
:<source nickname> QLINE <nickmask>

This command sets or removes a QLINE (the first syntax given is to add, the second to remove) and is passed on to servers exactly as it is formatted in our client Commands guide. 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 (as in ADDLINE)

SVSHOLD

(Broadcast)

:<source nickname> SVSHOLD <nickname> <duration> :<reason>
:<source nickname> 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.

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)

:<source server> SVSNICK <old nick> <new nick> <timestamp>

This command is implemented for services compatibility. When given it will change the user <old nick>'s nick to have the nickname <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 never sent out by InspIRCd servers directly, however it is forwarded from services servers, and should therefore be supported.

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 allows for services servers to wait for confirmation that the user changed nick, or collided, before actually introducing enforcers.

SVSJOIN

(Broadcast)

:<source server> SVSJOIN <nick> <channel>

This command is implemented for services compatibility. When given it will force the given nick 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)

:<source server> SVSPART <nick> <channel>

This command is implemented for services compatibility. When given it will force the given nick to part 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)

:<source nick> 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 client-side 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)

:<source server> METADATA <channel|user> <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)

:<source nick> IDLE <target nick>
:<source nick> IDLE <target nick> <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 <source nick> field and the user being whois'ed is placed into the <target nick> 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 nick> field, and the user that issued the WHOIS is placed in the <target nick> field, along with the signon time and idle time of the source nickname. 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)

:<source server> PUSH <target nick> :<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 file descriptor. 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)

:<source server> TIME <target server> <issuing nick>
:<source server> TIME <target server> <issuing nick> <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 <issuing nick>. 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 <source server> 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 <issuing nick> in the same manner as a local TIME request.

TIMESET

(Broadcast)

:<source server> TIMESET <timestamp>
:<source server> 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.

AES

(One-To-One)

NOTE: This was removed in protocol version 1003, and is deprecated in favour of transport modules such as m_ssl_openssl and m_ssl_gnutls

AES <server name>

Upon connection, servers which are of version 1.0 RC1 or later may negotiate optional AES encryption. When doing so, the connecting server will send this command before the SERVER and BURST command, but after any CAPAB commands (see below) and any commands following the AES command (including the SERVER command and the netburst) will be encrypted using AES, wrapping each encrypted line in base64 before transit. Both ends of the connection are expected to have a shared private key which is used to encrypt and decrypt the session. If the session cannot be decrypted, no authenticated connection can be made.

It is possible to send the AES message after negotiation of the server link, however this is not supported by current versions of InspIRCd. If the AES message is sent more than once in a single session, the second (and any other) AES commands will be dropped and an error given.

Encryption strengths of 128, 192 and 256 bits are currently allowed, using key lengths of 16, 24 or 32 bytes respectively with the CBC cipher.

WARNING: While in AES mode, lines sent over the link may exceed 512 bytes! Because messages must be padded to the nearest block size, where a block is equal to the key size, the encrypted payload may be up to 543 characters in length (512 plus the maximum modulus of 31 for the largest permitted key length). Also, the base64 encoded payload, which wraps the encrypted payload will further increase its size by up to 20%, making messages be as long as potentially 750 bytes! Because InspIRCd itself uses the C++ std::string class, the actual length of the message is not important as a buffer overflow cannot occur in any practical situation.

When the connect is running in AES encrypted mode, a certain subset of commands may be allowed along the link unencrypted so that the network is still able to understand them in the event of an encryption failure. Currently, the most recent version of InspIRCd only allows the ERROR command to pass along the link in this manner.

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)

:<source server> PING <destination-data>
:<source server> PONG <destination-data>
:<source> PING <source server> :<destination server>
:<source> PONG <source server> :<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 PONG reply are not important, however most InspIRCd servers 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 minutes, the remote server should close your 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 'liveliness' checks on the connection. NB: Please note that the long form of PONG uses the same string as last parameter as used in PING. This allows to identify pairs of PING/PONG.

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.

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.

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.

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.

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 privileges, 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.1.0 and IRCServices, running the newer IRCServices module, which is shown here to aid those wanting to see first hand how InspIRCd behaves when sent certain commands, etc.

This example shows a connection to a test network with two connectable servers and a services server:

[09:31] --- test2.chatspike.net
[09:31] --- `-test.chatspike.net
[09:31] ---   `-services-dev.chatspike.net
[09:31] --- End of /MAP
Initiated connection to 10.0.0.1:7000
Received: CAPAB START
Received: CAPAB CAPABILITIES :NICKMAX=32 HALFOP=1 CHANMAX=65 MAXMODES=20 IDENTMAX=12 MAXQUIT=255
Received: CAPAB CAPABILITIES :MAXTOPIC=307 MAXKICK=255 MAXGECOS=128 MAXAWAY=200 IP6NATIVE=0 IP6SUPPORT=1 PROTOCOL=1100
Received: CAPAB MODULES m_banexception.so,m_blockcolor.so,m_botmode.so,m_censor.so,m_chanfilter.so,m_chanprotect.so,m_cloaking.so
Received: CAPAB MODULES m_globops.so,m_httpd.so,m_httpd_stats.so,m_inviteexception.so,m_joinflood.so
Received: 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
Received: CAPAB MODULES m_redirect.so,m_services.so,m_spanningtree.so,m_stripcolor.so,m_testcommand.so,m_tline.so,m_uninvite.so
Received: CAPAB END
Sent: SERVER services-dev.chatspike.net password 0 :IRCServices test server
Sent: BURST 1133994664
Sent: :services-dev.chatspike.net VERSION :ircservices-5.0.56 services-dev.chatspike.net :build #26, compiled Wed Dec  7 11:31:19 GMT 2005
Sent: :services-dev.chatspike.net NICK 1133994664 OperServ chatspike.net chatspike.net services +oi 0.0.0.0 :Operator Server
Sent: :services-dev.chatspike.net NICK 1133994664 Global chatspike.net chatspike.net services +oi 0.0.0.0 :Global Noticer
Sent: :services-dev.chatspike.net NICK 1133994664 NickServ chatspike.net chatspike.net services +oi 0.0.0.0 :Nickname Server
Sent: :services-dev.chatspike.net NICK 1133994664 ChanServ chatspike.net chatspike.net services +oi 0.0.0.0 :Channel Server
Sent: :services-dev.chatspike.net NICK 1133994664 MemoServ chatspike.net chatspike.net services +oi 0.0.0.0 :Memo Server
Sent: :services-dev.chatspike.net NICK 1133994664 StatServ chatspike.net chatspike.net services +i 0.0.0.0 :Statistics Server
Sent: :services-dev.chatspike.net NICK 1133994664 HelpServ chatspike.net chatspike.net services +i 0.0.0.0 :Help Server
Sent: :services-dev.chatspike.net NICK 1133994664 DevNull chatspike.net chatspike.net services +i 0.0.0.0 :/dev/null -- message sink
Sent: :services-dev.chatspike.net ADDLINE G [email protected] Brain 1133994664 0 :You are banned from this network
Received: SERVER test.chatspike.net password 0 :ChatSpike InspIRCd test server
Received: BURST 1133994664
Received: :test.chatspike.net VERSION :InspIRCd-1.1.0+SVN(r5000) test.chatspike.net :FreeBSD neuron.brainbox.winbot.co.uk 5.4-RELEASE [FLAGS=0,kqueue,singlethread-object]
Received: :test.chatspike.net SERVER test2.chatspike.net * 1 :Second server
Received: :test2.chatspike.net VERSION :InspIRCd-1.1.0+SVN(r5000) test2.chatspike.net :Linux brainwave 2.6.12-gentoo-r6 [FLAGS=0,epoll,singlethread-object]
Received: :test.chatspike.net NICK 1133992412 Brain synapse.brainbox.winbot.co.uk netadmin.chatspike.net ~brain +xwsioS 10.0.0.2 :Craig Edwards
Sent: :NickServ SVSMODE Brain :-r
Sent: :NickServ NOTICE Brain :This nickname is registered and protected.  If it is your nickname, type /msg NickServ IDENTIFY password.  Otherwise, please choose a different nickname.
Sent: :OperServ GLOBOPS :Brain is now an IRC operator.
Received: :Brain OPERTYPE NetAdmin
Received: :test.chatspike.net METADATA Brain swhois :blah blah test blah
Received: :test2.chatspike.net NICK 1133992705 Brain2 127.0.0.1 0284D4C2C220AFC6.Blah.cloak ~brain +xwsi 127.0.0.1 :Craig Edwards
Received: :test.chatspike.net NICK 1133992510 w00teh my.fart.made.an.eternalstorm.org InspIRCd-Testnet-0893F385B1545E74.fart.made.an.eternalstorm.org ~w00t +x 66.111.40.128 :Robin Burchell
Received: :test.chatspike.net NICK 1133992412 DesktopOm wlupton.gotadsl.co.uk netadmin.chatspike.net ~om +xwsioS 81.6.252.165 :><(((\uffff\uffff>
Sent: :NickServ SVSMODE DesktopOm :-r
Sent: :NickServ NOTICE DesktopOm :This nickname is registered and protected.  If it is your nickname, type /msg NickServ IDENTIFY password.  Otherwise, please choose a different nickname.
Sent: :OperServ GLOBOPS :DesktopOm is now an IRC operator.
Received: :DesktopOm OPERTYPE NetAdmin
Received: :test.chatspike.net NICK 1133992598 Ghost hack.fi InspIRCd-Testnet-9204BC848FC84F28.fi ~Ghost +x 83.145.201.47 :Ghost
Received: :test.chatspike.net NICK 1133992430 Cyan 69.90.46.135 67B46DBE20695D01.InspIRCd-Testnet.cloak ~cyan +xiw 69.90.46.135 :Cyan Garamonde
Received: :test.chatspike.net NICK 1133992409 Omster wlupton.gotadsl.co.uk InspIRCd-Testnet-BD9CEF261F514F7B.gotadsl.co.uk ~om +xwsi 81.6.252.165 :Mr. Tiddles
Received: :test.chatspike.net FJOIN #test 1133992411 :,Omster ,Brain ,DesktopOm ,Cyan ,w00teh ,Ghost ,Brain2
Sent: :services-dev.chatspike.net FTOPIC #test 1133865017 Ghost :This is a test server. Support network at irc.inspircd.org -- Yes, this ircd package will eventually replace unreal on ChatSpike | Pwnd by Ghost
Received: :test.chatspike.net FMODE #test 1133994664 +ntr
Received: :test.chatspike.net FTOPIC #test 1133865017 Ghost :This is a test server. Support network at irc.inspircd.org -- Yes, this ircd package will eventually replace unreal on ChatSpike | Pwnd by Ghost
Received: :test.chatspike.net ADDLINE Z 66.66.66.66 <Config> 1133992407 0 :This is the devils ip. You cannot use it.
Received: :test.chatspike.net ADDLINE Z 69.69.69.69 <Config> 1133992705 0 :No porn here thanks.
Received: :test.chatspike.net ADDLINE Q *[rxHO]* <Config> 1133992407 0 :Script kiddiot.
Received: :test.chatspike.net ADDLINE Q ChanServ <Config> 1133992705 0 :Reserved For Services
Received: :test.chatspike.net ADDLINE Q NickServ <Config> 1133992705 0 :Reserved For Services
Received: :test.chatspike.net ADDLINE Q OperServ <Config> 1133992705 0 :Reserved For Services
Received: :test.chatspike.net ADDLINE Q MemoServ <Config> 1133992705 0 :Reserved For Services
Received: :test.chatspike.net ADDLINE G [email protected] Brain 1133992727 0 :You are banned from this network
Received: :test.chatspike.net ADDLINE E *@ircop.host.com <Config> 1133992705 0 :Opers hostname
Received: ENDBURST
Sent: :ChanServ MODE #test +ntr
Received: :Brain PRIVMSG NickServ : identify xxxxxxx
Sent: :NickServ NOTICE Brain :Password incorrect.
Received: :test.chatspike.net PING services-dev.chatspike.net
Sent: :services-dev.chatspike.net PONG services-dev.chatspike.net services-dev.chatspike.net