Dev:Extended Bans API

Writing a custom extended ban type is relatively easy as all you have to deal with is strings and/or return a value.

In addition to the tutorial below, you may also want to look at examples in UnrealIRCd itself (learn by copying). The built-in extban modules are in src/modules/extbans/.

= Creating an extban = Similar to Dev:Channel Mode API you call the function to register your extban from MOD_INIT and you throw a struct at it like this: MOD_INIT {   ExtbanInfo extban;

memset(&extban, 0, sizeof(extban)); extban.name = "example"; extban.letter = 'X'; /* only used for backwards compatibility (but required!) */ extban.is_ok = mymod_is_ok; extban.conv_param = mymod_conv_param; // or set to a generic handler, like: extban_conv_param_nuh_or_extban extban.is_banned = mymod_is_banned; extban.is_banned_events = BANCHK_ALL; /* what events to listen on, eg only BANCHK_NICK, or just BANCHK_ALL */ extban.options = EXTBOPT_ACTMODIFIER; ExtbanAdd(modinfo->handle, extban);

So basically you pass: 1) the module handle, 2) a ExtbanInfo struct

The ExtbanInfo struct contains the following (regular) variables which you may set:
 * name: name of the extban, eg if this is "example" then the extban will be "~example". No other module may use the same name (must be unique).
 * letter: specifies which letter the extban uses. This is only for backwards compatibility with older UnrealIRCd servers and clients. For example 'X' would mean +b ~X:..etc.. No other module may use the same letter (must be unique).
 * is_banned_events: one of . Most use   here, but if you only want the ban to apply on for example joining then you set it to  . You can also set   in which case you can use the ban in Extended server bans such as GLINE.
 * options: TODO

Other than that, the ExtbanInfo struct contains of function pointers which you must set. Only conv_param and is_banned are required, the rest is optional. See below.

conv_param
Convert input parameter to a 'correct' parameter. For example if you wish +b ~example:blah to be converted to +b ~example:blah!*@*.

Declaration of the conv_param function: const char *conv_param(BanContext *b, Extban *extban)

In the BanContext *b, the following values are useful:

You should return a string (a const char * to static storage!), or NULL if you wish to reject an invalid parameter. For better "is this parameter okay?" checking you can also use the is_ok function (in addition).

Example code: /* Silly example that converts ~example:somestring where somestring will be of max 8 characters in size. */ const char *mymod_conv_param(BanContext *b, Extban *extban) {   static char ret[8 + 1];

if (!*para) return NULL; /* empty string is rejected (eg "~example:") */

strlcpy(ret, param, sizeof(ret)); return ret; }

There is also some help from the UnrealIRCd side:
 * instead of writing your own conv_param you can use extban_conv_param_nuh which will accept and convert input to a nick!user@host (resulting in something like ~example:nick!user@host)
 * similarly you can use extban_conv_param_nuh_or_extban which will allow a nick!user@host or another extban, so to allow extban stacking (eg: ~example:~realname:*somerealname*)

is_ok
Access and parameter checking. This is completely optional and actually often not used. See also conv_param.

Declaration of the is_ok function: int is_ok(BanContext *b)

In the BanContext *b, the following values are useful:

The is_ok function is called in a number of cases:
 * If b->is_ok_check is EXBCHK_ACCESS then the function is called to check if the user may set/unset the mode. You must only check access and NOT send any error message(s). If access is granted you should return EX_ALLOW. If you want to disallow a set/unset then return EX_DENY. Normally IRC Operators with override capabilities may still override a deny, if you also want to prevent IRCOp's from (un)setting then you can return EX_ALWAYS_DENY.
 * When b->is_ok_check is EXCHK_ACCESS_ERR it means your function is called (again) to check access but this time you may send an error message to the user (in fact, you are expected to), indicating why setting or unsetting is not permitted.
 * Finally, when b->is_ok_check is EXCHK_PARAM then you are supposed to check the correctness of the parameter being passed. If it's not good (eg: you expect ~example:num where num is a value between 1 and 20 and you recieve 'lalala' or '30') then you return EX_DENY. Otherwise you return EX_ALLOW. You should also send an error message to the user telling them what's wrong.

Example: TODO

is_banned
Check if a user is affected by this ban.

Declaration: int is_banned(BanContext *b)

In the BanContext *b, the following values are useful:

Return: simply return 1 if the user is banned and 0 otherwise.

The b->ban_check_types decides what kind of check you need to do:

Example code: /* Dull example of a ~example:blah ban type where 'blah' must match the exact nick name of the user. No wildcards. */ int mymod_is_banned(BanContext *b) {   if (!stricmp(b->banstr, b->client->name)) return 1; return 0; }

= More information = UnrealIRCd ships with quite a lot of extended ban modules that you can use for examples and inspiration, they are all in src/modules/extbans/