diff --git a/doc/conf/rpc.modules.default.conf b/doc/conf/rpc.modules.default.conf index 4b4a85418..6c52e8f66 100644 --- a/doc/conf/rpc.modules.default.conf +++ b/doc/conf/rpc.modules.default.conf @@ -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"; diff --git a/include/h.h b/include/h.h index ff051bd78..666e2fc9c 100644 --- a/include/h.h +++ b/include/h.h @@ -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); diff --git a/include/modules.h b/include/modules.h index 73cf12281..800aaadd0 100644 --- a/include/modules.h +++ b/include/modules.h @@ -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, diff --git a/src/api-efunctions.c b/src/api-efunctions.c index 49fd6d821..95ec22e9d 100644 --- a/src/api-efunctions.c +++ b/src/api-efunctions.c @@ -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); diff --git a/src/modules/rpc/Makefile.in b/src/modules/rpc/Makefile.in index 550bc7d62..a7e87ac57 100644 --- a/src/modules/rpc/Makefile.in +++ b/src/modules/rpc/Makefile.in @@ -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@ diff --git a/src/modules/rpc/server_ban.c b/src/modules/rpc/server_ban.c new file mode 100644 index 000000000..c08d953b0 --- /dev/null +++ b/src/modules/rpc/server_ban.c @@ -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); +} diff --git a/src/modules/rpc/tkl.c b/src/modules/rpc/tkl.c deleted file mode 100644 index 8e429f21e..000000000 --- a/src/modules/rpc/tkl.c +++ /dev/null @@ -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); -} diff --git a/src/modules/tkl.c b/src/modules/tkl.c index aab8b3f81..d13189059 100644 --- a/src/modules/tkl.c +++ b/src/modules/tkl.c @@ -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;