diff --git a/include/h.h b/include/h.h index 525147704..d01876d4a 100644 --- a/include/h.h +++ b/include/h.h @@ -820,6 +820,7 @@ extern MODVAR int (*do_remote_nick_name)(char *nick); extern MODVAR const char *(*charsys_get_current_languages)(void); extern MODVAR void (*broadcast_sinfo)(Client *acptr, Client *to, Client *except); extern MODVAR void (*connect_server)(ConfigItem_link *aconf, Client *by, struct hostent *hp); +extern MODVAR int (*is_services_but_not_ulined)(Client *client); extern MODVAR void (*parse_message_tags)(Client *cptr, char **str, MessageTag **mtag_list); extern MODVAR const char *(*mtags_to_string)(MessageTag *m, Client *acptr); extern MODVAR int (*can_send_to_channel)(Client *cptr, Channel *channel, const char **msgtext, const char **errmsg, int notice); diff --git a/include/modules.h b/include/modules.h index 8f3924b6a..10fd11fda 100644 --- a/include/modules.h +++ b/include/modules.h @@ -2507,6 +2507,7 @@ enum EfunctionType { EFUNC_CHARSYS_GET_CURRENT_LANGUAGES, EFUNC_BROADCAST_SINFO, EFUNC_CONNECT_SERVER, + EFUNC_IS_SERVICES_BUT_NOT_ULINED, EFUNC_PARSE_MESSAGE_TAGS, EFUNC_MTAGS_TO_STRING, EFUNC_TKL_CHARTOTYPE, diff --git a/src/api-efunctions.c b/src/api-efunctions.c index 601eb62b9..aa7962847 100644 --- a/src/api-efunctions.c +++ b/src/api-efunctions.c @@ -106,6 +106,7 @@ int (*do_remote_nick_name)(char *nick); const char *(*charsys_get_current_languages)(void); void (*broadcast_sinfo)(Client *client, Client *to, Client *except); void (*connect_server)(ConfigItem_link *aconf, Client *by, struct hostent *hp); +int (*is_services_but_not_ulined)(Client *client); void (*parse_message_tags)(Client *client, char **str, MessageTag **mtag_list); const char *(*mtags_to_string)(MessageTag *m, Client *client); int (*can_send_to_channel)(Client *client, Channel *channel, const char **msgtext, const char **errmsg, int notice); @@ -389,6 +390,7 @@ void efunctions_init(void) efunc_init_function(EFUNC_CHARSYS_GET_CURRENT_LANGUAGES, charsys_get_current_languages, NULL); efunc_init_function(EFUNC_BROADCAST_SINFO, broadcast_sinfo, NULL); efunc_init_function(EFUNC_CONNECT_SERVER, connect_server, NULL); + efunc_init_function(EFUNC_IS_SERVICES_BUT_NOT_ULINED, is_services_but_not_ulined, NULL); 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); diff --git a/src/modules/protoctl.c b/src/modules/protoctl.c index c45af25e0..b4d48c4b8 100644 --- a/src/modules/protoctl.c +++ b/src/modules/protoctl.c @@ -277,6 +277,11 @@ CMD_FUNC(cmd_protoctl) client->server->features.protocol = atoi(protocol); if (software) safe_strdup(client->server->features.software, software); + if (is_services_but_not_ulined(client)) + { + exit_client_fmt(client, NULL, "Services detected but no ulines { } for server name %s", client->name); + return; + } if (!IsHandshake(client) && aconf) /* Send PASS early... */ sendto_one(client, NULL, "PASS :%s", (aconf->auth->type == AUTHTYPE_PLAINTEXT) ? aconf->auth->data : "*"); } diff --git a/src/modules/server.c b/src/modules/server.c index 995311015..a40a589b3 100644 --- a/src/modules/server.c +++ b/src/modules/server.c @@ -57,6 +57,7 @@ void server_generic_free(ModData *m); int server_post_connect(Client *client); void _connect_server(ConfigItem_link *aconf, Client *by, struct hostent *hp); static int connect_server_helper(ConfigItem_link *, Client *); +int _is_services_but_not_ulined(Client *client); /* Global variables */ static cfgstruct cfg; @@ -81,6 +82,7 @@ MOD_TEST() EfunctionAdd(modinfo->handle, EFUNC_CHECK_DENY_VERSION, _check_deny_version); EfunctionAddVoid(modinfo->handle, EFUNC_BROADCAST_SINFO, _broadcast_sinfo); EfunctionAddVoid(modinfo->handle, EFUNC_CONNECT_SERVER, _connect_server); + EfunctionAdd(modinfo->handle, EFUNC_IS_SERVICES_BUT_NOT_ULINED, _is_services_but_not_ulined); HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, server_config_test); return MOD_SUCCESS; } @@ -1979,3 +1981,25 @@ static int connect_server_helper(ConfigItem_link *aconf, Client *client) return 1; } +int _is_services_but_not_ulined(Client *client) +{ + if (!client->server || !client->server->features.software || !*client->name) + return 0; /* cannot detect software version or name not available yet */ + + if (our_strcasestr(client->server->features.software, "anope") || + our_strcasestr(client->server->features.software, "atheme")) + { + if (!find_uline(client->name)) + { + unreal_log(ULOG_ERROR, "link", "LINK_NO_ULINES", client, + "Server $client is a services server ($software). " + "However, server $me does not have $client in the ulines { } block, " + "which is required for services servers. " + "See https://www.unrealircd.org/docs/Ulines_block", + log_data_client("me", &me), + log_data_string("software", client->server->features.software)); + return 1; /* Is services AND no ulines { } entry */ + } + } + return 0; +} diff --git a/src/modules/sinfo.c b/src/modules/sinfo.c index 451db5854..15235a2f5 100644 --- a/src/modules/sinfo.c +++ b/src/modules/sinfo.c @@ -104,6 +104,14 @@ CMD_FUNC(sinfo_server) else safe_strdup(client->server->features.software, parv[parc-1]); + if (is_services_but_not_ulined(client)) + { + char buf[512]; + snprintf(buf, sizeof(buf), "Services detected but no ulines { } for server name %s", client->name); + exit_client_ex(client, &me, NULL, buf); + return; + } + /* Broadcast to 'the other side' of the net */ concat_params(buf, sizeof(buf), parc, parv); sendto_server(client, 0, 0, NULL, ":%s SINFO %s", client->id, buf);