1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-07-09 21:33:12 +02:00

RPC: remove tkl, split this up.. starting with server_ban.

Currently available:
* server_ban.list
* server_ban.get with params: name="*@1.2.3.4", type="kline"

This also adds server_ban_parse_mask() which is now used by both GLINE/etc
and the RPC API to parse the same way and convey the same error messages.
This commit is contained in:
Bram Matthys
2022-06-24 18:51:14 +02:00
parent 6596741638
commit 3d9b7e4b70
8 changed files with 353 additions and 220 deletions
+1 -1
View File
@@ -30,4 +30,4 @@ loadmodule "rpc/rpc";
/* Now the actual RPC call handlers */
loadmodule "rpc/user";
loadmodule "rpc/channel";
loadmodule "rpc/tkl";
loadmodule "rpc/server_ban";
+2
View File
@@ -745,6 +745,7 @@ extern MODVAR int (*register_user)(Client *client);
extern MODVAR int (*tkl_hash)(unsigned int c);
extern MODVAR char (*tkl_typetochar)(int type);
extern MODVAR int (*tkl_chartotype)(char c);
extern MODVAR char (*tkl_configtypetochar)(const char *name);
extern MODVAR const char *(*tkl_type_string)(TKL *tk);
extern MODVAR const char *(*tkl_type_config_string)(TKL *tk);
extern MODVAR TKL *(*tkl_add_serverban)(int type, const char *usermask, const char *hostmask, const char *reason, const char *setby,
@@ -817,6 +818,7 @@ extern MODVAR void (*broadcast_md_globalvar_cmd)(Client *except, Client *sender,
extern MODVAR int (*tkl_ip_hash)(const char *ip);
extern MODVAR int (*tkl_ip_hash_type)(int type);
extern MODVAR int (*find_tkl_exception)(int ban_type, Client *cptr);
extern MODVAR int (*server_ban_parse_mask)(Client *client, int add, char type, const char *str, char **usermask_out, char **hostmask_out, int *soft, const char **error);
extern MODVAR int (*del_silence)(Client *client, const char *mask);
extern MODVAR int (*add_silence)(Client *client, const char *mask, int senderr);
extern MODVAR int (*is_silenced)(Client *client, Client *acptr);
+2
View File
@@ -2464,6 +2464,7 @@ enum EfunctionType {
EFUNC_PARSE_MESSAGE_TAGS,
EFUNC_MTAGS_TO_STRING,
EFUNC_TKL_CHARTOTYPE,
EFUNC_TKL_CONFIGTYPETOCHAR,
EFUNC_TKL_TYPE_STRING,
EFUNC_TKL_TYPE_CONFIG_STRING,
EFUNC_CAN_SEND_TO_CHANNEL,
@@ -2483,6 +2484,7 @@ enum EfunctionType {
EFUNC_FIND_TKL_NAMEBAN,
EFUNC_FIND_TKL_SPAMFILTER,
EFUNC_FIND_TKL_EXCEPTION,
EFUNC_SERVER_BAN_PARSE_MASK,
EFUNC_ADD_SILENCE,
EFUNC_DEL_SILENCE,
EFUNC_IS_SILENCED,
+4
View File
@@ -46,6 +46,7 @@ int (*register_user)(Client *client);
int (*tkl_hash)(unsigned int c);
char (*tkl_typetochar)(int type);
int (*tkl_chartotype)(char c);
char (*tkl_configtypetochar)(const char *name);
const char *(*tkl_type_string)(TKL *tk);
const char *(*tkl_type_config_string)(TKL *tk);
char *(*tkl_uhost)(TKL *tkl, char *buf, size_t buflen, int options);
@@ -119,6 +120,7 @@ TKL *(*find_tkl_banexception)(int type, const char *usermask, const char *hostma
TKL *(*find_tkl_nameban)(int type, const char *name, int hold);
TKL *(*find_tkl_spamfilter)(int type, const char *match_string, unsigned short action, unsigned short target);
int (*find_tkl_exception)(int ban_type, Client *client);
int (*server_ban_parse_mask)(Client *client, int add, char type, const char *str, char **usermask_out, char **hostmask_out, int *soft, const char **error);
int (*is_silenced)(Client *client, Client *acptr);
int (*del_silence)(Client *client, const char *mask);
int (*add_silence)(Client *client, const char *mask, int senderr);
@@ -381,6 +383,7 @@ void efunctions_init(void)
efunc_init_function(EFUNC_PARSE_MESSAGE_TAGS, parse_message_tags, &parse_message_tags_default_handler);
efunc_init_function(EFUNC_MTAGS_TO_STRING, mtags_to_string, &mtags_to_string_default_handler);
efunc_init_function(EFUNC_TKL_CHARTOTYPE, tkl_chartotype, NULL);
efunc_init_function(EFUNC_TKL_CONFIGTYPETOCHAR, tkl_configtypetochar, NULL);
efunc_init_function(EFUNC_TKL_TYPE_STRING, tkl_type_string, NULL);
efunc_init_function(EFUNC_TKL_TYPE_CONFIG_STRING, tkl_type_config_string, NULL);
efunc_init_function(EFUNC_CAN_SEND_TO_CHANNEL, can_send_to_channel, NULL);
@@ -398,6 +401,7 @@ void efunctions_init(void)
efunc_init_function(EFUNC_FIND_TKL_NAMEBAN, find_tkl_nameban, NULL);
efunc_init_function(EFUNC_FIND_TKL_SPAMFILTER, find_tkl_spamfilter, NULL);
efunc_init_function(EFUNC_FIND_TKL_EXCEPTION, find_tkl_exception, NULL);
efunc_init_function(EFUNC_SERVER_BAN_PARSE_MASK, server_ban_parse_mask, NULL);
efunc_init_function(EFUNC_ADD_SILENCE, add_silence, add_silence_default_handler);
efunc_init_function(EFUNC_DEL_SILENCE, del_silence, del_silence_default_handler);
efunc_init_function(EFUNC_IS_SILENCED, is_silenced, is_silenced_default_handler);
+1 -1
View File
@@ -32,7 +32,7 @@ INCLUDES = ../../include/channel.h \
../../include/version.h ../../include/whowas.h
R_MODULES= \
rpc.so user.so channel.so tkl.so
rpc.so user.so channel.so server_ban.so
MODULES=$(R_MODULES)
MODULEFLAGS=@MODULEFLAGS@
+154
View File
@@ -0,0 +1,154 @@
/* server_ban.* RPC calls
* (C) Copyright 2022-.. Bram Matthys (Syzop) and the UnrealIRCd team
* License: GPLv2 or later
*/
#include "unrealircd.h"
ModuleHeader MOD_HEADER
= {
"rpc/server_ban",
"1.0.0",
"server_ban.* RPC calls",
"UnrealIRCd Team",
"unrealircd-6",
};
/* Forward declarations */
RPC_CALL_FUNC(rpc_server_ban_list);
RPC_CALL_FUNC(rpc_server_ban_get);
MOD_INIT()
{
RPCHandlerInfo r;
MARK_AS_OFFICIAL_MODULE(modinfo);
memset(&r, 0, sizeof(r));
r.method = "server_ban.list";
r.call = rpc_server_ban_list;
if (!RPCHandlerAdd(modinfo->handle, &r))
{
config_error("[rpc/server_ban] Could not register RPC handler");
return MOD_FAILED;
}
r.method = "server_ban.get";
r.call = rpc_server_ban_get;
if (!RPCHandlerAdd(modinfo->handle, &r))
{
config_error("[rpc/server_ban] Could not register RPC handler");
return MOD_FAILED;
}
return MOD_SUCCESS;
}
MOD_LOAD()
{
return MOD_SUCCESS;
}
MOD_UNLOAD()
{
return MOD_SUCCESS;
}
#define RPC_USER_LIST_EXPAND_NONE 0
#define RPC_USER_LIST_EXPAND_SELECT 1
#define RPC_USER_LIST_EXPAND_ALL 2
// TODO: right now returns everything for everyone,
// give the option to return a list of names only or
// certain options (hence the placeholder #define's above)
RPC_CALL_FUNC(rpc_server_ban_list)
{
json_t *result, *list, *item;
int index, index2;
TKL *tkl;
result = json_object();
list = json_array();
json_object_set_new(result, "list", list);
for (index = 0; index < TKLIPHASHLEN1; index++)
{
for (index2 = 0; index2 < TKLIPHASHLEN2; index2++)
{
for (tkl = tklines_ip_hash[index][index2]; tkl; tkl = tkl->next)
{
if (TKLIsServerBan(tkl))
{
item = json_object();
json_expand_tkl(item, NULL, tkl, 1);
json_array_append_new(list, item);
}
}
}
}
for (index = 0; index < TKLISTLEN; index++)
{
for (tkl = tklines[index]; tkl; tkl = tkl->next)
{
if (TKLIsServerBan(tkl))
{
item = json_object();
json_expand_tkl(item, NULL, tkl, 1);
json_array_append_new(list, item);
}
}
}
rpc_response(client, request, result);
json_decref(result);
}
RPC_CALL_FUNC(rpc_server_ban_get)
{
json_t *result, *list, *item;
const char *name, *type_name;
const char *error;
char *usermask, *hostmask;
int soft;
TKL *tkl;
char tkl_type_char;
int tkl_type_int;
name = json_object_get_string(params, "name");
if (!name)
{
rpc_error(client, NULL, JSON_RPC_ERROR_INVALID_PARAMS, "Missing parameter: 'name'");
return;
}
type_name = json_object_get_string(params, "type");
if (!type_name)
{
rpc_error(client, NULL, JSON_RPC_ERROR_INVALID_PARAMS, "Missing parameter: 'type'");
return;
}
tkl_type_char = tkl_configtypetochar(type_name);
if (!tkl_type_char)
{
rpc_error_fmt(client, NULL, JSON_RPC_ERROR_INVALID_PARAMS, "Invalid type: '%s'", type_name);
return;
}
tkl_type_int = tkl_chartotype(tkl_type_char);
if (!server_ban_parse_mask(client, 0, tkl_type_int, name, &usermask, &hostmask, &soft, &error))
{
rpc_error_fmt(client, NULL, JSON_RPC_ERROR_INVALID_PARAMS, "Error: %s", error);
return;
}
if (!(tkl = find_tkl_serverban(tkl_type_int, usermask, hostmask, soft)))
{
rpc_error(client, NULL, JSON_RPC_ERROR_NOT_FOUND, "Ban not found");
return;
}
result = json_object();
json_expand_tkl(result, "tkl", tkl, 1);
rpc_response(client, request, result);
json_decref(result);
}
-89
View File
@@ -1,89 +0,0 @@
/* tkl.* RPC calls
* (C) Copyright 2022-.. Bram Matthys (Syzop) and the UnrealIRCd team
* License: GPLv2 or later
*/
#include "unrealircd.h"
ModuleHeader MOD_HEADER
= {
"rpc/tkl",
"1.0.0",
"tkl.* RPC calls",
"UnrealIRCd Team",
"unrealircd-6",
};
/* Forward declarations */
RPC_CALL_FUNC(rpc_tkl_list);
MOD_INIT()
{
RPCHandlerInfo r;
MARK_AS_OFFICIAL_MODULE(modinfo);
memset(&r, 0, sizeof(r));
r.method = "tkl.list";
r.call = rpc_tkl_list;
if (!RPCHandlerAdd(modinfo->handle, &r))
{
config_error("[rpc/tkl] Could not register RPC handler");
return MOD_FAILED;
}
return MOD_SUCCESS;
}
MOD_LOAD()
{
return MOD_SUCCESS;
}
MOD_UNLOAD()
{
return MOD_SUCCESS;
}
#define RPC_USER_LIST_EXPAND_NONE 0
#define RPC_USER_LIST_EXPAND_SELECT 1
#define RPC_USER_LIST_EXPAND_ALL 2
// TODO: right now returns everything for everyone,
// give the option to return a list of names only or
// certain options (hence the placeholder #define's above)
RPC_CALL_FUNC(rpc_tkl_list)
{
json_t *result, *list, *item;
int index, index2;
TKL *tkl;
result = json_object();
list = json_array();
json_object_set_new(result, "list", list);
for (index = 0; index < TKLIPHASHLEN1; index++)
{
for (index2 = 0; index2 < TKLIPHASHLEN2; index2++)
{
for (tkl = tklines_ip_hash[index][index2]; tkl; tkl = tkl->next)
{
item = json_object();
json_expand_tkl(item, NULL, tkl, 1);
json_array_append_new(list, item);
}
}
}
for (index = 0; index < TKLISTLEN; index++)
{
for (tkl = tklines[index]; tkl; tkl = tkl->next)
{
item = json_object();
json_expand_tkl(item, NULL, tkl, 1);
json_array_append_new(list, item);
}
}
rpc_response(client, request, result);
json_decref(result);
}
+189 -129
View File
@@ -55,6 +55,7 @@ void cmd_tkl_line(Client *client, int parc, const char *parv[], char *type);
int _tkl_hash(unsigned int c);
char _tkl_typetochar(int type);
int _tkl_chartotype(char c);
char _tkl_configtypetochar(const char *name);
int tkl_banexception_chartotype(char c);
char *_tkl_type_string(TKL *tk);
char *_tkl_type_config_string(TKL *tk);
@@ -103,6 +104,7 @@ TKL *_find_tkl_banexception(int type, char *usermask, char *hostmask, int softba
TKL *_find_tkl_nameban(int type, char *name, int hold);
TKL *_find_tkl_spamfilter(int type, char *match_string, BanAction action, unsigned short target);
int _find_tkl_exception(int ban_type, Client *client);
int _server_ban_parse_mask(Client *client, int add, char type, const char *str, char **usermask_out, char **hostmask_out, int *soft, const char **error);
static void add_default_exempts(void);
int parse_extended_server_ban(const char *mask_in, Client *client, char **error, int skip_checking, char *buf1, size_t buf1len, char *buf2, size_t buf2len);
@@ -171,6 +173,7 @@ MOD_TEST()
#endif
EfunctionAdd(modinfo->handle, EFUNC_TKL_TYPETOCHAR, TO_INTFUNC(_tkl_typetochar));
EfunctionAdd(modinfo->handle, EFUNC_TKL_CHARTOTYPE, TO_INTFUNC(_tkl_chartotype));
EfunctionAdd(modinfo->handle, EFUNC_TKL_CONFIGTYPETOCHAR, TO_INTFUNC(_tkl_configtypetochar));
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
@@ -208,6 +211,7 @@ MOD_TEST()
EfunctionAdd(modinfo->handle, EFUNC_FIND_TKL_EXCEPTION, _find_tkl_exception);
EfunctionAddString(modinfo->handle, EFUNC_TKL_UHOST, _tkl_uhost);
EfunctionAdd(modinfo->handle, EFUNC_UNREAL_MATCH_IPLIST, _unreal_match_iplist);
EfunctionAdd(modinfo->handle, EFUNC_SERVER_BAN_PARSE_MASK, TO_INTFUNC(_server_ban_parse_mask));
return MOD_SUCCESS;
}
@@ -1339,6 +1343,175 @@ fail_parse_extended_server_ban:
return 0;
}
/** Parse a server ban request such as 'blah@blah.com' or '~account:EvilUser'
* @param client Client requesting the operation (can be NULL)
* @param add Set to 1 for add ban, 0 for remove ban
* @param type TKL type (character), see 2nd column of tkl_types[], eg 'G' for gline.
* @param str The input string
* @param usermask_out Will be set to the TKL usermask
* @param hostmask_out Will be set to the TKL hostmask
* @param soft Will be set to 1 if it's a softban, otherwise 0
* @param error On failure, this will contain the error string
* @retval 1 Success: usermask_out, hostmask_out and soft are set appropriately.
* @retval 0 Failed: error is set appropriately
*/
int _server_ban_parse_mask(Client *client, int add, char type, const char *str, char **usermask_out, char **hostmask_out, int *soft, const char **error)
{
static char maskbuf[512];
char mask1buf[BUFSIZE], mask2buf[BUFSIZE];
char *hostmask = NULL, *usermask = NULL;
char *mask, *p;
/* Set defaults */
*usermask_out = *hostmask_out = NULL;
*soft = 0;
strlcpy(maskbuf, str, sizeof(maskbuf));
mask = maskbuf;
if ((*mask != '~') && strchr(mask, '!'))
{
*error = "Cannot have '!' in masks.";
return 0;
}
if (*mask == ':')
{
*error = "Mask cannot start with a ':'.";
return 0;
}
if (strchr(mask, ' '))
{
*error = "Mask may not contain spaces";
return 0;
}
/* Check if it's a softban */
if (*mask == '%')
{
*soft = 1;
if (!strchr("kGs", type))
{
*error = "The %% prefix (soft ban) is only available for KLINE, GLINE and SHUN. "
"For technical reasons this will not work for (G)ZLINE.";
return 0;
}
}
/* Check if it's an extended server ban */
if (is_extended_server_ban(mask))
{
char *err;
if (!parse_extended_server_ban(mask, client, &err, 0, mask1buf, sizeof(mask1buf), mask2buf, sizeof(mask2buf)))
{
/* If adding, reject it */
if (add)
{
*error = err;
return 0;
} else
{
/* Always allow any removal attempt... */
char *p;
char save;
p = strchr(mask, ':');
p++;
save = *p;
*p = '\0';
strlcpy(mask1buf, mask, sizeof(mask1buf));
*p = save;
strlcpy(mask2buf, p, sizeof(mask2buf));
/* fallthrough */
}
}
if (add && ((type == 'z') || (type == 'Z')))
{
*error = "(G)Zlines must be placed at *@\037IPMASK\037. "
"Extended server bans don't work here because (g)zlines are processed "
"BEFORE dns and ident lookups are done and before reading any client data. "
"If you want to use extended server bans then use a KLINE/GLINE instead.";
return 0;
}
usermask = mask1buf; /* eg ~S: */
hostmask = mask2buf; /* eg 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef */
} else
{
/* Check if it's a hostmask and legal .. */
p = strchr(mask, '@');
if (p) {
if ((p == mask) || !p[1])
{
*error = "No user@host specified";
return 0;
}
usermask = strtok(mask, "@");
hostmask = strtok(NULL, "");
if (BadPtr(hostmask))
{
if (BadPtr(usermask))
{
*error = "Invalid mask";
return 0;
}
hostmask = usermask;
usermask = "*";
}
if (*hostmask == ':')
{
*error = "For technical reasons you cannot start the host with a ':', sorry";
return 0;
}
if (add && ((type == 'z') || (type == 'Z')))
{
/* It's a (G)ZLINE, make sure the user isn't specyfing a HOST.
* Just a warning in 3.2.3, but an error in 3.2.4.
*/
if (strcmp(usermask, "*"))
{
*error = "(G)Zlines must be placed at \037*\037@ipmask, not \037user\037@ipmask. This is "
"because (g)zlines are processed BEFORE dns and ident lookups are done. "
"If you want to use usermasks, use a KLINE/GLINE instead.";
return 0;
}
for (p=hostmask; *p; p++)
{
if (isalpha(*p) && !isxdigit(*p))
{
*error = "ERROR: (g)zlines must be placed at *@\037IPMASK\037, not *@\037HOSTMASK\037 "
"(so for example *@192.168.* is ok, but *@*.aol.com is not). "
"This is because (g)zlines are processed BEFORE dns and ident lookups are done. "
"If you want to use hostmasks instead of ipmasks, use a KLINE/GLINE instead.";
return 0;
}
}
}
}
else
{
/* It's seemingly a nick .. let's see if we can find the user */
Client *acptr;
if ((acptr = find_user(mask, NULL)))
{
BanAction action = BAN_ACT_KLINE; // just a dummy default
if ((type == 'z') || (type == 'Z'))
action = BAN_ACT_ZLINE; // to indicate zline (no hostname, no dns, etc)
ban_target_to_tkl_layer(iConf.manual_ban_target, action, acptr, (const char **)&usermask, (const char **)&hostmask);
}
else
{
*error = "Nickname not found";
return 0;
}
}
}
/* Success! */
*usermask_out = usermask;
*hostmask_out = hostmask;
return 1;
}
/** Intermediate layer between user functions such as KLINE/GLINE
* and the TKL layer (cmd_tkl).
@@ -1348,14 +1521,12 @@ fail_parse_extended_server_ban:
void cmd_tkl_line(Client *client, int parc, const char *parv[], char *type)
{
time_t secs;
int add = 1;
int add = 1, soft;
time_t i;
Client *acptr = NULL;
char maskbuf[BUFSIZE];
char *mask;
const char *mask;
const char *error;
char mo[64], mo2[64];
char mask1buf[BUFSIZE];
char mask2buf[BUFSIZE];
char *p, *usermask, *hostmask;
const char *tkllayer[10] = {
me.name, /*0 server.name */
@@ -1374,8 +1545,8 @@ void cmd_tkl_line(Client *client, int parc, const char *parv[], char *type)
if ((parc == 1) || BadPtr(parv[1]))
return; /* shouldn't happen */
strlcpy(maskbuf, parv[1], sizeof(maskbuf));
mask = maskbuf;
mask = parv[1];
if (*mask == '-')
{
add = 0;
@@ -1387,131 +1558,11 @@ void cmd_tkl_line(Client *client, int parc, const char *parv[], char *type)
mask++;
}
if ((*mask != '~') && strchr(mask, '!'))
if (!server_ban_parse_mask(client, add, *type, mask, &usermask, &hostmask, &soft, &error))
{
sendnotice(client, "[error] Cannot have '!' in masks.");
sendnotice(client, "[ERROR] %s", error);
return;
}
if (*mask == ':')
{
sendnotice(client, "[error] Mask cannot start with a ':'.");
return;
}
if (strchr(mask, ' '))
return;
/* Check if it's a softban */
if (*mask == '%')
{
if (!strchr("kGs", *type))
{
sendnotice(client, "The %% prefix (soft ban) is only available for KLINE, GLINE and SHUN."
"For technical reasons this will not work for (G)ZLINE.");
return;
}
}
/* Check if it's an extended server ban */
if (is_extended_server_ban(mask))
{
char *err;
if (!parse_extended_server_ban(mask, client, &err, 0, mask1buf, sizeof(mask1buf), mask2buf, sizeof(mask2buf)))
{
/* If adding, reject it */
if (add)
{
sendnotice(client, "ERROR: %s", err);
return;
} else
{
/* Always allow any removal attempt... */
char *p;
char save;
p = strchr(mask, ':');
p++;
save = *p;
*p = '\0';
strlcpy(mask1buf, mask, sizeof(mask1buf));
*p = save;
strlcpy(mask2buf, p, sizeof(mask2buf));
/* fallthrough */
}
}
if (add && ((*type == 'z') || (*type == 'Z')))
{
sendnotice(client, "ERROR: (g)zlines must be placed at *@\037IPMASK\037. "
"Extended server bans don't work here because (g)zlines are processed"
"BEFORE dns and ident lookups are done and before reading any client data. "
"If you want to use extended server bans then use a KLINE/GLINE instead.");
return;
}
usermask = mask1buf; /* eg ~S: */
hostmask = mask2buf; /* eg 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef */
} else
{
/* Check if it's a hostmask and legal .. */
p = strchr(mask, '@');
if (p) {
if ((p == mask) || !p[1])
{
sendnotice(client, "Error: no user@host specified");
return;
}
usermask = strtok(mask, "@");
hostmask = strtok(NULL, "");
if (BadPtr(hostmask)) {
if (BadPtr(usermask)) {
return;
}
hostmask = usermask;
usermask = "*";
}
if (*hostmask == ':')
{
sendnotice(client, "[error] For technical reasons you cannot start the host with a ':', sorry");
return;
}
if (add && ((*type == 'z') || (*type == 'Z')))
{
/* It's a (G)ZLINE, make sure the user isn't specyfing a HOST.
* Just a warning in 3.2.3, but an error in 3.2.4.
*/
if (strcmp(usermask, "*"))
{
sendnotice(client, "ERROR: (g)zlines must be placed at \037*\037@ipmask, not \037user\037@ipmask. This is "
"because (g)zlines are processed BEFORE dns and ident lookups are done. "
"If you want to use usermasks, use a KLINE/GLINE instead.");
return;
}
for (p=hostmask; *p; p++)
if (isalpha(*p) && !isxdigit(*p))
{
sendnotice(client, "ERROR: (g)zlines must be placed at *@\037IPMASK\037, not *@\037HOSTMASK\037 "
"(so for example *@192.168.* is ok, but *@*.aol.com is not). "
"This is because (g)zlines are processed BEFORE dns and ident lookups are done. "
"If you want to use hostmasks instead of ipmasks, use a KLINE/GLINE instead.");
return;
}
}
}
else
{
/* It's seemingly a nick .. let's see if we can find the user */
if ((acptr = find_user(mask, NULL)))
{
BanAction action = BAN_ACT_KLINE; // just a dummy default
if ((*type == 'z') || (*type == 'Z'))
action = BAN_ACT_ZLINE; // to indicate zline (no hostname, no dns, etc)
ban_target_to_tkl_layer(iConf.manual_ban_target, action, acptr, (const char **)&usermask, (const char **)&hostmask);
}
else
{
sendnumeric(client, ERR_NOSUCHNICK, mask);
return;
}
}
}
if (add && ban_too_broad(usermask, hostmask))
{
@@ -2201,6 +2252,15 @@ int _tkl_chartotype(char c)
return 0;
}
char _tkl_configtypetochar(const char *name)
{
int i;
for (i=0; tkl_types[i].config_name; i++)
if (!strcmp(tkl_types[i].config_name, name))
return tkl_types[i].letter;
return 0;
}
int tkl_banexception_chartotype(char c)
{
int i;