mirror of
git://git.acid.vegas/unrealircd.git
synced 2024-12-27 16:56:37 +00:00
Updated to 6.0.3
This commit is contained in:
parent
4e71d6fead
commit
252e8547f4
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,7 +9,6 @@ extras/c-ares*
|
||||
config.status
|
||||
extras/ircdcron/ircd.cron
|
||||
extras/ircdcron/ircdchk
|
||||
src/modules/snomasks/Makefile
|
||||
src/modules/chanmodes/Makefile
|
||||
src/modules/extbans/Makefile
|
||||
src/modules/usermodes/Makefile
|
||||
|
32
Config
32
Config
@ -18,7 +18,24 @@
|
||||
|
||||
# some bits edited by baafie on March 17 2004, every change marked.
|
||||
|
||||
# Remove trailing slash in paths (if any)
|
||||
FIX_PATHNAMES () {
|
||||
BASEPATH="${BASEPATH%/}"
|
||||
BINDIR="${BINDIR%/}"
|
||||
DATADIR="${DATADIR%/}"
|
||||
CONFDIR="${CONFDIR%/}"
|
||||
MODULESDIR="${MODULESDIR%/}"
|
||||
LOGDIR="${LOGDIR%/}"
|
||||
CACHEDIR="${CACHEDIR%/}"
|
||||
DOCDIR="${DOCDIR%/}"
|
||||
TMPDIR="${TMPDIR%/}"
|
||||
PRIVATELIBDIR="${PRIVATELIBDIR%/}"
|
||||
SSLDIR="${SSLDIR%/}"
|
||||
CURLDIR="${CURLDIR%/}"
|
||||
}
|
||||
|
||||
# Create and run the ./configure command with the appropriate
|
||||
# options based on the users settings.
|
||||
RUN_CONFIGURE () {
|
||||
ARG=" "
|
||||
|
||||
@ -72,6 +89,7 @@ fi
|
||||
ARG="$ARG--with-bindir=$BINDIR "
|
||||
ARG="$ARG--with-datadir=$DATADIR "
|
||||
ARG="$ARG--with-pidfile=$DATADIR/unrealircd.pid "
|
||||
ARG="$ARG--with-controlfile=$DATADIR/unrealircd.ctl "
|
||||
ARG="$ARG--with-confdir=$CONFDIR "
|
||||
ARG="$ARG--with-modulesdir=$MODULESDIR "
|
||||
ARG="$ARG--with-logdir=$LOGDIR "
|
||||
@ -292,6 +310,7 @@ while [ $# -ge 1 ] ; do
|
||||
if [ -f "config.settings" ] ; then
|
||||
. ./config.settings
|
||||
fi
|
||||
FIX_PATHNAMES
|
||||
RUN_CONFIGURE
|
||||
cd "$UNREALCWD"
|
||||
exit 0
|
||||
@ -356,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.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.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
|
||||
@ -701,11 +720,12 @@ while [ -z "$TEST" ] ; do
|
||||
TEST="$GEOIP"
|
||||
echo ""
|
||||
echo "GeoIP is a feature that allows converting an IP address to a location (country)"
|
||||
echo "You have three options in UnrealIRCd:"
|
||||
echo " classic: This is the DEFAULT geoip engine that should work on all systems"
|
||||
echo "libmaxminddb: This uses the libmaxminddb library. If you want to use it then"
|
||||
echo "Possible build options:"
|
||||
echo " classic: This is the DEFAULT geoip engine. It should work on all systems"
|
||||
echo " and receives automatic updates."
|
||||
echo "libmaxminddb: This uses the libmaxminddb library. If you want to use this, then"
|
||||
echo " you need to install the libmaxminddb library on your system first"
|
||||
echo " none: Don't built with any geoip feature"
|
||||
echo " none: Don't build with any geoip library (geoip-csv is still built)"
|
||||
echo "Choose one of: classic, libmaxminddb, none"
|
||||
echo $n "[$TEST] -> $c"
|
||||
read cc
|
||||
@ -814,6 +834,8 @@ if [ -z "$EXTRAPARA" ]; then
|
||||
EXTRAPARA="$TEST"
|
||||
fi
|
||||
|
||||
FIX_PATHNAMES
|
||||
|
||||
rm -f config.settings
|
||||
cat > config.settings << __EOF__
|
||||
#
|
||||
|
@ -179,13 +179,13 @@ depend:
|
||||
install: all
|
||||
$(INSTALL) -m 0700 -d $(DESTDIR)@BINDIR@
|
||||
$(INSTALL) -m 0700 src/ircd $(DESTDIR)@BINDIR@/unrealircd
|
||||
$(INSTALL) -m 0700 src/unrealircdctl $(DESTDIR)@BINDIR@/unrealircdctl
|
||||
$(INSTALL) -m 0700 extras/unrealircd-upgrade-script $(DESTDIR)@BINDIR@/unrealircd-upgrade-script
|
||||
$(INSTALL) -m 0700 -d $(DESTDIR)@DOCDIR@
|
||||
$(INSTALL) -m 0600 doc/Authors doc/coding-guidelines doc/tao.of.irc doc/KEYS doc/RELEASE-NOTES.md $(DESTDIR)@DOCDIR@
|
||||
$(INSTALL) -m 0700 -d $(DESTDIR)@CONFDIR@
|
||||
$(INSTALL) -m 0600 doc/conf/*.conf $(DESTDIR)@CONFDIR@
|
||||
$(INSTALL) -m 0600 doc/conf/*.motd $(DESTDIR)@CONFDIR@
|
||||
$(INSTALL) -m 0600 doc/conf/modules.sources.list $(DESTDIR)@CONFDIR@ ; \
|
||||
$(INSTALL) -m 0700 unrealircd $(DESTDIR)@SCRIPTDIR@
|
||||
$(INSTALL) -m 0700 -d $(DESTDIR)@MODULESDIR@
|
||||
@rm -f $(DESTDIR)@MODULESDIR@/*.so 1>/dev/null 2>&1
|
||||
|
@ -165,8 +165,7 @@ CFLAGS=$(DBGCFLAG) $(STDOPTIONS) /FS /MP1 /c /Fosrc/
|
||||
CFLAGSST=$(DBGCFLAGST) $(STDOPTIONS) /FS /MP1 /c /Fosrc/
|
||||
LFLAGS=kernel32.lib user32.lib gdi32.lib shell32.lib ws2_32.lib advapi32.lib \
|
||||
dbghelp.lib oldnames.lib comctl32.lib comdlg32.lib $(STDLIBS) \
|
||||
/def:UnrealIRCd.def /implib:UnrealIRCd.lib \
|
||||
/nologo $(DBGLFLAG) /out:UnrealIRCd.exe
|
||||
/nologo $(DBGLFLAG)
|
||||
MODCFLAGS=$(MODDBGCFLAG) $(STDOPTIONS) /D DYNAMIC_LINKING /D MODULE_COMPILE
|
||||
MODLFLAGS=/link /def:src/modules/module.def UnrealIRCd.lib ws2_32.lib $(STDLIBS)
|
||||
|
||||
@ -174,10 +173,10 @@ INCLUDES=./include/struct.h ./include/config.h ./include/sys.h \
|
||||
./include/common.h ./include/version.h ./include/h.h ./include/numeric.h \
|
||||
./include/msg.h ./include/setup.h ./include/dynconf.h
|
||||
|
||||
EXP_OBJ_FILES=src/channel.obj src/send.obj src/socket.obj \
|
||||
src/conf.obj src/conf_preprocessor.obj \
|
||||
EXP_OBJ_FILES=src/ircd_vars.obj src/channel.obj src/send.obj src/socket.obj \
|
||||
src/conf.obj src/proc_io_server.obj src/conf_preprocessor.obj \
|
||||
src/fdlist.obj src/dbuf.obj \
|
||||
src/hash.obj src/parse.obj src/ircd.obj \
|
||||
src/hash.obj src/parse.obj \
|
||||
src/whowas.obj \
|
||||
src/misc.obj src/match.obj src/crule.obj \
|
||||
src/debug.obj src/support.obj src/list.obj \
|
||||
@ -194,7 +193,7 @@ EXP_OBJ_FILES=src/channel.obj src/send.obj src/socket.obj \
|
||||
src/utf8.obj src/log.obj $(CURLOBJ)
|
||||
|
||||
OBJ_FILES=$(EXP_OBJ_FILES) src/gui.obj src/service.obj src/windebug.obj src/rtf.obj \
|
||||
src/editor.obj src/win.obj
|
||||
src/editor.obj src/win.obj src/ircd.obj src/proc_io_client.obj
|
||||
|
||||
DLL_FILES=\
|
||||
src/modules/account-notify.dll \
|
||||
@ -411,7 +410,7 @@ DLL_FILES=\
|
||||
src/modules/whox.dll
|
||||
|
||||
|
||||
ALL: CONF UNREALSVC.EXE UnrealIRCd.exe MODULES
|
||||
ALL: CONF unrealircdctl.exe UNREALSVC.EXE UnrealIRCd.exe MODULES
|
||||
|
||||
CLEAN:
|
||||
-@del /Q /S *.dll *.exe *.obj *.pdb *.res *.lib *.exp *.ilk src\version.c >NUL
|
||||
@ -424,21 +423,27 @@ CONF:
|
||||
$(CC) src/windows/config.c
|
||||
-@config.exe
|
||||
|
||||
UnrealIRCd.exe: $(OBJ_FILES) src/windows/win.res
|
||||
$(LINK) $(LFLAGS) $(OBJ_FILES) src/windows/win.res /MAP
|
||||
UnrealIRCd.exe: $(OBJ_FILES) src/ircd.obj src/windows/win.res
|
||||
$(LINK) $(LFLAGS) /out:UnrealIRCd.exe /def:UnrealIRCd.def /implib:UnrealIRCd.lib $(OBJ_FILES) src/windows/win.res /MAP
|
||||
-@erase src\windows\win.res
|
||||
$(MT) -manifest src\windows\UnrealIRCd.exe.manifest -outputresource:UnrealIRCd.exe;1
|
||||
!IFNDEF DEBUGEXTRA
|
||||
@echo Standard version built
|
||||
!ELSE
|
||||
@echo Extra-Debug version built ...
|
||||
!ENDIF
|
||||
|
||||
unrealircdctl.exe: $(OBJ_FILES) src/unrealircdctl.obj src/proc_io_client.obj
|
||||
$(LINK) $(LFLAGS) /SUBSYSTEM:CONSOLE /out:unrealircdctl.exe $(OBJ_FILES) src/unrealircdctl.obj
|
||||
$(MT) -manifest src\windows\unrealircdctl.exe.manifest -outputresource:unrealircdctl.exe;1
|
||||
|
||||
# alternative option -- FIXME: REMOVE / CHOOSE
|
||||
#unrealircdctl.exe: $(OBJ_FILES) src/unrealircdctl.obj src/proc_io_client.obj src/windows/unrealircdctl.res
|
||||
# $(LINK) $(LFLAGS) /out:unrealircdctl.exe $(OBJ_FILES) src/unrealircdctl.obj src/windows/unrealircdctl.res
|
||||
|
||||
#Source files
|
||||
|
||||
src/version.obj: src/version.c
|
||||
$(CC) $(CFLAGS) src/version.c
|
||||
|
||||
src/ircd_vars.obj: src/ircd_vars.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/ircd_vars.c
|
||||
|
||||
src/parse.obj: src/parse.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/parse.c
|
||||
|
||||
@ -485,6 +490,12 @@ src/dns.obj: src/dns.c $(INCLUDES)
|
||||
src/conf.obj: src/conf.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/conf.c
|
||||
|
||||
src/proc_io_server.obj: src/proc_io_server.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/proc_io_server.c
|
||||
|
||||
src/proc_io_client.obj: src/proc_io_client.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/proc_io_client.c
|
||||
|
||||
src/conf_preprocessor.obj: src/conf_preprocessor.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/conf_preprocessor.c
|
||||
|
||||
@ -540,6 +551,9 @@ src/win.obj: src/windows/win.c $(INCLUDES)
|
||||
src/unrealsvc.obj: src/windows/unrealsvc.c $(INCLUDES)
|
||||
$(CC) $(CFLAGSST) src/windows/unrealsvc.c
|
||||
|
||||
src/unrealircdctl.obj: src/unrealircdctl.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/unrealircdctl.c
|
||||
|
||||
src/modules.obj: src/modules.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/modules.c
|
||||
|
||||
@ -623,6 +637,10 @@ src/windows/unrealsvc.res: src/windows/unrealsvc.rc
|
||||
$(RC) /l 0x409 /fosrc/windows/unrealsvc.res /i ./include /i ./src \
|
||||
/d NDEBUG src/windows/unrealsvc.rc
|
||||
|
||||
src/windows/unrealircdctl.res: src/windows/unrealircdctl.rc
|
||||
$(RC) /l 0x409 /fosrc/windows/unrealircdctl.res /i ./include /i ./src \
|
||||
/d NDEBUG src/windows/unrealircdctl.rc
|
||||
|
||||
################# Modules #################
|
||||
|
||||
CUSTOMMODULE: src/modules/third/$(MODULEFILE).c
|
||||
|
51
configure
vendored
51
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.1.1.
|
||||
# Generated by GNU Autoconf 2.69 for unrealircd 6.0.3.
|
||||
#
|
||||
# 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.1.1'
|
||||
PACKAGE_STRING='unrealircd 6.0.1.1'
|
||||
PACKAGE_VERSION='6.0.3'
|
||||
PACKAGE_STRING='unrealircd 6.0.3'
|
||||
PACKAGE_BUGREPORT='https://bugs.unrealircd.org/'
|
||||
PACKAGE_URL='https://unrealircd.org/'
|
||||
|
||||
@ -659,6 +659,7 @@ PKG_CONFIG_LIBDIR
|
||||
PKG_CONFIG_PATH
|
||||
PKG_CONFIG
|
||||
LDFLAGS_PRIVATELIBS
|
||||
CONTROLFILE
|
||||
PIDFILE
|
||||
DOCDIR
|
||||
PERMDATADIR
|
||||
@ -752,6 +753,7 @@ with_tmpdir
|
||||
with_datadir
|
||||
with_docdir
|
||||
with_pidfile
|
||||
with_controlfile
|
||||
with_privatelibdir
|
||||
with_maxconnections
|
||||
with_no_operoverride
|
||||
@ -1345,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.1.1 to adapt to many kinds of systems.
|
||||
\`configure' configures unrealircd 6.0.3 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@ -1411,7 +1413,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of unrealircd 6.0.1.1:";;
|
||||
short | recursive ) echo "Configuration of unrealircd 6.0.3:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@ -1460,6 +1462,7 @@ Optional Packages:
|
||||
--with-datadir=path Specify the directory where permanent data is stored
|
||||
--with-docdir=path Specify the directory where documentation is stored
|
||||
--with-pidfile=path Specify the path of the pid file
|
||||
--with-controlfile=path Specify the path of the control socket
|
||||
--with-privatelibdir=path
|
||||
Specify the directory where private libraries are
|
||||
stored. Disable when building a package for a distro
|
||||
@ -1586,7 +1589,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
unrealircd configure 6.0.1.1
|
||||
unrealircd configure 6.0.3
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@ -1955,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.1.1, which was
|
||||
It was created by unrealircd $as_me 6.0.3, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@ -2363,7 +2366,7 @@ _ACEOF
|
||||
|
||||
|
||||
# Minor version number (e.g.: Z in X.Y.Z)
|
||||
UNREAL_VERSION_MINOR="1"
|
||||
UNREAL_VERSION_MINOR="3"
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define UNREAL_VERSION_MINOR $UNREAL_VERSION_MINOR
|
||||
@ -2373,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=".1"
|
||||
UNREAL_VERSION_SUFFIX=""
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define UNREAL_VERSION_SUFFIX "$UNREAL_VERSION_SUFFIX"
|
||||
@ -6548,6 +6551,25 @@ fi
|
||||
|
||||
|
||||
|
||||
# Check whether --with-controlfile was given.
|
||||
if test "${with_controlfile+set}" = set; then :
|
||||
withval=$with_controlfile;
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define CONTROLFILE "$withval"
|
||||
_ACEOF
|
||||
|
||||
CONTROLFILE="$withval"
|
||||
else
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define CONTROLFILE "$HOME/unrealircd/data/unrealircd.ctl"
|
||||
_ACEOF
|
||||
|
||||
CONTROLFILE="$HOME/unrealircd/data/unrealircd.ctl"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Check whether --with-privatelibdir was given.
|
||||
if test "${with_privatelibdir+set}" = set; then :
|
||||
withval=$with_privatelibdir;
|
||||
@ -6589,6 +6611,7 @@ fi
|
||||
|
||||
|
||||
|
||||
|
||||
# Check whether --with-maxconnections was given.
|
||||
if test "${with_maxconnections+set}" = set; then :
|
||||
withval=$with_maxconnections; ac_fd=$withval
|
||||
@ -7438,7 +7461,7 @@ fi
|
||||
|
||||
if test "$has_system_pcre2" = "no"; then :
|
||||
|
||||
pcre2_version="10.36"
|
||||
pcre2_version="10.39"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: extracting PCRE2 regex library" >&5
|
||||
$as_echo "extracting PCRE2 regex library" >&6; }
|
||||
cur_dir=`pwd`
|
||||
@ -7455,7 +7478,7 @@ fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: configuring PCRE2 regex library" >&5
|
||||
$as_echo "configuring PCRE2 regex library" >&6; }
|
||||
cd pcre2-$pcre2_version
|
||||
./configure --enable-jit --enable-shared --disable-unicode --prefix=$cur_dir/extras/pcre2 --libdir=$PRIVATELIBDIR || exit 1
|
||||
./configure --enable-jit --enable-shared --prefix=$cur_dir/extras/pcre2 --libdir=$PRIVATELIBDIR || exit 1
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: compiling PCRE2 regex library" >&5
|
||||
$as_echo "compiling PCRE2 regex library" >&6; }
|
||||
$ac_cv_prog_MAKER || exit 1
|
||||
@ -7798,7 +7821,7 @@ fi
|
||||
|
||||
if test "$has_system_cares" = "no"; then :
|
||||
|
||||
cares_version="1.17.2"
|
||||
cares_version="1.18.1"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: extracting c-ares resolver library" >&5
|
||||
$as_echo "extracting c-ares resolver library" >&6; }
|
||||
cur_dir=`pwd`
|
||||
@ -9391,7 +9414,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.1.1, which was
|
||||
This file was extended by unrealircd $as_me 6.0.3, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@ -9454,7 +9477,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.1.1
|
||||
unrealircd config.status 6.0.3
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
19
configure.ac
19
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.1.1], [https://bugs.unrealircd.org/], [], [https://unrealircd.org/])
|
||||
AC_INIT([unrealircd], [6.0.3], [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=["1"]
|
||||
UNREAL_VERSION_MINOR=["3"]
|
||||
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=[".1"]
|
||||
UNREAL_VERSION_SUFFIX=[""]
|
||||
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)
|
||||
@ -484,6 +484,12 @@ AC_ARG_WITH(pidfile, [AS_HELP_STRING([--with-pidfile=path],[Specify the path of
|
||||
[AC_DEFINE_UNQUOTED([PIDFILE], ["$HOME/unrealircd/data/unrealircd.pid"], [Define the path of the pid file])
|
||||
PIDFILE="$HOME/unrealircd/data/unrealircd.pid"])
|
||||
|
||||
AC_ARG_WITH(controlfile, [AS_HELP_STRING([--with-controlfile=path],[Specify the path of the control socket])],
|
||||
[AC_DEFINE_UNQUOTED([CONTROLFILE], ["$withval"], [Define the path of the control socket])
|
||||
CONTROLFILE="$withval"],
|
||||
[AC_DEFINE_UNQUOTED([CONTROLFILE], ["$HOME/unrealircd/data/unrealircd.ctl"], [Define the path of the control socket])
|
||||
CONTROLFILE="$HOME/unrealircd/data/unrealircd.ctl"])
|
||||
|
||||
dnl Ensure that this “feature” can be disabled as it makes it harder to package unrealircd.
|
||||
dnl Users have always been able to specify “./configure LDFLAGS=-Wl,-rpath,/path/to/blah”—binki
|
||||
AC_ARG_WITH(privatelibdir, [AS_HELP_STRING([--with-privatelibdir=path],[Specify the directory where private libraries are stored. Disable when building a package for a distro])],
|
||||
@ -514,6 +520,7 @@ dnl well, Because DATADIR conflicts with the Windows SDK header files.. amazing.
|
||||
AC_SUBST(PERMDATADIR)
|
||||
AC_SUBST(DOCDIR)
|
||||
AC_SUBST(PIDFILE)
|
||||
AC_SUBST(CONTROLFILE)
|
||||
AC_SUBST(LDFLAGS_PRIVATELIBS)
|
||||
|
||||
AC_ARG_WITH(maxconnections, [AS_HELP_STRING([--with-maxconnections=size], [Specify the max file descriptors to use])],
|
||||
@ -576,7 +583,7 @@ AS_IF([test "x$PRIVATELIBDIR" != "x"], [rm -f "$PRIVATELIBDIR/"libpcre2*])],[has
|
||||
|
||||
AS_IF([test "$has_system_pcre2" = "no"], [
|
||||
dnl REMEMBER TO CHANGE WITH A NEW PCRE2 RELEASE!
|
||||
pcre2_version="10.36"
|
||||
pcre2_version="10.39"
|
||||
AC_MSG_RESULT(extracting PCRE2 regex library)
|
||||
cur_dir=`pwd`
|
||||
cd extras
|
||||
@ -593,7 +600,7 @@ else
|
||||
fi
|
||||
AC_MSG_RESULT(configuring PCRE2 regex library)
|
||||
cd pcre2-$pcre2_version
|
||||
./configure --enable-jit --enable-shared --disable-unicode --prefix=$cur_dir/extras/pcre2 --libdir=$PRIVATELIBDIR || exit 1
|
||||
./configure --enable-jit --enable-shared --prefix=$cur_dir/extras/pcre2 --libdir=$PRIVATELIBDIR || exit 1
|
||||
AC_MSG_RESULT(compiling PCRE2 regex library)
|
||||
$ac_cv_prog_MAKER || exit 1
|
||||
AC_MSG_RESULT(installing PCRE2 regex library)
|
||||
@ -716,7 +723,7 @@ AS_IF([test "$has_system_cares" = "no"], [
|
||||
dnl REMEMBER TO CHANGE WITH A NEW C-ARES RELEASE!
|
||||
dnl NOTE: when changing this here, ALSO change it in extras/curlinstall
|
||||
dnl and in the comment in this file around line 400!
|
||||
cares_version="1.17.2"
|
||||
cares_version="1.18.1"
|
||||
AC_MSG_RESULT(extracting c-ares resolver library)
|
||||
cur_dir=`pwd`
|
||||
cd extras
|
||||
|
@ -7,7 +7,7 @@
|
||||
\___/|_| |_|_| \___|\__,_|_|\___/\_| \_| \____/\__,_|
|
||||
|
||||
Configuration Program
|
||||
for UnrealIRCd 6.0.1.1
|
||||
for UnrealIRCd 6.0.3
|
||||
|
||||
This program will help you to compile your IRC server, and ask you
|
||||
questions regarding the compile-time settings of it during the process.
|
||||
|
@ -1,8 +1,139 @@
|
||||
UnrealIRCd 6.0.3
|
||||
=================
|
||||
|
||||
A number of serious issues were discovered in UnrealIRCd 6. Among these is
|
||||
an issue which will likely crash the IRCd sooner or later if you /REHASH
|
||||
with any active clients connected.
|
||||
We suggest everyone who is running UnrealIRCd 6 to upgrade to 6.0.3.
|
||||
|
||||
If you are already running UnrealIRCd 6 then read below. Otherwise, jump
|
||||
straight to the [summary about UnrealIRCd 6](#Summary) to learn more
|
||||
about UnrealIRCd 6.
|
||||
|
||||
Fixes:
|
||||
* Crash in `WATCH` if the IRCd has been rehashed at least once. After doing
|
||||
a `REHASH` with active clients it will likely corrupt memory. It may take
|
||||
several days until after the rehash for the crash to occur, or even
|
||||
weeks/months on smaller networks (accidental triggering, that is).
|
||||
* A `REHASH` with certain remote includes setups could cause a crash or
|
||||
other weird and confusing problems such as complaining about unable
|
||||
to open an ipv6-database or missing snomask configuration.
|
||||
This only affected some people with remote includes, not all.
|
||||
* Potential out-of-bounds write in sending code. In practice it seems
|
||||
harmless on most servers but this cannot be 100% guaranteed.
|
||||
* Unlikely triggered log message would log uninitialized stack data to the
|
||||
log file or send it to ircops.
|
||||
* Channel ops could not remove halfops from a user (`-h`).
|
||||
* After using the `RESTART` command (not recommended) the new IRCd was
|
||||
often no longer writing to log files.
|
||||
* Fix compile problem if you choose to use cURL remote includes but don't
|
||||
have cURL on the system and ask UnrealIRCd to compile cURL.
|
||||
|
||||
Enhancements:
|
||||
* The default text log format on disk changed. It now includes the server
|
||||
name where the event was generated. Without this, it was sometimes
|
||||
difficult to trace problems, since previously it sometimes looked like
|
||||
there was a problem on your server when it was actually another server
|
||||
on the network.
|
||||
* Old log format: `[DATE TIME] subsystem.EVENT_ID loglevel: ........`
|
||||
* New log format: `[DATE TIME] servername subsystem.EVENT_ID loglevel: ........`
|
||||
|
||||
Changes:
|
||||
* Any MOTD lines added by services via
|
||||
[`SVSMOTD`](https://www.unrealircd.org/docs/MOTD_and_Rules#SVSMOTD)
|
||||
are now shown at the end of the MOTD-on-connect (unless using a shortmotd).
|
||||
Previously the lines were only shown if you manually ran the `MOTD` command.
|
||||
|
||||
Developers and protocol:
|
||||
* `LIST C<xx` now means: filter on channels that are created less
|
||||
than `xx` minutes ago. This is the opposite of what we had earlier.
|
||||
`LIST T<xx` is now supported as well (topic changed in last xx minutes),
|
||||
it was already advertised in ELIST but support was not enabled previously.
|
||||
|
||||
UnrealIRCd 6.0.2
|
||||
-----------------
|
||||
UnrealIRCd 6.0.2 comes with several nice feature enhancements along with
|
||||
some fixes. It also includes a fix for a crash bug that can be triggered
|
||||
by ordinary users.
|
||||
|
||||
Fixes:
|
||||
* Fix crash that can be triggered by regular users if you have any `deny dcc`
|
||||
blocks in the config or any spamfilters with the `d` (DCC) target.
|
||||
NOTE: You don't *have* to upgrade to 6.0.2 to fix this, you can also
|
||||
hot-patch this issue without restart, see the news announcement.
|
||||
* Windows: fix crash with IPv6 clients (local or remote) due to GeoIP lookup
|
||||
* Fix infinite hang on "Loading IRCd configuration" if DNS is not working.
|
||||
For example if the 1st DNS server in `/etc/resolv.conf` is down or refusing
|
||||
requests.
|
||||
* Some `MODE` server-to-server commands were missing a timestamp at the end,
|
||||
even though this is mandatory for modes coming from a server.
|
||||
* The [channeldb](https://www.unrealircd.org/docs/Set_block#set::channeldb)
|
||||
module now converts letter extbans to named extbans (eg `~a` to `~account`).
|
||||
Previously it did not, which caused letter extbans to appear in the banlist.
|
||||
Later on, when linking servers, this would cause duplicate entries to appear
|
||||
as well, with both the old and new format. The extbans were still effective
|
||||
though, so this is mostly a visual +b/+e/+I list issue.
|
||||
* Some [Extended Server Bans](https://www.unrealircd.org/docs/Extended_server_bans)
|
||||
were not working correctly for WEBIRC proxies. In particular, a server ban
|
||||
or exempt (ELINE) on `~country:XX` was only checked against the WEBIRC proxy.
|
||||
|
||||
Enhancements:
|
||||
* Support for [logging to a channel](https://www.unrealircd.org/docs/Log_block#Logging_to_a_channel).
|
||||
Similar to snomasks but then for channels.
|
||||
* Command line interface changes:
|
||||
* The [CLI tool](https://www.unrealircd.org/docs/Command_Line_Interface) now
|
||||
communicates to the running UnrealIRCd process via a UNIX socket to
|
||||
send commands and retrieve output.
|
||||
* The command `./unrealircd rehash` will now show the rehash output,
|
||||
including warnings and errors, and return a proper exit code.
|
||||
* The same for `./unrealircd reloadtls`
|
||||
* New command `./unrealircd status` to show if UnrealIRCd is running, the
|
||||
version, channel and user count, ..
|
||||
* The command `./unrealircd genlinkblock` is now
|
||||
[documented](https://www.unrealircd.org/docs/Linking_servers_(genlinkblock))
|
||||
and is referred to from the
|
||||
[Linking servers tutorial](https://www.unrealircd.org/docs/Tutorial:_Linking_servers).
|
||||
* On Windows in the `C:\Program Files\UnrealIRCd 6\bin` directory there is
|
||||
now an `unrealircdctl.exe` that can be used to do similar things to what
|
||||
you can do on *NIX. Supported operations are: `rehash`, `reloadtls`,
|
||||
`mkpasswd`, `gencloak` and `spkifp`.
|
||||
* New option [set::server-notice-show-event](https://www.unrealircd.org/docs/Set_block#set::server-notice-show-event)
|
||||
which can be set to `no` to hide the event information (eg `connect.LOCAL_CLIENT_CONNECT`)
|
||||
in server notices. This can be overridden per-oper in the
|
||||
[Oper block](https://www.unrealircd.org/docs/Oper_block) via oper::server-notice-show-event.
|
||||
* Support for IRC over UNIX sockets (on the same machine), if you specify a
|
||||
file in the [listen block](https://www.unrealircd.org/docs/Listen_block)
|
||||
instead of an ip/port. This probably won't be used much, but the option is
|
||||
there. Users will show up with a host of `localhost` and IP `127.0.0.1` to
|
||||
keep things simple.
|
||||
* The `MAP` command now shows percentages of users
|
||||
* Add `WHO` option to search clients by time connected (eg. `WHO <300 t` to
|
||||
search for less than 300 seconds)
|
||||
* Rate limiting of `MODE nick -x` and `-t` via new `vhost-flood` option in
|
||||
[set::anti-flood block](https://www.unrealircd.org/docs/Anti-flood_settings).
|
||||
|
||||
Changes:
|
||||
* Update Russian `help.ru.conf`.
|
||||
|
||||
Developers and protocol:
|
||||
* People packaging UnrealIRCd (eg. to an .rpm/.deb):
|
||||
* Be sure to pass the new `--with-controlfile` configure option
|
||||
* There is now an `unrealircdctl` tool that the `unrealircd` shell script
|
||||
uses, it is expected to be in `bindir`.
|
||||
* `SVSMODE #chan -b nick` will now correctly remove extbans that prevent `nick`
|
||||
from joining. This fixes a bug where it would remove too much (for `~time`)
|
||||
or not remove extbans (most other extbans, eg `~account`).
|
||||
`SVSMODE #chan -b` has also been fixed accordingly (remove all bans
|
||||
preventing joins).
|
||||
Note that all these commands do not remove bans that do not affect joins,
|
||||
such as `~quiet` or `~text`.
|
||||
* For module coders: setting the `EXTBOPT_CHSVSMODE` flag in `extban.options`
|
||||
is no longer useful, the flag is ignored. We now decide based on
|
||||
`BANCHK_JOIN` being in `extban.is_banned_events` if the ban should be
|
||||
removed or not upon SVS(2)MODE -b.
|
||||
|
||||
UnrealIRCd 6.0.1.1
|
||||
===================
|
||||
If you are already running UnrealIRCd 6 then read below on the
|
||||
changes between 6.0.0 and 6.0.1(.1). Otherwise, jump straight to the
|
||||
[summary about UnrealIRCd 6](#Summary) to learn more about UnrealIRCd 6.
|
||||
-------------------
|
||||
|
||||
Fixes:
|
||||
* In 6.0.1.1: extended bans were not properly synced between U5 and U6.
|
||||
@ -89,6 +220,8 @@ Enhancements
|
||||
* Colors are enabled by default in snomask server notices, these can be disabled via
|
||||
[set::server-notice-colors](https://www.unrealircd.org/docs/Set_block#set::server-notice-colors)
|
||||
and also in [oper::server-notice-colors](https://www.unrealircd.org/docs/Oper_block)
|
||||
* Support for [logging to a channel](https://www.unrealircd.org/docs/Log_block#Logging_to_a_channel).
|
||||
Similar to snomasks but then for channels. *Requires UnrealIRCd 6.0.2 or later*
|
||||
* Almost all channel modes are modularized
|
||||
* Only the three list modes (+b/+e/+I) are still in the core
|
||||
* The five [level modes](https://www.unrealircd.org/docs/Channel_Modes#Access_levels)
|
||||
|
@ -1 +0,0 @@
|
||||
https://modules.unrealircd.org/modules.list
|
@ -1,228 +1,50 @@
|
||||
/* Server bans snomask - 'b' */
|
||||
log {
|
||||
source {
|
||||
!debug;
|
||||
blacklist;
|
||||
chgcmds;
|
||||
connect.LOCAL_CLIENT_CONNECT;
|
||||
connect.LOCAL_CLIENT_DISCONNECT;
|
||||
connect.REMOTE_CLIENT_CONNECT;
|
||||
connect.REMOTE_CLIENT_DISCONNECT;
|
||||
dcc;
|
||||
flood;
|
||||
kill;
|
||||
link;
|
||||
nick.QLINE_NICK_LOCAL_ATTEMPT;
|
||||
nick.QLINE_NICK_REMOTE;
|
||||
nomatch;
|
||||
oper;
|
||||
operoverride;
|
||||
sacmds;
|
||||
tkl.BAN_REALNAME;
|
||||
tkl.RMTKL_COMMAND;
|
||||
tkl.SPAMFILTER_MATCH;
|
||||
tkl.TKL_ADD;
|
||||
tkl.TKL_DEL;
|
||||
tkl.TKL_ADD_TEMPSHUN;
|
||||
tkl.TKL_DEL_TEMPSHUN;
|
||||
tkl.TKL_EXPIRE;
|
||||
tkl.RMTKL_COMMAND;
|
||||
}
|
||||
destination {
|
||||
snomask b;
|
||||
}
|
||||
}
|
||||
|
||||
/* Blacklist snomask: 'B' */
|
||||
log {
|
||||
source {
|
||||
blacklist;
|
||||
}
|
||||
destination {
|
||||
snomask B;
|
||||
}
|
||||
}
|
||||
|
||||
/* Local client connects snomask - 'c' */
|
||||
log {
|
||||
source {
|
||||
connect.LOCAL_CLIENT_CONNECT;
|
||||
connect.LOCAL_CLIENT_DISCONNECT;
|
||||
}
|
||||
destination {
|
||||
snomask c;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remote client connects snomask - 'C' */
|
||||
log {
|
||||
source {
|
||||
connect.REMOTE_CLIENT_CONNECT;
|
||||
connect.REMOTE_CLIENT_DISCONNECT;
|
||||
}
|
||||
destination {
|
||||
snomask C;
|
||||
}
|
||||
}
|
||||
|
||||
/* DCC rejections snomask - 'd' */
|
||||
log {
|
||||
source {
|
||||
dcc;
|
||||
}
|
||||
destination {
|
||||
snomask d;
|
||||
}
|
||||
}
|
||||
|
||||
/* Debug snomask (not recommended) - 'D' */
|
||||
log {
|
||||
source {
|
||||
debug;
|
||||
}
|
||||
destination {
|
||||
snomask D;
|
||||
}
|
||||
}
|
||||
|
||||
/* Floods snomask - 'f' */
|
||||
log {
|
||||
source {
|
||||
flood;
|
||||
}
|
||||
destination {
|
||||
snomask f;
|
||||
}
|
||||
}
|
||||
|
||||
/* Join, parts, kicks - 'j' */
|
||||
log {
|
||||
source {
|
||||
// TODO: these don't exist yet..
|
||||
join.LOCAL_CLIENT_JOIN;
|
||||
join.REMOTE_CLIENT_JOIN;
|
||||
part.LOCAL_CLIENT_PART;
|
||||
part.REMOTE_CLIENT_PART;
|
||||
kick.LOCAL_CLIENT_KICK;
|
||||
kick.REMOTE_CLIENT_KICK;
|
||||
}
|
||||
destination {
|
||||
snomask j;
|
||||
}
|
||||
}
|
||||
|
||||
/* Kill snomask */
|
||||
log {
|
||||
source {
|
||||
kill;
|
||||
}
|
||||
destination {
|
||||
snomask k;
|
||||
}
|
||||
}
|
||||
|
||||
/* Local nick changes snomask - 'n' */
|
||||
log {
|
||||
source {
|
||||
nick.LOCAL_NICK_CHANGE;
|
||||
}
|
||||
destination {
|
||||
snomask n;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remote nick changes snomask - 'N' */
|
||||
log {
|
||||
source {
|
||||
nick.REMOTE_NICK_CHANGE;
|
||||
}
|
||||
destination {
|
||||
snomask N;
|
||||
}
|
||||
}
|
||||
|
||||
/* Deny nick (QLINE) rejections snomask - 'q' */
|
||||
log {
|
||||
source {
|
||||
nick.QLINE_NICK_LOCAL_ATTEMPT;
|
||||
nick.QLINE_NICK_REMOTE;
|
||||
}
|
||||
destination {
|
||||
snomask q;
|
||||
}
|
||||
}
|
||||
|
||||
/* Spamfilter hits snomask - 'S' */
|
||||
log {
|
||||
source {
|
||||
tkl.SPAMFILTER_MATCH;
|
||||
}
|
||||
destination {
|
||||
snomask S;
|
||||
}
|
||||
}
|
||||
|
||||
/* IRCOp overriding in channels (OperOverride) - 'o' */
|
||||
log {
|
||||
source {
|
||||
operoverride;
|
||||
}
|
||||
destination {
|
||||
snomask o;
|
||||
}
|
||||
}
|
||||
|
||||
/* IRCOp changing user properties or forcing users to do things - 'O' */
|
||||
log {
|
||||
source {
|
||||
chgcmds;
|
||||
sacmds;
|
||||
}
|
||||
destination {
|
||||
snomask O;
|
||||
}
|
||||
}
|
||||
|
||||
/* VHOST usage - 'v' */
|
||||
log {
|
||||
source {
|
||||
vhost;
|
||||
}
|
||||
destination {
|
||||
snomask v;
|
||||
}
|
||||
destination { snomask o; }
|
||||
}
|
||||
|
||||
/* Snomask s (server notices) - the "catch all" snomask for all other things */
|
||||
log {
|
||||
source {
|
||||
link;
|
||||
oper;
|
||||
!debug;
|
||||
nomatch;
|
||||
}
|
||||
destination {
|
||||
snomask s;
|
||||
}
|
||||
}
|
||||
|
||||
/* These log sources are sent to all servers (globally).
|
||||
* These are generally two categories:
|
||||
* 1) Things that affect the network as a whole, eg linking
|
||||
* 2) Things that otherwise cannot be logged by a remote server
|
||||
* that may interest ircops. Eg: a spamfilter match,
|
||||
* since that would otherwise not be propagated.
|
||||
*/
|
||||
log {
|
||||
source {
|
||||
/* All link messages affect the network so
|
||||
* these should be global. Except for the
|
||||
* link connecting... and timeout while
|
||||
* connecting.. messages, which can be noisy.
|
||||
*/
|
||||
flood;
|
||||
link;
|
||||
!link.LINK_CONNECTING;
|
||||
!link.LINK_CONNECT_TIMEOUT;
|
||||
!link.SERVER_LINKED_REMOTE;
|
||||
!link.SERVER_LINKED;
|
||||
/* All oper up/downs */
|
||||
oper;
|
||||
/* Flood messages, important to keep an eye on, network-wide */
|
||||
flood;
|
||||
/* TEMPSHUN: these are otherwise missing for snomask 'b' */
|
||||
samode.SAMODE_COMMAND;
|
||||
tkl.TKL_ADD_TEMPSHUN;
|
||||
tkl.TKL_DEL_TEMPSHUN;
|
||||
/* Spamfilter matches: needed for snomask 'S' */
|
||||
tkl.SPAMFILTER_MATCH;
|
||||
/* Critical issue: */
|
||||
tls.TLS_CERT_EXPIRING;
|
||||
/* SAMODE: needed for snomask 'o' */
|
||||
samode.SAMODE_COMMAND;
|
||||
/* Never any debug messages */
|
||||
!debug;
|
||||
}
|
||||
destination {
|
||||
remote;
|
||||
}
|
||||
}
|
||||
destination { remote; }
|
||||
}
|
@ -3,5 +3,6 @@ include "https://USERNAME:PASSWORD@HOSTNAME:PORT/except.conf";
|
||||
include "https://USERNAME:PASSWORD@HOSTNAME:PORT/ircd.conf";
|
||||
include "https://USERNAME:PASSWORD@HOSTNAME:PORT/modules.conf";
|
||||
include "https://USERNAME:PASSWORD@HOSTNAME:PORT/opers.conf";
|
||||
include "https://USERNAME:PASSWORD@HOSTNAME:PORT/snomasks.conf";
|
||||
include "https://USERNAME:PASSWORD@HOSTNAME:PORT/spamfilter.conf";
|
||||
me { name "example.supernets.org"; info "SuperNETS IRC Network"; sid XXX; }
|
@ -17,11 +17,6 @@ class servers { pingfreq 120; maxclients 10; sendq 1M; connfreq 30; }
|
||||
allow { mask *; class clients; maxperip 2; global-maxperip 2; }
|
||||
allow { mask 127.0.0.1; class clients; maxperip 10; global-maxperip 10; }
|
||||
|
||||
#require authentication {
|
||||
# mask *@*;
|
||||
# reason "8,4 E N T E R T H E V O I D ";
|
||||
#}
|
||||
|
||||
listen { ip *; port 6667; options { clientsonly; } }
|
||||
listen { ip *; port 6697; options { clientsonly; tls; } }
|
||||
listen { ip *; port REDACTED; options { serversonly; tls; } }
|
||||
@ -45,13 +40,13 @@ link irc.supernets.org {
|
||||
|
||||
log {
|
||||
source { error; fatal; warn; }
|
||||
destination { file "ircd.log" { maxsize 10M; } }
|
||||
destination { file "ircd.log" { maxsize 5M; } }
|
||||
}
|
||||
|
||||
log {
|
||||
source { all; }
|
||||
destination { channel "#REDACTED" }
|
||||
}
|
||||
#log {
|
||||
# source { all; }
|
||||
# destination { channel "#REDACTED" }
|
||||
#}
|
||||
|
||||
tld { mask *@*; motd remote.motd; rules remote.motd; options { remote; } }
|
||||
|
||||
@ -95,7 +90,7 @@ set {
|
||||
gline-address "enterthevoid@supernets.org";
|
||||
modes-on-connect "+iIpTx";
|
||||
modes-on-oper "+Hq";
|
||||
snomask-on-oper "+bBcCfksSoO";
|
||||
snomask-on-oper "+o";
|
||||
modes-on-join "+ns";
|
||||
level-on-join "op";
|
||||
restrict-usermodes "ips";
|
||||
@ -127,7 +122,7 @@ set {
|
||||
"REDACTED";
|
||||
"REDACTED";
|
||||
}
|
||||
hiddenhost-prefix "SUPER";
|
||||
cloak-prefix "SUPER";
|
||||
plaintext-policy {
|
||||
user warn;
|
||||
oper deny;
|
||||
@ -139,8 +134,8 @@ set {
|
||||
user warn;
|
||||
oper deny;
|
||||
server deny;
|
||||
user-message "4WARNING: You are using an outdated SSL/TLS protocol or cipher";
|
||||
oper-message "Network operators must be using an up-to-date SSL/TLS protocol & cipher";
|
||||
user-message "4WARNING: You are using an outdated TLS protocol or cipher";
|
||||
oper-message "Network operators must be using an up-to-date TLS protocol & cipher";
|
||||
}
|
||||
anti-flood {
|
||||
everyone {
|
||||
@ -209,9 +204,10 @@ set {
|
||||
ban-reason "8,4 E N T E R T H E V O I D ";
|
||||
}
|
||||
connthrottle {
|
||||
known-users { minimum-reputation-score 25; sasl-bypass yes; }
|
||||
new-users { local-throttle 20:60; global-throttle 30:60; }
|
||||
disabled-when { reputation-gathering 1w; start-delay 3m; }
|
||||
known-users { minimum-reputation-score 100; sasl-bypass yes; }
|
||||
new-users { local-throttle 20:60; global-throttle 30:60; }
|
||||
disabled-when { reputation-gathering 1w; start-delay 3m; }
|
||||
reason "8,4 E N T E R T H E V O I D ";
|
||||
}
|
||||
history {
|
||||
channel {
|
||||
@ -224,24 +220,24 @@ set {
|
||||
}
|
||||
hide-idle-time { policy always; }
|
||||
whois-details {
|
||||
basic { everyone full; }
|
||||
modes { everyone none; self full; oper full; }
|
||||
realhost { everyone none; self full; oper full; }
|
||||
registered-nick { everyone full; }
|
||||
channels { everyone limited; self full; oper full; }
|
||||
server { everyone full; }
|
||||
away { everyone full; }
|
||||
oper { everyone limited; self full; oper full; }
|
||||
secure { everyone limited; self full; oper full; }
|
||||
bot { everyone full; }
|
||||
services { everyone full; }
|
||||
reputation { everyone none; self none; oper full; }
|
||||
geo { everyone none; self none; oper full; }
|
||||
certfp { everyone full; }
|
||||
shunned { everyone none; self none; oper full; }
|
||||
account { everyone full; }
|
||||
away { everyone full; }
|
||||
basic { everyone full; }
|
||||
bot { everyone full; }
|
||||
certfp { everyone full; }
|
||||
channels { everyone none; self full; oper full; }
|
||||
geo { everyone none; }
|
||||
idle { everyone none; }
|
||||
modes { everyone none; self full; oper full; }
|
||||
oper { everyone limited; self full; oper full; }
|
||||
realhost { everyone none; self full; oper full; }
|
||||
registered-nick { everyone full; }
|
||||
reputation { everyone full; }
|
||||
secure { everyone limited; self full; oper full; }
|
||||
server { everyone full; }
|
||||
services { everyone full; }
|
||||
shunned { everyone none; self none; oper full; }
|
||||
swhois { everyone full; }
|
||||
idle { everyone limited; self full; oper full; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -254,5 +250,5 @@ hideserver {
|
||||
|
||||
security-group known-users {
|
||||
identified yes;
|
||||
reputation-score 25;
|
||||
reputation-score 100;
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
# in case it misbehaves
|
||||
#
|
||||
set +ex
|
||||
timeout --kill-after=5 600 extras/build-tests/nix/run-tests
|
||||
timeout --kill-after=5 900 extras/build-tests/nix/run-tests
|
||||
EX="$?"
|
||||
killall -9 valgrind valgrind.bin memcheck memcheck-amd64-linux memcheck-x86-linux ircd unrealircd val 1>/dev/null 2>&1
|
||||
exit $EX
|
||||
|
@ -36,11 +36,11 @@ rem Now the actual build
|
||||
rem - First this, otherwise JOM will fail
|
||||
IF NOT EXIST src\version.c nmake -f Makefile.windows CONF
|
||||
rem - Then build most of UnrealIRCd.exe etc
|
||||
call extras\build-tests\windows\compilecmd\%SHORTNAME%.bat UNREALSVC.EXE UnrealIRCd.exe
|
||||
call extras\build-tests\windows\compilecmd\%SHORTNAME%.bat UNREALSVC.EXE UnrealIRCd.exe unrealircdctl.exe
|
||||
rem - It will fail due to missing symbolfile, which we create here..
|
||||
nmake -f makefile.windows SYMBOLFILE
|
||||
rem - Then we finalize building UnrealIRCd.exe: should be no error
|
||||
call extras\build-tests\windows\compilecmd\%SHORTNAME%.bat UNREALSVC.EXE UnrealIRCd.exe
|
||||
call extras\build-tests\windows\compilecmd\%SHORTNAME%.bat UNREALSVC.EXE UnrealIRCd.exe unrealircdctl.exe
|
||||
if %ERRORLEVEL% NEQ 0 EXIT /B 1
|
||||
rem - Build all the modules (DLL files): should be no error
|
||||
call extras\build-tests\windows\compilecmd\%SHORTNAME%.bat MODULES
|
||||
|
Binary file not shown.
@ -2,10 +2,8 @@
|
||||
URL="https://www.unrealircd.org/files/curl-latest.tar.gz"
|
||||
OUTF="curl-latest.tar.gz"
|
||||
OUTD="curl-latest"
|
||||
ARESPATH="`pwd`/extras/c-ares"
|
||||
UNREALDIR="`pwd`"
|
||||
CARESVERSION="1.17.2"
|
||||
LIBDIR="$1"
|
||||
PRIVATELIBDIR="$1"
|
||||
|
||||
if [ "x$1" = "x" ]; then
|
||||
echo "You should (no longer) run this program directly."
|
||||
@ -73,26 +71,9 @@ else
|
||||
n="-n"
|
||||
fi
|
||||
|
||||
if [ ! -d "$ARESPATH/lib" ]; then
|
||||
echo "c-ares has not been build yet, let's do that now..."
|
||||
cd ../extras/
|
||||
tar xzf c-ares.tar.gz || exit 1
|
||||
cd c-ares-$CARESVERSION || exit 1
|
||||
./configure --prefix=$ARESPATH || exit 1
|
||||
(make && make install) || exit 1
|
||||
cd ../../tmp/
|
||||
echo "c-ares built."
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# We assume curl has been packaged in a way it will extract to "$OUTD"/
|
||||
cd "$OUTD" || exit 1
|
||||
|
||||
echo "Building and installing libcurl"
|
||||
CPPFLAGS="-I$ARESPATH/include" ./configure --prefix=$UNREALDIR/extras/curl --libdir=$LIBDIR --enable-shared \
|
||||
--enable-ares=$ARESPATH --with-openssl
|
||||
cp -R $ARESPATH/lib ares
|
||||
./configure --prefix=$UNREALDIR/extras/curl --libdir=$PRIVATELIBDIR --enable-shared --with-openssl
|
||||
make && make install
|
||||
|
||||
#cp $ARESPATH/lib/libcares.a $HOME/curl/lib
|
||||
# that isn't needed anymore as the lib is already in unreal...
|
||||
|
@ -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.1.1
|
||||
PROJECT_NUMBER = 6.0.3
|
||||
|
||||
# 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
|
||||
|
Binary file not shown.
@ -170,6 +170,7 @@ struct Configuration {
|
||||
char *stats_server;
|
||||
char *sasl_server;
|
||||
int server_notice_colors;
|
||||
int server_notice_show_event;
|
||||
};
|
||||
|
||||
extern MODVAR Configuration iConf;
|
||||
|
51
include/h.h
51
include/h.h
@ -28,6 +28,34 @@
|
||||
#include "setup.h"
|
||||
#include "fdlist.h"
|
||||
|
||||
extern int dorehash, dorestart, doreloadcert;
|
||||
#ifndef _WIN32
|
||||
extern char **myargv;
|
||||
#else
|
||||
extern LPCSTR cmdLine;
|
||||
#endif
|
||||
/* Externals */
|
||||
extern MODVAR char *buildid;
|
||||
extern MODVAR char backupbuf[8192];
|
||||
extern EVENT(unrealdns_removeoldrecords);
|
||||
extern EVENT(unrealdb_expire_secret_cache);
|
||||
extern void init_glines(void);
|
||||
extern void tkl_init(void);
|
||||
extern void process_clients(void);
|
||||
extern void unrealdb_test(void);
|
||||
extern void ignore_this_signal();
|
||||
extern void s_rehash();
|
||||
extern void s_reloadcert();
|
||||
extern void s_restart();
|
||||
extern void s_die();
|
||||
#ifndef _WIN32
|
||||
// nix specific
|
||||
extern char unreallogo[];
|
||||
#else
|
||||
// windows specific
|
||||
extern SERVICE_STATUS_HANDLE IRCDStatusHandle;
|
||||
extern SERVICE_STATUS IRCDStatus;
|
||||
#endif
|
||||
extern MODVAR char *extraflags;
|
||||
extern MODVAR int tainted;
|
||||
extern MODVAR Member *freemember;
|
||||
@ -117,7 +145,7 @@ extern void ipport_seperate(const char *string, char **ip, char **port);
|
||||
extern ConfigItem_class *find_class(const char *name);
|
||||
extern ConfigItem_oper *find_oper(const char *name);
|
||||
extern ConfigItem_operclass *find_operclass(const char *name);
|
||||
extern ConfigItem_listen *find_listen(const char *ipmask, int port, int ipv6);
|
||||
extern ConfigItem_listen *find_listen(const char *ipmask, int port, SocketType socket_type);
|
||||
extern ConfigItem_sni *find_sni(const char *name);
|
||||
extern ConfigItem_ulines *find_uline(const char *host);
|
||||
extern ConfigItem_tld *find_tld(Client *cptr);
|
||||
@ -153,6 +181,7 @@ extern MODVAR struct list_head lclient_list;
|
||||
extern MODVAR struct list_head server_list;
|
||||
extern MODVAR struct list_head oper_list;
|
||||
extern MODVAR struct list_head unknown_list;
|
||||
extern MODVAR struct list_head control_list;
|
||||
extern MODVAR struct list_head global_server_list;
|
||||
extern MODVAR struct list_head dead_list;
|
||||
extern RealCommand *find_command(const char *cmd, int flags);
|
||||
@ -489,6 +518,7 @@ extern int channel_canjoin(Client *client, const char *name);
|
||||
extern char *collapse(char *pattern);
|
||||
extern void dcc_sync(Client *client);
|
||||
extern void request_rehash(Client *client);
|
||||
extern int rehash_internal(Client *client);
|
||||
extern void s_die();
|
||||
extern int match_simple(const char *mask, const char *name);
|
||||
extern int match_esc(const char *mask, const char *name);
|
||||
@ -507,7 +537,7 @@ extern void rehash_motdrules();
|
||||
extern void read_motd(const char *filename, MOTDFile *motd); /* s_serv.c */
|
||||
extern void send_proto(Client *, ConfigItem_link *);
|
||||
extern void unload_all_modules(void);
|
||||
extern void set_sock_opts(int fd, Client *cptr, int ipv6);
|
||||
extern void set_sock_opts(int fd, Client *cptr, SocketType socket_type);
|
||||
extern void stripcrlf(char *line);
|
||||
extern int strnatcmp(char const *a, char const *b);
|
||||
extern int strnatcasecmp(char const *a, char const *b);
|
||||
@ -663,7 +693,6 @@ extern int spamfilter_getconftargets(const char *s);
|
||||
extern void remove_all_snomasks(Client *client);
|
||||
extern void remove_oper_modes(Client *client);
|
||||
extern char *spamfilter_inttostring_long(int v);
|
||||
extern MODVAR char backupbuf[];
|
||||
extern int is_invited(Client *client, Channel *channel);
|
||||
extern void channel_modes(Client *client, char *mbuf, char *pbuf, size_t mbuf_size, size_t pbuf_size, Channel *channel, int hide_local_modes);
|
||||
extern int op_can_override(const char *acl, Client *client,Channel *channel,void* extra);
|
||||
@ -859,6 +888,7 @@ extern const char *cmdname_by_spamftarget(int target);
|
||||
extern void unrealdns_delreq_bycptr(Client *cptr);
|
||||
extern void unrealdns_gethostbyname_link(const char *name, ConfigItem_link *conf, int ipv4_only);
|
||||
extern void unrealdns_delasyncconnects(void);
|
||||
extern EVENT(unrealdns_timeout);
|
||||
extern int is_autojoin_chan(const char *chname);
|
||||
extern void unreal_free_hostent(struct hostent *he);
|
||||
extern struct hostent *unreal_create_hostent(const char *name, const char *ip);
|
||||
@ -915,10 +945,14 @@ extern void report_crash(void);
|
||||
extern void modulemanager(int argc, char *argv[]);
|
||||
extern int inet_pton4(const char *src, unsigned char *dst);
|
||||
extern int inet_pton6(const char *src, unsigned char *dst);
|
||||
extern int unreal_bind(int fd, const char *ip, int port, int ipv6);
|
||||
extern int unreal_bind(int fd, const char *ip, int port, SocketType socket_type);
|
||||
extern int unreal_connect(int fd, const char *ip, int port, int ipv6);
|
||||
extern int is_valid_ip(const char *str);
|
||||
extern int ipv6_capable(void);
|
||||
extern int unix_sockets_capable(void);
|
||||
#ifdef _WIN32
|
||||
extern void init_winsock(void);
|
||||
#endif
|
||||
extern MODVAR Client *remote_rehash_client;
|
||||
extern MODVAR int debugfd;
|
||||
extern void convert_to_absolute_path(char **path, const char *reldir);
|
||||
@ -929,7 +963,7 @@ extern Cmode_t get_extmode_bitbychar(char m);
|
||||
extern long find_user_mode(char mode);
|
||||
extern void start_listeners(void);
|
||||
extern void buildvarstring(const char *inbuf, char *outbuf, size_t len, const char *name[], const char *value[]);
|
||||
extern void reinit_tls(void);
|
||||
extern int reinit_tls(void);
|
||||
extern CMD_FUNC(cmd_error);
|
||||
extern CMD_FUNC(cmd_dns);
|
||||
extern CMD_FUNC(cmd_info);
|
||||
@ -1135,6 +1169,8 @@ extern void flood_limit_exceeded_log(Client *client, const char *floodname);
|
||||
/* logging */
|
||||
extern int config_test_log(ConfigFile *conf, ConfigEntry *ce);
|
||||
extern int config_run_log(ConfigFile *conf, ConfigEntry *ce);
|
||||
extern const char *log_level_terminal_color(LogLevel loglevel);
|
||||
#define TERMINAL_COLOR_RESET "\033[0m"
|
||||
extern LogType log_type_stringtoval(const char *str);
|
||||
extern const char *log_type_valtostring(LogType v);
|
||||
#ifdef DEBUGMODE
|
||||
@ -1208,3 +1244,8 @@ extern void make_umodestr(void);
|
||||
extern void initwhowas(void);
|
||||
extern void uid_init(void);
|
||||
extern const char *uid_get(void);
|
||||
/* proc i/o */
|
||||
extern void add_proc_io_server(void);
|
||||
extern void procio_post_rehash(int failure);
|
||||
/* end of proc i/o */
|
||||
extern int minimum_msec_since_last_run(struct timeval *tv_old, long minimum);
|
||||
|
@ -394,7 +394,7 @@ typedef enum ExtbanType {
|
||||
#define EXTBANTABLESZ 32
|
||||
|
||||
typedef enum ExtbanOptions {
|
||||
EXTBOPT_CHSVSMODE=0x1, /**< SVSMODE -b/-e/-I will clear this ban */
|
||||
EXTBOPT_CHSVSMODE=0x1, /**< SVSMODE -b/-e/-I will clear this ban (UNUSED as of 6.0.1+) */
|
||||
EXTBOPT_ACTMODIFIER=0x2, /**< Action modifier (not a matcher). These are extended bans like ~q/~n/~j. */
|
||||
EXTBOPT_NOSTACKCHILD=0x4, /**< Disallow prefixing with another extban. Eg disallow ~n:~T:censor:xyz */
|
||||
EXTBOPT_INVEX=0x8, /**< Available for use with +I too */
|
||||
@ -1151,12 +1151,14 @@ extern void SavePersistentLongX(ModuleInfo *modinfo, const char *varshortname, l
|
||||
#define HOOKTYPE_POST_LOCAL_NICKCHANGE 106
|
||||
/** See hooktype_post_remote_nickchange() */
|
||||
#define HOOKTYPE_POST_REMOTE_NICKCHANGE 107
|
||||
/** See hooktype_userhost_changed() */
|
||||
#define HOOKTYPE_USERHOST_CHANGED 108
|
||||
/** See hooktype_realname_changed() */
|
||||
#define HOOKTYPE_REALNAME_CHANGED 109
|
||||
/** See hooktype_userhost_change() */
|
||||
#define HOOKTYPE_USERHOST_CHANGE 108
|
||||
/** See hooktype_realname_change() */
|
||||
#define HOOKTYPE_REALNAME_CHANGE 109
|
||||
/** See hooktype_can_set_topic() */
|
||||
#define HOOKTYPE_CAN_SET_TOPIC 110
|
||||
/** See hooktype_ip_change() */
|
||||
#define HOOKTYPE_IP_CHANGE 111
|
||||
/* Adding a new hook here?
|
||||
* 1) Add the #define HOOKTYPE_.... with a new number
|
||||
* 2) Add a hook prototype (see below)
|
||||
@ -2127,14 +2129,22 @@ int hooktype_post_remote_nickchange(Client *client, MessageTag *mtags, const cha
|
||||
* @param oldhost Old hostname of the client
|
||||
* @return The return value is ignored (use return 0)
|
||||
*/
|
||||
|
||||
int hooktype_realname_changed(Client *client, const char *oldinfo);
|
||||
int hooktype_userhost_change(Client *client, const char *olduser, const char *oldhost);
|
||||
|
||||
/** Called when user realname has changed.
|
||||
* @param client The client whose realname has changed
|
||||
* @param oldinfo Old realname of the client
|
||||
* @return The return value is ignored (use return 0)
|
||||
*/
|
||||
int hooktype_userhost_changed(Client *client, const char *olduser, const char *oldhost);
|
||||
int hooktype_realname_change(Client *client, const char *oldinfo);
|
||||
|
||||
/** Called when changing IP (eg due to PROXY/WEBIRC/etc).
|
||||
* @param client The client whose IP has changed
|
||||
* @param oldip Old IP of the client
|
||||
* @return The return value is ignored (use return 0)
|
||||
*/
|
||||
int hooktype_ip_change(Client *client, const char *oldip);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef GCC_TYPECHECKING
|
||||
@ -2247,8 +2257,9 @@ _UNREAL_ERROR(_hook_error_incompatible, "Incompatible hook function. Check argum
|
||||
((hooktype == HOOKTYPE_IS_INVITED) && !ValidateHook(hooktype_is_invited, func)) || \
|
||||
((hooktype == HOOKTYPE_POST_LOCAL_NICKCHANGE) && !ValidateHook(hooktype_post_local_nickchange, func)) || \
|
||||
((hooktype == HOOKTYPE_POST_REMOTE_NICKCHANGE) && !ValidateHook(hooktype_post_remote_nickchange, func)) || \
|
||||
((hooktype == HOOKTYPE_USERHOST_CHANGED) && !ValidateHook(hooktype_userhost_changed, func)) || \
|
||||
((hooktype == HOOKTYPE_REALNAME_CHANGED) && !ValidateHook(hooktype_realname_changed, func)) )\
|
||||
((hooktype == HOOKTYPE_USERHOST_CHANGE) && !ValidateHook(hooktype_userhost_change, func)) || \
|
||||
((hooktype == HOOKTYPE_REALNAME_CHANGE) && !ValidateHook(hooktype_realname_change, func)) || \
|
||||
((hooktype == HOOKTYPE_IP_CHANGE) && !ValidateHook(hooktype_ip_change, func)) ) \
|
||||
_hook_error_incompatible();
|
||||
#endif /* GCC_TYPECHECKING */
|
||||
|
||||
|
@ -37,6 +37,8 @@
|
||||
|
||||
#define RPL_REDIR 10
|
||||
|
||||
#define RPL_MAPUSERS 18
|
||||
|
||||
#define RPL_REMOTEISUPPORT 105
|
||||
|
||||
/*
|
||||
@ -349,10 +351,11 @@
|
||||
#define STR_RPL_CREATED /* 003 */ ":This server was created %s"
|
||||
#define STR_RPL_MYINFO /* 004 */ "%s %s %s %s"
|
||||
#define STR_RPL_ISUPPORT /* 005 */ "%s :are supported by this server"
|
||||
#define STR_RPL_MAP /* 006 */ ":%s%-*s(%ld) %s"
|
||||
#define STR_RPL_MAP /* 006 */ ":%s%s %s | Users: %*ld (%*.2f%%)%s"
|
||||
#define STR_RPL_MAPEND /* 007 */ ":End of /MAP"
|
||||
#define STR_RPL_SNOMASK /* 008 */ "+%s :Server notice mask"
|
||||
#define STR_RPL_REDIR /* 010 */ "%s %d :Please use this Server/Port instead"
|
||||
#define STR_RPL_MAPUSERS /* 018 */ ":%d server%s and %d user%s, average %.2f users per server"
|
||||
#define STR_RPL_REMOTEISUPPORT /* 105 */ "%s :are supported by this server"
|
||||
#define STR_RPL_TRACELINK /* 200 */ "Link %s%s %s %s"
|
||||
#define STR_RPL_TRACECONNECTING /* 201 */ "Attempt %s %s"
|
||||
|
@ -12,6 +12,9 @@
|
||||
/* Define the location of the configuration files */
|
||||
#undef CONFDIR
|
||||
|
||||
/* Define the path of the control socket */
|
||||
#undef CONTROLFILE
|
||||
|
||||
/* Define the location of permanent data files */
|
||||
#undef DATADIR
|
||||
|
||||
|
@ -263,12 +263,18 @@ typedef struct Log Log;
|
||||
struct Log {
|
||||
Log *prev, *next;
|
||||
LogSource *sources;
|
||||
int type;
|
||||
char destination[CHANNELLEN+1];
|
||||
int show_event;
|
||||
/* for destination::file */
|
||||
char *file;
|
||||
char *filefmt;
|
||||
long maxsize;
|
||||
int type;
|
||||
int logfd;
|
||||
/* for destination::channel */
|
||||
int color;
|
||||
int json_message_tag;
|
||||
int oper_only;
|
||||
};
|
||||
|
||||
/** This is used for deciding the <index> in logs[<index>] and temp_logs[<index>] */
|
||||
@ -317,6 +323,7 @@ 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_CONNECTING = -6, /**< Client is an outgoing connect */
|
||||
@ -339,6 +346,7 @@ 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 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 */
|
||||
@ -355,6 +363,8 @@ typedef enum ClientStatus {
|
||||
#define SetServer(x) ((x)->status = CLIENT_STATUS_SERVER)
|
||||
#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 SetUser(x) ((x)->status = CLIENT_STATUS_USER)
|
||||
|
||||
/** @} */
|
||||
|
||||
@ -366,7 +376,7 @@ typedef enum ClientStatus {
|
||||
#define CLIENT_FLAG_DEAD 0x00000002 /**< Client is dead: already quit/exited and removed from all lists -- Remaining part will soon be freed in main loop */
|
||||
#define CLIENT_FLAG_DEADSOCKET 0x00000004 /**< Local socket is dead but otherwise the client still exists fully -- Will soon exit in main loop */
|
||||
#define CLIENT_FLAG_KILLED 0x00000008 /**< Prevents "QUIT" from being sent for this */
|
||||
#define CLIENT_FLAG_IPV6 0x00000010 /**< Connection is using IPv6 */
|
||||
#define CLIENT_FLAG_MONITOR_REHASH 0x00000010 /**< Client is monitoring rehash output */
|
||||
#define CLIENT_FLAG_OUTGOING 0x00000020 /**< Outgoing connection (do not touch cptr->listener->clients) */
|
||||
#define CLIENT_FLAG_CLOSING 0x00000040 /**< Set when closing to suppress errors */
|
||||
#define CLIENT_FLAG_LISTEN 0x00000080 /**< Used to mark clients which we listen() on */
|
||||
@ -464,8 +474,8 @@ typedef enum ClientStatus {
|
||||
#define IsDNSLookup(x) ((x)->flags & CLIENT_FLAG_DNSLOOKUP)
|
||||
#define IsEAuth(x) ((x)->flags & CLIENT_FLAG_EAUTH)
|
||||
#define IsIdentSuccess(x) ((x)->flags & CLIENT_FLAG_IDENTSUCCESS)
|
||||
#define IsIPV6(x) ((x)->flags & CLIENT_FLAG_IPV6)
|
||||
#define IsKilled(x) ((x)->flags & CLIENT_FLAG_KILLED)
|
||||
#define IsMonitorRehash(x) ((x)->flags & CLIENT_FLAG_MONITOR_REHASH)
|
||||
#define IsListening(x) ((x)->flags & CLIENT_FLAG_LISTEN)
|
||||
#define IsLocalhost(x) ((x)->flags & CLIENT_FLAG_LOCALHOST)
|
||||
#define IsMap(x) ((x)->flags & CLIENT_FLAG_MAP)
|
||||
@ -496,8 +506,8 @@ typedef enum ClientStatus {
|
||||
#define SetDNSLookup(x) do { (x)->flags |= CLIENT_FLAG_DNSLOOKUP; } while(0)
|
||||
#define SetEAuth(x) do { (x)->flags |= CLIENT_FLAG_EAUTH; } while(0)
|
||||
#define SetIdentSuccess(x) do { (x)->flags |= CLIENT_FLAG_IDENTSUCCESS; } while(0)
|
||||
#define SetIPV6(x) do { (x)->flags |= CLIENT_FLAG_IPV6; } while(0)
|
||||
#define SetKilled(x) do { (x)->flags |= CLIENT_FLAG_KILLED; } while(0)
|
||||
#define SetMonitorRehash(x) do { (x)->flags |= CLIENT_FLAG_MONITOR_REHASH; } while(0)
|
||||
#define SetListening(x) do { (x)->flags |= CLIENT_FLAG_LISTEN; } while(0)
|
||||
#define SetLocalhost(x) do { (x)->flags |= CLIENT_FLAG_LOCALHOST; } while(0)
|
||||
#define SetMap(x) do { (x)->flags |= CLIENT_FLAG_MAP; } while(0)
|
||||
@ -526,8 +536,8 @@ typedef enum ClientStatus {
|
||||
#define ClearDNSLookup(x) do { (x)->flags &= ~CLIENT_FLAG_DNSLOOKUP; } while(0)
|
||||
#define ClearEAuth(x) do { (x)->flags &= ~CLIENT_FLAG_EAUTH; } while(0)
|
||||
#define ClearIdentSuccess(x) do { (x)->flags &= ~CLIENT_FLAG_IDENTSUCCESS; } while(0)
|
||||
#define ClearIPV6(x) do { (x)->flags &= ~CLIENT_FLAG_IPV6; } while(0)
|
||||
#define ClearKilled(x) do { (x)->flags &= ~CLIENT_FLAG_KILLED; } while(0)
|
||||
#define ClearMonitorRehash(x) do { (x)->flags &= ~CLIENT_FLAG_MONITOR_REHASH; } while(0)
|
||||
#define ClearListening(x) do { (x)->flags &= ~CLIENT_FLAG_LISTEN; } while(0)
|
||||
#define ClearLocalhost(x) do { (x)->flags &= ~CLIENT_FLAG_LOCALHOST; } while(0)
|
||||
#define ClearMap(x) do { (x)->flags &= ~CLIENT_FLAG_MAP; } while(0)
|
||||
@ -546,6 +556,9 @@ typedef enum ClientStatus {
|
||||
#define ClearULine(x) do { (x)->flags &= ~CLIENT_FLAG_ULINE; } while(0)
|
||||
#define ClearVirus(x) do { (x)->flags &= ~CLIENT_FLAG_VIRUS; } while(0)
|
||||
#define ClearIdentLookupSent(x) do { (x)->flags &= ~CLIENT_FLAG_IDENTLOOKUPSENT; } while(0)
|
||||
#define IsIPV6(x) ((x)->local->socket_type == SOCKET_TYPE_IPV6)
|
||||
#define IsUnixSocket(x) ((x)->local->socket_type == SOCKET_TYPE_UNIX)
|
||||
#define SetIPV6(x) do { (x)->local->socket_type = SOCKET_TYPE_IPV6; } while(0)
|
||||
/** @} */
|
||||
|
||||
|
||||
@ -779,11 +792,11 @@ struct LoopStruct {
|
||||
unsigned do_bancheck : 1; /* perform *line bancheck? */
|
||||
unsigned do_bancheck_spamf_user : 1; /* perform 'user' spamfilter bancheck */
|
||||
unsigned do_bancheck_spamf_away : 1; /* perform 'away' spamfilter bancheck */
|
||||
unsigned rehashing : 1;
|
||||
unsigned terminating : 1;
|
||||
unsigned config_load_failed : 1;
|
||||
unsigned rehash_download_busy : 1; /* don't return "all downloads complete", needed for race condition */
|
||||
unsigned tainted : 1;
|
||||
int rehashing;
|
||||
Client *rehash_save_client;
|
||||
void (*boot_function)();
|
||||
};
|
||||
@ -851,6 +864,8 @@ struct SWhois {
|
||||
#define CMD_VIRUS 0x0080
|
||||
/** Command requires IRCOp privileges */
|
||||
#define CMD_OPER 0x0200
|
||||
/** Command is for control channel only (unrealircd.ctl socket) */
|
||||
#define CMD_CONTROL 0x0400
|
||||
|
||||
/** Command function - used by all command handlers.
|
||||
* This is used in the code like <pre>CMD_FUNC(cmd_yourcmd)</pre> as a function definition.
|
||||
@ -1212,6 +1227,7 @@ extern void unload_all_unused_moddata(void);
|
||||
#define LISTENER_TLS 0x000010
|
||||
#define LISTENER_BOUND 0x000020
|
||||
#define LISTENER_DEFER_ACCEPT 0x000040
|
||||
#define LISTENER_CONTROL 0x000080 /**< Control channel */
|
||||
|
||||
#define IsServersOnlyListener(x) ((x) && ((x)->options & LISTENER_SERVERSONLY))
|
||||
|
||||
@ -1240,6 +1256,7 @@ typedef enum FloodOption {
|
||||
FLD_KNOCK = 4, /**< knock-flood */
|
||||
FLD_CONVERSATIONS = 5, /**< max-concurrent-conversations */
|
||||
FLD_LAG_PENALTY = 6, /**< lag-penalty / lag-penalty-bytes */
|
||||
FLD_VHOST = 7, /**< vhost-flood */
|
||||
} FloodOption;
|
||||
#define MAXFLOODOPTIONS 10
|
||||
|
||||
@ -1251,6 +1268,11 @@ struct TrafficStats {
|
||||
long long bytes_received; /* Received bytes */
|
||||
};
|
||||
|
||||
/** Socket type (IPv4, IPv6, UNIX) */
|
||||
typedef enum {
|
||||
SOCKET_TYPE_IPV4=0, SOCKET_TYPE_IPV6=1, SOCKET_TYPE_UNIX=2
|
||||
} SocketType;
|
||||
|
||||
/** This shows the Client struct (any client), the User struct (a user), Server (a server) that are commonly accessed both in the core and by 3rd party coders.
|
||||
* @defgroup CommonStructs Common structs
|
||||
* @{
|
||||
@ -1288,6 +1310,7 @@ struct Client {
|
||||
*/
|
||||
struct LocalClient {
|
||||
int fd; /**< File descriptor, can be <0 if socket has been closed already. */
|
||||
SocketType socket_type; /**< Type of socket: IPv4, IPV6, UNIX */
|
||||
SSL *ssl; /**< OpenSSL/LibreSSL struct for TLS connection */
|
||||
time_t fake_lag; /**< Time when user will next be allowed to send something (actually fake_lag<currenttime+10) */
|
||||
int fake_lag_msec; /**< Used for calculating 'fake_lag' penalty (modulo) */
|
||||
@ -1606,6 +1629,7 @@ struct ConfigItem_oper {
|
||||
char *vhost;
|
||||
int maxlogins;
|
||||
int server_notice_colors;
|
||||
int server_notice_show_event;
|
||||
};
|
||||
|
||||
/** The TLS options that are used in set::tls and otherblocks::tls-options.
|
||||
@ -1666,11 +1690,12 @@ struct ConfigItem_tld {
|
||||
struct ConfigItem_listen {
|
||||
ConfigItem_listen *prev, *next;
|
||||
ConfigFlag flag;
|
||||
SocketType socket_type;
|
||||
char *file;
|
||||
char *ip;
|
||||
int port;
|
||||
int options, clients;
|
||||
int fd;
|
||||
int ipv6;
|
||||
SSL_CTX *ssl_ctx;
|
||||
TLSOptions *tls_options;
|
||||
int websocket_options; /* should be in module, but lazy */
|
||||
|
@ -58,10 +58,12 @@
|
||||
#ifndef _WIN32
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <arpa/inet.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <afunix.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
|
@ -54,7 +54,7 @@
|
||||
* Can be useful if the above 3 versionids are insufficient for you (eg: you want to support CVS).
|
||||
* This is updated automatically on the CVS server every Monday. so don't touch it.
|
||||
*/
|
||||
#define UNREAL_VERSION_TIME 202148
|
||||
#define UNREAL_VERSION_TIME 202204
|
||||
|
||||
#define UNREAL_VERSION ((UNREAL_VERSION_GENERATION << 24) + (UNREAL_VERSION_MAJOR << 16) + (UNREAL_VERSION_MINOR << 8))
|
||||
#define UnrealProtocol 6000
|
||||
|
@ -33,6 +33,7 @@
|
||||
#define CACHEDIR "cache"
|
||||
#define TMPDIR "tmp"
|
||||
#define PIDFILE PERMDATADIR"/unrealircd.pid"
|
||||
#define CONTROLFILE PERMDATADIR"/unrealircd.ctl"
|
||||
#define NO_U_TYPES
|
||||
#define NEED_U_INT32_T
|
||||
#define strcasecmp _stricmp
|
||||
@ -61,10 +62,10 @@
|
||||
#define UNREAL_VERSION_MAJOR 0
|
||||
|
||||
/* Minor version number (e.g.: 1 for Unreal3.2.1) */
|
||||
#define UNREAL_VERSION_MINOR 1
|
||||
#define UNREAL_VERSION_MINOR 3
|
||||
|
||||
/* Version suffix such as a beta marker or release candidate marker. (e.g.:
|
||||
-rcX for unrealircd-3.2.9-rcX) */
|
||||
#define UNREAL_VERSION_SUFFIX ".1"
|
||||
#define UNREAL_VERSION_SUFFIX ""
|
||||
|
||||
#endif
|
||||
|
@ -21,10 +21,10 @@
|
||||
|
||||
CC = "==== DO NOT RUN MAKE FROM THIS DIRECTORY ===="
|
||||
|
||||
OBJS=dns.o auth.o channel.o crule.o dbuf.o \
|
||||
fdlist.o hash.o ircd.o ircsprintf.o list.o \
|
||||
OBJS=ircd_vars.o dns.o auth.o channel.o crule.o dbuf.o \
|
||||
fdlist.o hash.o ircsprintf.o list.o \
|
||||
match.o modules.o parse.o mempool.o operclass.o \
|
||||
conf_preprocessor.o conf.o debug.o dispatch.o \
|
||||
conf_preprocessor.o conf.o proc_io_server.o debug.o dispatch.o \
|
||||
misc.o serv.o aliases.o socket.o \
|
||||
tls.o user.o scache.o send.o support.o \
|
||||
version.o whowas.o random.o api-usermode.o api-channelmode.o \
|
||||
@ -62,22 +62,22 @@ all: build
|
||||
|
||||
build:
|
||||
# Force build of 'ircd', before we start building any modules:
|
||||
$(MAKE) ircd
|
||||
$(MAKE) ircd unrealircdctl
|
||||
$(MAKE) mods
|
||||
|
||||
custommodule:
|
||||
+cd modules/third; $(MAKE) MODULEFILE=$(MODULEFILE) 'EXLIBS=$(EXLIBS)' custommodule
|
||||
|
||||
ircd: $(OBJS)
|
||||
$(CC) $(CFLAGS) $(BINCFLAGS) $(CRYPTOLIB) -o ircd $(OBJS) $(LDFLAGS) $(BINLDFLAGS) $(IRCDLIBS) $(CRYPTOLIB)
|
||||
ircd: $(OBJS) ircd.o
|
||||
$(CC) $(CFLAGS) $(BINCFLAGS) $(CRYPTOLIB) -o ircd ircd.o $(OBJS) $(LDFLAGS) $(BINLDFLAGS) $(IRCDLIBS) $(CRYPTOLIB)
|
||||
|
||||
unrealircdctl: $(OBJS) unrealircdctl.o proc_io_client.o
|
||||
$(CC) $(CFLAGS) $(BINCFLAGS) $(CRYPTOLIB) -o unrealircdctl unrealircdctl.o proc_io_client.o $(OBJS) $(LDFLAGS) $(BINLDFLAGS) $(IRCDLIBS) $(CRYPTOLIB)
|
||||
|
||||
mods:
|
||||
@if [ ! -r include ] ; then \
|
||||
ln -s ../include include; \
|
||||
fi
|
||||
@if [ ! -r modules ] ; then \
|
||||
echo "You havent done cvs update -P -d"; \
|
||||
fi
|
||||
+cd modules; $(MAKE) all
|
||||
|
||||
version.c: version.c.SH
|
||||
|
@ -89,7 +89,7 @@ static Command *CommandAddInternal(Module *module, const char *cmd, CmdFunc func
|
||||
Command *command = NULL;
|
||||
RealCommand *c;
|
||||
|
||||
if (find_command_simple(cmd))
|
||||
if ((c = find_command(cmd, flags)) && (c->flags == flags))
|
||||
{
|
||||
if (module)
|
||||
module->errorcode = MODERR_EXISTS;
|
||||
@ -253,15 +253,26 @@ static RealCommand *add_Command_backend(const char *cmd)
|
||||
RealCommand *find_command(const char *cmd, int flags)
|
||||
{
|
||||
RealCommand *p;
|
||||
for (p = CommandHash[toupper(*cmd)]; p; p = p->next) {
|
||||
if ((flags & CMD_UNREGISTERED) && !(p->flags & CMD_UNREGISTERED))
|
||||
continue;
|
||||
if ((flags & CMD_SHUN) && !(p->flags & CMD_SHUN))
|
||||
continue;
|
||||
if ((flags & CMD_VIRUS) && !(p->flags & CMD_VIRUS))
|
||||
continue;
|
||||
if ((flags & CMD_ALIAS) && !(p->flags & CMD_ALIAS))
|
||||
continue;
|
||||
for (p = CommandHash[toupper(*cmd)]; p; p = p->next)
|
||||
{
|
||||
if (flags & CMD_CONTROL)
|
||||
{
|
||||
if (!(p->flags & CMD_CONTROL))
|
||||
continue;
|
||||
} else
|
||||
{
|
||||
if ((flags & CMD_UNREGISTERED) && !(p->flags & CMD_UNREGISTERED))
|
||||
continue;
|
||||
if ((flags & CMD_SHUN) && !(p->flags & CMD_SHUN))
|
||||
continue;
|
||||
if ((flags & CMD_VIRUS) && !(p->flags & CMD_VIRUS))
|
||||
continue;
|
||||
if ((flags & CMD_ALIAS) && !(p->flags & CMD_ALIAS))
|
||||
continue;
|
||||
if (p->flags & CMD_CONTROL)
|
||||
continue; /* important to also filter it this way ;) */
|
||||
}
|
||||
|
||||
if (!strcasecmp(p->cmd, cmd))
|
||||
return p;
|
||||
}
|
||||
|
@ -27,9 +27,6 @@ ID_Copyright("(C) Carsten Munk 2001");
|
||||
|
||||
MODVAR Event *events = NULL;
|
||||
|
||||
extern EVENT(unrealdns_removeoldrecords);
|
||||
extern EVENT(unrealdb_expire_secret_cache);
|
||||
|
||||
/** Add an event, a function that will run at regular intervals.
|
||||
* @param module Module that this event belongs to
|
||||
* @param name Name of the event
|
||||
@ -211,18 +208,3 @@ void DoEvents(void)
|
||||
|
||||
CleanupEvents();
|
||||
}
|
||||
|
||||
void SetupEvents(void)
|
||||
{
|
||||
/* Start events */
|
||||
EventAdd(NULL, "tunefile", save_tunefile, NULL, 300*1000, 0);
|
||||
EventAdd(NULL, "garbage", garbage_collect, NULL, GARBAGE_COLLECT_EVERY*1000, 0);
|
||||
EventAdd(NULL, "loop", loop_event, NULL, 1000, 0);
|
||||
EventAdd(NULL, "unrealdns_removeoldrecords", unrealdns_removeoldrecords, NULL, 15000, 0);
|
||||
EventAdd(NULL, "check_pings", check_pings, NULL, 1000, 0);
|
||||
EventAdd(NULL, "check_deadsockets", check_deadsockets, NULL, 1000, 0);
|
||||
EventAdd(NULL, "handshake_timeout", handshake_timeout, NULL, 1000, 0);
|
||||
EventAdd(NULL, "tls_check_expiry", tls_check_expiry, NULL, (86400/2)*1000, 0);
|
||||
EventAdd(NULL, "unrealdb_expire_secret_cache", unrealdb_expire_secret_cache, NULL, 61000, 0);
|
||||
EventAdd(NULL, "throttling_check_expire", throttling_check_expire, NULL, 1000, 0);
|
||||
}
|
||||
|
464
src/conf.c
464
src/conf.c
@ -199,8 +199,8 @@ void free_tls_options(TLSOptions *tlsoptions);
|
||||
* Config parser (IRCd)
|
||||
*/
|
||||
int config_read_file(const char *filename, const char *display_name);
|
||||
void config_rehash();
|
||||
int config_run_blocks();
|
||||
void config_rehash(void);
|
||||
int config_run_blocks(void);
|
||||
int config_test_blocks();
|
||||
|
||||
/*
|
||||
@ -464,10 +464,15 @@ int config_parse_flood_generic(const char *str, Configuration *conf, char *block
|
||||
|
||||
long config_checkval(const char *orig, unsigned short flags)
|
||||
{
|
||||
char *value = raw_strdup(orig);
|
||||
char *value;
|
||||
char *text;
|
||||
long ret = 0;
|
||||
|
||||
/* Handle empty strings early, since we use +1 later in the code etc. */
|
||||
if (BadPtr(orig))
|
||||
return 0;
|
||||
|
||||
value = raw_strdup(orig);
|
||||
if (flags == CFG_YESNO) {
|
||||
for (text = value; *text; text++) {
|
||||
if (!isalnum(*text))
|
||||
@ -1586,7 +1591,7 @@ ConfigCommand *config_binary_search(const char *cmd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void free_iConf(Configuration *i)
|
||||
void free_iConf(Configuration *i)
|
||||
{
|
||||
FloodSettings *f, *f_next;
|
||||
|
||||
@ -1645,6 +1650,7 @@ void config_setdefaultsettings(Configuration *i)
|
||||
|
||||
safe_strdup(i->oper_snomask, OPER_SNOMASKS);
|
||||
i->server_notice_colors = 1;
|
||||
i->server_notice_show_event = 1;
|
||||
i->ident_read_timeout = 7;
|
||||
i->ident_connect_timeout = 3;
|
||||
i->ban_version_tkl_time = 86400; /* 1d */
|
||||
@ -1694,6 +1700,7 @@ void config_setdefaultsettings(Configuration *i)
|
||||
/* - known-users */
|
||||
config_parse_flood_generic("3:60", i, "known-users", FLD_NICK); /* NICK flood protection: max 3 per 60s */
|
||||
config_parse_flood_generic("3:90", i, "known-users", FLD_JOIN); /* JOIN flood protection: max 3 per 90s */
|
||||
config_parse_flood_generic("3:90", i, "known-users", FLD_VHOST); /* MODE -x flood protection: max 3 per 90s */
|
||||
config_parse_flood_generic("4:120", i, "known-users", FLD_AWAY); /* AWAY flood protection: max 4 per 120s */
|
||||
config_parse_flood_generic("4:60", i, "known-users", FLD_INVITE); /* INVITE flood protection: max 4 per 60s */
|
||||
config_parse_flood_generic("4:120", i, "known-users", FLD_KNOCK); /* KNOCK protection: max 4 per 120s */
|
||||
@ -1702,6 +1709,7 @@ void config_setdefaultsettings(Configuration *i)
|
||||
/* - unknown-users */
|
||||
config_parse_flood_generic("2:60", i, "unknown-users", FLD_NICK); /* NICK flood protection: max 2 per 60s */
|
||||
config_parse_flood_generic("2:90", i, "unknown-users", FLD_JOIN); /* JOIN flood protection: max 2 per 90s */
|
||||
config_parse_flood_generic("2:90", i, "unknown-users", FLD_VHOST); /* MODE -x flood protection: max 2 per 90s */
|
||||
config_parse_flood_generic("4:120", i, "unknown-users", FLD_AWAY); /* AWAY flood protection: max 4 per 120s */
|
||||
config_parse_flood_generic("2:60", i, "unknown-users", FLD_INVITE); /* INVITE flood protection: max 2 per 60s */
|
||||
config_parse_flood_generic("2:120", i, "unknown-users", FLD_KNOCK); /* KNOCK protection: max 2 per 120s */
|
||||
@ -2411,7 +2419,8 @@ void config_rehash()
|
||||
}
|
||||
for (listen_ptr = conf_listen; listen_ptr; listen_ptr = listen_ptr->next)
|
||||
{
|
||||
listen_ptr->flag.temporary = 1;
|
||||
if (!(listen_ptr->options & LISTENER_CONTROL))
|
||||
listen_ptr->flag.temporary = 1;
|
||||
}
|
||||
for (tld_ptr = conf_tld; tld_ptr; tld_ptr = (ConfigItem_tld *) next)
|
||||
{
|
||||
@ -2642,152 +2651,87 @@ void config_switchover(void)
|
||||
log_blocks_switchover();
|
||||
}
|
||||
|
||||
int config_run_blocks()
|
||||
/** Priority of config blocks during CONFIG_TEST stage */
|
||||
static const char *config_test_priority_blocks[] =
|
||||
{
|
||||
"me",
|
||||
"secret",
|
||||
"log", /* "log" needs to be before "set" in CONFIG_TEST */
|
||||
"set",
|
||||
"class",
|
||||
};
|
||||
|
||||
/** Priority of config blocks during CONFIG_RUN stage */
|
||||
static const char *config_run_priority_blocks[] =
|
||||
{
|
||||
"me",
|
||||
"secret",
|
||||
"set",
|
||||
"log", /* "log" needs to be after "set" in CONFIG_RUN */
|
||||
"class",
|
||||
};
|
||||
|
||||
int config_test_blocks()
|
||||
{
|
||||
ConfigEntry *ce;
|
||||
ConfigFile *cfptr;
|
||||
ConfigCommand *cc;
|
||||
int errors = 0;
|
||||
int i;
|
||||
Hook *h;
|
||||
ConfigItem_allow *allow;
|
||||
|
||||
/* Stage 1: set block first */
|
||||
for (cfptr = conf; cfptr; cfptr = cfptr->next)
|
||||
invalid_snomasks_encountered = 0;
|
||||
|
||||
/* Stage 1: first the priority blocks, in the order as specified
|
||||
* in config_test_priority_blocks[]
|
||||
*/
|
||||
for (i=0; i < ARRAY_SIZEOF(config_test_priority_blocks); i++)
|
||||
{
|
||||
if (config_verbose > 1)
|
||||
config_status("Running %s", cfptr->filename);
|
||||
for (ce = cfptr->items; ce; ce = ce->next)
|
||||
const char *config_block = config_test_priority_blocks[i];
|
||||
cc = config_binary_search(config_block);
|
||||
if (!cc)
|
||||
abort(); /* internal fuckup */
|
||||
for (cfptr = conf; cfptr; cfptr = cfptr->next)
|
||||
{
|
||||
if (!strcmp(ce->name, "set"))
|
||||
if (config_verbose > 1)
|
||||
config_status("Running %s", cfptr->filename);
|
||||
for (ce = cfptr->items; ce; ce = ce->next)
|
||||
{
|
||||
if (_conf_set(cfptr, ce) < 0)
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Stage 2: now class blocks */
|
||||
for (cfptr = conf; cfptr; cfptr = cfptr->next)
|
||||
{
|
||||
if (config_verbose > 1)
|
||||
config_status("Running %s", cfptr->filename);
|
||||
for (ce = cfptr->items; ce; ce = ce->next)
|
||||
{
|
||||
if (!strcmp(ce->name, "class"))
|
||||
{
|
||||
if (_conf_class(cfptr, ce) < 0)
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Stage 3: now all the rest */
|
||||
for (cfptr = conf; cfptr; cfptr = cfptr->next)
|
||||
{
|
||||
if (config_verbose > 1)
|
||||
config_status("Running %s", cfptr->filename);
|
||||
for (ce = cfptr->items; ce; ce = ce->next)
|
||||
{
|
||||
/* These are already processed above (set, class)
|
||||
* or via config_test_blocks() (secret).
|
||||
*/
|
||||
if (!strcmp(ce->name, "set") ||
|
||||
!strcmp(ce->name, "class") ||
|
||||
!strcmp(ce->name, "secret"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((cc = config_binary_search(ce->name))) {
|
||||
if ((cc->conffunc) && (cc->conffunc(cfptr, ce) < 0))
|
||||
errors++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int value;
|
||||
for (h = Hooks[HOOKTYPE_CONFIGRUN]; h; h = h->next)
|
||||
if (!strcmp(ce->name, config_block))
|
||||
{
|
||||
value = (*(h->func.intfunc))(cfptr,ce,CONFIG_MAIN);
|
||||
if (value == 1)
|
||||
break;
|
||||
int n = cc->testfunc(cfptr, ce);
|
||||
errors += n;
|
||||
if (!strcmp(config_block, "secret") && (n == 0))
|
||||
{
|
||||
/* Yeah special case: secret { } blocks we run
|
||||
* immediately here.
|
||||
*/
|
||||
_conf_secret(cfptr, ce);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close_unbound_listeners();
|
||||
listen_cleanup();
|
||||
close_unbound_listeners();
|
||||
loop.do_bancheck = 1;
|
||||
config_switchover();
|
||||
update_throttling_timer_settings();
|
||||
|
||||
/* initialize conf_files with defaults if the block isn't set: */
|
||||
if (!conf_files)
|
||||
_conf_files(NULL, NULL);
|
||||
|
||||
if (errors > 0)
|
||||
{
|
||||
config_error("%i fatal errors encountered", errors);
|
||||
}
|
||||
return (errors > 0 ? -1 : 1);
|
||||
}
|
||||
|
||||
|
||||
int config_test_blocks()
|
||||
{
|
||||
ConfigEntry *ce;
|
||||
ConfigFile *cfptr;
|
||||
ConfigCommand *cc;
|
||||
int errors = 0;
|
||||
Hook *h;
|
||||
|
||||
invalid_snomasks_encountered = 0;
|
||||
|
||||
/* First, all the log { } blocks everywhere */
|
||||
/* Stage 2: now all the other config blocks */
|
||||
for (cfptr = conf; cfptr; cfptr = cfptr->next)
|
||||
{
|
||||
if (config_verbose > 1)
|
||||
config_status("Testing %s", cfptr->filename);
|
||||
/* First test and run the log { } blocks */
|
||||
config_status("Running %s", cfptr->filename);
|
||||
for (ce = cfptr->items; ce; ce = ce->next)
|
||||
{
|
||||
if (!strcmp(ce->name, "log"))
|
||||
errors += config_test_log(cfptr, ce);
|
||||
}
|
||||
}
|
||||
|
||||
for (cfptr = conf; cfptr; cfptr = cfptr->next)
|
||||
{
|
||||
if (config_verbose > 1)
|
||||
config_status("Testing %s", cfptr->filename);
|
||||
/* First test and run the secret { } blocks */
|
||||
for (ce = cfptr->items; ce; ce = ce->next)
|
||||
{
|
||||
if (!strcmp(ce->name, "secret"))
|
||||
char skip = 0;
|
||||
for (i=0; i < ARRAY_SIZEOF(config_test_priority_blocks); i++)
|
||||
{
|
||||
int n = _test_secret(cfptr, ce);
|
||||
errors += n;
|
||||
if (n == 0)
|
||||
_conf_secret(cfptr, ce);
|
||||
if (!strcmp(ce->name, config_test_priority_blocks[i]))
|
||||
{
|
||||
skip = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* First test the set { } block */
|
||||
for (ce = cfptr->items; ce; ce = ce->next)
|
||||
{
|
||||
if (!strcmp(ce->name, "set"))
|
||||
errors += _test_set(cfptr, ce);
|
||||
}
|
||||
/* Now test all the rest */
|
||||
for (ce = cfptr->items; ce; ce = ce->next)
|
||||
{
|
||||
/* These are already processed, so skip them here.. */
|
||||
if (!strcmp(ce->name, "secret") ||
|
||||
!strcmp(ce->name, "set") ||
|
||||
!strcmp(ce->name, "log"))
|
||||
{
|
||||
if (skip)
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((cc = config_binary_search(ce->name))) {
|
||||
if (cc->testfunc)
|
||||
errors += (cc->testfunc(cfptr, ce));
|
||||
@ -2841,7 +2785,9 @@ int config_test_blocks()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
errors += config_post_test();
|
||||
|
||||
if (errors > 0)
|
||||
{
|
||||
config_error("%i errors encountered", errors);
|
||||
@ -2856,6 +2802,96 @@ int config_test_blocks()
|
||||
return (errors > 0 ? -1 : 1);
|
||||
}
|
||||
|
||||
int config_run_blocks(void)
|
||||
{
|
||||
ConfigEntry *ce;
|
||||
ConfigFile *cfptr;
|
||||
ConfigCommand *cc;
|
||||
int errors = 0;
|
||||
int i;
|
||||
Hook *h;
|
||||
ConfigItem_allow *allow;
|
||||
|
||||
/* Stage 1: first the priority blocks, in the order as specified
|
||||
* in config_run_priority_blocks[]
|
||||
*/
|
||||
for (i=0; i < ARRAY_SIZEOF(config_run_priority_blocks); i++)
|
||||
{
|
||||
const char *config_block = config_run_priority_blocks[i];
|
||||
cc = config_binary_search(config_block);
|
||||
if (!cc)
|
||||
abort(); /* internal fuckup */
|
||||
if (!strcmp(config_block, "secret"))
|
||||
continue; /* yeah special case, we already processed the run part in test for these */
|
||||
for (cfptr = conf; cfptr; cfptr = cfptr->next)
|
||||
{
|
||||
if (config_verbose > 1)
|
||||
config_status("Running %s", cfptr->filename);
|
||||
for (ce = cfptr->items; ce; ce = ce->next)
|
||||
{
|
||||
if (!strcmp(ce->name, config_block))
|
||||
{
|
||||
if (cc->conffunc(cfptr, ce) < 0)
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Stage 2: now all the other config blocks */
|
||||
for (cfptr = conf; cfptr; cfptr = cfptr->next)
|
||||
{
|
||||
if (config_verbose > 1)
|
||||
config_status("Running %s", cfptr->filename);
|
||||
for (ce = cfptr->items; ce; ce = ce->next)
|
||||
{
|
||||
char skip = 0;
|
||||
for (i=0; i < ARRAY_SIZEOF(config_run_priority_blocks); i++)
|
||||
{
|
||||
if (!strcmp(ce->name, config_run_priority_blocks[i]))
|
||||
{
|
||||
skip = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (skip)
|
||||
continue;
|
||||
|
||||
if ((cc = config_binary_search(ce->name))) {
|
||||
if ((cc->conffunc) && (cc->conffunc(cfptr, ce) < 0))
|
||||
errors++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int value;
|
||||
for (h = Hooks[HOOKTYPE_CONFIGRUN]; h; h = h->next)
|
||||
{
|
||||
value = (*(h->func.intfunc))(cfptr,ce,CONFIG_MAIN);
|
||||
if (value == 1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close_unbound_listeners();
|
||||
listen_cleanup();
|
||||
close_unbound_listeners();
|
||||
loop.do_bancheck = 1;
|
||||
config_switchover();
|
||||
update_throttling_timer_settings();
|
||||
|
||||
/* initialize conf_files with defaults if the block isn't set: */
|
||||
if (!conf_files)
|
||||
_conf_files(NULL, NULL);
|
||||
|
||||
if (errors > 0)
|
||||
{
|
||||
config_error("%i fatal errors encountered", errors);
|
||||
}
|
||||
return (errors > 0 ? -1 : 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Service functions
|
||||
*/
|
||||
@ -2935,7 +2971,7 @@ int count_oper_sessions(const char *name)
|
||||
return count;
|
||||
}
|
||||
|
||||
ConfigItem_listen *find_listen(const char *ipmask, int port, int ipv6)
|
||||
ConfigItem_listen *find_listen(const char *ipmask, int port, SocketType socket_type)
|
||||
{
|
||||
ConfigItem_listen *e;
|
||||
|
||||
@ -2943,8 +2979,19 @@ ConfigItem_listen *find_listen(const char *ipmask, int port, int ipv6)
|
||||
return NULL;
|
||||
|
||||
for (e = conf_listen; e; e = e->next)
|
||||
if ((e->ipv6 == ipv6) && (e->port == port) && !strcmp(e->ip, ipmask))
|
||||
return e;
|
||||
{
|
||||
if (e->socket_type != socket_type)
|
||||
continue;
|
||||
if (e->socket_type == SOCKET_TYPE_UNIX)
|
||||
{
|
||||
if (!strcmp(e->file, ipmask))
|
||||
return e;
|
||||
} else
|
||||
{
|
||||
if ((e->socket_type == socket_type) && (e->port == port) && !strcmp(e->ip, ipmask))
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -3889,7 +3936,9 @@ int _conf_oper(ConfigFile *conf, ConfigEntry *ce)
|
||||
oper = safe_alloc(sizeof(ConfigItem_oper));
|
||||
safe_strdup(oper->name, ce->value);
|
||||
|
||||
oper->server_notice_colors = tempiConf.server_notice_colors; /* default */
|
||||
/* Inherit some defaults: */
|
||||
oper->server_notice_colors = tempiConf.server_notice_colors;
|
||||
oper->server_notice_show_event = tempiConf.server_notice_show_event;
|
||||
|
||||
for (cep = ce->items; cep; cep = cep->next)
|
||||
{
|
||||
@ -3937,6 +3986,10 @@ int _conf_oper(ConfigFile *conf, ConfigEntry *ce)
|
||||
{
|
||||
oper->server_notice_colors = config_checkval(cep->value, CFG_YESNO);
|
||||
}
|
||||
else if (!strcmp(cep->name, "server-notice-show-event"))
|
||||
{
|
||||
oper->server_notice_show_event = config_checkval(cep->value, CFG_YESNO);
|
||||
}
|
||||
else if (!strcmp(cep->name, "modes"))
|
||||
{
|
||||
oper->modes = set_usermode(cep->value);
|
||||
@ -4069,6 +4122,9 @@ int _test_oper(ConfigFile *conf, ConfigEntry *ce)
|
||||
else if (!strcmp(cep->name, "server-notice-colors"))
|
||||
{
|
||||
}
|
||||
else if (!strcmp(cep->name, "server-notice-show-event"))
|
||||
{
|
||||
}
|
||||
/* oper::modes */
|
||||
else if (!strcmp(cep->name, "modes"))
|
||||
{
|
||||
@ -4777,6 +4833,7 @@ int _conf_listen(ConfigFile *conf, ConfigEntry *ce)
|
||||
ConfigEntry *cepp;
|
||||
ConfigEntry *tlsconfig = NULL;
|
||||
ConfigItem_listen *listen = NULL;
|
||||
char *file = NULL;
|
||||
char *ip = NULL;
|
||||
int start=0, end=0, port, isnew;
|
||||
int tmpflags =0;
|
||||
@ -4784,6 +4841,10 @@ int _conf_listen(ConfigFile *conf, ConfigEntry *ce)
|
||||
|
||||
for (cep = ce->items; cep; cep = cep->next)
|
||||
{
|
||||
if (!strcmp(cep->name, "file"))
|
||||
{
|
||||
file = cep->value;
|
||||
} else
|
||||
if (!strcmp(cep->name, "ip"))
|
||||
{
|
||||
ip = cep->value;
|
||||
@ -4825,18 +4886,44 @@ int _conf_listen(ConfigFile *conf, ConfigEntry *ce)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* UNIX domain socket code */
|
||||
if (file)
|
||||
{
|
||||
if (!(listen = find_listen(file, 0, SOCKET_TYPE_UNIX)))
|
||||
{
|
||||
listen = safe_alloc(sizeof(ConfigItem_listen));
|
||||
safe_strdup(listen->file, file);
|
||||
listen->socket_type = SOCKET_TYPE_UNIX;
|
||||
listen->fd = -1;
|
||||
isnew = 1;
|
||||
} else {
|
||||
isnew = 0;
|
||||
}
|
||||
|
||||
if (listen->options & LISTENER_BOUND)
|
||||
tmpflags |= LISTENER_BOUND;
|
||||
|
||||
listen->options = tmpflags;
|
||||
if (isnew)
|
||||
AddListItem(listen, conf_listen);
|
||||
listen->flag.temporary = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (port = start; port <= end; port++)
|
||||
{
|
||||
/* First deal with IPv4 */
|
||||
if (!strchr(ip, ':'))
|
||||
{
|
||||
if (!(listen = find_listen(ip, port, 0)))
|
||||
if (!(listen = find_listen(ip, port, SOCKET_TYPE_IPV4)))
|
||||
{
|
||||
listen = safe_alloc(sizeof(ConfigItem_listen));
|
||||
safe_strdup(listen->ip, ip);
|
||||
listen->port = port;
|
||||
listen->fd = -1;
|
||||
listen->ipv6 = 0;
|
||||
listen->socket_type = SOCKET_TYPE_IPV4;
|
||||
isnew = 1;
|
||||
} else
|
||||
isnew = 0;
|
||||
@ -4915,13 +5002,13 @@ int _conf_listen(ConfigFile *conf, ConfigEntry *ce)
|
||||
{
|
||||
if (strchr(ip, ':') || (*ip == '*'))
|
||||
{
|
||||
if (!(listen = find_listen(ip, port, 1)))
|
||||
if (!(listen = find_listen(ip, port, SOCKET_TYPE_IPV6)))
|
||||
{
|
||||
listen = safe_alloc(sizeof(ConfigItem_listen));
|
||||
safe_strdup(listen->ip, ip);
|
||||
listen->port = port;
|
||||
listen->fd = -1;
|
||||
listen->ipv6 = 1;
|
||||
listen->socket_type = SOCKET_TYPE_IPV6;
|
||||
isnew = 1;
|
||||
} else
|
||||
isnew = 0;
|
||||
@ -5002,7 +5089,8 @@ int _test_listen(ConfigFile *conf, ConfigEntry *ce)
|
||||
ConfigEntry *cep;
|
||||
ConfigEntry *cepp;
|
||||
int errors = 0;
|
||||
char has_ip = 0, has_port = 0, has_options = 0, port_6667 = 0;
|
||||
char has_file = 0, has_ip = 0, has_port = 0, has_options = 0, port_6667 = 0;
|
||||
char *file = NULL;
|
||||
char *ip = NULL;
|
||||
Hook *h;
|
||||
|
||||
@ -5117,6 +5205,11 @@ int _test_listen(ConfigFile *conf, ConfigEntry *ce)
|
||||
}
|
||||
continue; /* always */
|
||||
} else
|
||||
if (!strcmp(cep->name, "file"))
|
||||
{
|
||||
has_file = 1;
|
||||
file = cep->value;
|
||||
} else
|
||||
if (!strcmp(cep->name, "ip"))
|
||||
{
|
||||
has_ip = 1;
|
||||
@ -5189,18 +5282,32 @@ int _test_listen(ConfigFile *conf, ConfigEntry *ce)
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_ip)
|
||||
if (has_file)
|
||||
{
|
||||
config_error("%s:%d: listen block requires an listen::ip",
|
||||
ce->file->filename, ce->line_number);
|
||||
errors++;
|
||||
}
|
||||
if (has_ip || has_port)
|
||||
{
|
||||
config_error("%s:%d: listen block should either have a 'file' (for *NIX domain socket), "
|
||||
"OR have an 'ip' and 'port' (for IPv4/IPv6). You cannot combine both in one listen block.",
|
||||
ce->file->filename, ce->line_number);
|
||||
errors++;
|
||||
} else {
|
||||
// TODO: check if file can be created fresh etc.
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (!has_ip)
|
||||
{
|
||||
config_error("%s:%d: listen block requires an listen::ip",
|
||||
ce->file->filename, ce->line_number);
|
||||
errors++;
|
||||
}
|
||||
|
||||
if (!has_port)
|
||||
{
|
||||
config_error("%s:%d: listen block requires an listen::port",
|
||||
ce->file->filename, ce->line_number);
|
||||
errors++;
|
||||
if (!has_port)
|
||||
{
|
||||
config_error("%s:%d: listen block requires an listen::port",
|
||||
ce->file->filename, ce->line_number);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
if (port_6667)
|
||||
@ -7167,6 +7274,9 @@ int _conf_set(ConfigFile *conf, ConfigEntry *ce)
|
||||
else if (!strcmp(cep->name, "server-notice-colors")) {
|
||||
tempiConf.server_notice_colors = config_checkval(cep->value, CFG_YESNO);
|
||||
}
|
||||
else if (!strcmp(cep->name, "server-notice-show-event")) {
|
||||
tempiConf.server_notice_show_event = config_checkval(cep->value, CFG_YESNO);
|
||||
}
|
||||
else if (!strcmp(cep->name, "level-on-join")) {
|
||||
const char *res = channellevel_to_string(cep->value); /* 'halfop', etc */
|
||||
if (!res)
|
||||
@ -7380,6 +7490,10 @@ int _conf_set(ConfigFile *conf, ConfigEntry *ce)
|
||||
{
|
||||
config_parse_flood_generic(ceppp->value, &tempiConf, cepp->name, FLD_NICK);
|
||||
}
|
||||
else if (!strcmp(ceppp->name, "vhost-flood"))
|
||||
{
|
||||
config_parse_flood_generic(ceppp->value, &tempiConf, cepp->name, FLD_VHOST);
|
||||
}
|
||||
else if (!strcmp(ceppp->name, "join-flood"))
|
||||
{
|
||||
config_parse_flood_generic(ceppp->value, &tempiConf, cepp->name, FLD_JOIN);
|
||||
@ -7847,6 +7961,9 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
|
||||
else if (!strcmp(cep->name, "server-notice-colors")) {
|
||||
CheckNull(cep);
|
||||
}
|
||||
else if (!strcmp(cep->name, "server-notice-show-event")) {
|
||||
CheckNull(cep);
|
||||
}
|
||||
else if (!strcmp(cep->name, "level-on-join")) {
|
||||
CheckNull(cep);
|
||||
CheckDuplicate(cep, level_on_join, "level-on-join");
|
||||
@ -8340,6 +8457,19 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(ceppp->name, "vhost-flood"))
|
||||
{
|
||||
int cnt, period;
|
||||
CheckNull(ceppp);
|
||||
if (!config_parse_flood(ceppp->value, &cnt, &period) ||
|
||||
(cnt < 1) || (cnt > 255) || (period < 5))
|
||||
{
|
||||
config_error("%s:%i: set::anti-flood::vhost-flood error. Syntax is '<count>:<period>' (eg 5:60), "
|
||||
"count should be 1-255, period should be greater than 4",
|
||||
ceppp->file->filename, ceppp->line_number);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(ceppp->name, "join-flood"))
|
||||
{
|
||||
int cnt, period;
|
||||
@ -9191,14 +9321,22 @@ void start_listeners(void)
|
||||
log_data_string("listen_ip", listener->ip),
|
||||
log_data_integer("listen_port", listener->port));
|
||||
} else {
|
||||
if (listener->ipv6)
|
||||
snprintf(boundmsg_ipv6+strlen(boundmsg_ipv6), sizeof(boundmsg_ipv6)-strlen(boundmsg_ipv6),
|
||||
"%s:%d%s, ", listener->ip, listener->port,
|
||||
listener->options & LISTENER_TLS ? "(TLS)" : "");
|
||||
else
|
||||
snprintf(boundmsg_ipv4+strlen(boundmsg_ipv4), sizeof(boundmsg_ipv4)-strlen(boundmsg_ipv4),
|
||||
"%s:%d%s, ", listener->ip, listener->port,
|
||||
listener->options & LISTENER_TLS ? "(TLS)" : "");
|
||||
switch (listener->socket_type)
|
||||
{
|
||||
case SOCKET_TYPE_IPV4:
|
||||
snprintf(boundmsg_ipv4+strlen(boundmsg_ipv4), sizeof(boundmsg_ipv4)-strlen(boundmsg_ipv4),
|
||||
"%s:%d%s, ", listener->ip, listener->port,
|
||||
listener->options & LISTENER_TLS ? "(TLS)" : "");
|
||||
break;
|
||||
case SOCKET_TYPE_IPV6:
|
||||
snprintf(boundmsg_ipv6+strlen(boundmsg_ipv6), sizeof(boundmsg_ipv6)-strlen(boundmsg_ipv6),
|
||||
"%s:%d%s, ", listener->ip, listener->port,
|
||||
listener->options & LISTENER_TLS ? "(TLS)" : "");
|
||||
break;
|
||||
// TODO: show unix domain sockets ;)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9268,6 +9406,7 @@ void config_run(void)
|
||||
{
|
||||
extcmodes_check_for_changes();
|
||||
start_listeners();
|
||||
add_proc_io_server();
|
||||
free_all_config_resources();
|
||||
}
|
||||
|
||||
@ -10499,13 +10638,6 @@ void resource_download_complete(const char *url, const char *file, const char *e
|
||||
safe_strdup(wce->ce->value, rs->file); // now information of url is lost, hm!!
|
||||
}
|
||||
}
|
||||
|
||||
/* If rehashing, check if we are done.
|
||||
* If booting (not rehashing), this is done from the
|
||||
* startup loop where it also checks is_config_read_finished().
|
||||
*/
|
||||
if (loop.rehashing && is_config_read_finished())
|
||||
rehash_internal(loop.rehash_save_client);
|
||||
}
|
||||
|
||||
/** Request to REHASH the configuration file.
|
||||
@ -10540,13 +10672,16 @@ void request_rehash(Client *client)
|
||||
|
||||
int rehash_internal(Client *client)
|
||||
{
|
||||
int failure;
|
||||
|
||||
/* Log it here if it is by a signal */
|
||||
if (client == NULL)
|
||||
unreal_log(ULOG_INFO, "config", "CONFIG_RELOAD", client, "Rehashing server configuration file [./unrealircd rehash]");
|
||||
|
||||
loop.rehashing = 1; /* double checking.. */
|
||||
loop.rehashing = 2; /* now doing the actual rehash */
|
||||
|
||||
if (config_test() == 0)
|
||||
failure = config_test();
|
||||
if (failure == 0)
|
||||
config_run();
|
||||
/* TODO: uh.. are we supposed to do all this for a failed rehash too? maybe some but not all? */
|
||||
reread_motdsandrules();
|
||||
@ -10557,8 +10692,11 @@ int rehash_internal(Client *client)
|
||||
// unload_all_unused_moddata(); -- this will crash
|
||||
umodes_check_for_changes();
|
||||
charsys_check_for_changes();
|
||||
|
||||
/* Clear everything now that we are done */
|
||||
loop.rehashing = 0;
|
||||
remote_rehash_client = NULL;
|
||||
procio_post_rehash(failure);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -649,6 +649,13 @@ int crashreport_send(char *fname)
|
||||
if ((n < 0) || strncmp(buf, "HTTP/1.1 100", 12))
|
||||
{
|
||||
printf("Error transmitting bug report (stage II, n=%d)\n", n);
|
||||
if (!strncmp(buf, "HTTP/1.1 403", 12))
|
||||
{
|
||||
printf("Your crash report was rejected automatically.\n"
|
||||
"This normally means your UnrealIRCd version is too old and unsupported.\n"
|
||||
"Chances are that your crash issue is already fixed in a later release.\n"
|
||||
"Check https://www.unrealircd.org/ for latest releases!\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,7 @@ static void dbuf_free(dbufbuf *ptr)
|
||||
|
||||
void dbuf_queue_init(dbuf *dyn)
|
||||
{
|
||||
memset(dyn, 0, sizeof(dbuf));
|
||||
INIT_LIST_HEAD(&dyn->dbuf_list);
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ static int unrealdns_sock_create_cb(ares_socket_t fd, int type, void *data)
|
||||
return ARES_SUCCESS;
|
||||
}
|
||||
|
||||
static EVENT(unrealdns_timeout)
|
||||
EVENT(unrealdns_timeout)
|
||||
{
|
||||
ares_process_fd(resolver_channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
|
||||
}
|
||||
|
344
src/ircd.c
344
src/ircd.c
@ -25,209 +25,10 @@
|
||||
char *malloc_options = "h" MALLOC_FLAGS_EXTRA;
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
extern char unreallogo[];
|
||||
#endif
|
||||
int SVSNOOP = 0;
|
||||
extern MODVAR char *buildid;
|
||||
time_t timeofday = 0;
|
||||
struct timeval timeofday_tv;
|
||||
int tainted = 0;
|
||||
LoopStruct loop;
|
||||
#ifndef _WIN32
|
||||
uid_t irc_uid = 0;
|
||||
gid_t irc_gid = 0;
|
||||
#endif
|
||||
|
||||
MODVAR IRCCounts irccounts;
|
||||
MODVAR Client me; /* That's me */
|
||||
MODVAR char *me_hash;
|
||||
extern char backupbuf[8192];
|
||||
#ifdef _WIN32
|
||||
extern SERVICE_STATUS_HANDLE IRCDStatusHandle;
|
||||
extern SERVICE_STATUS IRCDStatus;
|
||||
#endif
|
||||
|
||||
MODVAR unsigned char conf_debuglevel = 0;
|
||||
|
||||
/* Forward declarations */
|
||||
void server_reboot(const char *);
|
||||
void restart(const char *);
|
||||
static void open_debugfile(), setup_signals();
|
||||
extern void init_glines(void);
|
||||
extern void tkl_init(void);
|
||||
extern void process_clients(void);
|
||||
extern void unrealdb_test(void);
|
||||
|
||||
#ifndef _WIN32
|
||||
MODVAR char **myargv;
|
||||
#else
|
||||
LPCSTR cmdLine;
|
||||
#endif
|
||||
char *configfile = NULL; /* Server configuration file */
|
||||
int debuglevel = 0; /* Server debug level */
|
||||
int bootopt = 0; /* Server boot option flags */
|
||||
char *debugmode = ""; /* -"- -"- -"- */
|
||||
char *sbrk0; /* initial sbrk(0) */
|
||||
static int dorehash = 0, dorestart = 0, doreloadcert = 0;
|
||||
MODVAR int booted = FALSE;
|
||||
|
||||
void s_die()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
Client *client;
|
||||
if (!IsService)
|
||||
{
|
||||
loop.terminating = 1;
|
||||
unload_all_modules();
|
||||
|
||||
list_for_each_entry(client, &lclient_list, lclient_node)
|
||||
(void) send_queued(client);
|
||||
|
||||
exit(-1);
|
||||
}
|
||||
else {
|
||||
SERVICE_STATUS status;
|
||||
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||||
SC_HANDLE hService = OpenService(hSCManager, "UnrealIRCd", SERVICE_STOP);
|
||||
ControlService(hService, SERVICE_CONTROL_STOP, &status);
|
||||
}
|
||||
#else
|
||||
loop.terminating = 1;
|
||||
unload_all_modules();
|
||||
unlink(conf_files ? conf_files->pid_file : IRCD_PIDFILE);
|
||||
exit(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
static void s_rehash()
|
||||
{
|
||||
struct sigaction act;
|
||||
dorehash = 1;
|
||||
act.sa_handler = s_rehash;
|
||||
act.sa_flags = 0;
|
||||
(void)sigemptyset(&act.sa_mask);
|
||||
(void)sigaddset(&act.sa_mask, SIGHUP);
|
||||
(void)sigaction(SIGHUP, &act, NULL);
|
||||
}
|
||||
|
||||
static void s_reloadcert()
|
||||
{
|
||||
struct sigaction act;
|
||||
doreloadcert = 1;
|
||||
act.sa_handler = s_reloadcert;
|
||||
act.sa_flags = 0;
|
||||
(void)sigemptyset(&act.sa_mask);
|
||||
(void)sigaddset(&act.sa_mask, SIGUSR1);
|
||||
(void)sigaction(SIGUSR1, &act, NULL);
|
||||
}
|
||||
#endif // #ifndef _WIN32
|
||||
|
||||
void restart(const char *mesg)
|
||||
{
|
||||
server_reboot(mesg);
|
||||
}
|
||||
|
||||
void s_restart()
|
||||
{
|
||||
dorestart = 1;
|
||||
#if 0
|
||||
static int restarting = 0;
|
||||
|
||||
if (restarting == 0) {
|
||||
/*
|
||||
* Send (or attempt to) a dying scream to oper if present
|
||||
*/
|
||||
|
||||
restarting = 1;
|
||||
server_reboot("SIGINT");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
/** Signal handler for signals which we ignore,
|
||||
* like SIGPIPE ("Broken pipe") and SIGWINCH (terminal window changed) etc.
|
||||
*/
|
||||
void ignore_this_signal()
|
||||
{
|
||||
struct sigaction act;
|
||||
|
||||
act.sa_handler = ignore_this_signal;
|
||||
act.sa_flags = 0;
|
||||
(void)sigemptyset(&act.sa_mask);
|
||||
(void)sigaddset(&act.sa_mask, SIGALRM);
|
||||
(void)sigaddset(&act.sa_mask, SIGPIPE);
|
||||
(void)sigaction(SIGALRM, &act, (struct sigaction *)NULL);
|
||||
(void)sigaction(SIGPIPE, &act, (struct sigaction *)NULL);
|
||||
#ifdef SIGWINCH
|
||||
(void)sigaddset(&act.sa_mask, SIGWINCH);
|
||||
(void)sigaction(SIGWINCH, &act, (struct sigaction *)NULL);
|
||||
#endif
|
||||
}
|
||||
#endif /* #ifndef _WIN32 */
|
||||
|
||||
|
||||
void server_reboot(const char *mesg)
|
||||
{
|
||||
int i;
|
||||
Client *client;
|
||||
unreal_log(ULOG_INFO, "main", "UNREALIRCD_RESTARTING", NULL,
|
||||
"Restarting server: $reason",
|
||||
log_data_string("reason", mesg));
|
||||
|
||||
list_for_each_entry(client, &lclient_list, lclient_node)
|
||||
(void) send_queued(client);
|
||||
|
||||
/*
|
||||
* ** fd 0 must be 'preserved' if either the -d or -i options have
|
||||
* ** been passed to us before restarting.
|
||||
*/
|
||||
#ifdef HAVE_SYSLOG
|
||||
(void)closelog();
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
for (i = 3; i < MAXCONNECTIONS; i++)
|
||||
(void)close(i);
|
||||
if (!(bootopt & (BOOT_TTY | BOOT_DEBUG)))
|
||||
(void)close(2);
|
||||
(void)close(1);
|
||||
(void)close(0);
|
||||
(void)execv(MYNAME, myargv);
|
||||
#else
|
||||
close_connections();
|
||||
if (!IsService)
|
||||
{
|
||||
CleanUp();
|
||||
WinExec(cmdLine, SW_SHOWDEFAULT);
|
||||
}
|
||||
#endif
|
||||
unload_all_modules();
|
||||
#ifdef _WIN32
|
||||
if (IsService)
|
||||
{
|
||||
SERVICE_STATUS status;
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFO si;
|
||||
char fname[MAX_PATH];
|
||||
memset(&status, 0, sizeof(status));
|
||||
memset(&si, 0, sizeof(si));
|
||||
IRCDStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
||||
SetServiceStatus(IRCDStatusHandle, &IRCDStatus);
|
||||
GetModuleFileName(GetModuleHandle(NULL), fname, MAX_PATH);
|
||||
CreateProcess(fname, "restartsvc", NULL, NULL, FALSE,
|
||||
0, NULL, NULL, &si, &pi);
|
||||
IRCDStatus.dwCurrentState = SERVICE_STOPPED;
|
||||
SetServiceStatus(IRCDStatusHandle, &IRCDStatus);
|
||||
ExitProcess(0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
MODVAR char *areason;
|
||||
|
||||
EVENT(loop_event)
|
||||
{
|
||||
@ -557,58 +358,6 @@ void fix_timers(void)
|
||||
}
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
/* Generate 3 cloak keys and print to console */
|
||||
static void generate_cloakkeys()
|
||||
{
|
||||
#define GENERATE_CLOAKKEY_LEN 80 /* Length of cloak keys to generate. */
|
||||
char keyBuf[GENERATE_CLOAKKEY_LEN + 1];
|
||||
int keyNum;
|
||||
int charIndex;
|
||||
|
||||
short has_upper;
|
||||
short has_lower;
|
||||
short has_num;
|
||||
|
||||
fprintf(stderr, "Here are 3 random cloak keys that you can copy-paste to your configuration file:\n\n");
|
||||
|
||||
fprintf(stderr, "set {\n\tcloak-keys {\n");
|
||||
for (keyNum = 0; keyNum < 3; ++keyNum)
|
||||
{
|
||||
has_upper = 0;
|
||||
has_lower = 0;
|
||||
has_num = 0;
|
||||
|
||||
for (charIndex = 0; charIndex < sizeof(keyBuf)-1; ++charIndex)
|
||||
{
|
||||
switch (getrandom8() % 3)
|
||||
{
|
||||
case 0: /* Uppercase. */
|
||||
keyBuf[charIndex] = (char)('A' + (getrandom8() % ('Z' - 'A')));
|
||||
has_upper = 1;
|
||||
break;
|
||||
case 1: /* Lowercase. */
|
||||
keyBuf[charIndex] = (char)('a' + (getrandom8() % ('z' - 'a')));
|
||||
has_lower = 1;
|
||||
break;
|
||||
case 2: /* Digit. */
|
||||
keyBuf[charIndex] = (char)('0' + (getrandom8() % ('9' - '0')));
|
||||
has_num = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
keyBuf[sizeof(keyBuf)-1] = '\0';
|
||||
|
||||
if (has_upper && has_lower && has_num)
|
||||
fprintf(stderr, "\t\t\"%s\";\n", keyBuf);
|
||||
else
|
||||
/* Try again. For this reason, keyNum must be signed. */
|
||||
keyNum--;
|
||||
}
|
||||
fprintf(stderr, "\t}\n}\n\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* MY tdiff... because 'double' sucks.
|
||||
* This should work until 2038, and very likely after that as well
|
||||
* because 'long' should be 64 bit on all systems by then... -- Syzop
|
||||
@ -677,30 +426,19 @@ void detect_timeshift_and_warn(void)
|
||||
oldtimeofday = timeofday;
|
||||
}
|
||||
|
||||
/** Check if at least 'minimum' seconds passed by since last run.
|
||||
* @param tv_old Pointer to a timeval struct to keep track of things.
|
||||
* @param minimum The time specified in milliseconds (eg: 1000 for 1 second)
|
||||
* @returns When 'minimum' msec passed 1 is returned and the time is reset, otherwise 0 is returned.
|
||||
*/
|
||||
int minimum_msec_since_last_run(struct timeval *tv_old, long minimum)
|
||||
void SetupEvents(void)
|
||||
{
|
||||
long v;
|
||||
|
||||
if (tv_old->tv_sec == 0)
|
||||
{
|
||||
/* First call ever */
|
||||
tv_old->tv_sec = timeofday_tv.tv_sec;
|
||||
tv_old->tv_usec = timeofday_tv.tv_usec;
|
||||
return 0;
|
||||
}
|
||||
v = ((timeofday_tv.tv_sec - tv_old->tv_sec) * 1000) + ((timeofday_tv.tv_usec - tv_old->tv_usec)/1000);
|
||||
if (v >= minimum)
|
||||
{
|
||||
tv_old->tv_sec = timeofday_tv.tv_sec;
|
||||
tv_old->tv_usec = timeofday_tv.tv_usec;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
/* Start events */
|
||||
EventAdd(NULL, "tunefile", save_tunefile, NULL, 300*1000, 0);
|
||||
EventAdd(NULL, "garbage", garbage_collect, NULL, GARBAGE_COLLECT_EVERY*1000, 0);
|
||||
EventAdd(NULL, "loop", loop_event, NULL, 1000, 0);
|
||||
EventAdd(NULL, "unrealdns_removeoldrecords", unrealdns_removeoldrecords, NULL, 15000, 0);
|
||||
EventAdd(NULL, "check_pings", check_pings, NULL, 1000, 0);
|
||||
EventAdd(NULL, "check_deadsockets", check_deadsockets, NULL, 1000, 0);
|
||||
EventAdd(NULL, "handshake_timeout", handshake_timeout, NULL, 1000, 0);
|
||||
EventAdd(NULL, "tls_check_expiry", tls_check_expiry, NULL, (86400/2)*1000, 0);
|
||||
EventAdd(NULL, "unrealdb_expire_secret_cache", unrealdb_expire_secret_cache, NULL, 61000, 0);
|
||||
EventAdd(NULL, "throttling_check_expire", throttling_check_expire, NULL, 1000, 0);
|
||||
}
|
||||
|
||||
/** The main function. This will call SocketLoop() once the server is ready. */
|
||||
@ -710,10 +448,7 @@ int main(int argc, char *argv[])
|
||||
int InitUnrealIRCd(int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WORD wVersionRequested = MAKEWORD(1, 1);
|
||||
WSADATA wsaData;
|
||||
#else
|
||||
#ifndef _WIN32
|
||||
uid_t uid, euid;
|
||||
gid_t gid, egid;
|
||||
#endif
|
||||
@ -755,7 +490,6 @@ int InitUnrealIRCd(int argc, char *argv[])
|
||||
SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
#endif
|
||||
#if !defined(_WIN32) && !defined(_AMIGA)
|
||||
sbrk0 = (char *)sbrk((size_t)0);
|
||||
uid = getuid();
|
||||
euid = geteuid();
|
||||
gid = getgid();
|
||||
@ -784,7 +518,7 @@ int InitUnrealIRCd(int argc, char *argv[])
|
||||
#ifndef _WIN32
|
||||
(void)umask(077); /* better safe than sorry --SRB */
|
||||
#else
|
||||
WSAStartup(wVersionRequested, &wsaData);
|
||||
init_winsock();
|
||||
#endif
|
||||
setup_signals();
|
||||
|
||||
@ -840,43 +574,6 @@ int InitUnrealIRCd(int argc, char *argv[])
|
||||
safe_strdup(configfile, p);
|
||||
convert_to_absolute_path(&configfile, CONFDIR);
|
||||
break;
|
||||
#ifndef _WIN32
|
||||
case 'P':{
|
||||
short type;
|
||||
const char *result;
|
||||
srandom(TStime());
|
||||
type = Auth_FindType(NULL, p);
|
||||
if (type == -1)
|
||||
{
|
||||
type = AUTHTYPE_ARGON2;
|
||||
} else {
|
||||
p = *++argv;
|
||||
argc--;
|
||||
}
|
||||
if (BadPtr(p))
|
||||
{
|
||||
#ifndef _WIN32
|
||||
p = getpass("Enter password to hash: ");
|
||||
#else
|
||||
printf("ERROR: You should specify a password to hash");
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
if ((type == AUTHTYPE_UNIXCRYPT) && (strlen(p) > 8))
|
||||
{
|
||||
/* Hmmm.. is this warning really still true (and always) ?? */
|
||||
printf("WARNING: Password truncated to 8 characters due to 'crypt' algorithm. "
|
||||
"You are suggested to use the 'argon2' algorithm instead.");
|
||||
p[8] = '\0';
|
||||
}
|
||||
if (!(result = Auth_Hash(type, p))) {
|
||||
printf("Failed to generate password. Deprecated method? Try 'argon2' instead.\n");
|
||||
exit(0);
|
||||
}
|
||||
printf("Encrypted password is: %s\n", result);
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
case 'S':
|
||||
charsys_dump_table(p ? p : "*");
|
||||
@ -921,11 +618,6 @@ int InitUnrealIRCd(int argc, char *argv[])
|
||||
}
|
||||
# endif
|
||||
exit(0);
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
case 'k':
|
||||
generate_cloakkeys();
|
||||
exit(0);
|
||||
#endif
|
||||
case 'K':
|
||||
{
|
||||
@ -1032,7 +724,6 @@ int InitUnrealIRCd(int argc, char *argv[])
|
||||
initstats();
|
||||
if (!loop.config_test)
|
||||
DeleteTempModules();
|
||||
booted = FALSE;
|
||||
#if !defined(_WIN32) && !defined(_AMIGA) && !defined(OSXTIGER) && DEFAULT_PERMISSIONS != 0
|
||||
/* Hack to stop people from being able to read the config file */
|
||||
(void)chmod(CPATH, DEFAULT_PERMISSIONS);
|
||||
@ -1056,11 +747,11 @@ int InitUnrealIRCd(int argc, char *argv[])
|
||||
gettimeofday(&timeofday_tv, NULL);
|
||||
timeofday = timeofday_tv.tv_sec;
|
||||
url_socket_timeout(NULL);
|
||||
unrealdns_timeout(NULL);
|
||||
fd_select(500);
|
||||
}
|
||||
if (config_test() < 0)
|
||||
exit(-1);
|
||||
booted = TRUE;
|
||||
load_tunefile();
|
||||
make_umodestr();
|
||||
SetListening(&me);
|
||||
@ -1223,6 +914,9 @@ void SocketLoop(void *dummy)
|
||||
reinit_tls();
|
||||
doreloadcert = 0;
|
||||
}
|
||||
/* If rehashing, check if we are done. */
|
||||
if (loop.rehashing && is_config_read_finished())
|
||||
rehash_internal(loop.rehash_save_client);
|
||||
}
|
||||
}
|
||||
|
||||
|
31
src/ircd_vars.c
Normal file
31
src/ircd_vars.c
Normal file
@ -0,0 +1,31 @@
|
||||
/************************************************************************
|
||||
* UnrealIRCd - Unreal Internet Relay Chat Daemon - src/ircd_vars.c
|
||||
* (c) 2021- Bram Matthys and The UnrealIRCd team
|
||||
* License: GPLv2
|
||||
*/
|
||||
#include "unrealircd.h"
|
||||
|
||||
/** @file
|
||||
* @brief UnrealIRCd global variables of the IRCd
|
||||
*/
|
||||
|
||||
int SVSNOOP = 0;
|
||||
time_t timeofday = 0;
|
||||
struct timeval timeofday_tv;
|
||||
int tainted = 0;
|
||||
LoopStruct loop;
|
||||
MODVAR IRCCounts irccounts;
|
||||
MODVAR Client me; /* That's me */
|
||||
MODVAR char *me_hash;
|
||||
char *configfile = NULL; /* Server configuration file */
|
||||
int debuglevel = 0; /* Server debug level */
|
||||
int bootopt = 0; /* Server boot option flags */
|
||||
char *debugmode = ""; /* -"- -"- -"- */
|
||||
int dorehash = 0; /**< Rehash server on next socket loop */
|
||||
int dorestart = 0; /**< Restart server on next socket loop */
|
||||
int doreloadcert = 0; /**< Reload TLS certificate on next socket loop */
|
||||
#ifndef _WIN32
|
||||
char **myargv;
|
||||
#else
|
||||
LPCSTR cmdLine;
|
||||
#endif
|
@ -44,6 +44,7 @@ MODVAR int numclients = 0;
|
||||
// TODO: Document whether servers are included or excluded in these lists...
|
||||
|
||||
MODVAR struct list_head unknown_list; /**< Local clients in handshake (may become a user or server later) */
|
||||
MODVAR struct list_head control_list; /**< Local "control channel" clients */
|
||||
MODVAR struct list_head lclient_list; /**< Local clients (users only, right?) */
|
||||
MODVAR struct list_head client_list; /**< All clients - local and remote (not in handshake) */
|
||||
MODVAR struct list_head server_list; /**< Locally connected servers */
|
||||
@ -71,6 +72,7 @@ void initlists(void)
|
||||
INIT_LIST_HEAD(&server_list);
|
||||
INIT_LIST_HEAD(&oper_list);
|
||||
INIT_LIST_HEAD(&unknown_list);
|
||||
INIT_LIST_HEAD(&control_list);
|
||||
INIT_LIST_HEAD(&global_server_list);
|
||||
INIT_LIST_HEAD(&dead_list);
|
||||
|
||||
|
241
src/log.c
241
src/log.c
@ -28,7 +28,7 @@
|
||||
#include "unrealircd.h"
|
||||
|
||||
// TODO: Make configurable at compile time (runtime won't do, as we haven't read the config file)
|
||||
#define show_event_id_console 0
|
||||
#define show_event_console 0
|
||||
|
||||
/* Variables */
|
||||
Log *logs[NUM_LOG_DESTINATIONS] = { NULL, NULL, NULL, NULL, NULL };
|
||||
@ -186,7 +186,7 @@ int config_test_log(ConfigFile *conf, ConfigEntry *block)
|
||||
/* TODO: Validate the sources lightly for formatting issues */
|
||||
any_sources = 1;
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (!strcmp(ce->name, "destination"))
|
||||
{
|
||||
for (cep = ce->items; cep; cep = cep->next)
|
||||
@ -225,6 +225,22 @@ int config_test_log(ConfigFile *conf, ConfigEntry *block)
|
||||
cep->file->filename, cep->line_number, cep->value);
|
||||
errors++;
|
||||
}
|
||||
for (cepp = cep->items; cepp; cepp = cepp->next)
|
||||
{
|
||||
if (!strcmp(cepp->name, "color"))
|
||||
;
|
||||
else if (!strcmp(cepp->name, "show-event"))
|
||||
;
|
||||
else if (!strcmp(cepp->name, "json-message-tag"))
|
||||
;
|
||||
else if (!strcmp(cepp->name, "oper-only"))
|
||||
;
|
||||
else
|
||||
{
|
||||
config_error_unknown(cepp->file->filename, cepp->line_number, "log::destination::channel", cepp->name);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (!strcmp(cep->name, "file"))
|
||||
{
|
||||
@ -308,6 +324,10 @@ int config_test_log(ConfigFile *conf, ConfigEntry *block)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
config_error_unknown(ce->file->filename, ce->line_number, "log", ce->name);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -393,6 +413,23 @@ int config_run_log(ConfigFile *conf, ConfigEntry *block)
|
||||
strlcpy(log->destination, cep->value, sizeof(log->destination)); /* destination is the channel */
|
||||
log->sources = sources;
|
||||
AddListItem(log, temp_logs[LOG_DEST_CHANNEL]);
|
||||
/* set defaults */
|
||||
log->color = tempiConf.server_notice_colors;
|
||||
log->show_event = tempiConf.server_notice_show_event;
|
||||
log->json_message_tag = 1;
|
||||
log->oper_only = 1;
|
||||
/* now parse options (if any) */
|
||||
for (cepp = cep->items; cepp; cepp = cepp->next)
|
||||
{
|
||||
if (!strcmp(cepp->name, "color"))
|
||||
log->color = config_checkval(cepp->value, CFG_YESNO);
|
||||
else if (!strcmp(cepp->name, "show-event"))
|
||||
log->show_event = config_checkval(cepp->value, CFG_YESNO);
|
||||
else if (!strcmp(cepp->name, "json-message-tag"))
|
||||
log->json_message_tag = config_checkval(cepp->value, CFG_YESNO);
|
||||
else if (!strcmp(cepp->name, "oper-only"))
|
||||
log->oper_only = config_checkval(cepp->value, CFG_YESNO);
|
||||
}
|
||||
} else
|
||||
if (!strcmp(cep->name, "remote"))
|
||||
{
|
||||
@ -499,6 +536,10 @@ void json_expand_client(json_t *j, const char *key, Client *client, int detail)
|
||||
|
||||
/* same for ip, is there for all (well, some services pseudo-users may not have one) */
|
||||
json_object_set_new(child, "ip", json_string_unreal(client->ip));
|
||||
if (client->local && client->local->listener)
|
||||
json_object_set_new(child, "server_port", json_integer(client->local->listener->port));
|
||||
if (client->local && client->local->port)
|
||||
json_object_set_new(child, "client_port", json_integer(client->local->port));
|
||||
|
||||
/* client.details is always available: it is nick!user@host, nick@host, server@host
|
||||
* server@ip, or just server.
|
||||
@ -963,7 +1004,6 @@ static NameValue log_colors_terminal[] = {
|
||||
{ ULOG_ERROR, "\033[91m" },
|
||||
{ ULOG_FATAL, "\033[95m" },
|
||||
};
|
||||
#define TERMINAL_COLOR_RESET "\033[0m"
|
||||
|
||||
const char *log_level_irc_color(LogLevel loglevel)
|
||||
{
|
||||
@ -1151,7 +1191,7 @@ literal:
|
||||
}
|
||||
|
||||
/** Do the actual writing to log files */
|
||||
void do_unreal_log_disk(LogLevel loglevel, const char *subsystem, const char *event_id, MultiLine *msg, const char *json_serialized)
|
||||
void do_unreal_log_disk(LogLevel loglevel, const char *subsystem, const char *event_id, MultiLine *msg, const char *json_serialized, Client *from_server)
|
||||
{
|
||||
static int last_log_file_warning = 0;
|
||||
Log *l;
|
||||
@ -1171,14 +1211,14 @@ void do_unreal_log_disk(LogLevel loglevel, const char *subsystem, const char *ev
|
||||
for (m = msg; m; m = m->next)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (show_event_id_console)
|
||||
if (show_event_console)
|
||||
win_log("* %s.%s%s [%s] %s\n", subsystem, event_id, m->next?"+":"", log_level_valtostring(loglevel), m->line);
|
||||
else
|
||||
win_log("* [%s] %s\n", log_level_valtostring(loglevel), m->line);
|
||||
#else
|
||||
if (terminal_supports_color())
|
||||
{
|
||||
if (show_event_id_console)
|
||||
if (show_event_console)
|
||||
{
|
||||
fprintf(stderr, "%s%s.%s%s %s[%s]%s %s\n",
|
||||
log_level_terminal_color(ULOG_INVALID), subsystem, event_id, TERMINAL_COLOR_RESET,
|
||||
@ -1190,7 +1230,7 @@ void do_unreal_log_disk(LogLevel loglevel, const char *subsystem, const char *ev
|
||||
m->line);
|
||||
}
|
||||
} else {
|
||||
if (show_event_id_console)
|
||||
if (show_event_console)
|
||||
fprintf(stderr, "%s.%s%s [%s] %s\n", subsystem, event_id, m->next?"+":"", log_level_valtostring(loglevel), m->line);
|
||||
else
|
||||
fprintf(stderr, "[%s] %s\n", log_level_valtostring(loglevel), m->line);
|
||||
@ -1303,13 +1343,9 @@ void do_unreal_log_disk(LogLevel loglevel, const char *subsystem, const char *ev
|
||||
for (m = msg; m; m = m->next)
|
||||
{
|
||||
char text_buf[8192];
|
||||
snprintf(text_buf, sizeof(text_buf), "%s.%s%s %s: %s\n", subsystem, event_id, m->next?"+":"", log_level_valtostring(loglevel), m->line);
|
||||
// FIXME: don't write in 2 stages, waste of slow system calls
|
||||
if (write(l->logfd, timebuf, strlen(timebuf)) < 0)
|
||||
{
|
||||
/* Let's ignore any write errors for this one. Next write() will catch it... */
|
||||
;
|
||||
}
|
||||
snprintf(text_buf, sizeof(text_buf), "%s%s %s.%s%s %s: %s\n",
|
||||
timebuf, from_server->name,
|
||||
subsystem, event_id, m->next?"+":"", log_level_valtostring(loglevel), m->line);
|
||||
n = write(l->logfd, text_buf, strlen(text_buf));
|
||||
if (n < strlen(text_buf))
|
||||
{
|
||||
@ -1423,13 +1459,66 @@ const char *log_to_snomask(LogLevel loglevel, const char *subsystem, const char
|
||||
|
||||
#define COLOR_NONE "\xf"
|
||||
#define COLOR_DARKGREY "\00314"
|
||||
/** Do the actual writing to log files */
|
||||
|
||||
/** Generic sendto function for logging to IRC. Used for notices to IRCOps and also for sending to individual users on channels */
|
||||
void sendto_log(Client *client, const char *msgtype, const char *destination, int show_colors, int show_event,
|
||||
LogLevel loglevel, const char *subsystem, const char *event_id, MultiLine *msg, const char *json_serialized, Client *from_server)
|
||||
{
|
||||
MultiLine *m;
|
||||
|
||||
for (m = msg; m; m = m->next)
|
||||
{
|
||||
MessageTag *mtags = NULL;
|
||||
new_message(from_server, NULL, &mtags);
|
||||
|
||||
/* Add JSON data, but only if it is the first message (m == msg) */
|
||||
if (json_serialized && (m == msg))
|
||||
{
|
||||
MessageTag *json_mtag = safe_alloc(sizeof(MessageTag));
|
||||
safe_strdup(json_mtag->name, "unrealircd.org/json-log");
|
||||
safe_strdup(json_mtag->value, json_serialized);
|
||||
AddListItem(json_mtag, mtags);
|
||||
}
|
||||
|
||||
if (show_colors)
|
||||
{
|
||||
if (show_event)
|
||||
{
|
||||
sendto_one(client, mtags, ":%s %s %s :%s%s.%s%s%s %s[%s]%s %s",
|
||||
from_server->name, msgtype, destination,
|
||||
COLOR_DARKGREY, subsystem, event_id, m->next?"+":"", COLOR_NONE,
|
||||
log_level_irc_color(loglevel), log_level_valtostring(loglevel), COLOR_NONE,
|
||||
m->line);
|
||||
} else {
|
||||
sendto_one(client, mtags, ":%s %s %s :%s[%s]%s %s",
|
||||
from_server->name, msgtype, destination,
|
||||
log_level_irc_color(loglevel), log_level_valtostring(loglevel), COLOR_NONE,
|
||||
m->line);
|
||||
}
|
||||
} else {
|
||||
if (show_event)
|
||||
{
|
||||
sendto_one(client, mtags, ":%s %s %s :%s.%s%s [%s] %s",
|
||||
from_server->name, msgtype, destination,
|
||||
subsystem, event_id, m->next?"+":"",
|
||||
log_level_valtostring(loglevel),
|
||||
m->line);
|
||||
} else {
|
||||
sendto_one(client, mtags, ":%s %s %s :[%s] %s",
|
||||
from_server->name, msgtype, destination,
|
||||
log_level_valtostring(loglevel),
|
||||
m->line);
|
||||
}
|
||||
}
|
||||
safe_free_message_tags(mtags);
|
||||
}
|
||||
}
|
||||
|
||||
/** Send server notices to IRCOps */
|
||||
void do_unreal_log_opers(LogLevel loglevel, const char *subsystem, const char *event_id, MultiLine *msg, const char *json_serialized, Client *from_server)
|
||||
{
|
||||
Client *client;
|
||||
const char *snomask_destinations, *p;
|
||||
MessageTag *mtags = NULL, *mtags_loop;
|
||||
MultiLine *m;
|
||||
|
||||
/* If not fully booted then we don't have a logging to snomask mapping so can't do much.. */
|
||||
if (!loop.booted)
|
||||
@ -1443,20 +1532,13 @@ void do_unreal_log_opers(LogLevel loglevel, const char *subsystem, const char *e
|
||||
if (!snomask_destinations)
|
||||
return;
|
||||
|
||||
/* Prepare message tag for those who have CAP unrealircd.org/json-log */
|
||||
if (json_serialized)
|
||||
{
|
||||
mtags = safe_alloc(sizeof(MessageTag));
|
||||
safe_strdup(mtags->name, "unrealircd.org/json-log");
|
||||
safe_strdup(mtags->value, json_serialized);
|
||||
}
|
||||
|
||||
/* To specific snomasks... */
|
||||
list_for_each_entry(client, &oper_list, special_node)
|
||||
{
|
||||
const char *operlogin;
|
||||
ConfigItem_oper *oper;
|
||||
int colors = iConf.server_notice_colors;
|
||||
int show_colors = iConf.server_notice_colors;
|
||||
int show_event = iConf.server_notice_show_event;
|
||||
|
||||
if (snomask_destinations)
|
||||
{
|
||||
@ -1477,30 +1559,56 @@ void do_unreal_log_opers(LogLevel loglevel, const char *subsystem, const char *e
|
||||
|
||||
operlogin = get_operlogin(client);
|
||||
if (operlogin && (oper = find_oper(operlogin)))
|
||||
colors = oper->server_notice_colors;
|
||||
|
||||
mtags_loop = mtags;
|
||||
for (m = msg; m; m = m->next)
|
||||
{
|
||||
if (colors)
|
||||
{
|
||||
sendto_one(client, mtags_loop, ":%s NOTICE %s :%s%s.%s%s%s %s[%s]%s %s",
|
||||
from_server->name, client->name,
|
||||
COLOR_DARKGREY, subsystem, event_id, m->next?"+":"", COLOR_NONE,
|
||||
log_level_irc_color(loglevel), log_level_valtostring(loglevel), COLOR_NONE,
|
||||
m->line);
|
||||
} else {
|
||||
sendto_one(client, mtags_loop, ":%s NOTICE %s :%s.%s%s [%s] %s",
|
||||
from_server->name, client->name,
|
||||
subsystem, event_id, m->next?"+":"",
|
||||
log_level_valtostring(loglevel),
|
||||
m->line);
|
||||
}
|
||||
mtags_loop = NULL; /* this way we only send the JSON in the first msg */
|
||||
show_colors = oper->server_notice_colors;
|
||||
show_event = oper->server_notice_show_event;
|
||||
}
|
||||
|
||||
sendto_log(client, "NOTICE", client->name, show_colors, show_event, loglevel, subsystem, event_id, msg, json_serialized, from_server);
|
||||
}
|
||||
}
|
||||
|
||||
/** Send server notices to channels */
|
||||
void do_unreal_log_channels(LogLevel loglevel, const char *subsystem, const char *event_id, MultiLine *msg, const char *json_serialized, Client *from_server)
|
||||
{
|
||||
Log *l;
|
||||
Member *m;
|
||||
Client *client;
|
||||
|
||||
/* If not fully booted then we don't have a logging to snomask mapping so can't do much.. */
|
||||
if (!loop.booted)
|
||||
return;
|
||||
|
||||
/* Never send these */
|
||||
if (!strcmp(subsystem, "rawtraffic"))
|
||||
return;
|
||||
|
||||
for (l = logs[LOG_DEST_CHANNEL]; l; l = l->next)
|
||||
{
|
||||
const char *operlogin;
|
||||
ConfigItem_oper *oper;
|
||||
Channel *channel;
|
||||
|
||||
if (!log_sources_match(l->sources, loglevel, subsystem, event_id, 0))
|
||||
continue;
|
||||
|
||||
channel = find_channel(l->destination);
|
||||
if (!channel)
|
||||
continue;
|
||||
|
||||
for (m = channel->members; m; m = m->next)
|
||||
{
|
||||
Client *client = m->client;
|
||||
if (!MyUser(client))
|
||||
continue;
|
||||
if (l->oper_only && !IsOper(client))
|
||||
continue;
|
||||
sendto_log(client, "PRIVMSG", channel->name, l->color, l->show_event,
|
||||
loglevel, subsystem, event_id, msg,
|
||||
l->json_message_tag ? json_serialized : NULL,
|
||||
from_server);
|
||||
}
|
||||
}
|
||||
|
||||
safe_free_message_tags(mtags);
|
||||
}
|
||||
|
||||
void do_unreal_log_remote(LogLevel loglevel, const char *subsystem, const char *event_id, MultiLine *msg, const char *json_serialized)
|
||||
@ -1522,6 +1630,25 @@ void do_unreal_log_remote(LogLevel loglevel, const char *subsystem, const char *
|
||||
do_unreal_log_remote_deliver(loglevel, subsystem, event_id, msg, json_serialized);
|
||||
}
|
||||
|
||||
/** Send server notices to control channel */
|
||||
void do_unreal_log_control(LogLevel loglevel, const char *subsystem, const char *event_id, MultiLine *msg, const char *json_serialized, Client *from_server)
|
||||
{
|
||||
Client *client;
|
||||
MultiLine *m;
|
||||
|
||||
if (!loop.booted)
|
||||
return;
|
||||
|
||||
/* Never send these */
|
||||
if (!strcmp(subsystem, "rawtraffic"))
|
||||
return;
|
||||
|
||||
list_for_each_entry(client, &control_list, lclient_node)
|
||||
if (IsMonitorRehash(client))
|
||||
for (m = msg; m; m = m->next)
|
||||
sendto_one(client, NULL, "REPLY [%s] %s", log_level_valtostring(loglevel), m->line);
|
||||
}
|
||||
|
||||
void do_unreal_log_free_args(va_list vl)
|
||||
{
|
||||
LogData *d;
|
||||
@ -1693,17 +1820,24 @@ void do_unreal_log_internal(LogLevel loglevel, const char *subsystem, const char
|
||||
/* Convert the message buffer to MultiLine */
|
||||
mmsg = line2multiline(msgbuf);
|
||||
|
||||
/* Now call the disk loggers */
|
||||
do_unreal_log_disk(loglevel, subsystem, event_id, mmsg, json_serialized);
|
||||
|
||||
/* And the ircops stuff */
|
||||
/* Parse the "from server" info, if any */
|
||||
t = json_object_get(j_details, "from_server_name");
|
||||
if (t && (str = json_get_value(t)))
|
||||
from_server = find_server(str, NULL);
|
||||
if (from_server == NULL)
|
||||
from_server = &me;
|
||||
|
||||
/* Now call all the loggers: */
|
||||
|
||||
do_unreal_log_disk(loglevel, subsystem, event_id, mmsg, json_serialized, from_server);
|
||||
|
||||
if ((loop.rehashing == 2) || !strcmp(subsystem, "config"))
|
||||
do_unreal_log_control(loglevel, subsystem, event_id, mmsg, json_serialized, from_server);
|
||||
|
||||
do_unreal_log_opers(loglevel, subsystem, event_id, mmsg, json_serialized, from_server);
|
||||
|
||||
do_unreal_log_channels(loglevel, subsystem, event_id, mmsg, json_serialized, from_server);
|
||||
|
||||
do_unreal_log_remote(loglevel, subsystem, event_id, mmsg, json_serialized);
|
||||
|
||||
// NOTE: code duplication further down!
|
||||
@ -1723,10 +1857,11 @@ void do_unreal_log_internal_from_remote(LogLevel loglevel, const char *subsystem
|
||||
unreal_log_recursion_trap = 1;
|
||||
|
||||
/* Call the disk loggers */
|
||||
do_unreal_log_disk(loglevel, subsystem, event_id, msg, json_serialized);
|
||||
do_unreal_log_disk(loglevel, subsystem, event_id, msg, json_serialized, from_server);
|
||||
|
||||
/* And the ircops stuff */
|
||||
/* And to IRC */
|
||||
do_unreal_log_opers(loglevel, subsystem, event_id, msg, json_serialized, from_server);
|
||||
do_unreal_log_channels(loglevel, subsystem, event_id, msg, json_serialized, from_server);
|
||||
|
||||
unreal_log_recursion_trap = 0;
|
||||
}
|
||||
|
174
src/misc.c
174
src/misc.c
@ -623,8 +623,8 @@ void exit_client_ex(Client *client, Client *origin, MessageTag *recv_mtags, cons
|
||||
|
||||
if (client->local->fd >= 0 && !IsConnecting(client))
|
||||
{
|
||||
sendto_one(client, NULL, "ERROR :Closing Link: %s (%s)",
|
||||
get_client_name(client, FALSE), comment);
|
||||
if (!IsControl(client))
|
||||
sendto_one(client, NULL, "ERROR :Closing Link: %s (%s)", get_client_name(client, FALSE), comment);
|
||||
}
|
||||
close_connection(client);
|
||||
}
|
||||
@ -2369,3 +2369,173 @@ void addlettertodynamicstringsorted(char **str, char letter)
|
||||
safe_free_raw(*str);
|
||||
*str = newbuf;
|
||||
}
|
||||
|
||||
void s_die()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
Client *client;
|
||||
if (!IsService)
|
||||
{
|
||||
loop.terminating = 1;
|
||||
unload_all_modules();
|
||||
|
||||
list_for_each_entry(client, &lclient_list, lclient_node)
|
||||
(void) send_queued(client);
|
||||
|
||||
exit(-1);
|
||||
}
|
||||
else {
|
||||
SERVICE_STATUS status;
|
||||
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||||
SC_HANDLE hService = OpenService(hSCManager, "UnrealIRCd", SERVICE_STOP);
|
||||
ControlService(hService, SERVICE_CONTROL_STOP, &status);
|
||||
}
|
||||
#else
|
||||
loop.terminating = 1;
|
||||
unload_all_modules();
|
||||
unlink(conf_files ? conf_files->pid_file : IRCD_PIDFILE);
|
||||
exit(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
void s_rehash()
|
||||
{
|
||||
struct sigaction act;
|
||||
dorehash = 1;
|
||||
act.sa_handler = s_rehash;
|
||||
act.sa_flags = 0;
|
||||
(void)sigemptyset(&act.sa_mask);
|
||||
(void)sigaddset(&act.sa_mask, SIGHUP);
|
||||
(void)sigaction(SIGHUP, &act, NULL);
|
||||
}
|
||||
|
||||
void s_reloadcert()
|
||||
{
|
||||
struct sigaction act;
|
||||
doreloadcert = 1;
|
||||
act.sa_handler = s_reloadcert;
|
||||
act.sa_flags = 0;
|
||||
(void)sigemptyset(&act.sa_mask);
|
||||
(void)sigaddset(&act.sa_mask, SIGUSR1);
|
||||
(void)sigaction(SIGUSR1, &act, NULL);
|
||||
}
|
||||
#endif // #ifndef _WIN32
|
||||
|
||||
void restart(const char *mesg)
|
||||
{
|
||||
server_reboot(mesg);
|
||||
}
|
||||
|
||||
void s_restart()
|
||||
{
|
||||
dorestart = 1;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
/** Signal handler for signals which we ignore,
|
||||
* like SIGPIPE ("Broken pipe") and SIGWINCH (terminal window changed) etc.
|
||||
*/
|
||||
void ignore_this_signal()
|
||||
{
|
||||
struct sigaction act;
|
||||
|
||||
act.sa_handler = ignore_this_signal;
|
||||
act.sa_flags = 0;
|
||||
(void)sigemptyset(&act.sa_mask);
|
||||
(void)sigaddset(&act.sa_mask, SIGALRM);
|
||||
(void)sigaddset(&act.sa_mask, SIGPIPE);
|
||||
(void)sigaction(SIGALRM, &act, (struct sigaction *)NULL);
|
||||
(void)sigaction(SIGPIPE, &act, (struct sigaction *)NULL);
|
||||
#ifdef SIGWINCH
|
||||
(void)sigaddset(&act.sa_mask, SIGWINCH);
|
||||
(void)sigaction(SIGWINCH, &act, (struct sigaction *)NULL);
|
||||
#endif
|
||||
}
|
||||
#endif /* #ifndef _WIN32 */
|
||||
|
||||
|
||||
void server_reboot(const char *mesg)
|
||||
{
|
||||
int i;
|
||||
Client *client;
|
||||
unreal_log(ULOG_INFO, "main", "UNREALIRCD_RESTARTING", NULL,
|
||||
"Restarting server: $reason",
|
||||
log_data_string("reason", mesg));
|
||||
|
||||
list_for_each_entry(client, &lclient_list, lclient_node)
|
||||
(void) send_queued(client);
|
||||
|
||||
/*
|
||||
* ** fd 0 must be 'preserved' if either the -d or -i options have
|
||||
* ** been passed to us before restarting.
|
||||
*/
|
||||
#ifdef HAVE_SYSLOG
|
||||
(void)closelog();
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
for (i = 3; i < MAXCONNECTIONS; i++)
|
||||
(void)close(i);
|
||||
if (!(bootopt & (BOOT_TTY | BOOT_DEBUG)))
|
||||
(void)close(2);
|
||||
(void)close(1);
|
||||
(void)close(0);
|
||||
close_std_descriptors();
|
||||
(void)execv(MYNAME, myargv);
|
||||
#else
|
||||
close_connections();
|
||||
if (!IsService)
|
||||
{
|
||||
CleanUp();
|
||||
WinExec(cmdLine, SW_SHOWDEFAULT);
|
||||
}
|
||||
#endif
|
||||
unload_all_modules();
|
||||
#ifdef _WIN32
|
||||
if (IsService)
|
||||
{
|
||||
SERVICE_STATUS status;
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFO si;
|
||||
char fname[MAX_PATH];
|
||||
memset(&status, 0, sizeof(status));
|
||||
memset(&si, 0, sizeof(si));
|
||||
IRCDStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
||||
SetServiceStatus(IRCDStatusHandle, &IRCDStatus);
|
||||
GetModuleFileName(GetModuleHandle(NULL), fname, MAX_PATH);
|
||||
CreateProcess(fname, "restartsvc", NULL, NULL, FALSE,
|
||||
0, NULL, NULL, &si, &pi);
|
||||
IRCDStatus.dwCurrentState = SERVICE_STOPPED;
|
||||
SetServiceStatus(IRCDStatusHandle, &IRCDStatus);
|
||||
ExitProcess(0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/** Check if at least 'minimum' seconds passed by since last run.
|
||||
* @param tv_old Pointer to a timeval struct to keep track of things.
|
||||
* @param minimum The time specified in milliseconds (eg: 1000 for 1 second)
|
||||
* @returns When 'minimum' msec passed 1 is returned and the time is reset, otherwise 0 is returned.
|
||||
*/
|
||||
int minimum_msec_since_last_run(struct timeval *tv_old, long minimum)
|
||||
{
|
||||
long v;
|
||||
|
||||
if (tv_old->tv_sec == 0)
|
||||
{
|
||||
/* First call ever */
|
||||
tv_old->tv_sec = timeofday_tv.tv_sec;
|
||||
tv_old->tv_usec = timeofday_tv.tv_usec;
|
||||
return 0;
|
||||
}
|
||||
v = ((timeofday_tv.tv_sec - tv_old->tv_sec) * 1000) + ((timeofday_tv.tv_usec - tv_old->tv_usec)/1000);
|
||||
if (v >= minimum)
|
||||
{
|
||||
tv_old->tv_sec = timeofday_tv.tv_sec;
|
||||
tv_old->tv_usec = timeofday_tv.tv_usec;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -99,6 +99,7 @@ void blacklist_free_conf(void);
|
||||
void delete_blacklist_block(Blacklist *e);
|
||||
void blacklist_md_free(ModData *md);
|
||||
int blacklist_handshake(Client *client);
|
||||
int blacklist_ip_change(Client *client, const char *oldip);
|
||||
int blacklist_quit(Client *client, MessageTag *mtags, const char *comment);
|
||||
int blacklist_preconnect(Client *client);
|
||||
void blacklist_resolver_callback(void *arg, int status, int timeouts, struct hostent *he);
|
||||
@ -146,6 +147,7 @@ MOD_INIT()
|
||||
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, blacklist_config_run);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_HANDSHAKE, 0, blacklist_handshake);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_IP_CHANGE, 0, blacklist_ip_change);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_PRE_LOCAL_CONNECT, 0, blacklist_preconnect);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_REHASH, 0, blacklist_rehash);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_REHASH_COMPLETE, 0, blacklist_rehash_complete);
|
||||
@ -553,6 +555,12 @@ int blacklist_handshake(Client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blacklist_ip_change(Client *client, const char *oldip)
|
||||
{
|
||||
blacklist_start_check(client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blacklist_start_check(Client *client)
|
||||
{
|
||||
Blacklist *bl;
|
||||
|
@ -73,9 +73,9 @@ int cmode_halfop_is_ok(Client *client, Channel *channel, char mode, const char *
|
||||
/* User may always remove their own modes */
|
||||
return EX_ALLOW;
|
||||
}
|
||||
if ((what == MODE_ADD) && check_channel_access(client, channel, "hoaq"))
|
||||
if (check_channel_access(client, channel, "oaq"))
|
||||
{
|
||||
/* Permitted for +hoaq */
|
||||
/* Permitted for +oaq */
|
||||
return EX_ALLOW;
|
||||
}
|
||||
if (type == EXCHK_ACCESS_ERR)
|
||||
|
@ -384,10 +384,24 @@ int read_listmode(UnrealDB *db, Ban **lst)
|
||||
|
||||
for (i = 0; i < total; i++)
|
||||
{
|
||||
const char *str;
|
||||
e = safe_alloc(sizeof(Ban));
|
||||
R_SAFE(unrealdb_read_str(db, &e->banstr));
|
||||
R_SAFE(unrealdb_read_str(db, &e->who));
|
||||
R_SAFE(unrealdb_read_int64(db, &when));
|
||||
str = clean_ban_mask(e->banstr, MODE_ADD, &me, 0);
|
||||
if (str == NULL)
|
||||
{
|
||||
/* Skip this item */
|
||||
config_warn("[channeldb] listmode skipped (no longer valid?): %s", e->banstr);
|
||||
safe_free(e->banstr);
|
||||
safe_free(e->who);
|
||||
safe_free(e);
|
||||
continue;
|
||||
}
|
||||
safe_strdup(e->banstr, str);
|
||||
|
||||
/* Add to list */
|
||||
e->when = when;
|
||||
e->next = *lst;
|
||||
*lst = e;
|
||||
|
@ -219,7 +219,7 @@ void _userhost_changed(Client *client)
|
||||
}
|
||||
}
|
||||
|
||||
RunHook(HOOKTYPE_USERHOST_CHANGED, client, remember_user, remember_host);
|
||||
RunHook(HOOKTYPE_USERHOST_CHANGE, client, remember_user, remember_host);
|
||||
|
||||
if (MyUser(client))
|
||||
{
|
||||
|
@ -25,7 +25,7 @@
|
||||
ModuleHeader MOD_HEADER
|
||||
= {
|
||||
"dccdeny",
|
||||
"5.0",
|
||||
"6.0.2",
|
||||
"command /dccdeny",
|
||||
"UnrealIRCd Team",
|
||||
"unrealircd-6",
|
||||
@ -525,11 +525,8 @@ int dccdeny_can_send_to_channel(Client *client, Channel *channel, Membership *lp
|
||||
const char *filename = get_dcc_filename(*msg);
|
||||
if (filename && !can_dcc(client, channel->name, NULL, filename, &err))
|
||||
{
|
||||
if (!IsDead(client) && (sendtype != SEND_TYPE_NOTICE))
|
||||
{
|
||||
strlcpy(errbuf, err, sizeof(errbuf));
|
||||
*errmsg = errbuf;
|
||||
}
|
||||
strlcpy(errbuf, err, sizeof(errbuf));
|
||||
*errmsg = errbuf;
|
||||
return HOOK_DENY;
|
||||
}
|
||||
}
|
||||
@ -649,7 +646,11 @@ static int can_dcc(Client *client, const char *target, Client *targetcli, const
|
||||
}
|
||||
|
||||
if (match_spamfilter(client, filename, SPAMF_DCC, "PRIVMSG", target, 0, NULL))
|
||||
{
|
||||
/* Dirty hack, yeah spamfilter already sent the error message :( */
|
||||
*errmsg = "";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((fl = dcc_isforbidden(client, filename)))
|
||||
{
|
||||
|
@ -43,7 +43,7 @@ MOD_INIT()
|
||||
req.conv_param = extban_realname_conv_param;
|
||||
req.is_banned = extban_realname_is_banned;
|
||||
req.is_banned_events = BANCHK_ALL|BANCHK_TKL;
|
||||
req.options = EXTBOPT_CHSVSMODE|EXTBOPT_INVEX|EXTBOPT_TKL;
|
||||
req.options = EXTBOPT_INVEX|EXTBOPT_TKL;
|
||||
if (!ExtbanAdd(modinfo->handle, req))
|
||||
{
|
||||
config_error("could not register extended ban type");
|
||||
|
@ -78,7 +78,6 @@ MOD_INIT()
|
||||
extban.letter = 't';
|
||||
extban.name = "time";
|
||||
extban.options |= EXTBOPT_ACTMODIFIER; /* not really, but ours shouldn't be stacked from group 1 */
|
||||
extban.options |= EXTBOPT_CHSVSMODE; /* so "SVSMODE -nick" will unset affected ~t extbans */
|
||||
extban.options |= EXTBOPT_INVEX; /* also permit timed invite-only exceptions (+I) */
|
||||
extban.conv_param = timedban_extban_conv_param;
|
||||
extban.is_ok = timedban_extban_is_ok;
|
||||
|
@ -26,8 +26,8 @@ long CAP_EXTENDED_MONITOR = 0L;
|
||||
|
||||
int extended_monitor_away(Client *client, MessageTag *mtags, const char *reason, int already_as_away);
|
||||
int extended_monitor_account_login(Client *client, MessageTag *mtags);
|
||||
int extended_monitor_userhost_changed(Client *client, const char *olduser, const char *oldhost);
|
||||
int extended_monitor_realname_changed(Client *client, const char *oldinfo);
|
||||
int extended_monitor_userhost_change(Client *client, const char *olduser, const char *oldhost);
|
||||
int extended_monitor_realname_change(Client *client, const char *oldinfo);
|
||||
int extended_monitor_notification(Client *client, Watch *watch, Link *lp, int event);
|
||||
|
||||
ModuleHeader MOD_HEADER
|
||||
@ -59,8 +59,8 @@ MOD_INIT()
|
||||
|
||||
HookAdd(modinfo->handle, HOOKTYPE_AWAY, 0, extended_monitor_away);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_ACCOUNT_LOGIN, 0, extended_monitor_account_login);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_USERHOST_CHANGED, 0, extended_monitor_userhost_changed);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_REALNAME_CHANGED, 0, extended_monitor_realname_changed);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_USERHOST_CHANGE, 0, extended_monitor_userhost_change);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_REALNAME_CHANGE, 0, extended_monitor_realname_change);
|
||||
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
@ -95,13 +95,13 @@ int extended_monitor_account_login(Client *client, MessageTag *mtags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int extended_monitor_userhost_changed(Client *client, const char *olduser, const char *oldhost)
|
||||
int extended_monitor_userhost_change(Client *client, const char *olduser, const char *oldhost)
|
||||
{
|
||||
watch_check(client, WATCH_EVENT_USERHOST, extended_monitor_notification);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int extended_monitor_realname_changed(Client *client, const char *oldinfo)
|
||||
int extended_monitor_realname_change(Client *client, const char *oldinfo)
|
||||
{
|
||||
watch_check(client, WATCH_EVENT_REALNAME, extended_monitor_notification);
|
||||
return 0;
|
||||
|
@ -25,6 +25,7 @@ void geoip_base_free(ModData *m);
|
||||
const char *geoip_base_serialize(ModData *m);
|
||||
void geoip_base_unserialize(const char *str, ModData *m);
|
||||
int geoip_base_handshake(Client *client);
|
||||
int geoip_base_ip_change(Client *client, const char *oldip);
|
||||
int geoip_base_whois(Client *client, Client *target, NameValuePrioList **list);
|
||||
int geoip_connect_extinfo(Client *client, NameValuePrioList **list);
|
||||
int geoip_base_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs);
|
||||
@ -119,10 +120,10 @@ MOD_INIT()
|
||||
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, geoip_base_configrun);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_HANDSHAKE, 0, geoip_base_handshake);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_IP_CHANGE, 0, geoip_base_ip_change);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_SERVER_HANDSHAKE_OUT, 0, geoip_base_handshake);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONNECT_EXTINFO, 1, geoip_connect_extinfo); /* (prio: near-first) */
|
||||
HookAdd(modinfo->handle, HOOKTYPE_PRE_LOCAL_CONNECT, 0,geoip_base_handshake); /* in case the IP changed in registration phase (WEBIRC, HTTP Forwarded) */
|
||||
HookAdd(modinfo->handle, HOOKTYPE_REMOTE_CONNECT, 0, geoip_base_handshake); /* remote user */
|
||||
HookAdd(modinfo->handle, HOOKTYPE_WHOIS, 0, geoip_base_whois);
|
||||
|
||||
CommandAdd(modinfo->handle, "GEOIP", cmd_geoip, MAXPARA, CMD_USER);
|
||||
@ -167,6 +168,12 @@ int geoip_base_handshake(Client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int geoip_base_ip_change(Client *client, const char *oldip)
|
||||
{
|
||||
geoip_base_handshake(client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void geoip_base_free(ModData *m)
|
||||
{
|
||||
if (m->ptr)
|
||||
@ -229,12 +236,13 @@ void geoip_base_unserialize(const char *str, ModData *m)
|
||||
m->ptr = res;
|
||||
}
|
||||
|
||||
EVENT(geoip_base_set_existing_users_evt){
|
||||
EVENT(geoip_base_set_existing_users_evt)
|
||||
{
|
||||
Client *client;
|
||||
list_for_each_entry(client, &client_list, client_node){
|
||||
if (!IsUser(client))
|
||||
continue;
|
||||
geoip_base_handshake(client);
|
||||
list_for_each_entry(client, &client_list, client_node)
|
||||
{
|
||||
if (MyUser(client))
|
||||
geoip_base_handshake(client);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,22 @@ static ModuleInfo *MyModInfo;
|
||||
#define MyMod MyModInfo->handle
|
||||
#define SAVE_MODINFO MyModInfo = modinfo;
|
||||
|
||||
static int lmax = 0;
|
||||
static int umax = 0;
|
||||
|
||||
static int dcount(int n)
|
||||
{
|
||||
int cnt = 0;
|
||||
|
||||
while (n != 0)
|
||||
{
|
||||
n = n/10;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
ModuleHeader MOD_HEADER
|
||||
= {
|
||||
"hideserver",
|
||||
@ -230,8 +246,24 @@ static void dump_map(Client *client, Client *server, char *mask, int prompt_leng
|
||||
sendnumeric(client, RPL_MAPMORE, prompt, length, server->name);
|
||||
else
|
||||
{
|
||||
sendnumeric(client, RPL_MAP, prompt,
|
||||
length, server->name, server->server->users, IsOper(client) ? server->id : "");
|
||||
char tbuf[256];
|
||||
char sid[10];
|
||||
int len = length - strlen(server->name) + 1;
|
||||
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
if (len > 255)
|
||||
len = 255;
|
||||
|
||||
tbuf[len--] = '\0';
|
||||
while (len >= 0)
|
||||
tbuf[len--] = '-';
|
||||
if (IsOper(client))
|
||||
snprintf(sid, sizeof(sid), " [%s]", server->id);
|
||||
sendnumeric(client, RPL_MAP, prompt, server->name, tbuf, umax,
|
||||
server->server->users, (double)(lmax < 10) ? 4 : (lmax == 100) ? 6 : 5,
|
||||
(server->server->users * 100.0 / irccounts.clients),
|
||||
IsOper(client) ? sid : "");
|
||||
cnt = 0;
|
||||
}
|
||||
|
||||
@ -279,12 +311,25 @@ static void dump_map(Client *client, Client *server, char *mask, int prompt_leng
|
||||
void dump_flat_map(Client *client, Client *server, int length)
|
||||
{
|
||||
char buf[4];
|
||||
char tbuf[256];
|
||||
Client *acptr;
|
||||
int cnt = 0, hide_ulines;
|
||||
int cnt = 0, len = 0, hide_ulines;
|
||||
|
||||
hide_ulines = (HIDE_ULINES && !ValidatePermissionsForPath("server:info:map:ulines",client,NULL,NULL,NULL)) ? 1 : 0;
|
||||
|
||||
sendnumeric(client, RPL_MAP, "", length, server->name, server->server->users, "");
|
||||
len = length - strlen(server->name) + 3;
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
if (len > 255)
|
||||
len = 255;
|
||||
|
||||
tbuf[len--] = '\0';
|
||||
while (len >= 0)
|
||||
tbuf[len--] = '-';
|
||||
|
||||
sendnumeric(client, RPL_MAP, "", server->name, tbuf, umax, server->server->users,
|
||||
(lmax < 10) ? 4 : (lmax == 100) ? 6 : 5,
|
||||
(server->server->users * 100.0 / irccounts.clients), "");
|
||||
|
||||
list_for_each_entry(acptr, &global_server_list, client_node)
|
||||
{
|
||||
@ -304,7 +349,20 @@ void dump_flat_map(Client *client, Client *server, int length)
|
||||
break;
|
||||
if (--cnt == 0)
|
||||
*buf = '`';
|
||||
sendnumeric(client, RPL_MAP, buf, length-2, acptr->name, acptr->server->users, "");
|
||||
|
||||
len = length - strlen(acptr->name) + 1;
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
if (len > 255)
|
||||
len = 255;
|
||||
|
||||
tbuf[len--] = '\0';
|
||||
while (len >= 0)
|
||||
tbuf[len--] = '-';
|
||||
|
||||
sendnumeric(client, RPL_MAP, buf, acptr->name, tbuf, umax, acptr->server->users,
|
||||
(lmax < 10) ? 4 : (lmax == 100) ? 6 : 5,
|
||||
(acptr->server->users * 100.0 / irccounts.clients), "");
|
||||
}
|
||||
}
|
||||
|
||||
@ -318,6 +376,10 @@ CMD_OVERRIDE_FUNC(override_map)
|
||||
{
|
||||
Client *acptr;
|
||||
int longest = strlen(me.name);
|
||||
float avg_users = 0.0;
|
||||
|
||||
umax = 0;
|
||||
lmax = 0;
|
||||
|
||||
if (parc < 2)
|
||||
parv[1] = "*";
|
||||
@ -339,10 +401,16 @@ CMD_OVERRIDE_FUNC(override_map)
|
||||
|
||||
list_for_each_entry(acptr, &global_server_list, client_node)
|
||||
{
|
||||
int perc = 0;
|
||||
if (FindHiddenServer(acptr->name))
|
||||
break;
|
||||
perc = (acptr->server->users * 100 / irccounts.clients);
|
||||
if ((strlen(acptr->name) + acptr->hopcount * 2) > longest)
|
||||
longest = strlen(acptr->name) + acptr->hopcount * 2;
|
||||
if (lmax < perc)
|
||||
lmax = perc;
|
||||
if (umax < dcount(acptr->server->users))
|
||||
umax = dcount(acptr->server->users);
|
||||
}
|
||||
|
||||
if (longest > 60)
|
||||
@ -354,6 +422,9 @@ CMD_OVERRIDE_FUNC(override_map)
|
||||
else
|
||||
dump_map(client, &me, "*", 0, longest);
|
||||
|
||||
avg_users = irccounts.clients * 1.0 / irccounts.servers;
|
||||
sendnumeric(client, RPL_MAPUSERS, irccounts.servers, (irccounts.servers > 1 ? "s" : ""), irccounts.clients,
|
||||
(irccounts.clients > 1 ? "s" : ""), avg_users);
|
||||
sendnumeric(client, RPL_MAPEND);
|
||||
}
|
||||
|
||||
|
@ -196,7 +196,7 @@ int lr_post_command(Client *from, MessageTag *mtags, const char *buf)
|
||||
*/
|
||||
int more_tags = currentcmd.firstbuf[0] == '@';
|
||||
currentcmd.client = NULL; /* prevent lr_packet from interfering */
|
||||
snprintf(packet, sizeof(packet),
|
||||
snprintf(packet, sizeof(packet)-3,
|
||||
"@label=%s%s%s\r\n",
|
||||
currentcmd.label,
|
||||
more_tags ? ";" : " ",
|
||||
|
@ -31,7 +31,7 @@ ModuleHeader MOD_HEADER
|
||||
= {
|
||||
"list",
|
||||
"5.0",
|
||||
"command /list",
|
||||
"command /LIST",
|
||||
"UnrealIRCd Team",
|
||||
"unrealircd-6",
|
||||
};
|
||||
@ -136,8 +136,8 @@ CMD_FUNC(cmd_list)
|
||||
"use, and what channels LIST will return when you use them.",
|
||||
">number List channels with more than <number> people.",
|
||||
"<number List channels with less than <number> people.",
|
||||
"C>number List channels created between now and <number> minutes ago.",
|
||||
"C<number List channels created earlier than <number> minutes ago.",
|
||||
"C>number List channels created more than <number> minutes ago.",
|
||||
"C<number List channels created less than <number> minutes ago.",
|
||||
"T>number List channels whose topics are older than <number> minutes",
|
||||
" (Ie, they have not changed in the last <number> minutes.",
|
||||
"T<number List channels whose topics are not older than <number> minutes.",
|
||||
@ -199,56 +199,52 @@ CMD_FUNC(cmd_list)
|
||||
}
|
||||
switch (*name)
|
||||
{
|
||||
case '<':
|
||||
usermax = atoi(name + 1) - 1;
|
||||
doall = 1;
|
||||
break;
|
||||
case '>':
|
||||
usermin = atoi(name + 1) + 1;
|
||||
doall = 1;
|
||||
break;
|
||||
case 'C':
|
||||
case 'c': /* Channel time -- creation time? */
|
||||
++name;
|
||||
switch (*name++)
|
||||
{
|
||||
case '<':
|
||||
chantimemax = currenttime - 60 * atoi(name);
|
||||
doall = 1;
|
||||
break;
|
||||
case '>':
|
||||
chantimemin = currenttime - 60 * atoi(name);
|
||||
doall = 1;
|
||||
break;
|
||||
default:
|
||||
sendnumeric(client, ERR_LISTSYNTAX);
|
||||
error = 1;
|
||||
}
|
||||
break;
|
||||
#ifdef LIST_USE_T
|
||||
case 'T':
|
||||
case 't':
|
||||
++name;
|
||||
switch (*name++)
|
||||
{
|
||||
case '<':
|
||||
topictimemax =
|
||||
currenttime - 60 * atoi(name);
|
||||
doall = 1;
|
||||
break;
|
||||
case '>':
|
||||
topictimemin =
|
||||
currenttime - 60 * atoi(name);
|
||||
doall = 1;
|
||||
break;
|
||||
default:
|
||||
sendnumeric(client, ERR_LISTSYNTAX,
|
||||
"Bad list syntax, type /list ?");
|
||||
error = 1;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default: /* A channel, possibly with wildcards.
|
||||
case '<':
|
||||
usermax = atoi(name + 1) - 1;
|
||||
doall = 1;
|
||||
break;
|
||||
case '>':
|
||||
usermin = atoi(name + 1) + 1;
|
||||
doall = 1;
|
||||
break;
|
||||
case 'C':
|
||||
case 'c': /* Channel time -- creation time? */
|
||||
++name;
|
||||
switch (*name++)
|
||||
{
|
||||
case '<':
|
||||
chantimemin = currenttime - 60 * atoi(name);
|
||||
doall = 1;
|
||||
break;
|
||||
case '>':
|
||||
chantimemax = currenttime - 60 * atoi(name);
|
||||
doall = 1;
|
||||
break;
|
||||
default:
|
||||
sendnumeric(client, ERR_LISTSYNTAX);
|
||||
error = 1;
|
||||
}
|
||||
break;
|
||||
case 'T':
|
||||
case 't':
|
||||
++name;
|
||||
switch (*name++)
|
||||
{
|
||||
case '<':
|
||||
topictimemin = currenttime - 60 * atoi(name);
|
||||
doall = 1;
|
||||
break;
|
||||
case '>':
|
||||
topictimemax = currenttime - 60 * atoi(name);
|
||||
doall = 1;
|
||||
break;
|
||||
default:
|
||||
sendnumeric(client, ERR_LISTSYNTAX);
|
||||
error = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* A channel, possibly with wildcards.
|
||||
* Thought for the future: Consider turning wildcard
|
||||
* processing on the fly.
|
||||
* new syntax: !channelmask will tell ircd to ignore
|
||||
@ -259,35 +255,38 @@ CMD_FUNC(cmd_list)
|
||||
* channel even if any of the !channelmask masks
|
||||
* matches it.
|
||||
*/
|
||||
if (*name == '!')
|
||||
{
|
||||
doall = 1;
|
||||
add_name_list(nolist, name + 1);
|
||||
}
|
||||
else if (strchr(name, '*') || strchr(name, '?'))
|
||||
{
|
||||
doall = 1;
|
||||
add_name_list(yeslist, name);
|
||||
}
|
||||
else /* Just a normal channel */
|
||||
{
|
||||
channel = find_channel(name);
|
||||
if (channel && (ShowChannel(client, channel) || ValidatePermissionsForPath("channel:see:list:secret",client,NULL,channel,NULL))) {
|
||||
modebuf[0] = '[';
|
||||
channel_modes(client, modebuf+1, parabuf, sizeof(modebuf)-1, sizeof(parabuf), channel, 0);
|
||||
if (modebuf[2] == '\0')
|
||||
modebuf[0] = '\0';
|
||||
else
|
||||
strlcat(modebuf, "]", sizeof modebuf);
|
||||
sendnumeric(client, RPL_LIST,
|
||||
name, channel->users,
|
||||
modebuf,
|
||||
(channel->topic ? channel->topic :
|
||||
""));
|
||||
}
|
||||
}
|
||||
} /* switch */
|
||||
} /* while */
|
||||
if (*name == '!')
|
||||
{
|
||||
/* Negative matching by name */
|
||||
doall = 1;
|
||||
add_name_list(nolist, name + 1);
|
||||
}
|
||||
else if (strchr(name, '*') || strchr(name, '?'))
|
||||
{
|
||||
/* Channel with wildcards */
|
||||
doall = 1;
|
||||
add_name_list(yeslist, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A specific channel name without wildcards */
|
||||
channel = find_channel(name);
|
||||
if (channel && (ShowChannel(client, channel) || ValidatePermissionsForPath("channel:see:list:secret",client,NULL,channel,NULL)))
|
||||
{
|
||||
modebuf[0] = '[';
|
||||
channel_modes(client, modebuf+1, parabuf, sizeof(modebuf)-1, sizeof(parabuf), channel, 0);
|
||||
|
||||
if (modebuf[2] == '\0')
|
||||
modebuf[0] = '\0';
|
||||
else
|
||||
strlcat(modebuf, "]", sizeof modebuf);
|
||||
|
||||
sendnumeric(client, RPL_LIST, name, channel->users, modebuf,
|
||||
channel->topic ? channel->topic : "");
|
||||
}
|
||||
}
|
||||
} /* switch */
|
||||
} /* for */
|
||||
|
||||
if (doall)
|
||||
{
|
||||
@ -335,7 +334,7 @@ int send_list(Client *client)
|
||||
* choice of numsend. -Rak
|
||||
*/
|
||||
|
||||
/* Begin of /list? then send official channels. */
|
||||
/* Begin of /LIST? then send official channels first. */
|
||||
if ((lopt->starthash == 0) && conf_offchans)
|
||||
{
|
||||
ConfigItem_offchans *x;
|
||||
@ -343,18 +342,15 @@ int send_list(Client *client)
|
||||
{
|
||||
if (find_channel(x->name))
|
||||
continue; /* exists, >0 users.. will be sent later */
|
||||
sendnumeric(client, RPL_LIST, x->name,
|
||||
0,
|
||||
"",
|
||||
x->topic ? x->topic : "");
|
||||
sendnumeric(client, RPL_LIST, x->name, 0, "",
|
||||
x->topic ? x->topic : "");
|
||||
}
|
||||
}
|
||||
|
||||
for (hashnum = lopt->starthash; hashnum < CHAN_HASH_TABLE_SIZE; hashnum++)
|
||||
{
|
||||
if (numsend > 0)
|
||||
for (channel = hash_get_chan_bucket(hashnum);
|
||||
channel; channel = channel->hnextch)
|
||||
for (channel = hash_get_chan_bucket(hashnum); channel; channel = channel->hnextch)
|
||||
{
|
||||
if (SecretChannel(channel)
|
||||
&& !IsMember(client, channel)
|
||||
@ -373,15 +369,13 @@ int send_list(Client *client)
|
||||
if ((!lopt->showall))
|
||||
{
|
||||
/* User count must be in range */
|
||||
if ((channel->users < lopt->usermin) ||
|
||||
((lopt->usermax >= 0) && (channel->users >
|
||||
lopt->usermax)))
|
||||
if ((channel->users < lopt->usermin) ||
|
||||
((lopt->usermax >= 0) && (channel->users > lopt->usermax)))
|
||||
continue;
|
||||
|
||||
/* Creation time must be in range */
|
||||
if ((channel->creationtime && (channel->creationtime <
|
||||
lopt->chantimemin)) || (channel->creationtime >
|
||||
lopt->chantimemax))
|
||||
if ((channel->creationtime && (channel->creationtime < lopt->chantimemin)) ||
|
||||
(channel->creationtime > lopt->chantimemax))
|
||||
continue;
|
||||
|
||||
/* Topic time must be in range */
|
||||
@ -432,7 +426,7 @@ int send_list(Client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* We've exceeded the limit on the number of channels to send back
|
||||
* at once.
|
||||
*/
|
||||
|
@ -26,6 +26,22 @@ CMD_FUNC(cmd_map);
|
||||
|
||||
#define MSG_MAP "MAP"
|
||||
|
||||
static int lmax = 0;
|
||||
static int umax = 0;
|
||||
|
||||
static int dcount(int n)
|
||||
{
|
||||
int cnt = 0;
|
||||
|
||||
while (n != 0)
|
||||
{
|
||||
n = n/10;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
ModuleHeader MOD_HEADER
|
||||
= {
|
||||
"map",
|
||||
@ -70,8 +86,24 @@ static void dump_map(Client *client, Client *server, char *mask, int prompt_leng
|
||||
sendnumeric(client, RPL_MAPMORE, prompt, length, server->name);
|
||||
else
|
||||
{
|
||||
sendnumeric(client, RPL_MAP, prompt,
|
||||
length, server->name, server->server->users, IsOper(client) ? server->id : "");
|
||||
char tbuf[256];
|
||||
char sid[10];
|
||||
int len = length - strlen(server->name) + 1;
|
||||
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
if (len > 255)
|
||||
len = 255;
|
||||
|
||||
tbuf[len--] = '\0';
|
||||
while (len >= 0)
|
||||
tbuf[len--] = '-';
|
||||
if (IsOper(client))
|
||||
snprintf(sid, sizeof(sid), " [%s]", server->id);
|
||||
sendnumeric(client, RPL_MAP, prompt, server->name, tbuf, umax,
|
||||
server->server->users, (double)(lmax < 10) ? 4 : (lmax == 100) ? 6 : 5,
|
||||
(server->server->users * 100.0 / irccounts.clients),
|
||||
IsOper(client) ? sid : "");
|
||||
cnt = 0;
|
||||
}
|
||||
|
||||
@ -115,12 +147,25 @@ static void dump_map(Client *client, Client *server, char *mask, int prompt_leng
|
||||
void dump_flat_map(Client *client, Client *server, int length)
|
||||
{
|
||||
char buf[4];
|
||||
char tbuf[256];
|
||||
Client *acptr;
|
||||
int cnt = 0, hide_ulines;
|
||||
int cnt = 0, len = 0, hide_ulines;
|
||||
|
||||
hide_ulines = (HIDE_ULINES && !ValidatePermissionsForPath("server:info:map:ulines",client,NULL,NULL,NULL)) ? 1 : 0;
|
||||
|
||||
sendnumeric(client, RPL_MAP, "", length, server->name, server->server->users, "");
|
||||
len = length - strlen(server->name) + 3;
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
if (len > 255)
|
||||
len = 255;
|
||||
|
||||
tbuf[len--] = '\0';
|
||||
while (len >= 0)
|
||||
tbuf[len--] = '-';
|
||||
|
||||
sendnumeric(client, RPL_MAP, "", server->name, tbuf, umax, server->server->users,
|
||||
(lmax < 10) ? 4 : (lmax == 100) ? 6 : 5,
|
||||
(server->server->users * 100.0 / irccounts.clients), "");
|
||||
|
||||
list_for_each_entry(acptr, &global_server_list, client_node)
|
||||
{
|
||||
@ -136,7 +181,20 @@ void dump_flat_map(Client *client, Client *server, int length)
|
||||
continue;
|
||||
if (--cnt == 0)
|
||||
*buf = '`';
|
||||
sendnumeric(client, RPL_MAP, buf, length-2, acptr->name, acptr->server->users, "");
|
||||
|
||||
len = length - strlen(acptr->name) + 1;
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
if (len > 255)
|
||||
len = 255;
|
||||
|
||||
tbuf[len--] = '\0';
|
||||
while (len >= 0)
|
||||
tbuf[len--] = '-';
|
||||
|
||||
sendnumeric(client, RPL_MAP, buf, acptr->name, tbuf, umax, acptr->server->users,
|
||||
(lmax < 10) ? 4 : (lmax == 100) ? 6 : 5,
|
||||
(acptr->server->users * 100.0 / irccounts.clients), "");
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,14 +208,23 @@ CMD_FUNC(cmd_map)
|
||||
{
|
||||
Client *acptr;
|
||||
int longest = strlen(me.name);
|
||||
float avg_users;
|
||||
|
||||
umax = 0;
|
||||
lmax = 0;
|
||||
|
||||
if (parc < 2)
|
||||
parv[1] = "*";
|
||||
|
||||
list_for_each_entry(acptr, &global_server_list, client_node)
|
||||
{
|
||||
int perc = (acptr->server->users * 100 / irccounts.clients);
|
||||
if ((strlen(acptr->name) + acptr->hopcount * 2) > longest)
|
||||
longest = strlen(acptr->name) + acptr->hopcount * 2;
|
||||
if (lmax < perc)
|
||||
lmax = perc;
|
||||
if (umax < dcount(acptr->server->users))
|
||||
umax = dcount(acptr->server->users);
|
||||
}
|
||||
|
||||
if (longest > 60)
|
||||
@ -169,5 +236,8 @@ CMD_FUNC(cmd_map)
|
||||
else
|
||||
dump_map(client, &me, "*", 0, longest);
|
||||
|
||||
avg_users = irccounts.clients * 1.0 / irccounts.servers;
|
||||
sendnumeric(client, RPL_MAPUSERS, irccounts.servers, (irccounts.servers > 1 ? "s" : ""), irccounts.clients,
|
||||
(irccounts.clients > 1 ? "s" : ""), avg_users);
|
||||
sendnumeric(client, RPL_MAPEND);
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ long CAP_MESSAGE_TAGS = 0; /**< Looked up at MOD_LOAD, may stay 0 if message-tag
|
||||
ModuleHeader MOD_HEADER
|
||||
= {
|
||||
"message", /* Name of module */
|
||||
"5.0", /* Version */
|
||||
"6.0.2", /* Version */
|
||||
"private message and notice", /* Short description of module */
|
||||
"UnrealIRCd Team",
|
||||
"unrealircd-6",
|
||||
@ -318,7 +318,7 @@ void cmd_message(Client *client, MessageTag *recv_mtags, int parc, const char *p
|
||||
*/
|
||||
if (IsDead(client))
|
||||
return;
|
||||
if (!IsDead(client) && (sendtype != SEND_TYPE_NOTICE) && errmsg)
|
||||
if (!IsDead(client) && (sendtype != SEND_TYPE_NOTICE) && !BadPtr(errmsg))
|
||||
sendnumeric(client, ERR_CANNOTSENDTOCHAN, channel->name, errmsg, p2);
|
||||
continue; /* skip delivery to this target */
|
||||
}
|
||||
@ -423,7 +423,7 @@ void cmd_message(Client *client, MessageTag *recv_mtags, int parc, const char *p
|
||||
/* Message is discarded */
|
||||
if (IsDead(client))
|
||||
return;
|
||||
if ((sendtype != SEND_TYPE_NOTICE) && errmsg)
|
||||
if ((sendtype != SEND_TYPE_NOTICE) && !BadPtr(errmsg))
|
||||
sendnumeric(client, ERR_CANTSENDTOUSER, target->name, errmsg);
|
||||
} else
|
||||
{
|
||||
|
@ -370,28 +370,19 @@ void _do_mode(Channel *channel, Client *client, MessageTag *recv_mtags, int parc
|
||||
":%s MODE %s %s %s",
|
||||
client->name, channel->name, modebuf, parabuf);
|
||||
|
||||
if (IsServer(client) && sendts != -1)
|
||||
if (IsServer(client) || IsMe(client))
|
||||
{
|
||||
sendto_server(client, 0, 0, mtags,
|
||||
":%s MODE %s %s %s %lld",
|
||||
client->id, channel->name,
|
||||
modebuf, parabuf,
|
||||
(long long)sendts);
|
||||
} else
|
||||
if (samode && IsMe(client))
|
||||
{
|
||||
/* SAMODE is a special case: always send a TS of 0 (omitting TS==desync) */
|
||||
sendto_server(client, 0, 0, mtags,
|
||||
":%s MODE %s %s %s 0",
|
||||
client->id, channel->name,
|
||||
modebuf, parabuf);
|
||||
(sendts != -1) ? (long long)sendts : 0LL);
|
||||
} else
|
||||
{
|
||||
sendto_server(client, 0, 0, mtags,
|
||||
":%s MODE %s %s %s",
|
||||
client->id, channel->name,
|
||||
modebuf, parabuf);
|
||||
/* tell them it's not a timestamp, in case the last param is a number. */
|
||||
}
|
||||
|
||||
if (MyConnect(client))
|
||||
@ -1159,6 +1150,22 @@ CMD_FUNC(_cmd_umode)
|
||||
goto def;
|
||||
case 't':
|
||||
case 'x':
|
||||
/* set::anti-flood::vhost-flood */
|
||||
if (MyUser(client))
|
||||
{
|
||||
if ((what == MODE_DEL) && !ValidatePermissionsForPath("immune:vhost-flood",client,NULL,NULL,NULL) &&
|
||||
flood_limit_exceeded(client, FLD_VHOST))
|
||||
{
|
||||
/* Throttle... */
|
||||
if (!modex_err)
|
||||
{
|
||||
sendnotice(client, "*** Setting -%c too fast. Please try again later.", *m);
|
||||
modex_err = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (UHOST_ALLOWED)
|
||||
{
|
||||
case UHALLOW_ALWAYS:
|
||||
|
@ -141,6 +141,7 @@ CMD_FUNC(reputationunperm);
|
||||
int reputation_whois(Client *client, Client *target, NameValuePrioList **list);
|
||||
int reputation_set_on_connect(Client *client);
|
||||
int reputation_pre_lconnect(Client *client);
|
||||
int reputation_ip_change(Client *client, const char *oldip);
|
||||
int reputation_connect_extinfo(Client *client, NameValuePrioList **list);
|
||||
int reputation_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs);
|
||||
int reputation_config_run(ConfigFile *cf, ConfigEntry *ce, int type);
|
||||
@ -192,6 +193,7 @@ MOD_INIT()
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, reputation_config_run);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_WHOIS, 0, reputation_whois);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_HANDSHAKE, 0, reputation_set_on_connect);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_IP_CHANGE, 0, reputation_ip_change);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_PRE_LOCAL_CONNECT, 2000000000, reputation_pre_lconnect); /* (prio: last) */
|
||||
HookAdd(modinfo->handle, HOOKTYPE_REMOTE_CONNECT, -1000000000, reputation_set_on_connect); /* (prio: near-first) */
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONNECT_EXTINFO, 0, reputation_connect_extinfo); /* (prio: near-first) */
|
||||
@ -804,6 +806,12 @@ int reputation_set_on_connect(Client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int reputation_ip_change(Client *client, const char *oldip)
|
||||
{
|
||||
reputation_lookup_score_and_set(client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int reputation_pre_lconnect(Client *client)
|
||||
{
|
||||
/* User will likely be accepted. Inform other servers about the score
|
||||
|
@ -170,9 +170,9 @@ CMD_FUNC(cmd_sapart)
|
||||
if (comment)
|
||||
{
|
||||
snprintf(commentx, sizeof(commentx), "SAPart: %s", comment);
|
||||
//sendnotice(target, "*** You were forced to part %s (%s)", request, commentx);
|
||||
sendnotice(target, "*** You were forced to part %s (%s)", request, commentx);
|
||||
} else {
|
||||
//sendnotice(target, "*** You were forced to part %s", request);
|
||||
sendnotice(target, "*** You were forced to part %s", request);
|
||||
}
|
||||
|
||||
parv[0] = target->name; // nick
|
||||
|
@ -158,5 +158,5 @@ CMD_FUNC(cmd_setname)
|
||||
}
|
||||
free_message_tags(mtags);
|
||||
|
||||
RunHook(HOOKTYPE_REALNAME_CHANGED, client, oldinfo);
|
||||
RunHook(HOOKTYPE_REALNAME_CHANGE, client, oldinfo);
|
||||
}
|
||||
|
@ -520,17 +520,17 @@ int stats_command(Client *client, const char *para)
|
||||
|
||||
int stats_oper(Client *client, const char *para)
|
||||
{
|
||||
ConfigItem_oper *oper_p;
|
||||
ConfigItem_oper *o;
|
||||
ConfigItem_mask *m;
|
||||
|
||||
for (oper_p = conf_oper; oper_p; oper_p = oper_p->next)
|
||||
for (o = conf_oper; o; o = o->next)
|
||||
{
|
||||
for (m = oper_p->mask; m; m = m->next)
|
||||
for (m = o->mask; m; m = m->next)
|
||||
{
|
||||
sendnumeric(client, RPL_STATSOLINE,
|
||||
'O', m->mask, oper_p->name,
|
||||
"-",
|
||||
oper_p->class->name? oper_p->class->name : "");
|
||||
sendnumeric(client, RPL_STATSOLINE,
|
||||
'O', m->mask, o->name,
|
||||
o->operclass ? o->operclass: "",
|
||||
o->class->name ? o->class->name : "");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -540,11 +540,20 @@ static char *stats_port_helper(ConfigItem_listen *listener)
|
||||
{
|
||||
static char buf[256];
|
||||
|
||||
ircsnprintf(buf, sizeof(buf), "%s%s%s%s",
|
||||
ircsnprintf(buf, sizeof(buf), "%s%s%s",
|
||||
(listener->options & LISTENER_CLIENTSONLY)? "clientsonly ": "",
|
||||
(listener->options & LISTENER_SERVERSONLY)? "serversonly ": "",
|
||||
(listener->options & LISTENER_TLS)? "tls ": "",
|
||||
!(listener->options & LISTENER_TLS)? "plaintext ": "");
|
||||
(listener->options & LISTENER_DEFER_ACCEPT)? "defer-accept ": "");
|
||||
|
||||
/* And one of these.. */
|
||||
if (listener->options & LISTENER_CONTROL)
|
||||
strlcat(buf, "control ", sizeof(buf));
|
||||
else if (listener->socket_type == SOCKET_TYPE_UNIX)
|
||||
;
|
||||
else if (listener->options & LISTENER_TLS)
|
||||
strlcat(buf, "tls ", sizeof(buf));
|
||||
else
|
||||
strlcat(buf, "plaintext ", sizeof(buf));
|
||||
return buf;
|
||||
}
|
||||
|
||||
@ -558,13 +567,22 @@ int stats_port(Client *client, const char *para)
|
||||
continue;
|
||||
if ((listener->options & LISTENER_SERVERSONLY) && !ValidatePermissionsForPath("server:info:stats",client,NULL,NULL,NULL))
|
||||
continue;
|
||||
sendnotice(client, "*** Listener on %s:%i (%s): has %i client(s), options: %s %s",
|
||||
listener->ip,
|
||||
listener->port,
|
||||
listener->ipv6 ? "IPv6" : "IPv4",
|
||||
listener->clients,
|
||||
stats_port_helper(listener),
|
||||
listener->flag.temporary ? "[TEMPORARY]" : "");
|
||||
if (listener->socket_type == SOCKET_TYPE_UNIX)
|
||||
{
|
||||
sendnotice(client, "*** Listener on %s (UNIX): has %i client(s), options: %s %s",
|
||||
listener->file,
|
||||
listener->clients,
|
||||
stats_port_helper(listener),
|
||||
listener->flag.temporary ? "[TEMPORARY]" : "");
|
||||
} else {
|
||||
sendnotice(client, "*** Listener on %s:%i (%s): has %i client(s), options: %s %s",
|
||||
listener->ip,
|
||||
listener->port,
|
||||
listener->socket_type == SOCKET_TYPE_IPV6 ? "IPv6" : "IPv4",
|
||||
listener->clients,
|
||||
stats_port_helper(listener),
|
||||
listener->flag.temporary ? "[TEMPORARY]" : "");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ void unban_user(Client *client, Channel *channel, Client *acptr, char chmode)
|
||||
}
|
||||
else if (chmode != 'I' && *ban->banstr == '~' && (extban = findmod_by_bantype(ban->banstr, &nextbanstr)))
|
||||
{
|
||||
if ((extban->options & EXTBOPT_CHSVSMODE) && (extban->is_banned_events & b->ban_check_types))
|
||||
if (extban->is_banned_events & b->ban_check_types)
|
||||
{
|
||||
b->banstr = nextbanstr;
|
||||
if (extban->is_banned(b))
|
||||
@ -176,7 +176,7 @@ void clear_bans(Client *client, Channel *channel, char chmode)
|
||||
bnext = ban->next;
|
||||
if (chmode != 'I' && (*ban->banstr == '~') && (extban = findmod_by_bantype(ban->banstr, NULL)))
|
||||
{
|
||||
if (!(extban->options & EXTBOPT_CHSVSMODE))
|
||||
if (!(extban->is_banned_events & BANCHK_JOIN))
|
||||
continue;
|
||||
}
|
||||
add_send_mode_param(channel, client, '-', chmode, ban->banstr);
|
||||
@ -298,7 +298,7 @@ void channel_svsmode(Client *client, int parc, const char *parv[])
|
||||
sendto_channel(channel, client, client, 0, 0, SEND_LOCAL, mtags,
|
||||
":%s MODE %s %s %s",
|
||||
client->name, channel->name, modebuf, parabuf);
|
||||
sendto_server(NULL, 0, 0, mtags, ":%s MODE %s %s %s", client->id, channel->name, modebuf, parabuf);
|
||||
sendto_server(NULL, 0, 0, mtags, ":%s MODE %s %s %s%s", client->id, channel->name, modebuf, parabuf, IsServer(client)?" 0":"");
|
||||
|
||||
/* Activate this hook just like cmd_mode.c */
|
||||
RunHook(HOOKTYPE_REMOTE_CHANMODE, client, channel, mtags, modebuf, parabuf, 0, 0, &destroy_channel);
|
||||
@ -615,7 +615,7 @@ void add_send_mode_param(Channel *channel, Client *from, char what, char mode, c
|
||||
sendto_channel(channel, from, from, 0, 0, SEND_LOCAL, mtags,
|
||||
":%s MODE %s %s %s",
|
||||
from->name, channel->name, modebuf, parabuf);
|
||||
sendto_server(NULL, 0, 0, mtags, ":%s MODE %s %s %s", from->id, channel->name, modebuf, parabuf);
|
||||
sendto_server(NULL, 0, 0, mtags, ":%s MODE %s %s %s%s", from->id, channel->name, modebuf, parabuf, IsServer(from)?" 0":"");
|
||||
free_message_tags(mtags);
|
||||
send = 0;
|
||||
*parabuf = 0;
|
||||
|
@ -41,6 +41,7 @@ int tkl_config_test_except(ConfigFile *, ConfigEntry *, int, int *);
|
||||
int tkl_config_run_except(ConfigFile *, ConfigEntry *, int);
|
||||
int tkl_config_test_set(ConfigFile *, ConfigEntry *, int, int *);
|
||||
int tkl_config_run_set(ConfigFile *, ConfigEntry *, int);
|
||||
int tkl_ip_change(Client *client, const char *oldip);
|
||||
CMD_FUNC(cmd_gline);
|
||||
CMD_FUNC(cmd_shun);
|
||||
CMD_FUNC(cmd_tempshun);
|
||||
@ -213,6 +214,7 @@ MOD_INIT()
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, tkl_config_run_ban);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, tkl_config_run_except);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, tkl_config_run_set);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_IP_CHANGE, 2000000000, tkl_ip_change);
|
||||
CommandAdd(modinfo->handle, "GLINE", cmd_gline, 3, CMD_OPER);
|
||||
CommandAdd(modinfo->handle, "SHUN", cmd_shun, 3, CMD_OPER);
|
||||
CommandAdd(modinfo->handle, "TEMPSHUN", cmd_tempshun, 2, CMD_OPER);
|
||||
@ -952,6 +954,12 @@ char *spamfilter_id(TKL *tk)
|
||||
return buf;
|
||||
}
|
||||
|
||||
int tkl_ip_change(Client *client, const char *oldip)
|
||||
{
|
||||
check_banned(client, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** GLINE - Global kline.
|
||||
** Syntax: /gline [+|-]u@h mask time :reason
|
||||
**
|
||||
@ -4772,23 +4780,15 @@ int _match_spamfilter(Client *client, const char *str_in, int target, const char
|
||||
|
||||
if (ret)
|
||||
{
|
||||
/* We have a match! */
|
||||
char destinationbuf[48];
|
||||
|
||||
if (destination) {
|
||||
destinationbuf[0] = ' ';
|
||||
strlcpy(destinationbuf+1, destination, sizeof(destinationbuf)-1); /* cut it off */
|
||||
} else
|
||||
destinationbuf[0] = '\0';
|
||||
|
||||
/* Hold on.. perhaps it's on the exceptions list... */
|
||||
/* We have a match! But.. perhaps it's on the exceptions list? */
|
||||
if (!winner_tkl && destination && target_is_spamexcept(destination))
|
||||
return 0; /* No problem! */
|
||||
|
||||
unreal_log(ULOG_INFO, "tkl", "SPAMFILTER_MATCH", client,
|
||||
"[Spamfilter] $client.details matches filter '$tkl': [cmd: $command$destination: '$str'] [reason: $tkl.reason] [action: $tkl.ban_action]",
|
||||
"[Spamfilter] $client.details matches filter '$tkl': [cmd: $command$_space$destination: '$str'] [reason: $tkl.reason] [action: $tkl.ban_action]",
|
||||
log_data_tkl("tkl", tkl),
|
||||
log_data_string("command", cmd),
|
||||
log_data_string("_space", destination ? " " : ""),
|
||||
log_data_string("destination", destination ? destination : ""),
|
||||
log_data_string("str", str));
|
||||
|
||||
|
@ -29,9 +29,9 @@
|
||||
|
||||
ModDataInfo *watchCounterMD;
|
||||
ModDataInfo *watchListMD;
|
||||
static Watch *watchTable[WATCH_HASH_TABLE_SIZE];
|
||||
static int watch_initialized = 0;
|
||||
static char siphashkey_watch[SIPHASH_KEY_LENGTH];
|
||||
|
||||
static Watch **watchTable = NULL;
|
||||
static char *siphashkey_watch = NULL;
|
||||
|
||||
void dummy_free(ModData *md);
|
||||
void watch_free(ModData *md);
|
||||
@ -47,8 +47,8 @@ uint64_t hash_watch_nick_name(const char *name);
|
||||
ModuleHeader MOD_HEADER
|
||||
= {
|
||||
"watch-backend",
|
||||
"5.0",
|
||||
"backend for /watch",
|
||||
"6.0.3",
|
||||
"backend for /WATCH",
|
||||
"UnrealIRCd Team",
|
||||
"unrealircd-6",
|
||||
};
|
||||
@ -65,20 +65,28 @@ MOD_TEST()
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
void watch_generic_free(ModData *m)
|
||||
{
|
||||
safe_free(m->ptr);
|
||||
}
|
||||
|
||||
MOD_INIT()
|
||||
{
|
||||
ModDataInfo mreq;
|
||||
|
||||
MARK_AS_OFFICIAL_MODULE(modinfo);
|
||||
ModuleSetOptions(modinfo->handle, MOD_OPT_PERM_RELOADABLE, 1); /* or do a complex memory freeing algorithm instead */
|
||||
|
||||
if (!watch_initialized)
|
||||
|
||||
LoadPersistentPointer(modinfo, siphashkey_watch, watch_generic_free);
|
||||
if (siphashkey_watch == NULL)
|
||||
{
|
||||
memset(watchTable, 0, sizeof(watchTable));
|
||||
siphashkey_watch = safe_alloc(SIPHASH_KEY_LENGTH);
|
||||
siphash_generate_key(siphashkey_watch);
|
||||
watch_initialized = 1;
|
||||
}
|
||||
|
||||
LoadPersistentPointer(modinfo, watchTable, watch_generic_free);
|
||||
if (watchTable == NULL)
|
||||
watchTable = safe_alloc(sizeof(Watch) * WATCH_HASH_TABLE_SIZE);
|
||||
|
||||
memset(&mreq, 0 , sizeof(mreq));
|
||||
mreq.type = MODDATATYPE_LOCAL_CLIENT;
|
||||
mreq.name = "watchCount",
|
||||
@ -113,6 +121,8 @@ MOD_LOAD()
|
||||
|
||||
MOD_UNLOAD()
|
||||
{
|
||||
SavePersistentPointer(modinfo, siphashkey_watch);
|
||||
SavePersistentPointer(modinfo, watchTable);
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -151,13 +161,13 @@ int _watch_add(char *nick, Client *client, int flags)
|
||||
hashv = hash_watch_nick_name(nick);
|
||||
|
||||
/* Find the right nick (header) in the bucket, or NULL... */
|
||||
if ((watch = (Watch *)watchTable[hashv]))
|
||||
if ((watch = watchTable[hashv]))
|
||||
while (watch && mycmp(watch->nick, nick))
|
||||
watch = watch->hnext;
|
||||
|
||||
/* If found NULL (no header for this nick), make one... */
|
||||
if (!watch) {
|
||||
watch = (Watch *)safe_alloc(sizeof(Watch)+strlen(nick));
|
||||
watch = safe_alloc(sizeof(Watch)+strlen(nick));
|
||||
watch->lasttime = timeofday;
|
||||
strcpy(watch->nick, nick);
|
||||
|
||||
@ -203,7 +213,7 @@ int _watch_check(Client *client, int event, int (*watch_notify)(Client *client,
|
||||
hashv = hash_watch_nick_name(client->name);
|
||||
|
||||
/* Find the right header in this bucket */
|
||||
if ((watch = (Watch *)watchTable[hashv]))
|
||||
if ((watch = watchTable[hashv]))
|
||||
while (watch && mycmp(watch->nick, client->name))
|
||||
watch = watch->hnext;
|
||||
if (!watch)
|
||||
@ -231,7 +241,7 @@ Watch *_watch_get(char *nick)
|
||||
|
||||
hashv = hash_watch_nick_name(nick);
|
||||
|
||||
if ((watch = (Watch *)watchTable[hashv]))
|
||||
if ((watch = watchTable[hashv]))
|
||||
while (watch && mycmp(watch->nick, nick))
|
||||
watch = watch->hnext;
|
||||
|
||||
|
@ -336,6 +336,7 @@ ConfigItem_webirc *find_webirc(Client *client, const char *password, WEBIRCType
|
||||
/* Does the CGI:IRC host spoofing work */
|
||||
void dowebirc(Client *client, const char *ip, const char *host, const char *options)
|
||||
{
|
||||
char oldip[64];
|
||||
char scratch[64];
|
||||
|
||||
if (IsWEBIRC(client))
|
||||
@ -357,6 +358,7 @@ void dowebirc(Client *client, const char *ip, const char *host, const char *opti
|
||||
}
|
||||
|
||||
/* STEP 2: Update GetIP() */
|
||||
strlcpy(oldip, client->ip, sizeof(oldip));
|
||||
safe_strdup(client->ip, ip);
|
||||
|
||||
/* STEP 3: Update client->local->hostp */
|
||||
@ -397,15 +399,7 @@ void dowebirc(Client *client, const char *ip, const char *host, const char *opti
|
||||
}
|
||||
}
|
||||
|
||||
/* blacklist_start_check() */
|
||||
if (RCallbacks[CALLBACKTYPE_BLACKLIST_CHECK] != NULL)
|
||||
RCallbacks[CALLBACKTYPE_BLACKLIST_CHECK]->func.intfunc(client);
|
||||
|
||||
/* Check (g)zlines right now; these are normally checked upon accept(),
|
||||
* but since we know the IP only now after PASS/WEBIRC, we have to check
|
||||
* here again...
|
||||
*/
|
||||
check_banned(client, 0);
|
||||
RunHook(HOOKTYPE_IP_CHANGE, client, oldip);
|
||||
}
|
||||
|
||||
/* WEBIRC <pass> "cgiirc" <hostname> <ip> [:option1 [option2...]]*/
|
||||
|
@ -686,6 +686,9 @@ int websocket_handshake_valid(Client *client)
|
||||
}
|
||||
if (WSU(client)->forwarded)
|
||||
{
|
||||
struct HTTPForwardedHeader *forwarded;
|
||||
char oldip[64];
|
||||
|
||||
/* check for source ip */
|
||||
if (BadPtr(client->local->listener->websocket_forward) || !websocket_ip_compare(client->local->listener->websocket_forward, client->ip))
|
||||
{
|
||||
@ -694,7 +697,6 @@ int websocket_handshake_valid(Client *client)
|
||||
return 0;
|
||||
}
|
||||
/* parse the header */
|
||||
struct HTTPForwardedHeader *forwarded;
|
||||
forwarded = websocket_parse_forwarded_header(WSU(client)->forwarded);
|
||||
/* check header values */
|
||||
if (!is_valid_ip(forwarded->ip))
|
||||
@ -705,6 +707,7 @@ int websocket_handshake_valid(Client *client)
|
||||
}
|
||||
/* store data */
|
||||
WSU(client)->secure = forwarded->secure;
|
||||
strlcpy(oldip, client->ip, sizeof(oldip));
|
||||
safe_strdup(client->ip, forwarded->ip);
|
||||
/* Update client->local->hostp */
|
||||
strlcpy(client->local->sockhost, forwarded->ip, sizeof(client->local->sockhost)); /* in case dns lookup fails or is disabled */
|
||||
@ -733,15 +736,7 @@ int websocket_handshake_valid(Client *client)
|
||||
/* Race condition detected, DNS has been done, continue with auth */
|
||||
}
|
||||
}
|
||||
/* blacklist_start_check() */
|
||||
if (RCallbacks[CALLBACKTYPE_BLACKLIST_CHECK] != NULL)
|
||||
RCallbacks[CALLBACKTYPE_BLACKLIST_CHECK]->func.intfunc(client);
|
||||
|
||||
/* Check (g)zlines right now; these are normally checked upon accept(),
|
||||
* but since we know the IP only now after PASS/WEBIRC, we have to check
|
||||
* here again...
|
||||
*/
|
||||
check_banned(client, 0);
|
||||
RunHook(HOOKTYPE_IP_CHANGE, client, oldip);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ ModuleHeader MOD_HEADER
|
||||
#define WMATCH_ACCOUNT 0x0040
|
||||
#define WMATCH_IP 0x0080
|
||||
#define WMATCH_MODES 0x0100
|
||||
#define WMATCH_CONTIME 0x0200
|
||||
|
||||
#define RPL_WHOSPCRPL 354
|
||||
|
||||
@ -69,6 +70,8 @@ struct who_format
|
||||
const char *querytype;
|
||||
int show_realhost;
|
||||
int show_ip;
|
||||
time_t contimemin;
|
||||
time_t contimemax;
|
||||
};
|
||||
|
||||
/* Global variables */
|
||||
@ -229,6 +232,7 @@ CMD_FUNC(cmd_whox)
|
||||
case 's': fmt.matchsel |= WMATCH_SERVER; continue;
|
||||
case 'a': fmt.matchsel |= WMATCH_ACCOUNT; continue;
|
||||
case 'm': fmt.matchsel |= WMATCH_MODES; continue;
|
||||
case 't': fmt.matchsel |= WMATCH_CONTIME; continue;
|
||||
case 'R':
|
||||
if (IsOper(client))
|
||||
fmt.show_realhost = 1;
|
||||
@ -336,6 +340,28 @@ CMD_FUNC(cmd_whox)
|
||||
}
|
||||
}
|
||||
|
||||
/* match connect time */
|
||||
if (fmt.matchsel & WMATCH_CONTIME)
|
||||
{
|
||||
char *s = mask;
|
||||
time_t currenttime = TStime();
|
||||
|
||||
fmt.contimemin = 0;
|
||||
fmt.contimemax = 0;
|
||||
|
||||
switch (*s)
|
||||
{
|
||||
case '<':
|
||||
if (*s++)
|
||||
fmt.contimemin = currenttime - config_checkval(s, CFG_TIME);
|
||||
break;
|
||||
case '>':
|
||||
if (*s++)
|
||||
fmt.contimemax = currenttime - config_checkval(s, CFG_TIME);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* '/who #some_channel' */
|
||||
if (IsChannelName(mask))
|
||||
{
|
||||
@ -449,6 +475,16 @@ static int do_match(Client *client, Client *acptr, char *mask, struct who_format
|
||||
}
|
||||
}
|
||||
|
||||
/* match connect time */
|
||||
if (IsMatch(fmt, WMATCH_CONTIME) && MyConnect(acptr) && (fmt->contimemin || fmt->contimemax))
|
||||
{
|
||||
if (fmt->contimemin && (acptr->local->creationtime > fmt->contimemin))
|
||||
return 1;
|
||||
|
||||
if (fmt->contimemax && (acptr->local->creationtime < fmt->contimemax))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
12
src/parse.c
12
src/parse.c
@ -104,7 +104,9 @@ void parse_client_queued(Client *client)
|
||||
return; /* we delay processing of data until identd has replied */
|
||||
|
||||
if (!IsUser(client) && !IsServer(client) && (iConf.handshake_delay > 0) &&
|
||||
!IsNoHandshakeDelay(client) && (TStime() - client->local->creationtime < iConf.handshake_delay))
|
||||
!IsNoHandshakeDelay(client) &&
|
||||
!IsControl(client) &&
|
||||
(TStime() - client->local->creationtime < iConf.handshake_delay))
|
||||
{
|
||||
return; /* we delay processing of data until set::handshake-delay is reached */
|
||||
}
|
||||
@ -368,6 +370,8 @@ static void parse2(Client *cptr, Client **fromptr, MessageTag *mtags, int mtags_
|
||||
flags |= CMD_VIRUS;
|
||||
if (IsOper(from))
|
||||
flags |= CMD_OPER;
|
||||
if (IsControl(from))
|
||||
flags |= CMD_CONTROL;
|
||||
cmptr = find_command(ch, flags);
|
||||
if (!cmptr || !(cmptr->flags & CMD_NOLAG))
|
||||
{
|
||||
@ -376,6 +380,12 @@ static void parse2(Client *cptr, Client **fromptr, MessageTag *mtags, int mtags_
|
||||
}
|
||||
if (!cmptr)
|
||||
{
|
||||
if (IsControl(from))
|
||||
{
|
||||
sendto_one(from, NULL, "ERROR UNKNOWN_COMMAND: %s", ch);
|
||||
sendto_one(from, NULL, "END 1");
|
||||
return;
|
||||
}
|
||||
/* Don't send error messages in response to NOTICEs
|
||||
* in pre-connection state.
|
||||
*/
|
||||
|
199
src/proc_io_client.c
Normal file
199
src/proc_io_client.c
Normal file
@ -0,0 +1,199 @@
|
||||
/************************************************************************
|
||||
* UnrealIRCd - Unreal Internet Relay Chat Daemon - src/proc_io_client.c
|
||||
* (c) 2022- Bram Matthys and The UnrealIRCd team
|
||||
*
|
||||
* See file AUTHORS in IRC package for additional names of
|
||||
* the programmers.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* @brief Inter-process I/O
|
||||
*/
|
||||
#include "unrealircd.h"
|
||||
|
||||
int procio_client_connect(const char *file)
|
||||
{
|
||||
int fd;
|
||||
struct sockaddr_un addr;
|
||||
|
||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
fprintf(stderr, "Your Windows version does not support UNIX sockets, "
|
||||
"so cannot communicate to UnrealIRCd.\n"
|
||||
"Windows 10 version 1803 (April 2018) or later is needed.\n");
|
||||
#else
|
||||
fprintf(stderr, "Cannot communicate to UnrealIRCd: %s\n"
|
||||
"Perhaps your operating system does not support UNIX Sockets?\n",
|
||||
strerror(ERRNO));
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
strlcpy(addr.sun_path, file, sizeof(addr.sun_path));
|
||||
|
||||
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
|
||||
{
|
||||
fprintf(stderr, "Could not connect to '%s': %s\n",
|
||||
CONTROLFILE, strerror(errno));
|
||||
fprintf(stderr, "The IRC server does not appear to be running.\n");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int procio_send(int fd, const char *command)
|
||||
{
|
||||
char buf[512];
|
||||
int n;
|
||||
snprintf(buf, sizeof(buf), "%s\r\n", command);
|
||||
n = strlen(buf);
|
||||
if (send(fd, buf, n, 0) != n)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *recolor_logs(const char *str)
|
||||
{
|
||||
static char retbuf[2048];
|
||||
char buf[2048], *p;
|
||||
const char *color = NULL;
|
||||
|
||||
strlcpy(buf, str, sizeof(buf));
|
||||
p = strchr(buf, ' ');
|
||||
if ((*str != '[') || !p)
|
||||
return str;
|
||||
*p++ = '\0';
|
||||
|
||||
if (!strcmp(buf, "[debug]"))
|
||||
color = log_level_terminal_color(ULOG_DEBUG);
|
||||
else if (!strcmp(buf, "[info]"))
|
||||
color = log_level_terminal_color(ULOG_INFO);
|
||||
else if (!strcmp(buf, "[warning]"))
|
||||
color = log_level_terminal_color(ULOG_WARNING);
|
||||
else if (!strcmp(buf, "[error]"))
|
||||
color = log_level_terminal_color(ULOG_ERROR);
|
||||
else if (!strcmp(buf, "[fatal]"))
|
||||
color = log_level_terminal_color(ULOG_FATAL);
|
||||
else
|
||||
color = log_level_terminal_color(ULOG_INVALID);
|
||||
|
||||
snprintf(retbuf, sizeof(retbuf), "%s%s%s %s",
|
||||
color, buf, TERMINAL_COLOR_RESET, p);
|
||||
return retbuf;
|
||||
}
|
||||
|
||||
const char *recolor_split(const char *str)
|
||||
{
|
||||
static char retbuf[2048];
|
||||
char buf[2048], *p;
|
||||
const char *color = NULL;
|
||||
|
||||
strlcpy(buf, str, sizeof(buf));
|
||||
p = strchr(buf, ' ');
|
||||
if (!p)
|
||||
return str;
|
||||
*p++ = '\0';
|
||||
|
||||
snprintf(retbuf, sizeof(retbuf), "%s%s %s%s%s",
|
||||
"\033[92m", buf,
|
||||
"\033[93m", p,
|
||||
TERMINAL_COLOR_RESET);
|
||||
return retbuf;
|
||||
}
|
||||
|
||||
int procio_client(const char *command, int auto_color_logs)
|
||||
{
|
||||
int fd;
|
||||
char buf[READBUFSIZE];
|
||||
int n;
|
||||
dbuf queue;
|
||||
|
||||
if (auto_color_logs && !terminal_supports_color())
|
||||
auto_color_logs = 0;
|
||||
|
||||
fd = procio_client_connect(CONTROLFILE);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
/* Expect the welcome message */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
n = recv(fd, buf, sizeof(buf), 0);
|
||||
if ((n < 0) || strncmp(buf, "READY", 4))
|
||||
{
|
||||
fprintf(stderr, "Error while communicating to IRCd via '%s': %s\n"
|
||||
"Maybe the IRC server is not running?\n",
|
||||
CONTROLFILE, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!procio_send(fd, command))
|
||||
{
|
||||
fprintf(stderr, "Error while sending command to IRCd via '%s'. Strange!\n",
|
||||
CONTROLFILE);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*buf = '\0';
|
||||
dbuf_queue_init(&queue);
|
||||
while(1)
|
||||
{
|
||||
n = recv(fd, buf, sizeof(buf)-1, 0);
|
||||
if (n <= 0)
|
||||
break;
|
||||
buf[n] = '\0'; /* terminate the string */
|
||||
dbuf_put(&queue, buf, n);
|
||||
|
||||
/* And try to read all complete lines: */
|
||||
do
|
||||
{
|
||||
n = dbuf_getmsg(&queue, buf);
|
||||
if (n > 0)
|
||||
{
|
||||
if (!strncmp(buf, "REPLY ", 6))
|
||||
{
|
||||
char *reply = buf+6;
|
||||
if (auto_color_logs == 0)
|
||||
printf("%s\n", reply);
|
||||
else if (auto_color_logs == 1)
|
||||
printf("%s\n", recolor_logs(reply));
|
||||
else
|
||||
printf("%s\n", recolor_split(reply));
|
||||
} else
|
||||
if (!strncmp(buf, "END ", 4))
|
||||
{
|
||||
int exitcode = atoi(buf+4);
|
||||
close(fd);
|
||||
return exitcode;
|
||||
}
|
||||
}
|
||||
} while(n > 0);
|
||||
}
|
||||
|
||||
/* IRCd hung up without saying goodbye, possibly problematic,
|
||||
* or at least we cannot determine, so exit with status 66.
|
||||
*/
|
||||
close(fd);
|
||||
return 66;
|
||||
}
|
170
src/proc_io_server.c
Normal file
170
src/proc_io_server.c
Normal file
@ -0,0 +1,170 @@
|
||||
/************************************************************************
|
||||
* UnrealIRCd - Unreal Internet Relay Chat Daemon - src/proc_io_server.c
|
||||
* (c) 2022- Bram Matthys and The UnrealIRCd team
|
||||
*
|
||||
* See file AUTHORS in IRC package for additional names of
|
||||
* the programmers.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* @brief Inter-process I/O
|
||||
*/
|
||||
#include "unrealircd.h"
|
||||
#include <ares.h>
|
||||
|
||||
CMD_FUNC(procio_status);
|
||||
CMD_FUNC(procio_modules);
|
||||
CMD_FUNC(procio_rehash);
|
||||
CMD_FUNC(procio_exit);
|
||||
CMD_FUNC(procio_help);
|
||||
|
||||
/** Create the unrealircd.ctl socket (server-side) */
|
||||
void add_proc_io_server(void)
|
||||
{
|
||||
ConfigItem_listen *listener;
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Ignore silently on Windows versions older than W10 build 17061 */
|
||||
if (!unix_sockets_capable())
|
||||
return;
|
||||
#endif
|
||||
listener = safe_alloc(sizeof(ConfigItem_listen));
|
||||
safe_strdup(listener->file, CONTROLFILE);
|
||||
listener->socket_type = SOCKET_TYPE_UNIX;
|
||||
listener->options = LISTENER_CONTROL;
|
||||
listener->fd = -1;
|
||||
AddListItem(listener, conf_listen);
|
||||
if (add_listener(listener) == -1)
|
||||
exit(-1);
|
||||
CommandAdd(NULL, "STATUS", procio_status, MAXPARA, CMD_CONTROL);
|
||||
CommandAdd(NULL, "MODULES", procio_modules, MAXPARA, CMD_CONTROL);
|
||||
CommandAdd(NULL, "REHASH", procio_rehash, MAXPARA, CMD_CONTROL);
|
||||
CommandAdd(NULL, "EXIT", procio_exit, MAXPARA, CMD_CONTROL);
|
||||
CommandAdd(NULL, "HELP", procio_help, MAXPARA, CMD_CONTROL);
|
||||
}
|
||||
|
||||
/** Start of "control channel" client handshake - this is minimal
|
||||
* @param client The client
|
||||
*/
|
||||
void start_of_control_client_handshake(Client *client)
|
||||
{
|
||||
sendto_one(client, NULL, "READY %s %s", me.name, version);
|
||||
fd_setselect(client->local->fd, FD_SELECT_READ, read_packet, client);
|
||||
}
|
||||
|
||||
CMD_FUNC(procio_status)
|
||||
{
|
||||
sendto_one(client, NULL, "REPLY servername %s", me.name);
|
||||
sendto_one(client, NULL, "REPLY unrealircd_version %s", version);
|
||||
sendto_one(client, NULL, "REPLY libssl_version %s", SSLeay_version(SSLEAY_VERSION));
|
||||
sendto_one(client, NULL, "REPLY libsodium_version %s", sodium_version_string());
|
||||
#ifdef USE_LIBCURL
|
||||
sendto_one(client, NULL, "REPLY libcurl_version %s", curl_version());
|
||||
#endif
|
||||
sendto_one(client, NULL, "REPLY libcares_version %s", ares_version(NULL));
|
||||
sendto_one(client, NULL, "REPLY libpcre2_version %s", pcre2_version());
|
||||
sendto_one(client, NULL, "REPLY global_clients %ld", (long)irccounts.clients);
|
||||
sendto_one(client, NULL, "REPLY local_clients %ld", (long)irccounts.me_clients);
|
||||
sendto_one(client, NULL, "REPLY operators %ld", (long)irccounts.operators);
|
||||
sendto_one(client, NULL, "REPLY servers %ld", (long)irccounts.servers);
|
||||
sendto_one(client, NULL, "REPLY channels %ld", (long)irccounts.channels);
|
||||
sendto_one(client, NULL, "END 0");
|
||||
}
|
||||
|
||||
extern MODVAR Module *Modules;
|
||||
CMD_FUNC(procio_modules)
|
||||
{
|
||||
char tmp[1024];
|
||||
Module *m;
|
||||
|
||||
for (m = Modules; m; m = m->next)
|
||||
{
|
||||
tmp[0] = '\0';
|
||||
if (m->flags & MODFLAG_DELAYED)
|
||||
strlcat(tmp, "[Unloading] ", sizeof(tmp));
|
||||
if (m->options & MOD_OPT_PERM_RELOADABLE)
|
||||
strlcat(tmp, "[PERM-BUT-RELOADABLE] ", sizeof(tmp));
|
||||
if (m->options & MOD_OPT_PERM)
|
||||
strlcat(tmp, "[PERM] ", sizeof(tmp));
|
||||
if (!(m->options & MOD_OPT_OFFICIAL))
|
||||
strlcat(tmp, "[3RD] ", sizeof(tmp));
|
||||
sendto_one(client, NULL, "REPLY %s %s - %s - by %s %s",
|
||||
m->header->name,
|
||||
m->header->version,
|
||||
m->header->description,
|
||||
m->header->author,
|
||||
tmp);
|
||||
}
|
||||
sendto_one(client, NULL, "END 0");
|
||||
}
|
||||
|
||||
CMD_FUNC(procio_rehash)
|
||||
{
|
||||
if (loop.rehashing)
|
||||
{
|
||||
sendto_one(client, NULL, "REPLY ERROR: A rehash is already in progress");
|
||||
sendto_one(client, NULL, "END 1");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (parv[1] && !strcmp(parv[1], "-tls"))
|
||||
{
|
||||
int ret;
|
||||
SetMonitorRehash(client);
|
||||
unreal_log(ULOG_INFO, "config", "CONFIG_RELOAD_TLS", NULL, "Reloading all TLS related data (./unrealircd reloadtls)");
|
||||
ret = reinit_tls();
|
||||
sendto_one(client, NULL, "END %d", ret == 0 ? -1 : 0);
|
||||
ClearMonitorRehash(client);
|
||||
} else {
|
||||
SetMonitorRehash(client);
|
||||
request_rehash(client);
|
||||
/* completion will go via procio_post_rehash() */
|
||||
}
|
||||
}
|
||||
|
||||
CMD_FUNC(procio_exit)
|
||||
{
|
||||
sendto_one(client, NULL, "END 0");
|
||||
exit_client(client, NULL, "");
|
||||
}
|
||||
|
||||
CMD_FUNC(procio_help)
|
||||
{
|
||||
sendto_one(client, NULL, "REPLY Commands available:");
|
||||
sendto_one(client, NULL, "REPLY EXIT");
|
||||
sendto_one(client, NULL, "REPLY HELP");
|
||||
sendto_one(client, NULL, "REPLY REHASH");
|
||||
sendto_one(client, NULL, "REPLY STATUS");
|
||||
sendto_one(client, NULL, "REPLY MODULES");
|
||||
sendto_one(client, NULL, "END 0");
|
||||
}
|
||||
|
||||
/** Called upon REHASH completion (with or without failure) */
|
||||
void procio_post_rehash(int failure)
|
||||
{
|
||||
Client *client;
|
||||
|
||||
list_for_each_entry(client, &control_list, lclient_node)
|
||||
{
|
||||
if (IsMonitorRehash(client))
|
||||
{
|
||||
sendto_one(client, NULL, "END %d", failure);
|
||||
ClearMonitorRehash(client);
|
||||
}
|
||||
}
|
||||
}
|
15
src/send.c
15
src/send.c
@ -218,7 +218,7 @@ void vsendto_one(Client *to, MessageTag *mtags, const char *pattern, va_list vl)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
|
||||
#endif
|
||||
ircvsnprintf(sendbuf, sizeof(sendbuf), pattern, vl);
|
||||
ircvsnprintf(sendbuf, sizeof(sendbuf)-3, pattern, vl);
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
@ -229,7 +229,7 @@ void vsendto_one(Client *to, MessageTag *mtags, const char *pattern, va_list vl)
|
||||
sendbufto_one(to, sendbuf, 0);
|
||||
} else {
|
||||
/* Message tags need to be prepended */
|
||||
snprintf(sendbuf2, sizeof(sendbuf2), "@%s %s", mtags_str, sendbuf);
|
||||
snprintf(sendbuf2, sizeof(sendbuf2)-3, "@%s %s", mtags_str, sendbuf);
|
||||
sendbufto_one(to, sendbuf2, 0);
|
||||
}
|
||||
}
|
||||
@ -339,10 +339,10 @@ void sendbufto_one(Client *to, char *msg, unsigned int quick)
|
||||
|
||||
if (IsMe(to))
|
||||
{
|
||||
char tmp_msg[500], *p;
|
||||
char tmp_msg[500];
|
||||
|
||||
p = strchr(msg, '\r');
|
||||
if (p) *p = '\0';
|
||||
strlcpy(tmp_msg, msg, sizeof(tmp_msg));
|
||||
stripcrlf(tmp_msg);
|
||||
unreal_log(ULOG_WARNING, "send", "SENDBUFTO_ONE_ME_MESSAGE", to,
|
||||
"Trying to send data to myself: $buf",
|
||||
log_data_string("buf", tmp_msg));
|
||||
@ -395,7 +395,10 @@ void sendbufto_one(Client *to, char *msg, unsigned int quick)
|
||||
* a bad idea, CPU-wise. So now we just mark the client indicating
|
||||
* that there is data to send.
|
||||
*/
|
||||
mark_data_to_send(to);
|
||||
if (IsControl(to))
|
||||
send_queued(to); /* send this one ASAP */
|
||||
else
|
||||
mark_data_to_send(to);
|
||||
}
|
||||
|
||||
/** A single function to send data to a channel.
|
||||
|
111
src/serv.c
111
src/serv.c
@ -716,62 +716,77 @@ CMD_FUNC(cmd_restart)
|
||||
/** Send short message of the day to the client */
|
||||
void short_motd(Client *client)
|
||||
{
|
||||
ConfigItem_tld *tld;
|
||||
MOTDFile *themotd;
|
||||
MOTDLine *motdline;
|
||||
struct tm *tm;
|
||||
char is_short;
|
||||
ConfigItem_tld *tld;
|
||||
MOTDFile *themotd;
|
||||
MOTDLine *motdline;
|
||||
struct tm *tm;
|
||||
char is_short;
|
||||
|
||||
tm = NULL;
|
||||
is_short = 1;
|
||||
tm = NULL;
|
||||
is_short = 1;
|
||||
|
||||
tld = find_tld(client);
|
||||
tld = find_tld(client);
|
||||
|
||||
/*
|
||||
/*
|
||||
* Try different sources of short MOTDs, falling back to the
|
||||
* long MOTD.
|
||||
*/
|
||||
themotd = &smotd;
|
||||
if (tld && tld->smotd.lines)
|
||||
themotd = &tld->smotd;
|
||||
*/
|
||||
themotd = &smotd;
|
||||
if (tld && tld->smotd.lines)
|
||||
themotd = &tld->smotd;
|
||||
|
||||
/* try long MOTDs */
|
||||
if (!themotd->lines)
|
||||
{
|
||||
is_short = 0;
|
||||
if (tld && tld->motd.lines)
|
||||
themotd = &tld->motd;
|
||||
else
|
||||
themotd = &motd;
|
||||
}
|
||||
/* try long MOTDs */
|
||||
if (!themotd->lines)
|
||||
{
|
||||
is_short = 0;
|
||||
if (tld && tld->motd.lines)
|
||||
themotd = &tld->motd;
|
||||
else
|
||||
themotd = &motd;
|
||||
}
|
||||
|
||||
if (!themotd->lines)
|
||||
{
|
||||
sendnumeric(client, ERR_NOMOTD);
|
||||
return;
|
||||
}
|
||||
if (themotd->last_modified.tm_year)
|
||||
{
|
||||
tm = &themotd->last_modified; /* for readability */
|
||||
sendnumeric(client, RPL_MOTDSTART, me.name);
|
||||
sendnumericfmt(client, RPL_MOTD, ":- %d/%d/%d %d:%02d", tm->tm_mday, tm->tm_mon + 1,
|
||||
1900 + tm->tm_year, tm->tm_hour, tm->tm_min);
|
||||
}
|
||||
if (is_short)
|
||||
{
|
||||
sendnumeric(client, RPL_MOTD, "This is the short MOTD. To view the complete MOTD type /motd");
|
||||
sendnumeric(client, RPL_MOTD, "");
|
||||
}
|
||||
if (!themotd->lines)
|
||||
{
|
||||
sendnumeric(client, ERR_NOMOTD);
|
||||
return;
|
||||
}
|
||||
if (themotd->last_modified.tm_year)
|
||||
{
|
||||
tm = &themotd->last_modified; /* for readability */
|
||||
sendnumeric(client, RPL_MOTDSTART, me.name);
|
||||
sendnumericfmt(client, RPL_MOTD, ":- %d/%d/%d %d:%02d", tm->tm_mday, tm->tm_mon + 1,
|
||||
1900 + tm->tm_year, tm->tm_hour, tm->tm_min);
|
||||
}
|
||||
if (is_short)
|
||||
{
|
||||
sendnumeric(client, RPL_MOTD, "This is the short MOTD. To view the complete MOTD type /motd");
|
||||
sendnumeric(client, RPL_MOTD, "");
|
||||
}
|
||||
|
||||
motdline = NULL;
|
||||
if (themotd)
|
||||
motdline = themotd->lines;
|
||||
while (motdline)
|
||||
{
|
||||
sendnumeric(client, RPL_MOTD, motdline->line);
|
||||
motdline = motdline->next;
|
||||
}
|
||||
sendnumeric(client, RPL_ENDOFMOTD);
|
||||
motdline = NULL;
|
||||
if (themotd)
|
||||
motdline = themotd->lines;
|
||||
while (motdline)
|
||||
{
|
||||
sendnumeric(client, RPL_MOTD, motdline->line);
|
||||
motdline = motdline->next;
|
||||
}
|
||||
|
||||
if (!is_short)
|
||||
{
|
||||
/* If the admin does not use a short MOTD then we append the SVSMOTD here...
|
||||
* If we did show a short motd then we don't append SVSMOTD,
|
||||
* since they want to keep it short.
|
||||
*/
|
||||
motdline = svsmotd.lines;
|
||||
while (motdline)
|
||||
{
|
||||
sendnumeric(client, RPL_MOTD, motdline->line);
|
||||
motdline = motdline->next;
|
||||
}
|
||||
}
|
||||
|
||||
sendnumeric(client, RPL_ENDOFMOTD);
|
||||
}
|
||||
|
||||
/** Read motd-like file, used for rules/motd/botmotd/opermotd/etc.
|
||||
|
378
src/socket.c
378
src/socket.c
@ -32,7 +32,7 @@ int OpenFiles = 0; /* GLOBAL - number of files currently open */
|
||||
int readcalls = 0;
|
||||
|
||||
void completed_connection(int, int, void *);
|
||||
void set_sock_opts(int, Client *, int);
|
||||
void set_sock_opts(int, Client *, SocketType);
|
||||
void set_ipv6_opts(int);
|
||||
void close_listener(ConfigItem_listen *listener);
|
||||
static char readbuf[BUFSIZE];
|
||||
@ -41,6 +41,7 @@ extern char *version;
|
||||
MODVAR time_t last_allinuse = 0;
|
||||
|
||||
void start_of_normal_client_handshake(Client *client);
|
||||
extern void start_of_control_client_handshake(Client *client);
|
||||
void proceed_normal_client_handshake(Client *client, struct hostent *he);
|
||||
|
||||
/** Close all connections - only used when we terminate the server (eg: /DIE or SIGTERM) */
|
||||
@ -72,6 +73,15 @@ void close_connections(void)
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(client, &control_list, lclient_node)
|
||||
{
|
||||
if (client->local->fd >= 0)
|
||||
{
|
||||
fd_close(client->local->fd);
|
||||
client->local->fd = -2;
|
||||
}
|
||||
}
|
||||
|
||||
close_unbound_listeners();
|
||||
|
||||
OpenFiles = 0;
|
||||
@ -101,10 +111,17 @@ static void listener_accept(int listener_fd, int revents, void *data)
|
||||
* Of course the underlying cause of this issue should be investigated, as this
|
||||
* is very much a workaround.
|
||||
*/
|
||||
unreal_log(ULOG_FATAL, "listen", "ACCEPT_ERROR", NULL, "Cannot accept incoming connection on IP \"$listen_ip\" port $listen_port: $socket_error",
|
||||
log_data_socket_error(listener->fd),
|
||||
log_data_string("listen_ip", listener->ip),
|
||||
log_data_integer("listen_port", listener->port));
|
||||
if (listener->file)
|
||||
{
|
||||
unreal_log(ULOG_FATAL, "listen", "ACCEPT_ERROR", NULL, "Cannot accept incoming connection on file $file: $socket_error",
|
||||
log_data_socket_error(listener->fd),
|
||||
log_data_string("file", listener->file));
|
||||
} else {
|
||||
unreal_log(ULOG_FATAL, "listen", "ACCEPT_ERROR", NULL, "Cannot accept incoming connection on IP \"$listen_ip\" port $listen_port: $socket_error",
|
||||
log_data_socket_error(listener->fd),
|
||||
log_data_string("listen_ip", listener->ip),
|
||||
log_data_integer("listen_port", listener->port));
|
||||
}
|
||||
close_listener(listener);
|
||||
start_listeners();
|
||||
}
|
||||
@ -113,45 +130,67 @@ static void listener_accept(int listener_fd, int revents, void *data)
|
||||
|
||||
ircstats.is_ac++;
|
||||
|
||||
set_sock_opts(cli_fd, NULL, listener->ipv6);
|
||||
set_sock_opts(cli_fd, NULL, listener->socket_type);
|
||||
|
||||
if ((++OpenFiles >= maxclients) || (cli_fd >= maxclients))
|
||||
/* Allow connections to the control socket, even if maxclients is reached */
|
||||
if (listener->options & LISTENER_CONTROL)
|
||||
{
|
||||
ircstats.is_ref++;
|
||||
if (last_allinuse < TStime() - 15)
|
||||
/* ... but not unlimited ;) */
|
||||
if ((++OpenFiles >= maxclients+(CLIENTS_RESERVE/2)) || (cli_fd >= maxclients+(CLIENTS_RESERVE/2)))
|
||||
{
|
||||
unreal_log(ULOG_FATAL, "listen", "ACCEPT_ERROR_MAXCLIENTS", NULL, "Cannot accept incoming connection on IP \"$listen_ip\" port $listen_port: All connections in use",
|
||||
log_data_string("listen_ip", listener->ip),
|
||||
log_data_integer("listen_port", listener->port));
|
||||
last_allinuse = TStime();
|
||||
ircstats.is_ref++;
|
||||
if (last_allinuse < TStime() - 15)
|
||||
{
|
||||
unreal_log(ULOG_FATAL, "listen", "ACCEPT_ERROR_MAXCLIENTS", NULL, "Cannot accept incoming connection on file $file: All connections in use",
|
||||
log_data_string("file", listener->file));
|
||||
last_allinuse = TStime();
|
||||
}
|
||||
fd_close(cli_fd);
|
||||
--OpenFiles;
|
||||
return;
|
||||
}
|
||||
} else
|
||||
{
|
||||
if ((++OpenFiles >= maxclients) || (cli_fd >= maxclients))
|
||||
{
|
||||
ircstats.is_ref++;
|
||||
if (last_allinuse < TStime() - 15)
|
||||
{
|
||||
if (listener->file)
|
||||
{
|
||||
unreal_log(ULOG_FATAL, "listen", "ACCEPT_ERROR_MAXCLIENTS", NULL, "Cannot accept incoming connection on file $file: All connections in use",
|
||||
log_data_string("file", listener->file));
|
||||
} else {
|
||||
unreal_log(ULOG_FATAL, "listen", "ACCEPT_ERROR_MAXCLIENTS", NULL, "Cannot accept incoming connection on IP \"$listen_ip\" port $listen_port: All connections in use",
|
||||
log_data_string("listen_ip", listener->ip),
|
||||
log_data_integer("listen_port", listener->port));
|
||||
}
|
||||
last_allinuse = TStime();
|
||||
}
|
||||
|
||||
(void)send(cli_fd, "ERROR :All connections in use\r\n", 31, 0);
|
||||
(void)send(cli_fd, "ERROR :All connections in use\r\n", 31, 0);
|
||||
|
||||
fd_close(cli_fd);
|
||||
--OpenFiles;
|
||||
return;
|
||||
fd_close(cli_fd);
|
||||
--OpenFiles;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* add_connection() may fail. we just don't care. */
|
||||
add_connection(listener, cli_fd);
|
||||
}
|
||||
|
||||
/** Create a listener port.
|
||||
* @param listener The listen { } block configuration
|
||||
* @param ip IP address to bind on
|
||||
* @param port Port to bind on
|
||||
* @param ipv6 IPv6 (1) or IPv4 (0)
|
||||
* @returns 0 on success and <0 on error. Yeah, confusing.
|
||||
*/
|
||||
int unreal_listen(ConfigItem_listen *listener, char *ip, int port, int ipv6)
|
||||
int unreal_listen_inet(ConfigItem_listen *listener)
|
||||
{
|
||||
const char *ip = listener->ip;
|
||||
int port = listener->port;
|
||||
|
||||
if (BadPtr(ip))
|
||||
ip = "*";
|
||||
|
||||
|
||||
if (*ip == '*')
|
||||
{
|
||||
if (ipv6)
|
||||
if (listener->socket_type == SOCKET_TYPE_IPV6)
|
||||
ip = "::";
|
||||
else
|
||||
ip = "0.0.0.0";
|
||||
@ -160,11 +199,11 @@ int unreal_listen(ConfigItem_listen *listener, char *ip, int port, int ipv6)
|
||||
/* At first, open a new socket */
|
||||
if (listener->fd >= 0)
|
||||
abort(); /* Socket already exists but we are asked to create and listen on one. Bad! */
|
||||
|
||||
|
||||
if (port == 0)
|
||||
abort(); /* Impossible as well, right? */
|
||||
|
||||
listener->fd = fd_socket(ipv6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0, "Listener socket");
|
||||
listener->fd = fd_socket(listener->socket_type == SOCKET_TYPE_IPV6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0, "Listener socket");
|
||||
if (listener->fd < 0)
|
||||
{
|
||||
unreal_log(ULOG_FATAL, "listen", "LISTEN_SOCKET_ERROR", NULL,
|
||||
@ -187,9 +226,9 @@ int unreal_listen(ConfigItem_listen *listener, char *ip, int port, int ipv6)
|
||||
return -1;
|
||||
}
|
||||
|
||||
set_sock_opts(listener->fd, NULL, ipv6);
|
||||
set_sock_opts(listener->fd, NULL, listener->socket_type);
|
||||
|
||||
if (!unreal_bind(listener->fd, ip, port, ipv6))
|
||||
if (!unreal_bind(listener->fd, ip, port, listener->socket_type))
|
||||
{
|
||||
unreal_log(ULOG_FATAL, "listen", "LISTEN_BIND_ERROR", NULL,
|
||||
"Could not listen on IP \"$listen_ip\" on port $listen_port: $socket_error",
|
||||
@ -240,23 +279,95 @@ int unreal_listen(ConfigItem_listen *listener, char *ip, int port, int ipv6)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Activate a listen { } block */
|
||||
int add_listener(ConfigItem_listen *conf)
|
||||
int unreal_listen_unix(ConfigItem_listen *listener)
|
||||
{
|
||||
if (unreal_listen(conf, conf->ip, conf->port, conf->ipv6))
|
||||
if (listener->socket_type != SOCKET_TYPE_UNIX)
|
||||
abort(); /* "impossible" */
|
||||
|
||||
/* At first, open a new socket */
|
||||
if (listener->fd >= 0)
|
||||
abort(); /* Socket already exists but we are asked to create and listen on one. Bad! */
|
||||
|
||||
listener->fd = fd_socket(AF_UNIX, SOCK_STREAM, 0, "Listener socket (UNIX)");
|
||||
if (listener->fd < 0)
|
||||
{
|
||||
/* Error is already handled upstream */
|
||||
conf->fd = -2;
|
||||
unreal_log(ULOG_FATAL, "listen", "LISTEN_SOCKET_ERROR", NULL,
|
||||
"Could not create UNIX domain socket for $file: $socket_error",
|
||||
log_data_socket_error(-1),
|
||||
log_data_string("file", listener->file));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (conf->fd >= 0)
|
||||
if (++OpenFiles >= maxclients)
|
||||
{
|
||||
conf->options |= LISTENER_BOUND;
|
||||
unreal_log(ULOG_FATAL, "listen", "LISTEN_ERROR_MAXCLIENTS", NULL,
|
||||
"Could not create UNIX domain socket for $file: all connections in use",
|
||||
log_data_string("file", listener->file));
|
||||
fd_close(listener->fd);
|
||||
listener->fd = -1;
|
||||
--OpenFiles;
|
||||
return -1;
|
||||
}
|
||||
|
||||
set_sock_opts(listener->fd, NULL, listener->socket_type);
|
||||
|
||||
if (!unreal_bind(listener->fd, listener->file, 0, SOCKET_TYPE_UNIX))
|
||||
{
|
||||
unreal_log(ULOG_FATAL, "listen", "LISTEN_BIND_ERROR", NULL,
|
||||
"Could not listen on UNIX domain socket $file: $socket_error",
|
||||
log_data_socket_error(listener->fd),
|
||||
log_data_string("file", listener->file));
|
||||
fd_close(listener->fd);
|
||||
listener->fd = -1;
|
||||
--OpenFiles;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (listen(listener->fd, LISTEN_SIZE) < 0)
|
||||
{
|
||||
unreal_log(ULOG_FATAL, "listen", "LISTEN_LISTEN_ERROR", NULL,
|
||||
"Could not listen on UNIX domain socket $file: $socket_error",
|
||||
log_data_socket_error(listener->fd),
|
||||
log_data_string("file", listener->file));
|
||||
fd_close(listener->fd);
|
||||
listener->fd = -1;
|
||||
--OpenFiles;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd_setselect(listener->fd, FD_SELECT_READ, listener_accept, listener);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Create a listener port.
|
||||
* @param listener The listen { } block configuration
|
||||
* @returns 0 on success and <0 on error. Yeah, confusing.
|
||||
*/
|
||||
int unreal_listen(ConfigItem_listen *listener)
|
||||
{
|
||||
if ((listener->socket_type == SOCKET_TYPE_IPV4) || (listener->socket_type == SOCKET_TYPE_IPV6))
|
||||
return unreal_listen_inet(listener);
|
||||
return unreal_listen_unix(listener);
|
||||
}
|
||||
|
||||
/** Activate a listen { } block */
|
||||
int add_listener(ConfigItem_listen *listener)
|
||||
{
|
||||
if (unreal_listen(listener))
|
||||
{
|
||||
/* Error is already handled upstream */
|
||||
listener->fd = -2;
|
||||
}
|
||||
|
||||
if (listener->fd >= 0)
|
||||
{
|
||||
listener->options |= LISTENER_BOUND;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
conf->fd = -1;
|
||||
listener->fd = -1;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -433,7 +544,7 @@ void consider_ident_lookup(Client *client)
|
||||
char buf[BUFSIZE];
|
||||
|
||||
/* If ident checking is disabled or it's an outgoing connect, then no ident check */
|
||||
if ((IDENT_CHECK == 0) || (client->server && IsHandshake(client)))
|
||||
if ((IDENT_CHECK == 0) || (client->server && IsHandshake(client)) || IsUnixSocket(client))
|
||||
{
|
||||
ClearIdentLookupSent(client);
|
||||
ClearIdentLookup(client);
|
||||
@ -560,37 +671,38 @@ void set_socket_buffers(int fd, int rcvbuf, int sndbuf)
|
||||
}
|
||||
|
||||
/** Set the appropriate socket options */
|
||||
void set_sock_opts(int fd, Client *client, int ipv6)
|
||||
void set_sock_opts(int fd, Client *client, SocketType socket_type)
|
||||
{
|
||||
int opt;
|
||||
|
||||
if (ipv6)
|
||||
if (socket_type == SOCKET_TYPE_IPV6)
|
||||
set_ipv6_opts(fd);
|
||||
|
||||
#ifdef SO_REUSEADDR
|
||||
opt = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt)) < 0)
|
||||
if ((socket_type == SOCKET_TYPE_IPV4) || (socket_type == SOCKET_TYPE_IPV6))
|
||||
{
|
||||
unreal_log(ULOG_WARNING, "socket", "SOCKET_ERROR_SETSOCKOPTS", client,
|
||||
"Could not setsockopt(SO_REUSEADDR): $socket_error",
|
||||
log_data_socket_error(-1));
|
||||
}
|
||||
#ifdef SO_REUSEADDR
|
||||
opt = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt)) < 0)
|
||||
{
|
||||
unreal_log(ULOG_WARNING, "socket", "SOCKET_ERROR_SETSOCKOPTS", client,
|
||||
"Could not setsockopt(SO_REUSEADDR): $socket_error",
|
||||
log_data_socket_error(-1));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SO_USELOOPBACK) && !defined(_WIN32)
|
||||
opt = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_USELOOPBACK, (void *)&opt, sizeof(opt)) < 0)
|
||||
{
|
||||
unreal_log(ULOG_WARNING, "socket", "SOCKET_ERROR_SETSOCKOPTS", client,
|
||||
"Could not setsockopt(SO_USELOOPBACK): $socket_error",
|
||||
log_data_socket_error(-1));
|
||||
}
|
||||
opt = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_USELOOPBACK, (void *)&opt, sizeof(opt)) < 0)
|
||||
{
|
||||
unreal_log(ULOG_WARNING, "socket", "SOCKET_ERROR_SETSOCKOPTS", client,
|
||||
"Could not setsockopt(SO_USELOOPBACK): $socket_error",
|
||||
log_data_socket_error(-1));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Previously we also called set_socket_buffers() to set some
|
||||
* specific buffer limits. This is no longer needed on modern OS's.
|
||||
* Setting it explicitly actually slows things down.
|
||||
*/
|
||||
}
|
||||
|
||||
/* The following code applies to all socket types: IPv4, IPv6, UNIX domain sockets */
|
||||
|
||||
/* Set to non blocking: */
|
||||
#if !defined(_WIN32)
|
||||
@ -641,7 +753,7 @@ int is_loopback_ip(char *ip)
|
||||
|
||||
for (e = conf_listen; e; e = e->next)
|
||||
{
|
||||
if ((e->options & LISTENER_BOUND) && !strcmp(ip, e->ip))
|
||||
if ((e->options & LISTENER_BOUND) && e->ip && !strcmp(ip, e->ip))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -718,15 +830,15 @@ Client *add_connection(ConfigItem_listen *listener, int fd)
|
||||
Client *client;
|
||||
const char *ip;
|
||||
int port = 0;
|
||||
|
||||
|
||||
client = make_client(NULL, &me);
|
||||
client->local->socket_type = listener->socket_type;
|
||||
|
||||
/* If listener is IPv6 then mark client (client) as IPv6 */
|
||||
if (listener->ipv6)
|
||||
SetIPV6(client);
|
||||
if (listener->socket_type == SOCKET_TYPE_UNIX)
|
||||
ip = "127.0.0.1";
|
||||
else
|
||||
ip = getpeerip(client, fd, &port);
|
||||
|
||||
ip = getpeerip(client, fd, &port);
|
||||
|
||||
if (!ip)
|
||||
{
|
||||
/* On Linux 2.4 and FreeBSD the socket may just have been disconnected
|
||||
@ -762,29 +874,38 @@ refuse_client:
|
||||
SetLocalhost(client);
|
||||
}
|
||||
|
||||
/* Check set::max-unknown-connections-per-ip */
|
||||
if (check_too_many_unknown_connections(client))
|
||||
if (!(listener->options & LISTENER_CONTROL))
|
||||
{
|
||||
ircsnprintf(zlinebuf, sizeof(zlinebuf),
|
||||
"ERROR :Closing Link: [%s] (Too many unknown connections from your IP)\r\n",
|
||||
client->ip);
|
||||
(void)send(fd, zlinebuf, strlen(zlinebuf), 0);
|
||||
goto refuse_client;
|
||||
}
|
||||
/* Check set::max-unknown-connections-per-ip */
|
||||
if (check_too_many_unknown_connections(client))
|
||||
{
|
||||
ircsnprintf(zlinebuf, sizeof(zlinebuf),
|
||||
"ERROR :Closing Link: [%s] (Too many unknown connections from your IP)\r\n",
|
||||
client->ip);
|
||||
(void)send(fd, zlinebuf, strlen(zlinebuf), 0);
|
||||
goto refuse_client;
|
||||
}
|
||||
|
||||
/* Check (G)Z-Lines and set::anti-flood::connect-flood */
|
||||
if (check_banned(client, NO_EXIT_CLIENT))
|
||||
goto refuse_client;
|
||||
/* Check (G)Z-Lines and set::anti-flood::connect-flood */
|
||||
if (check_banned(client, NO_EXIT_CLIENT))
|
||||
goto refuse_client;
|
||||
}
|
||||
|
||||
client->local->listener = listener;
|
||||
if (client->local->listener != NULL)
|
||||
client->local->listener->clients++;
|
||||
add_client_to_list(client);
|
||||
|
||||
irccounts.unknown++;
|
||||
client->status = CLIENT_STATUS_UNKNOWN;
|
||||
|
||||
list_add(&client->lclient_node, &unknown_list);
|
||||
if (!(listener->options & LISTENER_CONTROL))
|
||||
{
|
||||
/* IRC: unknown connection */
|
||||
irccounts.unknown++;
|
||||
client->status = CLIENT_STATUS_UNKNOWN;
|
||||
list_add(&client->lclient_node, &unknown_list);
|
||||
} else {
|
||||
client->status = CLIENT_STATUS_CONTROL;
|
||||
list_add(&client->lclient_node, &control_list);
|
||||
}
|
||||
|
||||
if ((listener->options & LISTENER_TLS) && ctx_server)
|
||||
{
|
||||
@ -809,7 +930,9 @@ refuse_client:
|
||||
goto refuse_client;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (listener->options & LISTENER_CONTROL)
|
||||
start_of_control_client_handshake(client);
|
||||
else
|
||||
start_of_normal_client_handshake(client);
|
||||
return client;
|
||||
@ -828,7 +951,7 @@ void start_of_normal_client_handshake(Client *client)
|
||||
|
||||
RunHook(HOOKTYPE_HANDSHAKE, client);
|
||||
|
||||
if (!DONT_RESOLVE)
|
||||
if (!DONT_RESOLVE && !IsUnixSocket(client))
|
||||
{
|
||||
if (should_show_connect_info(client))
|
||||
sendto_one(client, NULL, ":%s %s", me.name, REPORT_DO_DNS);
|
||||
@ -1027,6 +1150,20 @@ void process_clients(void)
|
||||
}
|
||||
}
|
||||
} while(&client->lclient_node != &unknown_list);
|
||||
|
||||
do {
|
||||
list_for_each_entry(client, &control_list, lclient_node)
|
||||
{
|
||||
if ((client->local->fd >= 0) && DBufLength(&client->local->recvQ) && !IsDead(client))
|
||||
{
|
||||
parse_client_queued(client);
|
||||
if (IsDead(client))
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(&client->lclient_node != &control_list);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/** Check if 'ip' is a valid IP address, and if so what type.
|
||||
@ -1038,16 +1175,16 @@ void process_clients(void)
|
||||
int is_valid_ip(const char *ip)
|
||||
{
|
||||
char scratch[64];
|
||||
|
||||
|
||||
if (BadPtr(ip))
|
||||
return 0;
|
||||
|
||||
if (inet_pton(AF_INET, ip, scratch) == 1)
|
||||
return 4; /* IPv4 */
|
||||
|
||||
|
||||
if (inet_pton(AF_INET6, ip, scratch) == 1)
|
||||
return 6; /* IPv6 */
|
||||
|
||||
|
||||
return 0; /* not an IP address */
|
||||
}
|
||||
|
||||
@ -1060,11 +1197,21 @@ int ipv6_capable(void)
|
||||
int s = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
if (s < 0)
|
||||
return 0; /* NO ipv6 */
|
||||
|
||||
|
||||
CLOSE_SOCK(s);
|
||||
return 1; /* YES */
|
||||
}
|
||||
|
||||
/** Return 1 if UNIX sockets of type SOCK_STREAM are supported, and 0 otherwise */
|
||||
int unix_sockets_capable(void)
|
||||
{
|
||||
int fd = fd_socket(AF_UNIX, SOCK_STREAM, 0, "Testing UNIX socket");
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
fd_close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Attempt to deliver data to a client.
|
||||
* This function is only called from send_queued() and will deal
|
||||
* with sending to the TLS or plaintext connection.
|
||||
@ -1156,7 +1303,7 @@ int deliver_it(Client *client, char *str, int len, int *want_read)
|
||||
int unreal_connect(int fd, const char *ip, int port, int ipv6)
|
||||
{
|
||||
int n;
|
||||
|
||||
|
||||
if (ipv6)
|
||||
{
|
||||
struct sockaddr_in6 server;
|
||||
@ -1182,25 +1329,17 @@ int unreal_connect(int fd, const char *ip, int port, int ipv6)
|
||||
{
|
||||
return 0; /* FATAL ERROR */
|
||||
}
|
||||
|
||||
|
||||
return 1; /* SUCCESS (probably still in progress) */
|
||||
}
|
||||
|
||||
/** Bind to an IP/port (port may be 0 for auto).
|
||||
* @returns 0 on failure, other on success.
|
||||
*/
|
||||
int unreal_bind(int fd, const char *ip, int port, int ipv6)
|
||||
int unreal_bind(int fd, const char *ip, int port, SocketType socket_type)
|
||||
{
|
||||
if (ipv6)
|
||||
if (socket_type == SOCKET_TYPE_IPV4)
|
||||
{
|
||||
struct sockaddr_in6 server;
|
||||
memset(&server, 0, sizeof(server));
|
||||
server.sin6_family = AF_INET6;
|
||||
server.sin6_port = htons(port);
|
||||
if (inet_pton(AF_INET6, ip, &server.sin6_addr.s6_addr) != 1)
|
||||
return 0;
|
||||
return !bind(fd, (struct sockaddr *)&server, sizeof(server));
|
||||
} else {
|
||||
struct sockaddr_in server;
|
||||
memset(&server, 0, sizeof(server));
|
||||
server.sin_family = AF_INET;
|
||||
@ -1209,4 +1348,43 @@ int unreal_bind(int fd, const char *ip, int port, int ipv6)
|
||||
return 0;
|
||||
return !bind(fd, (struct sockaddr *)&server, sizeof(server));
|
||||
}
|
||||
else if (socket_type == SOCKET_TYPE_IPV6)
|
||||
{
|
||||
struct sockaddr_in6 server;
|
||||
memset(&server, 0, sizeof(server));
|
||||
server.sin6_family = AF_INET6;
|
||||
server.sin6_port = htons(port);
|
||||
if (inet_pton(AF_INET6, ip, &server.sin6_addr.s6_addr) != 1)
|
||||
return 0;
|
||||
return !bind(fd, (struct sockaddr *)&server, sizeof(server));
|
||||
} else
|
||||
{
|
||||
struct sockaddr_un server;
|
||||
mode_t saved_umask;
|
||||
int ret;
|
||||
|
||||
unlink(ip); /* (ignore errors) */
|
||||
|
||||
memset(&server, 0, sizeof(server));
|
||||
server.sun_family = AF_UNIX;
|
||||
strlcpy(server.sun_path, ip, sizeof(server.sun_path));
|
||||
saved_umask = umask(077); // TODO: make this configurable
|
||||
ret = !bind(fd, (struct sockaddr *)&server, sizeof(server));
|
||||
umask(saved_umask);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void init_winsock(void)
|
||||
{
|
||||
WSADATA WSAData;
|
||||
if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)
|
||||
{
|
||||
MessageBox(NULL, "Unable to initialize WinSock", "UnrealIRCD Initalization Error", MB_OK);
|
||||
fprintf(stderr, "Unable to initialize WinSock\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
14
src/tls.c
14
src/tls.c
@ -512,7 +512,7 @@ int init_tls(void)
|
||||
|
||||
/** Reinitialize TLS server and client contexts - after REHASH -tls
|
||||
*/
|
||||
void reinit_tls(void)
|
||||
int reinit_tls(void)
|
||||
{
|
||||
SSL_CTX *tmp;
|
||||
ConfigItem_listen *listen;
|
||||
@ -524,7 +524,7 @@ void reinit_tls(void)
|
||||
{
|
||||
unreal_log(ULOG_ERROR, "config", "TLS_RELOAD_FAILED", NULL,
|
||||
"TLS Reload failed. See previous errors.");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (ctx_server)
|
||||
SSL_CTX_free(ctx_server);
|
||||
@ -535,7 +535,7 @@ void reinit_tls(void)
|
||||
{
|
||||
unreal_log(ULOG_ERROR, "config", "TLS_RELOAD_FAILED", NULL,
|
||||
"TLS Reload failed at client context. See previous errors.");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (ctx_client)
|
||||
SSL_CTX_free(ctx_client);
|
||||
@ -551,7 +551,7 @@ void reinit_tls(void)
|
||||
{
|
||||
unreal_log(ULOG_ERROR, "config", "TLS_RELOAD_FAILED", NULL,
|
||||
"TLS Reload failed at listen::tls-options. See previous errors.");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (listen->ssl_ctx)
|
||||
SSL_CTX_free(listen->ssl_ctx);
|
||||
@ -569,7 +569,7 @@ void reinit_tls(void)
|
||||
{
|
||||
unreal_log(ULOG_ERROR, "config", "TLS_RELOAD_FAILED", NULL,
|
||||
"TLS Reload failed at sni::tls-options. See previous errors.");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (sni->ssl_ctx)
|
||||
SSL_CTX_free(sni->ssl_ctx);
|
||||
@ -588,13 +588,15 @@ void reinit_tls(void)
|
||||
unreal_log(ULOG_ERROR, "config", "TLS_RELOAD_FAILED", NULL,
|
||||
"TLS Reload failed at link $servername due to outgoing::tls-options. See previous errors.",
|
||||
log_data_string("servername", link->servername));
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (link->ssl_ctx)
|
||||
SSL_CTX_free(link->ssl_ctx);
|
||||
link->ssl_ctx = tmp; /* activate */
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Set SSL connection as nonblocking */
|
||||
|
266
src/unrealircdctl.c
Normal file
266
src/unrealircdctl.c
Normal file
@ -0,0 +1,266 @@
|
||||
/************************************************************************
|
||||
* UnrealIRCd - Unreal Internet Relay Chat Daemon - src/unrealircdctl
|
||||
* (c) 2022- Bram Matthys and The UnrealIRCd team
|
||||
*
|
||||
* See file AUTHORS in IRC package for additional names of
|
||||
* the programmers.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* @brief UnrealIRCd Control
|
||||
*/
|
||||
#include "unrealircd.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define UNREALCMD "unrealircdctl"
|
||||
#else
|
||||
#define UNREALCMD "./unrealircd"
|
||||
#endif
|
||||
|
||||
|
||||
extern int procio_client(const char *command, int auto_color_logs);
|
||||
|
||||
void unrealircdctl_usage(const char *program_name)
|
||||
{
|
||||
printf("Usage: %s <option>\n"
|
||||
"Where <option> is one of:\n"
|
||||
"rehash - Rehash the server (reread configuration files)\n"
|
||||
"reloadtls - Reload the SSL/TLS certificates\n"
|
||||
"status - Show current status of server\n"
|
||||
"module-status - Show currently loaded modules\n"
|
||||
"mkpasswd - Hash a password\n"
|
||||
"gencloak - Display 3 random cloak keys\n"
|
||||
"spkifp - Display SPKI Fingerprint\n"
|
||||
"\n", program_name);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void unrealircdctl_rehash(void)
|
||||
{
|
||||
if (procio_client("REHASH", 1) == 0)
|
||||
{
|
||||
printf("Rehashed succesfully.\n");
|
||||
exit(0);
|
||||
}
|
||||
printf("Rehash failed.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void unrealircdctl_reloadtls(void)
|
||||
{
|
||||
if (procio_client("REHASH -tls", 1) == 0)
|
||||
{
|
||||
printf("Reloading of TLS certificates successful.\n");
|
||||
exit(0);
|
||||
}
|
||||
printf("Reloading TLS certificates failed.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void unrealircdctl_status(void)
|
||||
{
|
||||
if (procio_client("STATUS", 2) == 0)
|
||||
{
|
||||
printf("UnrealIRCd is up and running.\n");
|
||||
exit(0);
|
||||
}
|
||||
printf("UnrealIRCd status report failed.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void unrealircdctl_module_status(void)
|
||||
{
|
||||
if (procio_client("MODULES", 2) == 0)
|
||||
exit(0);
|
||||
printf("Could not retrieve complete module list.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void unrealircdctl_mkpasswd(int argc, char *argv[])
|
||||
{
|
||||
AuthenticationType type;
|
||||
const char *result;
|
||||
char *p = argv[2];
|
||||
|
||||
type = Auth_FindType(NULL, p);
|
||||
if (type == -1)
|
||||
{
|
||||
type = AUTHTYPE_ARGON2;
|
||||
} else {
|
||||
p = argv[3];
|
||||
}
|
||||
if (BadPtr(p))
|
||||
{
|
||||
#ifndef _WIN32
|
||||
p = getpass("Enter password to hash: ");
|
||||
#else
|
||||
printf("ERROR: You should specify a password to hash");
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
if ((type == AUTHTYPE_UNIXCRYPT) && (strlen(p) > 8))
|
||||
{
|
||||
/* Hmmm.. is this warning really still true (and always) ?? */
|
||||
printf("WARNING: Password truncated to 8 characters due to 'crypt' algorithm. "
|
||||
"You are suggested to use the 'argon2' algorithm instead.");
|
||||
p[8] = '\0';
|
||||
}
|
||||
if (!(result = Auth_Hash(type, p))) {
|
||||
printf("Failed to generate password. Deprecated method? Try 'argon2' instead.\n");
|
||||
exit(0);
|
||||
}
|
||||
printf("Encrypted password is: %s\n", result);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void unrealircdctl_gencloak(int argc, char *argv[])
|
||||
{
|
||||
#define GENERATE_CLOAKKEY_LEN 80 /* Length of cloak keys to generate. */
|
||||
char keyBuf[GENERATE_CLOAKKEY_LEN + 1];
|
||||
int keyNum;
|
||||
int charIndex;
|
||||
|
||||
short has_upper;
|
||||
short has_lower;
|
||||
short has_num;
|
||||
|
||||
printf("Here are 3 random cloak keys that you can copy-paste to your configuration file:\n\n");
|
||||
|
||||
printf("set {\n\tcloak-keys {\n");
|
||||
for (keyNum = 0; keyNum < 3; ++keyNum)
|
||||
{
|
||||
has_upper = 0;
|
||||
has_lower = 0;
|
||||
has_num = 0;
|
||||
|
||||
for (charIndex = 0; charIndex < sizeof(keyBuf)-1; ++charIndex)
|
||||
{
|
||||
switch (getrandom8() % 3)
|
||||
{
|
||||
case 0: /* Uppercase. */
|
||||
keyBuf[charIndex] = (char)('A' + (getrandom8() % ('Z' - 'A')));
|
||||
has_upper = 1;
|
||||
break;
|
||||
case 1: /* Lowercase. */
|
||||
keyBuf[charIndex] = (char)('a' + (getrandom8() % ('z' - 'a')));
|
||||
has_lower = 1;
|
||||
break;
|
||||
case 2: /* Digit. */
|
||||
keyBuf[charIndex] = (char)('0' + (getrandom8() % ('9' - '0')));
|
||||
has_num = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
keyBuf[sizeof(keyBuf)-1] = '\0';
|
||||
|
||||
if (has_upper && has_lower && has_num)
|
||||
printf("\t\t\"%s\";\n", keyBuf);
|
||||
else
|
||||
/* Try again. For this reason, keyNum must be signed. */
|
||||
keyNum--;
|
||||
}
|
||||
printf("\t}\n}\n\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void unrealircdctl_spkifp(int argc, char *argv[])
|
||||
{
|
||||
char *file = argv[2];
|
||||
SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
|
||||
SSL *ssl;
|
||||
X509 *cert;
|
||||
const char *spkifp;
|
||||
|
||||
if (!ctx)
|
||||
{
|
||||
printf("Internal failure while initializing SSL/TLS library context\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!file)
|
||||
{
|
||||
printf("NOTE: This script uses the default certificate location (any set::tls settings\n"
|
||||
"are ignored). If this is not what you want then specify a certificate\n"
|
||||
"explicitly like this: %s spkifp conf/tls/example.pem\n\n", UNREALCMD);
|
||||
safe_strdup(file, "tls/server.cert.pem");
|
||||
convert_to_absolute_path(&file, CONFDIR);
|
||||
}
|
||||
|
||||
if (!file_exists(file))
|
||||
{
|
||||
printf("Could not open certificate: %s\n"
|
||||
"You can specify a certificate like this: %s spkifp conf/tls/example.pem\n",
|
||||
UNREALCMD, file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (SSL_CTX_use_certificate_chain_file(ctx, file) <= 0)
|
||||
{
|
||||
printf("Could not read certificate '%s'\n", file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ssl = SSL_new(ctx);
|
||||
if (!ssl)
|
||||
{
|
||||
printf("Something went wrong when generating the SPKI fingerprint.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cert = SSL_get_certificate(ssl);
|
||||
spkifp = spki_fingerprint_ex(cert);
|
||||
printf("The SPKI fingerprint for certificate '%s' is:\n"
|
||||
"%s\n"
|
||||
"\n"
|
||||
"You normally add this password on the other side of the link as:\n"
|
||||
"password \"%s\" { spkifp; };\n"
|
||||
"\n",
|
||||
file, spkifp, spkifp);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifdef _WIN32
|
||||
chdir(".."); /* go up one level from "bin" */
|
||||
init_winsock();
|
||||
#endif
|
||||
dbuf_init();
|
||||
init_random();
|
||||
early_init_tls();
|
||||
|
||||
if (argc == 1)
|
||||
unrealircdctl_usage(argv[0]);
|
||||
|
||||
if (!strcmp(argv[1], "rehash"))
|
||||
unrealircdctl_rehash();
|
||||
else if (!strcmp(argv[1], "reloadtls"))
|
||||
unrealircdctl_reloadtls();
|
||||
else if (!strcmp(argv[1], "status"))
|
||||
unrealircdctl_status();
|
||||
else if (!strcmp(argv[1], "module-status"))
|
||||
unrealircdctl_module_status();
|
||||
else if (!strcmp(argv[1], "mkpasswd"))
|
||||
unrealircdctl_mkpasswd(argc, argv);
|
||||
else if (!strcmp(argv[1], "gencloak"))
|
||||
unrealircdctl_gencloak(argc, argv);
|
||||
else if (!strcmp(argv[1], "spkifp") || !strcmp(argv[1], "spki"))
|
||||
unrealircdctl_spkifp(argc, argv);
|
||||
else
|
||||
unrealircdctl_usage(argv[0]);
|
||||
exit(0);
|
||||
}
|
@ -1083,6 +1083,7 @@ MODVAR const char *floodoption_names[] = {
|
||||
"knock-flood",
|
||||
"max-concurrent-conversations",
|
||||
"lag-penalty",
|
||||
"vhost-flood",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -7,7 +7,7 @@ echo "Extracting src/version.c..."
|
||||
if [ -d ../.git ]; then
|
||||
SUFFIX="-$(git rev-parse --short HEAD)"
|
||||
fi
|
||||
id="6.0.1.1$SUFFIX"
|
||||
id="6.0.3$SUFFIX"
|
||||
echo "$id"
|
||||
|
||||
if test -r version.c
|
||||
|
@ -3,7 +3,7 @@
|
||||
<assemblyIdentity
|
||||
processorArchitecture="amd64"
|
||||
name="UnrealIRCd.UnrealIRCd.6"
|
||||
version="6.0.1.0"
|
||||
version="6.0.3.0"
|
||||
type="win32"
|
||||
/>
|
||||
<description>Internet Relay Chat Daemon</description>
|
||||
@ -12,7 +12,7 @@
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.1.0"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="amd64"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
|
@ -188,7 +188,6 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
|
||||
MSG msg;
|
||||
unsigned char *s;
|
||||
HWND hWnd;
|
||||
WSADATA WSAData;
|
||||
HICON hIcon;
|
||||
SC_HANDLE hService, hSCManager;
|
||||
SERVICE_TABLE_ENTRY DispatchTable[] =
|
||||
@ -250,12 +249,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
|
||||
if (!LoadLibrary("riched20.dll"))
|
||||
LoadLibrary("riched32.dll");
|
||||
InitDebug();
|
||||
|
||||
if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)
|
||||
{
|
||||
MessageBox(NULL, "Unable to initialize WinSock", "UnrealIRCD Initalization Error", MB_OK);
|
||||
return FALSE;
|
||||
}
|
||||
init_winsock();
|
||||
hInst = hInstance;
|
||||
|
||||
MainDlgBackground = CreateSolidBrush(RGB(75, 134, 238)); /* Background of main dialog */
|
||||
|
@ -90,7 +90,6 @@ VOID WINAPI IRCDCtrlHandler(DWORD opcode)
|
||||
*/
|
||||
VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv)
|
||||
{
|
||||
WSADATA WSAData;
|
||||
DWORD error = 0;
|
||||
char path[MAX_PATH], *folder;
|
||||
|
||||
@ -121,13 +120,7 @@ VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv)
|
||||
GetOSName(OSName);
|
||||
|
||||
InitDebug();
|
||||
|
||||
/* Initialize Winsocks */
|
||||
if ((error = WSAStartup(MAKEWORD(1, 1), &WSAData)) != 0)
|
||||
{
|
||||
SetServiceStop(error);
|
||||
return;
|
||||
}
|
||||
init_winsock();
|
||||
|
||||
/* Initialize the IRCd */
|
||||
if ((error = InitUnrealIRCd(dwArgc, lpszArgv)) != 1)
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
[Setup]
|
||||
AppName=UnrealIRCd 6
|
||||
AppVerName=UnrealIRCd 6.0.1.1
|
||||
AppVerName=UnrealIRCd 6.0.3
|
||||
AppPublisher=UnrealIRCd Team
|
||||
AppPublisherURL=https://www.unrealircd.org
|
||||
AppSupportURL=https://www.unrealircd.org
|
||||
@ -45,6 +45,7 @@ Name: "fixperm"; Description: "Make UnrealIRCd folder writable by current user";
|
||||
; UnrealIRCd binaries
|
||||
Source: "UnrealIRCd.exe"; DestDir: "{app}\bin"; Flags: ignoreversion signonce
|
||||
Source: "UnrealIRCd.pdb"; DestDir: "{app}\bin"; Flags: ignoreversion
|
||||
Source: "unrealircdctl.exe"; DestDir: "{app}\bin"; Flags: ignoreversion signonce
|
||||
Source: "unrealsvc.exe"; DestDir: "{app}\bin"; Flags: ignoreversion signonce
|
||||
|
||||
; TLS certificate generation helpers
|
||||
|
10
src/windows/unrealircdctl.exe.manifest
Normal file
10
src/windows/unrealircdctl.exe.manifest
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity
|
||||
processorArchitecture="amd64"
|
||||
name="UnrealIRCd.UnrealIRCd.6"
|
||||
version="6.0.1.0"
|
||||
type="win32"
|
||||
/>
|
||||
<description>UnrealIRCd - Control utility</description>
|
||||
</assembly>
|
@ -2,6 +2,7 @@
|
||||
|
||||
PID_FILE="@PIDFILE@"
|
||||
PID_BACKUP="@PIDFILE@.bak"
|
||||
UNREALIRCDCTL="@BINDIR@/unrealircdctl"
|
||||
|
||||
# When built with --with-asan, ASan does not dump core by default because
|
||||
# older gcc/clang might dump a 16TB core file. We explicitly enable it here.
|
||||
@ -87,16 +88,13 @@ elif [ "$1" = "stop" ] ; then
|
||||
kill -9 `cat $PID_FILE` 1>/dev/null 2>&1
|
||||
fi
|
||||
elif [ "$1" = "rehash" ] ; then
|
||||
echo "Rehashing UnrealIRCd"
|
||||
if [ ! -r $PID_FILE ] ; then
|
||||
echo "ERROR: UnrealIRCd is not running"
|
||||
exit 1
|
||||
fi
|
||||
kill -1 `cat $PID_FILE`
|
||||
if [ "$?" != 0 ]; then
|
||||
echo "ERROR: UnrealIRCd is not running"
|
||||
exit 1
|
||||
fi
|
||||
$UNREALIRCDCTL $*
|
||||
elif [ "$1" = "status" ] ; then
|
||||
$UNREALIRCDCTL $*
|
||||
elif [ "$1" = "module-status" ] ; then
|
||||
$UNREALIRCDCTL $*
|
||||
elif [ "$1" = "reloadtls" ] ; then
|
||||
$UNREALIRCDCTL $*
|
||||
elif [ "$1" = "restart" ] ; then
|
||||
echo "Restarting UnrealIRCd"
|
||||
$0 stop
|
||||
@ -117,23 +115,12 @@ elif [ "$1" = "configtest" ] ; then
|
||||
elif [ "$1" = "module" ] ; then
|
||||
shift
|
||||
@BINDIR@/unrealircd -m $*
|
||||
elif [ "$1" = "reloadtls" ] ; then
|
||||
echo "Reloading SSL/TLS certificates"
|
||||
if [ ! -r $PID_FILE ] ; then
|
||||
echo "ERROR: UnrealIRCd is not running"
|
||||
exit 1
|
||||
fi
|
||||
kill -USR1 `cat $PID_FILE`
|
||||
if [ "$?" != 0 ]; then
|
||||
echo "ERROR: UnrealIRCd is not running"
|
||||
exit 1
|
||||
fi
|
||||
elif [ "$1" = "mkpasswd" ] ; then
|
||||
@BINDIR@/unrealircd -P $2 $3
|
||||
$UNREALIRCDCTL $*
|
||||
elif [ "$1" = "version" ] ; then
|
||||
@BINDIR@/unrealircd -v
|
||||
elif [ "$1" = "gencloak" ] ; then
|
||||
@BINDIR@/unrealircd -k
|
||||
$UNREALIRCDCTL $*
|
||||
elif [ "$1" = "backtrace" ] ; then
|
||||
cd @TMPDIR@
|
||||
|
||||
@ -224,34 +211,7 @@ __EOF__
|
||||
echo ""
|
||||
echo "Thanks!"
|
||||
elif [ "$1" = "spki" -o "$1" = "spkifp" ] ; then
|
||||
CERT="@CONFDIR@/tls/server.cert.pem"
|
||||
if [ "$2" != "" ]; then
|
||||
CERT="$2"
|
||||
else
|
||||
echo "NOTE: This script uses the default certificate location (any set::tls settings"
|
||||
echo "are ignored). If this is not what you want then specify a certificate"
|
||||
echo "explicitly like this: ./unrealircd spkifp conf/tls/example.pem"
|
||||
echo ""
|
||||
fi
|
||||
if [ ! -f "$CERT" ]; then
|
||||
echo "Could not open certificate: $CERT"
|
||||
echo "You can specify a certificate like this: ./unrealircd spkifp conf/tls/example.pem"
|
||||
exit 1
|
||||
fi
|
||||
openssl x509 -noout -in "$CERT" -pubkey | openssl asn1parse -noout -inform pem -out @TMPDIR@/tmp.public.key
|
||||
HASH="`openssl dgst -sha256 -binary @TMPDIR@/tmp.public.key | openssl enc -base64`"
|
||||
rm -f @TMPDIR@/tmp.public.key
|
||||
if [ "$HASH" = "" ]; then
|
||||
echo "Sorry, something went wrong when generating the SPKI fingerprint."
|
||||
echo "Is the 'openssl' tool properly installed?"
|
||||
exit 1
|
||||
fi
|
||||
echo "The SPKI fingerprint for certificate $CERT is:"
|
||||
echo "$HASH"
|
||||
echo ""
|
||||
echo "You normally add this password on the other side of the link as:"
|
||||
echo "password \"$HASH\" { spkifp; };"
|
||||
echo ""
|
||||
$UNREALIRCDCTL $*
|
||||
elif [ "$1" = "hot-patch" -o "$1" = "cold-patch" ] ; then
|
||||
if [ ! -d "@BUILDDIR@" ]; then
|
||||
echo "UnrealIRCd source not found. Sorry, it is not possible to patch."
|
||||
@ -282,6 +242,11 @@ elif [ "$1" = "hot-patch" -o "$1" = "cold-patch" ] ; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! patch --dry-run -p1 -N <patch 1>/dev/null 2>&1; then
|
||||
echo "Patch failed to apply (no files changed)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! patch -p1 <patch; then
|
||||
echo "Patch failed to apply"
|
||||
exit 1
|
||||
@ -291,11 +256,18 @@ elif [ "$1" = "hot-patch" -o "$1" = "cold-patch" ] ; then
|
||||
make || gmake || exit 1
|
||||
make install || gmake install || exit 1
|
||||
|
||||
cd -
|
||||
cd @SCRIPTDIR@
|
||||
if [ "$1" = "hot-patch" ]; then
|
||||
echo "Patch applied successfully and installed. Rehashing your IRCd..."
|
||||
./unrealircd rehash
|
||||
echo "Done! All should be good now."
|
||||
if ./unrealircd rehash; then
|
||||
echo "Patch installed and server rehashed correctly. All should be good now!"
|
||||
else
|
||||
echo "Patching the source code and recompiling succeeded,"
|
||||
echo "however rehashing the current UnrealIRCd process FAILED"
|
||||
echo "so it is NOT running the patched code yet."
|
||||
echo "IMPORTANT: Check error output above!"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Patch applied successfully. You must now restart your IRC server."
|
||||
fi
|
||||
@ -316,6 +288,8 @@ else
|
||||
echo "unrealircd rehash Reload the configuration file"
|
||||
echo "unrealircd reloadtls Reload the SSL/TLS certificates"
|
||||
echo "unrealircd restart Restart the IRC Server (stop+start)"
|
||||
echo "unrealircd status Show current status of the IRC Server"
|
||||
echo "unrealircd module-status Show all currently loaded modules"
|
||||
echo "unrealircd upgrade Upgrade UnrealIRCd to the latest version"
|
||||
echo "unrealircd upgrade-conf Upgrade the configuration file from UnrealIRCd"
|
||||
echo " 3.2.x/4.x to 5.x format"
|
||||
|
Loading…
Reference in New Issue
Block a user