Browse Source

Merge branch 'unreal60_dev' of github.com:unrealircd/unrealircd into unrealircd-unreal60_dev

piss60
angryce 3 months ago
parent
commit
99de2b3cee
  1. 2
      Config
  2. 3
      Makefile.in
  3. 21
      Makefile.windows
  4. 25
      configure
  5. 7
      configure.ac
  6. 2
      doc/Config.header
  7. 11
      doc/RELEASE-NOTES.md
  8. 7
      doc/conf/modules.default.conf
  9. 3
      doc/conf/modules.optional.conf
  10. 2
      extras/doxygen/Doxyfile
  11. 25
      include/h.h
  12. 70
      include/modules.h
  13. 136
      include/struct.h
  14. 4
      include/windows/setup.h
  15. 2
      src/Makefile.in
  16. 20
      src/api-efunctions.c
  17. 147
      src/api-rpc.c
  18. 64
      src/conf.c
  19. 5
      src/ircd.c
  20. 19
      src/list.c
  21. 28
      src/log.c
  22. 53
      src/misc.c
  23. 15
      src/modules.c
  24. 5
      src/modules/Makefile.in
  25. 6
      src/modules/botmotd.c
  26. 82
      src/modules/connect-flood.c
  27. 91
      src/modules/max-unknown-connections-per-ip.c
  28. 8
      src/modules/motd.c
  29. 8
      src/modules/nick.c
  30. 6
      src/modules/opermotd.c
  31. 57
      src/modules/pass.c
  32. 53
      src/modules/rpc/Makefile.in
  33. 66
      src/modules/rpc/channel.c
  34. 719
      src/modules/rpc/rpc.c
  35. 112
      src/modules/rpc/user.c
  36. 13
      src/modules/rules.c
  37. 17
      src/modules/tkl.c
  38. 675
      src/modules/webserver.c
  39. 774
      src/modules/websocket.c
  40. 431
      src/modules/websocket_common.c
  41. 2
      src/parse.c
  42. 19
      src/proc_io_server.c
  43. 2
      src/send.c
  44. 79
      src/socket.c
  45. 2
      src/tls.c
  46. 5
      src/url_unreal.c
  47. 2
      src/version.c.SH
  48. 2
      src/windows/UnrealIRCd.exe.manifest
  49. 2
      src/windows/unrealinst.iss

2
Config

@ -375,7 +375,7 @@ echo "We will now ask you a number of questions. You can just press ENTER to acc
echo ""
# This needs to be updated each release so auto-upgrading works for settings, modules, etc!!:
UNREALRELEASES="unrealircd-6.0.4-rc2 unrealircd-6.0.4-rc1 unrealircd-6.0.3 unrealircd-6.0.2 unrealircd-6.0.1.1 unrealircd-6.0.1 unrealircd-6.0.0 unrealircd-6.0.0-rc2 unrealircd-6.0.0-rc1 unrealircd-6.0.0-beta4 unrealircd-6.0.0-beta3 unrealircd-6.0.0-beta2 unrealircd-6.0.0-beta1 unrealircd-5.2.3 unrealircd-5.2.2 unrealircd-5.2.1.1 unrealircd-5.2.1 unrealircd-5.2.1-rc1 unrealircd-5.2.0.2 unrealircd-5.2.0.1 unrealircd-5.2.0 unrealircd-5.2.0-rc1 unrealircd-5.0.9.1 unrealircd-5.0.9 unrealircd-5.0.9-rc1 unrealircd-5.0.8 unrealircd-5.0.8-rc1 unrealircd-5.0.7 unrealircd-5.0.7-rc1 unrealircd-5.0.6"
UNREALRELEASES="unrealircd-6.0.4 unrealircd-6.0.4-rc2 unrealircd-6.0.4-rc1 unrealircd-6.0.3 unrealircd-6.0.2 unrealircd-6.0.1.1 unrealircd-6.0.1 unrealircd-6.0.0 unrealircd-6.0.0-rc2 unrealircd-6.0.0-rc1 unrealircd-6.0.0-beta4 unrealircd-6.0.0-beta3 unrealircd-6.0.0-beta2 unrealircd-6.0.0-beta1 unrealircd-5.2.3 unrealircd-5.2.2 unrealircd-5.2.1.1 unrealircd-5.2.1 unrealircd-5.2.1-rc1 unrealircd-5.2.0.2 unrealircd-5.2.0.1 unrealircd-5.2.0 unrealircd-5.2.0-rc1 unrealircd-5.0.9.1 unrealircd-5.0.9 unrealircd-5.0.9-rc1 unrealircd-5.0.8 unrealircd-5.0.8-rc1 unrealircd-5.0.7 unrealircd-5.0.7-rc1 unrealircd-5.0.6"
if [ -f "config.settings" ]; then
. ./config.settings
else

3
Makefile.in

@ -219,6 +219,9 @@ install: all
$(INSTALL) -m 0700 -d $(DESTDIR)@MODULESDIR@/extbans
@rm -f $(DESTDIR)@MODULESDIR@/extbans/*.so 1>/dev/null 2>&1
$(INSTALL) -m 0700 src/modules/extbans/*.so $(DESTDIR)@MODULESDIR@/extbans
$(INSTALL) -m 0700 -d $(DESTDIR)@MODULESDIR@/rpc
@rm -f $(DESTDIR)@MODULESDIR@/rpc/*.so 1>/dev/null 2>&1
$(INSTALL) -m 0700 src/modules/rpc/*.so $(DESTDIR)@MODULESDIR@/rpc
@#If the conf/ssl directory exists then rename it here to conf/tls
@#and add a symlink for backwards compatibility (so that f.e. certbot
@#doesn't randomly fail after an upgrade to U5).

21
Makefile.windows

@ -184,7 +184,7 @@ EXP_OBJ_FILES=src/ircd_vars.obj src/channel.obj src/send.obj src/socket.obj \
src/version.obj src/ircsprintf.obj \
src/scache.obj src/dns.obj src/modules.obj \
src/aliases.obj src/api-event.obj src/api-usermode.obj src/auth.obj src/tls.obj \
src/random.obj src/api-channelmode.obj src/api-moddata.obj src/mempool.obj \
src/random.obj src/api-channelmode.obj src/api-moddata.obj src/api-rpc.obj src/mempool.obj \
src/dispatch.obj src/api-isupport.obj src/api-command.obj \
src/api-clicap.obj src/api-messagetag.obj src/api-history-backend.obj \
src/api-extban.obj src/api-efunctions.obj src/crypt_blowfish.obj \
@ -253,6 +253,7 @@ DLL_FILES=\
src/modules/clienttagdeny.dll \
src/modules/close.dll \
src/modules/connect.dll \
src/modules/connect-flood.dll \
src/modules/connthrottle.dll \
src/modules/creationtime.dll \
src/modules/cycle.dll \
@ -305,6 +306,7 @@ DLL_FILES=\
src/modules/locops.dll \
src/modules/lusers.dll \
src/modules/map.dll \
src/modules/max-unknown-connections-per-ip.dll \
src/modules/md.dll \
src/modules/message.dll \
src/modules/message-ids.dll \
@ -407,7 +409,9 @@ DLL_FILES=\
src/modules/watch.dll \
src/modules/webirc.dll \
src/modules/webredir.dll \
src/modules/webserver.dll \
src/modules/websocket.dll \
src/modules/websocket_common.dll \
src/modules/whois.dll \
src/modules/who_old.dll \
src/modules/whowas.dll \
@ -582,6 +586,9 @@ src/api-channelmode.obj: src/api-channelmode.c $(INCLUDES)
src/api-moddata.obj: src/api-moddata.c $(INCLUDES)
$(CC) $(CFLAGS) src/api-moddata.c
src/api-rpc.obj: src/api-rpc.c $(INCLUDES)
$(CC) $(CFLAGS) src/api-rpc.c
src/mempool.obj: src/mempool.c $(INCLUDES)
$(CC) $(CFLAGS) src/mempool.c
@ -832,6 +839,9 @@ src/modules/close.dll: src/modules/close.c $(INCLUDES)
src/modules/connect.dll: src/modules/connect.c $(INCLUDES)
$(CC) $(MODCFLAGS) src/modules/connect.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/connect.pdb $(MODLFLAGS)
src/modules/connect-flood.dll: src/modules/connect-flood.c $(INCLUDES)
$(CC) $(MODCFLAGS) src/modules/connect-flood.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/connect-flood.pdb $(MODLFLAGS)
src/modules/connthrottle.dll: src/modules/connthrottle.c $(INCLUDES)
$(CC) $(MODCFLAGS) src/modules/connthrottle.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/connthrottle.pdb $(MODLFLAGS)
@ -991,6 +1001,9 @@ src/modules/lusers.dll: src/modules/lusers.c $(INCLUDES)
src/modules/map.dll: src/modules/map.c $(INCLUDES)
$(CC) $(MODCFLAGS) src/modules/map.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/map.pdb $(MODLFLAGS)
src/modules/max-unknown-connections-per-ip.dll: src/modules/max-unknown-connections-per-ip.c $(INCLUDES)
$(CC) $(MODCFLAGS) src/modules/max-unknown-connections-per-ip.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/max-unknown-connections-per-ip.pdb $(MODLFLAGS)
src/modules/md.dll: src/modules/md.c $(INCLUDES)
$(CC) $(MODCFLAGS) src/modules/md.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/md.pdb $(MODLFLAGS)
@ -1297,9 +1310,15 @@ src/modules/webirc.dll: src/modules/webirc.c $(INCLUDES)
src/modules/webredir.dll: src/modules/webredir.c $(INCLUDES)
$(CC) $(MODCFLAGS) src/modules/webredir.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/webredir.pdb $(MODLFLAGS)
src/modules/webserver.dll: src/modules/webserver.c $(INCLUDES)
$(CC) $(MODCFLAGS) src/modules/webserver.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/webserver.pdb $(MODLFLAGS)
src/modules/websocket.dll: src/modules/websocket.c $(INCLUDES)
$(CC) $(MODCFLAGS) src/modules/websocket.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/websocket.pdb $(MODLFLAGS)
src/modules/websocket_common.dll: src/modules/websocket_common.c $(INCLUDES)
$(CC) $(MODCFLAGS) src/modules/websocket_common.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/websocket_common.pdb $(MODLFLAGS)
src/modules/whois.dll: src/modules/whois.c $(INCLUDES)
$(CC) $(MODCFLAGS) src/modules/whois.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/whois.pdb $(MODLFLAGS)

25
configure vendored

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for unrealircd 6.0.4.
# Generated by GNU Autoconf 2.69 for unrealircd 6.0.5-git.
#
# Report bugs to <https://bugs.unrealircd.org/>.
#
@ -580,8 +580,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='unrealircd'
PACKAGE_TARNAME='unrealircd'
PACKAGE_VERSION='6.0.4'
PACKAGE_STRING='unrealircd 6.0.4'
PACKAGE_VERSION='6.0.5-git'
PACKAGE_STRING='unrealircd 6.0.5-git'
PACKAGE_BUGREPORT='https://bugs.unrealircd.org/'
PACKAGE_URL='https://unrealircd.org/'
@ -1347,7 +1347,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures unrealircd 6.0.4 to adapt to many kinds of systems.
\`configure' configures unrealircd 6.0.5-git to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1413,7 +1413,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of unrealircd 6.0.4:";;
short | recursive ) echo "Configuration of unrealircd 6.0.5-git:";;
esac
cat <<\_ACEOF
@ -1589,7 +1589,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
unrealircd configure 6.0.4
unrealircd configure 6.0.5-git
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@ -1958,7 +1958,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by unrealircd $as_me 6.0.4, which was
It was created by unrealircd $as_me 6.0.5-git, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@ -2366,7 +2366,7 @@ _ACEOF
# Minor version number (e.g.: Z in X.Y.Z)
UNREAL_VERSION_MINOR="4"
UNREAL_VERSION_MINOR="5"
cat >>confdefs.h <<_ACEOF
#define UNREAL_VERSION_MINOR $UNREAL_VERSION_MINOR
@ -2376,7 +2376,7 @@ _ACEOF
# The version suffix such as a beta marker or release candidate
# marker. (e.g.: -rcX for unrealircd-3.2.9-rcX). This macro is a
# string instead of an integer because it contains arbitrary data.
UNREAL_VERSION_SUFFIX=""
UNREAL_VERSION_SUFFIX="-git"
cat >>confdefs.h <<_ACEOF
#define UNREAL_VERSION_SUFFIX "$UNREAL_VERSION_SUFFIX"
@ -8954,7 +8954,7 @@ fi
ac_config_files="$ac_config_files Makefile src/Makefile src/modules/Makefile src/modules/chanmodes/Makefile src/modules/usermodes/Makefile src/modules/extbans/Makefile src/modules/third/Makefile extras/unrealircd-upgrade-script unrealircd"
ac_config_files="$ac_config_files Makefile src/Makefile src/modules/Makefile src/modules/chanmodes/Makefile src/modules/usermodes/Makefile src/modules/extbans/Makefile src/modules/rpc/Makefile src/modules/third/Makefile extras/unrealircd-upgrade-script unrealircd"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@ -9462,7 +9462,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by unrealircd $as_me 6.0.4, which was
This file was extended by unrealircd $as_me 6.0.5-git, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -9525,7 +9525,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
unrealircd config.status 6.0.4
unrealircd config.status 6.0.5-git
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@ -9653,6 +9653,7 @@ do
"src/modules/chanmodes/Makefile") CONFIG_FILES="$CONFIG_FILES src/modules/chanmodes/Makefile" ;;
"src/modules/usermodes/Makefile") CONFIG_FILES="$CONFIG_FILES src/modules/usermodes/Makefile" ;;
"src/modules/extbans/Makefile") CONFIG_FILES="$CONFIG_FILES src/modules/extbans/Makefile" ;;
"src/modules/rpc/Makefile") CONFIG_FILES="$CONFIG_FILES src/modules/rpc/Makefile" ;;
"src/modules/third/Makefile") CONFIG_FILES="$CONFIG_FILES src/modules/third/Makefile" ;;
"extras/unrealircd-upgrade-script") CONFIG_FILES="$CONFIG_FILES extras/unrealircd-upgrade-script" ;;
"unrealircd") CONFIG_FILES="$CONFIG_FILES unrealircd" ;;

7
configure.ac

@ -7,7 +7,7 @@ dnl src/windows/unrealinst.iss
dnl doc/Config.header
dnl src/version.c.SH
AC_INIT([unrealircd], [6.0.4], [https://bugs.unrealircd.org/], [], [https://unrealircd.org/])
AC_INIT([unrealircd], [6.0.5-git], [https://bugs.unrealircd.org/], [], [https://unrealircd.org/])
AC_CONFIG_SRCDIR([src/ircd.c])
AC_CONFIG_HEADER([include/setup.h])
AC_CONFIG_AUX_DIR([autoconf])
@ -34,13 +34,13 @@ UNREAL_VERSION_MAJOR=["0"]
AC_DEFINE_UNQUOTED([UNREAL_VERSION_MAJOR], [$UNREAL_VERSION_MAJOR], [Major version number (e.g.: Y for X.Y.Z)])
# Minor version number (e.g.: Z in X.Y.Z)
UNREAL_VERSION_MINOR=["4"]
UNREAL_VERSION_MINOR=["5"]
AC_DEFINE_UNQUOTED([UNREAL_VERSION_MINOR], [$UNREAL_VERSION_MINOR], [Minor version number (e.g.: Z for X.Y.Z)])
# The version suffix such as a beta marker or release candidate
# marker. (e.g.: -rcX for unrealircd-3.2.9-rcX). This macro is a
# string instead of an integer because it contains arbitrary data.
UNREAL_VERSION_SUFFIX=[""]
UNREAL_VERSION_SUFFIX=["-git"]
AC_DEFINE_UNQUOTED([UNREAL_VERSION_SUFFIX], ["$UNREAL_VERSION_SUFFIX"], [Version suffix such as a beta marker or release candidate marker. (e.g.: -rcX for unrealircd-3.2.9-rcX)])
AC_PATH_PROG(RM,rm)
@ -874,6 +874,7 @@ AC_CONFIG_FILES([Makefile
src/modules/chanmodes/Makefile
src/modules/usermodes/Makefile
src/modules/extbans/Makefile
src/modules/rpc/Makefile
src/modules/third/Makefile
extras/unrealircd-upgrade-script
unrealircd])

2
doc/Config.header

@ -7,7 +7,7 @@
\___/|_| |_|_| \___|\__,_|_|\___/\_| \_| \____/\__,_|
Configuration Program
for UnrealIRCd 6.0.4
for UnrealIRCd 6.0.5-git
This program will help you to compile your IRC server, and ask you
questions regarding the compile-time settings of it during the process.

11
doc/RELEASE-NOTES.md

@ -1,5 +1,14 @@
UnrealIRCd 6.0.4
UnrealIRCd 6.0.5-git
=================
This is work in progress. Current git is NOT stable.
If you want a stable IRCd, download 6.0.4 or upgrade to it via `./unrealircd upgrade`
### Enhancements:
* [JSON-RPC](https://www.unrealircd.org/docs/JSON-RPC) API for UnrealIRCd.
This is work in progress, only listing users and channels at the moment.
UnrealIRCd 6.0.4
-----------------
This release comes with lots of features and enhancements. In particular,
security groups and mask items now allow you to write cleaner and more
flexible configuration files. There are also JSON logging enhancements and

7
doc/conf/modules.default.conf

@ -240,6 +240,8 @@ loadmodule "ident_lookup"; /* Ident lookups if set::options::identd-check is set
loadmodule "certfp"; /* TLS certificate fingerprint in /WHOIS (& more) */
loadmodule "tls_cipher"; /* Store and retrieve TLS cipher of local and remote clients */
loadmodule "tls_antidos"; /* prevent TLS DoS (renegotiate floods) */
loadmodule "connect-flood"; /* throttling against connection flooding */
loadmodule "max-unknown-connections-per-ip"; /* limit number of connections in 'unknown state' */
loadmodule "webirc"; /* WEBIRC command. See webirc block. */
loadmodule "blacklist"; /* Blacklist support (DNSBL). See blacklist block. */
loadmodule "jointhrottle"; /* set::anti-flood::join-flood (previously chanmode +j) */
@ -258,13 +260,14 @@ loadmodule "geoip-tag"; /* unrealircd.org/geoip tag for ircops (country) */
loadmodule "json-log-tag"; /* unrealircd.org/json-log tag and CAP for ircops */
loadmodule "targetfloodprot"; /* set::anti-flood::target-flood protection */
loadmodule "watch-backend"; /* used by watch and other modules */
//loadmodule "geoip_base"; /* needed for ALL geoip functions */
//loadmodule "geoip_classic";
/* Piss modules */
loadmodule "third/noglobalmsg";
loadmodule "third/pissquit";
loadmodule "geoip_base"; /* needed for ALL geoip functions */
loadmodule "websocket_common"; /* helper functions for websocket (internal) */
@if module-loaded("geoip_classic")
set {

3
doc/conf/modules.optional.conf

@ -141,6 +141,9 @@ set {
// }
//}
// Load the webserver module, needed for websocket (see next)
loadmodule "webserver";
// This adds websocket support. For more information, see:
// https://www.unrealircd.org/docs/WebSocket_support
loadmodule "websocket";

2
extras/doxygen/Doxyfile

@ -38,7 +38,7 @@ PROJECT_NAME = "UnrealIRCd"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 6.0.4
PROJECT_NUMBER = 6.0.5-git
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

25
include/h.h

@ -798,7 +798,6 @@ extern MODVAR void (*send_moddata_client)(Client *srv, Client *acptr);
extern MODVAR void (*send_moddata_channel)(Client *srv, Channel *channel);
extern MODVAR void (*send_moddata_members)(Client *srv);
extern MODVAR void (*broadcast_moddata_client)(Client *acptr);
extern MODVAR int (*check_banned)(Client *cptr, int exitflags);
extern MODVAR void (*introduce_user)(Client *to, Client *acptr);
extern MODVAR int (*check_deny_version)(Client *cptr, const char *software, int protocol, const char *flags);
extern MODVAR int (*match_user)(const char *rmask, Client *acptr, int options);
@ -836,6 +835,15 @@ extern MODVAR char *(*get_chmodes_for_user)(Client *client, const char *flags);
extern MODVAR WhoisConfigDetails (*whois_get_policy)(Client *client, Client *target, const char *name);
extern MODVAR int (*make_oper)(Client *client, const char *operblock_name, const char *operclass, ConfigItem_class *clientclass, long modes, const char *snomask, const char *vhost);
extern MODVAR int (*unreal_match_iplist)(Client *client, NameList *l);
extern MODVAR void (*webserver_send_response)(Client *client, int status, char *msg);
extern MODVAR void (*webserver_close_client)(Client *client);
extern MODVAR int (*webserver_handle_body)(Client *client, WebRequest *web, const char *readbuf, int length);
extern MODVAR void (*rpc_response)(Client *client, json_t *request, json_t *result);
extern MODVAR void (*rpc_error)(Client *client, json_t *request, JsonRpcError error_code, const char *error_message);
extern MODVAR void (*rpc_error_fmt)(Client *client, json_t *request, JsonRpcError error_code, FORMAT_STRING(const char *fmt), ...) __attribute__((format(printf,4,5)));
extern MODVAR int (*websocket_handle_websocket)(Client *client, WebRequest *web, const char *readbuf2, int length2, int callback(Client *client, char *buf, int len));
extern MODVAR int (*websocket_create_packet)(int opcode, char **buf, int *len);
extern MODVAR int (*websocket_create_packet_simple)(int opcode, const char **buf, int *len);
/* /Efuncs */
/* TLS functions */
@ -872,6 +880,15 @@ extern int del_silence_default_handler(Client *client, const char *mask);
extern int is_silenced_default_handler(Client *client, Client *acptr);
extern void do_unreal_log_remote_deliver_default_handler(LogLevel loglevel, const char *subsystem, const char *event_id, MultiLine *msg, const char *json_serialized);
extern int make_oper_default_handler(Client *client, const char *operblock_name, const char *operclass, ConfigItem_class *clientclass, long modes, const char *snomask, const char *vhost);
extern void webserver_send_response_default_handler(Client *client, int status, char *msg);
extern void webserver_close_client_default_handler(Client *client);
extern int webserver_handle_body_default_handler(Client *client, WebRequest *web, const char *readbuf, int length);
extern void rpc_response_default_handler(Client *client, json_t *request, json_t *result);
extern void rpc_error_default_handler(Client *client, json_t *request, JsonRpcError error_code, const char *error_message);
extern void rpc_error_fmt_default_handler(Client *client, json_t *request, JsonRpcError error_code, const char *fmt, ...);
extern int websocket_handle_websocket_default_handler(Client *client, WebRequest *web, const char *readbuf2, int length2, int callback(Client *client, char *buf, int len));
extern int websocket_create_packet_default_handler(int opcode, char **buf, int *len);
extern int websocket_create_packet_simple_default_handler(int opcode, const char **buf, int *len);
/* End of default handlers for efunctions */
extern MODVAR MOTDFile opermotd, svsmotd, motd, botmotd, smotd, rules;
@ -1111,6 +1128,7 @@ extern void add_fmt_nvplist(NameValuePrioList **lst, int priority, const char *n
#define add_nvplist_numeric(lst, priority, name, to, numeric, ...) add_nvplist_numeric_fmt(lst, priority, name, to, numeric, STR_ ## numeric, ##__VA_ARGS__)
extern void add_nvplist_numeric_fmt(NameValuePrioList **lst, int priority, const char *name, Client *to, int numeric, FORMAT_STRING(const char *pattern), ...) __attribute__((format(printf,6,7)));
extern NameValuePrioList *find_nvplist(NameValuePrioList *list, const char *name);
extern const char *get_nvplist(NameValuePrioList *list, const char *name);
extern void free_nvplist(NameValuePrioList *lst);
extern void unreal_add_name_values(NameValuePrioList **n, const char *name, ConfigEntry *ce);
extern const char *namevalue(NameValuePrioList *n);
@ -1127,7 +1145,10 @@ extern void skip_whitespace(char **p);
extern void read_until(char **p, char *stopchars);
extern int is_ip_valid(const char *ip);
extern int is_file_readable(const char *file, const char *dir);
json_t *json_string_unreal(const char *s);
extern json_t *json_string_unreal(const char *s);
extern const char *json_object_get_string(json_t *j, const char *name);
extern void json_expand_client(json_t *j, const char *key, Client *client, int detail);
extern void json_expand_channel(json_t *j, const char *key, Channel *channel, int detail);
/* securitygroup.c start */
extern MODVAR SecurityGroup *securitygroups;
extern void unreal_delete_masks(ConfigItem_mask *m);

70
include/modules.h

@ -107,6 +107,7 @@ typedef enum ModuleObjectType {
MOBJ_CLICAP = 16,
MOBJ_MTAG = 17,
MOBJ_HISTORY_BACKEND = 18,
MOBJ_RPC = 19,
} ModuleObjectType;
typedef struct Umode Umode;
@ -604,6 +605,46 @@ typedef struct {
int (*history_destroy)(const char *object);
} HistoryBackendInfo;
/** @defgroup RPCAPI RPC API
* @{
*/
/** No special flags set */
#define RPC_HANDLER_FLAGS_NONE 0x0
/** Message Tag Handler */
typedef struct RPCHandler RPCHandler;
struct RPCHandler {
RPCHandler *prev, *next;
char *method; /**< Name of the method handler, eg "client.get" */
int flags; /**< A flag of RPC_HANDLER_FLAG_* */
void (*call)(Client *, json_t *request, json_t *params); /**< RPC call: use RPC_CALL_FUNC() ! */
Module *owner; /**< Module introducing this. */
char unloaded; /**< Internal flag to indicate module is being unloaded */
};
/** The struct used to register a RPC handler.
* For documentation, see the RPCHandler struct.
*/
typedef struct {
char *method;
int flags;
void (*call)(Client *, json_t *request, json_t *params);
} RPCHandlerInfo;
/** RPC function - used by all RPC call functions.
* This is used in the code like <pre>RPC_CALL_FUNC(rpc_call_xyz)</pre> as a function definition.
* It allows the UnrealIRCd devs to add or change parameters to the function without
* (necessarily) breaking your code.
* @param client The client issueing the request
* @param request The full JSON-RPC request
* @param params Parameters of the JSON-RPC call
* @note You are expected to call rpc_response() or rpc_error() on the request.
*/
#define RPC_CALL_FUNC(x) void (x) (Client *client, json_t *request, json_t *params)
/** @} */
struct Hook {
Hook *prev, *next;
int priority;
@ -688,6 +729,7 @@ typedef struct ModuleObject {
ClientCapability *clicap;
MessageTagHandler *mtag;
HistoryBackend *history_backend;
RPCHandler *rpc;
} object;
} ModuleObject;
@ -825,6 +867,10 @@ extern HistoryBackend *HistoryBackendFind(const char *name);
extern HistoryBackend *HistoryBackendAdd(Module *module, HistoryBackendInfo *mreq);
extern void HistoryBackendDel(HistoryBackend *m);
extern RPCHandler *RPCHandlerFind(const char *method);
extern RPCHandler *RPCHandlerAdd(Module *module, RPCHandlerInfo *mreq);
extern void RPCHandlerDel(RPCHandler *m);
#ifndef GCC_TYPECHECKING
#define HookAdd(module, hooktype, priority, func) HookAddMain(module, hooktype, priority, func, NULL, NULL, NULL)
#define HookAddVoid(module, hooktype, priority, func) HookAddMain(module, hooktype, priority, NULL, func, NULL, NULL)
@ -1170,6 +1216,8 @@ extern void SavePersistentLongX(ModuleInfo *modinfo, const char *varshortname, l
#define HOOKTYPE_JSON_EXPAND_CLIENT_SERVER 114
/** See hooktype_json_expand_channel() */
#define HOOKTYPE_JSON_EXPAND_CHANNEL 115
/** See hooktype_accept() */
#define HOOKTYPE_ACCEPT 116
/* Adding a new hook here?
* 1) Add the #define HOOKTYPE_.... with a new number
@ -1821,6 +1869,18 @@ int hooktype_packet(Client *from, Client *to, Client *intended_to, char **msg, i
*/
int hooktype_handshake(Client *client);
/** Called very early when a client connects (function prototype for HOOKTYPE_ACCEPT).
* Module coders: have a look at hooktype_handshake() instead of this one!
* HOOKTYPE_ACCEPT is called even before HOOKTYPE_HANDSHAKE, as soon as the socket
* is connected and during the client is being set up, before the SSL/TLS handshake.
* It is only used for connection flood detection and checking (G)Z-lines.
* Note that this connection is also called for *NIX domain socket connections,
* HTTP(S) requests, and so on.
* @param client The client
* @return One of HOOK_*. Use HOOK_DENY to reject the client.
*/
int hooktype_accept(Client *client);
/** Called when a client structure is freed (function prototype for HOOKTYPE_FREE_CLIENT).
* @param client The client
* @note Normally you use hooktype_local_quit(), hooktype_remote_quit() and hooktype_unkuser_quit() for this.
@ -2380,7 +2440,6 @@ enum EfunctionType {
EFUNC_BROADCAST_MD_CHANNEL,
EFUNC_BROADCAST_MD_MEMBER,
EFUNC_BROADCAST_MD_MEMBERSHIP,
EFUNC_CHECK_BANNED,
EFUNC_INTRODUCE_USER,
EFUNC_CHECK_DENY_VERSION,
EFUNC_BROADCAST_MD_CLIENT_CMD,
@ -2442,6 +2501,15 @@ enum EfunctionType {
EFUNC_WHOIS_GET_POLICY,
EFUNC_MAKE_OPER,
EFUNC_UNREAL_MATCH_IPLIST,
EFUNC_WEBSERVER_SEND_RESPONSE,
EFUNC_WEBSERVER_CLOSE_CLIENT,
EFUNC_WEBSERVER_HANDLE_BODY,
EFUNC_RPC_RESPONSE,
EFUNC_RPC_ERROR,
EFUNC_RPC_ERROR_FMT,
EFUNC_WEBSOCKET_HANDLE_WEBSOCKET,
EFUNC_WEBSOCKET_CREATE_PACKET,
EFUNC_WEBSOCKET_CREATE_PACKET_SIMPLE,
};
/* Module flags */

136
include/struct.h

@ -323,9 +323,10 @@ typedef enum LogDestination { LOG_DEST_SNOMASK=0, LOG_DEST_OPER=1, LOG_DEST_REMO
* @{
*/
typedef enum ClientStatus {
CLIENT_STATUS_CONTROL = -8, /**< Client is on the control channel */
CLIENT_STATUS_LOG = -7, /**< Client is a log file */
CLIENT_STATUS_TLS_STARTTLS_HANDSHAKE = -8, /**< Client is doing a STARTTLS handshake */
CLIENT_STATUS_RPC = -10, /**< RPC Client (either local or remote) */
CLIENT_STATUS_CONTROL = -9, /**< Client is on the control channel */
CLIENT_STATUS_LOG = -8, /**< Client is a log file */
CLIENT_STATUS_TLS_STARTTLS_HANDSHAKE = -7, /**< Client is doing a STARTTLS handshake */
CLIENT_STATUS_CONNECTING = -6, /**< Client is an outgoing connect */
CLIENT_STATUS_TLS_CONNECT_HANDSHAKE = -5, /**< Client is doing an TLS handshake - outgoing connection */
CLIENT_STATUS_TLS_ACCEPT_HANDSHAKE = -4, /**< Client is doing an TLS handshake - incoming connection */
@ -346,7 +347,8 @@ typedef enum ClientStatus {
/** Client is not fully registered yet. May become a user or a server, we don't know yet. */
#define IsUnknown(x) (((x)->status == CLIENT_STATUS_UNKNOWN) || ((x)->status == CLIENT_STATUS_TLS_STARTTLS_HANDSHAKE))
#define IsServer(x) ((x)->status == CLIENT_STATUS_SERVER) /**< Is a server that has completed the connection handshake */
#define IsControl(x) ((x)->status == CLIENT_STATUS_CONTROL) /**< Is on the control channel (not on IRC) */
#define IsControl(x) ((x)->status == CLIENT_STATUS_CONTROL) /**< Is on the control channel (not an IRC client) */
#define IsRPC(x) ((x)->status == CLIENT_STATUS_RPC) /**< Is doing RPC (not an IRC client) */
#define IsLog(x) ((x)->status == CLIENT_STATUS_LOG) /**< Is a log file, not a user or server */
#define IsStartTLSHandshake(x) ((x)->status == CLIENT_STATUS_TLS_STARTTLS_HANDSHAKE) /**< Currently doing a STARTTLS handshake */
#define IsTLSAcceptHandshake(x) ((x)->status == CLIENT_STATUS_TLS_ACCEPT_HANDSHAKE) /**< Currently doing a TLS handshake - incoming */
@ -364,6 +366,7 @@ typedef enum ClientStatus {
#define SetUser(x) ((x)->status = CLIENT_STATUS_USER)
#define SetLog(x) ((x)->status = CLIENT_STATUS_LOG)
#define SetControl(x) ((x)->status = CLIENT_STATUS_CONTROL)
#define SetRPC(x) ((x)->status = CLIENT_STATUS_RPC)
#define SetUser(x) ((x)->status = CLIENT_STATUS_USER)
/** @} */
@ -788,6 +791,20 @@ struct MOTDLine {
struct MOTDLine *next;
};
/** Current status of configuration in memory (what stage are we in..) */
typedef enum ConfigStatus {
CONFIG_STATUS_NONE = 0, /**< Config files have not been parsed yet */
CONFIG_STATUS_TEST = 1, /**< Currently running MOD_TEST() */
CONFIG_STATUS_POSTTEST = 2, /**< Currently running post_config_test hooks */
CONFIG_STATUS_PRE_INIT = 3, /**< In-between */
CONFIG_STATUS_INIT = 4, /**< Currently running MOD_INIT() */
CONFIG_STATUS_RUN_CONFIG = 5, /**< Currently running CONFIG_RUN hooks */
CONFIG_STATUS_LOAD = 6, /**< Currently running MOD_LOAD() */
CONFIG_STATUS_POSTLOAD = 7, /**< Doing post-load stuff like activating listeners */
CONFIG_STATUS_COMPLETE = 8, /**< Load or rehash complete */
CONFIG_STATUS_ROLLBACK = 99, /**< Configuration failed, rolling back changes */
} ConfigStatus;
struct LoopStruct {
unsigned do_garbage_collect : 1;
unsigned config_test : 1;
@ -801,6 +818,7 @@ struct LoopStruct {
unsigned rehash_download_busy : 1; /* don't return "all downloads complete", needed for race condition */
unsigned tainted : 1;
int rehashing;
ConfigStatus config_status;
Client *rehash_save_client;
void (*boot_function)();
};
@ -873,8 +891,9 @@ struct SWhois {
/** Command function - used by all command handlers.
* This is used in the code like <pre>CMD_FUNC(cmd_yourcmd)</pre> as a function definition.
* @param cptr The client direction pointer.
* @param client The source client pointer (you usually need this one).
* It allows UnrealIRCd devs to change the parameters in the function without
* (necessarily) breaking your code.
* @param client The client
* @param recv_mtags Received message tags for this command.
* @param parc Parameter count *plus* 1.
* @param parv Parameter values.
@ -1226,13 +1245,15 @@ extern ModDataInfo *ModDataAdd(Module *module, ModDataInfo req);
extern void ModDataDel(ModDataInfo *md);
extern void unload_all_unused_moddata(void);
#define LISTENER_NORMAL 0x000001
#define LISTENER_CLIENTSONLY 0x000002
#define LISTENER_SERVERSONLY 0x000004
#define LISTENER_TLS 0x000010
#define LISTENER_BOUND 0x000020
#define LISTENER_DEFER_ACCEPT 0x000040
#define LISTENER_CONTROL 0x000080 /**< Control channel */
#define LISTENER_NORMAL 0x000001
#define LISTENER_CLIENTSONLY 0x000002
#define LISTENER_SERVERSONLY 0x000004
#define LISTENER_TLS 0x000010
#define LISTENER_BOUND 0x000020
#define LISTENER_DEFER_ACCEPT 0x000040
#define LISTENER_CONTROL 0x000080 /**< Control channel */
#define LISTENER_NO_CHECK_CONNECT_FLOOD 0x000100 /**< Don't check for connect-flood and max-unknown-connections-per-ip (eg for RPC) */
#define LISTENER_NO_CHECK_ZLINED 0x000200 /**< Don't check for zlines */
#define IsServersOnlyListener(x) ((x) && ((x)->options & LISTENER_SERVERSONLY))
@ -1693,6 +1714,74 @@ struct ConfigItem_tld {
u_short options;
};
#define WEB_OPT_ENABLE 0x1
typedef enum HttpMethod {
HTTP_METHOD_NONE = 0, /**< No valid HTTP request (yet) */
HTTP_METHOD_HEAD = 1, /**< HEAD request */
HTTP_METHOD_GET = 2, /**< GET request */
HTTP_METHOD_PUT = 3, /**< PUT request */
HTTP_METHOD_POST = 4, /**< POST request */
} HttpMethod;
typedef enum TransferEncoding {
TRANSFER_ENCODING_NONE=0,
TRANSFER_ENCODING_CHUNKED=1
} TransferEncoding;
typedef struct WebRequest WebRequest;
struct WebRequest {
HttpMethod method; /**< GET/PUT/POST */
char *uri; /**< Requested resource, eg "/api" */
NameValuePrioList *headers; /**< HTTP request headers */
int num_headers; /**< Number of HTTP request headers (also used for sorting the list) */
char request_header_parsed; /**< Done parsing? */
char *lefttoparse; /**< Leftover buffer to parse */
int lefttoparselen; /**< Length of lefttoparse buffer */
int pending_close; /**< Set to 1 when connection should be closed as soon as all data is sent (sendq==0) */
char *request_buffer; /**< Buffer for POST data */
int request_buffer_size; /**< Size of buffer for POST data */
int request_body_complete; /**< POST data has all been read */
long long content_length; /**< "Content-Length" as sent by the client */
long long chunk_remaining;
TransferEncoding transfer_encoding;
long long config_max_request_buffer_size; /**< CONFIG: Maximum request length allowed */
};
typedef struct WebServer WebServer;
struct WebServer {
int (*handle_request)(Client *client, WebRequest *web);
int (*handle_body)(Client *client, WebRequest *web, const char *buf, int length);
};
typedef enum WebSocketType {
WEBSOCKET_TYPE_BINARY = 1,
WEBSOCKET_TYPE_TEXT = 2
} WebSocketType;
typedef struct WebSocketUser WebSocketUser;
struct WebSocketUser {
char get; /**< GET initiated */
char handshake_completed; /**< Handshake completed, use websocket frames */
char *handshake_key; /**< Handshake key (used during handshake) */
char *lefttoparse; /**< Leftover buffer to parse */
int lefttoparselen; /**< Length of lefttoparse buffer */
WebSocketType type; /**< WEBSOCKET_TYPE_BINARY or WEBSOCKET_TYPE_TEXT */
char *sec_websocket_protocol; /**< Only valid during parsing of the request, after that it is NULL again */
char *forwarded; /**< Unparsed `Forwarded:` header, RFC 7239 */
int secure; /**< If there is a Forwarded header, this indicates if the remote connection is secure */
};
#define WEBSOCKET_MAGIC_KEY "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" /* see RFC6455 */
/* Websocket operations: */
#define WSOP_CONTINUATION 0x00
#define WSOP_TEXT 0x01
#define WSOP_BINARY 0x02
#define WSOP_CLOSE 0x08
#define WSOP_PING 0x09
#define WSOP_PONG 0x0a
struct ConfigItem_listen {
ConfigItem_listen *prev, *next;
ConfigFlag flag;
@ -1704,7 +1793,10 @@ struct ConfigItem_listen {
int fd;
SSL_CTX *ssl_ctx;
TLSOptions *tls_options;
WebServer *webserver;
void (*start_handshake)(Client *client); /**< Function to call on accept() */
int websocket_options; /* should be in module, but lazy */
int rpc_options;
char *websocket_forward;
};
@ -2270,6 +2362,24 @@ typedef enum WhoisConfigDetails {
#define UNRL_STRIP_LOW_ASCII 0x1 /**< Strip all ASCII < 32 (control codes) */
#define UNRL_STRIP_KEEP_LF 0x2 /**< Do not strip LF (line feed, \n) */
/** JSON-RPC API Errors, according to jsonrpc.org spec */
typedef enum JsonRpcError {
// Official JSON-RPC error codes:
JSON_RPC_ERROR_PARSE_ERROR = -32700, /**< JSON parse error (fatal) */
JSON_RPC_ERROR_INVALID_REQUEST = -32600, /**< Invalid JSON-RPC Request */
JSON_RPC_ERROR_METHOD_NOT_FOUND = -32601, /**< Method not found */
JSON_RPC_ERROR_INVALID_PARAMS = -32602, /**< Method parameters invalid */
JSON_RPC_ERROR_INTERNAL_ERROR = -32603, /**< Internal server error */
// UnrealIRCd JSON-RPC server specific error codes:
JSON_RPC_ERROR_API_CALL_DENIED = -32000, /**< The api user does not have enough permissions to do this call */
// UnrealIRCd specific application error codes:
JSON_RPC_ERROR_NOT_FOUND = -1000, /**< Target not found (no such nick / channel / ..) */
JSON_RPC_ERROR_ALREADY_EXISTS = -1001, /**< Resource already exists by that name (eg on nickchange request, a gline, etc) */
JSON_RPC_ERROR_INVALID_NAME = -1002, /**< Name is not permitted (eg: nick, channel, ..) */
JSON_RPC_ERROR_USERNOTINCHANNEL = -1003, /**< The user is not in the channel */
JSON_RPC_ERROR_TOO_MANY_ENTRIES = -1004, /**< Too many entries (eg: banlist, ..) */
JSON_RPC_ERROR_DENIED = -1005, /**< Permission denied for user (unrelated to api user permissions) */
} JsonRpcError;
#endif /* __struct_include__ */
#include "dynconf.h"

4
include/windows/setup.h

@ -62,10 +62,10 @@
#define UNREAL_VERSION_MAJOR 0
/* Minor version number (e.g.: 1 for Unreal3.2.1) */
#define UNREAL_VERSION_MINOR 4
#define UNREAL_VERSION_MINOR 5
/* Version suffix such as a beta marker or release candidate marker. (e.g.:
-rcX for unrealircd-3.2.9-rcX) */
#define UNREAL_VERSION_SUFFIX ""
#define UNREAL_VERSION_SUFFIX "-git"
#endif

2
src/Makefile.in

@ -30,7 +30,7 @@ OBJS=ircd_vars.o dns.o auth.o channel.o crule.o dbuf.o \
version.o whowas.o random.o api-usermode.o api-channelmode.o \
api-moddata.o api-extban.o api-isupport.o api-command.o \
api-clicap.o api-messagetag.o api-history-backend.o api-efunctions.o \
api-event.o \
api-event.o api-rpc.o \
crypt_blowfish.o unrealdb.o crashreport.o modulemanager.o \
utf8.o log.o \
openssl_hostname_validation.o $(URL)

20
src/api-efunctions.c

@ -84,7 +84,6 @@ void (*broadcast_md_client)(ModDataInfo *mdi, Client *client, ModData *md);
void (*broadcast_md_channel)(ModDataInfo *mdi, Channel *channel, ModData *md);
void (*broadcast_md_member)(ModDataInfo *mdi, Channel *channel, Member *m, ModData *md);
void (*broadcast_md_membership)(ModDataInfo *mdi, Client *client, Membership *m, ModData *md);
int (*check_banned)(Client *client, int exitflags);
int (*check_deny_version)(Client *client, const char *software, int protocol, const char *flags);
void (*broadcast_md_client_cmd)(Client *except, Client *sender, Client *acptr, const char *varname, const char *value);
void (*broadcast_md_channel_cmd)(Client *except, Client *sender, Channel *channel, const char *varname, const char *value);
@ -137,6 +136,15 @@ char *(*get_chmodes_for_user)(Client *client, const char *flags);
WhoisConfigDetails (*whois_get_policy)(Client *client, Client *target, const char *name);
int (*make_oper)(Client *client, const char *operblock_name, const char *operclass, ConfigItem_class *clientclass, long modes, const char *snomask, const char *vhost);
int (*unreal_match_iplist)(Client *client, NameList *l);
void (*webserver_send_response)(Client *client, int status, char *msg);
void (*webserver_close_client)(Client *client);
int (*webserver_handle_body)(Client *client, WebRequest *web, const char *readbuf, int length);
void (*rpc_response)(Client *client, json_t *request, json_t *result);
void (*rpc_error)(Client *client, json_t *request, JsonRpcError error_code, const char *error_message);
void (*rpc_error_fmt)(Client *client, json_t *request, JsonRpcError error_code, const char *fmt, ...);
int (*websocket_handle_websocket)(Client *client, WebRequest *web, const char *readbuf2, int length2, int callback(Client *client, char *buf, int len));
int (*websocket_create_packet)(int opcode, char **buf, int *len);
int (*websocket_create_packet_simple)(int opcode, const char **buf, int *len);
Efunction *EfunctionAddMain(Module *module, EfunctionType eftype, int (*func)(), void (*vfunc)(), void *(*pvfunc)(), char *(*stringfunc)(), const char *(*conststringfunc)())
{
@ -349,7 +357,6 @@ void efunctions_init(void)
efunc_init_function(EFUNC_BROADCAST_MD_CHANNEL, broadcast_md_channel, NULL);
efunc_init_function(EFUNC_BROADCAST_MD_MEMBER, broadcast_md_member, NULL);
efunc_init_function(EFUNC_BROADCAST_MD_MEMBERSHIP, broadcast_md_membership, NULL);
efunc_init_function(EFUNC_CHECK_BANNED, check_banned, NULL);
efunc_init_function(EFUNC_INTRODUCE_USER, introduce_user, NULL);
efunc_init_function(EFUNC_CHECK_DENY_VERSION, check_deny_version, NULL);
efunc_init_function(EFUNC_BROADCAST_MD_CLIENT_CMD, broadcast_md_client_cmd, NULL);
@ -409,4 +416,13 @@ void efunctions_init(void)
efunc_init_function(EFUNC_WHOIS_GET_POLICY, whois_get_policy, NULL);
efunc_init_function(EFUNC_MAKE_OPER, make_oper, make_oper_default_handler);
efunc_init_function(EFUNC_UNREAL_MATCH_IPLIST, unreal_match_iplist, NULL);
efunc_init_function(EFUNC_WEBSERVER_SEND_RESPONSE, webserver_send_response, webserver_send_response_default_handler);
efunc_init_function(EFUNC_WEBSERVER_CLOSE_CLIENT, webserver_close_client, webserver_close_client_default_handler);
efunc_init_function(EFUNC_WEBSERVER_HANDLE_BODY, webserver_handle_body, webserver_handle_body_default_handler);
efunc_init_function(EFUNC_RPC_RESPONSE, rpc_response, rpc_response_default_handler);
efunc_init_function(EFUNC_RPC_ERROR, rpc_error, rpc_error_default_handler);
efunc_init_function(EFUNC_RPC_ERROR_FMT, rpc_error_fmt, rpc_error_fmt_default_handler);
efunc_init_function(EFUNC_WEBSOCKET_HANDLE_WEBSOCKET, websocket_handle_websocket, websocket_handle_websocket_default_handler);
efunc_init_function(EFUNC_WEBSOCKET_CREATE_PACKET, websocket_create_packet, websocket_create_packet_default_handler);
efunc_init_function(EFUNC_WEBSOCKET_CREATE_PACKET_SIMPLE, websocket_create_packet_simple, websocket_create_packet_simple_default_handler);
}

147
src/api-rpc.c

@ -0,0 +1,147 @@
/************************************************************************
* UnrealIRCd - Unreal Internet Relay Chat Daemon - src/api-rpc.c
* (c) 2022- Bram Matthys and The UnrealIRCd Team
* License: GPLv2 or later
*/
/** @file
* @brief RPC API
*/
#include "unrealircd.h"
/** This is the RPC API used for web requests.
* For an overview of available RPC's (not the API)
* see https://www.unrealircd.org/docs/RPC
* @defgroup RPCAPI RPC API
* @{
*/
/** List of RPC handlers */
MODVAR RPCHandler *rpchandlers = NULL;
/* Forward declarations */
static void unload_rpc_handler_commit(RPCHandler *m);
/** Adds a new RPC handler.
* @param module The module which owns this RPC handler.
* @param mreq The details of the request such as the method name, callback, etc.
* @return Returns the handle to the RPC handler if successful, otherwise NULL.
* The module's error code contains specific information about the
* error.
*/
RPCHandler *RPCHandlerAdd(Module *module, RPCHandlerInfo *mreq)
{
RPCHandler *m;
ModuleObject *mobj;
/* Some consistency checks to avoid a headache for module devs later on: */
if (!mreq->method || !mreq->call)
{
unreal_log(ULOG_ERROR, "module", "RPCHANDLERADD_API_ERROR", NULL,
"RPCHandlerAdd() from module $module_name: "
"Missing required fields.",
log_data_string("module_name", module->header->name));
abort();
}
m = RPCHandlerFind(mreq->method);
if (m)
{
if (m->unloaded)
{
m->unloaded = 0;
} else {
if (module)
module->errorcode = MODERR_EXISTS;
return NULL;
}
} else {
/* New RPC handler */
m = safe_alloc(sizeof(RPCHandler));
safe_strdup(m->method, mreq->method);
AddListItem(m, rpchandlers);
}
/* Add or update the following fields: */
m->owner = module;
m->flags = mreq->flags;
m->call = mreq->call;
/* Add module object */
mobj = safe_alloc(sizeof(ModuleObject));
mobj->type = MOBJ_RPC;
mobj->object.rpc = m;
AddListItem(mobj, module->objects);
module->errorcode = MODERR_NOERROR;
return m;
}
/** Returns the RPC handler for the given method name.
* @param method The method to search for.
* @return Returns the handle to the RPC handler,
* or NULL if not found.
*/
RPCHandler *RPCHandlerFind(const char *method)
{
RPCHandler *m;
for (m = rpchandlers; m; m = m->next)
{
if (!strcasecmp(method, m->method))
return m;
}
return NULL;
}
/** Remove the specified RPC handler - modules should not call this.
* This is done automatically for modules on unload, so is only called internally.
* @param m The PRC handler to remove.
*/
void RPCHandlerDel(RPCHandler *m)
{
if (m->owner)
{
ModuleObject *mobj;
for (mobj = m->owner->objects; mobj; mobj = mobj->next) {
if (mobj->type == MOBJ_RPC && mobj->object.rpc == m)
{
DelListItem(mobj, m->owner->objects);
safe_free(mobj);
break;
}
}
m->owner = NULL;
}
if (loop.rehashing)
m->unloaded = 1;
else
unload_rpc_handler_commit(m);
}
/** @} */
static void unload_rpc_handler_commit(RPCHandler *m)
{
/* This is an unusual operation, I think we should log it. */
unreal_log(ULOG_INFO, "module", "UNLOAD_RPC_HANDLER", NULL,
"Unloading RPC handler for '$method'",
log_data_string("method", m->method));
/* Destroy the object */
DelListItem(m, rpchandlers);
safe_free(m->method);
safe_free(m);
}
void unload_all_unused_rpc_handlers(void)
{
RPCHandler *m, *m_next;
for (m = rpchandlers; m; m = m_next)
{
m_next = m->next;
if (m->unloaded)
unload_rpc_handler_commit(m);
}
}

64
src/conf.c

@ -188,6 +188,8 @@ extern void unload_all_unused_extcmodes(void);
extern void unload_all_unused_extbans(void);
extern void unload_all_unused_caps(void);
extern void unload_all_unused_history_backends(void);
extern void unload_all_unused_rpc_handlers(void);
int reloadable_perm_module_unloaded(void);
int tls_tests(void);
@ -1979,6 +1981,7 @@ void config_load_failed(void)
{
if (conf)
unreal_log(ULOG_ERROR, "config", "CONFIG_NOT_LOADED", NULL, "IRCd configuration failed to load");
loop.config_status = CONFIG_STATUS_ROLLBACK;
Unload_all_testing_modules();
free_all_config_resources();
config_free(conf);
@ -2051,6 +2054,7 @@ int config_test(void)
}
config_status("Testing IRCd configuration..");
loop.config_status = CONFIG_STATUS_TEST;
memset(&tempiConf, 0, sizeof(iConf));
memset(&settings, 0, sizeof(settings));
@ -2069,12 +2073,14 @@ int config_test(void)
preprocessor_resolve_conditionals_all(PREPROCESSOR_PHASE_MODULE);
loop.config_status = CONFIG_STATUS_POSTTEST;
if (!config_test_all())
{
config_error("IRCd configuration failed to pass testing");
config_load_failed();
return -1;
}
loop.config_status = CONFIG_STATUS_PRE_INIT;
callbacks_switchover();
efunctions_switchover();
set_targmax_defaults();
@ -2099,8 +2105,10 @@ int config_test(void)
}
config_pre_run_log();
loop.config_status = CONFIG_STATUS_INIT;
Init_all_testing_modules();
loop.config_status = CONFIG_STATUS_RUN_CONFIG;
if (config_run_blocks() < 0)
{
config_error("Bad case of config errors. Server will now die. This really shouldn't happen");
@ -2124,9 +2132,11 @@ int config_test(void)
conf = NULL;
if (loop.rehashing)
{
/* loop.config_status = CONFIG_STATUS_LOAD is done by module_loadall() */
module_loadall();
RunHook(HOOKTYPE_REHASH_COMPLETE);
}
loop.config_status = CONFIG_STATUS_POSTLOAD;
postconf();
unreal_log(ULOG_INFO, "config", "CONFIG_LOADED", NULL, "Configuration loaded");
clicap_post_rehash();
@ -4900,18 +4910,6 @@ int _test_tld(ConfigFile *conf, ConfigEntry *ce)
ce->file->filename, ce->line_number, ce->name);
errors++;
}
if (!has_motd)
{
config_error_missing(ce->file->filename, ce->line_number,
"tld::motd");
errors++;
}
if (!has_rules)
{
config_error_missing(ce->file->filename, ce->line_number,
"tld::rules");
errors++;
}
return errors;
}
@ -4988,6 +4986,7 @@ int _conf_listen(ConfigFile *conf, ConfigEntry *ce)
} else {
isnew = 0;
}
listen->start_handshake = start_of_normal_client_handshake;
if (listen->options & LISTENER_BOUND)
tmpflags |= LISTENER_BOUND;
@ -4997,6 +4996,40 @@ int _conf_listen(ConfigFile *conf, ConfigEntry *ce)
AddListItem(listen, conf_listen);
listen->flag.temporary = 0;
/* For modules that hook CONFIG_LISTEN and CONFIG_LISTEN_OPTIONS.
* Yeah, ugly we have this here..
*/
for (cep = ce->items; cep; cep = cep->next)
{
if (!strcmp(cep->name, "file"))
;
else if (!strcmp(cep->name, "ssl-options") || !strcmp(cep->name, "tls-options"))
;
else if (!strcmp(cep->name, "options"))
{
for (cepp = cep->items; cepp; cepp = cepp->next)
{
if (!nv_find_by_name(_ListenerFlags, cepp->name))
{
for (h = Hooks[HOOKTYPE_CONFIGRUN_EX]; h; h = h->next)
{
int value = (*(h->func.intfunc))(conf, cepp, CONFIG_LISTEN_OPTIONS, listen);
if (value == 1)
break;
}
}
}
} else
{
for (h = Hooks[HOOKTYPE_CONFIGRUN_EX]; h; h = h->next)
{
int value = (*(h->func.intfunc))(conf, cep, CONFIG_LISTEN, listen);
if (value == 1)
break;
}
}
}
return 1;
}
@ -5016,6 +5049,8 @@ int _conf_listen(ConfigFile *conf, ConfigEntry *ce)
} else
isnew = 0;
listen->start_handshake = start_of_normal_client_handshake;
if (listen->options & LISTENER_BOUND)
tmpflags |= LISTENER_BOUND;
@ -5101,6 +5136,8 @@ int _conf_listen(ConfigFile *conf, ConfigEntry *ce)
} else
isnew = 0;
listen->start_handshake = start_of_normal_client_handshake;
if (listen->options & LISTENER_BOUND)
tmpflags |= LISTENER_BOUND;
@ -9579,6 +9616,7 @@ void start_listeners(void)
/* Actually use configuration */
void config_run(void)
{
loop.config_status = CONFIG_STATUS_POSTLOAD;
extcmodes_check_for_changes();
start_listeners();
add_proc_io_server();
@ -10782,6 +10820,7 @@ int rehash_internal(Client *client)
unload_all_unused_extbans();
unload_all_unused_caps();
unload_all_unused_history_backends();
unload_all_unused_rpc_handlers();
// unload_all_unused_moddata(); -- this will crash
umodes_check_for_changes();
charsys_check_for_changes();
@ -10790,6 +10829,7 @@ int rehash_internal(Client *client)
loop.rehashing = 0;
remote_rehash_client = NULL;
procio_post_rehash(failure);
loop.config_status = CONFIG_STATUS_COMPLETE;
return 1;
}

5
src/ircd.c

@ -121,7 +121,9 @@ EVENT(handshake_timeout)
list_for_each_entry_safe(client, next, &unknown_list, lclient_node)
{
if (client->local->creationtime && ((TStime() - client->local->creationtime) > iConf.handshake_timeout))
if (client->local->creationtime &&
((TStime() - client->local->creationtime) > iConf.handshake_timeout) &&
!(client->local->listener && (client->local->listener->socket_type == SOCKET_TYPE_UNIX)))
{
if (client->server && *client->server->by)
continue; /* handled by server module */
@ -854,6 +856,7 @@ int InitUnrealIRCd(int argc, char *argv[])
PS_STRINGS->ps_argvstr = me.name;
#endif
module_loadall();
loop.config_status = CONFIG_STATUS_COMPLETE;
#ifndef _WIN32
SocketLoop(NULL);

19
src/list.c

@ -160,6 +160,19 @@ void free_client(Client *client)
RunHook(HOOKTYPE_FREE_CLIENT, client);
if (client->local)
{
if (client->local->listener)
{
if (client->local->listener && !IsOutgoing(client))
{
ConfigItem_listen *listener = client->local->listener;
listener->clients--;
if (listener->flag.temporary && (listener->clients == 0))
{
/* Call listen cleanup */
listen_cleanup();
}
}
}
safe_free(client->local->passwd);
safe_free(client->local->error_str);
if (client->local->hostp)
@ -590,6 +603,12 @@ NameValuePrioList *find_nvplist(NameValuePrioList *list, const char *name)
return NULL;
}
const char *get_nvplist(NameValuePrioList *list, const char *name)
{
NameValuePrioList *e = find_nvplist(list, name);
return e ? e->value : NULL;
}
void add_fmt_nvplist(NameValuePrioList **lst, int priority, const char *name, FORMAT_STRING(const char *format), ...)
{
char value[512];

28
src/log.c