How To Add IRCd Support ----------------------- 1) Files to Edit 2) The Code 3) The IRCDVar struct 4) Modes 5) Functions / Events 6) CAPAB/PROTOCTL 7) IRCDProto Class 1) Files to Edit When preparing to add supprt to Anope for your IRCd, you need to edit the following files A) Make a copy of the .cpp file of the IRCd that matches the IRCd that you are attempting to add support for best. B) Add your IRCd into the supported IRCds in example.conf 2) The Code Here is where the code of the .cpp file comes in. Be prepared to spend at least an hour, if not longer, going over the code and getting it right; Especially if you are setting up an ircd that is completely different than the one you used as a base. This section covers the majority of the code that is in use. The first bit of code you will face is the IRCDVar structure, which is explained in depth in the next section. Scroll down to the bottom and find the class for this module and rename it to something reflecting your IRCd name. Find the function: pmodule_ircd_version("Unreal 3.2+"); This is the protocol name which will appear in various places; especially when you do -version at the command prompt, this is where you state the server name. The version is not always needed unless you are showing that the support is for one branch of a ircd family, such as Unreal 3.1 and Unreal 3.2. The next task that you will face is setting whether the IRCD sends time stamps on modes but does not tell us that it will do so. If it does, set UseTSMODE to 1; if it does not set it to be 0. If you're not sure refer to your IRCd's documentation on how MODE is sent. pmodule_ircd_useTSMode(0); 3) The IRCDVar struct Now you've come to the part where you setup your ircd. There are two structs which hold this information; This allows you to quickly setup your specific ircd. IRCDVar myIrcd[] = { }; This struct contains your basic IRCd functions. Your base source file has the list of all available variables; note that you should not swap any around, or you will break stuff. Here is a brief description of the usage of each. 1) Name: This member tells Anope about the IRCD's name. It may contain text about it's name and version. This is used to identify the build on startup. 2) Pseudo Client Mode: This is the user mode set by Anope on all BotServ bots. Normally you want this to be a some form of service or bot flag; you can use + for no mode at all. 3) Max Channelmode Symbols: This is the total number of possible channel modes that can appear before a nick. Do remember to count each possible mode, so +ov is 2. 4) Channelmode for bots: When a BotServ bot joins a channel, this is the mode set on them. Normally you will want them opped (+o), and protected (+a) on IRCd's that support it. 5) SVSNICK: Can the ircd use SVSNICK to change some ones nick? Otherwise, KILL is used. Use 1 for yes, 0 for no. 6) VHOST: Can a user's host be changed on the fly? Enabling this allow HostServ online. Use 1 for yes, 0 for no. 7) SGLINE: Does the IRCd support realname (geocs) bans? Use 1 for yes, 0 for no. 8) SQLINE: Does the IRCd support nick bans? Use 1 for yes, 0 for no. 9) SZLINE: Does the IRCd support SZLINES? Use 1 for yes, 0 for no. 10) Number of Server Args: When an IRCd connects, this is the number of parameters that are passed. 11) Join to Set: Services must join a channel to set any modes on that channel. Use 1 for yes, 0 for no. 12) Join to Message: Services must join a channel to send any message to that channel (cannot override +n). Use 1 for yes, 0 for no. 13) TS Topic Forward: Some IRCd's (like UnrealIRCd) like their topic TS set forward by +1. Use 1 for yes, 0 for no. 14) TS Topic Backward: Some IRCd's (mainly older DreamForge-like ones) like their topic TS set back by -1. Use 1 for yes, 0 for no. 15) SQline Channels: The IRCd's supports banning channel names via SQLINES. Use 1 for yes, 0 for no. 16) Quit On Kill: When we (SVS)KILL a user, does the IRCd send back a QUIT message for that user? Use 1 for yes, 0 for no. 17) SVSMODE -b: We can use SVSMODE to unban hosts from a channel. Use 1 for yes, 0 for no. 18) Reverse: We can do a reverse check when unbanning. For use with DreamForge based IRCd's. Use 1 for yes, 0 for no. 19) vIdent: Support for including a user's ident in their vHost. Use 1 for yes, 0 for no. 20) SVSHOLD: Support for temporarily 'holding' a nick, instead of using a nick enforcer client. Use 1 for yes, 0 for no. 21) TS on MODE: We need to send a timestamp when modes are being changed. Use 1 for yes, 0 for no. 22) NICKIP: The IP address of new users is being sent along with their hostname when new users are being introduced on the network. Use 1 for yes, 0 for no. 23) OMODE: We can use OperServ to give some user a temporary O:LINE. Use 1 for yes, 0 for no. 24) Umode: We can use OperServ to change a user's mode. Use 1 for yes, 0 for no. 25) Vhost On Nick: On NICK the IRCd sends the VHOST. Use 1 for yes, 0 for no. 26) Change Realname: Change real name. Use 1 for yes, 0 for no. 27) Check Nick ID: Should we check if a user should remain identified when changing their nick? This is for IRCd's that remove their registered-user mode when someone changes their nick (like Bahamut does). Use 1 for yes, 0 for no. 28) No Knock Requires +i: Does the No Knock channel mode require invite only channels? Use 1 for yes, 0 for no. 29) Chan Modes: If sent in CAPAB/PROTOCOL, we store it in here. This is NULL by default. 30) Tokens: Can we use tokens to talk to the IRCd? Use 1 for yes, 0 for no. 31) base64 SJOIN TS: Are the timestamps sent with a SJOIN in base64? Use 1 for yes, 0 for no. 32) SJOIN Ban Char: Character used to identify bans. Use ''. 33) SJOIN Except Char: Character used to identify exceptions. Use ''. 34) SJOIN Invite char: Character used to idenfity invexs. Use ''. 35) SVSMODE UCMODE: Can we clear user channel modes with SVSMODE? Use 1 for yes, 0 for no. 36) SGline Enforce: Does the IRCd enforce SGLINES for us or do we need to do so? Use 1 for yes, 0 for no. 37) Vhost Character: The character used to represent the vHost mode, if this is supported by the IRCd. 38) TS6: Does the IRCd support TS6? Use 1 for yes, 0 for no. 39) P10: Is this IRCd a P10-style IRCd? Use 1 for yes, 0 for no. 40) Character Set: Unreal passes the character set during PROTOCTL, the value is stored here. Set this NULL to start. 41) Channel CIDR: Set to 1 if channel bans, excepts and invites support CIDR masks. Expected syntax: *!*@ip/mask. When set to 1, anope will only parse strict CIDR masks. IRCd's that try to correct invalid CIDR's (like nefarious) will need a custom implementation in the core. Contact the anope Dev Team if this is the case. Set to 0 if CIDR's are not supported by your IRCd. 42) Global TLD Prefix: Prefix used to send global messages, should probably be "$" 43) Max Modes: The max number of mode changes we can send in one line 4) Modes Anope is told about modes in the moduleAddModes() function. For the most part, the syntax for adding channel and user modes are: ModeManager::AddUserMode(new UserMode(UMODE_NETADMIN, 'N')); Where 'N' is the char for the mode, and UMODE_NETADMIN shows what the mode does. Or: ModeManager::AddChannelMode(new ChannelMode(CMODE_BLOCKCOLOR, 'c')); Where 'c' is the char for the mode and CMODE_BLOCKCOLOR shows what the mode does A full list of valid mode names for the second param can be found in services.h in the enum for ChannelModeName and UserModeName If necessary, you can add additional modes to this list. Adding simple modes with parameters is similar, instead adding a 'new ChannelMode', use 'new ChannelModeParam', set the third optional arg of ChannelModeParam to false if the param should NOT be sent when unsetting it. Eg: ModeManager::AddChannelMode(new ChannelModeParam(CMODE_JOINFLOOD, 'j', true)); Anope will internally track the params, and they can be retrieved through Channel::GetParam(); If you want to make param validity checking for a mode, you must create a new class which inherits from ChannelModeParam and overload the IsValid function. Modes CMODE_OPERONLY, CMODE_ADMINONLY, and CMODE_REGISTERED already exist internally as classes, to overload the CanSet function to disable non opers from mlocking (or in CMODE_REGISTERED's case, anyone) from setting them. This should be added like: ModeManager::AddChannelMode(new ChannelModeOper('O')); The CMODE_FLOOD param also has its own class, but due to the wide range of valid parameters accepted across IRCds, your protocol module MUST have the IsValid function for this. bool ChannelModeFlood::IsValid(const std::string &value) { } 5) Functions and Events A brief word about functions and events. All events are captured using: void moduleAddIRCDMsgs(void) { m = createMessage("NICK", anope_event_nick); addCoreMessage(IRCD,m); } Each event should have a event handler if its important enough to be processed by services. All event functions should be formed like this: int anope_event_capab(char *source, int ac, char **av) { return MOD_CONT; } They will receive the source; this can be NULL at times depending on the event. Next, ac is the number of arguments that are in the event, and av holds the values for each; so av[0] is the first variable, av[1] will be the second one, and so on. Events are likely to pass to various upper level event handlers; see the previous ircd source for how they handle these events. All commands are formed like this: void anope_cmd_svsnoop(char *server, int set) { send_cmd(NULL, "SVSNOOP %s %s", server, (set ? "+" : "-")); } They may take any number of arguments, depending on the command. They should eventually come to a send_cmd(); this root function is how commands are sent to the IRCd. 6) CAPAB/PROTOCTL Most IRCD send a CAPAB or PROTOCTL line so that they can work out what the other end of the connection is capable of doing. Anope has a function to read these lines and set itself up to to handle these events better. When adding support for your ircd, take the following steps. 1) In the module constructor you must tell Anope what the uplink is capable of that isn't already passed in the CAPAB/PROTOCTL, you do this by something similar to: CapabType c[] = { CAPAB_NOQUIT, CAPAB_NICKIP, CAPAB_ZIP, CAPAB_TOKEN, CAPAB_SSJ3, CAPAB_NICK2, CAPAB_VL, CAPAB_TLKEXT, CAPAB_CHANMODE, CAPAB_SJB64, CAPAB_NICKCHARS }; for (unsigned i = 0; i < 11; ++i) Capab.SetFlag(c[i]); Anything else given to Anope in the CAPAB/PROTOCTL message will be handled later by CapabParse. The available CAPAB options are: -------------------------------------------------------------------------- Define | Description ----------------|------------|-----------|-------------------------------- CAPAB_NOQUIT | NOQUIT protocol support CAPAB_TSMODE | Chanmodes are timestamped CAPAB_UNCONNECT | UNCONNECT protocol support CAPAB_NICKIP | IP sent in the NICK line CAPAB_NSJOIN | Smart SJOIN support CAPAB_ZIP | Support for gzipped links CAPAB_BURST | Supports BURST command CAPAB_TS3 | Support for TS3 protocol CAPAB_TS5 | Support for TS5 protocol CAPAB_DKEY | DH-Key exchange using DKEY CAPAB_DOZIP | Link traffic will be gzipped CAPAB_DODKEY | Do DKEY with this link CAPAB_QS | Supports quit storm removal CAPAB_SCS | String Cache System support CAPAB_PT4 | Support for PT4 protocol CAPAB_UID | Support for UIDs CAPAB_KNOCK | Supports KNOCK CAPAB_CLIENT | Supports CLIENT CAPAB_IPV6 | Support for IPv6 addresses CAPAB_SSJ5 | Smart Join protocol 5 support CAPAB_SN2 | Support for SN2 protocol CAPAB_VHOST | Supports VHOST protocol CAPAB_TOKEN | Supports s2s tokens CAPAB_SSJ3 | Smart Join protocol 3 support CAPAB_NICK2 | Support for extended NICK (v2) CAPAB_UMODE2 | Supports UMODE2 command CAPAB_VL | VLine information in info field CAPAB_TLKEXT | Not 8, but 10 params in TKL's CAPAB_CHANMODE | Channel modes are passed here CAPAB_SJB64 | SJOIN timestamps are base64 encoded CAPAB_NICKCHARS | Character set used by the IRCD for nicks 2) In the ircd.c find the function anope_cmd_capab(); this function will send the CAPAB/PROTOCTL line (consult your ircd documentation for which to send). In a single line type in the tokens that anope must send. Here is an example of Hybrid's capab line: /* CAPAB */ void anope_cmd_capab() { send_cmd(NULL, "CAPAB TS5 EX IE HOPS HUB AOPS"); } 3) Ensure that the CAPAB/PROTOCTL event his handled correctly. A) In the function module constructor make sure that you have the following two lines: m = createMessage("CAPAB", anope_event_capab); addCoreMessage(IRCD,m); B) Add the function to handle the event int anope_event_capab(char *source, int ac, char **av) { CapabParse(ac, av); return MOD_CONT; } This function should call the CapabParse function which parses the received CAPAB/PROTOCTL line. 7) IRCDProto Class The IRCDProto class is set up like: class MyIRCdProto : public IRCDProto { } ircdproto; And told to Anope through the pmodule_ircd_proto(&ircd_proto); function. This is used for sending out specific messages from Anope to your IRCd. A list of all of the valid function names to overload and their args are in services.h. If the protocol module you are editing is similar enough to the IRCd you are adding support for, many of these probably won't need to be changed.