diff --git a/BSDmakefile b/BSDmakefile
new file mode 100644
index 0000000..f0efc9d
--- /dev/null
+++ b/BSDmakefile
@@ -0,0 +1,4 @@
+.DONE:
+ @echo "Please use GNU Make (gmake) to build UnrealIRCd"
+.DEFAULT:
+ @echo "Please use GNU Make (gmake) to build UnrealIRCd"
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..c1a2873
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,5 @@
+Help out and make UnrealIRCd a better product!
+
+You can do so by reporting issues, testing, programming, documenting,
+translating, helping others, and more.
+See https://www.unrealircd.org/docs/Contributing
diff --git a/Config b/Config
index 68a5906..8625041 100755
--- a/Config
+++ b/Config
@@ -1,7 +1,7 @@
#!/bin/sh
#
# Config script for UnrealIRCd
-# (C) 2001-2019 The UnrealIRCd Team
+# (C) 2001-2021 The UnrealIRCd Team
#
# This configure script is free software; the UnrealIRCd Team gives
# unlimited permission to copy, distribute and modify as long as the
@@ -37,9 +37,6 @@ mkdir -p $TMPDIR
mkdir -p $PRIVATELIBDIR
# Do this even if we're not in advanced mode
-if [ "$SHOWLISTMODES" = "1" ] ; then
- ARG="$ARG--with-showlistmodes "
-fi
if [ "$ADVANCED" = "1" ] ; then
if [ "$NOOPEROVERRIDE" = "1" ] ; then
ARG="$ARG--with-no-operoverride "
@@ -53,12 +50,21 @@ ARG="$ARG--enable-ssl "
else
ARG="$ARG--enable-ssl=$SSLDIR "
fi
+# Ensure we install curl even if someone does ./Config -quick...
+if [ "x$CURLDIR" = "x$UNREALCWD/extras/curl" ]; then
+ INSTALLCURL=1
+else
+ # And that the path does not refer to eg an old unrealircd-1.2.3 either ;)
+ if echo "$CURLDIR"|egrep -qi extras.*curl; then
+ echo "WARNING: Potentially old cURL directory encountered ($CURLDIR)."
+ echo "I am changing the cURL directory to $UNREALCWD/extras/curl and forcing a rebuild of cURL."
+ CURLDIR="$UNREALCWD/extras/curl"
+ INSTALLCURL=1
+ fi
+fi
if [ "$REMOTEINC" = "1" ] ; then
ARG="$ARG--enable-libcurl=$CURLDIR "
fi
-if [ "$PREFIXAQ" != "1" ]; then
-ARG="$ARG--disable-prefixaq "
-fi
if [ "$MAXCONNECTIONS_REQUEST" != "auto" ]; then
ARG="$ARG--with-maxconnections=$MAXCONNECTIONS_REQUEST "
fi
@@ -77,14 +83,19 @@ ARG="$ARG--with-scriptdir=$BASEPATH "
ARG="$ARG--with-nick-history=$NICKNAMEHISTORYLENGTH "
ARG="$ARG--with-permissions=$DEFPERM "
ARG="$ARG--enable-dynamic-linking "
+if [ "$GEOIP" = "classic" ]; then
+ ARG="$ARG--enable-geoip-classic "
+fi
+if [ "$GEOIP" = "libmaxminddb" ]; then
+ ARG="$ARG--enable-libmaxminddb "
+fi
+if [ "$SANITIZER" = "asan" ]; then
+ ARG="$ARG--enable-asan "
+fi
ARG="$ARG $EXTRAPARA "
CONF="./configure $ARG"
# remove possibly old instances of curl in ~/unrealircd/lib/
rm -f $PRIVATELIBDIR/*curl* 1>/dev/null 2>&1
-# Ensure we install curl even if someone does ./Config -quick...
-if [ "x$CURLDIR" = "x$UNREALCWD/extras/curl" ]; then
- INSTALLCURL=1
-fi
if [ "x$INSTALLCURL" = "x1" ]; then
extras/curlinstall "$PRIVATELIBDIR" || exit 1
fi
@@ -127,8 +138,8 @@ if [ "$QUICK" != "1" ] ; then
TEST="No"
fi
echo ""
- echo "UnrealIRCd requires an SSL certificate in order to work."
- echo "Do you want to generate an SSL certificate for the IRCd?"
+ echo "UnrealIRCd requires a TLS certificate in order to work."
+ echo "Do you want to generate a TLS certificate for the IRCd?"
echo "Only answer No if you already have one."
echo $n "[$TEST] -> $c"
read cc
@@ -152,60 +163,31 @@ if [ "$QUICK" != "1" ] ; then
if [ "$GENCERTIFICATE" = 1 ]; then
echo
echo "*******************************************************************************"
- echo "Next you will be asked some questions in order to generate the SSL certificate."
+ echo "Next you will be asked some questions in order to generate the TLS certificate."
echo "IMPORTANT: If you don't own a domain or don't know what to answer, then you can"
echo " simply press ENTER or use fictional names for each question!"
echo "*******************************************************************************"
echo "Press ENTER to continue"
read cc
- make pem
+ $MAKE pem
echo "Certificate created successfully."
sleep 1
else
- echo "Ok, not generating SSL certificate. Make sure that the certificate and key"
+ echo "Ok, not generating TLS certificate. Make sure that the certificate and key"
echo "are installed in conf/tls/server.cert.pem and conf/tls/server.key.pem prior to starting the IRCd."
fi
else
- echo "SSL certificate already exists in configuration directory, no need to regenerate."
+ echo "TLS certificate already exists in configuration directory, no need to regenerate."
fi
fi
# Silently force a 'make clean' as otherwise part (or whole) of the
# compiled source could be using different settings than the user
# just requested when re-running ./Config.
-make clean 1>/dev/null 2>&1
+$MAKE clean 1>/dev/null 2>&1
}
RUN_ADVANCED () {
-TEST=""
-while [ -z "$TEST" ] ; do
- if [ "$SHOWLISTMODES" = "1" ] ; then
- TEST="Yes"
- else
- TEST="No"
- fi
- echo ""
- echo "Do you want to show the modes a channel has set in the /list output?"
- echo $n "[$TEST] -> $c"
- read cc
- if [ -z "$cc" ] ; then
- cc=$TEST
- fi
- case "$cc" in
- [Yy]*)
- SHOWLISTMODES="1"
- ;;
- [Nn]*)
- SHOWLISTMODES=""
- ;;
- *)
- echo ""
- echo "You must enter either Yes or No"
- TEST=""
- ;;
- esac
-done
-
TEST=""
while [ -z "$TEST" ] ; do
if [ "$NOOPEROVERRIDE" = "1" ] ; then
@@ -271,16 +253,16 @@ UNREALCWD="`pwd`"
BASEPATH="$HOME/unrealircd"
DEFPERM="0600"
SSLDIR=""
-NICKNAMEHISTORYLENGTH="100"
+NICKNAMEHISTORYLENGTH="2000"
MAXCONNECTIONS_REQUEST="auto"
REMOTEINC="1"
CURLDIR=""
-PREFIXAQ="0"
-SHOWLISTMODES="0"
NOOPEROVERRIDE=""
OPEROVERRIDEVERIFY=""
GENCERTIFICATE="1"
EXTRAPARA=""
+SANITIZER=""
+GEOIP="classic"
if [ "`eval echo -n 'a'`" = "-n a" ] ; then
c="\c"
else
@@ -333,6 +315,33 @@ if [ "`id -u`" = "0" ]; then
exit
fi
+# Check for gmake early...
+if [ "$MAKE" = "" ]; then
+ MAKE="make"
+fi
+
+if ! $MAKE --version 2>&1|grep -q "GNU Make"; then
+ # So $MAKE is not GNU make, but do we have gmake?
+ if gmake --version 2>&1|grep -q "GNU Make"; then
+ # Great, use that one!
+ MAKE="gmake"
+ else
+ # Both $MAKE and gmake are not GNU make, do we have a working $MAKE at all?
+ if $MAKE --version 1>/dev/null 2>&1; then
+ echo "Your system has 'make' but UnrealIRCd requires GNU Make ('gmake')"
+ echo "Please install 'gmake' (eg 'pkg install gmake' on BSD)."
+ exit 1
+ else
+ echo "Your system does not have the required tools installed to build UnrealIRCd."
+ echo "Please check https://www.unrealircd.org/docs/Installing_from_source"
+ echo "and install the required tools listed under 'Prerequisites'."
+ echo "After that, you can run ./Config again"
+ exit 1
+ fi
+ fi
+fi
+
+
clear
if [ -f "doc/Config.header" -a -z "$NOINTRO" ] ; then
@@ -347,7 +356,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-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 unrealircd-5.0.5.1 unrealircd-5.0.5 unrealircd-5.0.4 unrealircd-5.0.3.1 unrealircd-5.0.3 unrealircd-5.0.2 unrealircd-5.0.1 unrealircd-5.0.0"
+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"
if [ -f "config.settings" ]; then
. ./config.settings
else
@@ -421,7 +430,7 @@ fi
TEST="$BASEPATH"
echo ""
echo "In what directory do you want to install UnrealIRCd?"
-echo "(Note: UnrealIRCd 5 will need to be installed somewhere."
+echo "(Note: UnrealIRCd 6 will need to be installed somewhere."
echo " If this directory does not exist it will be created.)"
echo $n "[$TEST] -> $c"
read cc
@@ -507,9 +516,12 @@ while [ -z "$TEST" ] ; do
TEST="No"
fi
echo ""
- echo "Do you want to enable remote includes?"
- echo "This allows stuff like this in your configuration file:"
- echo "include \"https://www.somesite.org/files/opers.conf\";"
+ echo "UnrealIRCd comes with support for 'remote includes', this allows things like:"
+ echo "include \"https://www.example.org/files/opers.conf\";"
+ echo "Do you want to compile with the libcurl library to enable additional protocols?"
+ echo "If you answer 'No' then only https:// links will work for remote includes."
+ echo "Answer 'Yes' if you need other protocols, such as plaintext http, ftp, tftp or smb."
+ echo "Most people answer 'No' here because they don't use remote includes or only need https."
echo $n "[$TEST] -> $c"
read cc
if [ -z "$cc" ] ; then
@@ -661,39 +673,6 @@ if [ "$REMOTEINC" = "1" ] ; then
fi
-TEST=""
-while [ -z "$TEST" ] ; do
- if [ "$PREFIXAQ" = "1" ] ; then
- TEST="Yes"
- else
- TEST="No"
- fi
- echo ""
- echo "Do you want to enable prefixes for chanadmin and chanowner?"
- echo "This will give +a the & prefix and ~ for +q (just like +o is @)"
- echo "Supported by the major clients (mIRC, xchat, epic, eggdrop, Klient,"
- echo "PJIRC, irssi, CGI:IRC, etc.)"
- echo "This feature should be enabled/disabled network-wide."
- echo $n "[$TEST] -> $c"
- read cc
- if [ -z "$cc" ] ; then
- cc=$TEST
- fi
- case "$cc" in
- [Yy]*)
- PREFIXAQ="1"
- ;;
- [Nn]*)
- PREFIXAQ=""
- ;;
- *)
- echo ""
- echo "You must enter either Yes or No"
- TEST=""
- ;;
- esac
-done
-
TEST=""
while [ -z "$TEST" ] ; do
TEST="$NICKNAMEHISTORYLENGTH"
@@ -717,6 +696,41 @@ while [ -z "$TEST" ] ; do
esac
done
+TEST=""
+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 " you need to install the libmaxminddb library on your system first"
+ echo " none: Don't built with any geoip feature"
+ echo "Choose one of: classic, libmaxminddb, none"
+ echo $n "[$TEST] -> $c"
+ read cc
+ if [ -z "$cc" ] ; then
+ GEOIP=$TEST
+ break
+ fi
+ case "$cc" in
+ classic)
+ GEOIP="$cc"
+ ;;
+ libmaxminddb)
+ GEOIP="$cc"
+ ;;
+ none)
+ GEOIP="$cc"
+ ;;
+ *)
+ echo ""
+ echo "Invalid choice: $cc"
+ TEST=""
+ ;;
+ esac
+done
+
echo ""
TEST=""
while [ -z "$TEST" ] ; do
@@ -753,6 +767,42 @@ if [ -n "$ADVANCED" ] ; then
RUN_ADVANCED
fi
+TEST=""
+while [ -z "$TEST" ] ; do
+ if [ "$SANITIZER" = "asan" ] ; then
+ TEST="Yes"
+ else
+ TEST="No"
+ fi
+ echo ""
+ echo "Are you running UnrealIRCd as a test, debugging a problem or developing a module?"
+ echo "Then it is possible to run with AddressSanitizer enabled. This will make it"
+ echo "catch bugs such as out-of-bounds and other memory corruption issues, which can"
+ echo "be really helpful in some cases. The downside is that it will consume a lot"
+ echo "more memory and run slower too. So, only answer 'Yes' if you are OK with this."
+ echo "Also, on some systems (notably FreeBSD), when you enable AddressSanitizer,"
+ echo "UnrealIRCd may fail to start. So when in doubt, answer 'No'."
+ echo "Do you want to enable AddressSanitizer?"
+ echo $n "[$TEST] -> $c"
+ read cc
+ if [ -z "$cc" ] ; then
+ cc=$TEST
+ fi
+ case "$cc" in
+ [Yy]*)
+ SANITIZER="asan"
+ ;;
+ [Nn]*)
+ SANITIZER=""
+ ;;
+ *)
+ echo ""
+ echo "You must enter either Yes or No"
+ TEST=""
+ ;;
+ esac
+done
+
TEST="$EXTRAPARA"
echo ""
echo "Would you like to pass any custom parameters to configure?"
@@ -784,17 +834,17 @@ CACHEDIR="$CACHEDIR"
DOCDIR="$DOCDIR"
TMPDIR="$TMPDIR"
PRIVATELIBDIR="$PRIVATELIBDIR"
-PREFIXAQ="$PREFIXAQ"
MAXCONNECTIONS_REQUEST="$MAXCONNECTIONS_REQUEST"
NICKNAMEHISTORYLENGTH="$NICKNAMEHISTORYLENGTH"
+GEOIP="$GEOIP"
DEFPERM="$DEFPERM"
SSLDIR="$SSLDIR"
REMOTEINC="$REMOTEINC"
CURLDIR="$CURLDIR"
-SHOWLISTMODES="$SHOWLISTMODES"
NOOPEROVERRIDE="$NOOPEROVERRIDE"
OPEROVERRIDEVERIFY="$OPEROVERRIDEVERIFY"
GENCERTIFICATE="$GENCERTIFICATE"
+SANITIZER="$SANITIZER"
EXTRAPARA="$EXTRAPARA"
ADVANCED="$ADVANCED"
__EOF__
@@ -808,16 +858,17 @@ cat << __EOF__
|_______________________________________________________________________|
|_______________________________________________________________________|
| |
-| Now all you have to do is type 'make' and let it compile. When that's |
-| done, you will receive other instructions on what to do next. |
-| |
-|_______________________________________________________________________|
-|_______________________________________________________________________|
| - The UnrealIRCd Team - |
| |
-| * Bram Matthys (Syzop) syzop@unrealircd.org |
-| * Gottem gottem@unrealircd.org |
-| * i i@unrealircd.org |
+| Bram Matthys (Syzop) - syzop@unrealircd.org |
+| Krzysztof Beresztant (k4be) - k4be@unrealircd.org |
+| Gottem - gottem@unrealircd.org |
+| i - i@unrealircd.org |
+|_______________________________________________________________________|
+|_______________________________________________________________________|
+| |
+| Now all you have to do is type '$MAKE' and let it compile. When that's |
+| done, you will receive other instructions on what to do next. |
|_______________________________________________________________________|
__EOF__
diff --git a/Makefile.in b/Makefile.in
index 1857495..7ce1dd2 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -34,11 +34,11 @@ FROMDOS=/home/cmunk/bin/4dos
#
#XCFLAGS=-O -g -export-dynamic
-IRCDLIBS=@IRCDLIBS@ @PCRE2_LIBS@ @ARGON2_LIBS@ @CARES_LIBS@ @SODIUM_LIBS@ @PTHREAD_LIBS@
+IRCDLIBS=@IRCDLIBS@ @PCRE2_LIBS@ @ARGON2_LIBS@ @CARES_LIBS@ @SODIUM_LIBS@ @JANSSON_LIBS@ @PTHREAD_LIBS@
CRYPTOLIB=@CRYPTOLIB@
OPENSSLINCLUDES=
-XCFLAGS=@PTHREAD_CFLAGS@ @PCRE2_CFLAGS@ @ARGON2_CFLAGS@ @CARES_CFLAGS@ @SODIUM_CFLAGS@ @CFLAGS@ @HARDEN_CFLAGS@ @CPPFLAGS@
+XCFLAGS=@PTHREAD_CFLAGS@ @PCRE2_CFLAGS@ @ARGON2_CFLAGS@ @CARES_CFLAGS@ @SODIUM_CFLAGS@ @JANSSON_CFLAGS@ @CFLAGS@ @HARDEN_CFLAGS@ @CPPFLAGS@
#
# use the following on MIPS:
#CFLAGS= -systype bsd43 -DSYSTYPE_BSD43 -I$(INCLUDEDIR)
@@ -89,7 +89,14 @@ XCFLAGS=@PTHREAD_CFLAGS@ @PCRE2_CFLAGS@ @ARGON2_CFLAGS@ @CARES_CFLAGS@ @SODIUM_C
# you are not defining CMDLINE_CONFIG
IRCDMODE = 711
+# Objects that are optional due to optional libraries:
URL=@URL@
+GEOIP_CLASSIC_OBJECTS=@GEOIP_CLASSIC_OBJECTS@
+GEOIP_CLASSIC_LIBS=@GEOIP_CLASSIC_LIBS@
+GEOIP_CLASSIC_CFLAGS=@GEOIP_CLASSIC_CFLAGS@
+GEOIP_MAXMIND_OBJECTS=@GEOIP_MAXMIND_OBJECTS@
+LIBMAXMINDDB_CFLAGS=@LIBMAXMINDDB_CFLAGS@
+LIBMAXMINDDB_LIBS=@LIBMAXMINDDB_LIBS@
# Where is your openssl binary
OPENSSLPATH=@OPENSSLPATH@
@@ -116,7 +123,13 @@ MAKEARGS = 'CFLAGS=${CFLAGS}' 'CC=${CC}' 'IRCDLIBS=${IRCDLIBS}' \
'SHELL=${SHELL}' \
'CRYPTOLIB=${CRYPTOLIB}' \
'CRYPTOINCLUDES=${CRYPTOINCLUDES}' \
- 'URL=${URL}'
+ 'URL=${URL}' \
+ 'GEOIP_CLASSIC_OBJECTS=${GEOIP_CLASSIC_OBJECTS}' \
+ 'GEOIP_CLASSIC_LIBS=${GEOIP_CLASSIC_LIBS}' \
+ 'GEOIP_CLASSIC_CFLAGS=${GEOIP_CLASSIC_CFLAGS}' \
+ 'GEOIP_MAXMIND_OBJECTS=${GEOIP_MAXMIND_OBJECTS}' \
+ 'LIBMAXMINDDB_CFLAGS=${LIBMAXMINDDB_CFLAGS}' \
+ 'LIBMAXMINDDB_LIBS=${LIBMAXMINDDB_LIBS}'
custommodule:
@if test -z "${MODULEFILE}"; then echo "Please set MODULEFILE when calling \`\`make custommodule''. For example, \`\`make custommodule MODULEFILE=callerid''." >&2; exit 1; fi
@@ -135,7 +148,7 @@ build: Makefile
done
@echo ''
@echo '* UnrealIRCd compiled successfully'
- @echo '* YOU ARE NOT DONE YET! Run "make install" to install UnrealIRCd !'
+ @echo '* YOU ARE NOT DONE YET! Run "${MAKE} install" to install UnrealIRCd !'
@echo ''
clean:
@@ -183,9 +196,6 @@ install: all
$(INSTALL) -m 0700 -d $(DESTDIR)@MODULESDIR@/chanmodes
@rm -f $(DESTDIR)@MODULESDIR@/chanmodes/*.so 1>/dev/null 2>&1
$(INSTALL) -m 0700 src/modules/chanmodes/*.so $(DESTDIR)@MODULESDIR@/chanmodes
- $(INSTALL) -m 0700 -d $(DESTDIR)@MODULESDIR@/snomasks
- @rm -f $(DESTDIR)@MODULESDIR@/snomasks/*.so 1>/dev/null 2>&1
- $(INSTALL) -m 0700 src/modules/snomasks/*.so $(DESTDIR)@MODULESDIR@/snomasks
$(INSTALL) -m 0700 -d $(DESTDIR)@MODULESDIR@/extbans
@rm -f $(DESTDIR)@MODULESDIR@/extbans/*.so 1>/dev/null 2>&1
$(INSTALL) -m 0700 src/modules/extbans/*.so $(DESTDIR)@MODULESDIR@/extbans
@@ -248,7 +258,7 @@ pem: extras/tls.cnf
-config extras/tls.cnf -sha256 -out server.req.pem \
-key server.key.pem -nodes
@echo "Generating self-signed certificate..."
- $(OPENSSLPATH) req -x509 -days 3650 -sha256 -in server.req.pem \
+ $(OPENSSLPATH) req -x509 -days 3650 -sha256 -nodes -in server.req.pem \
-key server.key.pem -out server.cert.pem
@echo "Setting permissions on server.*.pem files..."
chmod o-rwx server.req.pem server.key.pem server.cert.pem
diff --git a/Makefile.windows b/Makefile.windows
index f63f1ec..39cb1c9 100644
--- a/Makefile.windows
+++ b/Makefile.windows
@@ -25,15 +25,25 @@ MT=mt
#ARGON2LIB="Argon2RefDll.lib"
### SODIUM ###
-#SODIUM_LIB_DIR="C:\dev\unrealircd-5-libs\libsodium\......."
-#SODIUM_INC_DIR="C:\dev\unrealircd-5-libs\libsodium\......."
+#SODIUM_LIB_DIR="C:\dev\unrealircd-6-libs\libsodium\......."
+#SODIUM_INC_DIR="C:\dev\unrealircd-6-libs\libsodium\......."
#SODIUMLIB="libsodium.lib"
+### JANSSON ###
+#JANSSON_LIB_DIR="C:\dev\unrealircd-6-libs\jansson\lib"
+#JANSSON_INC_DIR="C:\dev\unrealircd-6-libs\jansson\include"
+#JANSSONLIB="jansson.lib"
+
### C-ARES ####
#CARES_LIB_DIR="C:\dev\c-ares\vc\cares\dll-release"
#CARES_INC_DIR="C:\dev\c-ares"
#CARESLIB="cares.lib"
+### GEOIP CLASSIC ###
+#GEOIPCLASSIC_LIB_DIR="c:\dev\unrealircd-6-libs\GeoIP\libGeoIP" ^
+#GEOIPCLASSIC_INC_DIR="c:\dev\unrealircd-6-libs\GeoIP\libGeoIP" ^
+#GEOIPCLASSICLIB="GeoIP.lib"
+
##### REMOTE INCLUDES ####
#To enable remote include support you must have libcurl installed on your
#system and it must have ares support enabled.
@@ -106,9 +116,16 @@ SODIUM_INC=/I "$(SODIUM_INC_DIR)"
SODIUM_LIB=/LIBPATH:"$(SODIUM_LIB_DIR)"
!ENDIF
+!IFDEF JANSSON_INC_DIR
+JANSSON_INC=/I "$(JANSSON_INC_DIR)"
+!ENDIF
+!IFDEF JANSSON_LIB_DIR
+JANSSON_LIB=/LIBPATH:"$(JANSSON_LIB_DIR)"
+!ENDIF
+
!IFDEF USE_REMOTEINC
CURLCFLAGS=/D USE_LIBCURL
-CURLOBJ=SRC/URL.OBJ
+CURLOBJ=SRC/URL_CURL.OBJ
CURLLIB=libcurl.lib
!IFDEF LIBCURL_INC_DIR
LIBCURL_INC=/I "$(LIBCURL_INC_DIR)"
@@ -137,15 +154,15 @@ DBGLFLAG=/debug
MODDBGCFLAG=/LDd /MD /Zi
!ENDIF
-STDOPTIONS=$(PCRE2_INC) $(ARGON2_INC) $(SODIUM_INC) $(CARES_INC) $(LIBCURL_INC) $(LIBRESSL_INC) /J /I ./INCLUDE /nologo \
+STDOPTIONS=$(PCRE2_INC) $(ARGON2_INC) $(SODIUM_INC) $(JANSSON_INC) $(CARES_INC) $(LIBCURL_INC) $(LIBRESSL_INC) \
+ /J /I ./INCLUDE /nologo \
$(CURLCFLAGS) /D FD_SETSIZE=16384 $(SSLCFLAGS) /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE \
/D FAKELAG_CONFIGURABLE=1 \
- /W3 /wd4267 /wd4101 /wd4018 /wd4244 /wd4996 /WX \
- /analyze:ruleset extras\VStudioAnalyze.ruleset
+ /W3 /wd4267 /wd4101 /wd4018 /wd4244 /wd4996 /WX /analyze:ruleset extras\VStudioAnalyze.ruleset
STDLIBS=$(CARES_LIB) $(CARESLIB) $(PCRE2_LIB) $(PCRE2LIB) $(ARGON2_LIB) $(ARGON2LIB) \
- $(SODIUM_LIB) $(SODIUMLIB) $(LIBRESSL_LIB) $(SSLLIB) $(LIBCURL_LIB) $(CURLLIB)
-CFLAGS=$(DBGCFLAG) $(STDOPTIONS) /c /Fosrc/
-CFLAGSST=$(DBGCFLAGST) $(STDOPTIONS) /c /Fosrc/
+ $(SODIUM_LIB) $(SODIUMLIB) $(JANSSON_LIB) $(JANSSONLIB) $(LIBRESSL_LIB) $(SSLLIB) $(LIBCURL_LIB) $(CURLLIB)
+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 \
@@ -157,203 +174,249 @@ 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 \
- SRC/FDLIST.OBJ SRC/DBUF.OBJ \
- SRC/HASH.OBJ SRC/PARSE.OBJ SRC/IRCD.OBJ \
- SRC/WHOWAS.OBJ \
- SRC/MISC.OBJ SRC/MATCH.OBJ SRC/CRULE.OBJ \
- SRC/DEBUG.OBJ SRC/SUPPORT.OBJ SRC/LIST.OBJ \
- SRC/NUMERIC.OBJ \
- SRC/SERV.OBJ SRC/USER.OBJ \
- SRC/VERSION.OBJ SRC/IRCSPRINTF.OBJ \
- SRC/SCACHE.OBJ SRC/DNS.OBJ SRC/MODULES.OBJ \
- SRC/ALIASES.OBJ SRC/API-EVENT.OBJ SRC/API-USERMODE.OBJ SRC/AUTH.OBJ SRC/TLS.OBJ \
- SRC/RANDOM.OBJ SRC/API-CHANNELMODE.OBJ SRC/API-MODDATA.OBJ SRC/MEMPOOL.OBJ \
- SRC/DISPATCH.OBJ SRC/API-ISUPPORT.OBJ SRC/API-COMMAND.OBJ \
- SRC/API-CLICAP.OBJ SRC/API-MESSAGETAG.OBJ SRC/API-HISTORY-BACKEND.OBJ \
- SRC/API-EXTBAN.OBJ SRC/API-EFUNCTIONS.OBJ SRC/CRYPT_BLOWFISH.OBJ \
- SRC/OPERCLASS.OBJ SRC/UPDCONF.OBJ SRC/CRASHREPORT.OBJ SRC/UNREALDB.OBJ \
- SRC/OPENSSL_HOSTNAME_VALIDATION.OBJ \
- SRC/UTF8.OBJ $(CURLOBJ)
+EXP_OBJ_FILES=src/channel.obj src/send.obj src/socket.obj \
+ src/conf.obj src/conf_preprocessor.obj \
+ src/fdlist.obj src/dbuf.obj \
+ src/hash.obj src/parse.obj src/ircd.obj \
+ src/whowas.obj \
+ src/misc.obj src/match.obj src/crule.obj \
+ src/debug.obj src/support.obj src/list.obj \
+ src/serv.obj src/user.obj \
+ src/version.obj src/ircsprintf.obj \
+ src/scache.obj src/dns.obj src/modules.obj \
+ src/aliases.obj src/api-event.obj src/api-usermode.obj src/auth.obj src/tls.obj \
+ src/random.obj src/api-channelmode.obj src/api-moddata.obj src/mempool.obj \
+ src/dispatch.obj src/api-isupport.obj src/api-command.obj \
+ src/api-clicap.obj src/api-messagetag.obj src/api-history-backend.obj \
+ src/api-extban.obj src/api-efunctions.obj src/crypt_blowfish.obj \
+ src/operclass.obj src/crashreport.obj src/unrealdb.obj \
+ src/openssl_hostname_validation.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
+OBJ_FILES=$(EXP_OBJ_FILES) src/gui.obj src/service.obj src/windebug.obj src/rtf.obj \
+ src/editor.obj src/win.obj
-DLL_FILES=SRC/MODULES/CLOAK.DLL \
- SRC/MODULES/CHGHOST.DLL SRC/MODULES/SDESC.DLL SRC/MODULES/SETIDENT.DLL \
- SRC/MODULES/SETNAME.DLL SRC/MODULES/SETHOST.DLL SRC/MODULES/CHGIDENT.DLL \
- SRC/MODULES/SVSMOTD.DLL SRC/MODULES/SVSNLINE.DLL SRC/MODULES/WHO_OLD.DLL \
- SRC/MODULES/WHOX.DLL \
- SRC/MODULES/SWHOIS.DLL SRC/MODULES/SVSMODE.DLL SRC/MODULES/AWAY.DLL \
- SRC/MODULES/SVSNOOP.DLL SRC/MODULES/MKPASSWD.DLL \
- SRC/MODULES/SVSNICK.DLL \
- SRC/MODULES/CHGNAME.DLL \
- SRC/MODULES/LAG.DLL SRC/MODULES/MESSAGE.DLL \
- SRC/MODULES/OPER.DLL SRC/MODULES/PINGPONG.DLL SRC/MODULES/QUIT.DLL \
- SRC/MODULES/SENDUMODE.DLL \
- SRC/MODULES/SQLINE.DLL SRC/MODULES/KILL.DLL SRC/MODULES/TSCTL.DLL \
- SRC/MODULES/UNSQLINE.DLL \
- SRC/MODULES/WHOIS.DLL SRC/MODULES/TKL.DLL SRC/MODULES/VHOST.DLL \
- SRC/MODULES/CYCLE.DLL SRC/MODULES/SVSJOIN.DLL SRC/MODULES/SVSPART.DLL \
- SRC/MODULES/SVSLUSERS.DLL SRC/MODULES/SVSWATCH.DLL SRC/MODULES/SVSSILENCE.DLL \
- SRC/MODULES/SENDSNO.DLL SRC/MODULES/SVSSNO.DLL SRC/MODULES/SAJOIN.DLL \
- SRC/MODULES/SAPART.DLL SRC/MODULES/SAMODE.DLL SRC/MODULES/KICK.DLL \
- SRC/MODULES/TOPIC.DLL SRC/MODULES/INVITE.DLL SRC/MODULES/LIST.DLL \
- SRC/MODULES/TIME.DLL SRC/MODULES/SVSKILL.DLL SRC/MODULES/KNOCK.DLL \
- SRC/MODULES/UMODE2.DLL SRC/MODULES/SQUIT.DLL SRC/MODULES/PROTOCTL.DLL \
- SRC/MODULES/SJOIN.DLL SRC/MODULES/PASS.DLL SRC/MODULES/USERHOST.DLL \
- SRC/MODULES/ISON.DLL SRC/MODULES/SILENCE.DLL \
- SRC/MODULES/ADDMOTD.DLL SRC/MODULES/ADDOMOTD.DLL SRC/MODULES/WALLOPS.DLL \
- SRC/MODULES/GLOBOPS.DLL SRC/MODULES/LOCOPS.DLL \
- SRC/MODULES/ADMIN.DLL SRC/MODULES/TRACE.DLL SRC/MODULES/NETINFO.DLL \
- SRC/MODULES/LINKS.DLL SRC/MODULES/HELP.DLL SRC/MODULES/RULES.DLL \
- SRC/MODULES/CLOSE.DLL SRC/MODULES/MAP.DLL SRC/MODULES/EOS.DLL \
- SRC/MODULES/SERVER.DLL SRC/MODULES/STATS.DLL \
- SRC/MODULES/DCCDENY.DLL SRC/MODULES/WHOWAS.DLL \
- SRC/MODULES/CONNECT.DLL SRC/MODULES/DCCALLOW.DLL SRC/MODULES/USERIP.DLL \
- SRC/MODULES/NICK.DLL SRC/MODULES/USER.DLL SRC/MODULES/MODE.DLL \
- SRC/MODULES/WATCH.DLL SRC/MODULES/PART.DLL SRC/MODULES/JOIN.DLL \
- SRC/MODULES/MOTD.DLL SRC/MODULES/OPERMOTD.DLL SRC/MODULES/BOTMOTD.DLL \
- SRC/MODULES/LUSERS.DLL SRC/MODULES/NAMES.DLL SRC/MODULES/SVSNOLAG.DLL \
- SRC/MODULES/STARTTLS.DLL \
- SRC/MODULES/WEBREDIR.DLL \
- SRC/MODULES/CAP.DLL \
- SRC/MODULES/SASL.DLL \
- SRC/MODULES/TLS_ANTIDOS.DLL \
- SRC/MODULES/MD.DLL \
- SRC/MODULES/CERTFP.DLL \
- SRC/MODULES/WEBIRC.DLL \
- SRC/MODULES/WEBSOCKET.DLL \
- SRC/MODULES/BLACKLIST.DLL \
- SRC/MODULES/JOINTHROTTLE.DLL \
- SRC/MODULES/ANTIRANDOM.DLL \
- SRC/MODULES/HIDESERVER.DLL \
- SRC/MODULES/JUMPSERVER.DLL \
- SRC/MODULES/IRCOPS.DLL \
- SRC/MODULES/STAFF.DLL \
- SRC/MODULES/NOCODES.DLL \
- SRC/MODULES/CHARSYS.DLL \
- SRC/MODULES/ANTIMIXEDUTF8.DLL \
- SRC/MODULES/AUTHPROMPT.DLL \
- SRC/MODULES/SINFO.DLL \
- SRC/MODULES/REPUTATION.DLL \
- SRC/MODULES/CONNTHROTTLE.DLL \
- SRC/MODULES/CHANMODES/CENSOR.DLL \
- SRC/MODULES/CHANMODES/DELAYJOIN.DLL \
- SRC/MODULES/CHANMODES/FLOODPROT.DLL \
- SRC/MODULES/CHANMODES/ISSECURE.DLL \
- SRC/MODULES/CHANMODES/LINK.DLL \
- SRC/MODULES/CHANMODES/NOCOLOR.DLL \
- SRC/MODULES/CHANMODES/NOCTCP.DLL \
- SRC/MODULES/CHANMODES/NOINVITE.DLL \
- SRC/MODULES/CHANMODES/NOKICK.DLL \
- SRC/MODULES/CHANMODES/NOKNOCK.DLL \
- SRC/MODULES/CHANMODES/NONICKCHANGE.DLL \
- SRC/MODULES/CHANMODES/NONOTICE.DLL \
- SRC/MODULES/CHANMODES/OPERONLY.DLL \
- SRC/MODULES/CHANMODES/PERMANENT.DLL \
- SRC/MODULES/CHANMODES/REGONLY.DLL \
- SRC/MODULES/CHANMODES/REGONLYSPEAK.DLL \
- SRC/MODULES/CHANMODES/SECUREONLY.DLL \
- SRC/MODULES/CHANMODES/STRIPCOLOR.DLL \
- SRC/MODULES/CHANMODES/HISTORY.DLL \
- SRC/MODULES/USERMODES/CENSOR.DLL \
- SRC/MODULES/USERMODES/NOCTCP.DLL \
- SRC/MODULES/USERMODES/BOT.DLL \
- SRC/MODULES/USERMODES/SERVICEBOT.DLL \
- SRC/MODULES/USERMODES/SHOWWHOIS.DLL \
- SRC/MODULES/USERMODES/PRIVACY.DLL \
- SRC/MODULES/USERMODES/NOKICK.DLL \
- SRC/MODULES/USERMODES/REGONLYMSG.DLL \
- SRC/MODULES/USERMODES/PRIVDEAF.DLL \
- SRC/MODULES/USERMODES/SECUREONLYMSG.DLL \
- SRC/MODULES/SNOMASKS/DCCREJECT.DLL \
- SRC/MODULES/EXTBANS/ACCOUNT.DLL \
- SRC/MODULES/EXTBANS/INCHANNEL.DLL \
- SRC/MODULES/EXTBANS/JOIN.DLL \
- SRC/MODULES/EXTBANS/NICKCHANGE.DLL \
- SRC/MODULES/EXTBANS/QUIET.DLL \
- SRC/MODULES/EXTBANS/REALNAME.DLL \
- SRC/MODULES/EXTBANS/OPERCLASS.DLL \
- SRC/MODULES/EXTBANS/CERTFP.DLL \
- SRC/MODULES/EXTBANS/TEXTBAN.DLL \
- SRC/MODULES/EXTBANS/MSGBYPASS.DLL \
- SRC/MODULES/EXTBANS/TIMEDBAN.DLL \
- SRC/MODULES/EXTBANS/PARTMSG.DLL \
- SRC/MODULES/EXTBANS/SECURITYGROUP.DLL \
- SRC/MODULES/ACCOUNT-NOTIFY.DLL \
- SRC/MODULES/MESSAGE-TAGS.DLL \
- SRC/MODULES/BATCH.DLL \
- SRC/MODULES/ACCOUNT-TAG.DLL \
- SRC/MODULES/LABELED-RESPONSE.DLL \
- SRC/MODULES/LINK-SECURITY.DLL \
- SRC/MODULES/MESSAGE-IDS.DLL \
- SRC/MODULES/PLAINTEXT-POLICY.DLL \
- SRC/MODULES/SERVER-TIME.DLL \
- SRC/MODULES/STS.DLL \
- SRC/MODULES/TKLDB.DLL \
- SRC/MODULES/CHANNELDB.DLL \
- SRC/MODULES/HISTORY_BACKEND_MEM.DLL \
- SRC/MODULES/HISTORY_BACKEND_NULL.DLL \
- SRC/MODULES/RESTRICT-COMMANDS.DLL \
- SRC/MODULES/RMTKL.DLL \
- SRC/MODULES/ECHO-MESSAGE.DLL \
- SRC/MODULES/USERIP-TAG.DLL \
- SRC/MODULES/USERHOST-TAG.DLL \
- SRC/MODULES/BOT-TAG.DLL \
- SRC/MODULES/REPLY-TAG.DLL \
- SRC/MODULES/REQUIRE-MODULE.DLL \
- SRC/MODULES/IDENT_LOOKUP.DLL \
- SRC/MODULES/HISTORY.DLL \
- SRC/MODULES/CHATHISTORY.DLL \
- SRC/MODULES/TARGETFLOODPROT.DLL \
- SRC/MODULES/TYPING-INDICATOR.DLL \
- SRC/MODULES/CLIENTTAGDENY.DLL
+DLL_FILES=\
+ src/modules/account-notify.dll \
+ src/modules/account-tag.dll \
+ src/modules/addmotd.dll \
+ src/modules/addomotd.dll \
+ src/modules/admin.dll \
+ src/modules/antimixedutf8.dll \
+ src/modules/antirandom.dll \
+ src/modules/authprompt.dll \
+ src/modules/away.dll \
+ src/modules/batch.dll \
+ src/modules/blacklist.dll \
+ src/modules/botmotd.dll \
+ src/modules/bot-tag.dll \
+ src/modules/cap.dll \
+ src/modules/certfp.dll \
+ src/modules/chanmodes/chanowner.dll \
+ src/modules/chanmodes/chanadmin.dll \
+ src/modules/chanmodes/chanop.dll \
+ src/modules/chanmodes/halfop.dll \
+ src/modules/chanmodes/voice.dll \
+ src/modules/chanmodes/censor.dll \
+ src/modules/chanmodes/delayjoin.dll \
+ src/modules/chanmodes/floodprot.dll \
+ src/modules/chanmodes/history.dll \
+ src/modules/chanmodes/inviteonly.dll \
+ src/modules/chanmodes/isregistered.dll \
+ src/modules/chanmodes/issecure.dll \
+ src/modules/chanmodes/key.dll \
+ src/modules/chanmodes/limit.dll \
+ src/modules/chanmodes/link.dll \
+ src/modules/chanmodes/moderated.dll \
+ src/modules/chanmodes/nocolor.dll \
+ src/modules/chanmodes/noctcp.dll \
+ src/modules/chanmodes/noexternalmsgs.dll \
+ src/modules/chanmodes/noinvite.dll \
+ src/modules/chanmodes/nokick.dll \
+ src/modules/chanmodes/noknock.dll \
+ src/modules/chanmodes/nonickchange.dll \
+ src/modules/chanmodes/nonotice.dll \
+ src/modules/chanmodes/operonly.dll \
+ src/modules/chanmodes/permanent.dll \
+ src/modules/chanmodes/private.dll \
+ src/modules/chanmodes/regonly.dll \
+ src/modules/chanmodes/regonlyspeak.dll \
+ src/modules/chanmodes/secret.dll \
+ src/modules/chanmodes/secureonly.dll \
+ src/modules/chanmodes/stripcolor.dll \
+ src/modules/chanmodes/topiclimit.dll \
+ src/modules/channeldb.dll \
+ src/modules/charsys.dll \
+ src/modules/chathistory.dll \
+ src/modules/chghost.dll \
+ src/modules/chgident.dll \
+ src/modules/chgname.dll \
+ src/modules/clienttagdeny.dll \
+ src/modules/close.dll \
+ src/modules/connect.dll \
+ src/modules/connthrottle.dll \
+ src/modules/cycle.dll \
+ src/modules/dccallow.dll \
+ src/modules/dccdeny.dll \
+ src/modules/echo-message.dll \
+ src/modules/eos.dll \
+ src/modules/extbans/account.dll \
+ src/modules/extbans/certfp.dll \
+ src/modules/extbans/country.dll \
+ src/modules/extbans/inchannel.dll \
+ src/modules/extbans/join.dll \
+ src/modules/extbans/msgbypass.dll \
+ src/modules/extbans/nickchange.dll \
+ src/modules/extbans/operclass.dll \
+ src/modules/extbans/partmsg.dll \
+ src/modules/extbans/quiet.dll \
+ src/modules/extbans/realname.dll \
+ src/modules/extbans/securitygroup.dll \
+ src/modules/extbans/textban.dll \
+ src/modules/extbans/timedban.dll \
+ src/modules/extended-monitor.dll \
+ src/modules/extjwt.dll \
+ src/modules/geoip_base.dll \
+ src/modules/geoip_classic.dll \
+ src/modules/geoip_csv.dll \
+ src/modules/globops.dll \
+ src/modules/help.dll \
+ src/modules/hideserver.dll \
+ src/modules/history_backend_mem.dll \
+ src/modules/history_backend_null.dll \
+ src/modules/history.dll \
+ src/modules/ident_lookup.dll \
+ src/modules/invite.dll \
+ src/modules/ircops.dll \
+ src/modules/ison.dll \
+ src/modules/join.dll \
+ src/modules/jointhrottle.dll \
+ src/modules/json-log-tag.dll \
+ src/modules/jumpserver.dll \
+ src/modules/kick.dll \
+ src/modules/kill.dll \
+ src/modules/knock.dll \
+ src/modules/labeled-response.dll \
+ src/modules/lag.dll \
+ src/modules/links.dll \
+ src/modules/link-security.dll \
+ src/modules/list.dll \
+ src/modules/locops.dll \
+ src/modules/lusers.dll \
+ src/modules/map.dll \
+ src/modules/md.dll \
+ src/modules/message.dll \
+ src/modules/message-ids.dll \
+ src/modules/message-tags.dll \
+ src/modules/mkpasswd.dll \
+ src/modules/mode.dll \
+ src/modules/monitor.dll \
+ src/modules/motd.dll \
+ src/modules/names.dll \
+ src/modules/netinfo.dll \
+ src/modules/nick.dll \
+ src/modules/nocodes.dll \
+ src/modules/cloak_md5.dll \
+ src/modules/cloak_none.dll \
+ src/modules/cloak_sha256.dll \
+ src/modules/oper.dll \
+ src/modules/operinfo.dll \
+ src/modules/opermotd.dll \
+ src/modules/part.dll \
+ src/modules/pass.dll \
+ src/modules/pingpong.dll \
+ src/modules/plaintext-policy.dll \
+ src/modules/protoctl.dll \
+ src/modules/quit.dll \
+ src/modules/reply-tag.dll \
+ src/modules/reputation.dll \
+ src/modules/require-module.dll \
+ src/modules/restrict-commands.dll \
+ src/modules/rmtkl.dll \
+ src/modules/rules.dll \
+ src/modules/sajoin.dll \
+ src/modules/samode.dll \
+ src/modules/sapart.dll \
+ src/modules/sasl.dll \
+ src/modules/sdesc.dll \
+ src/modules/sendsno.dll \
+ src/modules/sendumode.dll \
+ src/modules/server.dll \
+ src/modules/server-time.dll \
+ src/modules/sethost.dll \
+ src/modules/setident.dll \
+ src/modules/setname.dll \
+ src/modules/silence.dll \
+ src/modules/sinfo.dll \
+ src/modules/sjoin.dll \
+ src/modules/slog.dll \
+ src/modules/sqline.dll \
+ src/modules/squit.dll \
+ src/modules/staff.dll \
+ src/modules/starttls.dll \
+ src/modules/stats.dll \
+ src/modules/sts.dll \
+ src/modules/svsjoin.dll \
+ src/modules/svskill.dll \
+ src/modules/svslusers.dll \
+ src/modules/svsmode.dll \
+ src/modules/svsmotd.dll \
+ src/modules/svsnick.dll \
+ src/modules/svsnline.dll \
+ src/modules/svsnolag.dll \
+ src/modules/svsnoop.dll \
+ src/modules/svspart.dll \
+ src/modules/svssilence.dll \
+ src/modules/svssno.dll \
+ src/modules/svswatch.dll \
+ src/modules/swhois.dll \
+ src/modules/targetfloodprot.dll \
+ src/modules/time.dll \
+ src/modules/tkl.dll \
+ src/modules/tkldb.dll \
+ src/modules/tls_antidos.dll \
+ src/modules/tls_cipher.dll \
+ src/modules/topic.dll \
+ src/modules/trace.dll \
+ src/modules/tsctl.dll \
+ src/modules/typing-indicator.dll \
+ src/modules/umode2.dll \
+ src/modules/unreal_server_compat.dll \
+ src/modules/unsqline.dll \
+ src/modules/user.dll \
+ src/modules/userhost.dll \
+ src/modules/userhost-tag.dll \
+ src/modules/userip.dll \
+ src/modules/userip-tag.dll \
+ src/modules/usermodes/bot.dll \
+ src/modules/usermodes/censor.dll \
+ src/modules/usermodes/noctcp.dll \
+ src/modules/usermodes/nokick.dll \
+ src/modules/usermodes/privacy.dll \
+ src/modules/usermodes/privdeaf.dll \
+ src/modules/usermodes/regonlymsg.dll \
+ src/modules/usermodes/secureonlymsg.dll \
+ src/modules/usermodes/servicebot.dll \
+ src/modules/usermodes/showwhois.dll \
+ src/modules/usermodes/wallops.dll \
+ src/modules/vhost.dll \
+ src/modules/watch-backend.dll \
+ src/modules/watch.dll \
+ src/modules/webirc.dll \
+ src/modules/webredir.dll \
+ src/modules/websocket.dll \
+ src/modules/whois.dll \
+ src/modules/who_old.dll \
+ src/modules/whowas.dll \
+ src/modules/whox.dll
ALL: CONF UNREALSVC.EXE UnrealIRCd.exe MODULES
CLEAN:
- -@erase *.obj >NUL
- -@erase src\*.obj >NUL
- -@erase src\win.res >NUL
- -@erase src\version.c >NUL
- -@erase src\windows\*.obj >NUL
- -@erase src\modules\*.obj >NUL
- -@erase src\modules\*.lib >NUL
- -@erase src\modules\*.pdb >NUL
- -@erase src\modules\*.dll >NUL
- -@erase src\modules\*.exp >NUL
- -@erase src\modules\*.ilk >NUL
- -@erase src\modules\chanmodes\*.obj >NUL
- -@erase src\modules\chanmodes\*.lib >NUL
- -@erase src\modules\chanmodes\*.pdb >NUL
- -@erase src\modules\chanmodes\*.dll >NUL
- -@erase src\modules\chanmodes\*.exp >NUL
- -@erase src\modules\chanmodes\*.ilk >NUL
- -@erase src\modules\usermodes\*.obj >NUL
- -@erase src\modules\usermodes\*.lib >NUL
- -@erase src\modules\usermodes\*.pdb >NUL
- -@erase src\modules\usermodes\*.dll >NUL
- -@erase src\modules\usermodes\*.exp >NUL
- -@erase src\modules\usermodes\*.ilk >NUL
- -@erase src\modules\snomasks\*.obj >NUL
- -@erase src\modules\snomasks\*.lib >NUL
- -@erase src\modules\snomasks\*.pdb >NUL
- -@erase src\modules\snomasks\*.dll >NUL
- -@erase src\modules\snomasks\*.exp >NUL
- -@erase src\modules\snomasks\*.ilk >NUL
- -@erase src\modules\extbans\*.obj >NUL
- -@erase src\modules\extbans\*.lib >NUL
- -@erase src\modules\extbans\*.pdb >NUL
- -@erase src\modules\extbans\*.dll >NUL
- -@erase src\modules\extbans\*.exp >NUL
- -@erase src\modules\extbans\*.ilk >NUL
- -@erase .\*.exe >NUL
- -@erase UnrealIRCd.lib >NUL
+ -@del /Q /S *.dll *.exe *.obj *.pdb *.res *.lib *.exp *.ilk src\version.c >NUL
-./UNREALSVC.EXE: SRC/UNREALSVC.OBJ SRC/WINDOWS/UNREALSVC.RES
+UNREALSVC.EXE: SRC/UNREALSVC.OBJ SRC/WINDOWS/UNREALSVC.RES
$(LINK) $(DBGLFLAGST) advapi32.lib src/unrealsvc.obj src/windows/unrealsvc.res
CONF:
@@ -361,9 +424,7 @@ CONF:
$(CC) src/windows/config.c
-@config.exe
-
-
-./UnrealIRCd.exe: $(OBJ_FILES) src/windows/win.res
+UnrealIRCd.exe: $(OBJ_FILES) src/windows/win.res
$(LINK) $(LFLAGS) $(OBJ_FILES) src/windows/win.res /MAP
-@erase src\windows\win.res
$(MT) -manifest src\windows\UnrealIRCd.exe.manifest -outputresource:UnrealIRCd.exe;1
@@ -430,9 +491,6 @@ src/conf_preprocessor.obj: src/conf_preprocessor.c $(INCLUDES)
src/debug.obj: src/debug.c $(INCLUDES)
$(CC) $(CFLAGS) src/debug.c
-src/numeric.obj: src/numeric.c $(INCLUDES)
- $(CC) $(CFLAGS) src/numeric.c
-
src/misc.obj: src/misc.c $(INCLUDES) ./include/dbuf.h
$(CC) $(CFLAGS) src/misc.c
@@ -509,8 +567,8 @@ src/mempool.obj: src/mempool.c $(INCLUDES)
src/dispatch.obj: src/dispatch.c $(INCLUDES)
$(CC) $(CFLAGS) src/dispatch.c
-src/url.obj: src/url.c $(INCLUDES) ./include/url.h
- $(CC) $(CFLAGS) src/url.c
+src/url_curl.obj: src/url_curl.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/url_curl.c
src/api-extban.obj: src/api-extban.c $(INCLUDES)
$(CC) $(CFLAGS) src/api-extban.c
@@ -542,9 +600,6 @@ src/crypt_blowfish.obj: src/crypt_blowfish.c $(INCLUDES)
src/operclass.obj: src/operclass.c $(INCLUDES) ./include/dbuf.h
$(CC) $(CFLAGS) src/operclass.c
-src/updconf.obj: src/updconf.c $(INCLUDES) ./include/dbuf.h
- $(CC) $(CFLAGS) src/updconf.c
-
src/crashreport.obj: src/crashreport.c $(INCLUDES) ./include/dbuf.h
$(CC) $(CFLAGS) src/crashreport.c
@@ -554,6 +609,12 @@ src/unrealdb.obj: src/unrealdb.c $(INCLUDES) ./include/dbuf.h
src/utf8.obj: src/utf8.c $(INCLUDES) ./include/dbuf.h
$(CC) $(CFLAGS) src/utf8.c
+src/openssl_hostname_validation.obj: src/openssl_hostname_validation.c $(INCLUDES) ./include/dbuf.h
+ $(CC) $(CFLAGS) src/openssl_hostname_validation.c
+
+src/log.obj: src/log.c $(INCLUDES) ./include/dbuf.h
+ $(CC) $(CFLAGS) src/log.c
+
src/windows/win.res: src/windows/wingui.rc
$(RC) /l 0x409 /fosrc/windows/win.res /i ./include /i ./src \
/d NDEBUG src/windows/wingui.rc
@@ -575,556 +636,642 @@ SYMBOLFILE:
MODULES: $(DLL_FILES)
-src/modules/cloak.dll: src/modules/cloak.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/cloak.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/chghost.dll: src/modules/chghost.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/chghost.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/chgident.dll: src/modules/chgident.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/chgident.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/sdesc.dll: src/modules/sdesc.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/sdesc.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/sethost.dll: src/modules/sethost.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/sethost.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/setident.dll: src/modules/setident.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/setident.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/setname.dll: src/modules/setname.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/setname.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/svsmotd.dll: src/modules/svsmotd.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/svsmotd.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/svsmode.dll: src/modules/svsmode.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/svsmode.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/tkl.dll: src/modules/tkl.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/tkl.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/swhois.dll: src/modules/swhois.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/swhois.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/svsnline.dll: src/modules/svsnline.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/svsnline.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/who_old.dll: src/modules/who_old.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/who_old.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/whox.dll: src/modules/whox.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/whox.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/away.dll: src/modules/away.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/away.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/mkpasswd.dll: src/modules/mkpasswd.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/mkpasswd.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/svsnoop.dll: src/modules/svsnoop.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/svsnoop.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/svsnick.dll: src/modules/svsnick.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/svsnick.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/chgname.dll: src/modules/chgname.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/chgname.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/kill.dll: src/modules/kill.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/kill.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/lag.dll: src/modules/lag.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/lag.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/message.dll: src/modules/message.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/message.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/oper.dll: src/modules/oper.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/oper.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/pingpong.dll: src/modules/pingpong.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/pingpong.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/quit.dll: src/modules/quit.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/quit.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/sendumode.dll: src/modules/sendumode.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/sendumode.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/sqline.dll: src/modules/sqline.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/sqline.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/tsctl.dll: src/modules/tsctl.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/tsctl.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/unsqline.dll: src/modules/unsqline.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/unsqline.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/whois.dll: src/modules/whois.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/whois.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/vhost.dll: src/modules/vhost.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/vhost.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/cycle.dll: src/modules/cycle.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/cycle.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/svsjoin.dll: src/modules/svsjoin.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/svsjoin.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/svspart.dll: src/modules/svspart.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/svspart.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/svslusers.dll: src/modules/svslusers.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/svslusers.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/svswatch.dll: src/modules/svswatch.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/svswatch.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/svssilence.dll: src/modules/svssilence.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/svssilence.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/sendsno.dll: src/modules/sendsno.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/sendsno.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/svssno.dll: src/modules/svssno.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/svssno.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/sajoin.dll: src/modules/sajoin.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/sajoin.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/sapart.dll: src/modules/sapart.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/sapart.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/samode.dll: src/modules/samode.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/samode.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/kick.dll: src/modules/kick.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/kick.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/topic.dll: src/modules/topic.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/topic.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/invite.dll: src/modules/invite.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/invite.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/list.dll: src/modules/list.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/list.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/time.dll: src/modules/time.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/time.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/svskill.dll: src/modules/svskill.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/svskill.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/sjoin.dll: src/modules/sjoin.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/sjoin.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/pass.dll: src/modules/pass.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/pass.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/userhost.dll: src/modules/userhost.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/userhost.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/ison.dll: src/modules/ison.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/ison.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/silence.dll: src/modules/silence.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/silence.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/knock.dll: src/modules/knock.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/knock.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/umode2.dll: src/modules/umode2.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/umode2.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/squit.dll: src/modules/squit.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/squit.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/protoctl.dll: src/modules/protoctl.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/protoctl.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/addmotd.dll: src/modules/addmotd.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/addmotd.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/addomotd.dll: src/modules/addomotd.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/addomotd.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/wallops.dll: src/modules/wallops.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/wallops.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/admin.dll: src/modules/admin.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/admin.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/globops.dll: src/modules/globops.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/globops.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/locops.dll: src/modules/locops.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/locops.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/trace.dll: src/modules/trace.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/trace.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/netinfo.dll: src/modules/netinfo.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/netinfo.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/links.dll: src/modules/links.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/links.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/help.dll: src/modules/help.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/help.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/rules.dll: src/modules/rules.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/rules.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/close.dll: src/modules/close.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/close.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/map.dll: src/modules/map.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/map.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/eos.dll: src/modules/eos.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/eos.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/server.dll: src/modules/server.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/server.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/stats.dll: src/modules/stats.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/stats.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/dccdeny.dll: src/modules/dccdeny.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/dccdeny.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/whowas.dll: src/modules/whowas.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/whowas.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/connect.dll: src/modules/connect.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/connect.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/dccallow.dll: src/modules/dccallow.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/dccallow.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/userip.dll: src/modules/userip.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/userip.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/nick.dll: src/modules/nick.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/nick.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/user.dll: src/modules/user.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/user.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/mode.dll: src/modules/mode.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/mode.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/watch.dll: src/modules/watch.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/watch.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/part.dll: src/modules/part.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/part.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/join.dll: src/modules/join.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/join.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/motd.dll: src/modules/motd.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/motd.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/opermotd.dll: src/modules/opermotd.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/opermotd.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/botmotd.dll: src/modules/botmotd.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/botmotd.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/lusers.dll: src/modules/lusers.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/lusers.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/names.dll: src/modules/names.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/names.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/md.dll: src/modules/md.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/md.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/certfp.dll: src/modules/certfp.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/certfp.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/webirc.dll: src/modules/webirc.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/webirc.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/websocket.dll: src/modules/websocket.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/websocket.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/blacklist.dll: src/modules/blacklist.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/blacklist.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/jointhrottle.dll: src/modules/jointhrottle.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/jointhrottle.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/svsnolag.dll: src/modules/svsnolag.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/svsnolag.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/starttls.dll: src/modules/starttls.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/starttls.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/webredir.dll: src/modules/webredir.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/webredir.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/cap.dll: src/modules/cap.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/cap.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/sasl.dll: src/modules/sasl.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/sasl.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/tls_antidos.dll: src/modules/tls_antidos.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/tls_antidos.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/antirandom.dll: src/modules/antirandom.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/antirandom.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/hideserver.dll: src/modules/hideserver.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/hideserver.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/jumpserver.dll: src/modules/jumpserver.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/jumpserver.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/ircops.dll: src/modules/ircops.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/ircops.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/staff.dll: src/modules/staff.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/staff.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/nocodes.dll: src/modules/nocodes.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/nocodes.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/charsys.dll: src/modules/charsys.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/charsys.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/antimixedutf8.dll: src/modules/antimixedutf8.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/antimixedutf8.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/authprompt.dll: src/modules/authprompt.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/authprompt.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/sinfo.dll: src/modules/sinfo.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/sinfo.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/reputation.dll: src/modules/reputation.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/reputation.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/connthrottle.dll: src/modules/connthrottle.c $(INCLUDES)
- $(CC) $(MODCFLAGS) src/modules/connthrottle.c /Fesrc/modules/ /Fosrc/modules/ $(MODLFLAGS)
-
-src/modules/chanmodes/censor.dll: src/modules/chanmodes/censor.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/chanmodes/ /Fesrc/modules/chanmodes/ src/modules/chanmodes/censor.c $(MODLFLAGS)
-
-src/modules/chanmodes/delayjoin.dll: src/modules/chanmodes/delayjoin.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/chanmodes/ /Fesrc/modules/chanmodes/ src/modules/chanmodes/delayjoin.c $(MODLFLAGS)
-
-src/modules/chanmodes/floodprot.dll: src/modules/chanmodes/floodprot.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/chanmodes/ /Fesrc/modules/chanmodes/ src/modules/chanmodes/floodprot.c $(MODLFLAGS)
-
-src/modules/chanmodes/issecure.dll: src/modules/chanmodes/issecure.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/chanmodes/ /Fesrc/modules/chanmodes/ src/modules/chanmodes/issecure.c $(MODLFLAGS)
-
-src/modules/chanmodes/link.dll: src/modules/chanmodes/link.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/chanmodes/ /Fesrc/modules/chanmodes/ src/modules/chanmodes/link.c $(MODLFLAGS)
-
-src/modules/chanmodes/nocolor.dll: src/modules/chanmodes/nocolor.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/chanmodes/ /Fesrc/modules/chanmodes/ src/modules/chanmodes/nocolor.c $(MODLFLAGS)
-
-src/modules/chanmodes/noctcp.dll: src/modules/chanmodes/noctcp.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/chanmodes/ /Fesrc/modules/chanmodes/ src/modules/chanmodes/noctcp.c $(MODLFLAGS)
-
-src/modules/chanmodes/noinvite.dll: src/modules/chanmodes/noinvite.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/chanmodes/ /Fesrc/modules/chanmodes/ src/modules/chanmodes/noinvite.c $(MODLFLAGS)
-
-src/modules/chanmodes/nokick.dll: src/modules/chanmodes/nokick.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/chanmodes/ /Fesrc/modules/chanmodes/ src/modules/chanmodes/nokick.c $(MODLFLAGS)
-
-src/modules/chanmodes/noknock.dll: src/modules/chanmodes/noknock.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/chanmodes/ /Fesrc/modules/chanmodes/ src/modules/chanmodes/noknock.c $(MODLFLAGS)
-
-src/modules/chanmodes/nonickchange.dll: src/modules/chanmodes/nonickchange.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/chanmodes/ /Fesrc/modules/chanmodes/ src/modules/chanmodes/nonickchange.c $(MODLFLAGS)
-
-src/modules/chanmodes/nonotice.dll: src/modules/chanmodes/nonotice.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/chanmodes/ /Fesrc/modules/chanmodes/ src/modules/chanmodes/nonotice.c $(MODLFLAGS)
-
-src/modules/chanmodes/operonly.dll: src/modules/chanmodes/operonly.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/chanmodes/ /Fesrc/modules/chanmodes/ src/modules/chanmodes/operonly.c $(MODLFLAGS)
-
-src/modules/chanmodes/permanent.dll: src/modules/chanmodes/permanent.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/chanmodes/ /Fesrc/modules/chanmodes/ src/modules/chanmodes/permanent.c $(MODLFLAGS)
-
-src/modules/chanmodes/regonly.dll: src/modules/chanmodes/regonly.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/chanmodes/ /Fesrc/modules/chanmodes/ src/modules/chanmodes/regonly.c $(MODLFLAGS)
-
-src/modules/chanmodes/regonlyspeak.dll: src/modules/chanmodes/regonlyspeak.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/chanmodes/ /Fesrc/modules/chanmodes/ src/modules/chanmodes/regonlyspeak.c $(MODLFLAGS)
-
-src/modules/chanmodes/secureonly.dll: src/modules/chanmodes/secureonly.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/chanmodes/ /Fesrc/modules/chanmodes/ src/modules/chanmodes/secureonly.c $(MODLFLAGS)
-
-src/modules/chanmodes/stripcolor.dll: src/modules/chanmodes/stripcolor.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/chanmodes/ /Fesrc/modules/chanmodes/ src/modules/chanmodes/stripcolor.c $(MODLFLAGS)
-
-src/modules/chanmodes/history.dll: src/modules/chanmodes/history.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/chanmodes/ /Fesrc/modules/chanmodes/ src/modules/chanmodes/history.c $(MODLFLAGS)
-
-src/modules/usermodes/censor.dll: src/modules/usermodes/censor.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/usermodes/ /Fesrc/modules/usermodes/ src/modules/usermodes/censor.c $(MODLFLAGS)
-
-src/modules/usermodes/noctcp.dll: src/modules/usermodes/noctcp.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/usermodes/ /Fesrc/modules/usermodes/ src/modules/usermodes/noctcp.c $(MODLFLAGS)
-
-src/modules/usermodes/bot.dll: src/modules/usermodes/bot.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/usermodes/ /Fesrc/modules/usermodes/ src/modules/usermodes/bot.c $(MODLFLAGS)
-
-src/modules/usermodes/servicebot.dll: src/modules/usermodes/servicebot.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/usermodes/ /Fesrc/modules/usermodes/ src/modules/usermodes/servicebot.c $(MODLFLAGS)
-
-src/modules/usermodes/showwhois.dll: src/modules/usermodes/showwhois.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/usermodes/ /Fesrc/modules/usermodes/ src/modules/usermodes/showwhois.c $(MODLFLAGS)
-
-src/modules/usermodes/privacy.dll: src/modules/usermodes/privacy.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/usermodes/ /Fesrc/modules/usermodes/ src/modules/usermodes/privacy.c $(MODLFLAGS)
-
-src/modules/usermodes/nokick.dll: src/modules/usermodes/nokick.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/usermodes/ /Fesrc/modules/usermodes/ src/modules/usermodes/nokick.c $(MODLFLAGS)
-
-src/modules/usermodes/regonlymsg.dll: src/modules/usermodes/regonlymsg.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/usermodes/ /Fesrc/modules/usermodes/ src/modules/usermodes/regonlymsg.c $(MODLFLAGS)
-
-src/modules/usermodes/privdeaf.dll: src/modules/usermodes/privdeaf.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/usermodes/ /Fesrc/modules/usermodes/ src/modules/usermodes/privdeaf.c $(MODLFLAGS)
-
-src/modules/usermodes/secureonlymsg.dll: src/modules/usermodes/secureonlymsg.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/usermodes/ /Fesrc/modules/usermodes/ src/modules/usermodes/secureonlymsg.c $(MODLFLAGS)
-
-src/modules/snomasks/dccreject.dll: src/modules/snomasks/dccreject.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/snomasks/ /Fesrc/modules/snomasks/ src/modules/snomasks/dccreject.c $(MODLFLAGS)
-
-src/modules/extbans/account.dll: src/modules/extbans/account.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/extbans/ /Fesrc/modules/extbans/ src/modules/extbans/account.c $(MODLFLAGS)
-
-src/modules/extbans/inchannel.dll: src/modules/extbans/inchannel.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/extbans/ /Fesrc/modules/extbans/ src/modules/extbans/inchannel.c $(MODLFLAGS)
-
-src/modules/extbans/join.dll: src/modules/extbans/join.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/extbans/ /Fesrc/modules/extbans/ src/modules/extbans/join.c $(MODLFLAGS)
-
-src/modules/extbans/nickchange.dll: src/modules/extbans/nickchange.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/extbans/ /Fesrc/modules/extbans/ src/modules/extbans/nickchange.c $(MODLFLAGS)
-
-src/modules/extbans/quiet.dll: src/modules/extbans/quiet.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/extbans/ /Fesrc/modules/extbans/ src/modules/extbans/quiet.c $(MODLFLAGS)
-
-src/modules/extbans/realname.dll: src/modules/extbans/realname.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/extbans/ /Fesrc/modules/extbans/ src/modules/extbans/realname.c $(MODLFLAGS)
-
-src/modules/extbans/operclass.dll: src/modules/extbans/operclass.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/extbans/ /Fesrc/modules/extbans/ src/modules/extbans/operclass.c $(MODLFLAGS)
-
-src/modules/extbans/certfp.dll: src/modules/extbans/certfp.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/extbans/ /Fesrc/modules/extbans/ src/modules/extbans/certfp.c $(MODLFLAGS)
-
-src/modules/extbans/textban.dll: src/modules/extbans/textban.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/extbans/ /Fesrc/modules/extbans/ src/modules/extbans/textban.c $(MODLFLAGS)
-
-src/modules/extbans/msgbypass.dll: src/modules/extbans/msgbypass.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/extbans/ /Fesrc/modules/extbans/ src/modules/extbans/msgbypass.c $(MODLFLAGS)
-
-src/modules/extbans/timedban.dll: src/modules/extbans/timedban.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/extbans/ /Fesrc/modules/extbans/ src/modules/extbans/timedban.c $(MODLFLAGS)
-
-src/modules/extbans/partmsg.dll: src/modules/extbans/partmsg.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/extbans/ /Fesrc/modules/extbans/ src/modules/extbans/partmsg.c $(MODLFLAGS)
-
-src/modules/extbans/securitygroup.dll: src/modules/extbans/securitygroup.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/extbans/ /Fesrc/modules/extbans/ src/modules/extbans/securitygroup.c $(MODLFLAGS)
-
src/modules/account-notify.dll: src/modules/account-notify.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/account-notify.c $(MODLFLAGS)
-
-src/modules/message-tags.dll: src/modules/message-tags.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/message-tags.c $(MODLFLAGS)
-
-src/modules/batch.dll: src/modules/batch.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/batch.c $(MODLFLAGS)
+ $(CC) $(MODCFLAGS) src/modules/account-notify.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/account-notify.pdb $(MODLFLAGS)
src/modules/account-tag.dll: src/modules/account-tag.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/account-tag.c $(MODLFLAGS)
+ $(CC) $(MODCFLAGS) src/modules/account-tag.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/account-tag.pdb $(MODLFLAGS)
-src/modules/labeled-response.dll: src/modules/labeled-response.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/labeled-response.c $(MODLFLAGS)
+src/modules/addmotd.dll: src/modules/addmotd.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/addmotd.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/addmotd.pdb $(MODLFLAGS)
-src/modules/link-security.dll: src/modules/link-security.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/link-security.c $(MODLFLAGS)
+src/modules/addomotd.dll: src/modules/addomotd.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/addomotd.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/addomotd.pdb $(MODLFLAGS)
-src/modules/message-ids.dll: src/modules/message-ids.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/message-ids.c $(MODLFLAGS)
+src/modules/admin.dll: src/modules/admin.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/admin.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/admin.pdb $(MODLFLAGS)
-src/modules/plaintext-policy.dll: src/modules/plaintext-policy.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/plaintext-policy.c $(MODLFLAGS)
+src/modules/antimixedutf8.dll: src/modules/antimixedutf8.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/antimixedutf8.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/antimixedutf8.pdb $(MODLFLAGS)
-src/modules/server-time.dll: src/modules/server-time.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/server-time.c $(MODLFLAGS)
+src/modules/antirandom.dll: src/modules/antirandom.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/antirandom.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/antirandom.pdb $(MODLFLAGS)
-src/modules/sts.dll: src/modules/sts.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/sts.c $(MODLFLAGS)
+src/modules/authprompt.dll: src/modules/authprompt.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/authprompt.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/authprompt.pdb $(MODLFLAGS)
-src/modules/tkldb.dll: src/modules/tkldb.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/tkldb.c $(MODLFLAGS)
+src/modules/away.dll: src/modules/away.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/away.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/away.pdb $(MODLFLAGS)
-src/modules/channeldb.dll: src/modules/channeldb.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/channeldb.c $(MODLFLAGS)
+src/modules/batch.dll: src/modules/batch.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/batch.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/batch.pdb $(MODLFLAGS)
-src/modules/history_backend_mem.dll: src/modules/history_backend_mem.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/history_backend_mem.c $(MODLFLAGS)
+src/modules/blacklist.dll: src/modules/blacklist.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/blacklist.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/blacklist.pdb $(MODLFLAGS)
-src/modules/history_backend_null.dll: src/modules/history_backend_null.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/history_backend_null.c $(MODLFLAGS)
-
-src/modules/restrict-commands.dll: src/modules/restrict-commands.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/restrict-commands.c $(MODLFLAGS)
-
-src/modules/rmtkl.dll: src/modules/rmtkl.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/rmtkl.c $(MODLFLAGS)
-
-src/modules/echo-message.dll: src/modules/echo-message.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/echo-message.c $(MODLFLAGS)
-
-src/modules/userip-tag.dll: src/modules/userip-tag.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/userip-tag.c $(MODLFLAGS)
-
-src/modules/userhost-tag.dll: src/modules/userhost-tag.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/userhost-tag.c $(MODLFLAGS)
+src/modules/botmotd.dll: src/modules/botmotd.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/botmotd.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/botmotd.pdb $(MODLFLAGS)
src/modules/bot-tag.dll: src/modules/bot-tag.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/bot-tag.c $(MODLFLAGS)
+ $(CC) $(MODCFLAGS) src/modules/bot-tag.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/bot-tag.pdb $(MODLFLAGS)
-src/modules/reply-tag.dll: src/modules/reply-tag.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/reply-tag.c $(MODLFLAGS)
+src/modules/cap.dll: src/modules/cap.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/cap.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/cap.pdb $(MODLFLAGS)
-src/modules/require-module.dll: src/modules/require-module.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/require-module.c $(MODLFLAGS)
+src/modules/certfp.dll: src/modules/certfp.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/certfp.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/certfp.pdb $(MODLFLAGS)
-src/modules/ident_lookup.dll: src/modules/ident_lookup.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/ident_lookup.c $(MODLFLAGS)
+src/modules/chanmodes/chanowner.dll: src/modules/chanmodes/chanowner.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/chanowner.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/chanowner.pdb $(MODLFLAGS)
-src/modules/history.dll: src/modules/history.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/history.c $(MODLFLAGS)
+src/modules/chanmodes/chanadmin.dll: src/modules/chanmodes/chanadmin.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/chanadmin.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/chanadmin.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/chanop.dll: src/modules/chanmodes/chanop.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/chanop.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/chanop.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/halfop.dll: src/modules/chanmodes/halfop.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/halfop.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/halfop.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/voice.dll: src/modules/chanmodes/voice.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/voice.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/voice.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/censor.dll: src/modules/chanmodes/censor.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/censor.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/censor.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/delayjoin.dll: src/modules/chanmodes/delayjoin.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/delayjoin.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/delayjoin.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/floodprot.dll: src/modules/chanmodes/floodprot.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/floodprot.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/floodprot.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/history.dll: src/modules/chanmodes/history.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/history.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/history.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/inviteonly.dll: src/modules/chanmodes/inviteonly.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/inviteonly.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/inviteonly.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/isregistered.dll: src/modules/chanmodes/isregistered.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/isregistered.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/isregistered.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/issecure.dll: src/modules/chanmodes/issecure.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/issecure.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/issecure.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/key.dll: src/modules/chanmodes/key.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/key.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/key.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/limit.dll: src/modules/chanmodes/limit.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/limit.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/limit.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/link.dll: src/modules/chanmodes/link.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/link.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/link.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/moderated.dll: src/modules/chanmodes/moderated.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/moderated.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/moderated.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/nocolor.dll: src/modules/chanmodes/nocolor.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/nocolor.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/nocolor.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/noctcp.dll: src/modules/chanmodes/noctcp.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/noctcp.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/noctcp.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/noexternalmsgs.dll: src/modules/chanmodes/noexternalmsgs.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/noexternalmsgs.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/noexternalmsgs.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/noinvite.dll: src/modules/chanmodes/noinvite.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/noinvite.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/noinvite.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/nokick.dll: src/modules/chanmodes/nokick.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/nokick.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/nokick.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/noknock.dll: src/modules/chanmodes/noknock.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/noknock.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/noknock.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/nonickchange.dll: src/modules/chanmodes/nonickchange.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/nonickchange.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/nonickchange.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/nonotice.dll: src/modules/chanmodes/nonotice.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/nonotice.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/nonotice.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/operonly.dll: src/modules/chanmodes/operonly.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/operonly.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/operonly.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/permanent.dll: src/modules/chanmodes/permanent.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/permanent.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/permanent.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/private.dll: src/modules/chanmodes/private.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/private.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/private.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/regonly.dll: src/modules/chanmodes/regonly.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/regonly.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/regonly.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/regonlyspeak.dll: src/modules/chanmodes/regonlyspeak.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/regonlyspeak.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/regonlyspeak.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/secret.dll: src/modules/chanmodes/secret.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/secret.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/secret.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/secureonly.dll: src/modules/chanmodes/secureonly.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/secureonly.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/secureonly.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/stripcolor.dll: src/modules/chanmodes/stripcolor.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/stripcolor.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/stripcolor.pdb $(MODLFLAGS)
+
+src/modules/chanmodes/topiclimit.dll: src/modules/chanmodes/topiclimit.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chanmodes/topiclimit.c /Fesrc/modules/chanmodes/ /Fosrc/modules/chanmodes/ /Fdsrc/modules/chanmodes/topiclimit.pdb $(MODLFLAGS)
+
+src/modules/channeldb.dll: src/modules/channeldb.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/channeldb.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/channeldb.pdb $(MODLFLAGS)
+
+src/modules/charsys.dll: src/modules/charsys.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/charsys.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/charsys.pdb $(MODLFLAGS)
src/modules/chathistory.dll: src/modules/chathistory.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/chathistory.c $(MODLFLAGS)
+ $(CC) $(MODCFLAGS) src/modules/chathistory.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/chathistory.pdb $(MODLFLAGS)
-src/modules/targetfloodprot.dll: src/modules/targetfloodprot.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/targetfloodprot.c $(MODLFLAGS)
+src/modules/chghost.dll: src/modules/chghost.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chghost.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/chghost.pdb $(MODLFLAGS)
-src/modules/typing-indicator.dll: src/modules/typing-indicator.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/typing-indicator.c $(MODLFLAGS)
+src/modules/chgident.dll: src/modules/chgident.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chgident.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/chgident.pdb $(MODLFLAGS)
+
+src/modules/chgname.dll: src/modules/chgname.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/chgname.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/chgname.pdb $(MODLFLAGS)
src/modules/clienttagdeny.dll: src/modules/clienttagdeny.c $(INCLUDES)
- $(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/clienttagdeny.c $(MODLFLAGS)
+ $(CC) $(MODCFLAGS) src/modules/clienttagdeny.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/clienttagdeny.pdb $(MODLFLAGS)
+
+src/modules/close.dll: src/modules/close.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/close.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/close.pdb $(MODLFLAGS)
+
+src/modules/connect.dll: src/modules/connect.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/connect.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/connect.pdb $(MODLFLAGS)
+
+src/modules/connthrottle.dll: src/modules/connthrottle.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/connthrottle.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/connthrottle.pdb $(MODLFLAGS)
+
+src/modules/cycle.dll: src/modules/cycle.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/cycle.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/cycle.pdb $(MODLFLAGS)
+
+src/modules/dccallow.dll: src/modules/dccallow.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/dccallow.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/dccallow.pdb $(MODLFLAGS)
+
+src/modules/dccdeny.dll: src/modules/dccdeny.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/dccdeny.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/dccdeny.pdb $(MODLFLAGS)
+
+src/modules/echo-message.dll: src/modules/echo-message.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/echo-message.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/echo-message.pdb $(MODLFLAGS)
+
+src/modules/eos.dll: src/modules/eos.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/eos.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/eos.pdb $(MODLFLAGS)
+
+src/modules/extbans/account.dll: src/modules/extbans/account.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/extbans/account.c /Fesrc/modules/extbans/ /Fosrc/modules/extbans/ /Fdsrc/modules/extbans/account.pdb $(MODLFLAGS)
+
+src/modules/extbans/certfp.dll: src/modules/extbans/certfp.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/extbans/certfp.c /Fesrc/modules/extbans/ /Fosrc/modules/extbans/ /Fdsrc/modules/extbans/certfp.pdb $(MODLFLAGS)
+
+src/modules/extbans/country.dll: src/modules/extbans/country.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/extbans/country.c /Fesrc/modules/extbans/ /Fosrc/modules/extbans/ /Fdsrc/modules/extbans/country.pdb $(MODLFLAGS)
+
+src/modules/extbans/inchannel.dll: src/modules/extbans/inchannel.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/extbans/inchannel.c /Fesrc/modules/extbans/ /Fosrc/modules/extbans/ /Fdsrc/modules/extbans/inchannel.pdb $(MODLFLAGS)
+
+src/modules/extbans/join.dll: src/modules/extbans/join.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/extbans/join.c /Fesrc/modules/extbans/ /Fosrc/modules/extbans/ /Fdsrc/modules/extbans/join.pdb $(MODLFLAGS)
+
+src/modules/extbans/msgbypass.dll: src/modules/extbans/msgbypass.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/extbans/msgbypass.c /Fesrc/modules/extbans/ /Fosrc/modules/extbans/ /Fdsrc/modules/extbans/msgbypass.pdb $(MODLFLAGS)
+
+src/modules/extbans/nickchange.dll: src/modules/extbans/nickchange.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/extbans/nickchange.c /Fesrc/modules/extbans/ /Fosrc/modules/extbans/ /Fdsrc/modules/extbans/nickchange.pdb $(MODLFLAGS)
+
+src/modules/extbans/operclass.dll: src/modules/extbans/operclass.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/extbans/operclass.c /Fesrc/modules/extbans/ /Fosrc/modules/extbans/ /Fdsrc/modules/extbans/operclass.pdb $(MODLFLAGS)
+
+src/modules/extbans/partmsg.dll: src/modules/extbans/partmsg.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/extbans/partmsg.c /Fesrc/modules/extbans/ /Fosrc/modules/extbans/ /Fdsrc/modules/extbans/partmsg.pdb $(MODLFLAGS)
+
+src/modules/extbans/quiet.dll: src/modules/extbans/quiet.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/extbans/quiet.c /Fesrc/modules/extbans/ /Fosrc/modules/extbans/ /Fdsrc/modules/extbans/quiet.pdb $(MODLFLAGS)
+
+src/modules/extbans/realname.dll: src/modules/extbans/realname.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/extbans/realname.c /Fesrc/modules/extbans/ /Fosrc/modules/extbans/ /Fdsrc/modules/extbans/realname.pdb $(MODLFLAGS)
+
+src/modules/extbans/securitygroup.dll: src/modules/extbans/securitygroup.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/extbans/securitygroup.c /Fesrc/modules/extbans/ /Fosrc/modules/extbans/ /Fdsrc/modules/extbans/securitygroup.pdb $(MODLFLAGS)
+
+src/modules/extbans/textban.dll: src/modules/extbans/textban.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/extbans/textban.c /Fesrc/modules/extbans/ /Fosrc/modules/extbans/ /Fdsrc/modules/extbans/textban.pdb $(MODLFLAGS)
+
+src/modules/extbans/timedban.dll: src/modules/extbans/timedban.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/extbans/timedban.c /Fesrc/modules/extbans/ /Fosrc/modules/extbans/ /Fdsrc/modules/extbans/timedban.pdb $(MODLFLAGS)
+
+src/modules/extended-monitor.dll: src/modules/extended-monitor.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/extended-monitor.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/extended-monitor.pdb $(MODLFLAGS)
+
+src/modules/geoip_base.dll: src/modules/geoip_base.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/geoip_base.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/geoip_base.pdb $(MODLFLAGS)
+
+src/modules/extjwt.dll: src/modules/extjwt.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/extjwt.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/extjwt.pdb $(MODLFLAGS)
+
+src/modules/geoip_classic.dll: src/modules/geoip_classic.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) /I "$(GEOIPCLASSIC_INC_DIR)" src/modules/geoip_classic.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/geoip_classic.pdb $(MODLFLAGS) /LIBPATH:"$(GEOIPCLASSIC_LIB_DIR)" $(GEOIPCLASSICLIB)
+
+src/modules/geoip_csv.dll: src/modules/geoip_csv.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/geoip_csv.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/geoip_csv.pdb $(MODLFLAGS)
+
+src/modules/geoip_maxmind.dll: src/modules/geoip_maxmind.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/geoip_maxmind.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/geoip_maxmind.pdb $(MODLFLAGS)
+
+src/modules/globops.dll: src/modules/globops.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/globops.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/globops.pdb $(MODLFLAGS)
+
+src/modules/help.dll: src/modules/help.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/help.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/help.pdb $(MODLFLAGS)
+
+src/modules/hideserver.dll: src/modules/hideserver.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/hideserver.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/hideserver.pdb $(MODLFLAGS)
+
+src/modules/history_backend_mem.dll: src/modules/history_backend_mem.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/history_backend_mem.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/history_backend_mem.pdb $(MODLFLAGS)
+
+src/modules/history_backend_null.dll: src/modules/history_backend_null.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/history_backend_null.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/history_backend_null.pdb $(MODLFLAGS)
+
+src/modules/history.dll: src/modules/history.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/history.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/history.pdb $(MODLFLAGS)
+
+src/modules/ident_lookup.dll: src/modules/ident_lookup.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/ident_lookup.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/ident_lookup.pdb $(MODLFLAGS)
+
+src/modules/invite.dll: src/modules/invite.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/invite.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/invite.pdb $(MODLFLAGS)
+
+src/modules/ircops.dll: src/modules/ircops.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/ircops.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/ircops.pdb $(MODLFLAGS)
+
+src/modules/ison.dll: src/modules/ison.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/ison.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/ison.pdb $(MODLFLAGS)
+
+src/modules/join.dll: src/modules/join.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/join.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/join.pdb $(MODLFLAGS)
+
+src/modules/jointhrottle.dll: src/modules/jointhrottle.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/jointhrottle.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/jointhrottle.pdb $(MODLFLAGS)
+
+src/modules/json-log-tag.dll: src/modules/json-log-tag.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/json-log-tag.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/json-log-tag.pdb $(MODLFLAGS)
+
+src/modules/jumpserver.dll: src/modules/jumpserver.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/jumpserver.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/jumpserver.pdb $(MODLFLAGS)
+
+src/modules/kick.dll: src/modules/kick.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/kick.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/kick.pdb $(MODLFLAGS)
+
+src/modules/kill.dll: src/modules/kill.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/kill.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/kill.pdb $(MODLFLAGS)
+
+src/modules/knock.dll: src/modules/knock.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/knock.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/knock.pdb $(MODLFLAGS)
+
+src/modules/labeled-response.dll: src/modules/labeled-response.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/labeled-response.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/labeled-response.pdb $(MODLFLAGS)
+
+src/modules/lag.dll: src/modules/lag.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/lag.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/lag.pdb $(MODLFLAGS)
+
+src/modules/links.dll: src/modules/links.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/links.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/links.pdb $(MODLFLAGS)
+
+src/modules/link-security.dll: src/modules/link-security.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/link-security.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/link-security.pdb $(MODLFLAGS)
+
+src/modules/list.dll: src/modules/list.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/list.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/list.pdb $(MODLFLAGS)
+
+src/modules/locops.dll: src/modules/locops.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/locops.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/locops.pdb $(MODLFLAGS)
+
+src/modules/lusers.dll: src/modules/lusers.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/lusers.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/lusers.pdb $(MODLFLAGS)
+
+src/modules/map.dll: src/modules/map.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/map.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/map.pdb $(MODLFLAGS)
+
+src/modules/md.dll: src/modules/md.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/md.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/md.pdb $(MODLFLAGS)
+
+src/modules/message.dll: src/modules/message.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/message.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/message.pdb $(MODLFLAGS)
+
+src/modules/message-ids.dll: src/modules/message-ids.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/message-ids.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/message-ids.pdb $(MODLFLAGS)
+
+src/modules/message-tags.dll: src/modules/message-tags.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/message-tags.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/message-tags.pdb $(MODLFLAGS)
+
+src/modules/mkpasswd.dll: src/modules/mkpasswd.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/mkpasswd.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/mkpasswd.pdb $(MODLFLAGS)
+
+src/modules/mode.dll: src/modules/mode.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/mode.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/mode.pdb $(MODLFLAGS)
+
+src/modules/monitor.dll: src/modules/monitor.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/monitor.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/monitor.pdb $(MODLFLAGS)
+
+src/modules/motd.dll: src/modules/motd.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/motd.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/motd.pdb $(MODLFLAGS)
+
+src/modules/names.dll: src/modules/names.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/names.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/names.pdb $(MODLFLAGS)
+
+src/modules/netinfo.dll: src/modules/netinfo.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/netinfo.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/netinfo.pdb $(MODLFLAGS)
+
+src/modules/nick.dll: src/modules/nick.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/nick.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/nick.pdb $(MODLFLAGS)
+
+src/modules/nocodes.dll: src/modules/nocodes.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/nocodes.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/nocodes.pdb $(MODLFLAGS)
+
+src/modules/cloak_md5.dll: src/modules/cloak_md5.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/cloak_md5.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/cloak_md5.pdb $(MODLFLAGS)
+
+src/modules/cloak_none.dll: src/modules/cloak_none.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/cloak_none.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/cloak_none.pdb $(MODLFLAGS)
+
+src/modules/cloak_sha256.dll: src/modules/cloak_sha256.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/cloak_sha256.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/cloak_sha256.pdb $(MODLFLAGS)
+
+src/modules/oper.dll: src/modules/oper.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/oper.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/oper.pdb $(MODLFLAGS)
+
+src/modules/operinfo.dll: src/modules/operinfo.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/operinfo.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/operinfo.pdb $(MODLFLAGS)
+
+src/modules/opermotd.dll: src/modules/opermotd.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/opermotd.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/opermotd.pdb $(MODLFLAGS)
+
+src/modules/part.dll: src/modules/part.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/part.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/part.pdb $(MODLFLAGS)
+
+src/modules/pass.dll: src/modules/pass.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/pass.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/pass.pdb $(MODLFLAGS)
+
+src/modules/pingpong.dll: src/modules/pingpong.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/pingpong.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/pingpong.pdb $(MODLFLAGS)
+
+src/modules/plaintext-policy.dll: src/modules/plaintext-policy.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/plaintext-policy.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/plaintext-policy.pdb $(MODLFLAGS)
+
+src/modules/protoctl.dll: src/modules/protoctl.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/protoctl.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/protoctl.pdb $(MODLFLAGS)
+
+src/modules/quit.dll: src/modules/quit.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/quit.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/quit.pdb $(MODLFLAGS)
+
+src/modules/reply-tag.dll: src/modules/reply-tag.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/reply-tag.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/reply-tag.pdb $(MODLFLAGS)
+
+src/modules/reputation.dll: src/modules/reputation.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/reputation.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/reputation.pdb $(MODLFLAGS)
+
+src/modules/require-module.dll: src/modules/require-module.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/require-module.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/require-module.pdb $(MODLFLAGS)
+
+src/modules/restrict-commands.dll: src/modules/restrict-commands.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/restrict-commands.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/restrict-commands.pdb $(MODLFLAGS)
+
+src/modules/rmtkl.dll: src/modules/rmtkl.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/rmtkl.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/rmtkl.pdb $(MODLFLAGS)
+
+src/modules/rules.dll: src/modules/rules.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/rules.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/rules.pdb $(MODLFLAGS)
+
+src/modules/sajoin.dll: src/modules/sajoin.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/sajoin.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/sajoin.pdb $(MODLFLAGS)
+
+src/modules/samode.dll: src/modules/samode.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/samode.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/samode.pdb $(MODLFLAGS)
+
+src/modules/sapart.dll: src/modules/sapart.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/sapart.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/sapart.pdb $(MODLFLAGS)
+
+src/modules/sasl.dll: src/modules/sasl.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/sasl.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/sasl.pdb $(MODLFLAGS)
+
+src/modules/sdesc.dll: src/modules/sdesc.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/sdesc.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/sdesc.pdb $(MODLFLAGS)
+
+src/modules/sendsno.dll: src/modules/sendsno.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/sendsno.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/sendsno.pdb $(MODLFLAGS)
+
+src/modules/sendumode.dll: src/modules/sendumode.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/sendumode.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/sendumode.pdb $(MODLFLAGS)
+
+src/modules/server.dll: src/modules/server.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/server.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/server.pdb $(MODLFLAGS)
+
+src/modules/server-time.dll: src/modules/server-time.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/server-time.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/server-time.pdb $(MODLFLAGS)
+
+src/modules/sethost.dll: src/modules/sethost.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/sethost.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/sethost.pdb $(MODLFLAGS)
+
+src/modules/setident.dll: src/modules/setident.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/setident.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/setident.pdb $(MODLFLAGS)
+
+src/modules/setname.dll: src/modules/setname.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/setname.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/setname.pdb $(MODLFLAGS)
+
+src/modules/silence.dll: src/modules/silence.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/silence.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/silence.pdb $(MODLFLAGS)
+
+src/modules/sinfo.dll: src/modules/sinfo.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/sinfo.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/sinfo.pdb $(MODLFLAGS)
+
+src/modules/sjoin.dll: src/modules/sjoin.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/sjoin.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/sjoin.pdb $(MODLFLAGS)
+
+src/modules/slog.dll: src/modules/slog.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/slog.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/slog.pdb $(MODLFLAGS)
+
+src/modules/sqline.dll: src/modules/sqline.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/sqline.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/sqline.pdb $(MODLFLAGS)
+
+src/modules/squit.dll: src/modules/squit.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/squit.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/squit.pdb $(MODLFLAGS)
+
+src/modules/staff.dll: src/modules/staff.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/staff.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/staff.pdb $(MODLFLAGS)
+
+src/modules/starttls.dll: src/modules/starttls.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/starttls.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/starttls.pdb $(MODLFLAGS)
+
+src/modules/stats.dll: src/modules/stats.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/stats.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/stats.pdb $(MODLFLAGS)
+
+src/modules/sts.dll: src/modules/sts.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/sts.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/sts.pdb $(MODLFLAGS)
+
+src/modules/svsjoin.dll: src/modules/svsjoin.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/svsjoin.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/svsjoin.pdb $(MODLFLAGS)
+
+src/modules/svskill.dll: src/modules/svskill.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/svskill.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/svskill.pdb $(MODLFLAGS)
+
+src/modules/svslusers.dll: src/modules/svslusers.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/svslusers.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/svslusers.pdb $(MODLFLAGS)
+
+src/modules/svsmode.dll: src/modules/svsmode.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/svsmode.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/svsmode.pdb $(MODLFLAGS)
+
+src/modules/svsmotd.dll: src/modules/svsmotd.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/svsmotd.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/svsmotd.pdb $(MODLFLAGS)
+
+src/modules/svsnick.dll: src/modules/svsnick.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/svsnick.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/svsnick.pdb $(MODLFLAGS)
+
+src/modules/svsnline.dll: src/modules/svsnline.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/svsnline.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/svsnline.pdb $(MODLFLAGS)
+
+src/modules/svsnolag.dll: src/modules/svsnolag.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/svsnolag.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/svsnolag.pdb $(MODLFLAGS)
+
+src/modules/svsnoop.dll: src/modules/svsnoop.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/svsnoop.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/svsnoop.pdb $(MODLFLAGS)
+
+src/modules/svspart.dll: src/modules/svspart.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/svspart.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/svspart.pdb $(MODLFLAGS)
+
+src/modules/svssilence.dll: src/modules/svssilence.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/svssilence.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/svssilence.pdb $(MODLFLAGS)
+
+src/modules/svssno.dll: src/modules/svssno.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/svssno.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/svssno.pdb $(MODLFLAGS)
+
+src/modules/svswatch.dll: src/modules/svswatch.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/svswatch.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/svswatch.pdb $(MODLFLAGS)
+
+src/modules/swhois.dll: src/modules/swhois.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/swhois.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/swhois.pdb $(MODLFLAGS)
+
+src/modules/targetfloodprot.dll: src/modules/targetfloodprot.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/targetfloodprot.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/targetfloodprot.pdb $(MODLFLAGS)
+
+src/modules/time.dll: src/modules/time.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/time.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/time.pdb $(MODLFLAGS)
+
+src/modules/tkl.dll: src/modules/tkl.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/tkl.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/tkl.pdb $(MODLFLAGS)
+
+src/modules/tkldb.dll: src/modules/tkldb.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/tkldb.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/tkldb.pdb $(MODLFLAGS)
+
+src/modules/tls_antidos.dll: src/modules/tls_antidos.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/tls_antidos.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/tls_antidos.pdb $(MODLFLAGS)
+
+src/modules/tls_cipher.dll: src/modules/tls_cipher.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/tls_cipher.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/tls_cipher.pdb $(MODLFLAGS)
+
+src/modules/topic.dll: src/modules/topic.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/topic.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/topic.pdb $(MODLFLAGS)
+
+src/modules/trace.dll: src/modules/trace.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/trace.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/trace.pdb $(MODLFLAGS)
+
+src/modules/tsctl.dll: src/modules/tsctl.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/tsctl.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/tsctl.pdb $(MODLFLAGS)
+
+src/modules/typing-indicator.dll: src/modules/typing-indicator.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/typing-indicator.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/typing-indicator.pdb $(MODLFLAGS)
+
+src/modules/umode2.dll: src/modules/umode2.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/umode2.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/umode2.pdb $(MODLFLAGS)
+
+src/modules/unreal_server_compat.dll: src/modules/unreal_server_compat.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/unreal_server_compat.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/unreal_server_compat.pdb $(MODLFLAGS)
+
+src/modules/unsqline.dll: src/modules/unsqline.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/unsqline.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/unsqline.pdb $(MODLFLAGS)
+
+src/modules/user.dll: src/modules/user.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/user.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/user.pdb $(MODLFLAGS)
+
+src/modules/userhost.dll: src/modules/userhost.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/userhost.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/userhost.pdb $(MODLFLAGS)
+
+src/modules/userhost-tag.dll: src/modules/userhost-tag.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/userhost-tag.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/userhost-tag.pdb $(MODLFLAGS)
+
+src/modules/userip.dll: src/modules/userip.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/userip.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/userip.pdb $(MODLFLAGS)
+
+src/modules/userip-tag.dll: src/modules/userip-tag.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/userip-tag.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/userip-tag.pdb $(MODLFLAGS)
+
+src/modules/usermodes/bot.dll: src/modules/usermodes/bot.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/usermodes/bot.c /Fesrc/modules/usermodes/ /Fosrc/modules/usermodes/ /Fdsrc/modules/usermodes/bot.pdb $(MODLFLAGS)
+
+src/modules/usermodes/censor.dll: src/modules/usermodes/censor.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/usermodes/censor.c /Fesrc/modules/usermodes/ /Fosrc/modules/usermodes/ /Fdsrc/modules/usermodes/censor.pdb $(MODLFLAGS)
+
+src/modules/usermodes/noctcp.dll: src/modules/usermodes/noctcp.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/usermodes/noctcp.c /Fesrc/modules/usermodes/ /Fosrc/modules/usermodes/ /Fdsrc/modules/usermodes/noctcp.pdb $(MODLFLAGS)
+
+src/modules/usermodes/nokick.dll: src/modules/usermodes/nokick.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/usermodes/nokick.c /Fesrc/modules/usermodes/ /Fosrc/modules/usermodes/ /Fdsrc/modules/usermodes/nokick.pdb $(MODLFLAGS)
+
+src/modules/usermodes/privacy.dll: src/modules/usermodes/privacy.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/usermodes/privacy.c /Fesrc/modules/usermodes/ /Fosrc/modules/usermodes/ /Fdsrc/modules/usermodes/privacy.pdb $(MODLFLAGS)
+
+src/modules/usermodes/privdeaf.dll: src/modules/usermodes/privdeaf.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/usermodes/privdeaf.c /Fesrc/modules/usermodes/ /Fosrc/modules/usermodes/ /Fdsrc/modules/usermodes/privdeaf.pdb $(MODLFLAGS)
+
+src/modules/usermodes/regonlymsg.dll: src/modules/usermodes/regonlymsg.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/usermodes/regonlymsg.c /Fesrc/modules/usermodes/ /Fosrc/modules/usermodes/ /Fdsrc/modules/usermodes/regonlymsg.pdb $(MODLFLAGS)
+
+src/modules/usermodes/secureonlymsg.dll: src/modules/usermodes/secureonlymsg.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/usermodes/secureonlymsg.c /Fesrc/modules/usermodes/ /Fosrc/modules/usermodes/ /Fdsrc/modules/usermodes/secureonlymsg.pdb $(MODLFLAGS)
+
+src/modules/usermodes/servicebot.dll: src/modules/usermodes/servicebot.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/usermodes/servicebot.c /Fesrc/modules/usermodes/ /Fosrc/modules/usermodes/ /Fdsrc/modules/usermodes/servicebot.pdb $(MODLFLAGS)
+
+src/modules/usermodes/showwhois.dll: src/modules/usermodes/showwhois.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/usermodes/showwhois.c /Fesrc/modules/usermodes/ /Fosrc/modules/usermodes/ /Fdsrc/modules/usermodes/showwhois.pdb $(MODLFLAGS)
+
+src/modules/usermodes/wallops.dll: src/modules/usermodes/wallops.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/usermodes/wallops.c /Fesrc/modules/usermodes/ /Fosrc/modules/usermodes/ /Fdsrc/modules/usermodes/wallops.pdb $(MODLFLAGS)
+
+src/modules/vhost.dll: src/modules/vhost.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/vhost.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/vhost.pdb $(MODLFLAGS)
+
+src/modules/watch-backend.dll: src/modules/watch-backend.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/watch-backend.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/watch-backend.pdb $(MODLFLAGS)
+
+src/modules/watch.dll: src/modules/watch.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/watch.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/watch.pdb $(MODLFLAGS)
+
+src/modules/webirc.dll: src/modules/webirc.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/webirc.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/webirc.pdb $(MODLFLAGS)
+
+src/modules/webredir.dll: src/modules/webredir.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/webredir.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/webredir.pdb $(MODLFLAGS)
+
+src/modules/websocket.dll: src/modules/websocket.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/websocket.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/websocket.pdb $(MODLFLAGS)
+
+src/modules/whois.dll: src/modules/whois.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/whois.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/whois.pdb $(MODLFLAGS)
+
+src/modules/who_old.dll: src/modules/who_old.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/who_old.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/who_old.pdb $(MODLFLAGS)
+
+src/modules/whowas.dll: src/modules/whowas.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/whowas.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/whowas.pdb $(MODLFLAGS)
+
+src/modules/whox.dll: src/modules/whox.c $(INCLUDES)
+ $(CC) $(MODCFLAGS) src/modules/whox.c /Fesrc/modules/ /Fosrc/modules/ /Fdsrc/modules/whox.pdb $(MODLFLAGS)
-dummy:
diff --git a/README.md b/README.md
index cf4a267..86b1427 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,11 @@ Key features include SSL/TLS, cloaking, its advanced anti-flood and anti-spam sy
swear filtering and module support. We are also particularly proud on our extensive
online documentation.
+## Versions
+* UnrealIRCd 6 is the *stable* series since December 2021. All new features go in there.
+* UnrealIRCd 5 is the *oldstable* series. It will receive bug fixes until
+ July 1, 2022 plus another 12 months of security fixes.
+
## How to get started
Please consult our excellent online documentation at https://www.unrealircd.org/docs/
when setting up the IRCd!
diff --git a/SECURITY.md b/SECURITY.md
index 7708d00..0b6e8db 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -1,7 +1,8 @@
# Security Policy
## Supported Versions
-* The latest *stable* release of the 5.x branch
+* The latest *stable* release of UnrealIRCd 5 (until 2023-07-01)
+* The latest *stable* release of UnrealIRCd 6
See [UnrealIRCd releases](https://www.unrealircd.org/docs/UnrealIRCd_releases) for information on older versions and End Of Life dates.
diff --git a/autoconf/config.guess b/autoconf/config.guess
index f7eb141..e81d3ae 100644
--- a/autoconf/config.guess
+++ b/autoconf/config.guess
@@ -1,8 +1,10 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright 1992-2015 Free Software Foundation, Inc.
+# Copyright 1992-2021 Free Software Foundation, Inc.
-timestamp='2015-03-04'
+# shellcheck disable=SC2006,SC2268 # see below for rationale
+
+timestamp='2021-06-03'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -15,7 +17,7 @@ timestamp='2015-03-04'
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with this program; if not, see .
+# along with this program; if not, see .
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@@ -27,11 +29,19 @@ timestamp='2015-03-04'
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
#
# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
#
# Please send patches to .
+# The "shellcheck disable" line above the timestamp inhibits complaints
+# about features and limitations of the classic Bourne shell that were
+# superseded or lifted in POSIX. However, this script identifies a wide
+# variety of pre-POSIX systems that do not have POSIX shells at all, and
+# even some reasonably current systems (Solaris 10 as case-in-point) still
+# have a pre-POSIX /bin/sh.
+
+
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
@@ -39,7 +49,7 @@ Usage: $0 [OPTION]
Output the configuration name of the system \`$me' is run on.
-Operation modes:
+Options:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
@@ -50,7 +60,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright 1992-2015 Free Software Foundation, Inc.
+Copyright 1992-2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -84,7 +94,8 @@ if test $# != 0; then
exit 1
fi
-trap 'exit 1' 1 2 15
+# Just in case it came from the environment.
+GUESS=
# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
# compiler to aid in system detection is discouraged as it requires
@@ -96,66 +107,90 @@ trap 'exit 1' 1 2 15
# Portable tmp directory creation inspired by the Autoconf team.
-set_cc_for_build='
-trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
-trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
-: ${TMPDIR=/tmp} ;
- { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
- { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
- { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
- { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
-dummy=$tmp/dummy ;
-tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
-case $CC_FOR_BUILD,$HOST_CC,$CC in
- ,,) echo "int x;" > $dummy.c ;
- for c in cc gcc c89 c99 ; do
- if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
- CC_FOR_BUILD="$c"; break ;
- fi ;
- done ;
- if test x"$CC_FOR_BUILD" = x ; then
- CC_FOR_BUILD=no_compiler_found ;
- fi
- ;;
- ,,*) CC_FOR_BUILD=$CC ;;
- ,*,*) CC_FOR_BUILD=$HOST_CC ;;
-esac ; set_cc_for_build= ;'
+tmp=
+# shellcheck disable=SC2172
+trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
+
+set_cc_for_build() {
+ # prevent multiple calls if $tmp is already set
+ test "$tmp" && return 0
+ : "${TMPDIR=/tmp}"
+ # shellcheck disable=SC2039,SC3028
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
+ dummy=$tmp/dummy
+ case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
+ ,,) echo "int x;" > "$dummy.c"
+ for driver in cc gcc c89 c99 ; do
+ if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
+ CC_FOR_BUILD=$driver
+ break
+ fi
+ done
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+ esac
+}
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 1994-08-24)
-if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+if test -f /.attbin/uname ; then
PATH=$PATH:/.attbin ; export PATH
fi
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
-UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
-case "${UNAME_SYSTEM}" in
+case $UNAME_SYSTEM in
Linux|GNU|GNU/*)
- # If the system lacks a compiler, then just pick glibc.
- # We could probably try harder.
- LIBC=gnu
+ LIBC=unknown
- eval $set_cc_for_build
- cat <<-EOF > $dummy.c
+ set_cc_for_build
+ cat <<-EOF > "$dummy.c"
#include
#if defined(__UCLIBC__)
LIBC=uclibc
#elif defined(__dietlibc__)
LIBC=dietlibc
- #else
+ #elif defined(__GLIBC__)
LIBC=gnu
+ #else
+ #include
+ /* First heuristic to detect musl libc. */
+ #ifdef __DEFINED_va_list
+ LIBC=musl
+ #endif
#endif
EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ eval "$cc_set_libc"
+
+ # Second heuristic to detect musl libc.
+ if [ "$LIBC" = unknown ] &&
+ command -v ldd >/dev/null &&
+ ldd --version 2>&1 | grep -q ^musl; then
+ LIBC=musl
+ fi
+
+ # If the system lacks a compiler, then just pick glibc.
+ # We could probably try harder.
+ if [ "$LIBC" = unknown ]; then
+ LIBC=gnu
+ fi
;;
esac
# Note: order is significant - the case branches are not exclusive.
-case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in
*:NetBSD:*:*)
# NetBSD (nbsd) targets should (where applicable) match one or
# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
@@ -167,29 +202,32 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
#
# Note: NetBSD doesn't particularly care about the vendor
# portion of the name. We always set it to "unknown".
- sysctl="sysctl -n hw.machine_arch"
UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
- /sbin/$sysctl 2>/dev/null || \
- /usr/sbin/$sysctl 2>/dev/null || \
+ /sbin/sysctl -n hw.machine_arch 2>/dev/null || \
+ /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
echo unknown)`
- case "${UNAME_MACHINE_ARCH}" in
+ case $UNAME_MACHINE_ARCH in
+ aarch64eb) machine=aarch64_be-unknown ;;
armeb) machine=armeb-unknown ;;
arm*) machine=arm-unknown ;;
sh3el) machine=shl-unknown ;;
sh3eb) machine=sh-unknown ;;
sh5el) machine=sh5le-unknown ;;
earmv*)
- arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
- endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
+ arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+ endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
machine=${arch}${endian}-unknown
;;
- *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ *) machine=$UNAME_MACHINE_ARCH-unknown ;;
esac
# The Operating System including object format, if it has switched
- # to ELF recently, or will in the future.
- case "${UNAME_MACHINE_ARCH}" in
- arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax)
- eval $set_cc_for_build
+ # to ELF recently (or will in the future) and ABI.
+ case $UNAME_MACHINE_ARCH in
+ earm*)
+ os=netbsdelf
+ ;;
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ELF__
then
@@ -205,10 +243,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
;;
esac
# Determine ABI tags.
- case "${UNAME_MACHINE_ARCH}" in
+ case $UNAME_MACHINE_ARCH in
earm*)
expr='s/^earmv[0-9]/-eabi/;s/eb$//'
- abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
+ abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
;;
esac
# The OS release
@@ -216,40 +254,68 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# thus, need a distinct triplet. However, they do not need
# kernel version information, so it can be replaced with a
# suitable tag, in the style of linux-gnu.
- case "${UNAME_VERSION}" in
+ case $UNAME_VERSION in
Debian*)
release='-gnu'
;;
*)
- release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
;;
esac
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
# contains redundant information, the shorter form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
- echo "${machine}-${os}${release}${abi}"
- exit ;;
+ GUESS=$machine-${os}${release}${abi-}
+ ;;
*:Bitrig:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
- echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE
+ ;;
*:OpenBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
- echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE
+ ;;
+ *:SecBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'`
+ GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE
+ ;;
+ *:LibertyBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+ GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE
+ ;;
+ *:MidnightBSD:*:*)
+ GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE
+ ;;
*:ekkoBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE
+ ;;
*:SolidBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE
+ ;;
+ *:OS108:*:*)
+ GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE
+ ;;
macppc:MirBSD:*:*)
- echo powerpc-unknown-mirbsd${UNAME_RELEASE}
- exit ;;
+ GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE
+ ;;
*:MirBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE
+ ;;
+ *:Sortix:*:*)
+ GUESS=$UNAME_MACHINE-unknown-sortix
+ ;;
+ *:Twizzler:*:*)
+ GUESS=$UNAME_MACHINE-unknown-twizzler
+ ;;
+ *:Redox:*:*)
+ GUESS=$UNAME_MACHINE-unknown-redox
+ ;;
+ mips:OSF1:*.*)
+ GUESS=mips-dec-osf1
+ ;;
alpha:OSF1:*:*)
+ # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+ trap '' 0
case $UNAME_RELEASE in
*4.0)
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
@@ -263,163 +329,158 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# covers most systems running today. This code pipes the CPU
# types through head -n 1, so we only detect the type of CPU 0.
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
- case "$ALPHA_CPU_TYPE" in
+ case $ALPHA_CPU_TYPE in
"EV4 (21064)")
- UNAME_MACHINE="alpha" ;;
+ UNAME_MACHINE=alpha ;;
"EV4.5 (21064)")
- UNAME_MACHINE="alpha" ;;
+ UNAME_MACHINE=alpha ;;
"LCA4 (21066/21068)")
- UNAME_MACHINE="alpha" ;;
+ UNAME_MACHINE=alpha ;;
"EV5 (21164)")
- UNAME_MACHINE="alphaev5" ;;
+ UNAME_MACHINE=alphaev5 ;;
"EV5.6 (21164A)")
- UNAME_MACHINE="alphaev56" ;;
+ UNAME_MACHINE=alphaev56 ;;
"EV5.6 (21164PC)")
- UNAME_MACHINE="alphapca56" ;;
+ UNAME_MACHINE=alphapca56 ;;
"EV5.7 (21164PC)")
- UNAME_MACHINE="alphapca57" ;;
+ UNAME_MACHINE=alphapca57 ;;
"EV6 (21264)")
- UNAME_MACHINE="alphaev6" ;;
+ UNAME_MACHINE=alphaev6 ;;
"EV6.7 (21264A)")
- UNAME_MACHINE="alphaev67" ;;
+ UNAME_MACHINE=alphaev67 ;;
"EV6.8CB (21264C)")
- UNAME_MACHINE="alphaev68" ;;
+ UNAME_MACHINE=alphaev68 ;;
"EV6.8AL (21264B)")
- UNAME_MACHINE="alphaev68" ;;
+ UNAME_MACHINE=alphaev68 ;;
"EV6.8CX (21264D)")
- UNAME_MACHINE="alphaev68" ;;
+ UNAME_MACHINE=alphaev68 ;;
"EV6.9A (21264/EV69A)")
- UNAME_MACHINE="alphaev69" ;;
+ UNAME_MACHINE=alphaev69 ;;
"EV7 (21364)")
- UNAME_MACHINE="alphaev7" ;;
+ UNAME_MACHINE=alphaev7 ;;
"EV7.9 (21364A)")
- UNAME_MACHINE="alphaev79" ;;
+ UNAME_MACHINE=alphaev79 ;;
esac
# A Pn.n version is a patched version.
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
- echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
- exitcode=$?
- trap '' 0
- exit $exitcode ;;
- Alpha\ *:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # Should we change UNAME_MACHINE based on the output of uname instead
- # of the specific Alpha model?
- echo alpha-pc-interix
- exit ;;
- 21064:Windows_NT:50:3)
- echo alpha-dec-winnt3.5
- exit ;;
+ OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ GUESS=$UNAME_MACHINE-dec-osf$OSF_REL
+ ;;
Amiga*:UNIX_System_V:4.0:*)
- echo m68k-unknown-sysv4
- exit ;;
+ GUESS=m68k-unknown-sysv4
+ ;;
*:[Aa]miga[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-amigaos
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-amigaos
+ ;;
*:[Mm]orph[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-morphos
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-morphos
+ ;;
*:OS/390:*:*)
- echo i370-ibm-openedition
- exit ;;
+ GUESS=i370-ibm-openedition
+ ;;
*:z/VM:*:*)
- echo s390-ibm-zvmoe
- exit ;;
+ GUESS=s390-ibm-zvmoe
+ ;;
*:OS400:*:*)
- echo powerpc-ibm-os400
- exit ;;
+ GUESS=powerpc-ibm-os400
+ ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
- echo arm-acorn-riscix${UNAME_RELEASE}
- exit ;;
+ GUESS=arm-acorn-riscix$UNAME_RELEASE
+ ;;
arm*:riscos:*:*|arm*:RISCOS:*:*)
- echo arm-unknown-riscos
- exit ;;
+ GUESS=arm-unknown-riscos
+ ;;
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
- echo hppa1.1-hitachi-hiuxmpp
- exit ;;
+ GUESS=hppa1.1-hitachi-hiuxmpp
+ ;;
Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
- if test "`(/bin/universe) 2>/dev/null`" = att ; then
- echo pyramid-pyramid-sysv3
- else
- echo pyramid-pyramid-bsd
- fi
- exit ;;
+ case `(/bin/universe) 2>/dev/null` in
+ att) GUESS=pyramid-pyramid-sysv3 ;;
+ *) GUESS=pyramid-pyramid-bsd ;;
+ esac
+ ;;
NILE*:*:*:dcosx)
- echo pyramid-pyramid-svr4
- exit ;;
+ GUESS=pyramid-pyramid-svr4
+ ;;
DRS?6000:unix:4.0:6*)
- echo sparc-icl-nx6
- exit ;;
+ GUESS=sparc-icl-nx6
+ ;;
DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
case `/usr/bin/uname -p` in
- sparc) echo sparc-icl-nx7; exit ;;
- esac ;;
+ sparc) GUESS=sparc-icl-nx7 ;;
+ esac
+ ;;
s390x:SunOS:*:*)
- echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL
+ ;;
sun4H:SunOS:5.*:*)
- echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=sparc-hal-solaris2$SUN_REL
+ ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
- echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=sparc-sun-solaris2$SUN_REL
+ ;;
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
- echo i386-pc-auroraux${UNAME_RELEASE}
- exit ;;
+ GUESS=i386-pc-auroraux$UNAME_RELEASE
+ ;;
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
- eval $set_cc_for_build
- SUN_ARCH="i386"
+ set_cc_for_build
+ SUN_ARCH=i386
# If there is a compiler, see if it is configured for 64-bit objects.
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
# This test works for both compilers.
- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
- SUN_ARCH="x86_64"
+ SUN_ARCH=x86_64
fi
fi
- echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=$SUN_ARCH-pc-solaris2$SUN_REL
+ ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
- echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=sparc-sun-solaris3$SUN_REL
+ ;;
sun4*:SunOS:*:*)
- case "`/usr/bin/arch -k`" in
+ case `/usr/bin/arch -k` in
Series*|S4*)
UNAME_RELEASE=`uname -v`
;;
esac
# Japanese Language versions have a version number like `4.1.3-JL'.
- echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'`
+ GUESS=sparc-sun-sunos$SUN_REL
+ ;;
sun3*:SunOS:*:*)
- echo m68k-sun-sunos${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-sun-sunos$UNAME_RELEASE
+ ;;
sun*:*:4.2BSD:*)
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
- test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
- case "`/bin/arch`" in
+ test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
+ case `/bin/arch` in
sun3)
- echo m68k-sun-sunos${UNAME_RELEASE}
+ GUESS=m68k-sun-sunos$UNAME_RELEASE
;;
sun4)
- echo sparc-sun-sunos${UNAME_RELEASE}
+ GUESS=sparc-sun-sunos$UNAME_RELEASE
;;
esac
- exit ;;
+ ;;
aushp:SunOS:*:*)
- echo sparc-auspex-sunos${UNAME_RELEASE}
- exit ;;
+ GUESS=sparc-auspex-sunos$UNAME_RELEASE
+ ;;
# The situation for MiNT is a little confusing. The machine name
# can be virtually everything (everything which is not
# "atarist" or "atariste" at least should have a processor
@@ -429,44 +490,44 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# MiNT. But MiNT is downward compatible to TOS, so this should
# be no problem.
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-atari-mint$UNAME_RELEASE
+ ;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-atari-mint$UNAME_RELEASE
+ ;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-atari-mint$UNAME_RELEASE
+ ;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
- echo m68k-milan-mint${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-milan-mint$UNAME_RELEASE
+ ;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
- echo m68k-hades-mint${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-hades-mint$UNAME_RELEASE
+ ;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
- echo m68k-unknown-mint${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-unknown-mint$UNAME_RELEASE
+ ;;
m68k:machten:*:*)
- echo m68k-apple-machten${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-apple-machten$UNAME_RELEASE
+ ;;
powerpc:machten:*:*)
- echo powerpc-apple-machten${UNAME_RELEASE}
- exit ;;
+ GUESS=powerpc-apple-machten$UNAME_RELEASE
+ ;;
RISC*:Mach:*:*)
- echo mips-dec-mach_bsd4.3
- exit ;;
+ GUESS=mips-dec-mach_bsd4.3
+ ;;
RISC*:ULTRIX:*:*)
- echo mips-dec-ultrix${UNAME_RELEASE}
- exit ;;
+ GUESS=mips-dec-ultrix$UNAME_RELEASE
+ ;;
VAX*:ULTRIX*:*:*)
- echo vax-dec-ultrix${UNAME_RELEASE}
- exit ;;
+ GUESS=vax-dec-ultrix$UNAME_RELEASE
+ ;;
2020:CLIX:*:* | 2430:CLIX:*:*)
- echo clipper-intergraph-clix${UNAME_RELEASE}
- exit ;;
+ GUESS=clipper-intergraph-clix$UNAME_RELEASE
+ ;;
mips:*:*:UMIPS | mips:*:*:RISCos)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
#ifdef __cplusplus
#include /* for printf() prototype */
int main (int argc, char *argv[]) {
@@ -475,95 +536,96 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
#endif
#if defined (host_mips) && defined (MIPSEB)
#if defined (SYSTYPE_SYSV)
- printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_SVR4)
- printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
- printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
#endif
#endif
exit (-1);
}
EOF
- $CC_FOR_BUILD -o $dummy $dummy.c &&
- dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
- SYSTEM_NAME=`$dummy $dummyarg` &&
+ $CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
+ dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
{ echo "$SYSTEM_NAME"; exit; }
- echo mips-mips-riscos${UNAME_RELEASE}
- exit ;;
+ GUESS=mips-mips-riscos$UNAME_RELEASE
+ ;;
Motorola:PowerMAX_OS:*:*)
- echo powerpc-motorola-powermax
- exit ;;
+ GUESS=powerpc-motorola-powermax
+ ;;
Motorola:*:4.3:PL8-*)
- echo powerpc-harris-powermax
- exit ;;
+ GUESS=powerpc-harris-powermax
+ ;;
Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
- echo powerpc-harris-powermax
- exit ;;
+ GUESS=powerpc-harris-powermax
+ ;;
Night_Hawk:Power_UNIX:*:*)
- echo powerpc-harris-powerunix
- exit ;;
+ GUESS=powerpc-harris-powerunix
+ ;;
m88k:CX/UX:7*:*)
- echo m88k-harris-cxux7
- exit ;;
+ GUESS=m88k-harris-cxux7
+ ;;
m88k:*:4*:R4*)
- echo m88k-motorola-sysv4
- exit ;;
+ GUESS=m88k-motorola-sysv4
+ ;;
m88k:*:3*:R3*)
- echo m88k-motorola-sysv3
- exit ;;
+ GUESS=m88k-motorola-sysv3
+ ;;
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
- if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110
then
- if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
- [ ${TARGET_BINARY_INTERFACE}x = x ]
+ if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
+ test "$TARGET_BINARY_INTERFACE"x = x
then
- echo m88k-dg-dgux${UNAME_RELEASE}
+ GUESS=m88k-dg-dgux$UNAME_RELEASE
else
- echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ GUESS=m88k-dg-dguxbcs$UNAME_RELEASE
fi
else
- echo i586-dg-dgux${UNAME_RELEASE}
+ GUESS=i586-dg-dgux$UNAME_RELEASE
fi
- exit ;;
+ ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
- echo m88k-dolphin-sysv3
- exit ;;
+ GUESS=m88k-dolphin-sysv3
+ ;;
M88*:*:R3*:*)
# Delta 88k system running SVR3
- echo m88k-motorola-sysv3
- exit ;;
+ GUESS=m88k-motorola-sysv3
+ ;;
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
- echo m88k-tektronix-sysv3
- exit ;;
+ GUESS=m88k-tektronix-sysv3
+ ;;
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
- echo m68k-tektronix-bsd
- exit ;;
+ GUESS=m68k-tektronix-bsd
+ ;;
*:IRIX*:*:*)
- echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
- exit ;;
+ IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'`
+ GUESS=mips-sgi-irix$IRIX_REL
+ ;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
- echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
- exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ ;; # Note that: echo "'`uname -s`'" gives 'AIX '
i*86:AIX:*:*)
- echo i386-ibm-aix
- exit ;;
+ GUESS=i386-ibm-aix
+ ;;
ia64:AIX:*:*)
- if [ -x /usr/bin/oslevel ] ; then
+ if test -x /usr/bin/oslevel ; then
IBM_REV=`/usr/bin/oslevel`
else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
fi
- echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
- exit ;;
+ GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV
+ ;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
#include
main()
@@ -574,77 +636,77 @@ EOF
exit(0);
}
EOF
- if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
then
- echo "$SYSTEM_NAME"
+ GUESS=$SYSTEM_NAME
else
- echo rs6000-ibm-aix3.2.5
+ GUESS=rs6000-ibm-aix3.2.5
fi
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
- echo rs6000-ibm-aix3.2.4
+ GUESS=rs6000-ibm-aix3.2.4
else
- echo rs6000-ibm-aix3.2
+ GUESS=rs6000-ibm-aix3.2
fi
- exit ;;
+ ;;
*:AIX:*:[4567])
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
- if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
fi
- if [ -x /usr/bin/lslpp ] ; then
- IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+ if test -x /usr/bin/lslpp ; then
+ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \
awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
fi
- echo ${IBM_ARCH}-ibm-aix${IBM_REV}
- exit ;;
+ GUESS=$IBM_ARCH-ibm-aix$IBM_REV
+ ;;
*:AIX:*:*)
- echo rs6000-ibm-aix
- exit ;;
- ibmrt:4.4BSD:*|romp-ibm:BSD:*)
- echo romp-ibm-bsd4.4
- exit ;;
+ GUESS=rs6000-ibm-aix
+ ;;
+ ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
+ GUESS=romp-ibm-bsd4.4
+ ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
- echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
- exit ;; # report: romp-ibm BSD 4.3
+ GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to
+ ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
- echo rs6000-bull-bosx
- exit ;;
+ GUESS=rs6000-bull-bosx
+ ;;
DPX/2?00:B.O.S.:*:*)
- echo m68k-bull-sysv3
- exit ;;
+ GUESS=m68k-bull-sysv3
+ ;;
9000/[34]??:4.3bsd:1.*:*)
- echo m68k-hp-bsd
- exit ;;
+ GUESS=m68k-hp-bsd
+ ;;
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
- echo m68k-hp-bsd4.4
- exit ;;
+ GUESS=m68k-hp-bsd4.4
+ ;;
9000/[34678]??:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- case "${UNAME_MACHINE}" in
- 9000/31? ) HP_ARCH=m68000 ;;
- 9000/[34]?? ) HP_ARCH=m68k ;;
+ HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
+ case $UNAME_MACHINE in
+ 9000/31?) HP_ARCH=m68000 ;;
+ 9000/[34]??) HP_ARCH=m68k ;;
9000/[678][0-9][0-9])
- if [ -x /usr/bin/getconf ]; then
+ if test -x /usr/bin/getconf; then
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
- case "${sc_cpu_version}" in
- 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
- 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ case $sc_cpu_version in
+ 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
- case "${sc_kernel_bits}" in
- 32) HP_ARCH="hppa2.0n" ;;
- 64) HP_ARCH="hppa2.0w" ;;
- '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ case $sc_kernel_bits in
+ 32) HP_ARCH=hppa2.0n ;;
+ 64) HP_ARCH=hppa2.0w ;;
+ '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
esac ;;
esac
fi
- if [ "${HP_ARCH}" = "" ]; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ if test "$HP_ARCH" = ""; then
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
#define _HPUX_SOURCE
#include
@@ -677,13 +739,13 @@ EOF
exit (0);
}
EOF
- (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
test -z "$HP_ARCH" && HP_ARCH=hppa
fi ;;
esac
- if [ ${HP_ARCH} = "hppa2.0w" ]
+ if test "$HP_ARCH" = hppa2.0w
then
- eval $set_cc_for_build
+ set_cc_for_build
# hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
# 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
@@ -694,23 +756,23 @@ EOF
# $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
# => hppa64-hp-hpux11.23
- if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
grep -q __LP64__
then
- HP_ARCH="hppa2.0w"
+ HP_ARCH=hppa2.0w
else
- HP_ARCH="hppa64"
+ HP_ARCH=hppa64
fi
fi
- echo ${HP_ARCH}-hp-hpux${HPUX_REV}
- exit ;;
+ GUESS=$HP_ARCH-hp-hpux$HPUX_REV
+ ;;
ia64:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- echo ia64-hp-hpux${HPUX_REV}
- exit ;;
+ HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
+ GUESS=ia64-hp-hpux$HPUX_REV
+ ;;
3050*:HI-UX:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
#include
int
main ()
@@ -735,38 +797,38 @@ EOF
exit (0);
}
EOF
- $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
{ echo "$SYSTEM_NAME"; exit; }
- echo unknown-hitachi-hiuxwe2
- exit ;;
- 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
- echo hppa1.1-hp-bsd
- exit ;;
+ GUESS=unknown-hitachi-hiuxwe2
+ ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
+ GUESS=hppa1.1-hp-bsd
+ ;;
9000/8??:4.3bsd:*:*)
- echo hppa1.0-hp-bsd
- exit ;;
+ GUESS=hppa1.0-hp-bsd
+ ;;
*9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
- echo hppa1.0-hp-mpeix
- exit ;;
- hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
- echo hppa1.1-hp-osf
- exit ;;
+ GUESS=hppa1.0-hp-mpeix
+ ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
+ GUESS=hppa1.1-hp-osf
+ ;;
hp8??:OSF1:*:*)
- echo hppa1.0-hp-osf
- exit ;;
+ GUESS=hppa1.0-hp-osf
+ ;;
i*86:OSF1:*:*)
- if [ -x /usr/sbin/sysversion ] ; then
- echo ${UNAME_MACHINE}-unknown-osf1mk
+ if test -x /usr/sbin/sysversion ; then
+ GUESS=$UNAME_MACHINE-unknown-osf1mk
else
- echo ${UNAME_MACHINE}-unknown-osf1
+ GUESS=$UNAME_MACHINE-unknown-osf1
fi
- exit ;;
+ ;;
parisc*:Lites*:*:*)
- echo hppa1.1-hp-lites
- exit ;;
+ GUESS=hppa1.1-hp-lites
+ ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
- echo c1-convex-bsd
- exit ;;
+ GUESS=c1-convex-bsd
+ ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
@@ -774,139 +836,145 @@ EOF
fi
exit ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
- echo c34-convex-bsd
- exit ;;
+ GUESS=c34-convex-bsd
+ ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
- echo c38-convex-bsd
- exit ;;
+ GUESS=c38-convex-bsd
+ ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
- echo c4-convex-bsd
- exit ;;
+ GUESS=c4-convex-bsd
+ ;;
CRAY*Y-MP:*:*:*)
- echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=ymp-cray-unicos$CRAY_REL
+ ;;
CRAY*[A-Z]90:*:*:*)
- echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
-e 's/\.[^.]*$/.X/'
exit ;;
CRAY*TS:*:*:*)
- echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=t90-cray-unicos$CRAY_REL
+ ;;
CRAY*T3E:*:*:*)
- echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=alphaev5-cray-unicosmk$CRAY_REL
+ ;;
CRAY*SV1:*:*:*)
- echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=sv1-cray-unicos$CRAY_REL
+ ;;
*:UNICOS/mp:*:*)
- echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=craynv-cray-unicosmp$CRAY_REL
+ ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
- FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
- echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit ;;
+ FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
+ GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
+ ;;
5000:UNIX_System_V:4.*:*)
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
- echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit ;;
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
+ GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
+ ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
- echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE
+ ;;
sparc*:BSD/OS:*:*)
- echo sparc-unknown-bsdi${UNAME_RELEASE}
- exit ;;
+ GUESS=sparc-unknown-bsdi$UNAME_RELEASE
+ ;;
*:BSD/OS:*:*)
- echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE
+ ;;
+ arm:FreeBSD:*:*)
+ UNAME_PROCESSOR=`uname -p`
+ set_cc_for_build
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi
+ else
+ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf
+ fi
+ ;;
*:FreeBSD:*:*)
UNAME_PROCESSOR=`/usr/bin/uname -p`
- case ${UNAME_PROCESSOR} in
+ case $UNAME_PROCESSOR in
amd64)
- echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
- *)
- echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ UNAME_PROCESSOR=x86_64 ;;
+ i386)
+ UNAME_PROCESSOR=i586 ;;
esac
- exit ;;
+ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL
+ ;;
i*:CYGWIN*:*)
- echo ${UNAME_MACHINE}-pc-cygwin
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-cygwin
+ ;;
*:MINGW64*:*)
- echo ${UNAME_MACHINE}-pc-mingw64
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-mingw64
+ ;;
*:MINGW*:*)
- echo ${UNAME_MACHINE}-pc-mingw32
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-mingw32
+ ;;
*:MSYS*:*)
- echo ${UNAME_MACHINE}-pc-msys
- exit ;;
- i*:windows32*:*)
- # uname -m includes "-pc" on this system.
- echo ${UNAME_MACHINE}-mingw32
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-msys
+ ;;
i*:PW*:*)
- echo ${UNAME_MACHINE}-pc-pw32
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-pw32
+ ;;
*:Interix*:*)
- case ${UNAME_MACHINE} in
+ case $UNAME_MACHINE in
x86)
- echo i586-pc-interix${UNAME_RELEASE}
- exit ;;
+ GUESS=i586-pc-interix$UNAME_RELEASE
+ ;;
authenticamd | genuineintel | EM64T)
- echo x86_64-unknown-interix${UNAME_RELEASE}
- exit ;;
+ GUESS=x86_64-unknown-interix$UNAME_RELEASE
+ ;;
IA64)
- echo ia64-unknown-interix${UNAME_RELEASE}
- exit ;;
+ GUESS=ia64-unknown-interix$UNAME_RELEASE
+ ;;
esac ;;
- [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
- echo i${UNAME_MACHINE}-pc-mks
- exit ;;
- 8664:Windows_NT:*)
- echo x86_64-pc-mks
- exit ;;
- i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
- # UNAME_MACHINE based on the output of uname instead of i386?
- echo i586-pc-interix
- exit ;;
i*:UWIN*:*)
- echo ${UNAME_MACHINE}-pc-uwin
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-uwin
+ ;;
amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
- echo x86_64-unknown-cygwin
- exit ;;
- p*:CYGWIN*:*)
- echo powerpcle-unknown-cygwin
- exit ;;
+ GUESS=x86_64-pc-cygwin
+ ;;
prep*:SunOS:5.*:*)
- echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=powerpcle-unknown-solaris2$SUN_REL
+ ;;
*:GNU:*:*)
# the GNU system
- echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
- exit ;;
+ GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'`
+ GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'`
+ GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL
+ ;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
- echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
- exit ;;
- i*86:Minix:*:*)
- echo ${UNAME_MACHINE}-pc-minix
- exit ;;
+ GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"`
+ GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC
+ ;;
+ *:Minix:*:*)
+ GUESS=$UNAME_MACHINE-unknown-minix
+ ;;
aarch64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
alpha:Linux:*:*)
- case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in
EV5) UNAME_MACHINE=alphaev5 ;;
EV56) UNAME_MACHINE=alphaev56 ;;
PCA56) UNAME_MACHINE=alphapca56 ;;
@@ -916,175 +984,226 @@ EOF
EV68*) UNAME_MACHINE=alphaev68 ;;
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
- if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
- arc:Linux:*:* | arceb:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
arm*:Linux:*:*)
- eval $set_cc_for_build
+ set_cc_for_build
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
else
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+ GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi
else
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+ GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf
fi
fi
- exit ;;
+ ;;
avr32*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
cris:Linux:*:*)
- echo ${UNAME_MACHINE}-axis-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-axis-linux-$LIBC
+ ;;
crisv32:Linux:*:*)
- echo ${UNAME_MACHINE}-axis-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-axis-linux-$LIBC
+ ;;
e2k:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
frv:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
hexagon:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
i*86:Linux:*:*)
- echo ${UNAME_MACHINE}-pc-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-linux-$LIBC
+ ;;
ia64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ k1om:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
m32r*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
m68*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
mips:Linux:*:* | mips64:Linux:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ set_cc_for_build
+ IS_GLIBC=0
+ test x"${LIBC}" = xgnu && IS_GLIBC=1
+ sed 's/^ //' << EOF > "$dummy.c"
#undef CPU
- #undef ${UNAME_MACHINE}
- #undef ${UNAME_MACHINE}el
+ #undef mips
+ #undef mipsel
+ #undef mips64
+ #undef mips64el
+ #if ${IS_GLIBC} && defined(_ABI64)
+ LIBCABI=gnuabi64
+ #else
+ #if ${IS_GLIBC} && defined(_ABIN32)
+ LIBCABI=gnuabin32
+ #else
+ LIBCABI=${LIBC}
+ #endif
+ #endif
+
+ #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+ CPU=mipsisa64r6
+ #else
+ #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+ CPU=mipsisa32r6
+ #else
+ #if defined(__mips64)
+ CPU=mips64
+ #else
+ CPU=mips
+ #endif
+ #endif
+ #endif
+
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- CPU=${UNAME_MACHINE}el
+ MIPS_ENDIAN=el
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- CPU=${UNAME_MACHINE}
+ MIPS_ENDIAN=
#else
- CPU=
+ MIPS_ENDIAN=
#endif
#endif
EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+ cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`
+ eval "$cc_set_vars"
+ test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
+ ;;
+ mips64el:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
openrisc*:Linux:*:*)
- echo or1k-unknown-linux-${LIBC}
- exit ;;
+ GUESS=or1k-unknown-linux-$LIBC
+ ;;
or32:Linux:*:* | or1k*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
padre:Linux:*:*)
- echo sparc-unknown-linux-${LIBC}
- exit ;;
+ GUESS=sparc-unknown-linux-$LIBC
+ ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-unknown-linux-${LIBC}
- exit ;;
+ GUESS=hppa64-unknown-linux-$LIBC
+ ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
- PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
- PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
- *) echo hppa-unknown-linux-${LIBC} ;;
+ PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;;
+ PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;;
+ *) GUESS=hppa-unknown-linux-$LIBC ;;
esac
- exit ;;
+ ;;
ppc64:Linux:*:*)
- echo powerpc64-unknown-linux-${LIBC}
- exit ;;
+ GUESS=powerpc64-unknown-linux-$LIBC
+ ;;
ppc:Linux:*:*)
- echo powerpc-unknown-linux-${LIBC}
- exit ;;
+ GUESS=powerpc-unknown-linux-$LIBC
+ ;;
ppc64le:Linux:*:*)
- echo powerpc64le-unknown-linux-${LIBC}
- exit ;;
+ GUESS=powerpc64le-unknown-linux-$LIBC
+ ;;
ppcle:Linux:*:*)
- echo powerpcle-unknown-linux-${LIBC}
- exit ;;
+ GUESS=powerpcle-unknown-linux-$LIBC
+ ;;
+ riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
s390:Linux:*:* | s390x:Linux:*:*)
- echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-ibm-linux-$LIBC
+ ;;
sh64*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
sh*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
tile*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
vax:Linux:*:*)
- echo ${UNAME_MACHINE}-dec-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-dec-linux-$LIBC
+ ;;
x86_64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ set_cc_for_build
+ LIBCABI=$LIBC
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
+ if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_X32 >/dev/null
+ then
+ LIBCABI=${LIBC}x32
+ fi
+ fi
+ GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI
+ ;;
xtensa*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
# earlier versions are messed up and put the nodename in both
# sysname and nodename.
- echo i386-sequent-sysv4
- exit ;;
+ GUESS=i386-sequent-sysv4
+ ;;
i*86:UNIX_SV:4.2MP:2.*)
# Unixware is an offshoot of SVR4, but it has its own version
# number series starting with 2...
# I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
# Use sysv4.2uw... so that sysv4* matches it.
- echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION
+ ;;
i*86:OS/2:*:*)
# If we were able to find `uname', then EMX Unix compatibility
# is probably installed.
- echo ${UNAME_MACHINE}-pc-os2-emx
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-os2-emx
+ ;;
i*86:XTS-300:*:STOP)
- echo ${UNAME_MACHINE}-unknown-stop
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-stop
+ ;;
i*86:atheos:*:*)
- echo ${UNAME_MACHINE}-unknown-atheos
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-atheos
+ ;;
i*86:syllable:*:*)
- echo ${UNAME_MACHINE}-pc-syllable
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-syllable
+ ;;
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
- echo i386-unknown-lynxos${UNAME_RELEASE}
- exit ;;
+ GUESS=i386-unknown-lynxos$UNAME_RELEASE
+ ;;
i*86:*DOS:*:*)
- echo ${UNAME_MACHINE}-pc-msdosdjgpp
- exit ;;
- i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
- UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ GUESS=$UNAME_MACHINE-pc-msdosdjgpp
+ ;;
+ i*86:*:4.*:*)
+ UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
- echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL
else
- echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL
fi
- exit ;;
+ ;;
i*86:*:5:[678]*)
# UnixWare 7.x, OpenUNIX and OpenServer 6.
case `/bin/uname -X | grep "^Machine"` in
@@ -1092,12 +1211,12 @@ EOF
*Pentium) UNAME_MACHINE=i586 ;;
*Pent*|*Celeron) UNAME_MACHINE=i686 ;;
esac
- echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ ;;
i*86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then
UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
@@ -1107,43 +1226,43 @@ EOF
&& UNAME_MACHINE=i686
(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
&& UNAME_MACHINE=i686
- echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL
else
- echo ${UNAME_MACHINE}-pc-sysv32
+ GUESS=$UNAME_MACHINE-pc-sysv32
fi
- exit ;;
+ ;;
pc:*:*:*)
# Left here for compatibility:
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i586.
# Note: whatever this is, it MUST be the same as what config.sub
- # prints for the "djgpp" host, or else GDB configury will decide that
+ # prints for the "djgpp" host, or else GDB configure will decide that
# this is a cross-build.
- echo i586-pc-msdosdjgpp
- exit ;;
+ GUESS=i586-pc-msdosdjgpp
+ ;;
Intel:Mach:3*:*)
- echo i386-pc-mach3
- exit ;;
+ GUESS=i386-pc-mach3
+ ;;
paragon:*:*:*)
- echo i860-intel-osf1
- exit ;;
+ GUESS=i860-intel-osf1
+ ;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
- echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
- echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4
fi
- exit ;;
+ ;;
mini*:CTIX:SYS*5:*)
# "miniframe"
- echo m68010-convergent-sysv
- exit ;;
+ GUESS=m68010-convergent-sysv
+ ;;
mc68k:UNIX:SYSTEM5:3.51m)
- echo m68k-convergent-sysv
- exit ;;
+ GUESS=m68k-convergent-sysv
+ ;;
M680?0:D-NIX:5.3:*)
- echo m68k-diab-dnix
- exit ;;
+ GUESS=m68k-diab-dnix
+ ;;
M68*:*:R3V[5678]*:*)
test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
@@ -1151,9 +1270,9 @@ EOF
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4; exit; } ;;
@@ -1162,248 +1281,438 @@ EOF
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
- echo m68k-unknown-lynxos${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-unknown-lynxos$UNAME_RELEASE
+ ;;
mc68030:UNIX_System_V:4.*:*)
- echo m68k-atari-sysv4
- exit ;;
+ GUESS=m68k-atari-sysv4
+ ;;
TSUNAMI:LynxOS:2.*:*)
- echo sparc-unknown-lynxos${UNAME_RELEASE}
- exit ;;
+ GUESS=sparc-unknown-lynxos$UNAME_RELEASE
+ ;;
rs6000:LynxOS:2.*:*)
- echo rs6000-unknown-lynxos${UNAME_RELEASE}
- exit ;;
+ GUESS=rs6000-unknown-lynxos$UNAME_RELEASE
+ ;;
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
- echo powerpc-unknown-lynxos${UNAME_RELEASE}
- exit ;;
+ GUESS=powerpc-unknown-lynxos$UNAME_RELEASE
+ ;;
SM[BE]S:UNIX_SV:*:*)
- echo mips-dde-sysv${UNAME_RELEASE}
- exit ;;
+ GUESS=mips-dde-sysv$UNAME_RELEASE
+ ;;
RM*:ReliantUNIX-*:*:*)
- echo mips-sni-sysv4
- exit ;;
+ GUESS=mips-sni-sysv4
+ ;;
RM*:SINIX-*:*:*)
- echo mips-sni-sysv4
- exit ;;
+ GUESS=mips-sni-sysv4
+ ;;
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=`(uname -p) 2>/dev/null`
- echo ${UNAME_MACHINE}-sni-sysv4
+ GUESS=$UNAME_MACHINE-sni-sysv4
else
- echo ns32k-sni-sysv
+ GUESS=ns32k-sni-sysv
fi
- exit ;;
+ ;;
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
# says
- echo i586-unisys-sysv4
- exit ;;
+ GUESS=i586-unisys-sysv4
+ ;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes .
# How about differentiating between stratus architectures? -djm
- echo hppa1.1-stratus-sysv4
- exit ;;
+ GUESS=hppa1.1-stratus-sysv4
+ ;;
*:*:*:FTX*)
# From seanf@swdc.stratus.com.
- echo i860-stratus-sysv4
- exit ;;
+ GUESS=i860-stratus-sysv4
+ ;;
i*86:VOS:*:*)
# From Paul.Green@stratus.com.
- echo ${UNAME_MACHINE}-stratus-vos
- exit ;;
+ GUESS=$UNAME_MACHINE-stratus-vos
+ ;;
*:VOS:*:*)
# From Paul.Green@stratus.com.
- echo hppa1.1-stratus-vos
- exit ;;
+ GUESS=hppa1.1-stratus-vos
+ ;;
mc68*:A/UX:*:*)
- echo m68k-apple-aux${UNAME_RELEASE}
- exit ;;
+ GUESS=m68k-apple-aux$UNAME_RELEASE
+ ;;
news*:NEWS-OS:6*:*)
- echo mips-sony-newsos6
- exit ;;
+ GUESS=mips-sony-newsos6
+ ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
- if [ -d /usr/nec ]; then
- echo mips-nec-sysv${UNAME_RELEASE}
+ if test -d /usr/nec; then
+ GUESS=mips-nec-sysv$UNAME_RELEASE
else
- echo mips-unknown-sysv${UNAME_RELEASE}
+ GUESS=mips-unknown-sysv$UNAME_RELEASE
fi
- exit ;;
+ ;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
- echo powerpc-be-beos
- exit ;;
+ GUESS=powerpc-be-beos
+ ;;
BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
- echo powerpc-apple-beos
- exit ;;
+ GUESS=powerpc-apple-beos
+ ;;
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
- echo i586-pc-beos
- exit ;;
+ GUESS=i586-pc-beos
+ ;;
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
- echo i586-pc-haiku
- exit ;;
+ GUESS=i586-pc-haiku
+ ;;
x86_64:Haiku:*:*)
- echo x86_64-unknown-haiku
- exit ;;
+ GUESS=x86_64-unknown-haiku
+ ;;
SX-4:SUPER-UX:*:*)
- echo sx4-nec-superux${UNAME_RELEASE}
- exit ;;
+ GUESS=sx4-nec-superux$UNAME_RELEASE
+ ;;
SX-5:SUPER-UX:*:*)
- echo sx5-nec-superux${UNAME_RELEASE}
- exit ;;
+ GUESS=sx5-nec-superux$UNAME_RELEASE
+ ;;
SX-6:SUPER-UX:*:*)
- echo sx6-nec-superux${UNAME_RELEASE}
- exit ;;
+ GUESS=sx6-nec-superux$UNAME_RELEASE
+ ;;
SX-7:SUPER-UX:*:*)
- echo sx7-nec-superux${UNAME_RELEASE}
- exit ;;
+ GUESS=sx7-nec-superux$UNAME_RELEASE
+ ;;
SX-8:SUPER-UX:*:*)
- echo sx8-nec-superux${UNAME_RELEASE}
- exit ;;
+ GUESS=sx8-nec-superux$UNAME_RELEASE
+ ;;
SX-8R:SUPER-UX:*:*)
- echo sx8r-nec-superux${UNAME_RELEASE}
- exit ;;
+ GUESS=sx8r-nec-superux$UNAME_RELEASE
+ ;;
+ SX-ACE:SUPER-UX:*:*)
+ GUESS=sxace-nec-superux$UNAME_RELEASE
+ ;;
Power*:Rhapsody:*:*)
- echo powerpc-apple-rhapsody${UNAME_RELEASE}
- exit ;;
+ GUESS=powerpc-apple-rhapsody$UNAME_RELEASE
+ ;;
*:Rhapsody:*:*)
- echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE
+ ;;
+ arm64:Darwin:*:*)
+ GUESS=aarch64-apple-darwin$UNAME_RELEASE
+ ;;
*:Darwin:*:*)
- UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
- eval $set_cc_for_build
- if test "$UNAME_PROCESSOR" = unknown ; then
- UNAME_PROCESSOR=powerpc
+ UNAME_PROCESSOR=`uname -p`
+ case $UNAME_PROCESSOR in
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ if command -v xcode-select > /dev/null 2> /dev/null && \
+ ! xcode-select --print-path > /dev/null 2> /dev/null ; then
+ # Avoid executing cc if there is no toolchain installed as
+ # cc will be a stub that puts up a graphical alert
+ # prompting the user to install developer tools.
+ CC_FOR_BUILD=no_compiler_found
+ else
+ set_cc_for_build
fi
- if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
- if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_64BIT_ARCH >/dev/null
- then
- case $UNAME_PROCESSOR in
- i386) UNAME_PROCESSOR=x86_64 ;;
- powerpc) UNAME_PROCESSOR=powerpc64 ;;
- esac
- fi
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
+ fi
+ # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
+ if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_PPC >/dev/null
+ then
+ UNAME_PROCESSOR=powerpc
fi
elif test "$UNAME_PROCESSOR" = i386 ; then
- # Avoid executing cc on OS X 10.9, as it ships with a stub
- # that puts up a graphical alert prompting to install
- # developer tools. Any system running Mac OS X 10.7 or
- # later (Darwin 11 and later) is required to have a 64-bit
- # processor. This is not true of the ARM version of Darwin
- # that Apple uses in portable devices.
- UNAME_PROCESSOR=x86_64
+ # uname -m returns i386 or x86_64
+ UNAME_PROCESSOR=$UNAME_MACHINE
fi
- echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE
+ ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
UNAME_PROCESSOR=`uname -p`
- if test "$UNAME_PROCESSOR" = "x86"; then
+ if test "$UNAME_PROCESSOR" = x86; then
UNAME_PROCESSOR=i386
UNAME_MACHINE=pc
fi
- echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE
+ ;;
*:QNX:*:4*)
- echo i386-pc-qnx
- exit ;;
- NEO-?:NONSTOP_KERNEL:*:*)
- echo neo-tandem-nsk${UNAME_RELEASE}
- exit ;;
+ GUESS=i386-pc-qnx
+ ;;
+ NEO-*:NONSTOP_KERNEL:*:*)
+ GUESS=neo-tandem-nsk$UNAME_RELEASE
+ ;;
NSE-*:NONSTOP_KERNEL:*:*)
- echo nse-tandem-nsk${UNAME_RELEASE}
- exit ;;
- NSR-?:NONSTOP_KERNEL:*:*)
- echo nsr-tandem-nsk${UNAME_RELEASE}
- exit ;;
+ GUESS=nse-tandem-nsk$UNAME_RELEASE
+ ;;
+ NSR-*:NONSTOP_KERNEL:*:*)
+ GUESS=nsr-tandem-nsk$UNAME_RELEASE
+ ;;
+ NSV-*:NONSTOP_KERNEL:*:*)
+ GUESS=nsv-tandem-nsk$UNAME_RELEASE
+ ;;
+ NSX-*:NONSTOP_KERNEL:*:*)
+ GUESS=nsx-tandem-nsk$UNAME_RELEASE
+ ;;
*:NonStop-UX:*:*)
- echo mips-compaq-nonstopux
- exit ;;
+ GUESS=mips-compaq-nonstopux
+ ;;
BS2000:POSIX*:*:*)
- echo bs2000-siemens-sysv
- exit ;;
+ GUESS=bs2000-siemens-sysv
+ ;;
DS/*:UNIX_System_V:*:*)
- echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
- exit ;;
+ GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE
+ ;;
*:Plan9:*:*)
# "uname -m" is not consistent, so use $cputype instead. 386
# is converted to i386 for consistency with other x86
# operating systems.
- if test "$cputype" = "386"; then
+ if test "${cputype-}" = 386; then
UNAME_MACHINE=i386
- else
- UNAME_MACHINE="$cputype"
+ elif test "x${cputype-}" != x; then
+ UNAME_MACHINE=$cputype
fi
- echo ${UNAME_MACHINE}-unknown-plan9
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-plan9
+ ;;
*:TOPS-10:*:*)
- echo pdp10-unknown-tops10
- exit ;;
+ GUESS=pdp10-unknown-tops10
+ ;;
*:TENEX:*:*)
- echo pdp10-unknown-tenex
- exit ;;
+ GUESS=pdp10-unknown-tenex
+ ;;
KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
- echo pdp10-dec-tops20
- exit ;;
+ GUESS=pdp10-dec-tops20
+ ;;
XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
- echo pdp10-xkl-tops20
- exit ;;
+ GUESS=pdp10-xkl-tops20
+ ;;
*:TOPS-20:*:*)
- echo pdp10-unknown-tops20
- exit ;;
+ GUESS=pdp10-unknown-tops20
+ ;;
*:ITS:*:*)
- echo pdp10-unknown-its
- exit ;;
+ GUESS=pdp10-unknown-its
+ ;;
SEI:*:*:SEIUX)
- echo mips-sei-seiux${UNAME_RELEASE}
- exit ;;
+ GUESS=mips-sei-seiux$UNAME_RELEASE
+ ;;
*:DragonFly:*:*)
- echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
- exit ;;
+ DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL
+ ;;
*:*VMS:*:*)
UNAME_MACHINE=`(uname -p) 2>/dev/null`
- case "${UNAME_MACHINE}" in
- A*) echo alpha-dec-vms ; exit ;;
- I*) echo ia64-dec-vms ; exit ;;
- V*) echo vax-dec-vms ; exit ;;
+ case $UNAME_MACHINE in
+ A*) GUESS=alpha-dec-vms ;;
+ I*) GUESS=ia64-dec-vms ;;
+ V*) GUESS=vax-dec-vms ;;
esac ;;
*:XENIX:*:SysV)
- echo i386-pc-xenix
- exit ;;
+ GUESS=i386-pc-xenix
+ ;;
i*86:skyos:*:*)
- echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
- exit ;;
+ SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`
+ GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL
+ ;;
i*86:rdos:*:*)
- echo ${UNAME_MACHINE}-pc-rdos
- exit ;;
- i*86:AROS:*:*)
- echo ${UNAME_MACHINE}-pc-aros
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-rdos
+ ;;
+ *:AROS:*:*)
+ GUESS=$UNAME_MACHINE-unknown-aros
+ ;;
x86_64:VMkernel:*:*)
- echo ${UNAME_MACHINE}-unknown-esx
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-esx
+ ;;
+ amd64:Isilon\ OneFS:*:*)
+ GUESS=x86_64-unknown-onefs
+ ;;
+ *:Unleashed:*:*)
+ GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
+ ;;
+esac
+
+# Do we have a guess based on uname results?
+if test "x$GUESS" != x; then
+ echo "$GUESS"
+ exit
+fi
+
+# No uname command or uname output not recognized.
+set_cc_for_build
+cat > "$dummy.c" <
+#include
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#include
+#if defined(_SIZE_T_) || defined(SIGLOST)
+#include
+#endif
+#endif
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+#include
+#if defined (BSD)
+#if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+#else
+#if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#else
+ printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#endif
+#else
+ printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#else
+#if defined(_SIZE_T_) || defined(SIGLOST)
+ struct utsname un;
+ uname (&un);
+ printf ("vax-dec-ultrix%s\n", un.release); exit (0);
+#else
+ printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#if defined(_SIZE_T_) || defined(SIGLOST)
+ struct utsname *un;
+ uname (&un);
+ printf ("mips-dec-ultrix%s\n", un.release); exit (0);
+#else
+ printf ("mips-dec-ultrix\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; }
+
+echo "$0: unable to guess system type" >&2
+
+case $UNAME_MACHINE:$UNAME_SYSTEM in
+ mips:Linux | mips64:Linux)
+ # If we got here on MIPS GNU/Linux, output extra information.
+ cat >&2 <&2 < in order to provide the needed
-information to handle your system.
+our_year=`echo $timestamp | sed 's,-.*,,'`
+thisyear=`date +%Y`
+# shellcheck disable=SC2003
+script_age=`expr "$thisyear" - "$our_year"`
+if test "$script_age" -lt 3 ; then
+ cat >&2 </dev/null`
/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
-UNAME_MACHINE = ${UNAME_MACHINE}
-UNAME_RELEASE = ${UNAME_RELEASE}
-UNAME_SYSTEM = ${UNAME_SYSTEM}
-UNAME_VERSION = ${UNAME_VERSION}
+UNAME_MACHINE = "$UNAME_MACHINE"
+UNAME_RELEASE = "$UNAME_RELEASE"
+UNAME_SYSTEM = "$UNAME_SYSTEM"
+UNAME_VERSION = "$UNAME_VERSION"
EOF
+fi
exit 1
# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
+# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
diff --git a/autoconf/config.sub b/autoconf/config.sub
index 8f1229c..d74fb6d 100644
--- a/autoconf/config.sub
+++ b/autoconf/config.sub
@@ -1,8 +1,10 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright 1992-2015 Free Software Foundation, Inc.
+# Copyright 1992-2021 Free Software Foundation, Inc.
-timestamp='2015-03-08'
+# shellcheck disable=SC2006,SC2268 # see below for rationale
+
+timestamp='2021-08-14'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -15,7 +17,7 @@ timestamp='2015-03-08'
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with this program; if not, see .
+# along with this program; if not, see .
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@@ -33,7 +35,7 @@ timestamp='2015-03-08'
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
@@ -50,15 +52,21 @@ timestamp='2015-03-08'
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
+# The "shellcheck disable" line above the timestamp inhibits complaints
+# about features and limitations of the classic Bourne shell that were
+# superseded or lifted in POSIX. However, this script identifies a wide
+# variety of pre-POSIX systems that do not have POSIX shells at all, and
+# even some reasonably current systems (Solaris 10 as case-in-point) still
+# have a pre-POSIX /bin/sh.
+
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
-Usage: $0 [OPTION] CPU-MFR-OPSYS
- $0 [OPTION] ALIAS
+Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
Canonicalize a configuration name.
-Operation modes:
+Options:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
@@ -68,7 +76,7 @@ Report bugs and patches to ."
version="\
GNU config.sub ($timestamp)
-Copyright 1992-2015 Free Software Foundation, Inc.
+Copyright 1992-2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -90,12 +98,12 @@ while test $# -gt 0 ; do
- ) # Use stdin as input.
break ;;
-* )
- echo "$me: invalid option $1$help"
+ echo "$me: invalid option $1$help" >&2
exit 1 ;;
*local*)
# First pass through any local machine types.
- echo $1
+ echo "$1"
exit ;;
* )
@@ -111,1231 +119,1181 @@ case $# in
exit 1;;
esac
-# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
-# Here we must recognize all the valid KERNEL-OS combinations.
-maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
-case $maybe_os in
- nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
- linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
- knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
- kopensolaris*-gnu* | \
- storm-chaos* | os2-emx* | rtmk-nova*)
- os=-$maybe_os
- basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
- ;;
- android-linux)
- os=-linux-android
- basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
- ;;
- *)
- basic_machine=`echo $1 | sed 's/-[^-]*$//'`
- if [ $basic_machine != $1 ]
- then os=`echo $1 | sed 's/.*-/-/'`
- else os=; fi
- ;;
-esac
+# Split fields of configuration type
+# shellcheck disable=SC2162
+saved_IFS=$IFS
+IFS="-" read field1 field2 field3 field4 <&2
+ exit 1
;;
- -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
- -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
- -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
- -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
- -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
- -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
- -apple | -axis | -knuth | -cray | -microblaze*)
- os=
- basic_machine=$1
+ *-*-*-*)
+ basic_machine=$field1-$field2
+ basic_os=$field3-$field4
;;
- -bluegene*)
- os=-cnk
+ *-*-*)
+ # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
+ # parts
+ maybe_os=$field2-$field3
+ case $maybe_os in
+ nto-qnx* | linux-* | uclinux-uclibc* \
+ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
+ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
+ | storm-chaos* | os2-emx* | rtmk-nova*)
+ basic_machine=$field1
+ basic_os=$maybe_os
+ ;;
+ android-linux)
+ basic_machine=$field1-unknown
+ basic_os=linux-android
+ ;;
+ *)
+ basic_machine=$field1-$field2
+ basic_os=$field3
+ ;;
+ esac
;;
- -sim | -cisco | -oki | -wec | -winbond)
- os=
- basic_machine=$1
+ *-*)
+ # A lone config we happen to match not fitting any pattern
+ case $field1-$field2 in
+ decstation-3100)
+ basic_machine=mips-dec
+ basic_os=
+ ;;
+ *-*)
+ # Second component is usually, but not always the OS
+ case $field2 in
+ # Prevent following clause from handling this valid os
+ sun*os*)
+ basic_machine=$field1
+ basic_os=$field2
+ ;;
+ zephyr*)
+ basic_machine=$field1-unknown
+ basic_os=$field2
+ ;;
+ # Manufacturers
+ dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \
+ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
+ | unicom* | ibm* | next | hp | isi* | apollo | altos* \
+ | convergent* | ncr* | news | 32* | 3600* | 3100* \
+ | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \
+ | ultra | tti* | harris | dolphin | highlevel | gould \
+ | cbm | ns | masscomp | apple | axis | knuth | cray \
+ | microblaze* | sim | cisco \
+ | oki | wec | wrs | winbond)
+ basic_machine=$field1-$field2
+ basic_os=
+ ;;
+ *)
+ basic_machine=$field1
+ basic_os=$field2
+ ;;
+ esac
+ ;;
+ esac
;;
- -scout)
- ;;
- -wrs)
- os=-vxworks
- basic_machine=$1
- ;;
- -chorusos*)
- os=-chorusos
- basic_machine=$1
- ;;
- -chorusrdb)
- os=-chorusrdb
- basic_machine=$1
- ;;
- -hiux*)
- os=-hiuxwe2
- ;;
- -sco6)
- os=-sco5v6
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco5)
- os=-sco3.2v5
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco4)
- os=-sco3.2v4
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2.[4-9]*)
- os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2v[4-9]*)
- # Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco5v6*)
- # Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco*)
- os=-sco3.2v2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -udk*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -isc)
- os=-isc2.2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -clix*)
- basic_machine=clipper-intergraph
- ;;
- -isc*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -lynx*178)
- os=-lynxos178
- ;;
- -lynx*5)
- os=-lynxos5
- ;;
- -lynx*)
- os=-lynxos
- ;;
- -ptx*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
- ;;
- -windowsnt*)
- os=`echo $os | sed -e 's/windowsnt/winnt/'`
- ;;
- -psos*)
- os=-psos
- ;;
- -mint | -mint[0-9]*)
- basic_machine=m68k-atari
- os=-mint
+ *)
+ # Convert single-component short-hands not valid as part of
+ # multi-component configurations.
+ case $field1 in
+ 386bsd)
+ basic_machine=i386-pc
+ basic_os=bsd
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ basic_os=udi
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ basic_os=scout
+ ;;
+ alliant)
+ basic_machine=fx80-alliant
+ basic_os=
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ basic_os=
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ basic_os=bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ basic_os=sysv
+ ;;
+ amiga)
+ basic_machine=m68k-unknown
+ basic_os=
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ basic_os=amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ basic_os=sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ basic_os=sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ basic_os=bsd
+ ;;
+ aros)
+ basic_machine=i386-pc
+ basic_os=aros
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ basic_os=aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ basic_os=dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ basic_os=linux
+ ;;
+ cegcc)
+ basic_machine=arm-unknown
+ basic_os=cegcc
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ basic_os=bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ basic_os=bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ basic_os=bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ basic_os=bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ basic_os=bsd
+ ;;
+ cray)
+ basic_machine=j90-cray
+ basic_os=unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ basic_os=
+ ;;
+ da30)
+ basic_machine=m68k-da30
+ basic_os=
+ ;;
+ decstation | pmax | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ basic_os=
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ basic_os=sysv3
+ ;;
+ dicos)
+ basic_machine=i686-pc
+ basic_os=dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ basic_os=msdosdjgpp
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ basic_os=ebmon
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ basic_os=ose
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ basic_os=sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ basic_os=go32
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ basic_os=hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ basic_os=xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ basic_os=hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ basic_os=sysv3
+ ;;
+ hp300 | hp300hpux)
+ basic_machine=m68k-hp
+ basic_os=hpux
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ basic_os=bsd
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ basic_os=osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ basic_os=proelf
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ basic_os=mach
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ basic_os=sysv
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ basic_os=linux
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ basic_os=sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ basic_os=sysv
+ ;;
+ mingw64)
+ basic_machine=x86_64-pc
+ basic_os=mingw64
+ ;;
+ mingw32)
+ basic_machine=i686-pc
+ basic_os=mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ basic_os=mingw32ce
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ basic_os=coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ basic_os=morphos
+ ;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ basic_os=moxiebox
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ basic_os=msdos
+ ;;
+ msys)
+ basic_machine=i686-pc
+ basic_os=msys
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ basic_os=mvs
+ ;;
+ nacl)
+ basic_machine=le32-unknown
+ basic_os=nacl
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ basic_os=sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-pc
+ basic_os=netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ basic_os=linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ basic_os=newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ basic_os=newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ basic_os=sysv
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ basic_os=cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ basic_os=cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ basic_os=nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ basic_os=mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ basic_os=nonstopux
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ basic_os=os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ basic_os=ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ basic_os=os68k
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ basic_os=osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ basic_os=linux
+ ;;
+ psp)
+ basic_machine=mipsallegrexel-sony
+ basic_os=psp
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ basic_os=pw32
+ ;;
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ basic_os=rdos
+ ;;
+ rdos32)
+ basic_machine=i386-pc
+ basic_os=rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ basic_os=coff
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ basic_os=udi
+ ;;
+ sei)
+ basic_machine=mips-sei
+ basic_os=seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ basic_os=
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ basic_os=sysv2
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ basic_os=
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ basic_os=sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ basic_os=
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ basic_os=sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ basic_os=sunos4
+ ;;
+ sun3)
+ basic_machine=m68k-sun
+ basic_os=
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ basic_os=sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ basic_os=sunos4
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ basic_os=
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ basic_os=sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ basic_os=sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ basic_os=solaris2
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ basic_os=
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ basic_os=unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ basic_os=dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ basic_os=unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ basic_os=unicos
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ basic_os=tops20
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ basic_os=tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ basic_os=udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ basic_os=sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ basic_os=none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ basic_os=sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ basic_os=vms
+ ;;
+ vsta)
+ basic_machine=i386-pc
+ basic_os=vsta
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ basic_os=vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ basic_os=vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ basic_os=vxworks
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ basic_os=mingw32
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ basic_os=unicos
+ ;;
+ *)
+ basic_machine=$1
+ basic_os=
+ ;;
+ esac
;;
esac
-# Decode aliases for certain CPU-COMPANY combinations.
+# Decode 1-component or ad-hoc basic machines
case $basic_machine in
- # Recognize the basic CPU types without company name.
- # Some are omitted here because they have special meanings below.
- 1750a | 580 \
- | a29k \
- | aarch64 | aarch64_be \
- | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
- | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
- | am33_2.0 \
- | arc | arceb \
- | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
- | avr | avr32 \
- | be32 | be64 \
- | bfin \
- | c4x | c8051 | clipper \
- | d10v | d30v | dlx | dsp16xx \
- | e2k | epiphany \
- | fido | fr30 | frv | ft32 \
- | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
- | hexagon \
- | i370 | i860 | i960 | ia64 \
- | ip2k | iq2000 \
- | k1om \
- | le32 | le64 \
- | lm32 \
- | m32c | m32r | m32rle | m68000 | m68k | m88k \
- | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
- | mips | mipsbe | mipseb | mipsel | mipsle \
- | mips16 \
- | mips64 | mips64el \
- | mips64octeon | mips64octeonel \
- | mips64orion | mips64orionel \
- | mips64r5900 | mips64r5900el \
- | mips64vr | mips64vrel \
- | mips64vr4100 | mips64vr4100el \
- | mips64vr4300 | mips64vr4300el \
- | mips64vr5000 | mips64vr5000el \
- | mips64vr5900 | mips64vr5900el \
- | mipsisa32 | mipsisa32el \
- | mipsisa32r2 | mipsisa32r2el \
- | mipsisa32r6 | mipsisa32r6el \
- | mipsisa64 | mipsisa64el \
- | mipsisa64r2 | mipsisa64r2el \
- | mipsisa64r6 | mipsisa64r6el \
- | mipsisa64sb1 | mipsisa64sb1el \
- | mipsisa64sr71k | mipsisa64sr71kel \
- | mipsr5900 | mipsr5900el \
- | mipstx39 | mipstx39el \
- | mn10200 | mn10300 \
- | moxie \
- | mt \
- | msp430 \
- | nds32 | nds32le | nds32be \
- | nios | nios2 | nios2eb | nios2el \
- | ns16k | ns32k \
- | open8 | or1k | or1knd | or32 \
- | pdp10 | pdp11 | pj | pjl \
- | powerpc | powerpc64 | powerpc64le | powerpcle \
- | pyramid \
- | riscv32 | riscv64 \
- | rl78 | rx \
- | score \
- | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
- | sh64 | sh64le \
- | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
- | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
- | spu \
- | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
- | ubicom32 \
- | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
- | visium \
- | we32k \
- | x86 | xc16x | xstormy16 | xtensa \
- | z8k | z80)
- basic_machine=$basic_machine-unknown
+ # Here we handle the default manufacturer of certain CPU types. It is in
+ # some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ cpu=hppa1.1
+ vendor=winbond
;;
- c54x)
- basic_machine=tic54x-unknown
+ op50n)
+ cpu=hppa1.1
+ vendor=oki
;;
- c55x)
- basic_machine=tic55x-unknown
+ op60c)
+ cpu=hppa1.1
+ vendor=oki
;;
- c6x)
- basic_machine=tic6x-unknown
+ ibm*)
+ cpu=i370
+ vendor=ibm
+ ;;
+ orion105)
+ cpu=clipper
+ vendor=highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ cpu=m68k
+ vendor=apple
+ ;;
+ pmac | pmac-mpw)
+ cpu=powerpc
+ vendor=apple
+ ;;
+
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ cpu=m68000
+ vendor=att
+ ;;
+ 3b*)
+ cpu=we32k
+ vendor=att
+ ;;
+ bluegene*)
+ cpu=powerpc
+ vendor=ibm
+ basic_os=cnk
+ ;;
+ decsystem10* | dec10*)
+ cpu=pdp10
+ vendor=dec
+ basic_os=tops10
+ ;;
+ decsystem20* | dec20*)
+ cpu=pdp10
+ vendor=dec
+ basic_os=tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ cpu=m68k
+ vendor=motorola
+ ;;
+ dpx2*)
+ cpu=m68k
+ vendor=bull
+ basic_os=sysv3
+ ;;
+ encore | umax | mmax)
+ cpu=ns32k
+ vendor=encore
+ ;;
+ elxsi)
+ cpu=elxsi
+ vendor=elxsi
+ basic_os=${basic_os:-bsd}
+ ;;
+ fx2800)
+ cpu=i860
+ vendor=alliant
+ ;;
+ genix)
+ cpu=ns32k
+ vendor=ns
+ ;;
+ h3050r* | hiux*)
+ cpu=hppa1.1
+ vendor=hitachi
+ basic_os=hiuxwe2
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ cpu=hppa1.0
+ vendor=hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ cpu=m68000
+ vendor=hp
+ ;;
+ hp9k3[2-9][0-9])
+ cpu=m68k
+ vendor=hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ cpu=hppa1.0
+ vendor=hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ cpu=hppa1.1
+ vendor=hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ cpu=hppa1.1
+ vendor=hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ cpu=hppa1.1
+ vendor=hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ cpu=hppa1.1
+ vendor=hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ cpu=hppa1.0
+ vendor=hp
+ ;;
+ i*86v32)
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=sysv32
+ ;;
+ i*86v4*)
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=sysv4
+ ;;
+ i*86v)
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=sysv
+ ;;
+ i*86sol2)
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=solaris2
+ ;;
+ j90 | j90-cray)
+ cpu=j90
+ vendor=cray
+ basic_os=${basic_os:-unicos}
+ ;;
+ iris | iris4d)
+ cpu=mips
+ vendor=sgi
+ case $basic_os in
+ irix*)
+ ;;
+ *)
+ basic_os=irix4
+ ;;
+ esac
+ ;;
+ miniframe)
+ cpu=m68000
+ vendor=convergent
+ ;;
+ *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ cpu=m68k
+ vendor=atari
+ basic_os=mint
+ ;;
+ news-3600 | risc-news)
+ cpu=mips
+ vendor=sony
+ basic_os=newsos
+ ;;
+ next | m*-next)
+ cpu=m68k
+ vendor=next
+ case $basic_os in
+ openstep*)
+ ;;
+ nextstep*)
+ ;;
+ ns2*)
+ basic_os=nextstep2
+ ;;
+ *)
+ basic_os=nextstep3
+ ;;
+ esac
+ ;;
+ np1)
+ cpu=np1
+ vendor=gould
+ ;;
+ op50n-* | op60c-*)
+ cpu=hppa1.1
+ vendor=oki
+ basic_os=proelf
+ ;;
+ pa-hitachi)
+ cpu=hppa1.1
+ vendor=hitachi
+ basic_os=hiuxwe2
+ ;;
+ pbd)
+ cpu=sparc
+ vendor=tti
+ ;;
+ pbb)
+ cpu=m68k
+ vendor=tti
+ ;;
+ pc532)
+ cpu=ns32k
+ vendor=pc532
+ ;;
+ pn)
+ cpu=pn
+ vendor=gould
+ ;;
+ power)
+ cpu=power
+ vendor=ibm
+ ;;
+ ps2)
+ cpu=i386
+ vendor=ibm
+ ;;
+ rm[46]00)
+ cpu=mips
+ vendor=siemens
+ ;;
+ rtpc | rtpc-*)
+ cpu=romp
+ vendor=ibm
+ ;;
+ sde)
+ cpu=mipsisa32
+ vendor=sde
+ basic_os=${basic_os:-elf}
+ ;;
+ simso-wrs)
+ cpu=sparclite
+ vendor=wrs
+ basic_os=vxworks
+ ;;
+ tower | tower-32)
+ cpu=m68k
+ vendor=ncr
+ ;;
+ vpp*|vx|vx-*)
+ cpu=f301
+ vendor=fujitsu
+ ;;
+ w65)
+ cpu=w65
+ vendor=wdc
+ ;;
+ w89k-*)
+ cpu=hppa1.1
+ vendor=winbond
+ basic_os=proelf
+ ;;
+ none)
+ cpu=none
+ vendor=none
;;
leon|leon[3-9])
- basic_machine=sparc-$basic_machine
+ cpu=sparc
+ vendor=$basic_machine
;;
- m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
- basic_machine=$basic_machine-unknown
- os=-none
- ;;
- m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
- ;;
- ms1)
- basic_machine=mt-unknown
+ leon-*|leon[3-9]-*)
+ cpu=sparc
+ vendor=`echo "$basic_machine" | sed 's/-.*//'`
;;
- strongarm | thumb | xscale)
- basic_machine=arm-unknown
+ *-*)
+ # shellcheck disable=SC2162
+ saved_IFS=$IFS
+ IFS="-" read cpu vendor <&2
- exit 1
- ;;
- # Recognize the basic CPU types with company name.
- 580-* \
- | a29k-* \
- | aarch64-* | aarch64_be-* \
- | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
- | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
- | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
- | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
- | avr-* | avr32-* \
- | be32-* | be64-* \
- | bfin-* | bs2000-* \
- | c[123]* | c30-* | [cjt]90-* | c4x-* \
- | c8051-* | clipper-* | craynv-* | cydra-* \
- | d10v-* | d30v-* | dlx-* \
- | e2k-* | elxsi-* \
- | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
- | h8300-* | h8500-* \
- | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
- | hexagon-* \
- | i*86-* | i860-* | i960-* | ia64-* \
- | ip2k-* | iq2000-* \
- | k1om-* \
- | le32-* | le64-* \
- | lm32-* \
- | m32c-* | m32r-* | m32rle-* \
- | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
- | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
- | microblaze-* | microblazeel-* \
- | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
- | mips16-* \
- | mips64-* | mips64el-* \
- | mips64octeon-* | mips64octeonel-* \
- | mips64orion-* | mips64orionel-* \
- | mips64r5900-* | mips64r5900el-* \
- | mips64vr-* | mips64vrel-* \
- | mips64vr4100-* | mips64vr4100el-* \
- | mips64vr4300-* | mips64vr4300el-* \
- | mips64vr5000-* | mips64vr5000el-* \
- | mips64vr5900-* | mips64vr5900el-* \
- | mipsisa32-* | mipsisa32el-* \
- | mipsisa32r2-* | mipsisa32r2el-* \
- | mipsisa32r6-* | mipsisa32r6el-* \
- | mipsisa64-* | mipsisa64el-* \
- | mipsisa64r2-* | mipsisa64r2el-* \
- | mipsisa64r6-* | mipsisa64r6el-* \
- | mipsisa64sb1-* | mipsisa64sb1el-* \
- | mipsisa64sr71k-* | mipsisa64sr71kel-* \
- | mipsr5900-* | mipsr5900el-* \
- | mipstx39-* | mipstx39el-* \
- | mmix-* \
- | mt-* \
- | msp430-* \
- | nds32-* | nds32le-* | nds32be-* \
- | nios-* | nios2-* | nios2eb-* | nios2el-* \
- | none-* | np1-* | ns16k-* | ns32k-* \
- | open8-* \
- | or1k*-* \
- | orion-* \
- | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
- | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
- | pyramid-* \
- | rl78-* | romp-* | rs6000-* | rx-* \
- | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
- | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
- | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
- | sparclite-* \
- | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
- | tahoe-* \
- | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
- | tile*-* \
- | tron-* \
- | ubicom32-* \
- | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
- | vax-* \
- | visium-* \
- | we32k-* \
- | x86-* | x86_64-* | xc16x-* | xps100-* \
- | xstormy16-* | xtensa*-* \
- | ymp-* \
- | z8k-* | z80-*)
- ;;
- # Recognize the basic CPU types without company name, with glob match.
- xtensa*)
- basic_machine=$basic_machine-unknown
- ;;
- # Recognize the various machine names and aliases which stand
- # for a CPU type and a company and sometimes even an OS.
- 386bsd)
- basic_machine=i386-unknown
- os=-bsd
- ;;
- 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
- basic_machine=m68000-att
- ;;
- 3b*)
- basic_machine=we32k-att
- ;;
- a29khif)
- basic_machine=a29k-amd
- os=-udi
- ;;
- abacus)
- basic_machine=abacus-unknown
- ;;
- adobe68k)
- basic_machine=m68010-adobe
- os=-scout
- ;;
- alliant | fx80)
- basic_machine=fx80-alliant
- ;;
- altos | altos3068)
- basic_machine=m68k-altos
- ;;
- am29k)
- basic_machine=a29k-none
- os=-bsd
- ;;
- amd64)
- basic_machine=x86_64-pc
- ;;
- amd64-*)
- basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- amdahl)
- basic_machine=580-amdahl
- os=-sysv
- ;;
- amiga | amiga-*)
- basic_machine=m68k-unknown
- ;;
- amigaos | amigados)
- basic_machine=m68k-unknown
- os=-amigaos
- ;;
- amigaunix | amix)
- basic_machine=m68k-unknown
- os=-sysv4
- ;;
- apollo68)
- basic_machine=m68k-apollo
- os=-sysv
- ;;
- apollo68bsd)
- basic_machine=m68k-apollo
- os=-bsd
- ;;
- aros)
- basic_machine=i386-pc
- os=-aros
- ;;
- asmjs)
- basic_machine=asmjs-unknown
- ;;
- aux)
- basic_machine=m68k-apple
- os=-aux
- ;;
- balance)
- basic_machine=ns32k-sequent
- os=-dynix
- ;;
- blackfin)
- basic_machine=bfin-unknown
- os=-linux
- ;;
- blackfin-*)
- basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
- os=-linux
- ;;
- bluegene*)
- basic_machine=powerpc-ibm
- os=-cnk
- ;;
- c54x-*)
- basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- c55x-*)
- basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- c6x-*)
- basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- c90)
- basic_machine=c90-cray
- os=-unicos
- ;;
- cegcc)
- basic_machine=arm-unknown
- os=-cegcc
- ;;
- convex-c1)
- basic_machine=c1-convex
- os=-bsd
- ;;
- convex-c2)
- basic_machine=c2-convex
- os=-bsd
- ;;
- convex-c32)
- basic_machine=c32-convex
- os=-bsd
- ;;
- convex-c34)
- basic_machine=c34-convex
- os=-bsd
- ;;
- convex-c38)
- basic_machine=c38-convex
- os=-bsd
- ;;
- cray | j90)
- basic_machine=j90-cray
- os=-unicos
- ;;
- craynv)
- basic_machine=craynv-cray
- os=-unicosmp
- ;;
- cr16 | cr16-*)
- basic_machine=cr16-unknown
- os=-elf
- ;;
- crds | unos)
- basic_machine=m68k-crds
- ;;
- crisv32 | crisv32-* | etraxfs*)
- basic_machine=crisv32-axis
- ;;
- cris | cris-* | etrax*)
- basic_machine=cris-axis
- ;;
- crx)
- basic_machine=crx-unknown
- os=-elf
- ;;
- da30 | da30-*)
- basic_machine=m68k-da30
- ;;
- decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
- basic_machine=mips-dec
- ;;
- decsystem10* | dec10*)
- basic_machine=pdp10-dec
- os=-tops10
- ;;
- decsystem20* | dec20*)
- basic_machine=pdp10-dec
- os=-tops20
- ;;
- delta | 3300 | motorola-3300 | motorola-delta \
- | 3300-motorola | delta-motorola)
- basic_machine=m68k-motorola
- ;;
- delta88)
- basic_machine=m88k-motorola
- os=-sysv3
- ;;
- dicos)
- basic_machine=i686-pc
- os=-dicos
- ;;
- djgpp)
- basic_machine=i586-pc
- os=-msdosdjgpp
- ;;
- dpx20 | dpx20-*)
- basic_machine=rs6000-bull
- os=-bosx
- ;;
- dpx2* | dpx2*-bull)
- basic_machine=m68k-bull
- os=-sysv3
- ;;
- ebmon29k)
- basic_machine=a29k-amd
- os=-ebmon
- ;;
- elxsi)
- basic_machine=elxsi-elxsi
- os=-bsd
- ;;
- encore | umax | mmax)
- basic_machine=ns32k-encore
- ;;
- es1800 | OSE68k | ose68k | ose | OSE)
- basic_machine=m68k-ericsson
- os=-ose
- ;;
- fx2800)
- basic_machine=i860-alliant
- ;;
- genix)
- basic_machine=ns32k-ns
- ;;
- gmicro)
- basic_machine=tron-gmicro
- os=-sysv
- ;;
- go32)
- basic_machine=i386-pc
- os=-go32
- ;;
- h3050r* | hiux*)
- basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- h8300hms)
- basic_machine=h8300-hitachi
- os=-hms
- ;;
- h8300xray)
- basic_machine=h8300-hitachi
- os=-xray
- ;;
- h8500hms)
- basic_machine=h8500-hitachi
- os=-hms
- ;;
- harris)
- basic_machine=m88k-harris
- os=-sysv3
- ;;
- hp300-*)
- basic_machine=m68k-hp
- ;;
- hp300bsd)
- basic_machine=m68k-hp
- os=-bsd
- ;;
- hp300hpux)
- basic_machine=m68k-hp
- os=-hpux
- ;;
- hp3k9[0-9][0-9] | hp9[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hp9k2[0-9][0-9] | hp9k31[0-9])
- basic_machine=m68000-hp
- ;;
- hp9k3[2-9][0-9])
- basic_machine=m68k-hp
- ;;
- hp9k6[0-9][0-9] | hp6[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hp9k7[0-79][0-9] | hp7[0-79][0-9])
- basic_machine=hppa1.1-hp
- ;;
- hp9k78[0-9] | hp78[0-9])
- # FIXME: really hppa2.0-hp
- basic_machine=hppa1.1-hp
- ;;
- hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
- # FIXME: really hppa2.0-hp
- basic_machine=hppa1.1-hp
- ;;
- hp9k8[0-9][13679] | hp8[0-9][13679])
- basic_machine=hppa1.1-hp
- ;;
- hp9k8[0-9][0-9] | hp8[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hppa-next)
- os=-nextstep3
- ;;
- hppaosf)
- basic_machine=hppa1.1-hp
- os=-osf
- ;;
- hppro)
- basic_machine=hppa1.1-hp
- os=-proelf
- ;;
- i370-ibm* | ibm*)
- basic_machine=i370-ibm
- ;;
- i*86v32)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv32
- ;;
- i*86v4*)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv4
- ;;
- i*86v)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv
- ;;
- i*86sol2)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-solaris2
- ;;
- i386mach)
- basic_machine=i386-mach
- os=-mach
- ;;
- i386-vsta | vsta)
- basic_machine=i386-unknown
- os=-vsta
- ;;
- iris | iris4d)
- basic_machine=mips-sgi
- case $os in
- -irix*)
- ;;
- *)
- os=-irix4
- ;;
- esac
- ;;
- isi68 | isi)
- basic_machine=m68k-isi
- os=-sysv
- ;;
- leon-*|leon[3-9]-*)
- basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
- ;;
- m68knommu)
- basic_machine=m68k-unknown
- os=-linux
- ;;
- m68knommu-*)
- basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
- os=-linux
- ;;
- m88k-omron*)
- basic_machine=m88k-omron
- ;;
- magnum | m3230)
- basic_machine=mips-mips
- os=-sysv
- ;;
- merlin)
- basic_machine=ns32k-utek
- os=-sysv
- ;;
- microblaze*)
- basic_machine=microblaze-xilinx
- ;;
- mingw64)
- basic_machine=x86_64-pc
- os=-mingw64
- ;;
- mingw32)
- basic_machine=i686-pc
- os=-mingw32
- ;;
- mingw32ce)
- basic_machine=arm-unknown
- os=-mingw32ce
- ;;
- miniframe)
- basic_machine=m68000-convergent
- ;;
- *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
- basic_machine=m68k-atari
- os=-mint
- ;;
- mips3*-*)
- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
- ;;
- mips3*)
- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
- ;;
- monitor)
- basic_machine=m68k-rom68k
- os=-coff
- ;;
- morphos)
- basic_machine=powerpc-unknown
- os=-morphos
- ;;
- moxiebox)
- basic_machine=moxie-unknown
- os=-moxiebox
- ;;
- msdos)
- basic_machine=i386-pc
- os=-msdos
- ;;
- ms1-*)
- basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
- ;;
- msys)
- basic_machine=i686-pc
- os=-msys
- ;;
- mvs)
- basic_machine=i370-ibm
- os=-mvs
- ;;
- nacl)
- basic_machine=le32-unknown
- os=-nacl
- ;;
- ncr3000)
- basic_machine=i486-ncr
- os=-sysv4
- ;;
- netbsd386)
- basic_machine=i386-unknown
- os=-netbsd
- ;;
- netwinder)
- basic_machine=armv4l-rebel
- os=-linux
- ;;
- news | news700 | news800 | news900)
- basic_machine=m68k-sony
- os=-newsos
- ;;
- news1000)
- basic_machine=m68030-sony
- os=-newsos
- ;;
- news-3600 | risc-news)
- basic_machine=mips-sony
- os=-newsos
- ;;
- necv70)
- basic_machine=v70-nec
- os=-sysv
- ;;
- next | m*-next )
- basic_machine=m68k-next
- case $os in
- -nextstep* )
- ;;
- -ns2*)
- os=-nextstep2
- ;;
- *)
- os=-nextstep3
- ;;
- esac
- ;;
- nh3000)
- basic_machine=m68k-harris
- os=-cxux
- ;;
- nh[45]000)
- basic_machine=m88k-harris
- os=-cxux
- ;;
- nindy960)
- basic_machine=i960-intel
- os=-nindy
- ;;
- mon960)
- basic_machine=i960-intel
- os=-mon960
- ;;
- nonstopux)
- basic_machine=mips-compaq
- os=-nonstopux
- ;;
- np1)
- basic_machine=np1-gould
- ;;
- neo-tandem)
- basic_machine=neo-tandem
- ;;
- nse-tandem)
- basic_machine=nse-tandem
- ;;
- nsr-tandem)
- basic_machine=nsr-tandem
- ;;
- op50n-* | op60c-*)
- basic_machine=hppa1.1-oki
- os=-proelf
- ;;
- openrisc | openrisc-*)
- basic_machine=or32-unknown
- ;;
- os400)
- basic_machine=powerpc-ibm
- os=-os400
- ;;
- OSE68000 | ose68000)
- basic_machine=m68000-ericsson
- os=-ose
- ;;
- os68k)
- basic_machine=m68k-none
- os=-os68k
- ;;
- pa-hitachi)
- basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- paragon)
- basic_machine=i860-intel
- os=-osf
- ;;
- parisc)
- basic_machine=hppa-unknown
- os=-linux
- ;;
- parisc-*)
- basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
- os=-linux
- ;;
- pbd)
- basic_machine=sparc-tti
- ;;
- pbb)
- basic_machine=m68k-tti
- ;;
- pc532 | pc532-*)
- basic_machine=ns32k-pc532
+ cpu=$basic_machine
+ vendor=pc
;;
+ # These rules are duplicated from below for sake of the special case above;
+ # i.e. things that normalized to x86 arches should also default to "pc"
pc98)
- basic_machine=i386-pc
+ cpu=i386
+ vendor=pc
;;
- pc98-*)
- basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+ x64 | amd64)
+ cpu=x86_64
+ vendor=pc
;;
- pentium | p5 | k5 | k6 | nexgen | viac3)
- basic_machine=i586-pc
+ # Recognize the basic CPU types without company name.
+ *)
+ cpu=$basic_machine
+ vendor=unknown
;;
- pentiumpro | p6 | 6x86 | athlon | athlon_*)
- basic_machine=i686-pc
+esac
+
+unset -v basic_machine
+
+# Decode basic machines in the full and proper CPU-Company form.
+case $cpu-$vendor in
+ # Here we handle the default manufacturer of certain CPU types in canonical form. It is in
+ # some cases the only manufacturer, in others, it is the most popular.
+ craynv-unknown)
+ vendor=cray
+ basic_os=${basic_os:-unicosmp}
;;
- pentiumii | pentium2 | pentiumiii | pentium3)
- basic_machine=i686-pc
+ c90-unknown | c90-cray)
+ vendor=cray
+ basic_os=${Basic_os:-unicos}
;;
- pentium4)
- basic_machine=i786-pc
+ fx80-unknown)
+ vendor=alliant
;;
- pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
- basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ romp-unknown)
+ vendor=ibm
;;
- pentiumpro-* | p6-* | 6x86-* | athlon-*)
- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ mmix-unknown)
+ vendor=knuth
;;
- pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ microblaze-unknown | microblazeel-unknown)
+ vendor=xilinx
;;
- pentium4-*)
- basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ rs6000-unknown)
+ vendor=ibm
;;
- pn)
- basic_machine=pn-gould
+ vax-unknown)
+ vendor=dec
;;
- power) basic_machine=power-ibm
+ pdp11-unknown)
+ vendor=dec
;;
- ppc | ppcbe) basic_machine=powerpc-unknown
+ we32k-unknown)
+ vendor=att
;;
- ppc-* | ppcbe-*)
- basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ cydra-unknown)
+ vendor=cydrome
;;
- ppcle | powerpclittle | ppc-le | powerpc-little)
- basic_machine=powerpcle-unknown
+ i370-ibm*)
+ vendor=ibm
;;
- ppcle-* | powerpclittle-*)
- basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ orion-unknown)
+ vendor=highlevel
;;
- ppc64) basic_machine=powerpc64-unknown
- ;;
- ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppc64le | powerpc64little | ppc64-le | powerpc64-little)
- basic_machine=powerpc64le-unknown
- ;;
- ppc64le-* | powerpc64little-*)
- basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ps2)
- basic_machine=i386-ibm
- ;;
- pw32)
- basic_machine=i586-unknown
- os=-pw32
- ;;
- rdos | rdos64)
- basic_machine=x86_64-pc
- os=-rdos
- ;;
- rdos32)
- basic_machine=i386-pc
- os=-rdos
- ;;
- rom68k)
- basic_machine=m68k-rom68k
- os=-coff
- ;;
- rm[46]00)
- basic_machine=mips-siemens
- ;;
- rtpc | rtpc-*)
- basic_machine=romp-ibm
- ;;
- s390 | s390-*)
- basic_machine=s390-ibm
- ;;
- s390x | s390x-*)
- basic_machine=s390x-ibm
- ;;
- sa29200)
- basic_machine=a29k-amd
- os=-udi
- ;;
- sb1)
- basic_machine=mipsisa64sb1-unknown
- ;;
- sb1el)
- basic_machine=mipsisa64sb1el-unknown
- ;;
- sde)
- basic_machine=mipsisa32-sde
- os=-elf
- ;;
- sei)
- basic_machine=mips-sei
- os=-seiux
- ;;
- sequent)
- basic_machine=i386-sequent
- ;;
- sh)
- basic_machine=sh-hitachi
- os=-hms
- ;;
- sh5el)
- basic_machine=sh5le-unknown
- ;;
- sh64)
- basic_machine=sh64-unknown
- ;;
- sparclite-wrs | simso-wrs)
- basic_machine=sparclite-wrs
- os=-vxworks
- ;;
- sps7)
- basic_machine=m68k-bull
- os=-sysv2
- ;;
- spur)
- basic_machine=spur-unknown
- ;;
- st2000)
- basic_machine=m68k-tandem
- ;;
- stratus)
- basic_machine=i860-stratus
- os=-sysv4
- ;;
- strongarm-* | thumb-*)
- basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- sun2)
- basic_machine=m68000-sun
- ;;
- sun2os3)
- basic_machine=m68000-sun
- os=-sunos3
- ;;
- sun2os4)
- basic_machine=m68000-sun
- os=-sunos4
- ;;
- sun3os3)
- basic_machine=m68k-sun
- os=-sunos3
- ;;
- sun3os4)
- basic_machine=m68k-sun
- os=-sunos4
- ;;
- sun4os3)
- basic_machine=sparc-sun
- os=-sunos3
- ;;
- sun4os4)
- basic_machine=sparc-sun
- os=-sunos4
- ;;
- sun4sol2)
- basic_machine=sparc-sun
- os=-solaris2
- ;;
- sun3 | sun3-*)
- basic_machine=m68k-sun
- ;;
- sun4)
- basic_machine=sparc-sun
- ;;
- sun386 | sun386i | roadrunner)
- basic_machine=i386-sun
- ;;
- sv1)
- basic_machine=sv1-cray
- os=-unicos
- ;;
- symmetry)
- basic_machine=i386-sequent
- os=-dynix
- ;;
- t3e)
- basic_machine=alphaev5-cray
- os=-unicos
- ;;
- t90)
- basic_machine=t90-cray
- os=-unicos
- ;;
- tile*)
- basic_machine=$basic_machine-unknown
- os=-linux-gnu
- ;;
- tx39)
- basic_machine=mipstx39-unknown
- ;;
- tx39el)
- basic_machine=mipstx39el-unknown
- ;;
- toad1)
- basic_machine=pdp10-xkl
- os=-tops20
- ;;
- tower | tower-32)
- basic_machine=m68k-ncr
- ;;
- tpf)
- basic_machine=s390x-ibm
- os=-tpf
- ;;
- udi29k)
- basic_machine=a29k-amd
- os=-udi
- ;;
- ultra3)
- basic_machine=a29k-nyu
- os=-sym1
- ;;
- v810 | necv810)
- basic_machine=v810-nec
- os=-none
- ;;
- vaxv)
- basic_machine=vax-dec
- os=-sysv
- ;;
- vms)
- basic_machine=vax-dec
- os=-vms
- ;;
- vpp*|vx|vx-*)
- basic_machine=f301-fujitsu
- ;;
- vxworks960)
- basic_machine=i960-wrs
- os=-vxworks
- ;;
- vxworks68)
- basic_machine=m68k-wrs
- os=-vxworks
- ;;
- vxworks29k)
- basic_machine=a29k-wrs
- os=-vxworks
- ;;
- w65*)
- basic_machine=w65-wdc
- os=-none
- ;;
- w89k-*)
- basic_machine=hppa1.1-winbond
- os=-proelf
- ;;
- xbox)
- basic_machine=i686-pc
- os=-mingw32
- ;;
- xps | xps100)
- basic_machine=xps100-honeywell
- ;;
- xscale-* | xscalee[bl]-*)
- basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
- ;;
- ymp)
- basic_machine=ymp-cray
- os=-unicos
- ;;
- z8k-*-coff)
- basic_machine=z8k-unknown
- os=-sim
- ;;
- z80-*-coff)
- basic_machine=z80-unknown
- os=-sim
- ;;
- none)
- basic_machine=none-none
- os=-none
+ xps-unknown | xps100-unknown)
+ cpu=xps100
+ vendor=honeywell
;;
-# Here we handle the default manufacturer of certain CPU types. It is in
-# some cases the only manufacturer, in others, it is the most popular.
- w89k)
- basic_machine=hppa1.1-winbond
+ # Here we normalize CPU types with a missing or matching vendor
+ dpx20-unknown | dpx20-bull)
+ cpu=rs6000
+ vendor=bull
+ basic_os=${basic_os:-bosx}
;;
- op50n)
- basic_machine=hppa1.1-oki
+
+ # Here we normalize CPU types irrespective of the vendor
+ amd64-*)
+ cpu=x86_64
;;
- op60c)
- basic_machine=hppa1.1-oki
+ blackfin-*)
+ cpu=bfin
+ basic_os=linux
;;
- romp)
- basic_machine=romp-ibm
+ c54x-*)
+ cpu=tic54x
;;
- mmix)
- basic_machine=mmix-knuth
+ c55x-*)
+ cpu=tic55x
;;
- rs6000)
- basic_machine=rs6000-ibm
+ c6x-*)
+ cpu=tic6x
;;
- vax)
- basic_machine=vax-dec
+ e500v[12]-*)
+ cpu=powerpc
+ basic_os=${basic_os}"spe"
;;
- pdp10)
- # there are many clones, so DEC is not a safe bet
- basic_machine=pdp10-unknown
+ mips3*-*)
+ cpu=mips64
;;
- pdp11)
- basic_machine=pdp11-dec
+ ms1-*)
+ cpu=mt
;;
- we32k)
- basic_machine=we32k-att
+ m68knommu-*)
+ cpu=m68k
+ basic_os=linux
;;
- sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
- basic_machine=sh-unknown
+ m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*)
+ cpu=s12z
;;
- sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
- basic_machine=sparc-sun
+ openrisc-*)
+ cpu=or32
;;
- cydra)
- basic_machine=cydra-cydrome
+ parisc-*)
+ cpu=hppa
+ basic_os=linux
;;
- orion)
- basic_machine=orion-highlevel
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ cpu=i586
;;
- orion105)
- basic_machine=clipper-highlevel
+ pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*)
+ cpu=i686
;;
- mac | mpw | mac-mpw)
- basic_machine=m68k-apple
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ cpu=i686
;;
- pmac | pmac-mpw)
- basic_machine=powerpc-apple
+ pentium4-*)
+ cpu=i786
;;
- *-unknown)
- # Make sure to match an already-canonicalized machine name.
+ pc98-*)
+ cpu=i386
;;
+ ppc-* | ppcbe-*)
+ cpu=powerpc
+ ;;
+ ppcle-* | powerpclittle-*)
+ cpu=powerpcle
+ ;;
+ ppc64-*)
+ cpu=powerpc64
+ ;;
+ ppc64le-* | powerpc64little-*)
+ cpu=powerpc64le
+ ;;
+ sb1-*)
+ cpu=mipsisa64sb1
+ ;;
+ sb1el-*)
+ cpu=mipsisa64sb1el
+ ;;
+ sh5e[lb]-*)
+ cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'`
+ ;;
+ spur-*)
+ cpu=spur
+ ;;
+ strongarm-* | thumb-*)
+ cpu=arm
+ ;;
+ tx39-*)
+ cpu=mipstx39
+ ;;
+ tx39el-*)
+ cpu=mipstx39el
+ ;;
+ x64-*)
+ cpu=x86_64
+ ;;
+ xscale-* | xscalee[bl]-*)
+ cpu=`echo "$cpu" | sed 's/^xscale/arm/'`
+ ;;
+ arm64-*)
+ cpu=aarch64
+ ;;
+
+ # Recognize the canonical CPU Types that limit and/or modify the
+ # company names they are paired with.
+ cr16-*)
+ basic_os=${basic_os:-elf}
+ ;;
+ crisv32-* | etraxfs*-*)
+ cpu=crisv32
+ vendor=axis
+ ;;
+ cris-* | etrax*-*)
+ cpu=cris
+ vendor=axis
+ ;;
+ crx-*)
+ basic_os=${basic_os:-elf}
+ ;;
+ neo-tandem)
+ cpu=neo
+ vendor=tandem
+ ;;
+ nse-tandem)
+ cpu=nse
+ vendor=tandem
+ ;;
+ nsr-tandem)
+ cpu=nsr
+ vendor=tandem
+ ;;
+ nsv-tandem)
+ cpu=nsv
+ vendor=tandem
+ ;;
+ nsx-tandem)
+ cpu=nsx
+ vendor=tandem
+ ;;
+ mipsallegrexel-sony)
+ cpu=mipsallegrexel
+ vendor=sony
+ ;;
+ tile*-*)
+ basic_os=${basic_os:-linux-gnu}
+ ;;
+
*)
- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
- exit 1
+ # Recognize the canonical CPU types that are allowed with any
+ # company name.
+ case $cpu in
+ 1750a | 580 \
+ | a29k \
+ | aarch64 | aarch64_be \
+ | abacus \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
+ | alphapca5[67] | alpha64pca5[67] \
+ | am33_2.0 \
+ | amdgcn \
+ | arc | arceb | arc32 | arc64 \
+ | arm | arm[lb]e | arme[lb] | armv* \
+ | avr | avr32 \
+ | asmjs \
+ | ba \
+ | be32 | be64 \
+ | bfin | bpf | bs2000 \
+ | c[123]* | c30 | [cjt]90 | c4x \
+ | c8051 | clipper | craynv | csky | cydra \
+ | d10v | d30v | dlx | dsp16xx \
+ | e2k | elxsi | epiphany \
+ | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
+ | h8300 | h8500 \
+ | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
+ | i370 | i*86 | i860 | i960 | ia16 | ia64 \
+ | ip2k | iq2000 \
+ | k1om \
+ | le32 | le64 \
+ | lm32 \
+ | loongarch32 | loongarch64 | loongarchx32 \
+ | m32c | m32r | m32rle \
+ | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
+ | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
+ | m88110 | m88k | maxq | mb | mcore | mep | metag \
+ | microblaze | microblazeel \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64eb | mips64el \
+ | mips64octeon | mips64octeonel \
+ | mips64orion | mips64orionel \
+ | mips64r5900 | mips64r5900el \
+ | mips64vr | mips64vrel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa32r3 | mipsisa32r3el \
+ | mipsisa32r5 | mipsisa32r5el \
+ | mipsisa32r6 | mipsisa32r6el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64r3 | mipsisa64r3el \
+ | mipsisa64r5 | mipsisa64r5el \
+ | mipsisa64r6 | mipsisa64r6el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
+ | mipstx39 | mipstx39el \
+ | mmix \
+ | mn10200 | mn10300 \
+ | moxie \
+ | mt \
+ | msp430 \
+ | nds32 | nds32le | nds32be \
+ | nfp \
+ | nios | nios2 | nios2eb | nios2el \
+ | none | np1 | ns16k | ns32k | nvptx \
+ | open8 \
+ | or1k* \
+ | or32 \
+ | orion \
+ | picochip \
+ | pdp10 | pdp11 | pj | pjl | pn | power \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
+ | pru \
+ | pyramid \
+ | riscv | riscv32 | riscv32be | riscv64 | riscv64be \
+ | rl78 | romp | rs6000 | rx \
+ | s390 | s390x \
+ | score \
+ | sh | shl \
+ | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \
+ | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \
+ | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
+ | spu \
+ | tahoe \
+ | thumbv7* \
+ | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
+ | tron \
+ | ubicom32 \
+ | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
+ | vax \
+ | visium \
+ | w65 \
+ | wasm32 | wasm64 \
+ | we32k \
+ | x86 | x86_64 | xc16x | xgate | xps100 \
+ | xstormy16 | xtensa* \
+ | ymp \
+ | z8k | z80)
+ ;;
+
+ *)
+ echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2
+ exit 1
+ ;;
+ esac
;;
esac
# Here we canonicalize certain aliases for manufacturers.
-case $basic_machine in
- *-digital*)
- basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+case $vendor in
+ digital*)
+ vendor=dec
;;
- *-commodore*)
- basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ commodore*)
+ vendor=cbm
;;
*)
;;
@@ -1343,200 +1301,215 @@ esac
# Decode manufacturer-specific aliases for certain operating systems.
-if [ x"$os" != x"" ]
+if test x$basic_os != x
then
+
+# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just
+# set os.
+case $basic_os in
+ gnu/linux*)
+ kernel=linux
+ os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'`
+ ;;
+ os2-emx)
+ kernel=os2
+ os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'`
+ ;;
+ nto-qnx*)
+ kernel=nto
+ os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'`
+ ;;
+ *-*)
+ # shellcheck disable=SC2162
+ saved_IFS=$IFS
+ IFS="-" read kernel os <&2
- exit 1
+ # No normalization, but not necessarily accepted, that comes below.
;;
esac
+
else
# Here we handle the default operating systems that come with various machines.
@@ -1549,261 +1522,362 @@ else
# will signal an error saying that MANUFACTURER isn't an operating
# system, and we'll never get to this point.
-case $basic_machine in
+kernel=
+case $cpu-$vendor in
score-*)
- os=-elf
+ os=elf
;;
spu-*)
- os=-elf
+ os=elf
;;
*-acorn)
- os=-riscix1.2
+ os=riscix1.2
;;
arm*-rebel)
- os=-linux
+ kernel=linux
+ os=gnu
;;
arm*-semi)
- os=-aout
+ os=aout
;;
c4x-* | tic4x-*)
- os=-coff
+ os=coff
;;
c8051-*)
- os=-elf
+ os=elf
+ ;;
+ clipper-intergraph)
+ os=clix
;;
hexagon-*)
- os=-elf
+ os=elf
;;
tic54x-*)
- os=-coff
+ os=coff
;;
tic55x-*)
- os=-coff
+ os=coff
;;
tic6x-*)
- os=-coff
+ os=coff
;;
# This must come before the *-dec entry.
pdp10-*)
- os=-tops20
+ os=tops20
;;
pdp11-*)
- os=-none
+ os=none
;;
*-dec | vax-*)
- os=-ultrix4.2
+ os=ultrix4.2
;;
m68*-apollo)
- os=-domain
+ os=domain
;;
i386-sun)
- os=-sunos4.0.2
+ os=sunos4.0.2
;;
m68000-sun)
- os=-sunos3
+ os=sunos3
;;
m68*-cisco)
- os=-aout
+ os=aout
;;
mep-*)
- os=-elf
+ os=elf
;;
mips*-cisco)
- os=-elf
+ os=elf
;;
mips*-*)
- os=-elf
+ os=elf
;;
or32-*)
- os=-coff
+ os=coff
;;
*-tti) # must be before sparc entry or we get the wrong os.
- os=-sysv3
+ os=sysv3
;;
sparc-* | *-sun)
- os=-sunos4.1.1
+ os=sunos4.1.1
+ ;;
+ pru-*)
+ os=elf
;;
*-be)
- os=-beos
- ;;
- *-haiku)
- os=-haiku
+ os=beos
;;
*-ibm)
- os=-aix
+ os=aix
;;
*-knuth)
- os=-mmixware
+ os=mmixware
;;
*-wec)
- os=-proelf
+ os=proelf
;;
*-winbond)
- os=-proelf
+ os=proelf
;;
*-oki)
- os=-proelf
+ os=proelf
;;
*-hp)
- os=-hpux
+ os=hpux
;;
*-hitachi)
- os=-hiux
+ os=hiux
;;
i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
- os=-sysv
+ os=sysv
;;
*-cbm)
- os=-amigaos
+ os=amigaos
;;
*-dg)
- os=-dgux
+ os=dgux
;;
*-dolphin)
- os=-sysv3
+ os=sysv3
;;
m68k-ccur)
- os=-rtu
+ os=rtu
;;
m88k-omron*)
- os=-luna
- ;;
- *-next )
- os=-nextstep
- ;;
- *-sequent)
- os=-ptx
- ;;
- *-crds)
- os=-unos
- ;;
- *-ns)
- os=-genix
- ;;
- i370-*)
- os=-mvs
+ os=luna
;;
*-next)
- os=-nextstep3
+ os=nextstep
+ ;;
+ *-sequent)
+ os=ptx
+ ;;
+ *-crds)
+ os=unos
+ ;;
+ *-ns)
+ os=genix
+ ;;
+ i370-*)
+ os=mvs
;;
*-gould)
- os=-sysv
+ os=sysv
;;
*-highlevel)
- os=-bsd
+ os=bsd
;;
*-encore)
- os=-bsd
+ os=bsd
;;
*-sgi)
- os=-irix
+ os=irix
;;
*-siemens)
- os=-sysv4
+ os=sysv4
;;
*-masscomp)
- os=-rtu
+ os=rtu
;;
f30[01]-fujitsu | f700-fujitsu)
- os=-uxpv
+ os=uxpv
;;
*-rom68k)
- os=-coff
+ os=coff
;;
*-*bug)
- os=-coff
+ os=coff
;;
*-apple)
- os=-macos
+ os=macos
;;
*-atari*)
- os=-mint
+ os=mint
+ ;;
+ *-wrs)
+ os=vxworks
;;
*)
- os=-none
+ os=none
;;
esac
+
fi
+# Now, validate our (potentially fixed-up) OS.
+case $os in
+ # Sometimes we do "kernel-libc", so those need to count as OSes.
+ musl* | newlib* | relibc* | uclibc*)
+ ;;
+ # Likewise for "kernel-abi"
+ eabi* | gnueabi*)
+ ;;
+ # VxWorks passes extra cpu info in the 4th filed.
+ simlinux | simwindows | spe)
+ ;;
+ # Now accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST end in a * to match a version number.
+ gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
+ | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \
+ | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
+ | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \
+ | hiux* | abug | nacl* | netware* | windows* \
+ | os9* | macos* | osx* | ios* \
+ | mpw* | magic* | mmixware* | mon960* | lnews* \
+ | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
+ | aos* | aros* | cloudabi* | sortix* | twizzler* \
+ | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
+ | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
+ | mirbsd* | netbsd* | dicos* | openedition* | ose* \
+ | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \
+ | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
+ | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
+ | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
+ | udi* | lites* | ieee* | go32* | aux* | hcos* \
+ | chorusrdb* | cegcc* | glidix* | serenity* \
+ | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
+ | midipix* | mingw32* | mingw64* | mint* \
+ | uxpv* | beos* | mpeix* | udk* | moxiebox* \
+ | interix* | uwin* | mks* | rhapsody* | darwin* \
+ | openstep* | oskit* | conix* | pw32* | nonstopux* \
+ | storm-chaos* | tops10* | tenex* | tops20* | its* \
+ | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \
+ | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \
+ | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
+ | skyos* | haiku* | rdos* | toppers* | drops* | es* \
+ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
+ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
+ | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr*)
+ ;;
+ # This one is extra strict with allowed versions
+ sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ ;;
+ none)
+ ;;
+ *)
+ echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# As a final step for OS-related things, validate the OS-kernel combination
+# (given a valid OS), if there is a kernel.
+case $kernel-$os in
+ linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \
+ | linux-musl* | linux-relibc* | linux-uclibc* )
+ ;;
+ uclinux-uclibc* )
+ ;;
+ -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* )
+ # These are just libc implementations, not actual OSes, and thus
+ # require a kernel.
+ echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
+ exit 1
+ ;;
+ kfreebsd*-gnu* | kopensolaris*-gnu*)
+ ;;
+ vxworks-simlinux | vxworks-simwindows | vxworks-spe)
+ ;;
+ nto-qnx*)
+ ;;
+ os2-emx)
+ ;;
+ *-eabi* | *-gnueabi*)
+ ;;
+ -*)
+ # Blank kernel with real OS is always fine.
+ ;;
+ *-*)
+ echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2
+ exit 1
+ ;;
+esac
+
# Here we handle the case where we know the os, and the CPU type, but not the
# manufacturer. We pick the logical manufacturer.
-vendor=unknown
-case $basic_machine in
- *-unknown)
- case $os in
- -riscix*)
+case $vendor in
+ unknown)
+ case $cpu-$os in
+ *-riscix*)
vendor=acorn
;;
- -sunos*)
+ *-sunos*)
vendor=sun
;;
- -cnk*|-aix*)
+ *-cnk* | *-aix*)
vendor=ibm
;;
- -beos*)
+ *-beos*)
vendor=be
;;
- -hpux*)
+ *-hpux*)
vendor=hp
;;
- -mpeix*)
+ *-mpeix*)
vendor=hp
;;
- -hiux*)
+ *-hiux*)
vendor=hitachi
;;
- -unos*)
+ *-unos*)
vendor=crds
;;
- -dgux*)
+ *-dgux*)
vendor=dg
;;
- -luna*)
+ *-luna*)
vendor=omron
;;
- -genix*)
+ *-genix*)
vendor=ns
;;
- -mvs* | -opened*)
+ *-clix*)
+ vendor=intergraph
+ ;;
+ *-mvs* | *-opened*)
vendor=ibm
;;
- -os400*)
+ *-os400*)
vendor=ibm
;;
- -ptx*)
+ s390-* | s390x-*)
+ vendor=ibm
+ ;;
+ *-ptx*)
vendor=sequent
;;
- -tpf*)
+ *-tpf*)
vendor=ibm
;;
- -vxsim* | -vxworks* | -windiss*)
+ *-vxsim* | *-vxworks* | *-windiss*)
vendor=wrs
;;
- -aux*)
+ *-aux*)
vendor=apple
;;
- -hms*)
+ *-hms*)
vendor=hitachi
;;
- -mpw* | -macos*)
+ *-mpw* | *-macos*)
vendor=apple
;;
- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*)
vendor=atari
;;
- -vos*)
+ *-vos*)
vendor=stratus
;;
esac
- basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
;;
esac
-echo $basic_machine$os
+echo "$cpu-$vendor-${kernel:+$kernel-}$os"
exit
# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
+# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
diff --git a/autoconf/m4/unreal.m4 b/autoconf/m4/unreal.m4
index 345fdf7..73d37a9 100644
--- a/autoconf/m4/unreal.m4
+++ b/autoconf/m4/unreal.m4
@@ -130,9 +130,13 @@ AC_DEFUN([CHECK_LIBCURL],
LIBS="$LIBS_SAVEDA"
CFLAGS="$CFLAGS_SAVEDA"
- URL="url.o"
- AC_SUBST(URL)
+ dnl Finally, choose the cURL implementation of url.c
+ URL="url_curl.o"
+ ],[
+ dnl Choose UnrealIRCds internal implementation of url.c
+ URL="url_unreal.o"
]) dnl AS_IF(enable_curl)
+ AC_SUBST(URL)
])
dnl the following 2 macros are based on CHECK_SSL by Mark Ethan Trostler
@@ -178,7 +182,11 @@ AS_IF([test $enable_ssl != "no"],
else
CRYPTOLIB="-lssl -lcrypto";
if test ! "$ssldir" = "/usr" ; then
- LDFLAGS="$LDFLAGS -L$ssldir/lib";
+ if test -d "$ssldir/lib64" ; then
+ LDFLAGS="$LDFLAGS -L$ssldir/lib64";
+ else
+ LDFLAGS="$LDFLAGS -L$ssldir/lib";
+ fi
dnl check if binary path exists
if test -f "$ssldir/bin/openssl"; then
OPENSSLPATH="$ssldir/bin/openssl";
@@ -312,3 +320,94 @@ else
AC_MSG_RESULT([no])
fi
])
+
+dnl For geoip-api-c
+AC_DEFUN([CHECK_GEOIP_CLASSIC],
+[
+ AC_ARG_ENABLE(geoip_classic,
+ [AC_HELP_STRING([--enable-geoip-classic=no/yes],[enable GeoIP Classic support])],
+ [enable_geoip_classic=$enableval],
+ [enable_geoip_classic=no])
+
+ AS_IF([test "x$enable_geoip_classic" = "xyes"],
+ [
+ dnl First see if the system provides it
+ has_system_geoip_classic="no"
+ PKG_CHECK_MODULES([GEOIP_CLASSIC], [geoip >= 1.6.0],
+ [has_system_geoip_classic=yes
+ AS_IF([test "x$PRIVATELIBDIR" != "x"], [rm -f "$PRIVATELIBDIR/"libGeoIP.*])],
+ [has_system_geoip_classic=no])
+
+ dnl Otherwise fallback to our own..
+ AS_IF([test "$has_system_geoip_classic" = "no"],[
+ dnl REMEMBER TO CHANGE WITH A NEW GEOIP LIBRARY RELEASE!
+ geoip_classic_version="1.6.12"
+ AC_MSG_RESULT(extracting GeoIP Classic library)
+ cur_dir=`pwd`
+ cd extras
+ dnl remove old directory to force a recompile...
+ dnl and remove its installation prefix just to clean things up.
+ rm -rf GeoIP-$geoip_classic_version geoip-classic
+ if test "x$ac_cv_path_GUNZIP" = "x" ; then
+ tar xfz geoip-classic.tar.gz
+ else
+ cp geoip-classic.tar.gz geoip-classic.tar.gz.bak
+ gunzip -f geoip-classic.tar.gz
+ cp geoip-classic.tar.gz.bak geoip-classic.tar.gz
+ tar xf geoip-classic.tar
+ fi
+ AC_MSG_RESULT(configuring GeoIP Classic library)
+ cd GeoIP-$geoip_classic_version
+ save_cflags="$CFLAGS"
+ CFLAGS="$orig_cflags"
+ export CFLAGS
+ ./configure --prefix=$cur_dir/extras/geoip-classic --libdir=$PRIVATELIBDIR --enable-shared --disable-static || exit 1
+ CFLAGS="$save_cflags"
+ AC_MSG_RESULT(compiling GeoIP Classic library)
+ $ac_cv_prog_MAKER || exit 1
+ AC_MSG_RESULT(installing GeoIP Classic library)
+ $ac_cv_prog_MAKER install || exit 1
+ dnl Try pkg-config first...
+ AS_IF([test -n "$ac_cv_path_PKGCONFIG"],
+ [GEOIP_CLASSIC_LIBS="`$ac_cv_path_PKGCONFIG --libs geoip.pc`"
+ GEOIP_CLASSIC_CFLAGS="`$ac_cv_path_PKGCONFIG --cflags geoip.pc`"])
+ dnl In case the system does not have pkg-config, fallback to hardcoded settings...
+ AS_IF([test -z "$GEOIP_CLASSIC_LIBS"],
+ [GEOIP_CLASSIC_LIBS="-L$PRIVATELIBDIR -lGeoIP"
+ GEOIP_CLASSIC_CFLAGS="-I$cur_dir/extras/geoip-classic/include"])
+ cd $cur_dir
+ ])
+
+ AC_SUBST(GEOIP_CLASSIC_LIBS)
+ AC_SUBST(GEOIP_CLASSIC_CFLAGS)
+
+ GEOIP_CLASSIC_OBJECTS="geoip_classic.so"
+ AC_SUBST(GEOIP_CLASSIC_OBJECTS)
+ ]) dnl AS_IF(enable_geoip_classic)
+])
+
+AC_DEFUN([CHECK_LIBMAXMINDDB],
+[
+ AC_ARG_ENABLE(libmaxminddb,
+ [AC_HELP_STRING([--enable-libmaxminddb=no/yes],[enable GeoIP libmaxminddb support])],
+ [enable_libmaxminddb=$enableval],
+ [enable_libmaxminddb=no])
+
+ AS_IF([test "x$enable_libmaxminddb" = "xyes"],
+ [
+ dnl see if the system provides it
+ has_system_libmaxminddb="no"
+ PKG_CHECK_MODULES([LIBMAXMINDDB], [libmaxminddb >= 1.4.3],
+ [has_system_libmaxminddb=yes])
+ AS_IF([test "x$has_system_libmaxminddb" = "xyes"],
+ [
+
+ AC_SUBST(LIBMAXMINDDB_LIBS)
+ AC_SUBST(LIBMAXMINDDB_CFLAGS)
+
+ GEOIP_MAXMIND_OBJECTS="geoip_maxmind.so"
+ AC_SUBST(GEOIP_MAXMIND_OBJECTS)
+ ])
+ ])
+])
+
diff --git a/configure b/configure
index 11fec73..3b7068c 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for unrealircd 5.2.0.1.
+# Generated by GNU Autoconf 2.69 for unrealircd 6.0.1.1.
#
# Report bugs to .
#
@@ -580,8 +580,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='unrealircd'
PACKAGE_TARNAME='unrealircd'
-PACKAGE_VERSION='5.2.0.1'
-PACKAGE_STRING='unrealircd 5.2.0.1'
+PACKAGE_VERSION='6.0.1.1'
+PACKAGE_STRING='unrealircd 6.0.1.1'
PACKAGE_BUGREPORT='https://bugs.unrealircd.org/'
PACKAGE_URL='https://unrealircd.org/'
@@ -626,6 +626,12 @@ ac_subst_vars='LTLIBOBJS
LIBOBJS
UNRLINCDIR
IRCDLIBS
+GEOIP_MAXMIND_OBJECTS
+LIBMAXMINDDB_LIBS
+LIBMAXMINDDB_CFLAGS
+GEOIP_CLASSIC_OBJECTS
+GEOIP_CLASSIC_LIBS
+GEOIP_CLASSIC_CFLAGS
URL
PTHREAD_CFLAGS
PTHREAD_LIBS
@@ -639,6 +645,8 @@ build_os
build_vendor
build_cpu
build
+JANSSON_LIBS
+JANSSON_CFLAGS
CARES_LIBS
CARES_CFLAGS
SODIUM_LIBS
@@ -746,19 +754,20 @@ with_docdir
with_pidfile
with_privatelibdir
with_maxconnections
-enable_prefixaq
-with_showlistmodes
with_no_operoverride
with_operoverride_verify
with_system_pcre2
with_system_argon2
with_system_sodium
with_system_cares
+with_system_jansson
enable_ssl
enable_dynamic_linking
enable_werror
enable_asan
enable_libcurl
+enable_geoip_classic
+enable_libmaxminddb
'
ac_precious_vars='build_alias
host_alias
@@ -779,7 +788,13 @@ ARGON2_LIBS
SODIUM_CFLAGS
SODIUM_LIBS
CARES_CFLAGS
-CARES_LIBS'
+CARES_LIBS
+JANSSON_CFLAGS
+JANSSON_LIBS
+GEOIP_CLASSIC_CFLAGS
+GEOIP_CLASSIC_LIBS
+LIBMAXMINDDB_CFLAGS
+LIBMAXMINDDB_LIBS'
# Initialize some variables set by options.
@@ -1330,7 +1345,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 5.2.0.1 to adapt to many kinds of systems.
+\`configure' configures unrealircd 6.0.1.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1396,7 +1411,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of unrealircd 5.2.0.1:";;
+ short | recursive ) echo "Configuration of unrealircd 6.0.1.1:";;
esac
cat <<\_ACEOF
@@ -1406,7 +1421,6 @@ Optional Features:
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--enable-hardening Enable compiler and linker options to frustrate
memory corruption exploits [yes]
- --disable-prefixaq Disable chanadmin (+a) and chanowner (+q) prefixes
--enable-ssl= enable ssl will check /usr/local/opt/openssl
/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg
/usr/sfw /usr/local /usr
@@ -1418,6 +1432,10 @@ Optional Features:
--enable-asan Enable address sanitizer and other debugging
options, not recommended for production servers!
--enable-libcurl=DIR enable libcurl (remote include) support
+ --enable-geoip-classic=no/yes
+ enable GeoIP Classic support
+ --enable-libmaxminddb=no/yes
+ enable GeoIP libmaxminddb support
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -1447,7 +1465,6 @@ Optional Packages:
stored. Disable when building a package for a distro
--with-maxconnections=size
Specify the max file descriptors to use
- --with-showlistmodes Specify whether modes are shown in /list
--with-no-operoverride Disable OperOverride
--with-operoverride-verify
Require opers to invite themselves to +s/+p channels
@@ -1459,6 +1476,9 @@ Optional Packages:
library. Normally autodetected via pkg-config
--without-system-cares Use bundled version instead of system c-ares.
Normally autodetected via pkg-config.
+ --without-system-jansson
+ Use bundled version instead of system jansson.
+ Normally autodetected via pkg-config.
Some influential environment variables:
CC C compiler command
@@ -1486,6 +1506,18 @@ Some influential environment variables:
CARES_CFLAGS
C compiler flags for CARES, overriding pkg-config
CARES_LIBS linker flags for CARES, overriding pkg-config
+ JANSSON_CFLAGS
+ C compiler flags for JANSSON, overriding pkg-config
+ JANSSON_LIBS
+ linker flags for JANSSON, overriding pkg-config
+ GEOIP_CLASSIC_CFLAGS
+ C compiler flags for GEOIP_CLASSIC, overriding pkg-config
+ GEOIP_CLASSIC_LIBS
+ linker flags for GEOIP_CLASSIC, overriding pkg-config
+ LIBMAXMINDDB_CFLAGS
+ C compiler flags for LIBMAXMINDDB, overriding pkg-config
+ LIBMAXMINDDB_LIBS
+ linker flags for LIBMAXMINDDB, overriding pkg-config
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
@@ -1554,7 +1586,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-unrealircd configure 5.2.0.1
+unrealircd configure 6.0.1.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1923,7 +1955,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 5.2.0.1, which was
+It was created by unrealircd $as_me 6.0.1.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2315,7 +2347,7 @@ orig_cflags="$CFLAGS"
BUILDDIR_NOW="`pwd`"
# Generation version number (e.g.: X in X.Y.Z)
-UNREAL_VERSION_GENERATION="5"
+UNREAL_VERSION_GENERATION="6"
cat >>confdefs.h <<_ACEOF
#define UNREAL_VERSION_GENERATION $UNREAL_VERSION_GENERATION
@@ -2323,7 +2355,7 @@ _ACEOF
# Major version number (e.g.: Y in X.Y.Z)
-UNREAL_VERSION_MAJOR="2"
+UNREAL_VERSION_MAJOR="0"
cat >>confdefs.h <<_ACEOF
#define UNREAL_VERSION_MAJOR $UNREAL_VERSION_MAJOR
@@ -2331,7 +2363,7 @@ _ACEOF
# Minor version number (e.g.: Z in X.Y.Z)
-UNREAL_VERSION_MINOR="0"
+UNREAL_VERSION_MINOR="1"
cat >>confdefs.h <<_ACEOF
#define UNREAL_VERSION_MINOR $UNREAL_VERSION_MINOR
@@ -5121,6 +5153,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
CFLAGS="$CFLAGS -funsigned-char"
+
CFLAGS="$CFLAGS -Wall"
ac_ext=c
@@ -5217,6 +5250,54 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wformat-nonliteral" >&5
+$as_echo_n "checking whether C compiler accepts -Wformat-nonliteral... " >&6; }
+if ${ax_cv_check_cflags__Werror___Wformat_nonliteral+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -Werror -Wformat-nonliteral"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ax_cv_check_cflags__Werror___Wformat_nonliteral=yes
+else
+ ax_cv_check_cflags__Werror___Wformat_nonliteral=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags__Werror___Wformat_nonliteral" >&5
+$as_echo "$ax_cv_check_cflags__Werror___Wformat_nonliteral" >&6; }
+if test x"$ax_cv_check_cflags__Werror___Wformat_nonliteral" = xyes; then :
+ CFLAGS="$CFLAGS -Wformat-nonliteral"
+else
+ :
+fi
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -5312,6 +5393,55 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wparentheses" >&5
+$as_echo_n "checking whether C compiler accepts -Wparentheses... " >&6; }
+if ${ax_cv_check_cflags__Werror___Wparentheses+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -Werror -Wparentheses"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ax_cv_check_cflags__Werror___Wparentheses=yes
+else
+ ax_cv_check_cflags__Werror___Wparentheses=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags__Werror___Wparentheses" >&5
+$as_echo "$ax_cv_check_cflags__Werror___Wparentheses" >&6; }
+if test x"$ax_cv_check_cflags__Werror___Wparentheses" = xyes; then :
+ CFLAGS="$CFLAGS -Wparentheses"
+else
+ :
+fi
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
@@ -5791,20 +5921,24 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if $CC --version | grep -q "clang version 3."; then :
+ CFLAGS="$CFLAGS -Wno-tautological-compare -Wno-pragmas"
+fi
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Waddress" >&5
-$as_echo_n "checking whether C compiler accepts -Waddress... " >&6; }
-if ${ax_cv_check_cflags__Werror___Waddress+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wpragmas" >&5
+$as_echo_n "checking whether C compiler accepts -Wpragmas... " >&6; }
+if ${ax_cv_check_cflags__Werror___Wpragmas+:} false; then :
$as_echo_n "(cached) " >&6
else
ax_check_save_flags=$CFLAGS
- CFLAGS="$CFLAGS -Werror -Waddress"
+ CFLAGS="$CFLAGS -Werror -Wpragmas"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -5817,19 +5951,19 @@ main ()
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
- ax_cv_check_cflags__Werror___Waddress=yes
+ ax_cv_check_cflags__Werror___Wpragmas=yes
else
- ax_cv_check_cflags__Werror___Waddress=no
+ ax_cv_check_cflags__Werror___Wpragmas=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
CFLAGS=$ax_check_save_flags
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags__Werror___Waddress" >&5
-$as_echo "$ax_cv_check_cflags__Werror___Waddress" >&6; }
-if test x"$ax_cv_check_cflags__Werror___Waddress" = xyes; then :
- CFLAGS="$CFLAGS -Wno-address"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags__Werror___Wpragmas" >&5
+$as_echo "$ax_cv_check_cflags__Werror___Wpragmas" >&6; }
+if test x"$ax_cv_check_cflags__Werror___Wpragmas" = xyes; then :
+ no_pragmas=1
else
- :
+ no_pragmas=0
fi
ac_ext=c
@@ -5838,21 +5972,20 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wcast-function-type" >&5
-$as_echo_n "checking whether C compiler accepts -Wcast-function-type... " >&6; }
-if ${ax_cv_check_cflags__Werror___Wcast_function_type+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wunknown-warning-option" >&5
+$as_echo_n "checking whether C compiler accepts -Wunknown-warning-option... " >&6; }
+if ${ax_cv_check_cflags__Werror___Wunknown_warning_option+:} false; then :
$as_echo_n "(cached) " >&6
else
ax_check_save_flags=$CFLAGS
- CFLAGS="$CFLAGS -Werror -Wcast-function-type"
+ CFLAGS="$CFLAGS -Werror -Wunknown-warning-option"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -5865,19 +5998,19 @@ main ()
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
- ax_cv_check_cflags__Werror___Wcast_function_type=yes
+ ax_cv_check_cflags__Werror___Wunknown_warning_option=yes
else
- ax_cv_check_cflags__Werror___Wcast_function_type=no
+ ax_cv_check_cflags__Werror___Wunknown_warning_option=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
CFLAGS=$ax_check_save_flags
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags__Werror___Wcast_function_type" >&5
-$as_echo "$ax_cv_check_cflags__Werror___Wcast_function_type" >&6; }
-if test x"$ax_cv_check_cflags__Werror___Wcast_function_type" = xyes; then :
- CFLAGS="$CFLAGS -Wno-cast-function-type"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags__Werror___Wunknown_warning_option" >&5
+$as_echo "$ax_cv_check_cflags__Werror___Wunknown_warning_option" >&6; }
+if test x"$ax_cv_check_cflags__Werror___Wunknown_warning_option" = xyes; then :
+ unknown_warning_option=1
else
- :
+ unknown_warning_option=0
fi
ac_ext=c
@@ -5887,6 +6020,14 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test "$unknown_warning_option" = "1"; then
+ CFLAGS="$CFLAGS -Wno-unknown-warning-option"
+else
+ if test "$no_pragmas" = "1"; then
+ CFLAGS="$CFLAGS -Wno-pragmas"
+ fi
+fi
+
@@ -6008,6 +6149,19 @@ $as_echo "#define HAVE_STRLNCAT /**/" >>confdefs.h
fi
done
+for ac_func in strlncpy
+do :
+ ac_fn_c_check_func "$LINENO" "strlncpy" "ac_cv_func_strlncpy"
+if test "x$ac_cv_func_strlncpy" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_STRLNCPY 1
+_ACEOF
+
+$as_echo "#define HAVE_STRLNCPY /**/" >>confdefs.h
+
+fi
+done
+
for ac_func in getrusage
do :
@@ -6448,29 +6602,6 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
-# Check whether --enable-prefixaq was given.
-if test "${enable_prefixaq+set}" = set; then :
- enableval=$enable_prefixaq;
-else
- enable_prefixaq=yes
-fi
-
-if test $enable_prefixaq = "yes"; then :
-
-$as_echo "#define PREFIX_AQ /**/" >>confdefs.h
-
-fi
-
-
-# Check whether --with-showlistmodes was given.
-if test "${with_showlistmodes+set}" = set; then :
- withval=$with_showlistmodes; if test $withval = "yes"; then :
-
-$as_echo "#define LIST_SHOW_MODES /**/" >>confdefs.h
-
-fi
-fi
-
# Check whether --with-no-operoverride was given.
if test "${with_no_operoverride+set}" = set; then :
@@ -6524,6 +6655,14 @@ else
fi
+# Check whether --with-system-jansson was given.
+if test "${with_system_jansson+set}" = set; then :
+ withval=$with_system_jansson;
+else
+ with_system_jansson=yes
+fi
+
+
# Check whether --enable-ssl was given.
if test "${enable_ssl+set}" = set; then :
enableval=$enable_ssl;
@@ -6570,7 +6709,11 @@ $as_echo "not found" >&6; }
else
CRYPTOLIB="-lssl -lcrypto";
if test ! "$ssldir" = "/usr" ; then
- LDFLAGS="$LDFLAGS -L$ssldir/lib";
+ if test -d "$ssldir/lib64" ; then
+ LDFLAGS="$LDFLAGS -L$ssldir/lib64";
+ else
+ LDFLAGS="$LDFLAGS -L$ssldir/lib";
+ fi
if test -f "$ssldir/bin/openssl"; then
OPENSSLPATH="$ssldir/bin/openssl";
fi
@@ -7655,7 +7798,7 @@ fi
if test "$has_system_cares" = "no"; then :
-cares_version="1.17.1"
+cares_version="1.17.2"
{ $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`
@@ -7716,6 +7859,130 @@ cd $cur_dir
fi
+has_system_jansson="no"
+if test "x$with_system_jansson" = "xyes"; then :
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for JANSSON" >&5
+$as_echo_n "checking for JANSSON... " >&6; }
+
+if test -n "$JANSSON_CFLAGS"; then
+ pkg_cv_JANSSON_CFLAGS="$JANSSON_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"jansson >= 2.0.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "jansson >= 2.0.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_JANSSON_CFLAGS=`$PKG_CONFIG --cflags "jansson >= 2.0.0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$JANSSON_LIBS"; then
+ pkg_cv_JANSSON_LIBS="$JANSSON_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"jansson >= 2.0.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "jansson >= 2.0.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_JANSSON_LIBS=`$PKG_CONFIG --libs "jansson >= 2.0.0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ JANSSON_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "jansson >= 2.0.0" 2>&1`
+ else
+ JANSSON_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "jansson >= 2.0.0" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$JANSSON_PKG_ERRORS" >&5
+
+ has_system_jansson=no
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ has_system_jansson=no
+else
+ JANSSON_CFLAGS=$pkg_cv_JANSSON_CFLAGS
+ JANSSON_LIBS=$pkg_cv_JANSSON_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ has_system_jansson=yes
+if test "x$PRIVATELIBDIR" != "x"; then :
+ rm -f "$PRIVATELIBDIR/"libjansson*
+fi
+fi
+fi
+
+if test "$has_system_jansson" = "no"; then :
+
+jansson_version="2.13.1"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: extracting jansson library" >&5
+$as_echo "extracting jansson library" >&6; }
+cur_dir=`pwd`
+cd extras
+rm -rf jansson-$jansson_version jansson
+if test "x$ac_cv_path_GUNZIP" = "x" ; then
+ tar xfz jansson.tar.gz
+else
+ cp jansson.tar.gz jansson.tar.gz.bak
+ gunzip -f jansson.tar.gz
+ cp jansson.tar.gz.bak jansson.tar.gz
+ tar xf jansson.tar
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: compiling jansson library" >&5
+$as_echo "compiling jansson library" >&6; }
+cd jansson-$jansson_version
+save_cflags="$CFLAGS"
+CFLAGS="$orig_cflags"
+export CFLAGS
+./configure --prefix=$cur_dir/extras/jansson --libdir=$PRIVATELIBDIR --enable-shared --disable-static --enable-opt || exit 1
+CFLAGS="$save_cflags"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: compiling jansson resolver library" >&5
+$as_echo "compiling jansson resolver library" >&6; }
+$ac_cv_prog_MAKER || exit 1
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: installing jansson resolver library" >&5
+$as_echo "installing jansson resolver library" >&6; }
+$ac_cv_prog_MAKER install || exit 1
+JANSSON_CFLAGS="-I$cur_dir/extras/jansson/include"
+
+JANSSON_LIBS=
+if test -n "$ac_cv_path_PKGCONFIG"; then :
+ JANSSON_LIBS="`$ac_cv_path_PKGCONFIG --libs jansson.pc`"
+fi
+if test -z "$JANSSON_LIBS"; then :
+ JANSSON_LIBS="-L$PRIVATELIBDIR -ljansson"
+fi
+
+cd $cur_dir
+
+fi
+
+
# Make sure we can run config.sub.
$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
@@ -8338,11 +8605,269 @@ rm -f core conftest.err conftest.$ac_objext \
LIBS="$LIBS_SAVEDA"
CFLAGS="$CFLAGS_SAVEDA"
- URL="url.o"
+ URL="url_curl.o"
+
+else
+
+ URL="url_unreal.o"
+
+fi
+
+
+
+ # Check whether --enable-geoip_classic was given.
+if test "${enable_geoip_classic+set}" = set; then :
+ enableval=$enable_geoip_classic; enable_geoip_classic=$enableval
+else
+ enable_geoip_classic=no
+fi
+
+
+ if test "x$enable_geoip_classic" = "xyes"; then :
+
+ has_system_geoip_classic="no"
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GEOIP_CLASSIC" >&5
+$as_echo_n "checking for GEOIP_CLASSIC... " >&6; }
+
+if test -n "$GEOIP_CLASSIC_CFLAGS"; then
+ pkg_cv_GEOIP_CLASSIC_CFLAGS="$GEOIP_CLASSIC_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"geoip >= 1.6.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "geoip >= 1.6.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GEOIP_CLASSIC_CFLAGS=`$PKG_CONFIG --cflags "geoip >= 1.6.0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$GEOIP_CLASSIC_LIBS"; then
+ pkg_cv_GEOIP_CLASSIC_LIBS="$GEOIP_CLASSIC_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"geoip >= 1.6.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "geoip >= 1.6.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GEOIP_CLASSIC_LIBS=`$PKG_CONFIG --libs "geoip >= 1.6.0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ GEOIP_CLASSIC_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "geoip >= 1.6.0" 2>&1`
+ else
+ GEOIP_CLASSIC_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "geoip >= 1.6.0" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$GEOIP_CLASSIC_PKG_ERRORS" >&5
+
+ has_system_geoip_classic=no
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ has_system_geoip_classic=no
+else
+ GEOIP_CLASSIC_CFLAGS=$pkg_cv_GEOIP_CLASSIC_CFLAGS
+ GEOIP_CLASSIC_LIBS=$pkg_cv_GEOIP_CLASSIC_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ has_system_geoip_classic=yes
+ if test "x$PRIVATELIBDIR" != "x"; then :
+ rm -f "$PRIVATELIBDIR/"libGeoIP.*
+fi
+fi
+
+ if test "$has_system_geoip_classic" = "no"; then :
+
+ geoip_classic_version="1.6.12"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: extracting GeoIP Classic library" >&5
+$as_echo "extracting GeoIP Classic library" >&6; }
+ cur_dir=`pwd`
+ cd extras
+ rm -rf GeoIP-$geoip_classic_version geoip-classic
+ if test "x$ac_cv_path_GUNZIP" = "x" ; then
+ tar xfz geoip-classic.tar.gz
+ else
+ cp geoip-classic.tar.gz geoip-classic.tar.gz.bak
+ gunzip -f geoip-classic.tar.gz
+ cp geoip-classic.tar.gz.bak geoip-classic.tar.gz
+ tar xf geoip-classic.tar
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: configuring GeoIP Classic library" >&5
+$as_echo "configuring GeoIP Classic library" >&6; }
+ cd GeoIP-$geoip_classic_version
+ save_cflags="$CFLAGS"
+ CFLAGS="$orig_cflags"
+ export CFLAGS
+ ./configure --prefix=$cur_dir/extras/geoip-classic --libdir=$PRIVATELIBDIR --enable-shared --disable-static || exit 1
+ CFLAGS="$save_cflags"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: compiling GeoIP Classic library" >&5
+$as_echo "compiling GeoIP Classic library" >&6; }
+ $ac_cv_prog_MAKER || exit 1
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: installing GeoIP Classic library" >&5
+$as_echo "installing GeoIP Classic library" >&6; }
+ $ac_cv_prog_MAKER install || exit 1
+ if test -n "$ac_cv_path_PKGCONFIG"; then :
+ GEOIP_CLASSIC_LIBS="`$ac_cv_path_PKGCONFIG --libs geoip.pc`"
+ GEOIP_CLASSIC_CFLAGS="`$ac_cv_path_PKGCONFIG --cflags geoip.pc`"
+fi
+ if test -z "$GEOIP_CLASSIC_LIBS"; then :
+ GEOIP_CLASSIC_LIBS="-L$PRIVATELIBDIR -lGeoIP"
+ GEOIP_CLASSIC_CFLAGS="-I$cur_dir/extras/geoip-classic/include"
+fi
+ cd $cur_dir
+
+fi
+
+
+
+
+ GEOIP_CLASSIC_OBJECTS="geoip_classic.so"
fi
+
+ # Check whether --enable-libmaxminddb was given.
+if test "${enable_libmaxminddb+set}" = set; then :
+ enableval=$enable_libmaxminddb; enable_libmaxminddb=$enableval
+else
+ enable_libmaxminddb=no
+fi
+
+
+ if test "x$enable_libmaxminddb" = "xyes"; then :
+
+ has_system_libmaxminddb="no"
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBMAXMINDDB" >&5
+$as_echo_n "checking for LIBMAXMINDDB... " >&6; }
+
+if test -n "$LIBMAXMINDDB_CFLAGS"; then
+ pkg_cv_LIBMAXMINDDB_CFLAGS="$LIBMAXMINDDB_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libmaxminddb >= 1.4.3\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libmaxminddb >= 1.4.3") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBMAXMINDDB_CFLAGS=`$PKG_CONFIG --cflags "libmaxminddb >= 1.4.3" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBMAXMINDDB_LIBS"; then
+ pkg_cv_LIBMAXMINDDB_LIBS="$LIBMAXMINDDB_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libmaxminddb >= 1.4.3\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libmaxminddb >= 1.4.3") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBMAXMINDDB_LIBS=`$PKG_CONFIG --libs "libmaxminddb >= 1.4.3" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ LIBMAXMINDDB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libmaxminddb >= 1.4.3" 2>&1`
+ else
+ LIBMAXMINDDB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libmaxminddb >= 1.4.3" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBMAXMINDDB_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libmaxminddb >= 1.4.3) were not met:
+
+$LIBMAXMINDDB_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables LIBMAXMINDDB_CFLAGS
+and LIBMAXMINDDB_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables LIBMAXMINDDB_CFLAGS
+and LIBMAXMINDDB_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see .
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ LIBMAXMINDDB_CFLAGS=$pkg_cv_LIBMAXMINDDB_CFLAGS
+ LIBMAXMINDDB_LIBS=$pkg_cv_LIBMAXMINDDB_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ has_system_libmaxminddb=yes
+fi
+ if test "x$has_system_libmaxminddb" = "xyes"; then :
+
+
+
+
+
+ GEOIP_MAXMIND_OBJECTS="geoip_maxmind.so"
+
+
+fi
+
+fi
+
+
UNRLINCDIR="`pwd`/include"
if test "$ac_cv_werror" = "yes" ; then
@@ -8358,7 +8883,7 @@ fi
-ac_config_files="$ac_config_files Makefile src/Makefile src/modules/Makefile src/modules/chanmodes/Makefile src/modules/usermodes/Makefile src/modules/snomasks/Makefile src/modules/extbans/Makefile src/modules/third/Makefile extras/unrealircd-upgrade-script unrealircd"
+ac_config_files="$ac_config_files Makefile src/Makefile src/modules/Makefile src/modules/chanmodes/Makefile src/modules/usermodes/Makefile src/modules/extbans/Makefile src/modules/third/Makefile extras/unrealircd-upgrade-script unrealircd"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -8866,7 +9391,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 5.2.0.1, which was
+This file was extended by unrealircd $as_me 6.0.1.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -8929,7 +9454,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 5.2.0.1
+unrealircd config.status 6.0.1.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -9056,7 +9581,6 @@ do
"src/modules/Makefile") CONFIG_FILES="$CONFIG_FILES src/modules/Makefile" ;;
"src/modules/chanmodes/Makefile") CONFIG_FILES="$CONFIG_FILES src/modules/chanmodes/Makefile" ;;
"src/modules/usermodes/Makefile") CONFIG_FILES="$CONFIG_FILES src/modules/usermodes/Makefile" ;;
- "src/modules/snomasks/Makefile") CONFIG_FILES="$CONFIG_FILES src/modules/snomasks/Makefile" ;;
"src/modules/extbans/Makefile") CONFIG_FILES="$CONFIG_FILES src/modules/extbans/Makefile" ;;
"src/modules/third/Makefile") CONFIG_FILES="$CONFIG_FILES src/modules/third/Makefile" ;;
"extras/unrealircd-upgrade-script") CONFIG_FILES="$CONFIG_FILES extras/unrealircd-upgrade-script" ;;
diff --git a/configure.ac b/configure.ac
index 4246558..9dff663 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@ dnl src/windows/unrealinst.iss
dnl doc/Config.header
dnl src/version.c.SH
-AC_INIT([unrealircd], [5.2.0.1], [https://bugs.unrealircd.org/], [], [https://unrealircd.org/])
+AC_INIT([unrealircd], [6.0.1.1], [https://bugs.unrealircd.org/], [], [https://unrealircd.org/])
AC_CONFIG_SRCDIR([src/ircd.c])
AC_CONFIG_HEADER([include/setup.h])
AC_CONFIG_AUX_DIR([autoconf])
@@ -26,15 +26,15 @@ BUILDDIR_NOW="`pwd`"
dnl Calculate the versions. Perhaps the use of expr is a little too extravagant
# Generation version number (e.g.: X in X.Y.Z)
-UNREAL_VERSION_GENERATION=["5"]
+UNREAL_VERSION_GENERATION=["6"]
AC_DEFINE_UNQUOTED([UNREAL_VERSION_GENERATION], [$UNREAL_VERSION_GENERATION], [Generation version number (e.g.: X for X.Y.Z)])
# Major version number (e.g.: Y in X.Y.Z)
-UNREAL_VERSION_MAJOR=["2"]
+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=["0"]
+UNREAL_VERSION_MINOR=["1"]
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
@@ -189,18 +189,26 @@ CFLAGS="$CFLAGS -funsigned-char"
dnl Compiler -W checks...
+dnl == ADD THESE WARNINGS ==
+
dnl We should be able to turn this on unconditionally:
CFLAGS="$CFLAGS -Wall"
dnl More warnings (if the compiler supports it):
check_cc_flag([-Wextra], [CFLAGS="$CFLAGS -Wextra"])
check_cc_flag([-Waggregate-return], [CFLAGS="$CFLAGS -Waggregate-return"])
+check_cc_flag([-Wformat-nonliteral], [CFLAGS="$CFLAGS -Wformat-nonliteral"])
+
dnl The following few are more experimental, if they have false positives we'll have
dnl to disable them:
dnl Can't use this, too bad: check_cc_flag([-Wlogical-op], [CFLAGS="$CFLAGS -Wlogical-op"])
check_cc_flag([-Wduplicated-cond], [CFLAGS="$CFLAGS -Wduplicated-cond"])
check_cc_flag([-Wduplicated-branches], [CFLAGS="$CFLAGS -Wduplicated-branches"])
+check_cc_flag([-Wparentheses], [CFLAGS="$CFLAGS -Wparentheses"])
+
+dnl == REMOVE THESE WARNINGS ==
+
dnl And now to filter out certain warnings:
dnl [!] NOTE REGARDING THE check_cc_flag used by these:
dnl We check for the -Woption even though we are going to use -Wno-option.
@@ -247,12 +255,31 @@ check_cc_flag([-Wsign-compare], [CFLAGS="$CFLAGS -Wno-sign-compare"])
dnl Don't warn about empty body, we use this, eg via Debug(()) or in if's.
check_cc_flag([-Wempty-body], [CFLAGS="$CFLAGS -Wno-empty-body"])
-dnl This one fails with ircstrdup(var, staticstring)
-dnl Shame we have to turn it off completely...
-check_cc_flag([-Waddress], [CFLAGS="$CFLAGS -Wno-address"])
+dnl Yeah this old clang version is a bit problematic
+dnl (ships in Ubuntu 16.04 for example)
+dnl -Wtautological-compare has false positives
+dnl -Wno-pragmas is needed, despite -Wno-unknown-warning-option
+AS_IF([$CC --version | grep -q "clang version 3."],
+ [CFLAGS="$CFLAGS -Wno-tautological-compare -Wno-pragmas"])
-dnl This one breaks our TO_INTFUNC() that is used in m_tkl for tkl_typetochar
-check_cc_flag([-Wcast-function-type], [CFLAGS="$CFLAGS -Wno-cast-function-type"])
+dnl This one MUST be LAST!!
+dnl It disables -Wsomeunknownoption being an error. Which is needed for
+dnl the pragma's in individual files to selectively disable some warnings
+dnl on clang/gcc (that may exist in eg gcc but not in clang or vice versa).
+check_cc_flag([-Wpragmas], [no_pragmas=1],[no_pragmas=0])
+check_cc_flag([-Wunknown-warning-option], [unknown_warning_option=1], [unknown_warning_option=0])
+
+if test "$unknown_warning_option" = "1"; then
+ dnl This is the best option
+ CFLAGS="$CFLAGS -Wno-unknown-warning-option"
+else
+ if test "$no_pragmas" = "1"; then
+ dnl This is a fallback needed for older gcc/clang, it also
+ dnl disables several other useful warnings/errors related
+ dnl to pragma's unfortunately.
+ CFLAGS="$CFLAGS -Wno-pragmas"
+ fi
+fi
dnl End of -W... compiler checks.
@@ -352,6 +379,8 @@ AC_CHECK_FUNCS(strlcat,
AC_DEFINE([HAVE_STRLCAT], [], [Define if you have strlcat]))
AC_CHECK_FUNCS(strlncat,
AC_DEFINE([HAVE_STRLNCAT], [], [Define if you have strlncat]))
+AC_CHECK_FUNCS(strlncpy,
+ AC_DEFINE([HAVE_STRLNCPY], [], [Define if you have strlncpy]))
AC_CHECK_FUNCS([getrusage],
[AC_DEFINE([GETRUSAGE_2], [], [Define if you have getrusage])],
@@ -492,17 +521,6 @@ AC_ARG_WITH(maxconnections, [AS_HELP_STRING([--with-maxconnections=size], [Speci
[ac_fd=0])
AC_DEFINE_UNQUOTED([MAXCONNECTIONS_REQUEST], [$ac_fd], [Set to the maximum number of connections you want])
-AC_ARG_ENABLE([prefixaq],
- [AS_HELP_STRING([--disable-prefixaq],[Disable chanadmin (+a) and chanowner (+q) prefixes])],
- [],
- [enable_prefixaq=yes])
-AS_IF([test $enable_prefixaq = "yes"],
- [AC_DEFINE([PREFIX_AQ], [], [Define if you want +a/+q prefixes])])
-
-AC_ARG_WITH(showlistmodes,
- [AS_HELP_STRING([--with-showlistmodes], [Specify whether modes are shown in /list])],
- [AS_IF([test $withval = "yes"],
- [AC_DEFINE([LIST_SHOW_MODES], [], [Define if you want modes shown in /list])])])
AC_ARG_WITH(no-operoverride, [AS_HELP_STRING([--with-no-operoverride], [Disable OperOverride])],
[AS_IF([test $withval = "yes"],
[AC_DEFINE([NO_OPEROVERRIDE], [], [Define if you want OperOverride disabled])])])
@@ -513,6 +531,7 @@ AC_ARG_WITH(system-pcre2, [AS_HELP_STRING([--without-system-pcre2], [Use the sys
AC_ARG_WITH(system-argon2, [AS_HELP_STRING([--without-system-argon2], [Use bundled version instead of system argon2 library. Normally autodetected via pkg-config])], [], [with_system_argon2=yes])
AC_ARG_WITH(system-sodium, [AS_HELP_STRING([--without-system-sodium], [Use bundled version instead of system sodium library. Normally autodetected via pkg-config])], [], [with_system_sodium=yes])
AC_ARG_WITH(system-cares, [AS_HELP_STRING([--without-system-cares], [Use bundled version instead of system c-ares. Normally autodetected via pkg-config.])], [], [with_system_cares=yes])
+AC_ARG_WITH(system-jansson, [AS_HELP_STRING([--without-system-jansson], [Use bundled version instead of system jansson. Normally autodetected via pkg-config.])], [], [with_system_jansson=yes])
CHECK_SSL
CHECK_SSL_CTX_SET1_CURVES_LIST
CHECK_SSL_CTX_SET_MIN_PROTO_VERSION
@@ -697,7 +716,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.1"
+cares_version="1.17.2"
AC_MSG_RESULT(extracting c-ares resolver library)
cur_dir=`pwd`
cd extras
@@ -763,10 +782,65 @@ AC_SUBST(CARES_LIBS)
cd $cur_dir
])
+dnl Use system jansson when available, unless --without-system-jansson
+has_system_jansson="no"
+AS_IF([test "x$with_system_jansson" = "xyes"],[
+PKG_CHECK_MODULES([JANSSON], [jansson >= 2.0.0],[has_system_jansson=yes
+AS_IF([test "x$PRIVATELIBDIR" != "x"], [rm -f "$PRIVATELIBDIR/"libjansson*])],[has_system_jansson=no])])
+
+AS_IF([test "$has_system_jansson" = "no"],[
+dnl REMEMBER TO CHANGE WITH A NEW JANSSON RELEASE!
+jansson_version="2.13.1"
+AC_MSG_RESULT(extracting jansson library)
+cur_dir=`pwd`
+cd extras
+dnl remove old jansson directory to force a recompile...
+dnl and remove its installation prefix just to clean things up.
+rm -rf jansson-$jansson_version jansson
+if test "x$ac_cv_path_GUNZIP" = "x" ; then
+ tar xfz jansson.tar.gz
+else
+ cp jansson.tar.gz jansson.tar.gz.bak
+ gunzip -f jansson.tar.gz
+ cp jansson.tar.gz.bak jansson.tar.gz
+ tar xf jansson.tar
+fi
+AC_MSG_RESULT(compiling jansson library)
+cd jansson-$jansson_version
+save_cflags="$CFLAGS"
+CFLAGS="$orig_cflags"
+export CFLAGS
+./configure --prefix=$cur_dir/extras/jansson --libdir=$PRIVATELIBDIR --enable-shared --disable-static --enable-opt || exit 1
+CFLAGS="$save_cflags"
+AC_MSG_RESULT(compiling jansson resolver library)
+$ac_cv_prog_MAKER || exit 1
+AC_MSG_RESULT(installing jansson resolver library)
+$ac_cv_prog_MAKER install || exit 1
+JANSSON_CFLAGS="-I$cur_dir/extras/jansson/include"
+AC_SUBST(JANSSON_CFLAGS)
+JANSSON_LIBS=
+dnl See c-ares's compilation section for more info on this hack.
+dnl ensure that we're linking against the bundled version
+dnl (we only reach this code if linking against the bundled version is desired).
+AS_IF([test -n "$ac_cv_path_PKGCONFIG"],
+ [JANSSON_LIBS="`$ac_cv_path_PKGCONFIG --libs jansson.pc`"])
+dnl ^^^ FIXME FIXME this is likely incorrect the .pc etc
+dnl For when pkg-config isn't available
+AS_IF([test -z "$JANSSON_LIBS"],
+ [JANSSON_LIBS="-L$PRIVATELIBDIR -ljansson"])
+AC_SUBST(JANSSON_LIBS)
+cd $cur_dir
+])
+
+
AX_PTHREAD()
CHECK_LIBCURL
+CHECK_GEOIP_CLASSIC
+
+CHECK_LIBMAXMINDDB
+
UNRLINCDIR="`pwd`/include"
dnl Moved to the very end to ensure it doesn't affect any libs or tests.
@@ -789,7 +863,6 @@ AC_CONFIG_FILES([Makefile
src/modules/Makefile
src/modules/chanmodes/Makefile
src/modules/usermodes/Makefile
- src/modules/snomasks/Makefile
src/modules/extbans/Makefile
src/modules/third/Makefile
extras/unrealircd-upgrade-script
diff --git a/doc/Config.header b/doc/Config.header
index 849ed60..98ec32f 100644
--- a/doc/Config.header
+++ b/doc/Config.header
@@ -7,7 +7,7 @@
\___/|_| |_|_| \___|\__,_|_|\___/\_| \_| \____/\__,_|
Configuration Program
- for UnrealIRCd 5.2.0.1
+ for UnrealIRCd 6.0.1.1
This program will help you to compile your IRC server, and ask you
questions regarding the compile-time settings of it during the process.
@@ -16,15 +16,15 @@ A short installation guide is available online at:
https://www.unrealircd.org/docs/Installing_from_source
Full documentation is available at:
-https://www.unrealircd.org/docs/UnrealIRCd_5_documentation
+https://www.unrealircd.org/docs/UnrealIRCd_6_documentation
--------------------------------------------------------------------------------------
The full release notes are available in doc/RELEASE-NOTES.md
For easier viewing, check out the latest online release notes at:
-https://github.com/unrealircd/unrealircd/blob/unreal52/doc/RELEASE-NOTES.md
+https://github.com/unrealircd/unrealircd/blob/unreal60_dev/doc/RELEASE-NOTES.md
-UnrealIRCd 5 is compatible with the following services:
+UnrealIRCd 6 is compatible with the following services:
* anope with the "unreal4" protocol module - version 2.0.7 or higher required!
* atheme with the "unreal4" protocol module - tested with version 7.2.9
diff --git a/doc/RELEASE-NOTES.md b/doc/RELEASE-NOTES.md
index 5379a77..e0ac30d 100644
--- a/doc/RELEASE-NOTES.md
+++ b/doc/RELEASE-NOTES.md
@@ -1,1000 +1,254 @@
-UnrealIRCd 5.2.0.1 Release Notes
-=================================
-
-About 5.2.0.1
---------------
-5.2.0.1 fixes an issue with spamfilter that was present in 5.2.0.
-In channels spamfilters were processed for type ```p``` instead of ```c```.
-Existing 5.2.0 users on *NIX can upgrade without restart by running
-```./unrealircd hot-patch wrongspamfilter520```
-
-UnrealIRCd 5.2.0 is out!
--------------------------
-
-This is UnrealIRCd 5.2.0, a release with lots of new features.
-The two main new features are: an improved and more flexible anti-flood block
-and channel history which can now be stored encrypted on disk and allows
-clients to fetch hundreds/thousands of lines.
-
-Upgrading and the 5.0.x series
--------------------------------
-UnrealIRCd 5.2.0 is the direct successor to 5.0.9/5.0.9.1.
-There will be [no further 5.0.x releases](https://www.unrealircd.org/docs/FAQ#About_the_new_5.2.x_series),
-in particular there will be no 5.0.10.
-
-Only four bugs that affect a limited number of people/networks were fixed.
-UnrealIRCd 5.2.0 is mostly a feature release.
-Admins wishing to take a conservative approach don't need to rush an
-upgrade from 5.0.x to 5.2.0, they can wait for a 5.2.1 or 5.2.2 release.
-
-If you are upgrading from 5.0.9(.1) to 5.2.0 then feel free to try the new
-```./unrealircd upgrade``` command.
-
-The only configuration change is in the set::anti-flood block (as explained
-further down under *Enhancements*). When starting UnrealIRCd will give you
-clear instructions if anything needs to be changed (and what).
-This process is really minor, the server will usually tell you to just
-delete a few old lines from the configuration file.
-
-Enhancements
--------------
-* The set::anti-flood block has been redone so you can have different limits
- for *unknown-users* and *known-users*.
- * As a reminder, by default, *known-users* are users who are identified
- to services OR are on an IP that has been connected for over 2 hours
- in the past X days. The exact definition of "known-users" is in the
- [security-group block](https://www.unrealircd.org/docs/Security-group_block).
- * See [here](https://www.unrealircd.org/docs/Anti-flood_settings)
- for more information on the layout of the new set::anti-flood block.
- * All violations of target-flood, nick-flood, join-flood, away-flood,
- invite-flood, knock-flood, max-concurrent-conversations are now
- reported to opers with the snomask ```f``` (flood).
-* Add support for database encryption. The way this works
- is that you define an encryption password in a
- [secret { } block](https://www.unrealircd.org/docs/Secret_block).
- Then from the various modules you can refer to this secret
- block, from
- [set::reputation::db-secret](https://www.unrealircd.org/docs/Set_block#set::reputation),
- [set::tkldb::db-secret](https://www.unrealircd.org/docs/Set_block#set::tkldb)
- and [set::channeldb::db-secret](https://www.unrealircd.org/docs/Set_block#set::channeldb).
- This way you can encrypt the reputation, TKL and channel
- database for increased privacy.
-* Add optional support for
- [persistent channel history](https://www.unrealircd.org/docs/Set_block#Persistent_channel_history):
- * This stores channel history on disk for channels that have
- both ```+H``` and ```+P``` set.
- * If you enable this then we ALWAYS require you to set an
- encryption password, as we do not allow storing of
- channel history in plain text.
- * If you enable the option, then the history is stored in
- ```data/history/``` in individual .db files. No channel
- names are visible in the filenames for optimal privacy.
- * See [Persistent channel history](https://www.unrealircd.org/docs/Set_block#Persistent_channel_history)
- on how to enable this. By default it is off.
-* Add support for IRCv3
- [draft/chathistory](https://ircv3.net/specs/extensions/chathistory).
-* The maximums for channel mode ```+H``` have been raised and are now
- different for ```+r``` (registered) and ```-r``` channels. For unregistered
- channels the limit is now 200 lines / 31 days. For registered channels
- the limit is 5000 lines / 31 days. The old limit for both was 200 lines / 7 days.
- These maximums can be changed in the now slightly different
- [set::history::channel::max-storage-per-channel](https://www.unrealircd.org/docs/Set_block#set::history)
- block.
-* Add c-ares and libsodium version output to boot screen and /VERSION.
-* WHOX now supports displaying the
- [reputation score](https://www.unrealircd.org/docs/Reputation_score).
- If you are an IRCOp then you can use e.g. ```WHO * %cuhsnfmdaRr```.
-* Add ability to [spamfilter](https://www.unrealircd.org/docs/Spamfilter)
- message tags via the new ```T``` target. Right now it would be unusual
- to use this, but some day when we have more
- [message tags](https://www.unrealircd.org/docs/Message_tags) it
- may come in handy.
-* Support [```+draft/reply```](https://ircv3.net/specs/client-tags/reply) IRCv3
- client tag. Can be used by bots (and others) to indicate to what message
- people are replying to. This module, reply-tag, is loaded by default.
-* Send [```draft/bot```](https://ircv3.net/specs/extensions/bot-mode) IRCv3
- message tag if the user has mode ```+B``` set.
-* [Websockets](https://www.unrealircd.org/docs/WebSocket_support):
- add support for clients to negotiate an explicit type via
- ```Sec-WebSocket-Protocol```, instead of only the default type from
- [listen::websocket::type](https://www.unrealircd.org/docs/WebSocket_support#2._Enable_websocket_on_the_port).
- This is based on an IRCv3 websocket draft specification.
- Note that UnrealIRCd refuses type text if your configuration allows
- non-UTF8 characters in channel or nick names because it would lead
- to security and compatibility issues.
-* [set::restrict-commands](https://www.unrealircd.org/docs/Set_block#set::restrict-commands):
- new option *exempt-tls* which allows SSL/TLS users to bypass a restriction.
-
-Fixes
-------
-* Server squiting the wrong side. Often harmless, but when (re)connecting
- rapidly to multiple servers with autoconnect this could cause the
- network to fall apart.
-* Forbid using [extended server bans](https://www.unrealircd.org/docs/Extended_server_bans)
- in ZLINE/GZLINE since they won't work there.
-* Extended server ban ```~a:accname``` was not working for shun, and only
- partially working for kline/gline.
-* More accurate /ELINE error message.
-
-Changed
---------
-* Channel mode ```+H``` always showed time in minutes (```m```) until now.
- From now on it will show it in minutes (```m```), hours (```h```) or
- days (```d```) depending on the actual value. Eg ```+H 50:7d```.
-* If you ran ```./unrealircd stop``` we used to wait only 1 second.
- From now on we will wait up to 10 seconds max. This gives UnrealIRCd
- plenty of time to write database files.
-* If you have zero [log blocks](https://www.unrealircd.org/docs/Log_block)
- then we already automatically logged errors to ```ircd.log```.
- From now on we will log everything (not only errors) to that file.
-
-Removed
---------
-* Version check for curl and openssl as nowadays they have ABI guarantees.
-
-Module coders / Developers
----------------------------
-* New UnrealDB API and disk format, see
- https://www.unrealircd.org/docs/Dev:UnrealDB
-* We now use libsodium for file encryption routines as well
- as some helpers to lock/clear passwords in memory.
-* Updated ```HOOKTYPE_LOCAL_NICKCHANGE``` and
- ```HOOKTYPE_REMOTE_NICKCHANGE``` to include an
- ```MessageTag *mtags``` argument in the middle.
- You can use ```#if UNREAL_VERSION_TIME>=202115``` to detect this.
-* Updated channel mode ```conv_param``` function to
- include a ```Channel *channel``` argument at the end.
- You can use ```#if UNREAL_VERSION_TIME>=202120``` to detect this.
-* New: ```ModuleSetOptions(modinfo->handle, MOD_OPT_UNLOAD_PRIORITY, priority);```.
- This can be used for modules to indicate they wish to be unloaded
- before or after others. It is used by for example the channel
- and history modules so they can save their databases before
- channel mode modules or other modules get unloaded.
-* New CAP [```draft/chathistory```](https://ircv3.net/specs/extensions/chathistory).
- If a client REQ's this CAP then UnrealIRCd won't send history on-join as
- it assumes the client will fetch it when they feel the need for it.
-* New informative CAP:
- [```unrealircd.org/history-backend```](https://www.unrealircd.org/history-backend)
-
-Reminder: UnrealIRCd 4 is no longer supported
-----------------------------------------------
-
-UnrealIRCd 4.x is [no longer supported](https://www.unrealircd.org/docs/UnrealIRCd_4_EOL).
-Admins must [upgrade to UnrealIRCd 5](https://www.unrealircd.org/docs/Upgrading_from_4.x).
-
-UnrealIRCd 5.0.9.1
--------------------
-The only change between 5.0.9 and 5.0.9.1 is:
-* Build improvements on *NIX (faster compiling and lower memory requirements)
-* Windows version is unchanged and still 5.0.9
-
-UnrealIRCd 5.0.9
------------------
-The 5.0.9 release comes with several nice feature enhancements. There are no major bug fixes.
-
-Enhancements:
-* Changes to the "Client connecting" notice on IRC (for IRCOps):
- * The format changed slightly, instead of ```{clients}``` it
- now shows ```[class: clients]```
- * SSL/TLS information is still shown via ```[secure]```
- * New: ```[reputation: NNN]``` to show the current
- [reputation score](https://www.unrealircd.org/docs/Reputation_score)
- * New: ```[account: abcdef]``` to show the services account,
- but only if [SASL](https://www.unrealircd.org/docs/SASL) was used.
-* In the log file the format also changed slightly:
- * IP information is now added as ```[127.0.0.1]``` in both the
- connect and disconnect log messages.
- * The vhost is logged as ```[vhost: xyz]``` instead of ```[VHOST xyz]```
- * All the other values are now logged as well on-connect,
- similar to the "Client connecting" notice, so: secure, reputation,
- account (if applicable).
-* New option [allow::global-maxperip](https://www.unrealircd.org/docs/Allow_block):
- this imposes a global (network-wide) restriction on the number of
- connections per IP address.
- If you don't have a global-maxperip setting in the allow block then it
- will default to maxperip plus one. So, if you currently have an
- allow::maxperip of 3 then global-maxperip will be 4.
-* [Handshake delay](https://www.unrealircd.org/docs/Set_block#set::handshake-delay)
- is automatically disabled for users that are exempt from blacklist checking.
-* Always exempt 127.* from gline, kline, etc.
-* You can now have dated logfiles thanks to strftime formatting.
- For example ```log "ircd.%Y-%m-%d.log" { }``` will create a log
- file like called ircd.2020-01-31.log, a new one every day.
-* The Windows build now supports TLSv1.3 too.
+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:
-* Windows: some warnings and error messages on boot were previously
- missing.
+* In 6.0.1.1: extended bans were not properly synced between U5 and U6.
+ This caused missing extended bans on the U5 side (MODE was working OK,
+ this only happened when linking servers)
+* Text extbans did not have any effect (`+b ~text:censor:*badword*`)
+* Timed bans were not expiring if all servers on the network were on U6
+* Channel mode `+f` could place a timed extban with `~t` instead of `~time`
+* Crash when unloading any of the vhoaq modules at runtime
+* `./unrealircd upgrade` not working on FreeBSD and not with self-compiled cURL
+* Some log messages being wrong (`CHGIDENT`, `CHGNAME`)
+* Remove confusing high cpu load warning
-Changes:
-* Add ```doc/KEYS``` which contains the public key(s) used to sign UnrealIRCd releases
-* The options set::anti-flood::unknown-flood-* have been renamed and
-integrated in a new block called
-[set::anti-flood::handshake-data-flood](https://www.unrealircd.org/docs/Set_block#set::anti-flood::handshake-data-flood).
-The ban-action can now also be changed. Note that almost nobody will have to
-change this setting since it has a good default.
-* On *NIX bump the default maximum connections from 8192 to 16384.
-That is, when in "auto" mode, which is like for 99% of the users.
-Note that the system may still limit the actual number of connections
-to a lower value, epending on the value of ```ulimit -n -H```.
+Enhancements:
+* Error on unknown snomask in set::snomask-on-oper and oper::snomask.
+* TKL add/remove/expire messages now show `[duration: 60m]` instead of
+ the `[expires: ZZZ GMT]` string since that is what people are more
+ interested in and is not affected by time zones. The format in all the
+ 3 notices is also consistent now.
-UnrealIRCd 5.0.8
+UnrealIRCd 6.0.0
-----------------
-The main purpose of this release is to enhance the
-[reputation](https://www.unrealircd.org/docs/Reputation_score)
-functionality. There have also been some other changes and minor
-bug fixes. For more information, see below.
-
-Enhancements:
-* Support for [security groups](https://www.unrealircd.org/docs/Security-group_block),
- of which four groups always exist by default: known-users, unknown-users,
- tls-users and tls-and-known-users.
-* New extended ban ```~G:securitygroupname```. Typical usage would be
- ```MODE #chan +b ~G:unknown-users``` which will ban all users from the
- channel that are not identified to services and have a reputation
- score below 25 (by default). The exact settings can be tweaked in the
- [security group block](https://www.unrealircd.org/docs/Security-group_block).
-* The reputation command (IRCOp-only) has been extended to make it
- easier to look for potential troublemakers:
- * ```REPUTATION Nick``` shows reputation about the nick name
- * ```REPUTATION IP``` shows reputation about the IP address
- * ```REPUTATION #channel``` lists users in channel with their reputation score
- * ```REPUTATION chname` is `channel->name` now.
+* get_channel() is now make_channel() and creates if needed, otherwise use find_channel()
+* The Extended Ban API has been changed a lot. We use a `BanContext` struct now
+ that we pass around a lot. You also don't need to do `+3` magic anymore on the
+ string as it is handled in another layer. When registering the extended ban,
+ `.flag` is now `.letter`, and you also need to set a `.name` to a string due
+ to named extended bans. Have a look at the built-in extban modules to see
+ how to handle the changes.
+* ModData now has an option `MODDATA_SYNC_EARLY`. See under *Server protocol*.
+* If you want to lag someone up, don't touch `client->since`, but instead use:
+ `add_fake_lag(client, msec)`
+* Some client/user struct changes, with `client->user->account` (instead of svid)
+ and `client->uplink->name` being the most important ones.
+* Possibly more, but above is like 90%+ of the changes that you will encounter.
Server protocol
----------------
-* UnrealIRCd 5 now assumes you support the following PROTOCTL options:
- ```NOQUIT EAUTH SID NICKv2 SJOIN SJ3 NICKIP TKLEXT2```.
- If you fail to use ```SID``` or ```EAUTH``` then you will receive an
- error. For the other options, support is *assumed*, no warning or
- error is shown when you lack support. These are options that most,
- if not all, services support since UnrealIRCd 4.x so it shouldn't be
- a problem. More information [here](https://www.unrealircd.org/docs/FAQ#old-server-protocol)
-* ```PROTOCTL MTAGS``` indicates that the server is capable of handling
- message tags and that the server can cope with 4K lines. (Note that
- the ordinary non-message-tag part is still limited to 512 bytes).
-* Pseudo ID support in SASL was removed. We now use real UID's.
- This breaks services who rely on the old pseudo ID format.
+* When multiple related `SJOIN` messages are generated for the same channel
+ then we now only send the current channel modes (eg `+sntk key`) in the
+ first SJOIN and not in the other ones as they are unneeded for the
+ immediate followup SJOINs, they waste unnecessary bytes and CPU.
+ Such messages may be generated when syncing a channel that has dozens
+ of users and/or bans/exempts/invexes. Ideally this should not need any
+ changes in other software, since we already supported such messages in the
+ past and code for handling it exists way back to 3.2.x, but you better
+ check to be sure!
+* If you send `PROTOCTL NEXTBANS` then you will receive extended bans
+ with Named EXTended BANs instead of letters (eg: `+b ~account:xyz`),
+ otherwise you receive them with letters (eg: `+b ~a:xyz`).
+* Some ModData of users is (also) communicated in the `UID` message while
+ syncing using a message tag that only appears in server-to-server traffic,
+ `s2s-md/moddataname=value`. Thus, data such as operinfo, tls cipher,
+ geoip, certfp, sasl and webirc is communicated at the same time as when
+ a remote connection is added.
+ This makes it that a "connecting from" server notice can include all this
+ information and also so code can make an immediate decission on what to do
+ with the user in hooks. ModData modules need to set
+ `mreq.sync = MODDATA_SYNC_EARLY;` if they want this.
+ Servers of course need to enable `MTAGS` in PROTOCTL to see this.
+* The `SLOG` command is used to broadcast logging messages. This is done
+ for log::destination remote, as used in doc/conf/snomasks.default.conf,
+ for example for link errors, oper ups, flood messages, etc.
+ It also includes all JSON data in a message tag when `PROTOCTL MTAGS` is used.
+* Bounced modes are gone: these were MODEs that started with a `&` which
+ servers were to act on with reversed logic (add becoming remove and
+ vice versa) and never to send something back to that server.
+ In practice this was almost never used and complicated the code (way)
+ too much.
Client protocol
----------------
-* Support for message tags and other IRCv3 features. See the IRCv3
- specifications for more details.
-* When a message is blocked, for whatever reason, we now use a generic
- numeric response: ```:server 531 yourname targetname :reason``` for the block
- This replaces all the various NOTICEs, ```ERR_NOCTCP```, ```ERR_NONONREG```, etc.
- with just one single numeric.
- The only other numerics that you may still encounter when PM'ing are
- ```ERR_NOSUCHNICK```, ```ERR_TOOMANYTARGETS``` and ```ERR_TARGETTOOFAST```, which are
- generic errors to any command involving targets. And ```ERR_SERVICESDOWN```.
- Note that channel messages already had a generic numeric for signaling
- blocked messages for a very long time, ```ERR_CANNOTSENDTOCHAN```.
-* The 271 response to the SILENCE command is now:
- ```:server 271 yournick listentry!*@*```
- Previously the nick name appeared twice, which was a mistake.
-* The 470 numeric, which is sent on /JOIN #channel redirect to #redirect
- now uses the following format:
- ```:server 470 yournick #channel #redirect :[Link] Cannot join channel...etc..```
-* Clients are recommended to implement and enable the
- [server-time](https://ircv3.net/specs/extensions/server-time-3.2)
- extension by default. When enabled, channel history is played back
- on-join (if any) when the channel has channel mode +H.
- Otherwise your users will not see channel history.
+* Extended bans now have names instead of letters. If a client sends the
+ old format with letters (eg `+b ~a:XYZ`) then the server will
+ convert it to the new format with names (eg: `+b ~account:XYZ`)
+* Support for `MONITOR` and the other IRCv3 features (see *Enhancements*)
diff --git a/doc/conf/badwords.conf b/doc/conf/badwords.conf
index e11623e..56b5b7b 100644
--- a/doc/conf/badwords.conf
+++ b/doc/conf/badwords.conf
@@ -1,27 +1,44 @@
-badword channel { word "bitch"; replace "wombat"; }
-badword channel { word "bro"; replace "bo"; }
-badword channel { word "(brother)"; replace "bredda"; }
-badword channel { word "car"; replace "taxi"; }
-badword channel { word "discord"; replace "dicsord"; }
-badword channel { word "efnet"; replace "efrael"; }
-badword channel { word "hate"; replace "04 hate "; }
-badword channel { word "hello"; replace "smello"; }
-badword channel { word "house"; replace "flat"; }
-badword channel { word "gaming"; replace "gaymen"; }
-badword channel { word "im"; replace "m"; }
-badword channel { word "i'm"; replace "m"; }
-badword channel { word "i am"; replace "m"; }
-badword channel { word "ima"; replace "m"; }
-badword channel { word "my"; replace "me"; }
-badword channel { word "(nigger)"; replace "angel"; }
-badword channel { word "np"; replace "mp"; }
-badword channel { word "on"; replace "pon"; }
-badword channel { word "same"; replace "salami"; }
-badword channel { word "(skyp)"; replace "skik"; }
-badword channel { word "(ss)"; replace "ϟϟ"; }
-badword channel { word "(troll)"; replace "papillion"; }
-badword channel { word "uber"; replace "HELLS ANGELS"; }
-badword channel { word "(year)"; replace "yonk"; }
+badword channel { word "apartment"; replace "flat"; }
+badword channel { word "banana"; replace "bogoya"; }
+badword channel { word "bitch"; replace "wombat"; }
+badword channel { word "bro"; replace "bo"; }
+badword channel { word "(brother)"; replace "bredda"; }
+badword channel { word "bruh"; replace "bredda"; }
+badword channel { word "car"; replace "taxi"; }
+badword channel { word "cool"; replace "safe"; }
+badword channel { word "drunk"; replace "buck"; }
+badword channel { word "dude"; replace "blud"; }
+badword channel { word "discord"; replace "dicksword"; }
+badword channel { word "elaborate"; replace "ebloggerate"; }
+badword channel { word "efnet"; replace "efrael"; }
+badword channel { word "fuckin"; replace "blood clot"; }
+badword channel { word "fucking"; replace "blood clot"; }
+badword channel { word "fuckn"; replace "blood clot"; }
+badword channel { word "hate"; replace "04 hate "; }
+badword channel { word "hello"; replace "smello"; }
+badword channel { word "high"; replace "HIE"; }
+badword channel { word "home"; replace "flat"; }
+badword channel { word "house"; replace "flat"; }
+badword channel { word "gaming"; replace "gaymen"; }
+badword channel { word "im"; replace "m"; }
+badword channel { word "i'm"; replace "m"; }
+badword channel { word "i am"; replace "m"; }
+badword channel { word "ima"; replace "m"; }
+badword channel { word "jfc"; replace "bloody hell"; }
+badword channel { word "my"; replace "me"; }
+badword channel { word "nice"; replace "safe"; }
+badword channel { word "(nigger)"; replace "angel"; }
+badword channel { word "np"; replace "mp"; }
+badword channel { word "on"; replace "pon"; }
+badword channel { word "same"; replace "salami"; }
+badword channel { word "shitfaced"; replace "buck"; }
+badword channel { word "shit faced"; replace "buck"; }
+badword channel { word "shoes"; replace "kicks"; }
+badword channel { word "(skyp)"; replace "skik"; }
+badword channel { word "(ss)"; replace "ϟϟ"; }
+badword channel { word "(troll)"; replace "papillion"; }
+badword channel { word "uber"; replace "HELLS ANGELS"; }
+badword channel { word "(year)"; replace "yonk"; }
badword channel { word "sup"; replace "wah gwaan"; }
badword channel { word "wussup"; replace "wah gwaan"; }
@@ -33,15 +50,18 @@ badword channel { word "what's up"; replace "wah gwaan"; }
badword channel { word "wuddup"; replace "wah gwaan"; }
badword channel { word "gal"; replace "bint"; }
+badword channel { word "gf"; replace "bint"; }
badword channel { word "(girl)"; replace "bint"; }
badword channel { word "lady"; replace "bint"; }
badword channel { word "ladies"; replace "bints"; }
badword channel { word "(woman)"; replace "bint"; }
+badword channel { word "wife"; replace "bint"; }
badword channel { word "women"; replace "bints"; }
badword channel { word "ganja"; replace "bobby brown"; }
badword channel { word "marijuana"; replace "bobby brown"; }
badword channel { word "pot"; replace "bobby brown"; }
+badword channel { word "reefer"; replace "bobby brown"; }
badword channel { word "weed"; replace "bobby brown"; }
badword channel { word "kek"; replace "%%"; }
diff --git a/doc/conf/except.conf b/doc/conf/except.conf
index 5f6c0f6..18fa552 100644
--- a/doc/conf/except.conf
+++ b/doc/conf/except.conf
@@ -1,28 +1,34 @@
# IRCCloud
-except ban { mask *@5.254.36.56/29; }
-except ban { mask *@192.184.9.108/32; }
-except ban { mask *@192.184.9.112/32; }
-except ban { mask *@192.184.10.118/32; }
-except ban { mask *@192.184.10.9/32; }
-except ban { mask *@192.184.8.103/32; }
-except ban { mask *@2001:67c:2f08::/48; }
-except ban { mask *@2a03:5180:f::/62; }
-except ban { mask *@2a03:5180:f:4::/63; }
-except ban { mask *@2a03:5180:f:6::/64; }
+except ban {
+ mask *@5.254.36.56/29;
+ mask *@192.184.9.108/32;
+ mask *@192.184.9.112/32;
+ mask *@192.184.10.118/32;
+ mask *@192.184.10.9/32;
+ mask *@192.184.8.103/32;
+ mask *@2001:67c:2f08::/48;
+ mask *@2a03:5180:f::/62;
+ mask *@2a03:5180:f:4::/63;
+ mask *@2a03:5180:f:6::/64;
+}
# KiwiIRC
-except ban { mask *@107.161.19.53; }
-except ban { mask *@107.161.19.109; }
-except ban { mask *@109.169.31.4; }
-except ban { mask *@109.169.31.13; } # KiwiIRC Verify Bot (out.kiwiirc.com)
+except ban {
+ mask *@107.161.19.53;
+ mask *@107.161.19.109;
+ mask *@109.169.31.4;
+ mask *@109.169.31.13; # KiwiIRC Verify Bot (out.kiwiirc.com)
+}
# Mibbit
-except ban { mask *@207.192.75.252; } # ircip1.mibbit.com
-except ban { mask *@64.62.228.82; } # ircip2.mibbit.com
-except ban { mask *@78.129.202.38; } # ircip3.mibbit.com
-except ban { mask *@109.169.29.95; } # ircip4.mibbit.com
-except ban { mask *@97.107.138.109; } # bot.search.mibbit.com
-except ban { mask *@2600:3c03::f03c:91ff:fe96:c1fa; } # bot.search.mibbit.com
+except ban {
+ mask *@207.192.75.252; # ircip1.mibbit.com
+ mask *@64.62.228.82; # ircip2.mibbit.com
+ mask *@78.129.202.38; # ircip3.mibbit.com
+ mask *@109.169.29.95; # ircip4.mibbit.com
+ mask *@97.107.138.109; # bot.search.mibbit.com
+ mask *@2600:3c03::f03c:91ff:fe96:c1fa; # bot.search.mibbit.com
+}
# Netsplit
-except ban { mask *@85.25.10.40; } # anaconda.netsplit.de
\ No newline at end of file
+except ban { mask *@85.25.10.40; } # anaconda.netsplit.de
\ No newline at end of file
diff --git a/doc/conf/modules.conf b/doc/conf/modules.conf
index f1831d2..9cbe21b 100644
--- a/doc/conf/modules.conf
+++ b/doc/conf/modules.conf
@@ -1,5 +1,5 @@
// Cloaking (+x)
-loadmodule "cloak";
+loadmodule "cloak_sha256";
// User Commands (Minimal)
#loadmodule "admin";
@@ -63,6 +63,7 @@ loadmodule "kill";
#loadmodule "locops";
loadmodule "mkpasswd";
loadmodule "oper";
+loadmodule "operinfo";
#loadmodule "opermotd";
loadmodule "sajoin";
loadmodule "samode";
@@ -76,7 +77,6 @@ loadmodule "tkl";
loadmodule "trace";
loadmodule "tsctl";
loadmodule "unsqline";
-#loadmodule "wallops";
// Server-2-Server Commands
loadmodule "eos";
@@ -86,9 +86,11 @@ loadmodule "netinfo";
loadmodule "server";
loadmodule "sinfo";
loadmodule "sjoin";
+loadmodule "slog";
loadmodule "sqline";
loadmodule "swhois";
loadmodule "umode2";
+loadmodule "unreal_server_compat";
// Services Commands
loadmodule "sendsno";
@@ -108,25 +110,39 @@ loadmodule "svssno";
loadmodule "svswatch";
// Channel Modes
-loadmodule "chanmodes/censor"; /* +G */
-loadmodule "chanmodes/delayjoin"; /* +D */
-loadmodule "chanmodes/floodprot"; /* +f */
-loadmodule "chanmodes/history"; /* +H */
-loadmodule "chanmodes/issecure"; /* +Z */
-loadmodule "chanmodes/link"; /* +L */
-loadmodule "chanmodes/nocolor"; /* +c */
-loadmodule "chanmodes/noctcp"; /* +C */
-loadmodule "chanmodes/noinvite"; /* +V */
-loadmodule "chanmodes/nokick"; /* +Q */
-loadmodule "chanmodes/noknock"; /* +K */
-loadmodule "chanmodes/nonickchange"; /* +N */
-loadmodule "chanmodes/nonotice"; /* +T */
-loadmodule "chanmodes/operonly"; /* +O */
-loadmodule "chanmodes/permanent"; /* +P */
-loadmodule "chanmodes/regonly"; /* +R */
-loadmodule "chanmodes/regonlyspeak"; /* +M */
-loadmodule "chanmodes/secureonly"; /* +z */
-loadmodule "chanmodes/stripcolor"; /* +S */
+loadmodule "chanmodes/chanowner"; /* +q */
+loadmodule "chanmodes/chanadmin"; /* +a */
+loadmodule "chanmodes/chanop"; /* +o */
+loadmodule "chanmodes/halfop"; /* +h */
+loadmodule "chanmodes/voice"; /* +v */
+loadmodule "chanmodes/censor"; /* +G */
+loadmodule "chanmodes/delayjoin"; /* +D */
+loadmodule "chanmodes/floodprot"; /* +f */
+loadmodule "chanmodes/history"; /* +H */
+loadmodule "chanmodes/inviteonly"; /* +i */
+loadmodule "chanmodes/isregistered"; /* +r */
+loadmodule "chanmodes/issecure"; /* +Z */
+loadmodule "chanmodes/key"; /* +k */
+loadmodule "chanmodes/limit"; /* +l */
+loadmodule "chanmodes/link"; /* +L */
+loadmodule "chanmodes/moderated"; /* +m */
+loadmodule "chanmodes/nocolor"; /* +c */
+loadmodule "chanmodes/noctcp"; /* +C */
+loadmodule "chanmodes/noexternalmsgs"; /* +n */
+loadmodule "chanmodes/noinvite"; /* +V */
+loadmodule "chanmodes/nokick"; /* +Q */
+loadmodule "chanmodes/noknock"; /* +K */
+loadmodule "chanmodes/nonickchange"; /* +N */
+loadmodule "chanmodes/nonotice"; /* +T */
+loadmodule "chanmodes/operonly"; /* +O */
+loadmodule "chanmodes/permanent"; /* +P */
+loadmodule "chanmodes/private"; /* +p */
+loadmodule "chanmodes/regonly"; /* +R */
+loadmodule "chanmodes/regonlyspeak"; /* +M */
+loadmodule "chanmodes/secret"; /* +s */
+loadmodule "chanmodes/secureonly"; /* +z */
+loadmodule "chanmodes/stripcolor"; /* +S */
+loadmodule "chanmodes/topiclimit"; /* +t */
// User Modes
loadmodule "usermodes/bot"; /* +B */
@@ -139,24 +155,23 @@ loadmodule "usermodes/regonlymsg"; /* +R */
loadmodule "usermodes/secureonlymsg"; /* +Z */
loadmodule "usermodes/servicebot"; /* +S */
#loadmodule "usermodes/showwhois"; /* +W */
-
-// Snomasks
-#loadmodule "snomasks/dccreject"; /* +D */
+#loadmodule "usermodes/wallops"; /* +w */
// Extended Bans
-loadmodule "extbans/account"; /* +b ~a */
-#loadmodule "extbans/certfp"; /* +b ~S */
-#loadmodule "extbans/inchannel"; /* +b ~c */
-loadmodule "extbans/join"; /* +b ~j */
-loadmodule "extbans/msgbypass"; /* +e ~m */
-#loadmodule "extbans/nickchange"; /* +b ~n */
-#loadmodule "extbans/operclass"; /* +b ~O */
-#loadmodule "extbans/partmsg"; /* +b ~p */
-loadmodule "extbans/quiet"; /* +b ~q */
-#loadmodule "extbans/realname"; /* +b ~r */
-#loadmodule "extbans/textban"; /* +b ~T */
-loadmodule "extbans/timedban"; /* +b ~t */
-loadmodule "extbans/securitygroup"; /* +b ~G */
+loadmodule "extbans/account"; /* +b ~account */
+loadmodule "extbans/certfp"; /* +b ~certfp */
+#loadmodule "extbans/country"; /* +b ~country */
+loadmodule "extbans/inchannel"; /* +b ~channel */
+loadmodule "extbans/join"; /* +b ~join */
+loadmodule "extbans/msgbypass"; /* +e ~msgbypass */
+#loadmodule "extbans/nickchange"; /* +b ~nickchange */
+#loadmodule "extbans/operclass"; /* +b ~operclass */
+#loadmodule "extbans/partmsg"; /* +b ~partmsg */
+loadmodule "extbans/quiet"; /* +b ~quiet */
+#loadmodule "extbans/realname"; /* +b ~realname */
+loadmodule "extbans/textban"; /* +b ~text */
+loadmodule "extbans/timedban"; /* +b ~time */
+loadmodule "extbans/securitygroup"; /* +b ~security-group */
// IRCv3 Extensions
loadmodule "account-notify";
@@ -166,10 +181,12 @@ loadmodule "bot-tag";
loadmodule "chathistory";
loadmodule "clienttagdeny";
loadmodule "echo-message";
+loadmodule "extended-monitor";
loadmodule "labeled-response";
loadmodule "link-security";
loadmodule "message-ids";
loadmodule "message-tags";
+loadmodule "monitor";
loadmodule "plaintext-policy";
loadmodule "reply-tag";
loadmodule "server-time";
@@ -178,24 +195,29 @@ loadmodule "typing-indicator";
// Other
loadmodule "antimixedutf8";
-loadmodule "authprompt";
+#loadmodule "authprompt";
loadmodule "blacklist";
loadmodule "certfp";
loadmodule "channeldb";
loadmodule "charsys";
loadmodule "connthrottle";
+#loadmodule "geoip_base";
+#loadmodule "geoip_classic";
loadmodule "hideserver";
loadmodule "history_backend_mem";
#loadmodule "history_backend_null";
loadmodule "ident_lookup";
loadmodule "jointhrottle";
+loadmodule "json-log-tag";
loadmodule "targetfloodprot";
loadmodule "tkldb";
loadmodule "tls_antidos";
+loadmodule "tls_cipher";
loadmodule "userhost-tag";
loadmodule "userip-tag";
loadmodule "reputation";
loadmodule "restrict-commands";
loadmodule "rmtkl";
+loadmodule "watch-backend";
#loadmodule "webirc";
#loadmodule "websocket";
\ No newline at end of file
diff --git a/doc/conf/snomasks.conf b/doc/conf/snomasks.conf
new file mode 100644
index 0000000..5872ccc
--- /dev/null
+++ b/doc/conf/snomasks.conf
@@ -0,0 +1,228 @@
+/* Server bans snomask - 'b' */
+log {
+ source {
+ tkl.BAN_REALNAME;
+ 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;
+ }
+}
+
+/* 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.
+ */
+ 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' */
+ 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;
+ }
+}
diff --git a/doc/conf/tls/curl-ca-bundle.crt b/doc/conf/tls/curl-ca-bundle.crt
index 3c79c59..0bf312f 100644
--- a/doc/conf/tls/curl-ca-bundle.crt
+++ b/doc/conf/tls/curl-ca-bundle.crt
@@ -1,7 +1,7 @@
##
## Bundle of CA Root Certificates
##
-## Certificate data from Mozilla as of: Tue Jan 19 04:12:04 2021 GMT
+## Certificate data from Mozilla as of: Tue Oct 26 03:12:05 2021 GMT
##
## This is a bundle of X.509 certificates of public Certificate Authorities
## (CA). These were automatically extracted from Mozilla's root certificates
@@ -14,7 +14,7 @@
## Just configure this file as the SSLCACertificateFile.
##
## Conversion done with mk-ca-bundle.pl version 1.28.
-## SHA256: 3bdc63d1de27058fec943a999a2a8a01fcc6806a611b19221a7727d3d9bbbdfd
+## SHA256: bb36818a81feaa4cca61101e6d6276cd09e972efcb08112dfed846918ca41d7f
##
@@ -156,38 +156,6 @@ Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
-----END CERTIFICATE-----
-QuoVadis Root CA
-================
------BEGIN CERTIFICATE-----
-MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE
-ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
-eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz
-MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp
-cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD
-EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
-AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk
-J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL
-F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL
-YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen
-AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w
-PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y
-ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7
-MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj
-YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs
-ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
-Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW
-Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu
-BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw
-FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0
-aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6
-tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo
-fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul
-LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x
-gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi
-5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi
-5nrQNiOKSnQ2+Q==
------END CERTIFICATE-----
-
QuoVadis Root CA 2
==================
-----BEGIN CERTIFICATE-----
@@ -275,26 +243,6 @@ s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ
FL39vmwLAw==
-----END CERTIFICATE-----
-Sonera Class 2 Root CA
-======================
------BEGIN CERTIFICATE-----
-MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG
-U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw
-NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh
-IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3
-/Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT
-dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG
-f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P
-tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH
-nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT
-XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt
-0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI
-cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph
-Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx
-EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH
-llpwrN9M
------END CERTIFICATE-----
-
XRamp Global CA Root
====================
-----BEGIN CERTIFICATE-----
@@ -433,26 +381,6 @@ mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
-----END CERTIFICATE-----
-DST Root CA X3
-==============
------BEGIN CERTIFICATE-----
-MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK
-ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X
-DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1
-cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD
-ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT
-rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9
-UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy
-xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d
-utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T
-AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ
-MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug
-dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE
-GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw
-RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS
-fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
------END CERTIFICATE-----
-
SwissSign Gold CA - G2
======================
-----BEGIN CERTIFICATE-----
@@ -718,51 +646,6 @@ vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
-----END CERTIFICATE-----
-GeoTrust Primary Certification Authority - G2
-=============================================
------BEGIN CERTIFICATE-----
-MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC
-VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu
-Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD
-ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1
-OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
-MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl
-b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG
-BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc
-KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD
-VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+
-EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m
-ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2
-npaqBA+K
------END CERTIFICATE-----
-
-VeriSign Universal Root Certification Authority
-===============================================
------BEGIN CERTIFICATE-----
-MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE
-BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
-ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
-IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u
-IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV
-UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
-cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
-IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0
-aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj
-1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP
-MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72
-9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I
-AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR
-tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G
-CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O
-a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
-DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3
-Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx
-Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx
-P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P
-wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4
-mJO37M2CYfE45k+XmCpajQ==
------END CERTIFICATE-----
-
NetLock Arany (Class Gold) Főtanúsítvány
========================================
-----BEGIN CERTIFICATE-----
@@ -938,82 +821,6 @@ Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
-----END CERTIFICATE-----
-Chambers of Commerce Root - 2008
-================================
------BEGIN CERTIFICATE-----
-MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD
-MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
-bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
-QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy
-Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl
-ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF
-EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl
-cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
-AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA
-XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj
-h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/
-ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk
-NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g
-D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331
-lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ
-0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
-ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2
-EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI
-G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ
-BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh
-bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh
-bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC
-CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH
-AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1
-wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH
-3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU
-RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6
-M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1
-YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF
-9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK
-zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG
-nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
-OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ
------END CERTIFICATE-----
-
-Global Chambersign Root - 2008
-==============================
------BEGIN CERTIFICATE-----
-MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD
-MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
-bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
-QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx
-NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg
-Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ
-QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
-aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf
-VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf
-XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0
-ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB
-/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA
-TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M
-H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe
-Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF
-HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
-wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB
-AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT
-BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE
-BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm
-aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm
-aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp
-1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0
-dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG
-/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6
-ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s
-dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg
-9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH
-foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du
-qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr
-P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq
-c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
-09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
------END CERTIFICATE-----
-
Go Daddy Root Certificate Authority - G2
========================================
-----BEGIN CERTIFICATE-----
@@ -1315,27 +1122,6 @@ OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9
vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
-----END CERTIFICATE-----
-Trustis FPS Root CA
-===================
------BEGIN CERTIFICATE-----
-MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG
-EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290
-IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV
-BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ
-KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ
-RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk
-H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa
-cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt
-o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA
-AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd
-BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c
-GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC
-yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P
-8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV
-l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl
-iB6XzCGcKQENZetX2fNXlrtIzYE=
------END CERTIFICATE-----
-
Buypass Class 2 Root CA
=======================
-----BEGIN CERTIFICATE-----
@@ -1980,36 +1766,6 @@ uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7
yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3
-----END CERTIFICATE-----
-Staat der Nederlanden Root CA - G3
-==================================
------BEGIN CERTIFICATE-----
-MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
-CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
-Um9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloXDTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMC
-TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
-ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4y
-olQPcPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WWIkYFsO2t
-x1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqXxz8ecAgwoNzFs21v0IJy
-EavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFyKJLZWyNtZrVtB0LrpjPOktvA9mxjeM3K
-Tj215VKb8b475lRgsGYeCasH/lSJEULR9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUur
-mkVLoR9BvUhTFXFkC4az5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU5
-1nus6+N86U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7Ngzp
-07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHPbMk7ccHViLVlvMDo
-FxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXtBznaqB16nzaeErAMZRKQFWDZJkBE
-41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTtXUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMB
-AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleu
-yjWcLhL75LpdINyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD
-U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwpLiniyMMB8jPq
-KqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8Ipf3YF3qKS9Ysr1YvY2WTxB1
-v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixpgZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA
-8KCWAg8zxXHzniN9lLf9OtMJgwYh/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b
-8KKaa8MFSu1BYBQw0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0r
-mj1AfsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq4BZ+Extq
-1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR1VmiiXTTn74eS9fGbbeI
-JG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/QFH1T/U67cjF68IeHRaVesd+QnGTbksV
-tzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM94B7IWcnMFk=
------END CERTIFICATE-----
-
Staat der Nederlanden EV Root CA
================================
-----BEGIN CERTIFICATE-----
@@ -3226,3 +2982,251 @@ qqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oG
I/hGoiLtk/bdmuYqh7GYVPEi92tF4+KOdh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmg
kpzNNIaRkPpkUZ3+/uul9XXeifdy
-----END CERTIFICATE-----
+
+AC RAIZ FNMT-RCM SERVIDORES SEGUROS
+===================================
+-----BEGIN CERTIFICATE-----
+MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQswCQYDVQQGEwJF
+UzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgwFgYDVQRhDA9WQVRFUy1RMjgy
+NjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1SQ00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4
+MTIyMDA5MzczM1oXDTQzMTIyMDA5MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQt
+UkNNMQ4wDAYDVQQLDAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNB
+QyBSQUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuBBAAiA2IA
+BPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LHsbI6GA60XYyzZl2hNPk2
+LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oKUm8BA06Oi6NCMEAwDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqG
+SM49BAMDA2kAMGYCMQCuSuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoD
+zBOQn5ICMQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJyv+c=
+-----END CERTIFICATE-----
+
+GlobalSign Root R46
+===================
+-----BEGIN CERTIFICATE-----
+MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUAMEYxCzAJBgNV
+BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJv
+b3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAX
+BgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08Es
+CVeJOaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQGvGIFAha/
+r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud316HCkD7rRlr+/fKYIje
+2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo0q3v84RLHIf8E6M6cqJaESvWJ3En7YEt
+bWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSEy132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvj
+K8Cd+RTyG/FWaha/LIWFzXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD4
+12lPFzYE+cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCNI/on
+ccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzsx2sZy/N78CsHpdls
+eVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqaByFrgY/bxFn63iLABJzjqls2k+g9
+vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYD
+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEM
+BQADggIBAHx47PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg
+JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti2kM3S+LGteWy
+gxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIkpnnpHs6i58FZFZ8d4kuaPp92
+CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRFFRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZm
+OUdkLG5NrmJ7v2B0GbhWrJKsFjLtrWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qq
+JZ4d16GLuc1CLgSkZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwye
+qiv5u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP4vkYxboz
+nxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6N3ec592kD3ZDZopD8p/7
+DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3vouXsXgxT7PntgMTzlSdriVZzH81Xwj3
+QEUxeCp6
+-----END CERTIFICATE-----
+
+GlobalSign Root E46
+===================
+-----BEGIN CERTIFICATE-----
+MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYxCzAJBgNVBAYT
+AkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJvb3Qg
+RTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNV
+BAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcq
+hkjOPQIBBgUrgQQAIgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkB
+jtjqR+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGddyXqBPCCj
+QjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQxCpCPtsad0kRL
+gLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZk
+vLtoURMMA/cVi4RguYv/Uo7njLwcAjA8+RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+
+CAezNIm8BZ/3Hobui3A=
+-----END CERTIFICATE-----
+
+GLOBALTRUST 2020
+================
+-----BEGIN CERTIFICATE-----
+MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkGA1UEBhMCQVQx
+IzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVT
+VCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYxMDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAh
+BgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAy
+MDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWi
+D59bRatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9ZYybNpyrO
+VPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3QWPKzv9pj2gOlTblzLmM
+CcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPwyJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCm
+fecqQjuCgGOlYx8ZzHyyZqjC0203b+J+BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKA
+A1GqtH6qRNdDYfOiaxaJSaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9OR
+JitHHmkHr96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj04KlG
+DfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9MedKZssCz3AwyIDMvU
+clOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIwq7ejMZdnrY8XD2zHc+0klGvIg5rQ
+mjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1Ud
+IwQYMBaAFNwuH9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA
+VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJCXtzoRlgHNQIw
+4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd6IwPS3BD0IL/qMy/pJTAvoe9
+iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf+I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS
+8cE54+X1+NZK3TTN+2/BT+MAi1bikvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2
+HcqtbepBEX4tdJP7wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxS
+vTOBTI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6CMUO+1918
+oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn4rnvyOL2NSl6dPrFf4IF
+YqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+IaFvowdlxfv1k7/9nR4hYJS8+hge9+6jl
+gqispdNpQ80xiEmEU5LAsTkbOYMBMMTyqfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg==
+-----END CERTIFICATE-----
+
+ANF Secure Server Root CA
+=========================
+-----BEGIN CERTIFICATE-----
+MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNVBAUTCUc2MzI4
+NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lv
+bjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNVBAMTGUFORiBTZWN1cmUgU2VydmVyIFJvb3Qg
+Q0EwHhcNMTkwOTA0MTAwMDM4WhcNMzkwODMwMTAwMDM4WjCBhDESMBAGA1UEBRMJRzYzMjg3NTEw
+MQswCQYDVQQGEwJFUzEnMCUGA1UEChMeQU5GIEF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uMRQw
+EgYDVQQLEwtBTkYgQ0EgUmFpejEiMCAGA1UEAxMZQU5GIFNlY3VyZSBTZXJ2ZXIgUm9vdCBDQTCC
+AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvrayvmZFSVgpCjcqQZAZ2cC4Ffc0m6p6zz
+BE57lgvsEeBbphzOG9INgxwruJ4dfkUyYA8H6XdYfp9qyGFOtibBTI3/TO80sh9l2Ll49a2pcbnv
+T1gdpd50IJeh7WhM3pIXS7yr/2WanvtH2Vdy8wmhrnZEE26cLUQ5vPnHO6RYPUG9tMJJo8gN0pcv
+B2VSAKduyK9o7PQUlrZXH1bDOZ8rbeTzPvY1ZNoMHKGESy9LS+IsJJ1tk0DrtSOOMspvRdOoiXse
+zx76W0OLzc2oD2rKDF65nkeP8Nm2CgtYZRczuSPkdxl9y0oukntPLxB3sY0vaJxizOBQ+OyRp1RM
+VwnVdmPF6GUe7m1qzwmd+nxPrWAI/VaZDxUse6mAq4xhj0oHdkLePfTdsiQzW7i1o0TJrH93PB0j
+7IKppuLIBkwC/qxcmZkLLxCKpvR/1Yd0DVlJRfbwcVw5Kda/SiOL9V8BY9KHcyi1Swr1+KuCLH5z
+JTIdC2MKF4EA/7Z2Xue0sUDKIbvVgFHlSFJnLNJhiQcND85Cd8BEc5xEUKDbEAotlRyBr+Qc5RQe
+8TZBAQIvfXOn3kLMTOmJDVb3n5HUA8ZsyY/b2BzgQJhdZpmYgG4t/wHFzstGH6wCxkPmrqKEPMVO
+Hj1tyRRM4y5Bu8o5vzY8KhmqQYdOpc5LMnndkEl/AgMBAAGjYzBhMB8GA1UdIwQYMBaAFJxf0Gxj
+o1+TypOYCK2Mh6UsXME3MB0GA1UdDgQWBBScX9BsY6Nfk8qTmAitjIelLFzBNzAOBgNVHQ8BAf8E
+BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEATh65isagmD9uw2nAalxJ
+UqzLK114OMHVVISfk/CHGT0sZonrDUL8zPB1hT+L9IBdeeUXZ701guLyPI59WzbLWoAAKfLOKyzx
+j6ptBZNscsdW699QIyjlRRA96Gejrw5VD5AJYu9LWaL2U/HANeQvwSS9eS9OICI7/RogsKQOLHDt
+dD+4E5UGUcjohybKpFtqFiGS3XNgnhAY3jyB6ugYw3yJ8otQPr0R4hUDqDZ9MwFsSBXXiJCZBMXM
+5gf0vPSQ7RPi6ovDj6MzD8EpTBNO2hVWcXNyglD2mjN8orGoGjR0ZVzO0eurU+AagNjqOknkJjCb
+5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ/zo1PqVUSlJZS2Db7v54
+EX9K3BR5YLZrZAPbFYPhor72I5dQ8AkzNqdxliXzuUJ92zg/LFis6ELhDtjTO0wugumDLmsx2d1H
+hk9tl5EuT+IocTUW0fJz/iUrB0ckYyfI+PbZa/wSMVYIwFNCr5zQM378BvAxRAMU8Vjq8moNqRGy
+g77FGr8H6lnco4g175x2MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3
+r5+qPeoott7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw=
+-----END CERTIFICATE-----
+
+Certum EC-384 CA
+================
+-----BEGIN CERTIFICATE-----
+MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQswCQYDVQQGEwJQ
+TDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2
+MDcyNDU0WhcNNDMwMzI2MDcyNDU0WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERh
+dGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx
+GTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATEKI6rGFtq
+vm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7TmFy8as10CW4kjPMIRBSqn
+iBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68KjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
+VR0OBBYEFI0GZnQkdjrzife81r1HfS+8EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNo
+ADBlAjADVS2m5hjEfO/JUG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0
+QoSZ/6vnnvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k=
+-----END CERTIFICATE-----
+
+Certum Trusted Root CA
+======================
+-----BEGIN CERTIFICATE-----
+MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6MQswCQYDVQQG
+EwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0g
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0Ew
+HhcNMTgwMzE2MTIxMDEzWhcNNDMwMzE2MTIxMDEzWjB6MQswCQYDVQQGEwJQTDEhMB8GA1UEChMY
+QXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQDRLY67tzbqbTeRn06TpwXkKQMlzhyC93yZn0EGze2jusDbCSzBfN8p
+fktlL5On1AFrAygYo9idBcEq2EXxkd7fO9CAAozPOA/qp1x4EaTByIVcJdPTsuclzxFUl6s1wB52
+HO8AU5853BSlLCIls3Jy/I2z5T4IHhQqNwuIPMqw9MjCoa68wb4pZ1Xi/K1ZXP69VyywkI3C7Te2
+fJmItdUDmj0VDT06qKhF8JVOJVkdzZhpu9PMMsmN74H+rX2Ju7pgE8pllWeg8xn2A1bUatMn4qGt
+g/BKEiJ3HAVz4hlxQsDsdUaakFjgao4rpUYwBI4Zshfjvqm6f1bxJAPXsiEodg42MEx51UGamqi4
+NboMOvJEGyCI98Ul1z3G4z5D3Yf+xOr1Uz5MZf87Sst4WmsXXw3Hw09Omiqi7VdNIuJGmj8PkTQk
+fVXjjJU30xrwCSss0smNtA0Aq2cpKNgB9RkEth2+dv5yXMSFytKAQd8FqKPVhJBPC/PgP5sZ0jeJ
+P/J7UhyM9uH3PAeXjA6iWYEMspA90+NZRu0PqafegGtaqge2Gcu8V/OXIXoMsSt0Puvap2ctTMSY
+njYJdmZm/Bo/6khUHL4wvYBQv3y1zgD2DGHZ5yQD4OMBgQ692IU0iL2yNqh7XAjlRICMb/gv1SHK
+HRzQ+8S1h9E6Tsd2tTVItQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSM+xx1
+vALTn04uSNn5YFSqxLNP+jAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQADggIBAEii1QAL
+LtA/vBzVtVRJHlpr9OTy4EA34MwUe7nJ+jW1dReTagVphZzNTxl4WxmB82M+w85bj/UvXgF2Ez8s
+ALnNllI5SW0ETsXpD4YN4fqzX4IS8TrOZgYkNCvozMrnadyHncI013nR03e4qllY/p0m+jiGPp2K
+h2RX5Rc64vmNueMzeMGQ2Ljdt4NR5MTMI9UGfOZR0800McD2RrsLrfw9EAUqO0qRJe6M1ISHgCq8
+CYyqOhNf6DR5UMEQGfnTKB7U0VEwKbOukGfWHwpjscWpxkIxYxeU72nLL/qMFH3EQxiJ2fAyQOaA
+4kZf5ePBAFmo+eggvIksDkc0C+pXwlM2/KfUrzHN/gLldfq5Jwn58/U7yn2fqSLLiMmq0Uc9Nneo
+WWRrJ8/vJ8HjJLWG965+Mk2weWjROeiQWMODvA8s1pfrzgzhIMfatz7DP78v3DSk+yshzWePS/Tj
+6tQ/50+6uaWTRRxmHyH6ZF5v4HaUMst19W7l9o/HuKTMqJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmT
+OPQD8rv7gmsHINFSH5pkAnuYZttcTVoP0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZck
+bxJF0WddCajJFdr60qZfE2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb
+-----END CERTIFICATE-----
+
+TunTrust Root CA
+================
+-----BEGIN CERTIFICATE-----
+MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQELBQAwYTELMAkG
+A1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUgQ2VydGlmaWNhdGlvbiBFbGVj
+dHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJvb3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQw
+NDI2MDg1NzU2WjBhMQswCQYDVQQGEwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBD
+ZXJ0aWZpY2F0aW9uIEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIw
+DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZn56eY+hz
+2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd2JQDoOw05TDENX37Jk0b
+bjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgFVwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7
+NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZGoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAd
+gjH8KcwAWJeRTIAAHDOFli/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViW
+VSHbhlnUr8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2eY8f
+Tpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIbMlEsPvLfe/ZdeikZ
+juXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISgjwBUFfyRbVinljvrS5YnzWuioYas
+DXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwS
+VXAkPcvCFDVDXSdOvsC9qnyW5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI
+04Y+oXNZtPdEITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0
+90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+zxiD2BkewhpMl
+0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYuQEkHDVneixCwSQXi/5E/S7fd
+Ao74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRY
+YdZ2vyJ/0Adqp2RT8JeNnYA/u8EH22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJp
+adbGNjHh/PqAulxPxOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65x
+xBzndFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5Xc0yGYuP
+jCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7bnV2UqL1g52KAdoGDDIzM
+MEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQCvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9z
+ZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZHu/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3r
+AZ3r2OvEhJn7wAzMMujjd9qDRIueVSjAi1jTkD5OGwDxFa2DK5o=
+-----END CERTIFICATE-----
+
+HARICA TLS RSA Root CA 2021
+===========================
+-----BEGIN CERTIFICATE-----
+MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQG
+EwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u
+cyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0EgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUz
+OFoXDTQ1MDIxMzEwNTUzN1owbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRl
+bWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNB
+IFJvb3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569lmwVnlskN
+JLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE4VGC/6zStGndLuwRo0Xu
+a2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uva9of08WRiFukiZLRgeaMOVig1mlDqa2Y
+Ulhu2wr7a89o+uOkXjpFc5gH6l8Cct4MpbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K
+5FrZx40d/JiZ+yykgmvwKh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEv
+dmn8kN3bLW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcYAuUR
+0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqBAGMUuTNe3QvboEUH
+GjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYqE613TBoYm5EPWNgGVMWX+Ko/IIqm
+haZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHrW2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQ
+CPxrvrNQKlr9qEgYRtaQQJKQCoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8G
+A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE
+AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAUX15QvWiWkKQU
+EapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3f5Z2EMVGpdAgS1D0NTsY9FVq
+QRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxajaH6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxD
+QpSbIPDRzbLrLFPCU3hKTwSUQZqPJzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcR
+j88YxeMn/ibvBZ3PzzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5
+vZStjBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0/L5H9MG0
+qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pTBGIBnfHAT+7hOtSLIBD6
+Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79aPib8qXPMThcFarmlwDB31qlpzmq6YR/
+PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YWxw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnn
+kf3/W9b3raYvAwtt41dU63ZTGI0RmLo=
+-----END CERTIFICATE-----
+
+HARICA TLS ECC Root CA 2021
+===========================
+-----BEGIN CERTIFICATE-----
+MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQswCQYDVQQGEwJH
+UjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBD
+QTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoX
+DTQ1MDIxMzExMDEwOVowbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWlj
+IGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJv
+b3QgQ0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7KKrxcm1l
+AEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9YSTHMmE5gEYd103KUkE+b
+ECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW
+0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAi
+rcJRQO9gcS3ujwLEXQNwSaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/Qw
+CZ61IygNnxS2PFOiTAZpffpskcYqSUXm7LcT4Tps
+-----END CERTIFICATE-----
diff --git a/doc/conf/unrealircd.hub.conf b/doc/conf/unrealircd.hub.conf
index b55d85e..1e11620 100644
--- a/doc/conf/unrealircd.hub.conf
+++ b/doc/conf/unrealircd.hub.conf
@@ -16,9 +16,10 @@ link services.supernets.org {
class servers;
}
-log "ircd.log" { flags { errors; } maxsize 1K; }
-
-except ban { mask *@127.0.0.1; }
+log {
+ source { error; fatal; warn; }
+ destination { file "ircd.log" { maxsize 10M; } }
+}
ulines { services.supernets.org; }
diff --git a/doc/conf/unrealircd.remote.conf b/doc/conf/unrealircd.remote.conf
index 3091611..80b1a05 100644
--- a/doc/conf/unrealircd.remote.conf
+++ b/doc/conf/unrealircd.remote.conf
@@ -14,8 +14,8 @@ alias os { target operserv; type services; }
class clients { pingfreq 120; maxclients 100; sendq 1M; options { nofakelag; } }
class servers { pingfreq 120; maxclients 10; sendq 1M; connfreq 30; }
-allow { ip *; class clients; maxperip 2; global-maxperip 2; }
-allow { ip 127.0.0.1; class clients; maxperip 10; global-maxperip 10; }
+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 *@*;
@@ -26,9 +26,10 @@ listen { ip *; port 6667; options { clientsonly; } }
listen { ip *; port 6697; options { clientsonly; tls; } }
listen { ip *; port REDACTED; options { serversonly; tls; } }
-deny channel { channel "#pumpcoin"; reason "This channel has moved to #exchange"; redirect "#exchange"; }
deny channel { channel "#dev"; reason "This channel has moved to #superbowl"; redirect "#superbowl"; }
deny channel { channel "#help"; reason "This channel has moved to #superbowl"; redirect "#superbowl"; }
+deny channel { channel "#mensa"; reason "This channel has been closed"; redirect "#superbowl"; }
+deny channel { channel "#pumpcoin"; reason "This channel has moved to #exchange"; redirect "#exchange"; }
link irc.supernets.org {
incoming { mask REDACTED; }
@@ -42,7 +43,15 @@ link irc.supernets.org {
class servers;
}
-log "errors.log" { flags { errors; } maxsize 10K; }
+log {
+ source { error; fatal; warn; }
+ destination { file "ircd.log" { maxsize 10M; } }
+}
+
+log {
+ source { all; }
+ destination { channel "#REDACTED" }
+}
tld { mask *@*; motd remote.motd; rules remote.motd; options { remote; } }
@@ -81,39 +90,28 @@ blacklist torbl {
reason "8,4 E N T E R T H E V O I D ";
}
-webirc { mask 107.161.19.53; password "REDACTED"; } # KiwiIRC
-webirc { mask 107.161.19.109; password "REDACTED"; }
-webirc { mask 107.161.31.4; password "REDACTED"; }
-
-webirc { mask 207.192.75.252; password "REDACTED"; } # Mibbit
-webirc { mask 64.62.228.82; password "REDACTED"; }
-webirc { mask 78.129.202.38; password "REDACTED"; }
-webirc { mask 109.169.29.95 ; password "REDACTED"; }
-
set {
kline-address "enterthevoid@supernets.org";
gline-address "enterthevoid@supernets.org";
modes-on-connect "+iIpTx";
modes-on-oper "+Hq";
- snomask-on-oper "+bcFfkGsSo";
+ snomask-on-oper "+bBcCfksSoO";
modes-on-join "+ns";
level-on-join "op";
restrict-usermodes "ips";
restrict-channelmodes "nLpPs";
restrict-commands {
- channel-message { connect-delay 60; exempt-identified yes; exempt-reputation-score 100; }
- channel-notice { connect-delay 60; exempt-identified yes; exempt-reputation-score 100; }
- invite { connect-delay 3600; exempt-identified yes; exempt-reputation-score 100; }
- join { connect-delay 15; exempt-identified yes; exempt-reputation-score 100; }
- list { connect-delay 30; exempt-identified yes; exempt-reputation-score 100; }
- private-message { connect-delay 300; exempt-identified yes; exempt-reputation-score 100; }
- private-notice { connect-delay 3600; exempt-identified yes; exempt-reputation-score 100; }
+ channel-message { connect-delay 60; exempt-identified yes; exempt-reputation-score 100; }
+ channel-notice { connect-delay 60; exempt-identified yes; exempt-reputation-score 100; }
+ invite { connect-delay 300; exempt-identified yes; exempt-reputation-score 100; }
+ join { connect-delay 15; exempt-identified yes; exempt-reputation-score 100; }
+ list { connect-delay 30; exempt-identified yes; exempt-reputation-score 100; }
+ private-message { connect-delay 300; exempt-identified yes; exempt-reputation-score 100; }
+ private-notice { connect-delay 300; exempt-identified yes; exempt-reputation-score 100; }
}
- #auto-join "#superbowl";
- oper-auto-join "#superbowl";
+ auto-join "#superbowl";
static-quit "EMO-QUIT";
static-part "EMO-PART";
- who-limit 100;
nick-length 20;
maxchannelsperuser 10;
channel-command-prefix "`!@$.";
@@ -134,15 +132,15 @@ set {
user warn;
oper deny;
server deny;
- user-message "4WARNING: You are not using a secure (SSL/TLS) connection";
- oper-message "Network operators must connect using SSL/TLS";
+ user-message "4WARNING: You are not on a secure TLS connection";
+ oper-message "Network operators must be on a secure TLS connection";
}
outdated-tls-policy {
user warn;
oper deny;
server deny;
user-message "4WARNING: You are using an outdated SSL/TLS protocol or cipher";
- oper-message "Network operators must connect using an up-to-date SSL/TLS protocol or cipher";
+ oper-message "Network operators must be using an up-to-date SSL/TLS protocol & cipher";
}
anti-flood {
everyone {
@@ -152,14 +150,14 @@ set {
ban-action gzline;
ban-time 1h;
}
- target-flood {
- channel-notice 15:5;
- channel-privmsg 45:5;
- channel-tagmsg 15:5;
- private-notice 10:5;
- private-privmsg 30:5;
- private-tagmsg 10:5;
- }
+ #target-flood {
+ # channel-notice 15:5;
+ # channel-privmsg 45:5;
+ # channel-tagmsg 15:5;
+ # private-notice 10:5;
+ # private-privmsg 30:5;
+ # private-tagmsg 10:5;
+ #}
}
known-users {
away-flood 3:300;
@@ -171,6 +169,8 @@ set {
users 5;
new-user-every 60s;
}
+ lag-penalty 10; # update?
+ lag-penalty-bytes 0;
}
unknown-users {
away-flood 3:300;
@@ -182,6 +182,8 @@ set {
users 3;
new-user-every 60s;
}
+ lag-penalty 1000;
+ lag-penalty-bytes 90;
}
}
default-bantime 30d;
@@ -207,32 +209,50 @@ set {
ban-reason "8,4 E N T E R T H E V O I D ";
}
connthrottle {
- 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; }
+ 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; }
}
history {
channel {
- playback-on-join { lines 100; time 1d; }
+ playback-on-join { lines 1000; time 1d; }
max-storage-per-channel {
- registered { lines 100; time 1d; }
- unregistered { lines 50; time 1h; }
+ registered { lines 1000; time 1d; }
+ unregistered { lines 100; time 1h; }
}
}
}
- hide-idle-time { policy usermode; }
+ 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; }
+ swhois { everyone full; }
+ idle { everyone limited; self full; oper full; }
+ }
}
hideserver {
disable-map yes;
disable-links yes;
- map-deny-message "Denied";
- links-deny-message "Denied";
+ map-deny-message "8,4 E N T E R T H E V O I D ";
+ links-deny-message "8,4 E N T E R T H E V O I D ";
}
security-group known-users {
identified yes;
- webirc no;
- tls no;
- reputation-score 100;
+ reputation-score 25;
}
\ No newline at end of file
diff --git a/doc/translations.txt b/doc/translations.txt
index 800c00a..a89c6d8 100644
--- a/doc/translations.txt
+++ b/doc/translations.txt
@@ -1,6 +1,6 @@
==[ Translations ]===========================================================
-In UnrealIRCd 5 we support the following translations:
+In UnrealIRCd we support the following translations:
* on-line documentation at https://www.unrealircd.org/docs/ (wiki!)
* help.conf
* example.conf
diff --git a/extras/build-tests/nix/build b/extras/build-tests/nix/build
index c589458..caab490 100755
--- a/extras/build-tests/nix/build
+++ b/extras/build-tests/nix/build
@@ -16,7 +16,7 @@ else
export MAKE="make -j4"
fi
-export CPPFLAGS="-DFAKELAG_CONFIGURABLE -DNOREMOVETMP"
+export CPPFLAGS="-DFAKELAG_CONFIGURABLE -DNOREMOVETMP -DRAWCMDLOGGING"
# !! skipped for now: extras/build-tests/nix/select-config $BUILDCONFIG !!
# !! temporary use this:
@@ -27,6 +27,16 @@ if lsb_release -av 2>&1|egrep 'Debian.*jessie'; then
echo "Disabling ASan due to false positives on deb8"
echo 'EXTRAPARA="--enable-werror --disable-asan"' >>config.settings
fi
+if uname -s|grep -i freebsd; then
+ echo "Disabling ASan on FreeBSD due to 100% CPU loop in OpenSSL initialization routine"
+ echo 'EXTRAPARA="--enable-werror --disable-asan"' >>config.settings
+fi
+
+# If SSLDIR is set the environment, this overrides config.settings
+# Used for example in the openssl3 build tests.
+if [ "$SSLDIR" != "" ]; then
+ echo 'SSLDIR="'"$SSLDIR"'"' >>config.settings
+fi
# Read config.settings, this makes a couple of variables available to us.
. ./config.settings
@@ -36,10 +46,10 @@ if [ "$SSLDIR" != "" ]; then
fi
./Config -quick || (tail -n 5000 config.log; exit 1)
$MAKE
-yes ''|make pem
-make
+yes ''|$MAKE pem
+$MAKE || exit 1
./unrealircd module install third/dumpcmds
-make install
+$MAKE install || exit 1
set +x
echo ""
diff --git a/extras/build-tests/nix/configs/default b/extras/build-tests/nix/configs/default
index 3a7c28a..648a3ea 100644
--- a/extras/build-tests/nix/configs/default
+++ b/extras/build-tests/nix/configs/default
@@ -1,3 +1,9 @@
+# These are the settings saved from running './Config'.
+# Note that it is not recommended to edit config.settings by hand!
+# Chances are you misunderstand what a variable does or what the
+# supported values are. You better just re-run the ./Config script
+# and answer appropriately there, to get a correct config.settings
+# file.
#
BASEPATH=$HOME/unrealircd
BINDIR=$HOME/unrealircd/bin
@@ -9,16 +15,16 @@ CACHEDIR=$HOME/unrealircd/cache
DOCDIR=$HOME/unrealircd/doc
TMPDIR=$HOME/unrealircd/tmp
PRIVATELIBDIR=$HOME/unrealircd/lib
-PREFIXAQ="1"
-MAXCONNECTIONS="1024"
+MAXCONNECTIONS_REQUEST="auto"
NICKNAMEHISTORYLENGTH="2000"
+GEOIP="classic"
DEFPERM="0600"
SSLDIR=""
REMOTEINC=""
CURLDIR=""
-SHOWLISTMODES="1"
NOOPEROVERRIDE=""
OPEROVERRIDEVERIFY=""
GENCERTIFICATE="0"
-EXTRAPARA="--enable-werror --enable-asan"
+SANITIZER="asan"
+EXTRAPARA="--enable-werror"
ADVANCED=""
diff --git a/extras/build-tests/nix/run-tests b/extras/build-tests/nix/run-tests
index a25c101..02df361 100755
--- a/extras/build-tests/nix/run-tests
+++ b/extras/build-tests/nix/run-tests
@@ -19,8 +19,13 @@ if [ ! -d ~/cipherscan ]; then
git clone -q https://github.com/mozilla/cipherscan
fi
+if [ "$HOSTNAME" = "deb8" ]; then
+ echo "Not running tests on Debian 8. It's LTS is EOL and trouble with running tests."
+ exit 0
+fi
+
# Install 'unrealircd-tests'
-git clone -q https://github.com/unrealircd/unrealircd-tests.git
+git clone -q --branch unreal60 https://github.com/unrealircd/unrealircd-tests.git unrealircd-tests
cd unrealircd-tests
# FreeBSD has various issues with the tests from us and others,
diff --git a/extras/build-tests/windows/build.bat b/extras/build-tests/windows/build.bat
index 9eee847..6f8ed3c 100644
--- a/extras/build-tests/windows/build.bat
+++ b/extras/build-tests/windows/build.bat
@@ -16,35 +16,44 @@ rem cinst innosetup -y
rem Installing UnrealIRCd dependencies
cd \projects
-mkdir unrealircd-5-libs
-cd unrealircd-5-libs
-curl -fsS -o unrealircd-libraries-5-devel.zip https://www.unrealircd.org/files/dev/win/libs/unrealircd-libraries-5-devel.zip
-unzip unrealircd-libraries-5-devel.zip
-copy dlltool.exe \users\user\worker\unreal5-w10\build /y
+mkdir unrealircd-6-libs
+cd unrealircd-6-libs
+curl -fsS -o unrealircd-libraries-6-devel.zip https://www.unrealircd.org/files/dev/win/libs/unrealircd-libraries-6-devel.zip
+unzip unrealircd-libraries-6-devel.zip
+copy dlltool.exe \users\user\worker\unreal6-w10\build /y
-rem for appveyor: cd \projects\unrealircd
-cd \users\user\worker\unreal5-w10\build
+rem for appveyor, use: cd \projects\unrealircd
+cd \users\user\worker\unreal6-w10\build
+
+rem Install 'unrealircd-tests'
+cd ..
+rd /q/s unrealircd-tests
+git clone -q --branch unreal60 https://github.com/unrealircd/unrealircd-tests.git unrealircd-tests
+if %ERRORLEVEL% NEQ 0 EXIT /B 1
+cd build
rem Now the actual build
-call extras\build-tests\windows\compilecmd\%SHORTNAME%.bat
-
-rem The above command will fail, due to missing symbol file
-rem However the symbol file can only be generated after the above command
-rem So... we create the symbolfile...
+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
+rem - It will fail due to missing symbolfile, which we create here..
nmake -f makefile.windows SYMBOLFILE
-
-rem And we re-run the exact same command:
-call extras\build-tests\windows\compilecmd\%SHORTNAME%.bat
+rem - Then we finalize building UnrealIRCd.exe: should be no error
+call extras\build-tests\windows\compilecmd\%SHORTNAME%.bat UNREALSVC.EXE UnrealIRCd.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
if %ERRORLEVEL% NEQ 0 EXIT /B 1
rem Compile dependencies for unrealircd-tests -- this doesn't belong here though..
-curl -fsS -o src\modules\third\fakereputation.c https://raw.githubusercontent.com/unrealircd/unrealircd-tests/master/serverconfig/unrealircd/modules/fakereputation.c
+copy ..\unrealircd-tests\serverconfig\unrealircd\modules\fakereputation.c src\modules\third /Y
call extras\build-tests\windows\compilecmd\%SHORTNAME%.bat CUSTOMMODULE MODULEFILE=fakereputation
if %ERRORLEVEL% NEQ 0 EXIT /B 1
-rem Convert c:\dev to c:\projects\unrealircd-5-libs
+rem Convert c:\dev to c:\projects\unrealircd-6-libs
rem TODO: should use environment variable in innosetup script?
-sed -i "s/c:\\dev\\unrealircd-5-libs/c:\\projects\\unrealircd-5-libs/gi" src\windows\unrealinst.iss
+sed -i "s/c:\\dev\\unrealircd-6-libs/c:\\projects\\unrealircd-6-libs/gi" src\windows\unrealinst.iss
rem Build installer file
"c:\Program Files (x86)\Inno Setup 5\iscc.exe" /Q- src\windows\unrealinst.iss
@@ -60,7 +69,7 @@ taskkill -im unrealircd.exe -f
sleep 2
rem Just a safety measure so we don't end up testing
rem some old version...
-del "C:\Program Files\UnrealIRCd 5\bin\unrealircd.exe"
+del "C:\Program Files\UnrealIRCd 6\bin\unrealircd.exe"
echo Running installer...
start /WAIT unrealircd-dev-build.exe /VERYSILENT /LOG=setup.log
@@ -70,12 +79,7 @@ rem Upload artifact
rem appveyor PushArtifact unrealircd-dev-build.exe
rem if %ERRORLEVEL% NEQ 0 EXIT /B 1
-rem Install 'unrealircd-tests'
-cd ..
-rd /q/s unrealircd-tests
-git clone https://github.com/unrealircd/unrealircd-tests.git
-if %ERRORLEVEL% NEQ 0 EXIT /B 1
-cd unrealircd-tests
+cd ..\unrealircd-tests
dir
rem All tests except db:
diff --git a/extras/build-tests/windows/compilecmd/vs2019.bat b/extras/build-tests/windows/compilecmd/vs2019.bat
index 690194c..238b808 100644
--- a/extras/build-tests/windows/compilecmd/vs2019.bat
+++ b/extras/build-tests/windows/compilecmd/vs2019.bat
@@ -1,21 +1,30 @@
rem Build command for Visual Studio 2019
-nmake -f makefile.windows ^
-LIBRESSL_INC_DIR="c:\projects\unrealircd-5-libs\libressl\include" ^
-LIBRESSL_LIB_DIR="c:\projects\unrealircd-5-libs\libressl\lib" ^
-SSLLIB="crypto-46.lib ssl-48.lib" ^
+rem This used to start with:
+rem nmake -f makefile.windows ^
+rem But nowadays we use JOM for parallel builds:
+jom /j32 -f makefile.windows ^
+LIBRESSL_INC_DIR="c:\projects\unrealircd-6-libs\libressl\include" ^
+LIBRESSL_LIB_DIR="c:\projects\unrealircd-6-libs\libressl\lib" ^
+SSLLIB="crypto-47.lib ssl-50.lib" ^
USE_REMOTEINC=1 ^
-LIBCURL_INC_DIR="c:\projects\unrealircd-5-libs\curl\include" ^
-LIBCURL_LIB_DIR="c:\projects\unrealircd-5-libs\curl\builds\libcurl-vc-x64-release-dll-ssl-dll-cares-dll-ipv6-obj-lib" ^
-CARES_LIB_DIR="c:\projects\unrealircd-5-libs\c-ares\msvc\cares\dll-release" ^
-CARES_INC_DIR="c:\projects\unrealircd-5-libs\c-ares\include" ^
+LIBCURL_INC_DIR="c:\projects\unrealircd-6-libs\curl\include" ^
+LIBCURL_LIB_DIR="c:\projects\unrealircd-6-libs\curl\builds\libcurl-vc-x64-release-dll-ssl-dll-cares-dll-ipv6-obj-lib" ^
+CARES_LIB_DIR="c:\projects\unrealircd-6-libs\c-ares\msvc\cares\dll-release" ^
+CARES_INC_DIR="c:\projects\unrealircd-6-libs\c-ares\include" ^
CARESLIB="cares.lib" ^
-PCRE2_INC_DIR="c:\projects\unrealircd-5-libs\pcre2\include" ^
-PCRE2_LIB_DIR="c:\projects\unrealircd-5-libs\pcre2\lib" ^
+PCRE2_INC_DIR="c:\projects\unrealircd-6-libs\pcre2\include" ^
+PCRE2_LIB_DIR="c:\projects\unrealircd-6-libs\pcre2\lib" ^
PCRE2LIB="pcre2-8.lib" ^
-ARGON2_LIB_DIR="c:\projects\unrealircd-5-libs\argon2\vs2015\build" ^
-ARGON2_INC_DIR="c:\projects\unrealircd-5-libs\argon2\include" ^
+ARGON2_LIB_DIR="c:\projects\unrealircd-6-libs\argon2\vs2015\build" ^
+ARGON2_INC_DIR="c:\projects\unrealircd-6-libs\argon2\include" ^
ARGON2LIB="Argon2RefDll.lib" ^
-SODIUM_LIB_DIR="c:\projects\unrealircd-5-libs\libsodium\bin\x64\Release\v142\dynamic" ^
-SODIUM_INC_DIR="c:\projects\unrealircd-5-libs\libsodium\src\libsodium\include" ^
-SODIUMLIB="libsodium.lib" %*
+SODIUM_LIB_DIR="c:\projects\unrealircd-6-libs\libsodium\bin\x64\Release\v142\dynamic" ^
+SODIUM_INC_DIR="c:\projects\unrealircd-6-libs\libsodium\src\libsodium\include" ^
+SODIUMLIB="libsodium.lib" ^
+JANSSON_LIB_DIR="c:\projects\unrealircd-6-libs\jansson\lib" ^
+JANSSON_INC_DIR="c:\projects\unrealircd-6-libs\jansson\include" ^
+JANSSONLIB="jansson.lib" ^
+GEOIPCLASSIC_LIB_DIR="c:\projects\unrealircd-6-libs\GeoIP\libGeoIP" ^
+GEOIPCLASSIC_INC_DIR="c:\projects\unrealircd-6-libs\GeoIP\libGeoIP" ^
+GEOIPCLASSICLIB="GeoIP.lib" %*
diff --git a/extras/c-ares.tar.gz b/extras/c-ares.tar.gz
index b59d17a..bb16c09 100644
Binary files a/extras/c-ares.tar.gz and b/extras/c-ares.tar.gz differ
diff --git a/extras/curlinstall b/extras/curlinstall
index 6715ed9..85bce4e 100755
--- a/extras/curlinstall
+++ b/extras/curlinstall
@@ -4,7 +4,7 @@ OUTF="curl-latest.tar.gz"
OUTD="curl-latest"
ARESPATH="`pwd`/extras/c-ares"
UNREALDIR="`pwd`"
-CARESVERSION="1.17.1"
+CARESVERSION="1.17.2"
LIBDIR="$1"
if [ "x$1" = "x" ]; then
diff --git a/extras/doxygen/Developers.md b/extras/doxygen/Developers.md
index 85be6d1..2344f7d 100644
--- a/extras/doxygen/Developers.md
+++ b/extras/doxygen/Developers.md
@@ -1,4 +1,4 @@
-Welcome to the doxygen-generated documentation for the UnrealIRCd 5.x API.
+Welcome to the doxygen-generated documentation for the UnrealIRCd 6.x API.
This is intended **for developers only!**
If you are creating a 3rd party module for UnrealIRCd or are interested
diff --git a/extras/doxygen/Doxyfile b/extras/doxygen/Doxyfile
index 579e7ca..f9e71a9 100644
--- a/extras/doxygen/Doxyfile
+++ b/extras/doxygen/Doxyfile
@@ -38,7 +38,7 @@ PROJECT_NAME = "UnrealIRCd"
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER = 5.2.0.1
+PROJECT_NUMBER = 6.0.1.1
# 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
diff --git a/extras/geoip-classic.tar.gz b/extras/geoip-classic.tar.gz
new file mode 100644
index 0000000..ded9ebd
Binary files /dev/null and b/extras/geoip-classic.tar.gz differ
diff --git a/extras/jansson.tar.gz b/extras/jansson.tar.gz
new file mode 100644
index 0000000..bd1d16c
Binary files /dev/null and b/extras/jansson.tar.gz differ
diff --git a/extras/security/apparmor/unrealircd b/extras/security/apparmor/unrealircd
index c9eb837..e6c9a0a 100644
--- a/extras/security/apparmor/unrealircd
+++ b/extras/security/apparmor/unrealircd
@@ -1,9 +1,9 @@
-# AppArmor profile for UnrealIRCd 5
+# AppArmor profile for UnrealIRCd 6
#
# Note that you may still see some DENIED warnings in logs with
# operation="chmod". These are harmless and can be safely ignored.
#
-# Tested on Ubuntu 16.04 LTS and Ubuntu 18.04 LTS
+# Tested on Ubuntu 16.04 LTS, Ubuntu 18.04 LTS, Ubuntu 20.04 LTS
#
# IMPORTANT: you will have to modify the path to executable below
# if it's not /home/ircd/unrealircd/bin/unrealircd !
diff --git a/extras/tests/tls/cipherscan_profiles/openssl-300.txt b/extras/tests/tls/cipherscan_profiles/openssl-300.txt
new file mode 100644
index 0000000..76c368f
--- /dev/null
+++ b/extras/tests/tls/cipherscan_profiles/openssl-300.txt
@@ -0,0 +1,27 @@
+Target: 127.0.0.1:5901
+
+prio ciphersuite protocols pfs curves
+1 ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1
+2 ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1
+3 ECDHE-ECDSA-AES256-SHA384 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1
+4 ECDHE-ECDSA-AES128-SHA256 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1
+5 ECDHE-ECDSA-AES256-SHA TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1
+6 ECDHE-ECDSA-AES128-SHA TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1
+
+Certificate: untrusted, 384 bits, ecdsa-with-SHA256 signature
+TLS ticket lifetime hint: None
+NPN protocols: None
+OCSP stapling: not supported
+Cipher ordering: server
+Curves ordering: server - fallback: no
+Server supports secure renegotiation
+Server supported compression methods: NONE
+TLS Tolerance: yes
+
+Intolerance to:
+ SSL 3.254 : absent
+ TLS 1.0 : PRESENT
+ TLS 1.1 : PRESENT
+ TLS 1.2 : absent
+ TLS 1.3 : absent
+ TLS 1.4 : absent
diff --git a/extras/tls.cnf b/extras/tls.cnf
index 7a04a4a..46a9611 100644
--- a/extras/tls.cnf
+++ b/extras/tls.cnf
@@ -18,7 +18,7 @@ stateOrProvinceName_default = New York
localityName = Locality Name (eg, city)
0.organizationName = Organization Name (eg, company)
-0.organizationName_default = SuperNETs
+0.organizationName_default = IRC geeks
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = IRCd
diff --git a/extras/unrealircd-upgrade-script.in b/extras/unrealircd-upgrade-script.in
index 6ce5743..6c3005b 100644
--- a/extras/unrealircd-upgrade-script.in
+++ b/extras/unrealircd-upgrade-script.in
@@ -1,11 +1,11 @@
-#!/bin/bash
+#!/usr/bin/env bash
#
# This is stage 1 of the UnrealIRCd upgrade script
# It downloads stage 2 online, verifies the integrity, and then
# passes control to it to proceed with the rest of the upgrade.
#
-# This is a bash script, so it is less cross-platform than
-# the rest of UnrealIRCd. We also mostly assume Linux here.
+# This is a bash script, so it is less cross-platform than the
+# rest of UnrealIRCd. We also mostly assume Linux/FreeBSD here.
#
BUILDDIR="@BUILDDIR@"
@@ -55,13 +55,19 @@ if [ ! -d "$BUILDDIR" ]; then
exit 1
fi
+FETCHER="wget"
if ! wget --help 1>/dev/null 2>&1; then
- echo "The tool 'wget' is missing, which is used by this script."
- echo "On Linux consider running 'sudo apt install wget' or 'sudo yum install wget'"
- echo "and run this script again."
- echo "Or, don't use this script and follow the manual upgrade procedure from"
- echo "https://www.unrealircd.org/docs/Upgrading"
- exit 1
+ # fetch is a pain: it always returns 1 (false) even for usage info and has no --version
+ fetch 1>/dev/null 2>&1
+ if [ "$?" -ne 1 ]; then
+ echo "The tool 'wget' is missing, which is used by this script."
+ echo "On Linux consider running 'sudo apt install wget' or 'sudo yum install wget'"
+ echo "and run this script again."
+ echo "Or, don't use this script and follow the manual upgrade procedure from"
+ echo "https://www.unrealircd.org/docs/Upgrading"
+ exit 1
+ fi
+ FETCHER="fetch"
fi
# Weird way to get version, but ok.
@@ -70,11 +76,16 @@ UNREALVER="`./configure --version|head -n1|awk '{ print $3 }'`"
cd .. || fail "Could not cd back"
# Set and export all variables with settings
-export UNREALVER BUILDDIR SCRIPTDIR DOCDIR TMPDIR
+export UNREALVER BUILDDIR SCRIPTDIR DOCDIR TMPDIR FETCHER
# Download the install script
-wget -O unrealircd-upgrade-script.stage2 "https://www.unrealircd.org/downloads/unrealircd-upgrade-script.stage2?from=$UNREALVER" || fail "Could not download online installer"
-wget -O unrealircd-upgrade-script.stage2.asc "https://www.unrealircd.org/downloads/unrealircd-upgrade-script.stage2.asc" || fail "Could not download online installer signature"
+if [ "$FETCHER" = "wget" ]; then
+ wget -O unrealircd-upgrade-script.stage2 "https://www.unrealircd.org/downloads/unrealircd-upgrade-script.stage2?from=$UNREALVER" || fail "Could not download online installer"
+ wget -O unrealircd-upgrade-script.stage2.asc "https://www.unrealircd.org/downloads/unrealircd-upgrade-script.stage2.asc" || fail "Could not download online installer signature"
+else
+ fetch -o unrealircd-upgrade-script.stage2 "https://www.unrealircd.org/downloads/unrealircd-upgrade-script.stage2?from=$UNREALVER" || fail "Could not download online installer"
+ fetch -o unrealircd-upgrade-script.stage2.asc "https://www.unrealircd.org/downloads/unrealircd-upgrade-script.stage2.asc" || fail "Could not download online installer signature"
+fi
# GPG verification - if available
if gpg --version 1>/dev/null 2>&1; then
@@ -94,7 +105,11 @@ if gpg --version 1>/dev/null 2>&1; then
fi
else
echo "WARNING: The GnuPG (GPG/PGP) verification tool 'gpg' is not installed."
- echo "Consider running 'sudo apt install gpg' or 'yum install gnupg2'"
+ if [[ "$OSTYPE" == "freebsd"* ]] ; then
+ echo "Consider running 'sudo pkg install gnupg'"
+ else
+ echo "Consider running 'sudo apt install gpg' or 'yum install gnupg2'"
+ fi
echo "When 'gpg' is installed then the UnrealIRCd upgrade script can"
echo "verify the digital signature of the download file."
warn "Unable to check download integrity"
@@ -103,3 +118,6 @@ fi
chmod +x unrealircd-upgrade-script.stage2
./unrealircd-upgrade-script.stage2 $*
+SAVERET="$?"
+rm -f unrealircd-upgrade-script.stage2 unrealircd-upgrade-script.stage2
+exit $SAVERET
diff --git a/include/channel.h b/include/channel.h
index 44fe84a..f229290 100644
--- a/include/channel.h
+++ b/include/channel.h
@@ -26,7 +26,7 @@
#define MODEBUFLEN 200
-#define ChannelExists(n) (find_channel(n, NULL))
+#define ChannelExists(n) (find_channel(n))
/* NOTE: Timestamps will be added to MODE-commands, so never make
* RESYNCMODES and MODEPARAMS higher than MAXPARA-3. DALnet servers
diff --git a/include/common.h b/include/common.h
index a666bb9..5a0d1d6 100644
--- a/include/common.h
+++ b/include/common.h
@@ -98,7 +98,6 @@ extern int myncmp(const char *, const char *, int);
extern char *strtoken(char **, char *, char *);
extern MODVAR int global_count, max_global_count;
-extern char *myctime(time_t);
#ifdef _WIN32
extern int gettimeofday(struct timeval *tp, void *tzp);
#endif
@@ -174,18 +173,7 @@ extern MODVAR unsigned char char_atribs[];
#define EXPAR2 extchmstr[1]
#define EXPAR3 extchmstr[2]
#define EXPAR4 extchmstr[3]
-
-#ifdef PREFIX_AQ
-#define CHPFIX "(qaohv)~&@%+"
-#define CHPAR1 "beI"
-#else
-#define CHPFIX "(ohv)@%+"
-#define CHPAR1 "beIqa"
-#endif /* PREFIX_AQ */
-
-#define CHPAR2 "k"
-#define CHPAR3 "l"
-#define CHPAR4 "psmntir"
+#define CHPAR1 "beI"
#ifdef _WIN32
/*
diff --git a/include/config.h b/include/config.h
index 6becea2..9156eb7 100644
--- a/include/config.h
+++ b/include/config.h
@@ -98,9 +98,6 @@
*/
/* #undef DEBUGMODE */
-/* Similarly, DEBUG_IOENGINE can be used to debug the I/O engine. */
-/* #undef DEBUG_IOENGINE */
-
/*
* Full pathnames and defaults of irc system's support files.
*/
@@ -126,7 +123,7 @@
* Common usage for this are: a trusted bot ran by an IRCOp, that you only
* want to give "flood access" and nothing else, and other such things.
*/
-#define FAKELAG_CONFIGURABLE
+//#undef FAKELAG_CONFIGURABLE
/* The default value for class::sendq */
#define DEFAULT_SENDQ 3000000
@@ -212,10 +209,25 @@
* when there is no socket data waiting for us (no clients sending anything).
* Was 2000ms in 3.2.x, 1000ms for versions below 3.4-alpha4.
* 500ms in UnrealIRCd 4 (?)
- * 250ms in UnrealIRCd 5.
+ * 250ms in UnrealIRCd 5 and UnrealIRCd 6.
*/
#define SOCKETLOOP_MAX_DELAY 250
+/* After how much time should we timeout downloads:
+ * DOWNLOAD_CONNECT_TIMEOUT: for the DNS and connect() / TLS_connect() call
+ * DOWNLOAD_TRANSFER_TIMEOUT: for the complete transfer (including connect)
+ * This can't be in the configuration file, as we need it while
+ * fetching the configuration file.. ;)
+ */
+#define DOWNLOAD_CONNECT_TIMEOUT 15
+#define DOWNLOAD_TRANSFER_TIMEOUT 45
+
+/* Maximum number of HTTP redirects to follow.
+ * Keep this reasonably low, as this may delay booting up to
+ * DOWNLOAD_TRANSFER_TIMEOUT * DOWNLOAD_MAX_REDIRECTS
+ */
+#define DOWNLOAD_MAX_REDIRECTS 2
+
/*
* Max time from the nickname change that still causes KILL
* automaticly to switch for the current nick of that user. (seconds)
@@ -233,25 +245,34 @@
#endif
/* Maximum number of ModData objects that may be attached to an object */
-/* UnrealIRCd 4.0.0 - 4.0.13: 8, 8, 4, 4
- * UnrealIRCd 4.0.14+ : 12, 8, 4, 4
- * UnrealIRCd 5.0.0 : 12, 8, 8, 4, 4, 500, 500
+/* UnrealIRCd 4.0.0 - 4.0.13: 8, 8, 4, 4
+ * UnrealIRCd 4.0.14+ : 12, 8, 4, 4
+ * UnrealIRCd 5.0.0 : 12, 8, 8, 4, 4, 500, 500
+ * UnrealIRCd 6.0.0 : 24, 12, 8, 4, 4, 500, 500
*/
-#define MODDATA_MAX_CLIENT 12
-#define MODDATA_MAX_LOCAL_CLIENT 8
+#define MODDATA_MAX_CLIENT 24
+#define MODDATA_MAX_LOCAL_CLIENT 12
#define MODDATA_MAX_CHANNEL 8
#define MODDATA_MAX_MEMBER 4
#define MODDATA_MAX_MEMBERSHIP 4
#define MODDATA_MAX_LOCAL_VARIABLE 500
#define MODDATA_MAX_GLOBAL_VARIABLE 500
+/** Size of the member modes buffer, so can be max this-1 modes
+ * assigned to an individual user (and thus max prefixes as well).
+ * The default is 8, so 7 max modes, and is a bit tight.
+ * It allows for vhoaq (5) and then 2 additional ones from 3rd
+ * party modules.
+ */
+#define MEMBERMODESLEN 8
+
/* If EXPERIMENTAL is #define'd then all users will receive a notice about
* this when they connect, along with a pointer to bugs.unrealircd.org where
* they can report any problems. This is mainly to help UnrealIRCd development.
*/
#undef EXPERIMENTAL
-/* Default SSL/TLS cipherlist (except for TLS1.3, see further down).
+/* Default TLS cipherlist (except for TLS1.3, see further down).
* This can be changed via set::ssl::options::ciphers in the config file.
*/
#define UNREALIRCD_DEFAULT_CIPHERS "TLS13-CHACHA20-POLY1305-SHA256 TLS13-AES-256-GCM-SHA384 TLS13-AES-128-GCM-SHA256 EECDH+CHACHA20 EECDH+AESGCM EECDH+AES AES256-GCM-SHA384 AES128-GCM-SHA256 AES256-SHA256 AES128-SHA256 AES256-SHA AES128-SHA"
@@ -261,7 +282,7 @@
*/
#define UNREALIRCD_DEFAULT_CIPHERSUITES "TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_8_SHA256:TLS_AES_128_CCM_SHA256"
-/* Default SSL/TLS curves for ECDH(E)
+/* Default TLS curves for ECDH(E)
* This can be changed via set::ssl::options::ecdh-curve in the config file.
* NOTE: This requires openssl 1.0.2 or newer, otherwise these defaults
* are not applied, due to the missing openssl API call.
@@ -280,10 +301,8 @@
#define IRCD_PIDFILE PIDFILE
#ifdef DEBUGMODE
- #define Debug(x) debug x
#define LOGFILE LPATH
#else
- #define Debug(x) ;
#define LOGFILE "/dev/null"
#endif
diff --git a/include/dbuf.h b/include/dbuf.h
index fe1e88e..522b6c4 100644
--- a/include/dbuf.h
+++ b/include/dbuf.h
@@ -70,7 +70,7 @@ typedef struct dbufbuf {
** memory as needed. Bytes are copied into internal buffers
** from users buffer.
*/
-void dbuf_put(dbuf *, char *, size_t);
+void dbuf_put(dbuf *, const char *, size_t);
/* Dynamic buffer header */
/* Pointer to data to be stored */
/* Number of bytes to store */
diff --git a/include/dynconf.h b/include/dynconf.h
index dbf4c4d..978f444 100644
--- a/include/dynconf.h
+++ b/include/dynconf.h
@@ -32,26 +32,12 @@ struct FloodSettings {
long period[MAXFLOODOPTIONS];
};
-typedef struct NetworkConfiguration NetworkConfiguration;
-struct NetworkConfiguration {
- unsigned x_inah:1;
- char *x_ircnetwork;
- char *x_ircnet005;
- char *x_defserv;
- char *x_services_name;
- char *x_hidden_host;
- char *x_prefix_quit;
- char *x_helpchan;
- char *x_stats_server;
- char *x_sasl_server;
-};
-
enum UHAllowed { UHALLOW_ALWAYS, UHALLOW_NOCHANS, UHALLOW_REJOIN, UHALLOW_NEVER };
struct ChMode {
- long mode;
+ long mode;
long extmodes;
- char *extparams[EXTCMODETABLESZ];
+ char *extparams[256];
};
typedef struct OperStat {
@@ -70,10 +56,9 @@ typedef enum HideIdleTimePolicy { HIDE_IDLE_TIME_NEVER=1, HIDE_IDLE_TIME_ALWAYS=
/** The set { } block configuration */
typedef struct Configuration Configuration;
struct Configuration {
- unsigned som:1;
+ unsigned show_opermotd:1;
unsigned hide_ulines:1;
unsigned flat_map:1;
- unsigned allow_chatops:1;
unsigned ident_check:1;
unsigned fail_oper_warn:1;
unsigned show_connect_info:1;
@@ -86,8 +71,6 @@ struct Configuration {
unsigned allow_part_if_shunned:1;
unsigned disable_cap:1;
unsigned check_target_nick_bans:1;
- unsigned use_egd : 1;
- char *dns_bindip;
char *link_bindip;
long throttle_period;
char throttle_count;
@@ -100,11 +83,10 @@ struct Configuration {
char *oper_auto_join_chans;
char *allow_user_stats;
OperStat *allow_user_stats_ext;
- int ping_warning;
- int maxchannelsperuser;
- int maxdccallow;
- int anti_spam_quit_message_time;
- char *egd_path;
+ int ping_warning;
+ int maxchannelsperuser;
+ int maxdccallow;
+ int anti_spam_quit_message_time;
char *static_quit;
char *static_part;
TLSOptions *tls_options;
@@ -122,12 +104,14 @@ struct Configuration {
char *restrict_usermodes;
char *restrict_channelmodes;
char *restrict_extendedbans;
+ int named_extended_bans;
char *channel_command_prefix;
long handshake_data_flood_amount;
long handshake_data_flood_ban_time;
int handshake_data_flood_ban_action;
struct ChMode modes_on_join;
- int level_on_join;
+ int modes_on_join_set;
+ char *level_on_join;
FloodSettings *floodsettings;
int ident_connect_timeout;
int ident_read_timeout;
@@ -148,7 +132,6 @@ struct Configuration {
int maxbanlength;
int watch_away_notification;
int uhnames;
- NetworkConfiguration network;
unsigned short default_ipv6_clone_mask;
int ping_cookie;
int min_nick_length;
@@ -176,6 +159,17 @@ struct Configuration {
BroadcastChannelMessagesOption broadcast_channel_messages;
AllowedChannelChars allowed_channelchars;
HideIdleTimePolicy hide_idle_time;
+ unsigned inah:1;
+ char *network_name;
+ char *network_name_005;
+ char *default_server;
+ char *services_name;
+ char *cloak_prefix;
+ char *prefix_quit;
+ char *helpchan;
+ char *stats_server;
+ char *sasl_server;
+ int server_notice_colors;
};
extern MODVAR Configuration iConf;
@@ -187,7 +181,7 @@ extern MODVAR int ipv6_disabled;
#define CONN_MODES iConf.conn_modes
#define OPER_MODES iConf.oper_modes
#define OPER_SNOMASK iConf.oper_snomask
-#define SHOWOPERMOTD iConf.som
+#define SHOWOPERMOTD iConf.show_opermotd
#define HIDE_ULINES iConf.hide_ulines
#define FLAT_MAP iConf.flat_map
#define ALLOW_CHATOPS iConf.allow_chatops
@@ -197,7 +191,6 @@ extern MODVAR int ipv6_disabled;
#define DONT_RESOLVE iConf.dont_resolve
#define AUTO_JOIN_CHANS iConf.auto_join_chans
#define OPER_AUTO_JOIN_CHANS iConf.oper_auto_join_chans
-#define DNS_BINDIP iConf.dns_bindip
#define LINK_BINDIP iConf.link_bindip
#define IDENT_CHECK iConf.ident_check
#define FAILOPER_WARN iConf.fail_oper_warn
@@ -205,23 +198,17 @@ extern MODVAR int ipv6_disabled;
#define NOCONNECTTLSLINFO iConf.no_connect_tls_info
#define ALLOW_USER_STATS iConf.allow_user_stats
#define ANTI_SPAM_QUIT_MSG_TIME iConf.anti_spam_quit_message_time
-#ifdef HAVE_RAND_EGD
-#define USE_EGD iConf.use_egd
-#else
-#define USE_EGD 0
-#endif
-#define EGD_PATH iConf.egd_path
-#define ircnetwork iConf.network.x_ircnetwork
-#define ircnet005 iConf.network.x_ircnet005
-#define defserv iConf.network.x_defserv
-#define SERVICES_NAME iConf.network.x_services_name
-#define hidden_host iConf.network.x_hidden_host
-#define helpchan iConf.network.x_helpchan
-#define STATS_SERVER iConf.network.x_stats_server
-#define SASL_SERVER iConf.network.x_sasl_server
-#define iNAH iConf.network.x_inah
-#define PREFIX_QUIT iConf.network.x_prefix_quit
+#define NETWORK_NAME iConf.network_name
+#define NETWORK_NAME_005 iConf.network_name_005
+#define DEFAULT_SERVER iConf.default_server
+#define SERVICES_NAME iConf.services_name
+#define CLOAK_PREFIX iConf.cloak_prefix
+#define HELP_CHANNEL iConf.helpchan
+#define STATS_SERVER iConf.stats_server
+#define SASL_SERVER iConf.sasl_server
+#define iNAH iConf.inah
+#define PREFIX_QUIT iConf.prefix_quit
#define STATIC_QUIT iConf.static_quit
#define STATIC_PART iConf.static_part
@@ -232,7 +219,7 @@ extern MODVAR int ipv6_disabled;
#define THROTTLING_PERIOD iConf.throttle_period
#define THROTTLING_COUNT iConf.throttle_count
#define USE_BAN_VERSION iConf.use_ban_version
-#define MODES_ON_JOIN iConf.modes_on_join.mode
+#define MODES_ON_JOIN iConf.modes_on_join.extmodes
#define LEVEL_ON_JOIN iConf.level_on_join
#define IDENT_CONNECT_TIMEOUT iConf.ident_connect_timeout
@@ -309,7 +296,6 @@ struct SetCheck {
unsigned has_maxchannelsperuser:1;
unsigned has_maxdccallow:1;
unsigned has_anti_spam_quit_message_time:1;
- unsigned has_egd_path:1;
unsigned has_static_quit:1;
unsigned has_static_part:1;
unsigned has_allow_userhost_change:1;
diff --git a/include/fdlist.h b/include/fdlist.h
index 6bb0318..bb24f4f 100644
--- a/include/fdlist.h
+++ b/include/fdlist.h
@@ -7,6 +7,8 @@
typedef void (*IOCallbackFunc)(int fd, int revents, void *data);
+typedef enum FDCloseMethod { FDCLOSE_SOCKET=0, FDCLOSE_FILE=1, FDCLOSE_NONE=3 } FDCloseMethod;
+
typedef struct fd_entry {
int fd;
char desc[FD_DESC_SZ];
@@ -15,14 +17,14 @@ typedef struct fd_entry {
void *data;
time_t deadline;
unsigned char is_open;
+ FDCloseMethod close_method;
unsigned int backend_flags;
} FDEntry;
extern MODVAR FDEntry fd_table[MAXCONNECTIONS + 1];
-extern int fd_open(int fd, const char *desc);
-extern void fd_close(int fd);
-extern int fd_unmap(int fd);
+extern int fd_open(int fd, const char *desc, FDCloseMethod close_method);
+extern int fd_close(int fd);
extern void fd_unnotify(int fd);
extern int fd_socket(int family, int type, int protocol, const char *desc);
extern int fd_accept(int sockfd);
diff --git a/include/h.h b/include/h.h
index f1aa4fc..6b380f5 100644
--- a/include/h.h
+++ b/include/h.h
@@ -30,10 +30,6 @@
extern MODVAR char *extraflags;
extern MODVAR int tainted;
-/* for the new s_err.c */
-extern char *getreply(int);
-#define rpl_str(x) getreply(x)
-#define err_str(x) getreply(x)
extern MODVAR Member *freemember;
extern MODVAR Membership *freemembership;
extern MODVAR Client me;
@@ -52,7 +48,7 @@ extern MODVAR char umodestring[UMODETABLESZ+1];
#define get_recvq(x) ((x)->local->class->recvq ? (x)->local->class->recvq : DEFAULT_RECVQ)
/* Configuration preprocessor */
-extern PreprocessorItem parse_preprocessor_item(char *start, char *end, char *filename, int linenumber, ConditionalConfig **cc);
+extern PreprocessorItem parse_preprocessor_item(char *start, char *end, const char *filename, int linenumber, ConditionalConfig **cc);
extern void preprocessor_cc_duplicate_list(ConditionalConfig *r, ConditionalConfig **out);
extern void preprocessor_cc_free_level(ConditionalConfig **cc_list, int level);
extern void preprocessor_cc_free_list(ConditionalConfig *cc);
@@ -76,7 +72,6 @@ extern MODVAR ConfigItem_tld *conf_tld;
extern MODVAR ConfigItem_oper *conf_oper;
extern MODVAR ConfigItem_listen *conf_listen;
extern MODVAR ConfigItem_allow *conf_allow;
-extern MODVAR ConfigItem_except *conf_except;
extern MODVAR ConfigItem_vhost *conf_vhost;
extern MODVAR ConfigItem_link *conf_link;
extern MODVAR ConfigItem_sni *conf_sni;
@@ -85,9 +80,7 @@ extern MODVAR ConfigItem_deny_channel *conf_deny_channel;
extern MODVAR ConfigItem_deny_link *conf_deny_link;
extern MODVAR ConfigItem_allow_channel *conf_allow_channel;
extern MODVAR ConfigItem_deny_version *conf_deny_version;
-extern MODVAR ConfigItem_log *conf_log;
extern MODVAR ConfigItem_alias *conf_alias;
-extern MODVAR ConfigItem_include *conf_include;
extern MODVAR ConfigItem_help *conf_help;
extern MODVAR ConfigItem_offchans *conf_offchans;
extern MODVAR SecurityGroup *securitygroups;
@@ -97,10 +90,13 @@ extern EVENT(e_unload_module_delayed);
extern EVENT(throttling_check_expire);
extern void module_loadall(void);
-extern long set_usermode(char *umode);
-extern char *get_usermode_string_raw(long umodes);
-extern ConfigFile *config_parse(char *filename, char *confdata);
-extern ConfigFile *config_parse_with_offset(char *filename, char *confdata, unsigned int line_offset);
+extern long set_usermode(const char *umode);
+extern const char *get_usermode_string(Client *acptr);
+extern const char *get_usermode_string_r(Client *client, char *buf, size_t buflen);
+extern const char *get_usermode_string_raw(long umodes);
+extern const char *get_usermode_string_raw_r(long umodes, char *buf, size_t buflen);
+extern ConfigFile *config_parse(const char *filename, char *confdata);
+extern ConfigFile *config_parse_with_offset(const char *filename, char *confdata, unsigned int line_offset);
extern void config_error(FORMAT_STRING(const char *format), ...) __attribute__((format(printf,1,2)));
extern void config_warn(FORMAT_STRING(const char *format), ...) __attribute__((format(printf,1,2)));
extern void config_error_missing(const char *filename, int line, const char *entry);
@@ -115,27 +111,25 @@ extern int config_is_blankorempty(ConfigEntry *cep, const char *block);
extern MODVAR int config_verbose;
extern void config_entry_free(ConfigEntry *ce);
extern void config_entry_free_all(ConfigEntry *ce);
-extern ConfigFile *config_load(char *filename, char *displayname);
+extern ConfigFile *config_load(const char *filename, const char *displayname);
extern void config_free(ConfigFile *cfptr);
-extern void ipport_seperate(char *string, char **ip, char **port);
-extern ConfigItem_class *find_class(char *name);
-extern ConfigItem_deny_dcc *find_deny_dcc(char *name);
-extern ConfigItem_oper *find_oper(char *name);
-extern ConfigItem_operclass *find_operclass(char *name);
-extern ConfigItem_listen *find_listen(char *ipmask, int port, int ipv6);
-extern ConfigItem_sni *find_sni(char *name);
-extern ConfigItem_ulines *find_uline(char *host);
-extern ConfigItem_except *find_except(Client *, short type);
+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_sni *find_sni(const char *name);
+extern ConfigItem_ulines *find_uline(const char *host);
extern ConfigItem_tld *find_tld(Client *cptr);
-extern ConfigItem_link *find_link(char *servername, Client *acptr);
-extern ConfigItem_ban *find_ban(Client *, char *host, short type);
-extern ConfigItem_ban *find_banEx(Client *,char *host, short type, short type2);
-extern ConfigItem_vhost *find_vhost(char *name);
-extern ConfigItem_deny_channel *find_channel_allowed(Client *cptr, char *name);
-extern ConfigItem_alias *find_alias(char *name);
-extern ConfigItem_help *find_Help(char *command);
+extern ConfigItem_link *find_link(const char *servername, Client *acptr);
+extern ConfigItem_ban *find_ban(Client *, const char *host, short type);
+extern ConfigItem_ban *find_banEx(Client *,const char *host, short type, short type2);
+extern ConfigItem_vhost *find_vhost(const char *name);
+extern ConfigItem_deny_channel *find_channel_allowed(Client *cptr, const char *name);
+extern ConfigItem_alias *find_alias(const char *name);
+extern ConfigItem_help *find_Help(const char *command);
-extern OperPermission ValidatePermissionsForPath(char *path, Client *client, Client *victim, Channel *channel, void *extra);
+extern OperPermission ValidatePermissionsForPath(const char *path, Client *client, Client *victim, Channel *channel, const void *extra);
extern void OperClassValidatorDel(OperClassValidator *validator);
extern ConfigItem_ban *find_ban_ip(Client *client);
@@ -144,8 +138,8 @@ extern void append_ListItem(ListStruct *item, ListStruct **list);
extern void add_ListItemPrio(ListStructPrio *, ListStructPrio **, int);
extern void del_ListItem(ListStruct *, ListStruct **);
extern MODVAR LoopStruct loop;
-extern int del_banid(Channel *channel, char *banid);
-extern int del_exbanid(Channel *channel, char *banid);
+extern int del_banid(Channel *channel, const char *banid);
+extern int del_exbanid(Channel *channel, const char *banid);
#define REPORT_DO_DNS "NOTICE * :*** Looking up your hostname...\r\n"
#define REPORT_FIN_DNS "NOTICE * :*** Found your hostname\r\n"
#define REPORT_FIN_DNSC "NOTICE * :*** Found your hostname (cached)\r\n"
@@ -161,48 +155,66 @@ extern MODVAR struct list_head oper_list;
extern MODVAR struct list_head unknown_list;
extern MODVAR struct list_head global_server_list;
extern MODVAR struct list_head dead_list;
-extern RealCommand *find_command(char *cmd, int flags);
-extern RealCommand *find_command_simple(char *cmd);
+extern RealCommand *find_command(const char *cmd, int flags);
+extern RealCommand *find_command_simple(const char *cmd);
extern Membership *find_membership_link(Membership *lp, Channel *ptr);
extern Member *find_member_link(Member *, Client *);
-extern int remove_user_from_channel(Client *, Channel *);
+extern int remove_user_from_channel(Client *client, Channel *channel, int dont_log);
extern void add_server_to_table(Client *);
extern void remove_server_from_table(Client *);
-extern void iNAH_host(Client *client, char *host);
-extern void set_snomask(Client *client, char *snomask);
-extern char *get_snomask_string(Client *client);
+extern void iNAH_host(Client *client, const char *host);
+extern void set_snomask(Client *client, const char *snomask);
extern int check_tkls(Client *cptr);
/* for services */
extern void send_user_joins(Client *, Client *);
extern int valid_channelname(const char *);
-extern int valid_server_name(char *name);
-extern long get_access(Client *, Channel *);
-extern int ban_check_mask(Client *, Channel *, char *, int, char **, char **, int);
-extern int extban_is_ok_nuh_extban(Client *, Channel *, char *, int, int, int);
-extern char *extban_conv_param_nuh_or_extban(char *);
-extern char *extban_conv_param_nuh(char *);
-extern Ban *is_banned(Client *, Channel *, int, char **, char **);
-extern Ban *is_banned_with_nick(Client *, Channel *, int, char *, char **, char **);
+extern int valid_server_name(const char *name);
+extern Cmode *find_channel_mode_handler(char letter);
+extern int valid_channel_access_mode_letter(char letter);
+extern int check_channel_access(Client *client, Channel *channel, const char *modes);
+extern int check_channel_access_membership(Membership *mb, const char *modes);
+extern int check_channel_access_member(Member *mb, const char *modes);
+extern int check_channel_access_string(const char *current_modes, const char *modes);
+extern int check_channel_access_letter(const char *current_modes, const char letter);
+extern const char *get_channel_access(Client *client, Channel *channel);
+extern void add_member_mode_fast(Member *mb, Membership *mbs, char letter);
+extern void del_member_mode_fast(Member *mb, Membership *mbs, char letter);
+extern void add_member_mode(Client *client, Channel *channel, char letter);
+extern void del_member_mode(Client *client, Channel *channel, char letter);
+extern char sjoin_prefix_to_mode(char s);
+extern char mode_to_sjoin_prefix(char s);
+extern char mode_to_prefix(char s);
+extern char prefix_to_mode(char s);
+extern const char *modes_to_prefix(const char *modes);
+extern const char *modes_to_sjoin_prefix(const char *modes);
+extern char rank_to_mode(int rank);
+extern int mode_to_rank(char mode);
+extern char lowest_ranking_mode(const char *modes);
+extern char lowest_ranking_prefix(const char *prefix);
+extern void channel_member_modes_generate_equal_or_greater(const char *modes, char *buf, size_t buflen);
+extern int ban_check_mask(BanContext *b);
+extern int extban_is_ok_nuh_extban(BanContext *b);
+extern const char *extban_conv_param_nuh_or_extban(BanContext *b, Extban *extban);
+extern const char *extban_conv_param_nuh(BanContext *b, Extban *extban);
+extern Ban *is_banned(Client *, Channel *, int, const char **, const char **);
+extern Ban *is_banned_with_nick(Client *, Channel *, int, const char *, const char **, const char **);
-extern void ircd_log(int, FORMAT_STRING(const char *), ...) __attribute__((format(printf,2,3)));
-extern Client *find_client(char *, Client *);
-extern Client *find_name(char *, Client *);
-extern Client *find_nickserv(char *, Client *);
-extern Client *find_person(char *, Client *);
-extern Client *find_server(char *, Client *);
-extern Client *find_service(char *, Client *);
+extern Client *find_client(const char *, Client *);
+extern Client *find_name(const char *, Client *);
+extern Client *find_nickserv(const char *, Client *);
+extern Client *find_user(const char *, Client *);
+extern Client *find_server(const char *, Client *);
+extern Client *find_service(const char *, Client *);
#define find_server_quick(x) find_server(x, NULL)
extern char *find_or_add(char *);
extern void inittoken();
extern void reset_help();
extern MODVAR char *debugmode, *configfile, *sbrk0;
-extern char *getfield(char *);
-extern void set_sockhost(Client *, char *);
+extern void set_sockhost(Client *, const char *);
#ifdef _WIN32
-extern MODFUNC char *sock_strerror(int);
+extern const char *sock_strerror(int);
#endif
-extern int dgets(int, char *, int);
#ifdef _WIN32
extern MODVAR int debuglevel;
@@ -213,86 +225,111 @@ extern MODVAR int OpenFiles; /* number of files currently open */
extern MODVAR int debuglevel, portnum, debugtty, maxusersperchannel;
extern MODVAR int readcalls, udpfd, resfd;
extern Client *add_connection(ConfigItem_listen *, int);
-extern void add_local_domain(char *, int);
extern int check_server_init(Client *);
extern void close_connection(Client *);
extern void close_unbound_listeners();
-extern int connect_server(ConfigItem_link *, Client *, struct hostent *);
-extern void get_my_name(Client *, char *, int);
extern int get_sockerr(Client *);
extern int inetport(ConfigItem_listen *, char *, int, int);
extern void init_sys();
extern void check_user_limit(void);
extern void init_modef();
-extern int verify_hostname(char *name);
+extern int verify_hostname(const char *name);
-extern void report_error(char *, Client *);
extern int setup_ping();
extern void set_channel_mlock(Client *, Channel *, const char *, int);
-extern void restart(char *);
-extern void server_reboot(char *);
+extern void restart(const char *);
+extern void server_reboot(const char *);
extern void terminate(), write_pidfile();
extern void *safe_alloc(size_t size);
extern void set_socket_buffers(int fd, int rcvbuf, int sndbuf);
extern int send_queued(Client *);
extern void send_queued_cb(int fd, int revents, void *data);
-extern void sendto_connectnotice(Client *client, int disconnect, char *comment);
-extern void sendto_serv_butone_nickcmd(Client *one, Client *client, char *umodes);
-extern void sendto_message_one(Client *to, Client *from, char *sender,
- char *cmd, char *nick, char *msg);
-#define PREFIX_ALL 0
-#define PREFIX_HALFOP 0x1
-#define PREFIX_VOICE 0x2
-#define PREFIX_OP 0x4
-#define PREFIX_ADMIN 0x08
-#define PREFIX_OWNER 0x10
+extern void sendto_serv_butone_nickcmd(Client *one, MessageTag *mtags, Client *client, const char *umodes);
+extern void sendto_message_one(Client *to, Client *from, const char *sender, const char *cmd, const char *nick, const char *msg);
extern void sendto_channel(Channel *channel, Client *from, Client *skip,
- int prefix, long clicap, int sendflags,
+ char *member_modes, long clicap, int sendflags,
MessageTag *mtags,
FORMAT_STRING(const char *pattern), ...) __attribute__((format(printf,8,9)));
extern void sendto_local_common_channels(Client *user, Client *skip,
long clicap, MessageTag *mtags,
FORMAT_STRING(const char *pattern), ...) __attribute__((format(printf,5,6)));
extern void sendto_match_servs(Channel *, Client *, FORMAT_STRING(const char *), ...) __attribute__((format(printf,3,4)));
-extern void sendto_match_butone(Client *, Client *, char *, int, MessageTag *,
+extern void sendto_match_butone(Client *, Client *, const char *, int, MessageTag *,
FORMAT_STRING(const char *pattern), ...) __attribute__((format(printf,6,7)));
extern void sendto_all_butone(Client *, Client *, FORMAT_STRING(const char *), ...) __attribute__((format(printf,3,4)));
extern void sendto_ops(FORMAT_STRING(const char *), ...) __attribute__((format(printf,1,2)));
-extern void sendto_ops_butone(Client *, Client *, FORMAT_STRING(const char *), ...) __attribute__((format(printf,3,4)));
extern void sendto_prefix_one(Client *, Client *, MessageTag *, FORMAT_STRING(const char *), ...) __attribute__((format(printf,4,5)));
+extern void vsendto_prefix_one(Client *to, Client *from, MessageTag *mtags, const char *pattern, va_list vl);
extern void sendto_opers(FORMAT_STRING(const char *), ...) __attribute__((format(printf,1,2)));
extern void sendto_umode(int, FORMAT_STRING(const char *), ...) __attribute__((format(printf,2,3)));
extern void sendto_umode_global(int, FORMAT_STRING(const char *), ...) __attribute__((format(printf,2,3)));
-extern void sendto_snomask(int snomask, FORMAT_STRING(const char *pattern), ...) __attribute__((format(printf,2,3)));
-extern void sendto_snomask_global(int snomask, FORMAT_STRING(const char *pattern), ...) __attribute__((format(printf,2,3)));
extern void sendnotice(Client *to, FORMAT_STRING(const char *pattern), ...) __attribute__((format(printf,2,3)));
-extern void sendnumeric(Client *to, int numeric, ...);
+/** Send numeric message to a client.
+ * @param to The recipient
+ * @param numeric The numeric, one of RPL_* or ERR_*, see include/numeric.h
+ * @param ... The parameters for the numeric
+ * @note Be sure to provide the correct number and type of parameters that belong to the numeric. Check include/numeric.h when in doubt!
+ * @section sendnumeric_examples Examples
+ * @subsection sendnumeric_permission_denied Send "Permission Denied" numeric
+ * This numeric has no parameter, so is simple:
+ * @code
+ * sendnumeric(client, ERR_NOPRIVILEGES);
+ * @endcode
+ * @subsection sendnumeric_notenoughparameters Send "Not enough parameters" numeric
+ * This numeric requires 1 parameter: the name of the command.
+ * @code
+ * sendnumeric(client, ERR_NEEDMOREPARAMS, "SOMECOMMAND");
+ * @endcode
+ * @ingroup SendFunctions
+ */
+#define sendnumeric(to, numeric, ...) sendnumericfmt(to, numeric, STR_ ## numeric, ##__VA_ARGS__)
extern void sendnumericfmt(Client *to, int numeric, FORMAT_STRING(const char *pattern), ...) __attribute__((format(printf,3,4)));
+extern void sendtxtnumeric(Client *to, FORMAT_STRING(const char *pattern), ...) __attribute__((format(printf,2,3)));
+/** Build numeric message so it is ready to be sent to a client - rarely used, normally you use sendnumeric() instead.
+ * This function is normally only used in eg CAN_KICK and CAN_SET_TOPIC, where
+ * you need to set an 'errbuf' with a full IRC protocol line to reject the request
+ * (which then may or may not be sent depending on operoverride privileges).
+ * @param buf The buffer where the message should be stored to (full IRC protocol line)
+ * @param buflen The size of the buffer
+ * @param to The recipient
+ * @param numeric The numeric, one of RPL_* or ERR_*, see include/numeric.h
+ * @param ... The parameters for the numeric
+ * @note Be sure to provide the correct number and type of parameters that belong to the numeric. Check include/numeric.h when in doubt!
+ * @ingroup SendFunctions
+ */
+#define buildnumeric(buf, buflen, to, numeric, ...) buildnumericfmt(buf, buflen, to, numeric, STR_ ## numeric, ##__VA_ARGS__)
+extern void buildnumericfmt(char *buf, size_t buflen, Client *to, int numeric, FORMAT_STRING(const char *pattern), ...) __attribute__((format(printf,5,6)));
extern void sendto_server(Client *one, unsigned long caps, unsigned long nocaps, MessageTag *mtags, FORMAT_STRING(const char *format), ...) __attribute__((format(printf, 5, 6)));
-extern void sendto_ops_and_log(FORMAT_STRING(const char *pattern), ...) __attribute__((format(printf,1,2)));
-
+extern void send_raw_direct(Client *user, FORMAT_STRING(const char *pattern), ...) __attribute__((format(printf, 2, 3)));
extern MODVAR int writecalls, writeb[];
extern int deliver_it(Client *cptr, char *str, int len, int *want_read);
extern int target_limit_exceeded(Client *client, void *target, const char *name);
-extern char *canonize(char *buffer);
+extern char *canonize(const char *buffer);
extern int check_registered(Client *);
extern int check_registered_user(Client *);
-extern char *get_client_name(Client *, int);
-extern char *get_client_host(Client *);
-extern char *myctime(time_t);
-extern char *short_date(time_t, char *buf);
-extern char *long_date(time_t);
-extern void exit_client(Client *client, MessageTag *recv_mtags, char *comment);
-extern void exit_client_ex(Client *client, Client *origin, MessageTag *recv_mtags, char *comment);
-extern void initstats(), tstats(Client *, char *);
-extern char *check_string(char *);
-extern char *make_nick_user_host(char *, char *, char *);
-extern char *make_nick_user_host_r(char *namebuf, char *nick, char *name, char *host);
-extern char *make_user_host(char *, char *);
+extern const char *get_client_name(Client *, int);
+extern const char *get_client_host(Client *);
+extern const char *myctime(time_t);
+extern const char *short_date(time_t, char *buf);
+extern const char *long_date(time_t);
+extern const char *pretty_time_val(long);
+extern const char *pretty_time_val_r(char *buf, size_t buflen, long timeval);
+extern const char *pretty_date(time_t t);
+extern time_t server_time_to_unix_time(const char *tbuf);
+extern time_t rfc2616_time_to_unix_time(const char *tbuf);
+extern const char *rfc2616_time(time_t clock);
+extern void exit_client(Client *client, MessageTag *recv_mtags, const char *comment);
+extern void exit_client_fmt(Client *client, MessageTag *recv_mtags, FORMAT_STRING(const char *pattern), ...) __attribute__((format(printf, 3, 4)));
+extern void exit_client_ex(Client *client, Client *origin, MessageTag *recv_mtags, const char *comment);
+extern void initstats();
+extern const char *check_string(const char *);
+extern char *make_nick_user_host(const char *, const char *, const char *);
+extern char *make_nick_user_host_r(char *namebuf, size_t namebuflen, const char *nick, const char *name, const char *host);
+extern char *make_user_host(const char *, const char *);
extern void parse(Client *cptr, char *buffer, int length);
-extern int hunt_server(Client *, MessageTag *, char *, int, int, char **);
+extern int hunt_server(Client *, MessageTag *, const char *, int, int, const char **);
extern int cmd_server_estab(Client *);
extern void umode_init(void);
#define UMODE_GLOBAL 1
@@ -309,79 +346,68 @@ extern void free_client(Client *);
extern void free_link(Link *);
extern void free_ban(Ban *);
extern void free_user(Client *);
-extern int find_str_match_link(Link *, char *);
+extern int link_list_length(Link *lp);
+extern int find_str_match_link(Link *, const char *);
extern void free_str_list(Link *);
extern Link *make_link();
extern Ban *make_ban();
extern User *make_user(Client *);
extern Server *make_server();
extern Client *make_client(Client *, Client *);
+extern Channel *make_channel(const char *name);
extern Member *find_channel_link(Member *, Channel *);
-extern char *pretty_mask(char *);
+extern char *pretty_mask(const char *);
extern void add_client_to_list(Client *);
extern void remove_client_from_list(Client *);
-extern void initlists();
-extern struct hostent *get_res(char *);
-extern struct hostent *gethost_byaddr(char *, Link *);
-extern struct hostent *gethost_byname(char *, Link *);
+extern void initlists(void);
+extern void initlist_channels(void);
+extern struct hostent *get_res(const char *);
+extern struct hostent *gethost_byaddr(const char *, Link *);
+extern struct hostent *gethost_byname(const char *, Link *);
extern void flush_cache();
extern void init_resolver(int firsttime);
extern time_t timeout_query_list(time_t);
extern time_t expire_cache(time_t);
-extern void del_queries(char *);
+extern void del_queries(const char *);
/* Hash stuff */
#define NICK_HASH_TABLE_SIZE 32768
#define CHAN_HASH_TABLE_SIZE 32768
-#define WATCH_HASH_TABLE_SIZE 32768
#define WHOWAS_HASH_TABLE_SIZE 32768
#define THROTTLING_HASH_TABLE_SIZE 8192
-#define hash_find_channel find_channel
extern uint64_t siphash(const char *in, const char *k);
extern uint64_t siphash_raw(const char *in, size_t len, const char *k);
extern uint64_t siphash_nocase(const char *in, const char *k);
extern void siphash_generate_key(char *k);
extern void init_hash(void);
uint64_t hash_whowas_name(const char *name);
-extern int add_to_client_hash_table(char *, Client *);
-extern int del_from_client_hash_table(char *, Client *);
-extern int add_to_id_hash_table(char *, Client *);
-extern int del_from_id_hash_table(char *, Client *);
-extern int add_to_channel_hash_table(char *, Channel *);
-extern void del_from_channel_hash_table(char *, Channel *);
-extern int add_to_watch_hash_table(char *, Client *, int);
-extern int del_from_watch_hash_table(char *, Client *);
-extern int hash_check_watch(Client *, int);
-extern int hash_del_watch_list(Client *);
-extern void count_watch_memory(int *, u_long *);
-extern Watch *hash_get_watch(char *);
+extern int add_to_client_hash_table(const char *, Client *);
+extern int del_from_client_hash_table(const char *, Client *);
+extern int add_to_id_hash_table(const char *, Client *);
+extern int del_from_id_hash_table(const char *, Client *);
+extern int add_to_channel_hash_table(const char *, Channel *);
+extern void del_from_channel_hash_table(const char *, Channel *);
extern Channel *hash_get_chan_bucket(uint64_t);
extern Client *hash_find_client(const char *, Client *);
extern Client *hash_find_id(const char *, Client *);
extern Client *hash_find_nickatserver(const char *, Client *);
-extern Channel *find_channel(char *name, Channel *channel);
+extern Channel *find_channel(const char *name);
extern Client *hash_find_server(const char *, Client *);
extern struct MODVAR ThrottlingBucket *ThrottlingHash[THROTTLING_HASH_TABLE_SIZE];
-extern char *find_by_aln(char *);
-extern char *convert2aln(int);
-extern int convertfromaln(char *);
-extern char *find_server_aln(char *);
-extern time_t atime(char *xtime);
/* Mode externs
*/
-extern MODVAR long UMODE_INVISIBLE; /* 0x0001 makes user invisible */
-extern MODVAR long UMODE_OPER; /* 0x0002 Operator */
-extern MODVAR long UMODE_WALLOP; /* 0x0004 send wallops to them */
-extern MODVAR long UMODE_REGNICK; /* 0x0020 Nick set by services as registered */
-extern MODVAR long UMODE_SERVNOTICE;/* 0x0100 server notices such as kill */
-extern MODVAR long UMODE_HIDE; /* 0x8000 Hide from Nukes */
-extern MODVAR long UMODE_SECURE; /* 0x800000 User is a secure connect */
-extern MODVAR long UMODE_DEAF; /* 0x10000000 Deaf */
-extern MODVAR long UMODE_HIDEOPER; /* 0x20000000 Hide oper mode */
-extern MODVAR long UMODE_SETHOST; /* 0x40000000 used sethost */
+extern MODVAR long UMODE_INVISIBLE; /* makes user invisible */
+extern MODVAR long UMODE_OPER; /* Operator */
+extern MODVAR long UMODE_REGNICK; /* Nick set by services as registered */
+extern MODVAR long UMODE_SERVNOTICE;/* server notices such as kill */
+extern MODVAR long UMODE_HIDE; /* Hide from Nukes */
+extern MODVAR long UMODE_SECURE; /* User is a secure connect */
+extern MODVAR long UMODE_DEAF; /* Deaf */
+extern MODVAR long UMODE_HIDEOPER; /* Hide oper mode */
+extern MODVAR long UMODE_SETHOST; /* used sethost */
extern MODVAR long UMODE_HIDLE; /* hides oper idle times */
extern MODVAR long AllUmodes, SendUmodes;
@@ -403,24 +429,32 @@ extern MODVAR long SNO_OPER;
#ifndef HAVE_STRLCPY
extern size_t strlcpy(char *dst, const char *src, size_t size);
#endif
+#ifndef HAVE_STRLNCPY
+extern size_t strlncpy(char *dst, const char *src, size_t size, size_t n);
+#endif
#ifndef HAVE_STRLCAT
extern size_t strlcat(char *dst, const char *src, size_t size);
#endif
#ifndef HAVE_STRLNCAT
extern size_t strlncat(char *dst, const char *src, size_t size, size_t n);
#endif
+extern void strlcat_letter(char *buf, char c, size_t buflen);
extern char *strldup(const char *src, size_t n);
extern void dopacket(Client *, char *, int);
extern void debug(int, FORMAT_STRING(const char *), ...) __attribute__((format(printf,2,3)));
#if defined(DEBUGMODE)
-extern void send_usage(Client *, char *);
-extern void count_memory(Client *, char *);
-extern int checkprotoflags(Client *, int, char *, int);
+extern void send_usage(Client *, const char *);
+extern void count_memory(Client *, const char *);
+extern int checkprotoflags(Client *, int, const char *, int);
#endif
-extern char *inetntop(int af, const void *in, char *local_dummy, size_t the_size);
+extern const char *inetntop(int af, const void *in, char *local_dummy, size_t the_size);
+
+extern void delletterfromstring(char *s, char letter);
+extern void addlettertodynamicstringsorted(char **str, char letter);
+extern int sort_character_lowercase_before_uppercase(char x, char y);
/* Internal command stuff - not for modules */
extern MODVAR RealCommand *CommandHash[256];
@@ -442,25 +476,19 @@ extern void close_connections(void);
extern int b64_encode(unsigned char const *src, size_t srclength, char *target, size_t targsize);
extern int b64_decode(char const *src, unsigned char *target, size_t targsize);
-extern AuthenticationType Auth_FindType(char *hash, char *type);
+extern AuthenticationType Auth_FindType(const char *hash, const char *type);
extern AuthConfig *AuthBlockToAuthConfig(ConfigEntry *ce);
extern void Auth_FreeAuthConfig(AuthConfig *as);
-extern int Auth_Check(Client *cptr, AuthConfig *as, char *para);
-extern char *Auth_Hash(int type, char *para);
+extern int Auth_Check(Client *cptr, AuthConfig *as, const char *para);
+extern const char *Auth_Hash(int type, const char *para);
extern int Auth_CheckError(ConfigEntry *ce);
-extern int Auth_AutoDetectHashType(char *hash);
+extern int Auth_AutoDetectHashType(const char *hash);
-extern void make_cloakedhost(Client *client, char *curr, char *buf, size_t buflen);
-extern int channel_canjoin(Client *client, char *name);
+extern void make_cloakedhost(Client *client, const char *curr, char *buf, size_t buflen);
+extern int channel_canjoin(Client *client, const char *name);
extern char *collapse(char *pattern);
extern void dcc_sync(Client *client);
-extern void report_flines(Client *client);
-extern void report_network(Client *client);
-extern void report_dynconf(Client *client);
-extern void count_memory(Client *cptr, char *nick);
-extern void list_scache(Client *client);
-extern char *oflagstr(long oflag);
-extern int rehash(Client *client, int sig);
+extern void request_rehash(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);
@@ -468,23 +496,19 @@ extern int add_listener(ConfigItem_listen *conf);
extern void link_cleanup(ConfigItem_link *link_ptr);
extern void listen_cleanup();
extern int numeric_collides(long numeric);
-extern u_long cres_mem(Client *client, char *nick);
extern void flag_add(char ch);
extern void flag_del(char ch);
extern void init_dynconf(void);
-extern char *pretty_time_val(long);
-extern char *pretty_date(time_t t);
-extern int init_conf(char *filename, int rehash);
-extern void validate_configuration(void);
-extern void run_configuration(void);
+extern int config_read_start(void);
+extern int is_config_read_finished(void);
+extern int config_test(void);
+extern void config_run(void);
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 stripcrlf(char *line);
-extern time_t rfc2time(char *s);
-extern char *rfctime(time_t t, char *buf);
extern int strnatcmp(char const *a, char const *b);
extern int strnatcasecmp(char const *a, char const *b);
extern void outofmemory(size_t bytes);
@@ -509,7 +533,7 @@ extern void *safe_alloc(size_t size);
* @param dst The current pointer and the pointer where a new copy of the string will be stored.
* @param str The string you want to copy
*/
-#define safe_strdup(dst,str) do { if (dst) free(dst); if (!(str)) dst = NULL; else dst = our_strdup(str); } while(0)
+#define safe_strdup(dst,str) do { if (dst) free(dst); if ((str) == NULL) dst = NULL; else dst = our_strdup(str); } while(0)
/** Return a copy of the string. Do not free any existing memory.
* @param str The string to duplicate
@@ -573,7 +597,7 @@ extern char *our_strdup(const char *str);
extern char *our_strldup(const char *str, size_t max);
extern char *our_strdup_sensitive(const char *str);
-extern long config_checkval(char *value, unsigned short flags);
+extern long config_checkval(const char *value, unsigned short flags);
extern void config_status(FORMAT_STRING(const char *format), ...) __attribute__((format(printf,1,2)));
extern void init_random();
extern u_char getrandom8();
@@ -581,10 +605,15 @@ extern uint16_t getrandom16();
extern uint32_t getrandom32();
extern void gen_random_alnum(char *buf, int numbytes);
+/* Check config entry for empty/missing parameter */
+#define CheckNull(x) if ((!(x)->value) || (!(*((x)->value)))) { config_error("%s:%i: missing parameter", (x)->file->filename, (x)->line_number); errors++; continue; }
+/* as above, but accepting empty string */
+#define CheckNullAllowEmpty(x) if ((!(x)->value)) { config_error("%s:%i: missing parameter", (x)->file->filename, (x)->line_number); errors++; continue; }
+
extern MODVAR char extchmstr[4][64];
-extern int extcmode_default_requirechop(Client *, Channel *, char, char *, int, int);
-extern int extcmode_default_requirehalfop(Client *, Channel *, char, char *, int, int);
+extern int extcmode_default_requirechop(Client *, Channel *, char, const char *, int, int);
+extern int extcmode_default_requirehalfop(Client *, Channel *, char, const char *, int, int);
extern Cmode_t extcmode_get(Cmode *);
extern void extcmode_init(void);
extern void make_extcmodestr();
@@ -592,8 +621,7 @@ extern void extcmode_duplicate_paramlist(void **xi, void **xo);
extern void extcmode_free_paramlist(void **ar);
extern void chmode_str(struct ChMode *, char *, char *, size_t, size_t);
-extern char *get_client_status(Client *);
-extern char *get_snomask_string_raw(long);
+extern const char *get_client_status(Client *);
extern void SocketLoop(void *);
#ifdef _WIN32
extern void InitDebug(void);
@@ -605,54 +633,46 @@ extern void CleanUp(void);
extern int CountRTFSize(unsigned char *buffer);
extern void IRCToRTF(unsigned char *buffer, unsigned char *string);
#endif
-extern void sendto_chmodemucrap(Client *, Channel *, char *);
-extern void verify_opercount(Client *, char *);
-extern int valid_host(char *host);
-extern int count_oper_sessions(char *);
+extern void verify_opercount(Client *, const char *);
+extern int valid_host(const char *host, int strict);
+extern int count_oper_sessions(const char *);
extern char *unreal_mktemp(const char *dir, const char *suffix);
-extern char *unreal_getpathname(char *filepath, char *path);
-extern char *unreal_getfilename(char *path);
-extern char *unreal_getmodfilename(char *path);
-extern char *unreal_mkcache(const char *url);
-extern int has_cached_version(const char *url);
+extern char *unreal_getpathname(const char *filepath, char *path);
+extern const char *unreal_getfilename(const char *path);
+extern const char *unreal_getmodfilename(const char *path);
extern int unreal_copyfile(const char *src, const char *dest);
extern int unreal_copyfileex(const char *src, const char *dest, int tryhardlink);
extern time_t unreal_getfilemodtime(const char *filename);
extern void unreal_setfilemodtime(const char *filename, time_t mtime);
extern void DeleteTempModules(void);
extern MODVAR Extban *extbaninfo;
-extern Extban *findmod_by_bantype(char c);
+extern Extban *findmod_by_bantype(const char *str, const char **remainder);
extern Extban *ExtbanAdd(Module *reserved, ExtbanInfo req);
extern void ExtbanDel(Extban *);
extern void extban_init(void);
extern char *trim_str(char *str, int len);
extern MODVAR char *ban_realhost, *ban_virthost, *ban_ip;
-extern BanAction banact_stringtoval(char *s);
-extern char *banact_valtostring(BanAction val);
+extern BanAction banact_stringtoval(const char *s);
+extern const char *banact_valtostring(BanAction val);
extern BanAction banact_chartoval(char c);
extern char banact_valtochar(BanAction val);
-extern int spamfilter_gettargets(char *s, Client *client);
+extern int spamfilter_gettargets(const char *s, Client *client);
extern char *spamfilter_target_inttostring(int v);
-extern Spamfilter *unreal_buildspamfilter(char *s);
-extern char *our_strcasestr(char *haystack, char *needle);
-extern int spamfilter_getconftargets(char *s);
-extern void remove_oper_snomasks(Client *client);
+extern char *our_strcasestr(const char *haystack, const char *needle);
+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 Channel *get_channel(Client *cptr, char *chname, int flag);
extern MODVAR char backupbuf[];
-extern void add_invite(Client *, Client *, Channel *, MessageTag *);
-extern void del_invite(Client *, Channel *);
extern int is_invited(Client *client, Channel *channel);
-extern void channel_modes(Client *cptr, char *mbuf, char *pbuf, size_t mbuf_size, size_t pbuf_size, Channel *channel);
-extern MODVAR char modebuf[BUFSIZE], parabuf[BUFSIZE];
-extern int op_can_override(char *acl, Client *client,Channel *channel,void* extra);
-extern Client *find_chasing(Client *client, char *user, int *chasing);
+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);
+extern Client *find_chasing(Client *client, const char *user, int *chasing);
extern MODVAR long opermode;
extern MODVAR long sajoinmode;
-extern void add_user_to_channel(Channel *channel, Client *who, int flags);
-extern int add_banid(Client *, Channel *, char *);
-extern int add_exbanid(Client *cptr, Channel *channel, char *banid);
+extern void add_user_to_channel(Channel *channel, Client *who, const char *modes);
+extern int add_banid(Client *, Channel *, const char *);
+extern int add_exbanid(Client *cptr, Channel *channel, const char *banid);
extern int sub1_from_channel(Channel *);
extern MODVAR CoreChannelModeTable corechannelmodetable[];
extern char *unreal_encodespace(char *s);
@@ -664,10 +684,9 @@ extern int callbacks_check(void);
extern void callbacks_switchover(void);
extern int efunctions_check(void);
extern void efunctions_switchover(void);
-extern char *encode_ip(char *);
-extern char *decode_ip(char *);
-extern void sendto_fconnectnotice(Client *client, int disconnect, char *comment);
-extern void sendto_one_nickcmd(Client *server, Client *client, char *umodes);
+extern const char *encode_ip(const char *);
+extern const char *decode_ip(const char *);
+extern void sendto_one_nickcmd(Client *server, MessageTag *mtags, Client *client, const char *umodes);
extern int on_dccallow_list(Client *to, Client *from);
extern int add_dccallow(Client *client, Client *optr);
extern int del_dccallow(Client *client, Client *optr);
@@ -677,7 +696,7 @@ extern void del_async_connects(void);
extern void isupport_init(void);
extern void clicap_init(void);
extern void efunctions_init(void);
-extern void do_cmd(Client *client, MessageTag *mtags, char *cmd, int parc, char *parv[]);
+extern void do_cmd(Client *client, MessageTag *mtags, const char *cmd, int parc, const char *parv[]);
extern MODVAR char *me_hash;
extern MODVAR int dontspread;
extern MODVAR int labeled_response_inhibit;
@@ -685,33 +704,35 @@ extern MODVAR int labeled_response_inhibit_end;
extern MODVAR int labeled_response_force;
/* Efuncs */
-extern MODVAR void (*do_join)(Client *, int, char **);
-extern MODVAR void (*join_channel)(Channel *channel, Client *client, MessageTag *mtags, int flags);
-extern MODVAR int (*can_join)(Client *client, Channel *channel, char *key, char *parv[]);
-extern MODVAR void (*do_mode)(Channel *channel, Client *client, MessageTag *mtags, int parc, char *parv[], time_t sendts, int samode);
-extern MODVAR void (*set_mode)(Channel *channel, Client *cptr, int parc, char *parv[], u_int *pcount,
- char pvar[MAXMODEPARAMS][MODEBUFLEN + 3], int bounce);
-extern MODVAR void (*cmd_umode)(Client *, MessageTag *, int, char **);
-extern MODVAR int (*register_user)(Client *client, char *nick, char *username, char *umode, char *virthost, char *ip);
+extern MODVAR void (*do_join)(Client *, int, const char **);
+extern MODVAR void (*join_channel)(Channel *channel, Client *client, MessageTag *mtags, const char *flags);
+extern MODVAR int (*can_join)(Client *client, Channel *channel, const char *key, char **errmsg);
+extern MODVAR void (*do_mode)(Channel *channel, Client *client, MessageTag *mtags, int parc, const char *parv[], time_t sendts, int samode);
+extern MODVAR MultiLineMode *(*set_mode)(Channel *channel, Client *cptr, int parc, const char *parv[], u_int *pcount,
+ char pvar[MAXMODEPARAMS][MODEBUFLEN + 3]);
+extern MODVAR void (*set_channel_mode)(Channel *channel, char *modes, char *parameters);
+extern MODVAR void (*cmd_umode)(Client *, MessageTag *, int, const char **);
+extern MODVAR int (*register_user)(Client *client);
extern MODVAR int (*tkl_hash)(unsigned int c);
extern MODVAR char (*tkl_typetochar)(int type);
extern MODVAR int (*tkl_chartotype)(char c);
-extern MODVAR char *(*tkl_type_string)(TKL *tk);
-extern MODVAR TKL *(*tkl_add_serverban)(int type, char *usermask, char *hostmask, char *reason, char *setby,
+extern MODVAR const char *(*tkl_type_string)(TKL *tk);
+extern MODVAR const char *(*tkl_type_config_string)(TKL *tk);
+extern MODVAR TKL *(*tkl_add_serverban)(int type, const char *usermask, const char *hostmask, const char *reason, const char *setby,
time_t expire_at, time_t set_at, int soft, int flags);
-extern MODVAR TKL *(*tkl_add_banexception)(int type, char *usermask, char *hostmask, char *reason, char *set_by,
- time_t expire_at, time_t set_at, int soft, char *bantypes, int flags);
-extern MODVAR TKL *(*tkl_add_nameban)(int type, char *name, int hold, char *reason, char *setby,
+extern MODVAR TKL *(*tkl_add_banexception)(int type, const char *usermask, const char *hostmask, const char *reason, const char *set_by,
+ time_t expire_at, time_t set_at, int soft, const char *bantypes, int flags);
+extern MODVAR TKL *(*tkl_add_nameban)(int type, const char *name, int hold, const char *reason, const char *setby,
time_t expire_at, time_t set_at, int flags);
-extern MODVAR TKL *(*tkl_add_spamfilter)(int type, unsigned short target, unsigned short action, Match *match, char *setby,
+extern MODVAR TKL *(*tkl_add_spamfilter)(int type, unsigned short target, unsigned short action, Match *match, const char *setby,
time_t expire_at, time_t set_at,
- time_t spamf_tkl_duration, char *spamf_tkl_reason,
+ time_t spamf_tkl_duration, const char *spamf_tkl_reason,
int flags);
-extern MODVAR TKL *(*find_tkl_serverban)(int type, char *usermask, char *hostmask, int softban);
-extern MODVAR TKL *(*find_tkl_banexception)(int type, char *usermask, char *hostmask, int softban);
-extern MODVAR TKL *(*find_tkl_nameban)(int type, char *name, int hold);
-extern MODVAR TKL *(*find_tkl_spamfilter)(int type, char *match_string, unsigned short action, unsigned short target);
-extern MODVAR void (*sendnotice_tkl_del)(char *removed_by, TKL *tkl);
+extern MODVAR TKL *(*find_tkl_serverban)(int type, const char *usermask, const char *hostmask, int softban);
+extern MODVAR TKL *(*find_tkl_banexception)(int type, const char *usermask, const char *hostmask, int softban);
+extern MODVAR TKL *(*find_tkl_nameban)(int type, const char *name, int hold);
+extern MODVAR TKL *(*find_tkl_spamfilter)(int type, const char *match_string, unsigned short action, unsigned short target);
+extern MODVAR void (*sendnotice_tkl_del)(const char *removed_by, TKL *tkl);
extern MODVAR void (*sendnotice_tkl_add)(TKL *tkl);
extern MODVAR void (*free_tkl)(TKL *tkl);
extern MODVAR TKL *(*tkl_del_line)(TKL *tkl);
@@ -719,50 +740,53 @@ extern MODVAR void (*tkl_check_local_remove_shun)(TKL *tmp);
extern MODVAR int (*find_tkline_match)(Client *cptr, int skip_soft);
extern MODVAR int (*find_shun)(Client *cptr);
extern MODVAR int (*find_spamfilter_user)(Client *client, int flags);
-extern MODVAR TKL *(*find_qline)(Client *cptr, char *nick, int *ishold);
+extern MODVAR TKL *(*find_qline)(Client *cptr, const char *nick, int *ishold);
extern MODVAR TKL *(*find_tkline_match_zap)(Client *cptr);
-extern MODVAR void (*tkl_stats)(Client *cptr, int type, char *para, int *cnt);
+extern MODVAR void (*tkl_stats)(Client *cptr, int type, const char *para, int *cnt);
extern MODVAR void (*tkl_sync)(Client *client);
-extern MODVAR void (*cmd_tkl)(Client *client, MessageTag *recv_mtags, int parc, char *parv[]);
-extern MODVAR int (*place_host_ban)(Client *client, BanAction action, char *reason, long duration);
-extern MODVAR int (*match_spamfilter)(Client *client, char *str_in, int type, char *cmd, char *target, int flags, TKL **rettk);
-extern MODVAR int (*match_spamfilter_mtags)(Client *client, MessageTag *mtags, char *cmd);
+extern MODVAR void (*cmd_tkl)(Client *client, MessageTag *recv_mtags, int parc, const char *parv[]);
+extern MODVAR int (*place_host_ban)(Client *client, BanAction action, const char *reason, long duration);
+extern MODVAR int (*match_spamfilter)(Client *client, const char *str_in, int type, const char *cmd, const char *target, int flags, TKL **rettk);
+extern MODVAR int (*match_spamfilter_mtags)(Client *client, MessageTag *mtags, const char *cmd);
extern MODVAR int (*join_viruschan)(Client *client, TKL *tk, int type);
-extern MODVAR unsigned char *(*StripColors)(unsigned char *text);
-extern MODVAR const char *(*StripControlCodes)(unsigned char *text);
-extern MODVAR void (*spamfilter_build_user_string)(char *buf, char *nick, Client *acptr);
+extern MODVAR const char *(*StripColors)(const char *text);
+extern MODVAR const char *(*StripControlCodes)(const char *text);
+extern MODVAR void (*spamfilter_build_user_string)(char *buf, const char *nick, Client *acptr);
extern MODVAR void (*send_protoctl_servers)(Client *client, int response);
-extern MODVAR int (*verify_link)(Client *client, char *servername, ConfigItem_link **link_out);
+extern MODVAR int (*verify_link)(Client *client, ConfigItem_link **link_out);
extern MODVAR void (*send_server_message)(Client *client);
extern MODVAR void (*broadcast_md_client)(ModDataInfo *mdi, Client *acptr, ModData *md);
extern MODVAR void (*broadcast_md_channel)(ModDataInfo *mdi, Channel *channel, ModData *md);
extern MODVAR void (*broadcast_md_member)(ModDataInfo *mdi, Channel *channel, Member *m, ModData *md);
extern MODVAR void (*broadcast_md_membership)(ModDataInfo *mdi, Client *acptr, Membership *m, ModData *md);
-extern MODVAR void (*broadcast_md_client_cmd)(Client *except, Client *sender, Client *acptr, char *varname, char *value);
-extern MODVAR void (*broadcast_md_channel_cmd)(Client *except, Client *sender, Channel *channel, char *varname, char *value);
-extern MODVAR void (*broadcast_md_member_cmd)(Client *except, Client *sender, Channel *channel, Client *acptr, char *varname, char *value);
-extern MODVAR void (*broadcast_md_membership_cmd)(Client *except, Client *sender, Client *acptr, Channel *channel, char *varname, char *value);
+extern MODVAR void (*broadcast_md_client_cmd)(Client *except, Client *sender, Client *acptr, const char *varname, const char *value);
+extern MODVAR void (*broadcast_md_channel_cmd)(Client *except, Client *sender, Channel *channel, const char *varname, const char *value);
+extern MODVAR void (*broadcast_md_member_cmd)(Client *except, Client *sender, Channel *channel, Client *acptr, const char *varname, const char *value);
+extern MODVAR void (*broadcast_md_membership_cmd)(Client *except, Client *sender, Client *acptr, Channel *channel, const char *varname, const char *value);
+extern MODVAR void (*moddata_add_s2s_mtags)(Client *client, MessageTag **mtags);
+extern MODVAR void (*moddata_extract_s2s_mtags)(Client *client, MessageTag *mtags);
extern MODVAR void (*send_moddata_client)(Client *srv, Client *acptr);
extern MODVAR void (*send_moddata_channel)(Client *srv, Channel *channel);
extern MODVAR void (*send_moddata_members)(Client *srv);
extern MODVAR void (*broadcast_moddata_client)(Client *acptr);
extern MODVAR int (*check_banned)(Client *cptr, int exitflags);
extern MODVAR void (*introduce_user)(Client *to, Client *acptr);
-extern MODVAR int (*check_deny_version)(Client *cptr, char *software, int protocol, char *flags);
-extern MODVAR int (*match_user)(char *rmask, Client *acptr, int options);
+extern MODVAR int (*check_deny_version)(Client *cptr, const char *software, int protocol, const char *flags);
+extern MODVAR int (*match_user)(const char *rmask, Client *acptr, int options);
extern MODVAR void (*userhost_save_current)(Client *client);
extern MODVAR void (*userhost_changed)(Client *client);
extern MODVAR void (*send_join_to_local_users)(Client *client, Channel *channel, MessageTag *mtags);
extern MODVAR int (*do_nick_name)(char *nick);
extern MODVAR int (*do_remote_nick_name)(char *nick);
-extern MODVAR char *(*charsys_get_current_languages)(void);
+extern MODVAR const char *(*charsys_get_current_languages)(void);
extern MODVAR void (*broadcast_sinfo)(Client *acptr, Client *to, Client *except);
+extern MODVAR void (*connect_server)(ConfigItem_link *aconf, Client *by, struct hostent *hp);
extern MODVAR void (*parse_message_tags)(Client *cptr, char **str, MessageTag **mtag_list);
-extern MODVAR char *(*mtags_to_string)(MessageTag *m, Client *acptr);
-extern MODVAR int (*can_send_to_channel)(Client *cptr, Channel *channel, char **msgtext, char **errmsg, int notice);
+extern MODVAR const char *(*mtags_to_string)(MessageTag *m, Client *acptr);
+extern MODVAR int (*can_send_to_channel)(Client *cptr, Channel *channel, const char **msgtext, const char **errmsg, int notice);
extern MODVAR void (*broadcast_md_globalvar)(ModDataInfo *mdi, ModData *md);
-extern MODVAR void (*broadcast_md_globalvar_cmd)(Client *except, Client *sender, char *varname, char *value);
-extern MODVAR int (*tkl_ip_hash)(char *ip);
+extern MODVAR void (*broadcast_md_globalvar_cmd)(Client *except, Client *sender, const char *varname, const char *value);
+extern MODVAR int (*tkl_ip_hash)(const char *ip);
extern MODVAR int (*tkl_ip_hash_type)(int type);
extern MODVAR int (*find_tkl_exception)(int ban_type, Client *cptr);
extern MODVAR int (*del_silence)(Client *client, const char *mask);
@@ -771,109 +795,118 @@ extern MODVAR int (*is_silenced)(Client *client, Client *acptr);
extern MODVAR void *(*labeled_response_save_context)(void);
extern MODVAR void (*labeled_response_set_context)(void *ctx);
extern MODVAR void (*labeled_response_force_end)(void);
-extern MODVAR void (*kick_user)(MessageTag *mtags, Channel *channel, Client *client, Client *victim, char *comment);
+extern MODVAR void (*kick_user)(MessageTag *mtags, Channel *channel, Client *client, Client *victim, const char *comment);
+extern MODVAR int (*watch_add)(const char *nick, Client *client, int flags);
+extern MODVAR int (*watch_del)(const char *nick, Client *client, int flags);
+extern MODVAR int (*watch_del_list)(Client *client, int flags);
+extern MODVAR Watch *(*watch_get)(const char *nick);
+extern MODVAR int (*watch_check)(Client *client, int reply, int (*watch_notify)(Client *client, Watch *watch, Link *lp, int event));
+extern MODVAR char *(*tkl_uhost)(TKL *tkl, char *buf, size_t buflen, int options);
+extern MODVAR void (*do_unreal_log_remote_deliver)(LogLevel loglevel, const char *subsystem, const char *event_id, MultiLine *msg, const char *json_serialized);
+extern MODVAR char *(*get_chmodes_for_user)(Client *client, const char *flags);
+extern MODVAR WhoisConfigDetails (*whois_get_policy)(Client *client, Client *target, const char *name);
/* /Efuncs */
-/* SSL/TLS functions */
-extern int early_init_ssl();
-extern int init_ssl();
+/* TLS functions */
+extern int early_init_tls();
+extern int init_tls();
extern int ssl_handshake(Client *); /* Handshake the accpeted con.*/
extern int ssl_client_handshake(Client *, ConfigItem_link *); /* and the initiated con.*/
-extern int ircd_SSL_accept(Client *acptr, int fd);
-extern int ircd_SSL_connect(Client *acptr, int fd);
+extern int unreal_tls_accept(Client *acptr, int fd);
+extern int unreal_tls_connect(Client *acptr, int fd);
extern int SSL_smart_shutdown(SSL *ssl);
-extern void ircd_SSL_client_handshake(int, int, void *);
+extern const char *ssl_error_str(int err, int my_errno);
+extern void unreal_tls_client_handshake(int, int, void *);
extern void SSL_set_nonblocking(SSL *s);
extern SSL_CTX *init_ctx(TLSOptions *tlsoptions, int server);
-extern MODFUNC char *tls_get_cipher(SSL *ssl);
+extern const char *tls_get_cipher(Client *client);
extern TLSOptions *get_tls_options_for_client(Client *acptr);
extern int outdated_tls_client(Client *acptr);
-extern char *outdated_tls_client_build_string(char *pattern, Client *acptr);
+extern const char *outdated_tls_client_build_string(const char *pattern, Client *acptr);
extern int check_certificate_expiry_ctx(SSL_CTX *ctx, char **errstr);
extern EVENT(tls_check_expiry);
-/* End of SSL/TLS functions */
+extern MODVAR EVP_MD *sha256_function;
+extern MODVAR EVP_MD *sha1_function;
+extern MODVAR EVP_MD *md5_function;
+/* End of TLS functions */
extern void parse_message_tags_default_handler(Client *client, char **str, MessageTag **mtag_list);
-extern char *mtags_to_string_default_handler(MessageTag *m, Client *client);
+extern const char *mtags_to_string_default_handler(MessageTag *m, Client *client);
extern void *labeled_response_save_context_default_handler(void);
extern void labeled_response_set_context_default_handler(void *ctx);
extern void labeled_response_force_end_default_handler(void);
extern int add_silence_default_handler(Client *client, const char *mask, int senderr);
extern int del_silence_default_handler(Client *client, const char *mask);
extern int is_silenced_default_handler(Client *client, Client *acptr);
+extern void do_unreal_log_remote_deliver_default_handler(LogLevel loglevel, const char *subsystem, const char *event_id, MultiLine *msg, const char *json_serialized);
extern MODVAR MOTDFile opermotd, svsmotd, motd, botmotd, smotd, rules;
extern MODVAR int max_connection_count;
-extern int add_listmode(Ban **list, Client *cptr, Channel *channel, char *banid);
-extern int add_listmode_ex(Ban **list, Client *cptr, Channel *channel, char *banid, char *setby, time_t seton);
-extern int del_listmode(Ban **list, Channel *channel, char *banid);
+extern int add_listmode(Ban **list, Client *cptr, Channel *channel, const char *banid);
+extern int add_listmode_ex(Ban **list, Client *cptr, Channel *channel, const char *banid, const char *setby, time_t seton);
+extern int del_listmode(Ban **list, Channel *channel, const char *banid);
extern int Halfop_mode(long mode);
-extern char *clean_ban_mask(char *, int, Client *);
+extern const char *clean_ban_mask(const char *, int, Client *, int);
extern int find_invex(Channel *channel, Client *client);
extern void DoMD5(char *mdout, const char *src, unsigned long n);
extern char *md5hash(char *dst, const char *src, unsigned long n);
extern char *sha256hash(char *dst, const char *src, unsigned long n);
+extern void sha256hash_binary(char *dst, const char *src, unsigned long n);
+extern void sha1hash_binary(char *dst, const char *src, unsigned long n);
extern MODVAR TKL *tklines[TKLISTLEN];
extern MODVAR TKL *tklines_ip_hash[TKLIPHASHLEN1][TKLIPHASHLEN2];
-extern char *cmdname_by_spamftarget(int target);
+extern const char *cmdname_by_spamftarget(int target);
extern void unrealdns_delreq_bycptr(Client *cptr);
-extern void sendtxtnumeric(Client *to, FORMAT_STRING(const char *pattern), ...) __attribute__((format(printf,2,3)));
-extern void unrealdns_gethostbyname_link(char *name, ConfigItem_link *conf, int ipv4_only);
+extern void unrealdns_gethostbyname_link(const char *name, ConfigItem_link *conf, int ipv4_only);
extern void unrealdns_delasyncconnects(void);
-extern int is_autojoin_chan(char *chname);
+extern int is_autojoin_chan(const char *chname);
extern void unreal_free_hostent(struct hostent *he);
-extern struct hostent *unreal_create_hostent(char *name, char *ip);
-extern char *unreal_time_sync_error(void);
+extern struct hostent *unreal_create_hostent(const char *name, const char *ip);
+extern const char *unreal_time_sync_error(void);
extern int unreal_time_synch(int timeout);
-extern char *getcloak(Client *client);
+extern const char *getcloak(Client *client);
extern MODVAR unsigned char param_to_slot_mapping[256];
-extern char *cm_getparameter(Channel *channel, char mode);
-extern void cm_putparameter(Channel *channel, char mode, char *str);
+extern const char *cm_getparameter(Channel *channel, char mode);
+extern const char *cm_getparameter_ex(void **p, char mode);
+extern void cm_putparameter(Channel *channel, char mode, const char *str);
+extern void cm_putparameter_ex(void **p, char mode, const char *str);
extern void cm_freeparameter(Channel *channel, char mode);
-extern char *cm_getparameter_ex(void **p, char mode);
-extern void cm_putparameter_ex(void **p, char mode, char *str);
extern void cm_freeparameter_ex(void **p, char mode, char *str);
-extern int file_exists(char *file);
-extern time_t get_file_time(char *fname);
-extern long get_file_size(char *fname);
+extern int file_exists(const char *file);
+extern time_t get_file_time(const char *fname);
+extern long get_file_size(const char *fname);
extern void free_motd(MOTDFile *motd); /* s_serv.c */
extern void fix_timers(void);
-extern char *chfl_to_sjoin_symbol(int s);
+extern const char *chfl_to_sjoin_symbol(int s);
extern char chfl_to_chanmode(int s);
-extern void add_pending_net(Client *client, char *str);
+extern void add_pending_net(Client *client, const char *str);
extern void free_pending_net(Client *client);
extern Client *find_non_pending_net_duplicates(Client *cptr);
-extern PendingNet *find_pending_net_by_sid_butone(char *sid, Client *exempt);
+extern PendingNet *find_pending_net_by_sid_butone(const char *sid, Client *exempt);
extern Client *find_pending_net_duplicates(Client *cptr, Client **srv, char **sid);
extern MODVAR char serveropts[];
extern MODVAR char *ISupportStrings[];
extern void read_packet(int fd, int revents, void *data);
extern int process_packet(Client *cptr, char *readbuf, int length, int killsafely);
-extern void sendto_realops_and_log(FORMAT_STRING(const char *fmt), ...) __attribute__((format(printf,1,2)));
-extern int parse_chanmode(ParseMode *pm, char *modebuf_in, char *parabuf_in);
-extern void config_report_ssl_error(void);
-extern int dead_socket(Client *to, char *notice);
-extern Match *unreal_create_match(MatchType type, char *str, char **error);
+extern int parse_chanmode(ParseMode *pm, const char *modebuf_in, const char *parabuf_in);
+extern int dead_socket(Client *to, const char *notice);
+extern Match *unreal_create_match(MatchType type, const char *str, char **error);
extern void unreal_delete_match(Match *m);
-extern int unreal_match(Match *m, char *str);
-extern int unreal_match_method_strtoval(char *str);
+extern int unreal_match(Match *m, const char *str);
+extern int unreal_match_method_strtoval(const char *str);
extern char *unreal_match_method_valtostr(int val);
-extern int mixed_network(void);
extern void unreal_delete_masks(ConfigItem_mask *m);
extern void unreal_add_masks(ConfigItem_mask **head, ConfigEntry *ce);
extern int unreal_mask_match(Client *acptr, ConfigItem_mask *m);
-extern char *our_strcasestr(char *haystack, char *needle);
-extern void update_conf(void);
-extern MODVAR int need_34_upgrade;
+extern int unreal_mask_match_string(const char *name, ConfigItem_mask *m);
#ifdef _WIN32
extern MODVAR BOOL IsService;
#endif
-extern int match_ip46(char *a, char *b);
extern void extcmodes_check_for_changes(void);
extern void umodes_check_for_changes(void);
-extern int config_parse_flood(char *orig, int *times, int *period);
-extern int swhois_add(Client *acptr, char *tag, int priority, char *swhois, Client *from, Client *skip);
-extern int swhois_delete(Client *acptr, char *tag, char *swhois, Client *from, Client *skip);
+extern int config_parse_flood(const char *orig, int *times, int *period);
+extern int swhois_add(Client *acptr, const char *tag, int priority, const char *swhois, Client *from, Client *skip);
+extern int swhois_delete(Client *acptr, const char *tag, const char *swhois, Client *from, Client *skip);
extern void remove_oper_privileges(Client *client, int broadcast_mode_change);
extern int client_starttls(Client *acptr);
extern void start_server_handshake(Client *cptr);
@@ -882,21 +915,21 @@ 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, char *ip, int port, int ipv6);
-extern int unreal_connect(int fd, char *ip, int port, int ipv6);
-extern int is_valid_ip(char *str);
+extern int unreal_bind(int fd, const char *ip, int port, int ipv6);
+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 MODVAR Client *remote_rehash_client;
extern MODVAR int debugfd;
-extern void convert_to_absolute_path(char **path, char *reldir);
+extern void convert_to_absolute_path(char **path, const char *reldir);
extern int has_user_mode(Client *acptr, char mode);
extern int has_channel_mode(Channel *channel, char mode);
+extern int has_channel_mode_raw(Cmode_t m, char mode);
extern Cmode_t get_extmode_bitbychar(char m);
-extern long get_mode_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_ssl(Client *);
+extern void reinit_tls(void);
extern CMD_FUNC(cmd_error);
extern CMD_FUNC(cmd_dns);
extern CMD_FUNC(cmd_info);
@@ -910,53 +943,53 @@ extern CMD_FUNC(cmd_module);
extern CMD_FUNC(cmd_rehash);
extern CMD_FUNC(cmd_die);
extern CMD_FUNC(cmd_restart);
-extern void cmd_alias(Client *client, MessageTag *recv_mtags, int parc, char *parv[], char *cmd); /* special! */
-extern char *pcre2_version(void);
+extern void cmd_alias(Client *client, MessageTag *recv_mtags, int parc, const char *parv[], const char *cmd); /* special! */
+extern const char *pcre2_version(void);
extern int get_terminal_width(void);
extern int has_common_channels(Client *c1, Client *c2);
extern int user_can_see_member(Client *user, Client *target, Channel *channel);
extern int invisible_user_in_channel(Client *target, Channel *channel);
-extern MODVAR int ssl_client_index;
+extern MODVAR int tls_client_index;
extern TLSOptions *FindTLSOptionsForUser(Client *acptr);
extern int IsWebsocket(Client *acptr);
-extern Policy policy_strtoval(char *s);
-extern char *policy_valtostr(Policy policy);
+extern Policy policy_strtoval(const char *s);
+extern const char *policy_valtostr(Policy policy);
extern char policy_valtochar(Policy policy);
-extern int verify_certificate(SSL *ssl, char *hostname, char **errstr);
-extern char *certificate_name(SSL *ssl);
+extern int verify_certificate(SSL *ssl, const char *hostname, char **errstr);
+extern const char *certificate_name(SSL *ssl);
extern void start_of_normal_client_handshake(Client *acptr);
extern void clicap_pre_rehash(void);
extern void clicap_post_rehash(void);
extern void unload_all_unused_mtag_handlers(void);
-extern void send_cap_notify(int add, char *token);
+extern void send_cap_notify(int add, const char *token);
extern void sendbufto_one(Client *to, char *msg, unsigned int quick);
extern MODVAR int current_serial;
-extern char *spki_fingerprint(Client *acptr);
-extern char *spki_fingerprint_ex(X509 *x509_cert);
-extern int is_module_loaded(char *name);
+extern const char *spki_fingerprint(Client *acptr);
+extern const char *spki_fingerprint_ex(X509 *x509_cert);
+extern int is_module_loaded(const char *name);
extern void close_std_descriptors(void);
-extern void banned_client(Client *acptr, char *bantype, char *reason, int global, int noexit);
+extern void banned_client(Client *acptr, const char *bantype, const char *reason, int global, int noexit);
extern char *mystpcpy(char *dst, const char *src);
-extern size_t add_sjsby(char *buf, char *setby, time_t seton);
-extern MaxTarget *findmaxtarget(char *cmd);
-extern void setmaxtargets(char *cmd, int limit);
+extern size_t add_sjsby(char *buf, const char *setby, time_t seton);
+extern MaxTarget *findmaxtarget(const char *cmd);
+extern void setmaxtargets(const char *cmd, int limit);
extern void freemaxtargets(void);
-extern int max_targets_for_command(char *cmd);
+extern int max_targets_for_command(const char *cmd);
extern void set_targmax_defaults(void);
-extern void parse_chanmodes_protoctl(Client *client, char *str);
-extern void concat_params(char *buf, int len, int parc, char *parv[]);
+extern void parse_chanmodes_protoctl(Client *client, const char *str);
+extern void concat_params(char *buf, int len, int parc, const char *parv[]);
extern void charsys_check_for_changes(void);
-extern int maxclients;
-extern int fast_badword_match(ConfigItem_badword *badword, char *line);
-extern int fast_badword_replace(ConfigItem_badword *badword, char *line, char *buf, int max);
-extern char *stripbadwords(char *str, ConfigItem_badword *start_bw, int *blocked);
-extern int badword_config_process(ConfigItem_badword *ca, char *str);
+extern MODVAR int maxclients;
+extern int fast_badword_match(ConfigItem_badword *badword, const char *line);
+extern int fast_badword_replace(ConfigItem_badword *badword, const char *line, char *buf, int max);
+extern const char *stripbadwords(const char *str, ConfigItem_badword *start_bw, int *blocked);
+extern int badword_config_process(ConfigItem_badword *ca, const char *str);
extern void badword_config_free(ConfigItem_badword *ca);
-extern char *badword_config_check_regex(char *s, int fastsupport, int check_broadness);
-extern AllowedChannelChars allowed_channelchars_strtoval(char *str);
-extern char *allowed_channelchars_valtostr(AllowedChannelChars v);
-extern HideIdleTimePolicy hideidletime_strtoval(char *str);
-extern char *hideidletime_valtostr(HideIdleTimePolicy v);
+extern const char *badword_config_check_regex(const char *s, int fastsupport, int check_broadness);
+extern AllowedChannelChars allowed_channelchars_strtoval(const char *str);
+extern const char *allowed_channelchars_valtostr(AllowedChannelChars v);
+extern HideIdleTimePolicy hideidletime_strtoval(const char *str);
+extern const char *hideidletime_valtostr(HideIdleTimePolicy v);
extern long ClientCapabilityBit(const char *token);
extern int is_handshake_finished(Client *client);
extern void SetCapability(Client *acptr, const char *token);
@@ -966,12 +999,12 @@ extern void new_message_special(Client *sender, MessageTag *recv_mtags, MessageT
extern void generate_batch_id(char *str);
extern MessageTag *find_mtag(MessageTag *mtags, const char *token);
extern MessageTag *duplicate_mtag(MessageTag *mtag);
+#define safe_free_message_tags(x) do { if (x) free_message_tags(x); x = NULL; } while(0)
extern void free_message_tags(MessageTag *m);
-extern time_t server_time_to_unix_time(const char *tbuf);
-extern int history_set_limit(char *object, int max_lines, long max_t);
-extern int history_add(char *object, MessageTag *mtags, char *line);
-extern HistoryResult *history_request(char *object, HistoryFilter *filter);
-extern int history_destroy(char *object);
+extern int history_set_limit(const char *object, int max_lines, long max_t);
+extern int history_add(const char *object, MessageTag *mtags, const char *line);
+extern HistoryResult *history_request(const char *object, HistoryFilter *filter);
+extern int history_destroy(const char *object);
extern int can_receive_history(Client *client);
extern void history_send_result(Client *client, HistoryResult *r);
extern void free_history_result(HistoryResult *r);
@@ -983,61 +1016,88 @@ extern int read_int64(FILE *fd, uint64_t *t);
extern int read_int32(FILE *fd, uint32_t *t);
extern int read_data(FILE *fd, void *buf, size_t len);
extern int write_data(FILE *fd, const void *buf, size_t len);
-extern int write_str(FILE *fd, char *x);
+extern int write_str(FILE *fd, const char *x);
extern int read_str(FILE *fd, char **x);
-extern int char_to_channelflag(char c);
extern void _free_entire_name_list(NameList *n);
-extern void _add_name_list(NameList **list, char *name);
-extern void _del_name_list(NameList **list, char *name);
-extern NameList *find_name_list(NameList *list, char *name);
-extern NameList *find_name_list_match(NameList *list, char *name);
+extern void _add_name_list(NameList **list, const char *name);
+extern void _del_name_list(NameList **list, const char *name);
+extern NameList *find_name_list(NameList *list, const char *name);
+extern NameList *find_name_list_match(NameList *list, const char *name);
extern int minimum_msec_since_last_run(struct timeval *tv_old, long minimum);
extern int unrl_utf8_validate(const char *str, const char **end);
-extern char *unrl_utf8_make_valid(const char *str);
+extern char *unrl_utf8_make_valid(const char *str, char *outputbuf, size_t outputbuflen, int strict_length_check);
extern void utf8_test(void);
extern MODVAR int non_utf8_nick_chars_in_use;
extern void short_motd(Client *client);
extern int should_show_connect_info(Client *client);
-extern void send_invalid_channelname(Client *client, char *channelname);
+extern void send_invalid_channelname(Client *client, const char *channelname);
extern int is_extended_ban(const char *str);
-extern int valid_sid(char *name);
+extern int is_extended_server_ban(const char *str);
+extern int empty_mode(const char *m);
+extern void free_multilinemode(MultiLineMode *m);
+#define safe_free_multilinemode(m) do { if (m) free_multilinemode(m); m = NULL; } while(0)
+extern int valid_sid(const char *name);
+extern int valid_uid(const char *name);
extern void parse_client_queued(Client *client);
-extern char *sha256sum_file(const char *fname);
+extern const char *sha256sum_file(const char *fname);
extern char *filename_strip_suffix(const char *fname, const char *suffix);
extern char *filename_add_suffix(const char *fname, const char *suffix);
extern int filename_has_suffix(const char *fname, const char *suffix);
-extern void addmultiline(MultiLine **l, char *line);
+extern void addmultiline(MultiLine **l, const char *line);
extern void freemultiline(MultiLine *l);
#define safe_free_multiline(x) do { if (x) freemultiline(x); x = NULL; } while(0)
+extern MultiLine *line2multiline(const char *str);
extern void sendnotice_multiline(Client *client, MultiLine *m);
extern void unreal_del_quotes(char *i);
-extern char *unreal_add_quotes(char *str);
-extern int unreal_add_quotes_r(char *i, char *o, size_t len);
+extern const char *unreal_add_quotes(const char *str);
+extern int unreal_add_quotes_r(const char *i, char *o, size_t len);
extern void user_account_login(MessageTag *recv_mtags, Client *client);
extern void link_generator(void);
extern void update_throttling_timer_settings(void);
extern int hide_idle_time(Client *client, Client *target);
-extern void lost_server_link(Client *serv, FORMAT_STRING(const char *fmt), ...);
-extern char *sendtype_to_cmd(SendType sendtype);
+extern void lost_server_link(Client *serv, const char *tls_error_string);
+extern const char *sendtype_to_cmd(SendType sendtype);
extern MODVAR MessageTagHandler *mtaghandlers;
-extern int security_group_valid_name(char *name);
-extern int security_group_exists(char *name);
-extern SecurityGroup *add_security_group(char *name, int order);
-extern SecurityGroup *find_security_group(char *name);
+extern int security_group_valid_name(const char *name);
+extern int security_group_exists(const char *name);
+extern SecurityGroup *add_security_group(const char *name, int order);
+extern SecurityGroup *find_security_group(const char *name);
extern void free_security_group(SecurityGroup *s);
extern void set_security_group_defaults(void);
extern int user_allowed_by_security_group(Client *client, SecurityGroup *s);
-extern int user_allowed_by_security_group_name(Client *client, char *secgroupname);
-extern void add_nvplist(NameValuePrioList **lst, int priority, char *name, char *value);
-extern void add_fmt_nvplist(NameValuePrioList **lst, int priority, char *name, FORMAT_STRING(const char *format), ...) __attribute__((format(printf,4,5)));
-extern NameValuePrioList *find_nvplist(NameValuePrioList *list, char *name);
+extern int user_allowed_by_security_group_name(Client *client, const char *secgroupname);
+#define nv_find_by_name(stru, name) do_nv_find_by_name(stru, name, ARRAY_SIZEOF((stru)))
+extern long do_nv_find_by_name(NameValue *table, const char *cmd, int numelements);
+#define nv_find_by_value(stru, value) do_nv_find_by_value(stru, value, ARRAY_SIZEOF((stru)))
+extern const char *do_nv_find_by_value(NameValue *table, long value, int numelements);
+extern void add_nvplist(NameValuePrioList **lst, int priority, const char *name, const char *value);
+extern void add_fmt_nvplist(NameValuePrioList **lst, int priority, const char *name, FORMAT_STRING(const char *format), ...) __attribute__((format(printf,4,5)));
+/** Combination of add_nvplist() and buildnumeric() for convenience - only used in WHOIS response functions.
+ * @param lst The NameValuePrioList &head
+ * @param priority The priority of the item being added
+ * @param name The name of the item being added (eg: "certfp")
+ * @param to The recipient
+ * @param numeric The numeric, one of RPL_* or ERR_*, see include/numeric.h
+ * @param ... The parameters for the numeric
+ * @note Be sure to provide the correct number and type of parameters that belong to the numeric. Check include/numeric.h when in doubt!
+ */
+#define add_nvplist_numeric(lst, priority, name, to, numeric, ...) add_nvplist_numeric_fmt(lst, priority, name, to, numeric, STR_ ## numeric, ##__VA_ARGS__)
+extern void add_nvplist_numeric_fmt(NameValuePrioList **lst, int priority, const char *name, Client *to, int numeric, FORMAT_STRING(const char *pattern), ...) __attribute__((format(printf,6,7)));
+extern NameValuePrioList *find_nvplist(NameValuePrioList *list, const char *name);
extern void free_nvplist(NameValuePrioList *lst);
-extern char *get_connect_extinfo(Client *client);
-extern char *unreal_strftime(char *str);
-extern void strtolower_safe(char *dst, char *src, int size);
+extern const char *get_connect_extinfo(Client *client);
+extern char *unreal_strftime(const char *str);
+extern void strtolower(char *str);
+extern void strtolower_safe(char *dst, const char *src, int size);
+extern void strtoupper(char *str);
+extern void strtoupper_safe(char *dst, const char *src, int size);
extern int running_interactively(void);
+extern int terminal_supports_color(void);
extern void skip_whitespace(char **p);
extern void read_until(char **p, char *stopchars);
+extern int is_ip_valid(const char *ip);
+extern int is_file_readable(const char *file, const char *dir);
+json_t *json_string_unreal(const char *s);
/* src/unrealdb.c start */
extern UnrealDB *unrealdb_open(const char *filename, UnrealDBMode mode, char *secret_block);
extern int unrealdb_close(UnrealDB *c);
@@ -1045,30 +1105,106 @@ extern char *unrealdb_test_db(const char *filename, char *secret_block);
extern int unrealdb_write_int64(UnrealDB *c, uint64_t t);
extern int unrealdb_write_int32(UnrealDB *c, uint32_t t);
extern int unrealdb_write_int16(UnrealDB *c, uint16_t t);
-extern int unrealdb_write_str(UnrealDB *c, char *x);
+extern int unrealdb_write_str(UnrealDB *c, const char *x);
extern int unrealdb_write_char(UnrealDB *c, char t);
extern int unrealdb_read_int64(UnrealDB *c, uint64_t *t);
extern int unrealdb_read_int32(UnrealDB *c, uint32_t *t);
extern int unrealdb_read_int16(UnrealDB *c, uint16_t *t);
extern int unrealdb_read_str(UnrealDB *c, char **x);
extern int unrealdb_read_char(UnrealDB *c, char *t);
-extern char *unrealdb_test_secret(char *name);
+extern const char *unrealdb_test_secret(const char *name);
extern UnrealDBConfig *unrealdb_copy_config(UnrealDBConfig *src);
extern UnrealDBConfig *unrealdb_get_config(UnrealDB *db);
extern void unrealdb_free_config(UnrealDBConfig *c);
extern UnrealDBError unrealdb_get_error_code(void);
-extern char *unrealdb_get_error_string(void);
+extern const char *unrealdb_get_error_string(void);
/* src/unrealdb.c end */
/* secret { } related stuff */
-extern Secret *find_secret(char *secret_name);
+extern Secret *find_secret(const char *secret_name);
extern void free_secret_cache(SecretCache *c);
extern void free_secret(Secret *s);
extern Secret *secrets;
/* end */
-extern int check_password_strength(char *pass, int min_length, int strict, char **err);
-extern int valid_secret_password(char *pass, char **err);
+extern int check_password_strength(const char *pass, int min_length, int strict, char **err);
+extern int valid_secret_password(const char *pass, char **err);
extern int flood_limit_exceeded(Client *client, FloodOption opt);
extern FloodSettings *find_floodsettings_block(const char *name);
extern FloodSettings *get_floodsettings_for_user(Client *client, FloodOption opt);
-extern MODVAR char *floodoption_names[];
-extern void flood_limit_exceeded_log(Client *client, char *floodname);
+extern MODVAR const char *floodoption_names[];
+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 LogType log_type_stringtoval(const char *str);
+extern const char *log_type_valtostring(LogType v);
+#ifdef DEBUGMODE
+#define unreal_log(...) do_unreal_log(__VA_ARGS__, log_data_source(__FILE__, __LINE__, __FUNCTION__), NULL)
+#define unreal_log_raw(...) do_unreal_log_raw(__VA_ARGS__, log_data_source(__FILE__, __LINE__, __FUNCTION__), NULL)
+#else
+#define unreal_log(...) do_unreal_log(__VA_ARGS__, NULL)
+#define unreal_log_raw(...) do_unreal_log_raw(__VA_ARGS__, NULL)
+#endif
+extern void do_unreal_log(LogLevel loglevel, const char *subsystem, const char *event_id, Client *client, const char *msg, ...) __attribute__((format(printf,5,0)));
+extern void do_unreal_log_raw(LogLevel loglevel, const char *subsystem, const char *event_id, Client *client, const char *msg, ...);
+extern void do_unreal_log_internal_from_remote(LogLevel loglevel, const char *subsystem, const char *event_id, MultiLine *msg, const char *json_serialized, Client *from_server);
+extern LogData *log_data_string(const char *key, const char *str);
+extern LogData *log_data_char(const char *key, const char c);
+extern LogData *log_data_integer(const char *key, int64_t integer);
+extern LogData *log_data_timestamp(const char *key, time_t ts);
+extern LogData *log_data_client(const char *key, Client *client);
+extern LogData *log_data_channel(const char *key, Channel *channel);
+extern LogData *log_data_source(const char *file, int line, const char *function);
+extern LogData *log_data_socket_error(int fd);
+extern LogData *log_data_link_block(ConfigItem_link *link);
+extern LogData *log_data_tkl(const char *key, TKL *tkl);
+extern LogData *log_data_tls_error(void);
+extern void log_pre_rehash(void);
+extern int log_tests(void);
+extern void config_pre_run_log(void);
+extern void log_blocks_switchover(void);
+extern void postconf_defaults_log_block(void);
+extern LogLevel log_level_stringtoval(const char *str);
+extern const char *log_level_valtostring(LogLevel loglevel);
+extern LogLevel log_level_stringtoval(const char *str);
+extern int valid_event_id(const char *s);
+extern int valid_subsystem(const char *s);
+extern const char *timestamp_iso8601_now(void);
+extern const char *timestamp_iso8601(time_t v);
+extern int is_valid_snomask(char c);
+extern int is_valid_snomask_string_testing(const char *str, char **wrong);
+/* end of logging */
+extern void add_fake_lag(Client *client, long msec);
+extern char *prefix_with_extban(const char *remainder, BanContext *b, Extban *extban, char *buf, size_t buflen);
+extern GeoIPResult *geoip_client(Client *client);
+extern GeoIPResult *geoip_lookup(const char *ip);
+extern void free_geoip_result(GeoIPResult *r);
+extern const char *get_operlogin(Client *client);
+extern const char *get_operclass(Client *client);
+/* url stuff */
+extern const char *unreal_mkcache(const char *url);
+extern int has_cached_version(const char *url);
+extern int url_is_valid(const char *);
+extern const char *displayurl(const char *url);
+extern char *url_getfilename(const char *url);
+extern void download_file_async(const char *url, time_t cachetime, vFP callback, void *callback_data, char *original_url, int maxredirects);
+extern void url_init(void);
+extern EVENT(url_socket_timeout);
+/* end of url stuff */
+extern char *collapse(char *pattern);
+extern void clear_scache_hash_table(void);
+extern void sendto_one(Client *, MessageTag *mtags, FORMAT_STRING(const char *), ...) __attribute__((format(printf,3,4)));
+extern EVENT(garbage_collect);
+extern EVENT(loop_event);
+extern EVENT(check_pings);
+extern EVENT(handshake_timeout);
+extern EVENT(check_deadsockets);
+extern EVENT(try_connections);
+extern const char *my_itoa(int i);
+extern void load_tunefile(void);
+extern EVENT(save_tunefile);
+extern void read_motd(const char *filename, MOTDFile *motd);
+extern int target_limit_exceeded(Client *client, void *target, const char *name);
+extern void make_umodestr(void);
+extern void initwhowas(void);
+extern void uid_init(void);
+extern const char *uid_get(void);
diff --git a/include/ircsprintf.h b/include/ircsprintf.h
index fe78767..af30808 100644
--- a/include/ircsprintf.h
+++ b/include/ircsprintf.h
@@ -17,7 +17,7 @@
# define FORMAT_STRING(p) p
#endif
-extern char *ircvsnprintf(char *str, size_t size, const char *format, va_list);
+extern char *ircvsnprintf(char *str, size_t size, const char *format, va_list) __attribute__((format(printf,3,0)));
extern char *ircsnprintf(char *str, size_t size, FORMAT_STRING(const char *format), ...) __attribute__((format(printf,3,4)));
#endif
diff --git a/include/modules.h b/include/modules.h
index 5bd22ec..62054cf 100644
--- a/include/modules.h
+++ b/include/modules.h
@@ -24,7 +24,7 @@
#define MAXCUSTOMHOOKS 30
#define MAXHOOKTYPES 150
#define MAXCALLBACKS 30
-#define MAXEFUNCTIONS 90
+#define MAXEFUNCTIONS 128
#if defined(_WIN32)
#define MOD_EXTENSION "dll"
#define DLLFUNC _declspec(dllexport)
@@ -95,7 +95,6 @@ typedef enum ModuleObjectType {
MOBJ_COMMAND = 3,
MOBJ_HOOKTYPE = 4,
MOBJ_VERSIONFLAG = 5,
- MOBJ_SNOMASK = 6,
MOBJ_UMODE = 7,
MOBJ_COMMANDOVERRIDE = 8,
MOBJ_EXTBAN = 9,
@@ -110,23 +109,16 @@ typedef enum ModuleObjectType {
MOBJ_HISTORY_BACKEND = 18,
} ModuleObjectType;
-typedef struct {
- long mode; /**< Mode mask */
- char flag; /**< Mode character */
- int unset_on_deoper; /**< When set to 1 then this user mode will be unset on de-oper */
- int (*allowed)(Client *client, int what); /**< The 'is this user allowed to set this mode?' routine */
- char unloaded; /**< Internal flag to indicate module is being unloaded */
- Module *owner; /**< Module that owns this user mode */
-} Umode;
-
-typedef struct {
- long mode; /**< Snomask mask */
- char flag; /**< Snomask character */
- int unset_on_deoper; /**< When set to 1 then this snomask will be unset on de-oper */
- int (*allowed)(Client *client, int what); /**< The 'is this user allowed to set this snomask?' routine */
- char unloaded; /**< Internal flag to indicate module is being unloaded */
- Module *owner; /**< Module that owns this snomask */
-} Snomask;
+typedef struct Umode Umode;
+struct Umode {
+ Umode *prev, *next;
+ long mode; /**< Mode mask */
+ char letter; /**< Mode character */
+ int unset_on_deoper; /**< When set to 1 then this user mode will be unset on de-oper */
+ int (*allowed)(Client *client, int what); /**< The 'is this user allowed to set this mode?' routine */
+ char unloaded; /**< Internal flag to indicate module is being unloaded */
+ Module *owner; /**< Module that owns this user mode */
+};
typedef enum ModDataType {
MODDATATYPE_LOCAL_VARIABLE = 1,
@@ -138,6 +130,11 @@ typedef enum ModDataType {
MODDATATYPE_MEMBERSHIP = 7,
} ModDataType;
+typedef enum ModDataSync {
+ MODDATA_SYNC_NORMAL = 1, /**< Sync normally via MD command */
+ MODDATA_SYNC_EARLY = 2, /**< Attempt to (also) sync early in the UID command */
+} ModDataSync;
+
typedef struct ModDataInfo ModDataInfo;
struct ModDataInfo {
@@ -148,9 +145,11 @@ struct ModDataInfo {
int slot; /**< Assigned slot */
char unloaded; /**< Module being unloaded? */
void (*free)(ModData *m); /**< Function will be called when the data needs to be freed (may be NULL if not using dynamic storage) */
- char *(*serialize)(ModData *m); /**< Function which converts the data to a string. May return NULL if 'm' contains no data (since for example m->ptr may be NULL). */
- void (*unserialize)(char *str, ModData *m); /**< Function which converts the string back to data */
- int sync; /**< Send in netsynch (when servers connect) */
+ const char *(*serialize)(ModData *m); /**< Function which converts the data to a string. May return NULL if 'm' contains no data (since for example m->ptr may be NULL). */
+ void (*unserialize)(const char *str, ModData *m); /**< Function which converts the string back to data */
+ ModDataSync sync; /**< Send in netsynch (when servers connect) */
+ int remote_write; /**< Allow remote servers to set/unset this moddata, even if it they target one of our own clients */
+ int self_write; /**< Allow remote servers to set/unset moddata of their own server object (irc1.example.net writing the MD object of irc1.example.net) */
};
#define moddata_client(acptr, md) acptr->moddata[md->slot]
@@ -191,6 +190,17 @@ typedef enum BypassChannelMessageRestrictionType {
/** Channel mode bit/value */
typedef unsigned long Cmode_t;
+typedef enum CmodeType {
+ CMODE_NORMAL=0,
+ CMODE_MEMBER=1,
+} CmodeType;
+
+#define RANK_CHANOWNER 4000
+#define RANK_CHANADMIN 3000
+#define RANK_CHANOP 2000
+#define RANK_HALFOP 1000
+#define RANK_VOICE -1
+
/** Channel mode handler.
* This struct contains all extended channel mode information,
* like the flag, mode, their handler functions, etc.
@@ -199,15 +209,36 @@ typedef unsigned long Cmode_t;
* and set the 'is_ok' function. All the rest is for parameter modes
* or is optional.
*/
-typedef struct {
- /** mode character (like 'Z') */
- char flag;
+typedef struct Cmode Cmode;
+struct Cmode {
+ Cmode *prev, *next;
- /** unique flag (like 0x10) */
+ /** mode character (like 'Z') */
+ char letter;
+
+ CmodeType type;
+
+ /** If type is CMODE_NORMAL, then bitmask (eg: 0x10) that
+ * is used in channel->mode.mode
+ */
Cmode_t mode;
+ /** If type is CMODE_MEMBER, then the prefix used in NAMES etc (eg @) */
+ char prefix;
+
+ /** If type is CMODE_MEMBER, then the prefix used in SJOIN (eg @) */
+ char sjoin_prefix;
+
+ /** If type is CMODE_MEMBER, then the rank of this prefix.
+ * Higher ranking = more rights.
+ * This is used, for example, in NAMES without NAMESX when we can only
+ * show one symbol but not all.
+ * For the shipped modules vhoaq we use the RANK_* values.
+ */
+ int rank;
+
/** Number of parameters (1 or 0) */
- int paracount;
+ int paracount;
/** Check access or parameter of the channel mode.
* @param client The client
@@ -217,24 +248,24 @@ typedef struct {
* @param what MODE_ADD or MODE_DEL
* @returns EX_DENY, EX_ALLOW or EX_ALWAYS_DENY
*/
- int (*is_ok)(Client *client, Channel *channel, char mode, char *para, int checkt, int what);
+ int (*is_ok)(Client *client, Channel *channel, char mode, const char *para, int checkt, int what);
/** Store parameter in memory for channel.
* This function pointer is NULL (unused) for modes without parameters.
- * @param list The list, this usually points to channel->mode.extmodeparams.
+ * @param list The list, this usually points to channel->mode.mode_params.
* @param para The parameter to store.
* @returns the head of the list, RTFS if you wonder why.
* @note IMPORTANT: only allocate a new paramstruct if you need to.
* Search for any current one first! Eg: in case of mode +y 5 and then +y 6 later without -y.
*/
- void *(*put_param)(void *list, char *para);
+ void *(*put_param)(void *list, const char *para);
/** Get the stored parameter as a readable/printable string.
* This function pointer is NULL (unused) for modes without parameters.
* @param parastruct The parameter struct
* @returns a pointer to the string (temporary storage)
*/
- char *(*get_param)(void *parastruct);
+ const char *(*get_param)(void *parastruct);
/** Convert input parameter to output.
* This converts stuff like where a MODE +l "1aaa" becomes "1".
@@ -249,7 +280,7 @@ typedef struct {
* In particular you MUST NOT SEND ERRORS to the client.
* This should be done in is_ok() and not in conv_param().
*/
- char *(*conv_param)(char *para, Client *client, Channel *channel);
+ const char *(*conv_param)(const char *para, Client *client, Channel *channel);
/** Free and remove parameter from list.
* This function pointer is NULL (unused) for modes without parameters.
@@ -295,24 +326,28 @@ typedef struct {
char unloaded;
/** Slot number - Can be used instead of GETPARAMSLOT() */
- int slot;
+ int param_slot;
/** Module owner */
Module *owner;
-} Cmode;
+};
/** The struct used to register a channel mode handler.
* For documentation, see Cmode struct.
*/
typedef struct {
- char flag;
+ char letter;
+ CmodeType type;
+ char prefix;
+ char sjoin_prefix;
+ int rank;
int paracount;
- int (*is_ok)(Client *,Channel *, char mode, char *para, int, int);
- void * (*put_param)(void *, char *);
- char * (*get_param)(void *);
- char * (*conv_param)(char *, Client *, Channel *);
+ int (*is_ok)(Client *,Channel *, char mode, const char *para, int, int);
+ void * (*put_param)(void *, const char *);
+ const char * (*get_param)(void *);
+ const char * (*conv_param)(const char *, Client *, Channel *);
void (*free_param)(void *);
- void * (*dup_struct)(void *);
+ void * (*dup_struct)(void *);
int (*sjoin_check)(Channel *, void *, void *);
char local;
char unset_with_param;
@@ -328,7 +363,7 @@ typedef struct {
#define GETPARAMHANDLERBYLETTER(x) ParamTable[GETPARAMSLOT(x)]
/** Get paramter data struct - for like: ((aModejEntry *)GETPARASTRUCT(channel, 'j'))->t */
-#define GETPARASTRUCT(mychannel, mychar) channel->mode.extmodeparams[GETPARAMSLOT(mychar)]
+#define GETPARASTRUCT(mychannel, mychar) channel->mode.mode_params[GETPARAMSLOT(mychar)]
#define GETPARASTRUCTEX(v, mychar) v[GETPARAMSLOT(mychar)]
@@ -341,16 +376,20 @@ typedef struct {
/*** Extended bans ***/
-// TODO: These should be enums!
+typedef enum ExtbanCheck {
+ EXBCHK_ACCESS=0, /**< Check access */
+ EXBCHK_ACCESS_ERR=1, /**< Check access and send error */
+ EXBCHK_PARAM=2 /**< Check if the parameter is valid */
+} ExtbanCheck;
-#define EXBCHK_ACCESS 0 /* Check access */
-#define EXBCHK_ACCESS_ERR 1 /* Check access and send error */
-#define EXBCHK_PARAM 2 /* Check if the parameter is valid */
+typedef enum ExtbanType {
+ EXBTYPE_BAN=0, /**< Ban (channel mode +b) */
+ EXBTYPE_EXCEPT=1, /**< Ban exception (channel mode +e) */
+ EXBTYPE_INVEX=2, /**< Invite exception (channel mode +I) */
+ EXBTYPE_TKL=3 /**< TKL or other generic matcher outside banning routines */
+} ExtbanType;
-#define EXBTYPE_BAN 0 /* a ban */
-#define EXBTYPE_EXCEPT 1 /* an except */
-#define EXBTYPE_INVEX 2 /* an invite exception */
-#define EXBTYPE_TKL 3 /* TKL or other generic matcher outside banning routines */
+#define BCTX_CONV_OPTION_WRITE_LETTER_BANS 1 /* Always write letter extbans in output of conv_param */
#define EXTBANTABLESZ 32
@@ -363,54 +402,66 @@ typedef enum ExtbanOptions {
} ExtbanOptions;
typedef struct {
- /** extbans module */
- Module *owner;
+ Client *client; /**< Client to check, can be a remote client */
+ Channel *channel; /**< Channel to check */
+ const char *banstr; /**< Mask string (ban) */
+ int ban_check_types; /**< Ban types to check for, one or more of BANCHK_* OR'd together */
+ const char *msg; /**< Message, only for some BANCHK_* types (for censoring text) */
+ const char *error_msg; /**< Error message, can be NULL */
+ int no_extbans; /**< Set to 1 to disable extended bans checking - only nick!user@host allowed */
+ int what; /**< MODE_ADD or MODE_DEL (for is_ok) */
+ ExtbanType ban_type; /**< EXBTYPE_BAN or EXBTYPE_EXCEPT (for is_ok) */
+ ExtbanCheck is_ok_check;/**< One of EXBCHK_* (for is_ok) */
+ int conv_options; /**< One of BCTX_CONV_OPTION_* (for conv_param) */
+} BanContext;
+
+typedef struct Extban Extban;
+
+struct Extban {
+ Extban *prev, *next;
+
/** extended ban character */
- char flag;
+ char letter;
+
+ /** extended ban name */
+ char *name;
/** extban options */
ExtbanOptions options;
- /** access checking [optional].
- * Client *: the client
- * Channel *: the channel
- * para: the ban parameter
- * int: check type (see EXBCHK_*)
- * int: what (MODE_ADD or MODE_DEL)
- * int: what2 (EXBTYPE_BAN or EXBTYPE_EXCEPT)
- * return value: 1=ok, 0=bad
- * NOTE: just set this of NULL if you want only +hoaq to place/remove bans as usual.
- * NOTE2: This has not been tested yet!!
- */
- int (*is_ok)(Client *, Channel *, char *para, int, int, int);
+ unsigned int is_banned_events; /**< Which BANCHK_* events to listen on */
+
+ int (*is_ok)(BanContext *b);
/** Convert input parameter to output [optional].
* like with normal bans '+b blah' gets '+b blah!*@*', and it allows
- * you to limit the length of the ban too. You can set this to NULL however
- * to use the value as-is.
- * char *: the input parameter.
+ * you to limit the length of the ban too.
* return value: pointer to output string (temp. storage)
*/
- char * (*conv_param)(char *);
+ const char *(*conv_param)(BanContext *b, Extban *handler);
- /** Checks if the user is affected by this ban [required].
- * Called from is_banned.
- * Client *: the client
- * Channel *: the channel
- * para: the ban entry
- * int: a value of BANCHK_* (see struct.h)
- * char **: optionally a message, can be NULL!! (for some BANCHK_ types)
- * char **: optionally for setting an error message, can be NULL!!
+ /** Checks if the user is affected by this ban [optional].
+ * This may be set to NULL if you have is_banned_events set to 0 (zero),
+ * this can be useful if you don't actually ban a user, eg for text bans.
+ * This function is called from is_banned() and two other places.
*/
- int (*is_banned)(Client *client, Channel *channel, char *para, int checktype, char **msg, char **errormsg);
-} Extban;
+ int (*is_banned)(BanContext *b);
+
+ /** extbans module */
+ Module *owner;
+
+ /* Set to 1 during rehash when module is unloading (which may be re-used, and then set to 0) */
+ char unloaded;
+};
typedef struct {
- char flag;
+ char letter;
+ char *name;
ExtbanOptions options;
- int (*is_ok)(Client *, Channel *, char *para, int, int, int);
- char * (*conv_param)(char *);
- int (*is_banned)(Client *, Channel *, char *, int, char **, char **);
+ int (*is_ok)(BanContext *b);
+ const char *(*conv_param)(BanContext *b, Extban *handler);
+ int (*is_banned)(BanContext *b);
+ unsigned int is_banned_events;
} ExtbanInfo;
@@ -439,8 +490,8 @@ struct ClientCapability {
char *name; /**< The name of the CAP */
long cap; /**< The acptr->user->proto we should set (if any, can be 0, like for sts) */
int flags; /**< A flag from CLICAP_FLAGS_* */
- int (*visible)(Client *); /**< Should the capability be visible? Note: parameter may be NULL. [optional] */
- char *(*parameter)(Client *); /**< CAP parameters. Note: parameter may be NULL. [optional] */
+ int (*visible)(Client *); /**< Should the capability be visible? Note: parameter may be NULL. [optional] */
+ const char *(*parameter)(Client *); /**< CAP parameters. Note: parameter may be NULL. [optional] */
MessageTagHandler *mtag_handler; /**< For reverse dependency */
Module *owner; /**< Module introducing this CAP. */
char unloaded; /**< Internal flag to indicate module is being unloaded */
@@ -450,7 +501,7 @@ typedef struct {
char *name;
int flags;
int (*visible)(Client *);
- char *(*parameter)(Client *);
+ const char *(*parameter)(Client *);
} ClientCapabilityInfo;
/** @defgroup MessagetagAPI Message tag API
@@ -465,13 +516,13 @@ typedef struct {
/** Message Tag Handler */
struct MessageTagHandler {
MessageTagHandler *prev, *next;
- char *name; /**< The name of the message-tag */
- int flags; /**< A flag of MTAG_HANDLER_FLAGS_* */
- int (*is_ok)(Client *, char *, char *); /**< Verify syntax and access rights */
- int (*can_send)(Client *); /**< Tag may be sent to this client (normally NULL!) */
- Module *owner; /**< Module introducing this CAP. */
- ClientCapability *clicap_handler; /**< Client capability handler associated with this */
- char unloaded; /**< Internal flag to indicate module is being unloaded */
+ char *name; /**< The name of the message-tag */
+ int flags; /**< A flag of MTAG_HANDLER_FLAGS_* */
+ int (*is_ok)(Client *, const char *, const char *); /**< Verify syntax and access rights */
+ int (*should_send_to_client)(Client *); /**< Tag may be sent to this client (normally NULL!) */
+ Module *owner; /**< Module introducing this CAP. */
+ ClientCapability *clicap_handler; /**< Client capability handler associated with this */
+ char unloaded; /**< Internal flag to indicate module is being unloaded */
};
/** The struct used to register a message tag handler.
@@ -480,8 +531,8 @@ struct MessageTagHandler {
typedef struct {
char *name;
int flags;
- int (*is_ok)(Client *, char *, char *);
- int (*can_send)(Client *);
+ int (*is_ok)(Client *, const char *, const char *);
+ int (*should_send_to_client)(Client *);
ClientCapability *clicap_handler;
} MessageTagHandlerInfo;
@@ -531,10 +582,10 @@ typedef struct HistoryBackend HistoryBackend;
struct HistoryBackend {
HistoryBackend *prev, *next;
char *name; /**< The name of the history backend (eg: "mem") */
- int (*history_set_limit)(char *object, int max_lines, long max_time); /**< Impose a limit on a history object */
- int (*history_add)(char *object, MessageTag *mtags, char *line); /**< Add to history */
- HistoryResult *(*history_request)(char *object, HistoryFilter *filter); /**< Request history */
- int (*history_destroy)(char *object); /**< Destroy history of this object completely */
+ int (*history_set_limit)(const char *object, int max_lines, long max_time); /**< Impose a limit on a history object */
+ int (*history_add)(const char *object, MessageTag *mtags, const char *line); /**< Add to history */
+ HistoryResult *(*history_request)(const char *object, HistoryFilter *filter); /**< Request history */
+ int (*history_destroy)(const char *object); /**< Destroy history of this object completely */
Module *owner; /**< Module introducing this */
char unloaded; /**< Internal flag to indicate module is being unloaded */
};
@@ -544,10 +595,10 @@ struct HistoryBackend {
*/
typedef struct {
char *name;
- int (*history_set_limit)(char *object, int max_lines, long max_time);
- int (*history_add)(char *object, MessageTag *mtags, char *line);
- HistoryResult *(*history_request)(char *object, HistoryFilter *filter);
- int (*history_destroy)(char *object);
+ int (*history_set_limit)(const char *object, int max_lines, long max_time);
+ int (*history_add)(const char *object, MessageTag *mtags, const char *line);
+ HistoryResult *(*history_request)(const char *object, HistoryFilter *filter);
+ int (*history_destroy)(const char *object);
} HistoryBackendInfo;
struct Hook {
@@ -557,7 +608,8 @@ struct Hook {
union {
int (*intfunc)();
void (*voidfunc)();
- char *(*pcharfunc)();
+ char *(*stringfunc)();
+ const char *(*conststringfunc)();
} func;
Module *owner;
};
@@ -568,7 +620,9 @@ struct Callback {
union {
int (*intfunc)();
void (*voidfunc)();
- char *(*pcharfunc)();
+ void *(*pvoidfunc)();
+ char *(*stringfunc)();
+ const char *(*conststringfunc)();
} func;
Module *owner;
char willberemoved; /* will be removed on next rehash? (eg the 'old'/'current' one) */
@@ -589,7 +643,8 @@ struct Efunction {
int (*intfunc)();
void (*voidfunc)();
void *(*pvoidfunc)();
- char *(*pcharfunc)();
+ char *(*stringfunc)();
+ const char *(*conststringfunc)();
} func;
Module *owner;
char willberemoved; /* will be removed on next rehash? (eg the 'old'/'current' one) */
@@ -618,7 +673,6 @@ typedef struct ModuleObject {
Command *command;
Hooktype *hooktype;
Versionflag *versionflag;
- Snomask *snomask;
Umode *umode;
CommandOverride *cmdoverride;
Extban *extban;
@@ -717,31 +771,29 @@ extern MODVAR Hooktype Hooktypes[MAXCUSTOMHOOKS];
extern MODVAR Callback *Callbacks[MAXCALLBACKS], *RCallbacks[MAXCALLBACKS];
extern MODVAR ClientCapability *clicaps;
-extern Event *EventAdd(Module *module, char *name, vFP event, void *data, long every_msec, int count);
+extern Event *EventAdd(Module *module, const char *name, vFP event, void *data, long every_msec, int count);
extern void EventDel(Event *event);
extern Event *EventMarkDel(Event *event);
-extern Event *EventFind(char *name);
+extern Event *EventFind(const char *name);
extern int EventMod(Event *event, EventInfo *mods);
extern void DoEvents(void);
extern void EventStatus(Client *client);
extern void SetupEvents(void);
-extern void Module_Init(void);
-extern char *Module_Create(char *path);
-extern char *Module_TransformPath(char *path_);
-extern void Init_all_testing_modules(void);
-extern void Unload_all_loaded_modules(void);
-extern void Unload_all_testing_modules(void);
-extern int Module_Unload(char *name);
-extern vFP Module_Sym(char *name);
-extern vFP Module_SymX(char *name, Module **mptr);
-extern int Module_free(Module *mod);
-
+extern void Module_Init(void);
+extern const char *Module_Create(const char *path);
+extern const char *Module_TransformPath(const char *path_);
+extern void Init_all_testing_modules(void);
+extern void Unload_all_loaded_modules(void);
+extern void Unload_all_testing_modules(void);
+extern int Module_Unload(const char *name);
+extern vFP Module_Sym(const char *name);
+extern vFP Module_SymX(const char *name, Module **mptr);
+extern int Module_free(Module *mod);
#ifdef __OpenBSD__
-extern void *obsd_dlsym(void *handle, char *symbol);
+extern void *obsd_dlsym(void *handle, const char *symbol);
#endif
-
#ifdef _WIN32
extern const char *our_dlerror(void);
#endif
@@ -771,179 +823,115 @@ extern HistoryBackend *HistoryBackendAdd(Module *module, HistoryBackendInfo *mre
extern void HistoryBackendDel(HistoryBackend *m);
#ifndef GCC_TYPECHECKING
-#define HookAdd(module, hooktype, priority, func) HookAddMain(module, hooktype, priority, func, NULL, NULL)
-#define HookAddVoid(module, hooktype, priority, func) HookAddMain(module, hooktype, priority, NULL, func, NULL)
-#define HookAddPChar(module, hooktype, priority, func) HookAddMain(module, hooktype, priority, NULL, NULL, func)
+#define HookAdd(module, hooktype, priority, func) HookAddMain(module, hooktype, priority, func, NULL, NULL, NULL)
+#define HookAddVoid(module, hooktype, priority, func) HookAddMain(module, hooktype, priority, NULL, func, NULL, NULL)
+#define HookAddString(module, hooktype, priority, func) HookAddMain(module, hooktype, priority, NULL, NULL, func, NULL)
+#define HookAddConstString(module, hooktype, priority, func) HookAddMain(module, hooktype, priority, NULL, NULL, NULL, func)
#else
#define HookAdd(module, hooktype, priority, func) \
__extension__ ({ \
ValidateHooks(hooktype, func); \
- HookAddMain(module, hooktype, priority, func, NULL, NULL); \
+ HookAddMain(module, hooktype, priority, func, NULL, NULL, NULL); \
})
#define HookAddVoid(module, hooktype, priority, func) \
__extension__ ({ \
ValidateHooks(hooktype, func); \
- HookAddMain(module, hooktype, priority, NULL, func, NULL); \
+ HookAddMain(module, hooktype, priority, NULL, func, NULL, NULL); \
})
-#define HookAddPChar(module, hooktype, priority, func) \
+#define HookAddString(module, hooktype, priority, func) \
__extension__ ({ \
ValidateHooks(hooktype, func); \
- HookAddMain(module, hooktype, priority, NULL, NULL, func); \
+ HookAddMain(module, hooktype, priority, NULL, NULL, func, NULL); \
+})
+#define HookAddConstString(module, hooktype, priority, func) \
+__extension__ ({ \
+ ValidateHooks(hooktype, func); \
+ HookAddMain(module, hooktype, priority, NULL, NULL, NULL, func); \
})
#endif /* GCC_TYPCHECKING */
-extern Hook *HookAddMain(Module *module, int hooktype, int priority, int (*intfunc)(), void (*voidfunc)(), char *(*pcharfunc)());
+extern Hook *HookAddMain(Module *module, int hooktype, int priority, int (*intfunc)(), void (*voidfunc)(), char *(*stringfunc)(), const char *(*conststringfunc)());
extern Hook *HookDel(Hook *hook);
-extern Hooktype *HooktypeAdd(Module *module, char *string, int *type);
+extern Hooktype *HooktypeAdd(Module *module, const char *string, int *type);
extern void HooktypeDel(Hooktype *hooktype, Module *module);
-#define RunHook0(hooktype) do { Hook *h; for (h = Hooks[hooktype]; h; h = h->next)(*(h->func.intfunc))(); } while(0)
-#define RunHook(hooktype,x) do { Hook *h; for (h = Hooks[hooktype]; h; h = h->next) (*(h->func.intfunc))(x); } while(0)
-#define RunHookReturn(hooktype,x,retchk) \
+#define RunHook(hooktype,...) do { Hook *h; for (h = Hooks[hooktype]; h; h = h->next) (*(h->func.intfunc))(__VA_ARGS__); } while(0)
+#define RunHookReturn(hooktype,retchk,...) \
{ \
int retval; \
Hook *h; \
for (h = Hooks[hooktype]; h; h = h->next) \
{ \
- retval = (*(h->func.intfunc))(x); \
+ retval = (*(h->func.intfunc))(__VA_ARGS__); \
if (retval retchk) return; \
} \
}
-#define RunHookReturn2(hooktype,x,y,retchk) \
+#define RunHookReturnInt(hooktype,retchk,...) \
{ \
int retval; \
Hook *h; \
for (h = Hooks[hooktype]; h; h = h->next) \
{ \
- retval = (*(h->func.intfunc))(x,y); \
- if (retval retchk) return; \
- } \
-}
-#define RunHookReturn3(hooktype,x,y,z,retchk) \
-{ \
- int retval; \
- Hook *h; \
- for (h = Hooks[hooktype]; h; h = h->next) \
- { \
- retval = (*(h->func.intfunc))(x,y,z); \
- if (retval retchk) return; \
- } \
-}
-#define RunHookReturn4(hooktype,a,b,c,d,retchk) \
-{ \
- int retval; \
- Hook *h; \
- for (h = Hooks[hooktype]; h; h = h->next) \
- { \
- retval = (*(h->func.intfunc))(a,b,c,d); \
- if (retval retchk) return; \
- } \
-}
-#define RunHookReturnInt(hooktype,x,retchk) \
-{ \
- int retval; \
- Hook *h; \
- for (h = Hooks[hooktype]; h; h = h->next) \
- { \
- retval = (*(h->func.intfunc))(x); \
- if (retval retchk) return retval; \
- } \
-}
-#define RunHookReturnInt2(hooktype,x,y,retchk) \
-{ \
- int retval; \
- Hook *h; \
- for (h = Hooks[hooktype]; h; h = h->next) \
- { \
- retval = (*(h->func.intfunc))(x,y); \
- if (retval retchk) return retval; \
- } \
-}
-#define RunHookReturnInt3(hooktype,x,y,z,retchk) \
-{ \
- int retval; \
- Hook *h; \
- for (h = Hooks[hooktype]; h; h = h->next) \
- { \
- retval = (*(h->func.intfunc))(x,y,z); \
- if (retval retchk) return retval; \
- } \
-}
-#define RunHookReturnInt4(hooktype,a,b,c,d,retchk) \
-{ \
- int retval; \
- Hook *h; \
- for (h = Hooks[hooktype]; h; h = h->next) \
- { \
- retval = (*(h->func.intfunc))(a,b,c,d); \
+ retval = (*(h->func.intfunc))(__VA_ARGS__); \
if (retval retchk) return retval; \
} \
}
-#define RunHookReturnVoid(hooktype,x,ret) do { Hook *hook; for (hook = Hooks[hooktype]; hook; hook = hook->next) if((*(hook->func.intfunc))(x) ret) return; } while(0)
-#define RunHook2(hooktype,x,y) do { Hook *hook; for (hook = Hooks[hooktype]; hook; hook = hook->next) (*(hook->func.intfunc))(x,y); } while(0)
-#define RunHook3(hooktype,a,b,c) do { Hook *hook; for (hook = Hooks[hooktype]; hook; hook = hook->next) (*(hook->func.intfunc))(a,b,c); } while(0)
-#define RunHook4(hooktype,a,b,c,d) do { Hook *hook; for (hook = Hooks[hooktype]; hook; hook = hook->next) (*(hook->func.intfunc))(a,b,c,d); } while(0)
-#define RunHook5(hooktype,a,b,c,d,e) do { Hook *hook; for (hook = Hooks[hooktype]; hook; hook = hook->next) (*(hook->func.intfunc))(a,b,c,d,e); } while(0)
-#define RunHook6(hooktype,a,b,c,d,e,f) do { Hook *hook; for (hook = Hooks[hooktype]; hook; hook = hook->next) (*(hook->func.intfunc))(a,b,c,d,e,f); } while(0)
-#define RunHook7(hooktype,a,b,c,d,e,f,g) do { Hook *hook; for (hook = Hooks[hooktype]; hook; hook = hook->next) (*(hook->func.intfunc))(a,b,c,d,e,f,g); } while(0)
-#define RunHook8(hooktype,a,b,c,d,e,f,g,h) do { Hook *hook; for (hook = Hooks[hooktype]; hook; hook = hook->next) (*(hook->func.intfunc))(a,b,c,d,e,f,g,h); } while(0)
+#define CallbackAdd(module, cbtype, func) CallbackAddMain(module, cbtype, func, NULL, NULL, NULL, NULL)
+#define CallbackAddVoid(module, cbtype, func) CallbackAddMain(module, cbtype, NULL, func, NULL, NULL, NULL)
+#define CallbackAddPVoid(module, cbtype, func) CallbackAddMain(module, cbtype, NULL, NULL, func, NULL, NULL)
+#define CallbackAddString(module, cbtype, func) CallbackAddMain(module, cbtype, NULL, NULL, NULL, func, NULL)
+#define CallbackAddConstString(module, cbtype, func) CallbackAddMain(module, cbtype, NULL, NULL, NULL, NULL, func)
-#define CallbackAdd(cbtype, func) CallbackAddMain(NULL, cbtype, func, NULL, NULL)
-#define CallbackAddEx(module, cbtype, func) CallbackAddMain(module, cbtype, func, NULL, NULL)
-#define CallbackAddVoid(cbtype, func) CallbackAddMain(NULL, cbtype, NULL, func, NULL)
-#define CallbackAddVoidEx(module, cbtype, func) CallbackAddMain(module, cbtype, NULL, func, NULL)
-#define CallbackAddPChar(cbtype, func) CallbackAddMain(NULL, cbtype, NULL, NULL, func)
-#define CallbackAddPCharEx(module, cbtype, func) CallbackAddMain(module, cbtype, NULL, NULL, func)
-
-extern Callback *CallbackAddMain(Module *module, int cbtype, int (*intfunc)(), void (*voidfunc)(), char *(*pcharfunc)());
+extern Callback *CallbackAddMain(Module *module, int cbtype, int (*func)(), void (*vfunc)(), void *(*pvfunc)(), char *(*stringfunc)(), const char *(*conststringfunc)());
extern Callback *CallbackDel(Callback *cb);
-#define EfunctionAdd(module, cbtype, func) EfunctionAddMain(module, cbtype, func, NULL, NULL, NULL)
-#define EfunctionAddVoid(module, cbtype, func) EfunctionAddMain(module, cbtype, NULL, func, NULL, NULL)
-#define EfunctionAddPVoid(module, cbtype, func) EfunctionAddMain(module, cbtype, NULL, NULL, func, NULL)
-#define EfunctionAddPChar(module, cbtype, func) EfunctionAddMain(module, cbtype, NULL, NULL, NULL, func)
+#define EfunctionAdd(module, cbtype, func) EfunctionAddMain(module, cbtype, func, NULL, NULL, NULL, NULL)
+#define EfunctionAddVoid(module, cbtype, func) EfunctionAddMain(module, cbtype, NULL, func, NULL, NULL, NULL)
+#define EfunctionAddPVoid(module, cbtype, func) EfunctionAddMain(module, cbtype, NULL, NULL, func, NULL, NULL)
+#define EfunctionAddString(module, cbtype, func) EfunctionAddMain(module, cbtype, NULL, NULL, NULL, func, NULL)
+#define EfunctionAddConstString(module, cbtype, func) EfunctionAddMain(module, cbtype, NULL, NULL, NULL, NULL, func)
-extern Efunction *EfunctionAddMain(Module *module, EfunctionType eftype, int (*intfunc)(), void (*voidfunc)(), void *(*pvoidfunc)(), char *(*pcharfunc)());
+extern Efunction *EfunctionAddMain(Module *module, EfunctionType eftype, int (*intfunc)(), void (*voidfunc)(), void *(*pvoidfunc)(), char *(*stringfunc)(), const char *(*conststringfunc)());
extern Efunction *EfunctionDel(Efunction *cb);
-extern Command *CommandAdd(Module *module, char *cmd, CmdFunc func, unsigned char params, int flags);
-extern Command *AliasAdd(Module *module, char *cmd, AliasCmdFunc aliasfunc, unsigned char params, int flags);
+extern Command *CommandAdd(Module *module, const char *cmd, CmdFunc func, unsigned char params, int flags);
+extern Command *AliasAdd(Module *module, const char *cmd, AliasCmdFunc aliasfunc, unsigned char params, int flags);
extern void CommandDel(Command *command);
extern void CommandDelX(Command *command, RealCommand *cmd);
-extern int CommandExists(char *name);
-extern CommandOverride *CommandOverrideAdd(Module *module, char *cmd, OverrideCmdFunc func);
-extern CommandOverride *CommandOverrideAddEx(Module *module, char *name, int priority, OverrideCmdFunc func);
+extern int CommandExists(const char *name);
+extern CommandOverride *CommandOverrideAdd(Module *module, const char *name, int priority, OverrideCmdFunc func);
extern void CommandOverrideDel(CommandOverride *ovr);
-extern void CallCommandOverride(CommandOverride *ovr, Client *client, MessageTag *mtags, int parc, char *parv[]);
+extern void CallCommandOverride(CommandOverride *ovr, Client *client, MessageTag *mtags, int parc, const char *parv[]);
extern void moddata_free_client(Client *acptr);
extern void moddata_free_local_client(Client *acptr);
extern void moddata_free_channel(Channel *channel);
extern void moddata_free_member(Member *m);
extern void moddata_free_membership(Membership *m);
-extern ModDataInfo *findmoddata_byname(char *name, ModDataType type);
-extern int moddata_client_set(Client *acptr, char *varname, char *value);
-extern char *moddata_client_get(Client *acptr, char *varname);
-extern int moddata_local_client_set(Client *acptr, char *varname, char *value);
-extern char *moddata_local_client_get(Client *acptr, char *varname);
+extern ModDataInfo *findmoddata_byname(const char *name, ModDataType type);
+extern int moddata_client_set(Client *acptr, const char *varname, const char *value);
+extern const char *moddata_client_get(Client *acptr, const char *varname);
+extern ModData *moddata_client_get_raw(Client *client, const char *varname);
+extern int moddata_local_client_set(Client *acptr, const char *varname, const char *value);
+extern const char *moddata_local_client_get(Client *acptr, const char *varname);
-extern int LoadPersistentPointerX(ModuleInfo *modinfo, char *varshortname, void **var, void (*free_variable)(ModData *m));
+extern int LoadPersistentPointerX(ModuleInfo *modinfo, const char *varshortname, void **var, void (*free_variable)(ModData *m));
#define LoadPersistentPointer(modinfo, var, free_variable) LoadPersistentPointerX(modinfo, #var, (void **)&var, free_variable)
-extern void SavePersistentPointerX(ModuleInfo *modinfo, char *varshortname, void *var);
+extern void SavePersistentPointerX(ModuleInfo *modinfo, const char *varshortname, void *var);
#define SavePersistentPointer(modinfo, var) SavePersistentPointerX(modinfo, #var, var)
-extern int LoadPersistentIntX(ModuleInfo *modinfo, char *varshortname, int *var);
+extern int LoadPersistentIntX(ModuleInfo *modinfo, const char *varshortname, int *var);
#define LoadPersistentInt(modinfo, var) LoadPersistentIntX(modinfo, #var, &var)
-extern void SavePersistentIntX(ModuleInfo *modinfo, char *varshortname, int var);
+extern void SavePersistentIntX(ModuleInfo *modinfo, const char *varshortname, int var);
#define SavePersistentInt(modinfo, var) SavePersistentIntX(modinfo, #var, var)
-extern int LoadPersistentLongX(ModuleInfo *modinfo, char *varshortname, long *var);
+extern int LoadPersistentLongX(ModuleInfo *modinfo, const char *varshortname, long *var);
#define LoadPersistentLong(modinfo, var) LoadPersistentLongX(modinfo, #var, &var)
-extern void SavePersistentLongX(ModuleInfo *modinfo, char *varshortname, long var);
+extern void SavePersistentLongX(ModuleInfo *modinfo, const char *varshortname, long var);
#define SavePersistentLong(modinfo, var) SavePersistentLongX(modinfo, #var, var)
/** Hooks trigger on "events", such as a new user connecting or joining a channel,
@@ -1121,8 +1109,6 @@ extern void SavePersistentLongX(ModuleInfo *modinfo, char *varshortname, long va
#define HOOKTYPE_CHANNEL_SYNCED 83
/** See hooktype_can_sajoin() */
#define HOOKTYPE_CAN_SAJOIN 84
-/** See hooktype_check_init() */
-#define HOOKTYPE_CHECK_INIT 85
/** See hooktype_mode_deop() */
#define HOOKTYPE_MODE_DEOP 86
/** See hooktype_dcc_denied() */
@@ -1131,8 +1117,6 @@ extern void SavePersistentLongX(ModuleInfo *modinfo, char *varshortname, long va
#define HOOKTYPE_SECURE_CONNECT 88
/** See hooktype_can_bypass_channel_message_restriction() */
#define HOOKTYPE_CAN_BYPASS_CHANNEL_MESSAGE_RESTRICTION 89
-/** See hooktype_require_sasl() */
-#define HOOKTYPE_REQUIRE_SASL 90
/** See hooktype_sasl_continuation() */
#define HOOKTYPE_SASL_CONTINUATION 91
/** See hooktype_sasl_result() */
@@ -1161,6 +1145,18 @@ extern void SavePersistentLongX(ModuleInfo *modinfo, char *varshortname, long va
#define HOOKTYPE_CLOSE_CONNECTION 103
/** See hooktype_connect_extinfo() */
#define HOOKTYPE_CONNECT_EXTINFO 104
+/** See hooktype_is_invited() */
+#define HOOKTYPE_IS_INVITED 105
+/** See hooktype_post_local_nickchange() */
+#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_can_set_topic() */
+#define HOOKTYPE_CAN_SET_TOPIC 110
/* Adding a new hook here?
* 1) Add the #define HOOKTYPE_.... with a new number
* 2) Add a hook prototype (see below)
@@ -1193,7 +1189,7 @@ int hooktype_remote_connect(Client *client);
* @param client The quit/disconnect reason
* @return The quit reason (you may also return 'comment' if it should be unchanged) or NULL for an empty reason.
*/
-char *hooktype_pre_local_quit(Client *client, char *comment);
+const char *hooktype_pre_local_quit(Client *client, const char *comment);
/** Called when a local user quits or otherwise disconnects (function prototype for HOOKTYPE_PRE_LOCAL_QUIT).
* @param client The client
@@ -1201,7 +1197,7 @@ char *hooktype_pre_local_quit(Client *client, char *comment);
* @param comment The quit/exit reason
* @return The return value is ignored (use return 0)
*/
-int hooktype_local_quit(Client *client, MessageTag *mtags, char *comment);
+int hooktype_local_quit(Client *client, MessageTag *mtags, const char *comment);
/** Called when a remote user qutis or otherwise disconnects (function prototype for HOOKTYPE_REMOTE_QUIT).
* @param client The client
@@ -1209,7 +1205,7 @@ int hooktype_local_quit(Client *client, MessageTag *mtags, char *comment);
* @param comment The quit/exit reason
* @return The return value is ignored (use return 0)
*/
-int hooktype_remote_quit(Client *client, MessageTag *mtags, char *comment);
+int hooktype_remote_quit(Client *client, MessageTag *mtags, const char *comment);
/** Called when an unregistered user disconnects, so before the user was fully online (function prototype for HOOKTYPE_UNKUSER_QUIT).
* @param client The client
@@ -1217,7 +1213,7 @@ int hooktype_remote_quit(Client *client, MessageTag *mtags, char *comment);
* @param comment The quit/exit reason
* @return The return value is ignored (use return 0)
*/
-int hooktype_unkuser_quit(Client *client, MessageTag *mtags, char *comment);
+int hooktype_unkuser_quit(Client *client, MessageTag *mtags, const char *comment);
/** Called when a local or remote server connects / links in (function prototype for HOOKTYPE_SERVER_CONNECT).
* @param client The client
@@ -1262,7 +1258,7 @@ int hooktype_server_quit(Client *client, MessageTag *mtags);
* @param newnick The new nick name
* @return The return value is ignored (use return 0)
*/
-int hooktype_local_nickchange(Client *client, MessageTag *mtags, char *newnick);
+int hooktype_local_nickchange(Client *client, MessageTag *mtags, const char *newnick);
/** Called when a remote user changes the nick name (function prototype for HOOKTYPE_REMOTE_NICKCHANGE).
* @param client The client
@@ -1270,45 +1266,42 @@ int hooktype_local_nickchange(Client *client, MessageTag *mtags, char *newnick);
* @param newnick The new nick name
* @return The return value is ignored (use return 0)
*/
-int hooktype_remote_nickchange(Client *client, MessageTag *mtags, char *newnick);
+int hooktype_remote_nickchange(Client *client, MessageTag *mtags, const char *newnick);
/** Called when a user wants to join a channel, may the user join? (function prototype for HOOKTYPE_CAN_JOIN).
* @param client The client
* @param channel The channel the user wants to join
* @param key The key supplied by the client
- * @param parv The parameters from the JOIN. Normally you should not use this.
* @return Return 0 to allow the user, any other value should be an IRC numeric (eg: ERR_BANNEDFROMCHAN).
*/
-int hooktype_can_join(Client *client, Channel *channel, char *key, char *parv[]);
+int hooktype_can_join(Client *client, Channel *channel, const char *key, char **errmsg);
-/** Called when a user wants to join a channel, may the user join? (function prototype for HOOKTYPE_PRE_LOCAL_JOIN).
- * FIXME: It's not entirely clear why we have both hooktype_can_join() and hooktype_pre_local_join().
+/** Called when a user wants to join a channel (function prototype for HOOKTYPE_PRE_LOCAL_JOIN).
+ * IMPORTANT: Generally you want to use HOOKTYPE_CAN_JOIN / hooktype_can_join() instead!!
* @param client The client
* @param channel The channel the user wants to join
- * @param parv The parameters from the JOIN. May contain channel key in parv[2].
+ * @param key Channel key (can be NULL)
* @retval HOOK_DENY Deny the join.
* @retval HOOK_ALLOW Allow the join (stop processing other modules)
* @retval HOOK_CONTINUE Allow the join, unless another module blocks it.
*/
-int hooktype_pre_local_join(Client *client, Channel *channel, char *parv[]);
+int hooktype_pre_local_join(Client *client, Channel *channel, const char *key);
/** Called when a local user joins a channel (function prototype for HOOKTYPE_LOCAL_JOIN).
* @param client The client
* @param channel The channel the user wants to join
* @param mtags Message tags associated with the event
- * @param parv The parameters from the JOIN. May contain channel key in parv[2].
* @return The return value is ignored (use return 0)
*/
-int hooktype_local_join(Client *client, Channel *channel, MessageTag *mtags, char *parv[]);
+int hooktype_local_join(Client *client, Channel *channel, MessageTag *mtags);
/** Called when a remote user joins a channel (function prototype for HOOKTYPE_REMOTE_JOIN).
* @param client The client
* @param channel The channel the user wants to join
* @param mtags Message tags associated with the event
- * @param parv The parameters from the JOIN. May contain channel key in parv[2].
* @return The return value is ignored (use return 0)
*/
-int hooktype_remote_join(Client *client, Channel *channel, MessageTag *mtags, char *parv[]);
+int hooktype_remote_join(Client *client, Channel *channel, MessageTag *mtags);
/** Called when a local user wants to part a channel (function prototype for HOOKTYPE_PRE_LOCAL_PART).
* @param client The client
@@ -1316,7 +1309,7 @@ int hooktype_remote_join(Client *client, Channel *channel, MessageTag *mtags, ch
* @param comment The PART reason, this may be NULL.
* @return The part reason (you may also return 'comment' if it should be unchanged) or NULL for an empty reason.
*/
-char *hooktype_pre_local_part(Client *client, Channel *channel, char *comment);
+const char *hooktype_pre_local_part(Client *client, Channel *channel, const char *comment);
/** Called when a local user parts a channel (function prototype for HOOKTYPE_LOCAL_PART).
* @param client The client
@@ -1325,7 +1318,7 @@ char *hooktype_pre_local_part(Client *client, Channel *channel, char *comment);
* @param comment The PART reason, this may be NULL.
* @return The return value is ignored (use return 0)
*/
-int hooktype_local_part(Client *client, Channel *channel, MessageTag *mtags, char *comment);
+int hooktype_local_part(Client *client, Channel *channel, MessageTag *mtags, const char *comment);
/** Called when a remote user parts a channel (function prototype for HOOKTYPE_REMOTE_PART).
* @param client The client
@@ -1334,25 +1327,25 @@ int hooktype_local_part(Client *client, Channel *channel, MessageTag *mtags, cha
* @param comment The PART reason, this may be NULL.
* @return The return value is ignored (use return 0)
*/
-int hooktype_remote_part(Client *client, Channel *channel, MessageTag *mtags, char *comment);
+int hooktype_remote_part(Client *client, Channel *channel, MessageTag *mtags, const char *comment);
/** Do not use this function, use hooktype_can_kick() instead!
*/
-char *hooktype_pre_local_kick(Client *client, Client *victim, Channel *channel, char *comment);
+const char *hooktype_pre_local_kick(Client *client, Client *victim, Channel *channel, const char *comment);
/** Called when a local user wants to kick another user from a channel (function prototype for HOOKTYPE_CAN_KICK).
* @param client The client issuing the command
* @param victim The victim that should be kicked
* @param channel The channel the user should be kicked from
* @param comment The KICK reason, this may be NULL.
- * @param client_flags The access flags of 'client', one of CHFL_*, eg CHFL_CHANOP.
- * @param victim_flags The access flags of 'victim', one of CHFL_*, eg CHFL_VOICE.
- * @param error The error message that should be shown to the user (full IRC protocol line).
+ * @param client_member_modes The member modes of 'client' (eg "o"), never NULL but can be empty.
+ * @param victim_member_modes The member modes of 'victim' (eg "v"), never NULL but can be empty.
+ * @param errmsg The error message that should be shown to the user (full IRC protocol line).
* @retval EX_DENY Deny the KICK (unless IRCOp with sufficient override rights).
* @retval EX_ALWAYS_DENY Deny the KICK always (even if IRCOp).
* @retval EX_ALLOW Allow the kick, unless another module blocks it.
*/
-int hooktype_can_kick(Client *client, Client *victim, Channel *channel, char *comment, long client_flags, long victim_flags, char **error);
+int hooktype_can_kick(Client *client, Client *victim, Channel *channel, const char *comment, const char *client_member_modes, const char *victim_member_modes, const char **errmsg);
/** Called when a local user is kicked (function prototype for HOOKTYPE_LOCAL_KICK).
* @param client The client issuing the command
@@ -1362,7 +1355,7 @@ int hooktype_can_kick(Client *client, Client *victim, Channel *channel, char *co
* @param comment The KICK reason, this may be NULL.
* @return The return value is ignored (use return 0)
*/
-int hooktype_local_kick(Client *client, Client *victim, Channel *channel, MessageTag *mtags, char *comment);
+int hooktype_local_kick(Client *client, Client *victim, Channel *channel, MessageTag *mtags, const char *comment);
/** Called when a remote user is kicked (function prototype for HOOKTYPE_REMOTE_KICK).
* @param client The client issuing the command
@@ -1372,7 +1365,7 @@ int hooktype_local_kick(Client *client, Client *victim, Channel *channel, Messag
* @param comment The KICK reason, this may be NULL.
* @return The return value is ignored (use return 0)
*/
-int hooktype_remote_kick(Client *client, Client *victim, Channel *channel, MessageTag *mtags, char *comment);
+int hooktype_remote_kick(Client *client, Client *victim, Channel *channel, MessageTag *mtags, const char *comment);
/** Called right before a message is sent to the channel (function prototype for HOOKTYPE_PRE_CHANMSG).
* This function is only used by delayjoin. It cannot block a message. See hooktype_can_send_to_user() instead!
@@ -1382,7 +1375,7 @@ int hooktype_remote_kick(Client *client, Client *victim, Channel *channel, Messa
* @param text The text that will be sent
* @return The return value is ignored (use return 0)
*/
-int hooktype_pre_chanmsg(Client *client, Channel *channel, MessageTag *mtags, char *text, SendType sendtype);
+int hooktype_pre_chanmsg(Client *client, Channel *channel, MessageTag *mtags, const char *text, SendType sendtype);
/** Called when a user wants to send a message to another user (function prototype for HOOKTYPE_CAN_SEND_TO_USER).
* @param client The sender
@@ -1393,7 +1386,7 @@ int hooktype_pre_chanmsg(Client *client, Channel *channel, MessageTag *mtags, ch
* @retval HOOK_DENY Deny the message. The 'errmsg' will be sent to the user.
* @retval HOOK_CONTINUE Allow the message, unless other modules block it.
*/
-int hooktype_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype);
+int hooktype_can_send_to_user(Client *client, Client *target, const char **text, const char **errmsg, SendType sendtype);
/** Called when a user wants to send a message to a channel (function prototype for HOOKTYPE_CAN_SEND_TO_CHANNEL).
* @param client The sender
@@ -1405,7 +1398,7 @@ int hooktype_can_send_to_user(Client *client, Client *target, char **text, char
* @retval HOOK_DENY Deny the message. The 'errmsg' will be sent to the user.
* @retval HOOK_CONTINUE Allow the message, unless other modules block it.
*/
-int hooktype_can_send_to_channel(Client *client, Channel *channel, Membership *member, char **text, char **errmsg, SendType sendtype);
+int hooktype_can_send_to_channel(Client *client, Channel *channel, Membership *member, const char **text, const char **errmsg, SendType sendtype);
/** Called when a message is sent from one user to another user (function prototype for HOOKTYPE_USERMSG).
* @param client The sender
@@ -1415,20 +1408,31 @@ int hooktype_can_send_to_channel(Client *client, Channel *channel, Membership *m
* @param sendtype The message type, for example SEND_TYPE_PRIVMSG.
* @return The return value is ignored (use return 0)
*/
-int hooktype_usermsg(Client *client, Client *to, MessageTag *mtags, char *text, SendType sendtype);
+int hooktype_usermsg(Client *client, Client *to, MessageTag *mtags, const char *text, SendType sendtype);
/** Called when a message is sent to a channel (function prototype for HOOKTYPE_CHANMSG).
* @param client The sender
* @param channel The channel
* @param sendflags One of SEND_* (eg SEND_ALL, SKIP_DEAF).
- * @param prefix Either zero, one or a combination of PREFIX_*.
+ * @param member_modes Either NULL, or a member mode like "h", "o", etc.
* @param target Target string, usually this is "#channel", but it can also contain prefixes like "@#channel"
* @param mtags Message tags associated with the event
* @param text The text
* @param sendtype The message type, for example SEND_TYPE_PRIVMSG.
* @return The return value is ignored (use return 0)
*/
-int hooktype_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, SendType sendtype);
+int hooktype_chanmsg(Client *client, Channel *channel, int sendflags, const char *member_modes, const char *target, MessageTag *mtags, const char *text, SendType sendtype);
+
+/** Called when a user wants to set the topic (function prototype for HOOKTYPE_CAN_SET_TOPIC).
+ * @param client The client issuing the command
+ * @param channel The channel the topic should be set for
+ * @param topic The topic that should be set, this may be NULL for unset.
+ * @param errmsg The error message that should be shown to the user (full IRC protocol line).
+ * @retval EX_DENY Deny the TOPIC (unless IRCOp with sufficient override rights).
+ * @retval EX_ALWAYS_DENY Deny the TOPIC always (even if IRCOp).
+ * @retval EX_ALLOW Allow the TOPIC, unless another module blocks it.
+ */
+int hooktype_can_set_topic(Client *client, Channel *channel, const char *topic, const char **errmsg);
/** Called when a local user wants to change the channel topic (function prototype for HOOKTYPE_PRE_LOCAL_TOPIC).
* @param client The client
@@ -1436,7 +1440,7 @@ int hooktype_chanmsg(Client *client, Channel *channel, int sendflags, int prefix
* @param topic The new requested topic
* @return The new topic (you may also return 'topic'), or NULL if the topic change request should be rejected.
*/
-char *hooktype_pre_local_topic(Client *client, Channel *channel, char *topic);
+const char *hooktype_pre_local_topic(Client *client, Channel *channel, const char *topic);
/** Called when the channel topic is changed (function prototype for HOOKTYPE_TOPIC).
* @param client The client
@@ -1445,7 +1449,7 @@ char *hooktype_pre_local_topic(Client *client, Channel *channel, char *topic);
* @param topic The new topic
* @return The return value is ignored (use return 0)
*/
-int hooktype_topic(Client *client, Channel *channel, MessageTag *mtags, char *topic);
+int hooktype_topic(Client *client, Channel *channel, MessageTag *mtags, const char *topic);
/** Called when a local user changes channel modes, called early (function prototype for HOOKTYPE_PRE_LOCAL_CHANMODE).
* WARNING: This does not allow you to stop or reject the channel modes. It only allows you to do stuff -before- the
@@ -1459,7 +1463,7 @@ int hooktype_topic(Client *client, Channel *channel, MessageTag *mtags, char *to
* @param samode Is this an SAMODE?
* @return The return value is ignored (use return 0)
*/
-int hooktype_pre_local_chanmode(Client *client, Channel *channel, MessageTag *mtags, char *modebuf, char *parabuf, time_t sendts, int samode);
+int hooktype_pre_local_chanmode(Client *client, Channel *channel, MessageTag *mtags, const char *modebuf, const char *parabuf, time_t sendts, int samode);
/** Called when a remote user changes channel modes, called early (function prototype for HOOKTYPE_PRE_REMOTE_CHANMODE).
* WARNING: This does not allow you to stop or reject the channel modes. It only allows you to do stuff -before- the
@@ -1473,7 +1477,7 @@ int hooktype_pre_local_chanmode(Client *client, Channel *channel, MessageTag *mt
* @param samode Is this an SAMODE?
* @return The return value is ignored (use return 0)
*/
-int hooktype_pre_remote_chanmode(Client *client, Channel *channel, MessageTag *mtags, char *modebuf, char *parabuf, time_t sendts, int samode);
+int hooktype_pre_remote_chanmode(Client *client, Channel *channel, MessageTag *mtags, const char *modebuf, const char *parabuf, time_t sendts, int samode);
/** Called when a local user changes channel modes (function prototype for HOOKTYPE_LOCAL_CHANMODE).
* @param client The client
@@ -1483,9 +1487,10 @@ int hooktype_pre_remote_chanmode(Client *client, Channel *channel, MessageTag *m
* @param parabuf The parameter buffer, for example "NiceOp"
* @param sendts Send timestamp
* @param samode Is this an SAMODE?
+ * @param destroy_channel Module can set this to 1 to indicate 'channel' was destroyed
* @return The return value is ignored (use return 0)
*/
-int hooktype_local_chanmode(Client *client, Channel *channel, MessageTag *mtags, char *modebuf, char *parabuf, time_t sendts, int samode);
+int hooktype_local_chanmode(Client *client, Channel *channel, MessageTag *mtags, const char *modebuf, const char *parabuf, time_t sendts, int samode, int *destroy_channel);
/** Called when a remote user changes channel modes (function prototype for HOOKTYPE_REMOTE_CHANMODE).
* @param client The client
@@ -1495,9 +1500,10 @@ int hooktype_local_chanmode(Client *client, Channel *channel, MessageTag *mtags,
* @param parabuf The parameter buffer, for example "NiceOp"
* @param sendts Send timestamp
* @param samode Is this an SAMODE?
+ * @param destroy_channel Module can set this to 1 to indicate 'channel' was destroyed
* @return The return value is ignored (use return 0)
*/
-int hooktype_remote_chanmode(Client *client, Channel *channel, MessageTag *mtags, char *modebuf, char *parabuf, time_t sendts, int samode);
+int hooktype_remote_chanmode(Client *client, Channel *channel, MessageTag *mtags, const char *modebuf, const char *parabuf, time_t sendts, int samode, int *destroy_channel);
/** Called when a channel mode is removed by a local or remote user (function prototype for HOOKTYPE_MODECHAR_DEL).
* NOTE: This is currently not terribly useful for most modules. It is used by by the floodprot and noknock modules.
@@ -1519,9 +1525,10 @@ int hooktype_modechar_add(Channel *channel, int modechar);
* @param client The client
* @param mtags Message tags associated with the event
* @param reason The away reason, or NULL if away is unset.
+ * @param already_as_away Set to 1 if the user only changed their away reason.
* @return The return value is ignored (use return 0)
*/
-int hooktype_away(Client *client, MessageTag *mtags, char *reason);
+int hooktype_away(Client *client, MessageTag *mtags, const char *reason, int already_as_away);
/** Called when a user wants to invite another user to a channel (function prototype for HOOKTYPE_PRE_INVITE).
* @param client The client
@@ -1544,14 +1551,14 @@ int hooktype_pre_invite(Client *client, Client *acptr, Channel *channel, int *ov
int hooktype_invite(Client *client, Client *acptr, Channel *channel, MessageTag *mtags);
/** Called when a user wants to knock on a channel (function prototype for HOOKTYPE_PRE_KNOCK).
- * FIXME: where is the knock reason ?
* @param client The client
* @param channel The channel to knock on
+ * @param reason Knock reason (can be replaced if needed)
* @retval HOOK_DENY Deny the knock.
* @retval HOOK_ALLOW Allow the knock (stop processing other modules)
* @retval HOOK_CONTINUE Allow the knock, unless another module blocks it.
*/
-int hooktype_pre_knock(Client *client, Channel *channel);
+int hooktype_pre_knock(Client *client, Channel *channel, const char **reason);
/** Called when a user knocks on a channel (function prototype for HOOKTYPE_KNOCK).
* @param client The client
@@ -1560,14 +1567,16 @@ int hooktype_pre_knock(Client *client, Channel *channel);
* @param comment The knock reason
* @return The return value is ignored (use return 0)
*/
-int hooktype_knock(Client *client, Channel *channel, MessageTag *mtags, char *comment);
+int hooktype_knock(Client *client, Channel *channel, MessageTag *mtags, const char *comment);
/** Called when a user whoises someone (function prototype for HOOKTYPE_WHOIS).
* @param client The client issuing the command
* @param target The user who is the target of the /WHOIS.
+ * @param list The name/value/prio list that you can add information to
+ * that will be sent to the user as the WHOIS response.
* @return The return value is ignored (use return 0)
*/
-int hooktype_whois(Client *client, Client *target);
+int hooktype_whois(Client *client, Client *target, NameValuePrioList **list);
/** Called to add letters to the WHO status column (function prototype for HOOKTYPE_WHO_STATUS).
* If a user does a /WHO request, then WHO will show a number of status flags
@@ -1580,7 +1589,7 @@ int hooktype_whois(Client *client, Client *target);
* @param cansee If 'client' can see 'target' (eg: in same channel or -i)
* @return Return 0 if no WHO status flags need to be added, otherwise return the ascii character (eg: return 'B').
*/
-int hooktype_who_status(Client *client, Client *target, Channel *channel, Member *member, char *status, int cansee);
+int hooktype_who_status(Client *client, Client *target, Channel *channel, Member *member, const char *status, int cansee);
/** Called when an IRCOp wants to kill another user (function prototype for HOOKTYPE_PRE_KILL).
* @param client The client
@@ -1590,7 +1599,7 @@ int hooktype_who_status(Client *client, Client *target, Channel *channel, Member
* @retval EX_ALWAYS_DENY Deny the KICK always (even if IRCOp).
* @retval EX_ALLOW Allow the kick, unless another module blocks it.
*/
-int hooktype_pre_kill(Client *client, Client *victim, char *reason);
+int hooktype_pre_kill(Client *client, Client *victim, const char *reason);
/** Called when a local user kills another user (function prototype for HOOKTYPE_LOCAL_KILL).
* Note that kills from remote IRCOps will show up as regular quits, so use hooktype_remote_quit() and hooktype_local_quit().
@@ -1599,15 +1608,14 @@ int hooktype_pre_kill(Client *client, Client *victim, char *reason);
* @param comment The kill reason
* @return The return value is ignored (use return 0)
*/
-int hooktype_local_kill(Client *client, Client *victim, char *comment);
+int hooktype_local_kill(Client *client, Client *victim, const char *comment);
-/** Called when an IRCOp /REHASH'es, and passes the parameters (function prototype for HOOKTYPE_REHASHFLAG).
- * FIXME: shouldn't this be merged with hooktype_rehash() ?
+/** Called when an IRCOp calls /REHASH with a -parameter (function prototype for HOOKTYPE_REHASHFLAG).
* @param client The client issuing the command, or NULL if rehashing due to system signal.
* @param str The rehash flag (eg: "-all")
* @return The return value is ignored (use return 0)
*/
-int hooktype_rehashflag(Client *client, char *str);
+int hooktype_rehashflag(Client *client, const char *str);
/** Called when the server is rehashing (function prototype for HOOKTYPE_REHASH).
* @return The return value is ignored (use return 0)
@@ -1667,29 +1675,29 @@ int hooktype_configrun_ex(ConfigFile *cfptr, ConfigEntry *ce, int section, void
* @param str The parameter to the STATS command, eg 'something'.
* @return The return value is ignored (use return 0)
*/
-int hooktype_stats(Client *client, char *str);
+int hooktype_stats(Client *client, const char *str);
/** Called when a user becomes IRCOp or is no longer an IRCOp (function prototype for HOOKTYPE_LOCAL_OPER).
* @param client The client
* @param add 1 if the user becomes IRCOp, 0 if the user is no longer IRCOp
+ * @param oper_block The name of the oper block used to oper up
* @return The return value is ignored (use return 0)
*/
-int hooktype_local_oper(Client *client, int add);
+int hooktype_local_oper(Client *client, int add, ConfigItem_oper *oper_block);
/** Called when a client sends a PASS command (function prototype for HOOKTYPE_LOCAL_PASS).
* @param client The client
* @param password The password supplied by the client
* @return The return value is ignored (use return 0)
*/
-int hooktype_local_pass(Client *client, char *password);
+int hooktype_local_pass(Client *client, const char *password);
/** Called when a channel is created (function prototype for HOOKTYPE_CHANNEL_CREATE).
- * @param client The client
* @param channel The channel that just got created
* @note This function is not used much, use hooktype_local_join() and hooktype_remote_join() instead.
* @return The return value is ignored (use return 0)
*/
-int hooktype_channel_create(Client *client, Channel *channel);
+int hooktype_channel_create(Channel *channel);
/** Called when a channel is completely destroyed (function prototype for HOOKTYPE_CHANNEL_DESTROY).
* @param channel The channel that is about to be destroyed
@@ -1731,13 +1739,16 @@ int hooktype_tkl_add(Client *client, TKL *tkl);
*/
int hooktype_tkl_del(Client *client, TKL *tkl);
-/** Called when something is logged via the ircd_log() function (function prototype for HOOKTYPE_LOG).
- * @param flags One of LOG_*, such as LOG_ERROR.
- * @param timebuf The time buffer, such as "[2030-01-01 12:00:00]"
- * @param buf The text to be logged
+/** Called when something is logged via the unreal_log() function (function prototype for HOOKTYPE_LOG).
+ * @param loglevel Loglevel (eg ULOG_INFO)
+ * @param subsystem Subsystem (eg "operoverride")
+ * @param event_id Event ID (eg "SAJOIN_COMMAND")
+ * @param msg Message(s) in text form
+ * @param json_serialized The associated JSON text
+ * @param timebuf The [xxxx] time buffer, for convenience
* @return The return value is ignored (use return 0)
*/
-int hooktype_log(int flags, char *timebuf, char *buf);
+int hooktype_log(LogLevel loglevel, const char *subsystem, const char *event_id, MultiLine *msg, const char *json_serialized, const char *timebuf);
/** Called when a local user matches a spamfilter (function prototype for HOOKTYPE_LOCAL_SPAMFILTER).
* @param client The client
@@ -1748,7 +1759,7 @@ int hooktype_log(int flags, char *timebuf, char *buf);
* @param tkl The spamfilter TKL entry that matched
* @return The return value is ignored (use return 0)
*/
-int hooktype_local_spamfilter(Client *client, char *str, char *str_in, int type, char *target, TKL *tkl);
+int hooktype_local_spamfilter(Client *client, const char *str, const char *str_in, int type, const char *target, TKL *tkl);
/** Called when a user sends something to a user that has the sender silenced (function prototype for HOOKTYPE_SILENCED).
* UnrealIRCd support a SILENCE list. If the target user has added someone on the silence list, eg via SILENCE +BadUser,
@@ -1771,7 +1782,7 @@ int hooktype_silenced(Client *client, Client *target, SendType sendtype);
* @note If you want to alter the buffer contents then replace 'readbuf' with your own buffer and set 'length' appropriately.
* @return The return value is ignored (use return 0)
*/
-int hooktype_rawpacket_in(Client *client, char *readbuf, int *length);
+int hooktype_rawpacket_in(Client *client, const char *readbuf, int *length);
/** Called when a packet is received or sent (function prototype for HOOKTYPE_PACKET).
* @param client The locally connected sender, this can be &me
@@ -1812,11 +1823,10 @@ int hooktype_free_user(Client *client);
* @param client The client
* @param channel The channel
* @param key The channel key
- * @param parv The join parameters
* @note I don't think this works?
* @return Unclear..
*/
-int hooktype_can_join_limitexceeded(Client *client, Channel *channel, char *key, char *parv[]);
+int hooktype_can_join_limitexceeded(Client *client, Channel *channel, const char *key, char **errmsg);
/** Called to check if the user is visible in the channel (function prototype for HOOKTYPE_VISIBLE_IN_CHANNEL).
* For example, the delayjoin module (+d/+D) will 'return 0' here if the user is hidden due to delayed join.
@@ -1904,16 +1914,6 @@ int hooktype_channel_synced(Channel *channel, int merge, int removetheirs, int n
*/
int hooktype_can_sajoin(Client *target, Channel *channel, Client *client);
-/** Called when the hostname is initialized for a client (function prototype for HOOKTYPE_CHECK_INIT).
- * This is a very specific call, it is only meant for the WEBIRC module.
- * @param client The client
- * @param sockname The socket name
- * @param size The size of the socket name? :D
- * @retval HOOK_CONTINUE Proceed normally
- * @retval HOOK_DENY Reject the connection(?)
- */
-int hooktype_check_init(Client *client, char *sockname, size_t size);
-
/** May the target user be deoped? (function prototype for HOOKTYPE_MODE_DEOP).
* This is for example used by the +S (Services bot) user mode to block deop requests to services bots.
* @param client The client issuing the command
@@ -1921,13 +1921,14 @@ int hooktype_check_init(Client *client, char *sockname, size_t size);
* @param channel The channel
* @param what Always MODE_DEL at the moment
* @param modechar The mode character: q/a/o/h/v
- * @param my_access Cached result of get_access(), so one of CHFL_*, for example CHFL_CHANOP.
- * @param badmode The error string that should be sent to the client
+ * @param client_access Channel member modes of 'client', eg "o", never NULL but can be empty.
+ * @param target_access Channel member modes of 'client', eg "h", never NULL but can be empty.
+ * @param reject_reason The error string that should be sent to the client
* @retval HOOK_CONTINUE Proceed normally (allow it)
* @retval HOOK_DENY Reject the mode change
* @retval HOOK_ALWAYS_DENY Reject the mode change, even if IRCOp/Services/..
*/
-int hooktype_mode_deop(Client *client, Client *victim, Channel *channel, u_int what, int modechar, long my_access, char **badmode);
+int hooktype_mode_deop(Client *client, Client *victim, Channel *channel, u_int what, int modechar, const char *client_access, const char *target_access, const char **reject_reason);
/** Called when a DCC request was denied by the IRCd (function prototype for HOOKTYPE_DCC_DENIED).
* @param client The client who tried to send a file
@@ -1937,7 +1938,7 @@ int hooktype_mode_deop(Client *client, Client *victim, Channel *channel, u_int w
* @param denydcc The deny dcc { ] rule that triggered.
* @return The return value is ignored (use return 0)
*/
-int hooktype_dcc_denied(Client *client, char *target, char *realfile, char *displayfile, ConfigItem_deny_dcc *denydcc);
+int hooktype_dcc_denied(Client *client, const char *target, const char *realfile, const char *displayfile, ConfigItem_deny_dcc *denydcc);
/** Called in the user accept procedure, when setting the +z user mode (function prototype for HOOKTYPE_SECURE_CONNECT).
* This is only meant to be used by the WEBIRC module, so it can do -z for fake secure users.
@@ -1956,13 +1957,6 @@ int hooktype_secure_connect(Client *client);
*/
int hooktype_can_bypass_channel_message_restriction(Client *client, Channel *channel, BypassChannelMessageRestrictionType bypass_type);
-/** Called when xxxx (function prototype for HOOKTYPE_REQUIRE_SASL).
- * FIXME: this hook is never called!?
- * @param client The client
- * @return The return value is ignored (use return 0)
- */
-int hooktype_require_sasl(Client *client, char *reason);
-
/** Called when a SASL continuation response is received (function prototype for HOOKTYPE_SASL_CONTINUATION).
* This is only used by the authprompt module, it unlikely that you need it.
* @param client The client for which the SASL authentication is taking place
@@ -1970,7 +1964,7 @@ int hooktype_require_sasl(Client *client, char *reason);
* @retval HOOK_CONTINUE Continue as normal
* @retval HOOK_DENY Do not handle the SASL request, or at least don't show the response to the client.
*/
-int hooktype_sasl_continuation(Client *client, char *buf);
+int hooktype_sasl_continuation(Client *client, const char *buf);
/** Called when a SASL result response is received (function prototype for HOOKTYPE_SASL_RESULT).
* This is only used by the authprompt module.
@@ -1990,7 +1984,7 @@ int hooktype_sasl_result(Client *client, int success);
* @param duration The duration of the ban, 0 for permanent ban
* @return The magic value 99 is used to exempt the user (=do not ban!), otherwise the ban is added.
*/
-int hooktype_place_host_ban(Client *client, int action, char *reason, long duration);
+int hooktype_place_host_ban(Client *client, int action, const char *reason, long duration);
/** Called when a TKL ban is hit by this user (function prototype for HOOKTYPE_FIND_TKLINE_MATCH).
* This is called when an existing TKL entry is hit by the user.
@@ -2020,7 +2014,7 @@ int hooktype_welcome(Client *client, int after_numeric);
* @param buf The buffer (without message tags)
* @return The return value is ignored (use return 0)
*/
-int hooktype_pre_command(Client *from, MessageTag *mtags, char *buf);
+int hooktype_pre_command(Client *from, MessageTag *mtags, const char *buf);
/** Called right after finishing a client command (function prototype for HOOKTYPE_POST_COMMAND).
* This is only used by labeled-reponse. If you think this hook is useful then you
@@ -2030,7 +2024,7 @@ int hooktype_pre_command(Client *from, MessageTag *mtags, char *buf);
* @param buf The buffer (without message tags)
* @return The return value is ignored (use return 0)
*/
-int hooktype_post_command(Client *from, MessageTag *mtags, char *buf);
+int hooktype_post_command(Client *from, MessageTag *mtags, const char *buf);
/** Called when new_message() is executed (function prototype for HOOKTYPE_NEW_MESSAGE).
* When a new message with message tags is prepared, code in UnrealIRCd
@@ -2044,7 +2038,7 @@ int hooktype_post_command(Client *from, MessageTag *mtags, char *buf);
* @param signature Special signature when used through new_message_special()
* @return The return value is ignored (use return 0)
*/
-void hooktype_new_message(Client *sender, MessageTag *recv_mtags, MessageTag **mtag_list, char *signature);
+void hooktype_new_message(Client *sender, MessageTag *recv_mtags, MessageTag **mtag_list, const char *signature);
/** Is the client handshake finished? (function prototype for HOOKTYPE_IS_HANDSHAKE_FINISHED).
* This is called by the is_handshake_finished() function to check if the user
@@ -2067,7 +2061,7 @@ int hooktype_is_handshake_finished(Client *client);
* @param comment The quit message
* @return The original quit message (comment), the new quit message (pointing to your own static buffer), or NULL (no quit message)
*/
-char *hooktype_pre_local_quit_chan(Client *client, Channel *channel, char *comment);
+const char *hooktype_pre_local_quit_chan(Client *client, Channel *channel, const char *comment);
/** Called when an ident lookup should be made (function prototype for HOOKTYPE_IDENT_LOOKUP).
* This is used by the ident_lookup module.
@@ -2077,7 +2071,7 @@ char *hooktype_pre_local_quit_chan(Client *client, Channel *channel, char *comme
int hooktype_ident_lookup(Client *client);
/** Called when someone logs in/out a services account (function prototype for HOOKTYPE_ACCOUNT_LOGIN).
- * The account name can be found in client->user->svid. It will be the string "0" if the user is logged out.
+ * The account name can be found in client->user->account. It will be the string "0" if the user is logged out.
* @param client The client
* @param mtags Message tags associated with the event
* @return The return value is ignored (use return 0)
@@ -2102,6 +2096,45 @@ int hooktype_close_connection(Client *client);
*/
int hooktype_connect_extinfo(Client *client, NameValuePrioList **list);
+/** Called when a user wants to join a channel that require invitation.
+ * Use hook priorities to enforce a specific policy, especially denying the invitation.
+ * @param client The client
+ * @param channel The channel client is willing to join
+ * @param invited Set to 0 for user who should not be invited, set to 1 if the user is invited.
+ * @return The return value is ignored (use return 0)
+ */
+int hooktype_is_invited(Client *client, Channel *channel, int *invited);
+
+/** Called after a local user has changed the nick name (function prototype for HOOKTYPE_POST_LOCAL_NICKCHANGE).
+ * @param client The client
+ * @param mtags Message tags associated with the event
+ * @param oldnick The nick name before the nick change
+ * @return The return value is ignored (use return 0)
+ */
+int hooktype_post_local_nickchange(Client *client, MessageTag *mtags, const char *oldnick);
+
+/** Called after a remote user has changed the nick name (function prototype for HOOKTYPE_POST_REMOTE_NICKCHANGE).
+ * @param client The client
+ * @param mtags Message tags associated with the event
+ * @param oldnick The nick name before the nick change
+ * @return The return value is ignored (use return 0)
+ */
+int hooktype_post_remote_nickchange(Client *client, MessageTag *mtags, const char *oldnick);
+
+/** Called when user name or user host has changed.
+ * @param client The client whose user@host has changed
+ * @param olduser Old username of the client
+ * @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);
+/** 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);
/** @} */
#ifdef GCC_TYPECHECKING
@@ -2138,6 +2171,7 @@ _UNREAL_ERROR(_hook_error_incompatible, "Incompatible hook function. Check argum
((hooktype == HOOKTYPE_REMOTE_QUIT) && !ValidateHook(hooktype_remote_quit, func)) || \
((hooktype == HOOKTYPE_PRE_LOCAL_JOIN) && !ValidateHook(hooktype_pre_local_join, func)) || \
((hooktype == HOOKTYPE_PRE_LOCAL_KICK) && !ValidateHook(hooktype_pre_local_kick, func)) || \
+ ((hooktype == HOOKTYPE_CAN_SET_TOPIC) && !ValidateHook(hooktype_can_set_topic, func)) || \
((hooktype == HOOKTYPE_PRE_LOCAL_TOPIC) && !ValidateHook(hooktype_pre_local_topic, func)) || \
((hooktype == HOOKTYPE_REMOTE_NICKCHANGE) && !ValidateHook(hooktype_remote_nickchange, func)) || \
((hooktype == HOOKTYPE_CHANNEL_CREATE) && !ValidateHook(hooktype_channel_create, func)) || \
@@ -2186,7 +2220,6 @@ _UNREAL_ERROR(_hook_error_incompatible, "Incompatible hook function. Check argum
((hooktype == HOOKTYPE_CHANNEL_SYNCED) && !ValidateHook(hooktype_channel_synced, func)) || \
((hooktype == HOOKTYPE_CAN_SAJOIN) && !ValidateHook(hooktype_can_sajoin, func)) || \
((hooktype == HOOKTYPE_WHOIS) && !ValidateHook(hooktype_whois, func)) || \
- ((hooktype == HOOKTYPE_CHECK_INIT) && !ValidateHook(hooktype_check_init, func)) || \
((hooktype == HOOKTYPE_WHO_STATUS) && !ValidateHook(hooktype_who_status, func)) || \
((hooktype == HOOKTYPE_MODE_DEOP) && !ValidateHook(hooktype_mode_deop, func)) || \
((hooktype == HOOKTYPE_PRE_KILL) && !ValidateHook(hooktype_pre_kill, func)) || \
@@ -2196,7 +2229,6 @@ _UNREAL_ERROR(_hook_error_incompatible, "Incompatible hook function. Check argum
((hooktype == HOOKTYPE_SERVER_SYNCED) && !ValidateHook(hooktype_server_synced, func)) || \
((hooktype == HOOKTYPE_SECURE_CONNECT) && !ValidateHook(hooktype_secure_connect, func)) || \
((hooktype == HOOKTYPE_CAN_BYPASS_CHANNEL_MESSAGE_RESTRICTION) && !ValidateHook(hooktype_can_bypass_channel_message_restriction, func)) || \
- ((hooktype == HOOKTYPE_REQUIRE_SASL) && !ValidateHook(hooktype_require_sasl, func)) || \
((hooktype == HOOKTYPE_SASL_CONTINUATION) && !ValidateHook(hooktype_sasl_continuation, func)) || \
((hooktype == HOOKTYPE_SASL_RESULT) && !ValidateHook(hooktype_sasl_result, func)) || \
((hooktype == HOOKTYPE_PLACE_HOST_BAN) && !ValidateHook(hooktype_place_host_ban, func)) || \
@@ -2211,7 +2243,12 @@ _UNREAL_ERROR(_hook_error_incompatible, "Incompatible hook function. Check argum
((hooktype == HOOKTYPE_CONFIGRUN_EX) && !ValidateHook(hooktype_configrun_ex, func)) || \
((hooktype == HOOKTYPE_ACCOUNT_LOGIN) && !ValidateHook(hooktype_account_login, func)) || \
((hooktype == HOOKTYPE_CLOSE_CONNECTION) && !ValidateHook(hooktype_close_connection, func)) || \
- ((hooktype == HOOKTYPE_CONNECT_EXTINFO) && !ValidateHook(hooktype_connect_extinfo, func)) ) \
+ ((hooktype == HOOKTYPE_CONNECT_EXTINFO) && !ValidateHook(hooktype_connect_extinfo, func)) || \
+ ((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)) )\
_hook_error_incompatible();
#endif /* GCC_TYPECHECKING */
@@ -2222,10 +2259,11 @@ _UNREAL_ERROR(_hook_error_incompatible, "Incompatible hook function. Check argum
/* Callback types */
#define CALLBACKTYPE_CLOAK 1
-#define CALLBACKTYPE_CLOAKKEYCSUM 2
+#define CALLBACKTYPE_CLOAK_KEY_CHECKSUM 2
#define CALLBACKTYPE_CLOAK_EX 3
#define CALLBACKTYPE_BLACKLIST_CHECK 4
#define CALLBACKTYPE_REPUTATION_STARTTIME 5
+#define CALLBACKTYPE_GEOIP_LOOKUP 6
/* To add a new efunction, only if you are an UnrealIRCd coder:
* 1) Add a new entry here
@@ -2241,6 +2279,7 @@ enum EfunctionType {
EFUNC_CAN_JOIN,
EFUNC_DO_MODE,
EFUNC_SET_MODE,
+ EFUNC_SET_CHANNEL_MODE,
EFUNC_CMD_UMODE,
EFUNC_REGISTER_USER,
EFUNC_TKL_HASH,
@@ -2281,6 +2320,8 @@ enum EfunctionType {
EFUNC_BROADCAST_MD_CHANNEL_CMD,
EFUNC_BROADCAST_MD_MEMBER_CMD,
EFUNC_BROADCAST_MD_MEMBERSHIP_CMD,
+ EFUNC_MODDATA_ADD_S2S_MTAGS,
+ EFUNC_MODDATA_EXTRACT_S2S_MTAGS,
EFUNC_SEND_MODDATA_CLIENT,
EFUNC_SEND_MODDATA_CHANNEL,
EFUNC_SEND_MODDATA_MEMBERS,
@@ -2293,10 +2334,12 @@ enum EfunctionType {
EFUNC_DO_REMOTE_NICK_NAME,
EFUNC_CHARSYS_GET_CURRENT_LANGUAGES,
EFUNC_BROADCAST_SINFO,
+ EFUNC_CONNECT_SERVER,
EFUNC_PARSE_MESSAGE_TAGS,
EFUNC_MTAGS_TO_STRING,
EFUNC_TKL_CHARTOTYPE,
EFUNC_TKL_TYPE_STRING,
+ EFUNC_TKL_TYPE_CONFIG_STRING,
EFUNC_CAN_SEND_TO_CHANNEL,
EFUNC_CAN_SEND_TO_USER,
EFUNC_BROADCAST_MD_GLOBALVAR,
@@ -2321,6 +2364,15 @@ enum EfunctionType {
EFUNC_LABELED_RESPONSE_SET_CONTEXT,
EFUNC_LABELED_RESPONSE_FORCE_END,
EFUNC_KICK_USER,
+ EFUNC_WATCH_ADD,
+ EFUNC_WATCH_DEL,
+ EFUNC_WATCH_DEL_LIST,
+ EFUNC_WATCH_GET,
+ EFUNC_WATCH_CHECK,
+ EFUNC_TKL_UHOST,
+ EFUNC_DO_UNREAL_LOG_REMOTE_DELIVER,
+ EFUNC_GET_CHMODES_FOR_USER,
+ EFUNC_WHOIS_GET_POLICY,
};
/* Module flags */
@@ -2354,7 +2406,7 @@ enum EfunctionType {
#define MOD_LOAD() DLLFUNC int Mod_Load(ModuleInfo *modinfo)
#define MOD_UNLOAD() DLLFUNC int Mod_Unload(ModuleInfo *modinfo)
-#define CLOAK_KEYCRC RCallbacks[CALLBACKTYPE_CLOAKKEYCSUM] != NULL ? RCallbacks[CALLBACKTYPE_CLOAKKEYCSUM]->func.pcharfunc() : "nil"
+#define CLOAK_KEY_CHECKSUM RCallbacks[CALLBACKTYPE_CLOAK_KEY_CHECKSUM] != NULL ? RCallbacks[CALLBACKTYPE_CLOAK_KEY_CHECKSUM]->func.stringfunc() : "nil"
#ifdef DYNAMIC_LINKING
#include "modversion.h"
diff --git a/include/msg.h b/include/msg.h
index 0b97314..dcae509 100644
--- a/include/msg.h
+++ b/include/msg.h
@@ -51,7 +51,6 @@
#define MSG_PONG "PONG" /* PONG */
#define MSG_OPER "OPER" /* OPER */
#define MSG_PASS "PASS" /* PASS */
-#define MSG_WALLOPS "WALLOPS" /* WALL */
#define MSG_TIME "TIME" /* TIME */
#define MSG_NAMES "NAMES" /* NAME */
#define MSG_ADMIN "ADMIN" /* ADMI */
diff --git a/include/numeric.h b/include/numeric.h
index fce4268..a380889 100644
--- a/include/numeric.h
+++ b/include/numeric.h
@@ -36,7 +36,6 @@
#define RPL_ISUPPORT 005
#define RPL_REDIR 10
-#define RPL_YOURID 42
#define RPL_REMOTEISUPPORT 105
@@ -51,29 +50,23 @@
#define ERR_TOOMANYCHANNELS 405
#define ERR_WASNOSUCHNICK 406
#define ERR_TOOMANYTARGETS 407
-#define ERR_NOSUCHSERVICE 408
#define ERR_NOORIGIN 409
#define ERR_INVALIDCAPCMD 410
#define ERR_NORECIPIENT 411
#define ERR_NOTEXTTOSEND 412
-#define ERR_NOTOPLEVEL 413
-#define ERR_WILDTOPLEVEL 414
#define ERR_TOOMANYMATCHES 416
#define ERR_UNKNOWNCOMMAND 421
#define ERR_NOMOTD 422
#define ERR_NOADMININFO 423
-#define ERR_FILEERROR 424
#define ERR_NOOPERMOTD 425
#define ERR_TOOMANYAWAY 429
#define ERR_NONICKNAMEGIVEN 431
#define ERR_ERRONEUSNICKNAME 432
#define ERR_NICKNAMEINUSE 433
#define ERR_NORULES 434
-#define ERR_SERVICECONFUSED 435
-#define ERR_NICKCOLLISION 436
#define ERR_BANNICKCHANGE 437
#define ERR_NCHANGETOOFAST 438
#define ERR_TARGETTOOFAST 439
@@ -82,53 +75,36 @@
#define ERR_USERNOTINCHANNEL 441
#define ERR_NOTONCHANNEL 442
#define ERR_USERONCHANNEL 443
-#define ERR_NOLOGIN 444
-#define ERR_SUMMONDISABLED 445
-#define ERR_USERSDISABLED 446
#define ERR_NONICKCHANGE 447
#define ERR_FORBIDDENCHANNEL 448
#define ERR_NOTREGISTERED 451
-#define ERR_HOSTILENAME 455
-
-#define ERR_NOHIDING 459
#define ERR_NOTFORHALFOPS 460
#define ERR_NEEDMOREPARAMS 461
#define ERR_ALREADYREGISTRED 462
-#define ERR_NOPERMFORHOST 463
#define ERR_PASSWDMISMATCH 464
#define ERR_YOUREBANNEDCREEP 465
-#define ERR_YOUWILLBEBANNED 466
-#define ERR_KEYSET 467
#define ERR_ONLYSERVERSCANCHANGE 468
-#define ERR_LINKSET 469
#define ERR_LINKCHANNEL 470
#define ERR_CHANNELISFULL 471
#define ERR_UNKNOWNMODE 472
#define ERR_INVITEONLYCHAN 473
#define ERR_BANNEDFROMCHAN 474
#define ERR_BADCHANNELKEY 475
-#define ERR_BADCHANMASK 476
#define ERR_NEEDREGGEDNICK 477
#define ERR_BANLISTFULL 478
-#define ERR_LINKFAIL 479
#define ERR_CANNOTKNOCK 480
#define ERR_NOPRIVILEGES 481
#define ERR_CHANOPRIVSNEEDED 482
-#define ERR_CANTKILLSERVER 483
-#define ERR_ATTACKDENY 484
#define ERR_KILLDENY 485
-#define ERR_NONONREG 486
#define ERR_NOTFORUSERS 487
#define ERR_SECUREONLYCHAN 489
-#define ERR_NOSWEAR 490
#define ERR_NOOPERHOST 491
-#define ERR_NOCTCP 492
#define ERR_CHANOWNPRIVNEEDED 499
@@ -138,13 +114,11 @@
#define ERR_SILELISTFULL 511
#define ERR_TOOMANYWATCH 512
-#define ERR_NEEDPONG 513
#define ERR_TOOMANYDCC 514
#define ERR_DISABLED 517
#define ERR_NOINVITE 518
-#define ERR_ADMONLY 519
#define ERR_OPERONLY 520
#define ERR_LISTSYNTAX 521
@@ -163,7 +137,6 @@
#define RPL_WHOISREGNICK 307
#define RPL_RULESSTART 308
#define RPL_ENDOFRULES 309
-#define RPL_WHOISHELPOP 310 /* -Donwulff */
#define RPL_WHOISUSER 311
#define RPL_WHOISSERVER 312
@@ -173,7 +146,6 @@
/* rpl_endofwho below (315) */
#define RPL_ENDOFWHOWAS 369
-#define RPL_WHOISCHANOP 316 /* redundant and not needed but reserved */
#define RPL_WHOISIDLE 317
#define RPL_ENDOFWHOIS 318
@@ -198,7 +170,7 @@
#define RPL_WHOISBOT 335
#define RPL_USERIP 340
#define RPL_INVITING 341
-#define RPL_SUMMONING 342
+#define RPL_WHOISCOUNTRY 344
#define RPL_VERSION 351
@@ -211,7 +183,6 @@
#define RPL_EXLIST 348
#define RPL_ENDOFEXLIST 349
-#define RPL_KILLDONE 361
#define RPL_CLOSING 362
#define RPL_CLOSEEND 363
#define RPL_LINKS 364
@@ -223,7 +194,6 @@
#define RPL_INFO 371
#define RPL_MOTD 372
-#define RPL_INFOSTART 373
#define RPL_ENDOFINFO 374
#define RPL_MOTDSTART 375
#define RPL_ENDOFMOTD 376
@@ -232,9 +202,6 @@
#define RPL_WHOISMODES 379
#define RPL_YOUREOPER 381
#define RPL_REHASHING 382
-#define RPL_YOURESERVICE 383
-#define RPL_MYPORTIS 384
-#define RPL_NOTOPERANYMORE 385
#define RPL_QLIST 386
#define RPL_ENDOFQLIST 387
#define RPL_ALIST 388
@@ -255,7 +222,6 @@
#define RPL_TRACEOPERATOR 204
#define RPL_TRACEUSER 205
#define RPL_TRACESERVER 206
-#define RPL_TRACESERVICE 207
#define RPL_TRACENEWTYPE 208
#define RPL_TRACECLASS 209
@@ -263,37 +229,28 @@
#define RPL_STATSLINKINFO 211
#define RPL_STATSCOMMANDS 212
#define RPL_STATSCLINE 213
-#define RPL_STATSOLDNLINE 214
#define RPL_STATSILINE 215
-#define RPL_STATSKLINE 216
#define RPL_STATSQLINE 217
#define RPL_STATSYLINE 218
#define RPL_ENDOFSTATS 219
-#define RPL_STATSBLINE 220
#define RPL_UMODEIS 221
-#define RPL_SQLINE_NICK 222
#define RPL_STATSGLINE 223
#define RPL_STATSTLINE 224
-#define RPL_STATSELINE 225
#define RPL_STATSNLINE 226
#define RPL_STATSVLINE 227
#define RPL_STATSBANVER 228
#define RPL_STATSSPAMF 229
#define RPL_STATSEXCEPTTKL 230
-#define RPL_SERVICEINFO 231
#define RPL_RULES 232
#define RPL_SERVICE 233
-#define RPL_SERVLIST 234
-#define RPL_SERVLISTEND 235
#define RPL_STATSLLINE 241
#define RPL_STATSUPTIME 242
#define RPL_STATSOLINE 243
#define RPL_STATSHLINE 244
-#define RPL_STATSSLINE 245
#define RPL_STATSXLINE 247
#define RPL_STATSULINE 248
#define RPL_STATSDEBUG 249
@@ -319,14 +276,6 @@
#define RPL_STATSDLINE 275
#define RPL_WHOISCERTFP 276
-#define RPL_HELPHDR 290
-#define RPL_HELPOP 291
-#define RPL_HELPTLR 292
-#define RPL_HELPHLP 293
-#define RPL_HELPFWD 294
-#define RPL_HELPIGN 295
-
-
/*
* New /MAP format.
*/
@@ -335,7 +284,6 @@
#define RPL_MAPEND 007
-#define ERR_WHOSYNTAX 522
#define ERR_WHOLIMEXCEED 523
#define ERR_OPERSPVERIFY 524
@@ -357,7 +305,6 @@
#define RPL_NOWOFF 605
#define RPL_WATCHLIST 606
#define RPL_ENDOFWATCHLIST 607
-#define RPL_CLEARWATCH 608
#define RPL_NOWISAWAY 609
#define RPL_DCCSTATUS 617
@@ -365,16 +312,18 @@
#define RPL_ENDOFDCCLIST 619
#define RPL_DCCINFO 620
-#define RPL_DUMPING 640
-#define RPL_DUMPRPL 641
-#define RPL_EODUMP 642
-
#define RPL_SPAMCMDFWD 659
#define RPL_STARTTLS 670
#define RPL_WHOISSECURE 671
+#define RPL_MONONLINE 730
+#define RPL_MONOFFLINE 731
+#define RPL_MONLIST 732
+#define RPL_ENDOFMONLIST 733
+#define ERR_MONLISTFULL 734
+
#define ERR_MLOCKRESTRICTED 742
#define ERR_CANNOTDOCOMMAND 972
@@ -382,15 +331,242 @@
#define ERR_STARTTLS 691
+#define ERR_INVALIDMODEPARAM 696
+
#define RPL_LOGGEDIN 900
#define RPL_LOGGEDOUT 901
-#define ERR_NICKLOCKED 902
#define RPL_SASLSUCCESS 903
#define ERR_SASLFAIL 904
#define ERR_SASLTOOLONG 905
#define ERR_SASLABORTED 906
-#define ERR_SASLALREADY 907
#define RPL_SASLMECHS 908
-#define ERR_NUMERICERR 999
+/* Numeric texts */
+
+#define STR_RPL_WELCOME /* 001 */ ":Welcome to the %s IRC Network %s!%s@%s"
+#define STR_RPL_YOURHOST /* 002 */ ":Your host is %s, running version %s"
+#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_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_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"
+#define STR_RPL_TRACEHANDSHAKE /* 202 */ "Handshaking %s %s"
+#define STR_RPL_TRACEUNKNOWN /* 203 */ "???? %s %s"
+#define STR_RPL_TRACEOPERATOR /* 204 */ "Operator %s %s [%s] %lld"
+#define STR_RPL_TRACEUSER /* 205 */ "User %s %s [%s] %lld"
+#define STR_RPL_TRACESERVER /* 206 */ "Server %s %dS %dC %s %s!%s@%s %lld"
+#define STR_RPL_TRACENEWTYPE /* 208 */ "%s 0 %s"
+#define STR_RPL_TRACECLASS /* 209 */ "Class %s %d"
+#define STR_RPL_STATSHELP /* 210 */ ":%s"
+#define STR_RPL_STATSCOMMANDS /* 212 */ "%s %u %lu"
+#define STR_RPL_STATSCLINE /* 213 */ "%c %s * %s %d %d %s"
+#define STR_RPL_STATSILINE /* 215 */ "I %s %s %d %d %s %s %d"
+#define STR_RPL_STATSQLINE /* 217 */ "%c %s %lld %lld %s :%s"
+#define STR_RPL_STATSYLINE /* 218 */ "Y %s %d %d %d %d %d"
+#define STR_RPL_ENDOFSTATS /* 219 */ "%c :End of /STATS report"
+#define STR_RPL_UMODEIS /* 221 */ "%s"
+#define STR_RPL_STATSGLINE /* 223 */ "%c %s %lld %lld %s :%s"
+#define STR_RPL_STATSTLINE /* 224 */ "T %s %s %s"
+#define STR_RPL_STATSNLINE /* 226 */ "n %s %s"
+#define STR_RPL_STATSVLINE /* 227 */ "v %s %s %s"
+#define STR_RPL_STATSBANVER /* 228 */ "%s %s"
+#define STR_RPL_STATSSPAMF /* 229 */ "%c %s %s %s %lld %lld %lld %s %s :%s"
+#define STR_RPL_STATSEXCEPTTKL /* 230 */ "%s %s %lld %lld %s :%s"
+#define STR_RPL_RULES /* 232 */ ":- %s"
+#define STR_RPL_STATSLLINE /* 241 */ "%c %s * %s %d %d"
+#define STR_RPL_STATSUPTIME /* 242 */ ":Server Up %lld days, %lld:%02lld:%02lld"
+#define STR_RPL_STATSOLINE /* 243 */ "%c %s * %s %s %s"
+#define STR_RPL_STATSHLINE /* 244 */ "%c %s * %s %d %d"
+#define STR_RPL_STATSXLINE /* 247 */ "X %s %d"
+#define STR_RPL_STATSULINE /* 248 */ "U %s"
+#define STR_RPL_STATSDEBUG /* 249 */ ":%s"
+#define STR_RPL_STATSCONN /* 250 */ ":Highest connection count: %d (%d clients)"
+#define STR_RPL_LUSERCLIENT /* 251 */ ":There are %d users and %d invisible on %d servers"
+#define STR_RPL_LUSEROP /* 252 */ "%d :operator(s) online"
+#define STR_RPL_LUSERUNKNOWN /* 253 */ "%d :unknown connection(s)"
+#define STR_RPL_LUSERCHANNELS /* 254 */ "%d :channels formed"
+#define STR_RPL_LUSERME /* 255 */ ":I have %d clients and %d servers"
+#define STR_RPL_ADMINME /* 256 */ ":Administrative info about %s"
+#define STR_RPL_ADMINLOC1 /* 257 */ ":%s"
+#define STR_RPL_ADMINLOC2 /* 258 */ ":%s"
+#define STR_RPL_ADMINEMAIL /* 259 */ ":%s"
+#define STR_RPL_TRACELOG /* 261 */ "File %s %d"
+#define STR_RPL_TRYAGAIN /* 263 */ "%s :Flooding detected. Please wait a while and try again."
+#define STR_RPL_LOCALUSERS /* 265 */ "%d %d :Current local users %d, max %d"
+#define STR_RPL_GLOBALUSERS /* 266 */ "%d %d :Current global users %d, max %d"
+#define STR_RPL_SILELIST /* 271 */ "%s"
+#define STR_RPL_ENDOFSILELIST /* 272 */ ":End of Silence List"
+#define STR_RPL_STATSDLINE /* 275 */ "%c %s %s"
+#define STR_RPL_WHOISCERTFP /* 276 */ "%s :has client certificate fingerprint %s"
+#define STR_RPL_AWAY /* 301 */ "%s :%s"
+#define STR_RPL_USERHOST /* 302 */ ":%s %s %s %s %s"
+#define STR_RPL_ISON /* 303 */ ":"
+#define STR_RPL_UNAWAY /* 305 */ ":You are no longer marked as being away"
+#define STR_RPL_NOWAWAY /* 306 */ ":You have been marked as being away"
+#define STR_RPL_WHOISREGNICK /* 307 */ "%s :is identified for this nick"
+#define STR_RPL_RULESSTART /* 308 */ ":- %s Server Rules - "
+#define STR_RPL_ENDOFRULES /* 309 */ ":End of RULES command."
+#define STR_RPL_WHOISUSER /* 311 */ "%s %s %s * :%s"
+#define STR_RPL_WHOISSERVER /* 312 */ "%s %s :%s"
+#define STR_RPL_WHOISOPERATOR /* 313 */ "%s :is %s"
+#define STR_RPL_WHOWASUSER /* 314 */ "%s %s %s * :%s"
+#define STR_RPL_ENDOFWHO /* 315 */ "%s :End of /WHO list."
+#define STR_RPL_WHOISIDLE /* 317 */ "%s %lld %lld :seconds idle, signon time"
+#define STR_RPL_ENDOFWHOIS /* 318 */ "%s :End of /WHOIS list."
+#define STR_RPL_WHOISCHANNELS /* 319 */ "%s :%s"
+#define STR_RPL_WHOISSPECIAL /* 320 */ "%s :%s"
+#define STR_RPL_LISTSTART /* 321 */ "Channel :Users Name"
+#define STR_RPL_LIST /* 322 */ "%s %d :%s %s"
+#define STR_RPL_LISTEND /* 323 */ ":End of /LIST"
+#define STR_RPL_CHANNELMODEIS /* 324 */ "%s %s %s"
+#define STR_RPL_CREATIONTIME /* 329 */ "%s %lld"
+#define STR_RPL_WHOISLOGGEDIN /* 330 */ "%s %s :is logged in as"
+#define STR_RPL_NOTOPIC /* 331 */ "%s :No topic is set."
+#define STR_RPL_TOPIC /* 332 */ "%s :%s"
+#define STR_RPL_TOPICWHOTIME /* 333 */ "%s %s %lld"
+#define STR_RPL_LISTSYNTAX /* 334 */ ":%s"
+#define STR_RPL_WHOISBOT /* 335 */ "%s :is a \2Bot\2 on %s"
+#define STR_RPL_INVITELIST /* 336 */ ":%s"
+#define STR_RPL_ENDOFINVITELIST /* 337 */ ":End of /INVITE list."
+#define STR_RPL_USERIP /* 340 */ ":%s %s %s %s %s"
+#define STR_RPL_INVITING /* 341 */ "%s %s"
+#define STR_RPL_WHOISCOUNTRY /* 344 */ "%s %s :is connecting from %s"
+#define STR_RPL_INVEXLIST /* 346 */ "%s %s %s %lld"
+#define STR_RPL_ENDOFINVEXLIST /* 347 */ "%s :End of Channel Invite List"
+#define STR_RPL_EXLIST /* 348 */ "%s %s %s %lld"
+#define STR_RPL_ENDOFEXLIST /* 349 */ "%s :End of Channel Exception List"
+#define STR_RPL_VERSION /* 351 */ "%s.%s %s :%s%s%s [%s=%d]"
+#define STR_RPL_WHOREPLY /* 352 */ "%s %s %s %s %s %s :%d %s"
+#define STR_RPL_NAMREPLY /* 353 */ "%s"
+#define STR_RPL_CLOSING /* 362 */ "%s :Closed. Status = %d"
+#define STR_RPL_CLOSEEND /* 363 */ "%d: Connections Closed"
+#define STR_RPL_LINKS /* 364 */ "%s %s :%d %s"
+#define STR_RPL_ENDOFLINKS /* 365 */ "%s :End of /LINKS list."
+#define STR_RPL_ENDOFNAMES /* 366 */ "%s :End of /NAMES list."
+#define STR_RPL_BANLIST /* 367 */ "%s %s %s %lld"
+#define STR_RPL_ENDOFBANLIST /* 368 */ "%s :End of Channel Ban List"
+#define STR_RPL_ENDOFWHOWAS /* 369 */ "%s :End of WHOWAS"
+#define STR_RPL_INFO /* 371 */ ":%s"
+#define STR_RPL_MOTD /* 372 */ ":- %s"
+#define STR_RPL_ENDOFINFO /* 374 */ ":End of /INFO list."
+#define STR_RPL_MOTDSTART /* 375 */ ":- %s Message of the Day - "
+#define STR_RPL_ENDOFMOTD /* 376 */ ":End of /MOTD command."
+#define STR_RPL_WHOISHOST /* 378 */ "%s :is connecting from %s@%s %s"
+#define STR_RPL_WHOISMODES /* 379 */ "%s :is using modes %s %s"
+#define STR_RPL_YOUREOPER /* 381 */ ":You are now an IRC Operator"
+#define STR_RPL_REHASHING /* 382 */ "%s :Rehashing"
+#define STR_RPL_QLIST /* 386 */ "%s %s"
+#define STR_RPL_ENDOFQLIST /* 387 */ "%s :End of Channel Owner List"
+#define STR_RPL_ALIST /* 388 */ "%s %s"
+#define STR_RPL_ENDOFALIST /* 389 */ "%s :End of Protected User List"
+#define STR_RPL_TIME /* 391 */ "%s :%s"
+#define STR_RPL_HOSTHIDDEN /* 396 */ "%s :is now your displayed host"
+#define STR_ERR_NOSUCHNICK /* 401 */ "%s :No such nick/channel"
+#define STR_ERR_NOSUCHSERVER /* 402 */ "%s :No such server"
+#define STR_ERR_NOSUCHCHANNEL /* 403 */ "%s :No such channel"
+#define STR_ERR_CANNOTSENDTOCHAN /* 404 */ "%s :%s (%s)"
+#define STR_ERR_TOOMANYCHANNELS /* 405 */ "%s :You have joined too many channels"
+#define STR_ERR_WASNOSUCHNICK /* 406 */ "%s :There was no such nickname"
+#define STR_ERR_TOOMANYTARGETS /* 407 */ "%s :Too many targets. The maximum is %d for %s."
+#define STR_ERR_NOORIGIN /* 409 */ ":No origin specified"
+#define STR_ERR_INVALIDCAPCMD /* 410 */ "%s :Invalid CAP subcommand"
+#define STR_ERR_NORECIPIENT /* 411 */ ":No recipient given (%s)"
+#define STR_ERR_NOTEXTTOSEND /* 412 */ ":No text to send"
+#define STR_ERR_TOOMANYMATCHES /* 416 */ "%s :%s"
+#define STR_ERR_UNKNOWNCOMMAND /* 421 */ "%s :Unknown command"
+#define STR_ERR_NOMOTD /* 422 */ ":MOTD File is missing"
+#define STR_ERR_NOADMININFO /* 423 */ "%s :No administrative info available"
+#define STR_ERR_NOOPERMOTD /* 425 */ ":OPERMOTD File is missing"
+#define STR_ERR_TOOMANYAWAY /* 429 */ ":Too Many aways - Flood Protection activated"
+#define STR_ERR_NONICKNAMEGIVEN /* 431 */ ":No nickname given"
+#define STR_ERR_ERRONEUSNICKNAME /* 432 */ "%s :Nickname is unavailable: %s"
+#define STR_ERR_NICKNAMEINUSE /* 433 */ "%s :Nickname is already in use."
+#define STR_ERR_NORULES /* 434 */ ":RULES File is missing"
+#define STR_ERR_BANNICKCHANGE /* 437 */ "%s :Cannot change nickname while banned on channel"
+#define STR_ERR_NCHANGETOOFAST /* 438 */ "%s :Nick change too fast. Please try again later."
+#define STR_ERR_TARGETTOOFAST /* 439 */ "%s :Message target change too fast. Please wait %lld seconds"
+#define STR_ERR_SERVICESDOWN /* 440 */ "%s :Services are currently down. Please try again later."
+#define STR_ERR_USERNOTINCHANNEL /* 441 */ "%s %s :They aren't on that channel"
+#define STR_ERR_NOTONCHANNEL /* 442 */ "%s :You're not on that channel"
+#define STR_ERR_USERONCHANNEL /* 443 */ "%s %s :is already on channel"
+#define STR_ERR_NONICKCHANGE /* 447 */ ":Can not change nickname while on %s (+N)"
+#define STR_ERR_FORBIDDENCHANNEL /* 448 */ "%s :Cannot join channel: %s"
+#define STR_ERR_NOTREGISTERED /* 451 */ ":You have not registered"
+#define STR_ERR_NOTFORHALFOPS /* 460 */ ":Halfops cannot set mode %c"
+#define STR_ERR_NEEDMOREPARAMS /* 461 */ "%s :Not enough parameters"
+#define STR_ERR_ALREADYREGISTRED /* 462 */ ":You may not reregister"
+#define STR_ERR_PASSWDMISMATCH /* 464 */ ":Password Incorrect"
+#define STR_ERR_YOUREBANNEDCREEP /* 465 */ ":%s"
+#define STR_ERR_ONLYSERVERSCANCHANGE /* 468 */ "%s :Only servers can change that mode"
+#define STR_ERR_LINKCHANNEL /* 470 */ "%s %s :[Link] %s has become full, so you are automatically being transferred to the linked channel %s"
+#define STR_ERR_CHANNELISFULL /* 471 */ "%s :Cannot join channel (+l)"
+#define STR_ERR_UNKNOWNMODE /* 472 */ "%c :is unknown mode char to me"
+#define STR_ERR_INVITEONLYCHAN /* 473 */ "%s :Cannot join channel (+i)"
+#define STR_ERR_BANNEDFROMCHAN /* 474 */ "%s :Cannot join channel (+b)"
+#define STR_ERR_BADCHANNELKEY /* 475 */ "%s :Cannot join channel (+k)"
+#define STR_ERR_NEEDREGGEDNICK /* 477 */ "%s :You need a registered nick to join that channel."
+#define STR_ERR_BANLISTFULL /* 478 */ "%s %s :Channel ban/ignore list is full"
+#define STR_ERR_CANNOTKNOCK /* 480 */ ":Cannot knock on %s (%s)"
+#define STR_ERR_NOPRIVILEGES /* 481 */ ":Permission Denied- You do not have the correct IRC operator privileges"
+#define STR_ERR_CHANOPRIVSNEEDED /* 482 */ "%s :You're not channel operator"
+#define STR_ERR_KILLDENY /* 485 */ ":Cannot kill protected user %s."
+#define STR_ERR_NOTFORUSERS /* 487 */ ":%s is a server only command"
+#define STR_ERR_SECUREONLYCHAN /* 489 */ "%s :Cannot join channel (Secure connection is required)"
+#define STR_ERR_NOOPERHOST /* 491 */ ":No O-lines for your host"
+#define STR_ERR_CHANOWNPRIVNEEDED /* 499 */ "%s :You're not a channel owner"
+#define STR_ERR_TOOMANYJOINS /* 500 */ "%s :Too many join requests. Please wait a while and try again."
+#define STR_ERR_UMODEUNKNOWNFLAG /* 501 */ ":Unknown MODE flag"
+#define STR_ERR_USERSDONTMATCH /* 502 */ ":Cant change mode for other users"
+#define STR_ERR_SILELISTFULL /* 511 */ "%s :Your silence list is full"
+#define STR_ERR_TOOMANYWATCH /* 512 */ "%s :Maximum size for WATCH-list is 128 entries"
+#define STR_ERR_TOOMANYDCC /* 514 */ "%s :Your dcc allow list is full. Maximum size is %d entries"
+#define STR_ERR_DISABLED /* 517 */ "%s :%s" /* ircu */
+#define STR_ERR_NOINVITE /* 518 */ ":Cannot invite (+V) at channel %s"
+#define STR_ERR_OPERONLY /* 520 */ ":Cannot join channel %s (IRCops only)"
+#define STR_ERR_LISTSYNTAX /* 521 */ ":Bad list syntax, type /quote list ? or /raw list ?"
+#define STR_ERR_WHOLIMEXCEED /* 523 */ ":Error, /who limit of %d exceeded. Please narrow your search down and try again"
+#define STR_ERR_OPERSPVERIFY /* 524 */ ":Trying to join +s or +p channel as an oper. Please invite yourself first."
+#define STR_ERR_CANTSENDTOUSER /* 531 */ "%s :%s"
+#define STR_RPL_REAWAY /* 597 */ "%s %s %s %lld :%s"
+#define STR_RPL_GONEAWAY /* 598 */ "%s %s %s %lld :%s"
+#define STR_RPL_NOTAWAY /* 599 */ "%s %s %s %lld :is no longer away"
+#define STR_RPL_LOGON /* 600 */ "%s %s %s %lld :logged online"
+#define STR_RPL_LOGOFF /* 601 */ "%s %s %s %lld :logged offline"
+#define STR_RPL_WATCHOFF /* 602 */ "%s %s %s %lld :stopped watching"
+#define STR_RPL_WATCHSTAT /* 603 */ ":You have %d and are on %d WATCH entries"
+#define STR_RPL_NOWON /* 604 */ "%s %s %s %lld :is online"
+#define STR_RPL_NOWOFF /* 605 */ "%s %s %s %lld :is offline"
+#define STR_RPL_WATCHLIST /* 606 */ ":%s"
+#define STR_RPL_ENDOFWATCHLIST /* 607 */ ":End of WATCH %c"
+#define STR_RPL_NOWISAWAY /* 609 */ "%s %s %s %lld :is away"
+#define STR_RPL_MAPMORE /* 610 */ ":%s%-*s --> *more*"
+#define STR_RPL_DCCSTATUS /* 617 */ ":%s has been %s your DCC allow list"
+#define STR_RPL_DCCLIST /* 618 */ ":%s"
+#define STR_RPL_ENDOFDCCLIST /* 619 */ ":End of DCCALLOW %s"
+#define STR_RPL_DCCINFO /* 620 */ ":%s"
+#define STR_RPL_SPAMCMDFWD /* 659 */ "%s :Command processed, but a copy has been sent to ircops for evaluation (anti-spam) purposes. [%s]"
+#define STR_RPL_STARTTLS /* 670 */ ":STARTTLS successful, go ahead with TLS handshake" /* kineircd */
+#define STR_RPL_WHOISSECURE /* 671 */ "%s :%s" /* our variation on the kineircd numeric */
+#define STR_ERR_STARTTLS /* 691 */ ":%s"
+#define STR_ERR_INVALIDMODEPARAM /* 696 */ "%s %c %s :%s"
+#define STR_RPL_MONONLINE /* 730 */ ":%s!%s@%s"
+#define STR_RPL_MONOFFLINE /* 731 */ ":%s"
+#define STR_RPL_MONLIST /* 732 */ ":%s"
+#define STR_RPL_ENDOFMONLIST /* 733 */ ":End of MONITOR list"
+#define STR_ERR_MONLISTFULL /* 734 */ "%d %s :Monitor list is full."
+#define STR_ERR_MLOCKRESTRICTED /* 742 */ "%s %c %s :MODE cannot be set due to channel having an active MLOCK restriction policy"
+#define STR_RPL_LOGGEDIN /* 900 */ "%s!%s@%s %s :You are now logged in as %s."
+#define STR_RPL_LOGGEDOUT /* 901 */ "%s!%s@%s :You are now logged out."
+#define STR_RPL_SASLSUCCESS /* 903 */ ":SASL authentication successful"
+#define STR_ERR_SASLFAIL /* 904 */ ":SASL authentication failed"
+#define STR_ERR_SASLTOOLONG /* 905 */ ":SASL message too long"
+#define STR_ERR_SASLABORTED /* 906 */ ":SASL authentication aborted"
+#define STR_RPL_SASLMECHS /* 908 */ "%s :are available SASL mechanisms"
+#define STR_ERR_CANNOTDOCOMMAND /* 972 */ "%s :%s"
+#define STR_ERR_CANNOTCHANGECHANMODE /* 974 */ "%c :%s"
diff --git a/include/proto.h b/include/proto.h
deleted file mode 100644
index 037d6e6..0000000
--- a/include/proto.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/************************************************************************
- * Unreal Internet Relay Chat Daemon, include/proto.h
- * (C) Dominick Meglio 2000
- *
- * 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.
- */
-
-#ifndef proto_h
-#define proto_h
-/* lusers.c */
-extern void init_irccounts(void);
-
-/* match.c */
-extern char *collapse(char *pattern);
-
-/* scache.c */
-extern void clear_scache_hash_table(void);
-
-/* send.c */
-extern void sendto_one(Client *, MessageTag *mtags, FORMAT_STRING(const char *), ...) __attribute__((format(printf,3,4)));
-extern void sendto_realops(FORMAT_STRING(const char *pattern), ...) __attribute__((format(printf,1,2)));
-
-/* ircd.c */
-extern EVENT(garbage_collect);
-extern EVENT(loop_event);
-extern EVENT(check_pings);
-extern EVENT(handshake_timeout);
-extern EVENT(check_deadsockets);
-extern EVENT(try_connections);
-/* support.c */
-extern char *my_itoa(int i);
-
-/* s_serv.c */
-extern void load_tunefile(void);
-extern EVENT(save_tunefile);
-extern void read_motd(const char *filename, MOTDFile *motd);
-
-/* s_user.c */
-extern int target_limit_exceeded(Client *client, void *target, const char *name);
-extern void make_umodestr(void);
-extern char *get_usermode_string(Client *acptr);
-
-/* s_misc.c */
-extern char *convert_time(time_t ltime);
-
-/* whowas.c */
-extern void initwhowas(void);
-
-/* uid.c */
-extern void uid_init(void);
-extern const char *uid_get(void);
-
-#endif /* proto_h */
diff --git a/include/setup.h.in b/include/setup.h.in
index a4e0830..18f6908 100644
--- a/include/setup.h.in
+++ b/include/setup.h.in
@@ -115,6 +115,9 @@
/* Define to 1 if you have the `strlncat' function. */
#undef HAVE_STRLNCAT
+/* Define to 1 if you have the `strlncpy' function. */
+#undef HAVE_STRLNCPY
+
/* Define to 1 if you have the `syslog' function. */
#undef HAVE_SYSLOG
@@ -130,9 +133,6 @@
/* Define to 1 if you have the header file. */
#undef HAVE_UNISTD_H
-/* Define if you want modes shown in /list */
-#undef LIST_SHOW_MODES
-
/* Define the location of the log files */
#undef LOGDIR
@@ -181,9 +181,6 @@
/* Define the path of the pid file */
#undef PIDFILE
-/* Define if you want +a/+q prefixes */
-#undef PREFIX_AQ
-
/* Define the location of private libraries */
#undef PRIVATELIBDIR
diff --git a/include/struct.h b/include/struct.h
index 2e1e33e..d820f2b 100644
--- a/include/struct.h
+++ b/include/struct.h
@@ -39,6 +39,7 @@
#include
#include
#include
+#include
#include "common.h"
#include "sys.h"
#include
@@ -54,6 +55,14 @@
# ifdef SYSSYSLOGH
# include
# endif
+#ifndef UNREAL_LOGGER_CODE
+/* undef these as they cause confusion with our ULOG_xxx codes */
+#undef LOG_DEBUG
+#undef LOG_INFO
+#undef LOG_WARNING
+#undef LOG_ERROR
+#undef LOG_FATAL
+#endif
#endif
#define PCRE2_CODE_UNIT_WIDTH 8
#include "pcre2.h"
@@ -92,19 +101,15 @@ typedef struct ConfigFlag_allow ConfigFlag_allow;
typedef struct ConfigItem_allow_channel ConfigItem_allow_channel;
typedef struct ConfigItem_allow_dcc ConfigItem_allow_dcc;
typedef struct ConfigItem_vhost ConfigItem_vhost;
-typedef struct ConfigItem_except ConfigItem_except;
typedef struct ConfigItem_link ConfigItem_link;
typedef struct ConfigItem_ban ConfigItem_ban;
typedef struct ConfigItem_deny_dcc ConfigItem_deny_dcc;
typedef struct ConfigItem_deny_link ConfigItem_deny_link;
typedef struct ConfigItem_deny_channel ConfigItem_deny_channel;
typedef struct ConfigItem_deny_version ConfigItem_deny_version;
-typedef struct ConfigItem_log ConfigItem_log;
-typedef struct ConfigItem_unknown ConfigItem_unknown;
-typedef struct ConfigItem_unknown_ext ConfigItem_unknown_ext;
typedef struct ConfigItem_alias ConfigItem_alias;
typedef struct ConfigItem_alias_format ConfigItem_alias_format;
-typedef struct ConfigItem_include ConfigItem_include;
+typedef struct ConfigResource ConfigResource;
typedef struct ConfigItem_blacklist_module ConfigItem_blacklist_module;
typedef struct ConfigItem_help ConfigItem_help;
typedef struct ConfigItem_offchans ConfigItem_offchans;
@@ -129,9 +134,6 @@ typedef struct Mode Mode;
typedef struct MessageTag MessageTag;
typedef struct MOTDFile MOTDFile; /* represents a whole MOTD, including remote MOTD support info */
typedef struct MOTDLine MOTDLine; /* one line of a MOTD stored as a linked list */
-#ifdef USE_LIBCURL
-typedef struct MOTDDownload MOTDDownload; /* used to coordinate download of a remote MOTD */
-#endif
typedef struct RealCommand RealCommand;
typedef struct CommandOverride CommandOverride;
@@ -163,13 +165,11 @@ typedef OperPermission (*OperClassEntryEvalCallback)(OperClassACLEntryVar* varia
#include "dbuf.h" /* THIS REALLY SHOULDN'T BE HERE!!! --msa */
#endif
-#define HOSTLEN 63 /* Length of hostname. Updated to */
- /* comply with RFC1123 */
-
+#define HOSTLEN 63 /* Length of hostname */
#define NICKLEN 30
#define USERLEN 10
#define REALLEN 50
-#define SVIDLEN 30
+#define ACCOUNTLEN 30
#define MAXTOPICLEN 360 /* absolute maximum permitted topic length (above this = potential desync) */
#define MAXAWAYLEN 360 /* absolute maximum permitted away length (above this = potential desync) */
#define MAXKICKLEN 360 /* absolute maximum kick length (above this = only cutoff danger) */
@@ -182,8 +182,8 @@ typedef OperPermission (*OperClassEntryEvalCallback)(OperClassACLEntryVar* varia
#define READBUFSIZE 8192 /* for the read buffer */
#define MAXRECIPIENTS 20
#define MAXSILELENGTH NICKLEN+USERLEN+HOSTLEN+10
-#define IDLEN 10
-#define SIDLEN 3
+#define IDLEN 12
+#define SIDLEN 3
#define SWHOISLEN 256
#define UMODETABLESZ (sizeof(long) * 8)
#define MAXCCUSERS 20 /* Maximum for set::anti-flood::max-concurrent-conversations */
@@ -203,16 +203,77 @@ typedef OperPermission (*OperClassEntryEvalCallback)(OperClassACLEntryVar* varia
/* Logging types */
#define LOG_ERROR 0x0001
#define LOG_KILL 0x0002
-#define LOG_TKL 0x0004
-#define LOG_KLINE 0x0008
-#define LOG_CLIENT 0x0010
-#define LOG_SERVER 0x0020
-#define LOG_OPER 0x0040
#define LOG_SACMDS 0x0080
#define LOG_CHGCMDS 0x0100
#define LOG_OVERRIDE 0x0200
-#define LOG_SPAMFILTER 0x0400
-#define LOG_FLOOD 0x0800
+
+typedef enum LogFieldType {
+ LOG_FIELD_INTEGER, // and unsigned?
+ LOG_FIELD_STRING,
+ LOG_FIELD_CLIENT,
+ LOG_FIELD_CHANNEL,
+ LOG_FIELD_OBJECT
+} LogFieldType;
+
+typedef struct LogData {
+ LogFieldType type;
+ char *key;
+ union {
+ int64_t integer;
+ char *string;
+ Client *client;
+ Channel *channel;
+ json_t *object;
+ } value;
+} LogData;
+
+/** New log levels for unreal_log() */
+/* Note: the reason for these high numbers is so we can easily catch
+ * if someone makes a mistake to use LOG_INFO (from syslog.h) instead
+ * of the ULOG_xxx levels.
+ */
+typedef enum LogLevel {
+ ULOG_INVALID = 0,
+ ULOG_DEBUG = 1000,
+ ULOG_INFO = 2000,
+ ULOG_WARNING = 3000,
+ ULOG_ERROR = 4000,
+ ULOG_FATAL = 5000
+} LogLevel;
+
+/** Logging types (text, json, etc) */
+typedef enum LogType {
+ LOG_TYPE_INVALID = 0,
+ LOG_TYPE_TEXT = 1,
+ LOG_TYPE_JSON = 2,
+} LogType;
+
+#define LOG_CATEGORY_LEN 32
+#define LOG_EVENT_ID_LEN 64
+typedef struct LogSource LogSource;
+struct LogSource {
+ LogSource *prev, *next;
+ LogLevel loglevel;
+ char negative; /**< 1 if negative match (eg !operoverride), 0 if normal */
+ char subsystem[LOG_CATEGORY_LEN+1];
+ char event_id[LOG_EVENT_ID_LEN+1];
+};
+
+typedef struct Log Log;
+struct Log {
+ Log *prev, *next;
+ LogSource *sources;
+ char destination[CHANNELLEN+1];
+ char *file;
+ char *filefmt;
+ long maxsize;
+ int type;
+ int logfd;
+};
+
+/** This is used for deciding the in logs[] and temp_logs[] */
+typedef enum LogDestination { LOG_DEST_SNOMASK=0, LOG_DEST_OPER=1, LOG_DEST_REMOTE=2, LOG_DEST_CHANNEL=3, LOG_DEST_DISK=4 } LogDestination;
+#define NUM_LOG_DESTINATIONS 5
/*
** 'offsetof' is defined in ANSI-C. The following definition
@@ -251,7 +312,7 @@ typedef OperPermission (*OperClassEntryEvalCallback)(OperClassACLEntryVar* varia
/** This specifies the current client status or the client type - see @link ClientStatus @endlink in particular.
* You may think "server" or "client" are the only choices here, but there are many more
- * such as states where the user is in the middle of an SSL/TLS handshake.
+ * such as states where the user is in the middle of an TLS handshake.
* @defgroup ClientStatuses Client statuses / types
* @{
*/
@@ -259,8 +320,8 @@ typedef enum ClientStatus {
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 */
- CLIENT_STATUS_TLS_CONNECT_HANDSHAKE = -5, /**< Client is doing an SSL/TLS handshake - outgoing connection */
- CLIENT_STATUS_TLS_ACCEPT_HANDSHAKE = -4, /**< Client is doing an SSL/TLS handshake - incoming connection */
+ CLIENT_STATUS_TLS_CONNECT_HANDSHAKE = -5, /**< Client is doing an TLS handshake - outgoing connection */
+ CLIENT_STATUS_TLS_ACCEPT_HANDSHAKE = -4, /**< Client is doing an TLS handshake - incoming connection */
CLIENT_STATUS_HANDSHAKE = -3, /**< Client is doing a server handshake - outgoing connection */
CLIENT_STATUS_ME = -2, /**< Client is &me (this server) */
CLIENT_STATUS_UNKNOWN = -1, /**< Client is doing a hanshake. May become a server or user later, we don't know yet */
@@ -325,16 +386,17 @@ typedef enum ClientStatus {
#define CLIENT_FLAG_DCCNOTICE 0x00200000 /**< Has the user seen a notice on how to use DCCALLOW already? */
#define CLIENT_FLAG_SHUNNED 0x00400000 /**< Connection is shunned (user cannot execute any commands) */
#define CLIENT_FLAG_VIRUS 0x00800000 /**< Tagged by spamfilter as a virus */
-#define CLIENT_FLAG_TLS 0x01000000 /**< Connection is using SSL/TLS */
+#define CLIENT_FLAG_TLS 0x01000000 /**< Connection is using TLS */
#define CLIENT_FLAG_NOFAKELAG 0x02000000 /**< Exemption from fake lag */
#define CLIENT_FLAG_DCCBLOCK 0x04000000 /**< Block all DCC send requests */
#define CLIENT_FLAG_MAP 0x08000000 /**< Show this entry in /MAP (only used in map module) */
#define CLIENT_FLAG_PINGWARN 0x10000000 /**< Server ping warning (remote server slow with responding to PINGs) */
#define CLIENT_FLAG_NOHANDSHAKEDELAY 0x20000000 /**< No handshake delay */
+#define CLIENT_FLAG_SERVER_DISCONNECT_LOGGED 0x40000000 /**< Server disconnect message is (already) logged */
+
/** @} */
-#define SNO_DEFOPER "+kscfvGqobS"
-#define SNO_DEFUSER "+ks"
+#define OPER_SNOMASKS "+bBcdfkqsSoO"
#define SEND_UMODES (SendUmodes)
#define ALL_UMODES (AllUmodes)
@@ -346,13 +408,14 @@ typedef enum ClientStatus {
* Note that client protocol extensions have been moved
* to the ClientCapability API which uses acptr->local->caps.
*/
-#define PROTO_VL 0x000040 /* Negotiated VL protocol */
-#define PROTO_VHP 0x000100 /* Send hostnames in NICKv2 even if not sethosted */
-#define PROTO_CLK 0x001000 /* Send cloaked host in the NICK command (regardless of +x/-x) */
-#define PROTO_MLOCK 0x002000 /* server supports MLOCK */
-#define PROTO_EXTSWHOIS 0x004000 /* extended SWHOIS support */
-#define PROTO_SJSBY 0x008000 /* SJOIN setby information (TS and nick) */
-#define PROTO_MTAGS 0x010000 /* Support message tags and big buffers */
+#define PROTO_VL 0x000001 /* Negotiated VL protocol */
+#define PROTO_VHP 0x000002 /* Send hostnames in NICKv2 even if not sethosted */
+#define PROTO_CLK 0x000004 /* Send cloaked host in the NICK command (regardless of +x/-x) */
+#define PROTO_MLOCK 0x000008 /* server supports MLOCK */
+#define PROTO_EXTSWHOIS 0x000010 /* extended SWHOIS support */
+#define PROTO_SJSBY 0x000020 /* SJOIN setby information (TS and nick) */
+#define PROTO_MTAGS 0x000040 /* Support message tags and big buffers */
+#define PROTO_NEXTBANS 0x000080 /* Server supports named extended bans */
/* For client capabilities: */
#define CAP_INVERT 1L
@@ -368,41 +431,21 @@ typedef enum ClientStatus {
#define IsDeaf(x) ((x)->umodes & UMODE_DEAF)
#define IsOper(x) ((x)->umodes & UMODE_OPER)
#define IsInvisible(x) ((x)->umodes & UMODE_INVISIBLE)
-#define IsARegNick(x) ((x)->umodes & (UMODE_REGNICK))
#define IsRegNick(x) ((x)->umodes & UMODE_REGNICK)
-#define SendWallops(x) (!IsMe(x) && IsUser(x) && ((x)->umodes & UMODE_WALLOP))
#define IsHidden(x) ((x)->umodes & UMODE_HIDE)
#define IsSetHost(x) ((x)->umodes & UMODE_SETHOST)
#define IsHideOper(x) ((x)->umodes & UMODE_HIDEOPER)
#define SetOper(x) ((x)->umodes |= UMODE_OPER)
#define SetInvisible(x) ((x)->umodes |= UMODE_INVISIBLE)
-#define SetWallops(x) ((x)->umodes |= UMODE_WALLOP)
#define SetRegNick(x) ((x)->umodes & UMODE_REGNICK)
#define SetHidden(x) ((x)->umodes |= UMODE_HIDE)
#define SetHideOper(x) ((x)->umodes |= UMODE_HIDEOPER)
#define IsSecureConnect(x) ((x)->umodes & UMODE_SECURE)
#define ClearOper(x) ((x)->umodes &= ~UMODE_OPER)
#define ClearInvisible(x) ((x)->umodes &= ~UMODE_INVISIBLE)
-#define ClearWallops(x) ((x)->umodes &= ~UMODE_WALLOP)
#define ClearHidden(x) ((x)->umodes &= ~UMODE_HIDE)
#define ClearHideOper(x) ((x)->umodes &= ~UMODE_HIDEOPER)
-/* Snomask macros: */
-#define SendServNotice(x) (((x)->user) && ((x)->user->snomask & SNO_SNOTICE))
-#define IsKillsF(x) ((x)->user->snomask & SNO_KILLS)
-#define IsClientF(x) ((x)->user->snomask & SNO_CLIENT)
-#define IsFloodF(x) ((x)->user->snomask & SNO_FLOOD)
-#define IsEyes(x) ((x)->user->snomask & SNO_EYES)
-#define SetKillsF(x) ((x)->user->snomask |= SNO_KILLS)
-#define SetClientF(x) ((x)->user->snomask |= SNO_CLIENT)
-#define SetFloodF(x) ((x)->user->snomask |= SNO_FLOOD)
-#define SetEyes(x) ((x)->user->snomask |= SNO_EYES)
-#define ClearKillsF(x) ((x)->user->snomask &= ~SNO_KILLS)
-#define ClearClientF(x) ((x)->user->snomask &= ~SNO_CLIENT)
-#define ClearFloodF(x) ((x)->user->snomask &= ~SNO_FLOOD)
-#define ClearEyes(x) ((x)->user->snomask &= ~SNO_EYES)
-
-
/* Client flags macros: to check for via IsXX(),
* to set via SetXX() and to clear the flag via ClearXX()
*/
@@ -416,6 +459,7 @@ typedef enum ClientStatus {
#define IsDCCNotice(x) ((x)->flags & CLIENT_FLAG_DCCNOTICE)
#define IsDead(x) ((x)->flags & CLIENT_FLAG_DEAD)
#define IsDeadSocket(x) ((x)->flags & CLIENT_FLAG_DEADSOCKET)
+#define IsServerDisconnectLogged(x) ((x)->flags & CLIENT_FLAG_SERVER_DISCONNECT_LOGGED)
#define IsUseIdent(x) ((x)->flags & CLIENT_FLAG_USEIDENT)
#define IsDNSLookup(x) ((x)->flags & CLIENT_FLAG_DNSLOOKUP)
#define IsEAuth(x) ((x)->flags & CLIENT_FLAG_EAUTH)
@@ -447,6 +491,7 @@ typedef enum ClientStatus {
#define SetDCCNotice(x) do { (x)->flags |= CLIENT_FLAG_DCCNOTICE; } while(0)
#define SetDead(x) do { (x)->flags |= CLIENT_FLAG_DEAD; } while(0)
#define SetDeadSocket(x) do { (x)->flags |= CLIENT_FLAG_DEADSOCKET; } while(0)
+#define SetServerDisconnectLogged(x) do { (x)->flags |= CLIENT_FLAG_SERVER_DISCONNECT_LOGGED; } while(0)
#define SetUseIdent(x) do { (x)->flags |= CLIENT_FLAG_USEIDENT; } while(0)
#define SetDNSLookup(x) do { (x)->flags |= CLIENT_FLAG_DNSLOOKUP; } while(0)
#define SetEAuth(x) do { (x)->flags |= CLIENT_FLAG_EAUTH; } while(0)
@@ -508,9 +553,9 @@ typedef enum ClientStatus {
#define IsNotSpoof(x) ((x)->local->nospoof == 0)
#define GetHost(x) (IsHidden(x) ? (x)->user->virthost : (x)->user->realhost)
#define GetIP(x) (x->ip ? x->ip : "255.255.255.255")
-#define IsLoggedIn(x) (IsRegNick(x) || (x->user && (*x->user->svid != '*') && !isdigit(*x->user->svid))) /* registered nick (+r) or just logged into services (may be -r) */
-#define IsSynched(x) (x->serv->flags.synced)
-#define IsServerSent(x) (x->serv && x->serv->flags.server_sent)
+#define IsLoggedIn(x) (x->user && (*x->user->account != '*') && !isdigit(*x->user->account)) /**< Logged into services */
+#define IsSynched(x) (x->server->flags.synced)
+#define IsServerSent(x) (x->server && x->server->flags.server_sent)
/* And more that access client stuff - but actually modularized */
#define GetReputation(client) (moddata_client_get(client, "reputation") ? atoi(moddata_client_get(client, "reputation")) : 0) /**< Get reputation value for a client */
@@ -527,33 +572,14 @@ typedef enum ClientStatus {
#define SupportVHP(x) (CHECKSERVERPROTO(x, PROTO_VHP))
#define SupportCLK(x) (CHECKSERVERPROTO(x, PROTO_CLK))
#define SupportMTAGS(x) (CHECKSERVERPROTO(x, PROTO_MTAGS))
+#define SupportNEXTBANS(x) (CHECKSERVERPROTO(x, PROTO_NEXTBANS))
#define SetVL(x) ((x)->local->proto |= PROTO_VL)
#define SetSJSBY(x) ((x)->local->proto |= PROTO_SJSBY)
#define SetVHP(x) ((x)->local->proto |= PROTO_VHP)
#define SetCLK(x) ((x)->local->proto |= PROTO_CLK)
#define SetMTAGS(x) ((x)->local->proto |= PROTO_MTAGS)
-
-/*
- * defined debugging levels
- */
-#define DEBUG_FATAL 0
-#define DEBUG_ERROR 1 /* report_error() and other errors that are found */
-#define DEBUG_NOTICE 3
-#define DEBUG_DNS 4 /* used by all DNS related routines - a *lot* */
-#define DEBUG_INFO 5 /* general usful info */
-#define DEBUG_NUM 6 /* numerics */
-#define DEBUG_SEND 7 /* everything that is sent out */
-#define DEBUG_DEBUG 8 /* anything to do with debugging, ie unimportant :) */
-#define DEBUG_MALLOC 9 /* malloc/free calls */
-#define DEBUG_LIST 10 /* debug list use */
-
-/*
- * defines for curses in client
- */
-#define DUMMY_TERM 0
-#define CURSES_TERM 1
-#define TERMCAP_TERM 2
+#define SetNEXTBANS(x) ((x)->local->proto |= PROTO_NEXTBANS)
/* Dcc deny types (see src/s_extra.c) */
#define DCCDENY_HARD 0
@@ -576,12 +602,20 @@ union ModData
#ifndef _WIN32
#define CHECK_LIST_ENTRY(list) if (offsetof(typeof(*list),prev) != offsetof(ListStruct,prev)) \
{ \
- ircd_log(LOG_ERROR, "[BUG] %s:%d: List operation on struct with incorrect order (->prev must be 1st struct member)", __FILE__, __LINE__); \
+ unreal_log(ULOG_FATAL, "main", "BUG_LIST_OPERATION", NULL, \
+ "[BUG] $file:$line: List operation on struct with incorrect order ($error_details)", \
+ log_data_string("error_details", "->prev must be 1st struct member"), \
+ log_data_string("file", __FILE__), \
+ log_data_integer("line", __LINE__)); \
abort(); \
} \
if (offsetof(typeof(*list),next) != offsetof(ListStruct,next)) \
{ \
- ircd_log(LOG_ERROR, "[BUG] %s:%d: List operation on struct with incorrect order (->next must be 2nd struct member))", __FILE__, __LINE__); \
+ unreal_log(ULOG_FATAL, "main", "BUG_LIST_OPERATION", NULL, \
+ "[BUG] $file:$line: List operation on struct with incorrect order ($error_details)", \
+ log_data_string("error_details", "->next must be 2nd struct member"), \
+ log_data_string("file", __FILE__), \
+ log_data_integer("line", __LINE__)); \
abort(); \
}
#else
@@ -591,17 +625,29 @@ union ModData
#ifndef _WIN32
#define CHECK_PRIO_LIST_ENTRY(list) if (offsetof(typeof(*list),prev) != offsetof(ListStructPrio,prev)) \
{ \
- ircd_log(LOG_ERROR, "[BUG] %s:%d: List operation on struct with incorrect order (->prev must be 1st struct member)", __FILE__, __LINE__); \
+ unreal_log(ULOG_FATAL, "main", "BUG_LIST_OPERATION", NULL, \
+ "[BUG] $file:$line: List operation on struct with incorrect order ($error_details)", \
+ log_data_string("error_details", "->prev must be 1st struct member"), \
+ log_data_string("file", __FILE__), \
+ log_data_integer("line", __LINE__)); \
abort(); \
} \
if (offsetof(typeof(*list),next) != offsetof(ListStructPrio,next)) \
{ \
- ircd_log(LOG_ERROR, "[BUG] %s:%d: List operation on struct with incorrect order (->next must be 2nd struct member))", __FILE__, __LINE__); \
+ unreal_log(ULOG_FATAL, "main", "BUG_LIST_OPERATION", NULL, \
+ "[BUG] $file:$line: List operation on struct with incorrect order ($error_details)", \
+ log_data_string("error_details", "->next must be 2nd struct member"), \
+ log_data_string("file", __FILE__), \
+ log_data_integer("line", __LINE__)); \
abort(); \
} \
if (offsetof(typeof(*list),priority) != offsetof(ListStructPrio,priority)) \
{ \
- ircd_log(LOG_ERROR, "[BUG] %s:%d: List operation on struct with incorrect order (->priority must be 3rd struct member))", __FILE__, __LINE__); \
+ unreal_log(ULOG_FATAL, "main", "BUG_LIST_OPERATION", NULL, \
+ "[BUG] $file:$line: List operation on struct with incorrect order ($error_details)", \
+ log_data_string("error_details", "->priority must be 3rd struct member"), \
+ log_data_string("file", __FILE__), \
+ log_data_integer("line", __LINE__)); \
abort(); \
}
#else
@@ -610,7 +656,10 @@ union ModData
#define CHECK_NULL_LIST_ITEM(item) if ((item)->prev || (item)->next) \
{ \
- ircd_log(LOG_ERROR, "[BUG] %s:%d: List operation on item with non-NULL 'prev' or 'next' -- are you adding to a list twice?", __FILE__, __LINE__); \
+ unreal_log(ULOG_FATAL, "main", "BUG_LIST_OPERATION_DOUBLE_ADD", NULL, \
+ "[BUG] $file:$line: List operation on item with non-NULL 'prev' or 'next' -- are you adding to a list twice?", \
+ log_data_string("file", __FILE__), \
+ log_data_integer("line", __LINE__)); \
abort(); \
}
@@ -711,43 +760,10 @@ struct MultiLine {
char *line;
};
-#ifdef USE_LIBCURL
-struct MOTDDownload
-{
- MOTDFile *themotd;
-};
-#endif /* USE_LIBCURL */
-
struct MOTDFile
{
struct MOTDLine *lines;
struct tm last_modified; /* store the last modification time */
-
-#ifdef USE_LIBCURL
- /*
- This pointer is used to communicate with an asynchronous MOTD
- download. The problem is that a download may take 10 seconds or
- more to complete and, in that time, the IRCd could be rehashed.
- This would mean that TLD blocks are reallocated and thus the
- aMotd structs would be free()d in the meantime.
-
- To prevent such a situation from leading to a segfault, we
- introduce this remote control pointer. It works like this:
- 1. read_motd() is called with a URL. A new MOTDDownload is
- allocated and the pointer is placed here. This pointer is
- also passed to the asynchrnous download handler.
- 2.a. The download is completed and read_motd_async_downloaded()
- is called with the same pointer. From this function, this pointer
- if free()d. No other code may free() the pointer. Not even free_motd().
- OR
- 2.b. The user rehashes the IRCd before the download is completed.
- free_motd() is called, which sets motd_download->themotd to NULL
- to signal to read_motd_async_downloaded() that it should ignore
- the download. read_motd_async_downloaded() is eventually called
- and frees motd_download.
- */
- struct MOTDDownload *motd_download;
-#endif /* USE_LIBCURL */
};
struct MOTDLine {
@@ -758,16 +774,17 @@ struct MOTDLine {
struct LoopStruct {
unsigned do_garbage_collect : 1;
unsigned config_test : 1;
- unsigned ircd_booted : 1;
- unsigned ircd_forked : 1;
+ unsigned booted : 1;
+ unsigned forked : 1;
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 ircd_rehashing : 1;
- unsigned ircd_terminating : 1;
+ 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;
- Client *rehash_save_cptr, *rehash_save_client;
- int rehash_save_sig;
+ Client *rehash_save_client;
void (*boot_function)();
};
@@ -801,7 +818,7 @@ typedef struct Whowas {
struct Whowas *prev; /* for hash table... */
struct Whowas *cnext; /* for client struct linked list */
struct Whowas *cprev; /* for client struct linked list */
-} aWhowas;
+} WhoWas;
typedef struct SWhois SWhois;
struct SWhois {
@@ -848,7 +865,7 @@ struct SWhois {
* Note that reading parv[parc] and beyond is OUT OF BOUNDS and will cause a crash.
* E.g. parv[3] in the above example is out of bounds.
*/
-#define CMD_FUNC(x) void (x) (Client *client, MessageTag *recv_mtags, int parc, char *parv[])
+#define CMD_FUNC(x) void (x) (Client *client, MessageTag *recv_mtags, int parc, const char *parv[])
/** @} */
/** Command override function - used by all command override handlers.
@@ -865,13 +882,13 @@ struct SWhois {
* Note that reading parv[parc] and beyond is OUT OF BOUNDS and will cause a crash.
* E.g. parv[3] in the above example.
*/
-#define CMD_OVERRIDE_FUNC(x) void (x)(CommandOverride *ovr, Client *client, MessageTag *recv_mtags, int parc, char *parv[])
+#define CMD_OVERRIDE_FUNC(x) void (x)(CommandOverride *ovr, Client *client, MessageTag *recv_mtags, int parc, const char *parv[])
-typedef void (*CmdFunc)(Client *client, MessageTag *mtags, int parc, char *parv[]);
-typedef void (*AliasCmdFunc)(Client *client, MessageTag *mtags, int parc, char *parv[], char *cmd);
-typedef void (*OverrideCmdFunc)(CommandOverride *ovr, Client *client, MessageTag *mtags, int parc, char *parv[]);
+typedef void (*CmdFunc)(Client *client, MessageTag *mtags, int parc, const char *parv[]);
+typedef void (*AliasCmdFunc)(Client *client, MessageTag *mtags, int parc, const char *parv[], const char *cmd);
+typedef void (*OverrideCmdFunc)(CommandOverride *ovr, Client *client, MessageTag *mtags, int parc, const char *parv[]);
#include
@@ -1106,21 +1123,30 @@ struct SpamExcept {
/** IRC Counts, used for /LUSERS */
typedef struct IRCCounts IRCCounts;
struct IRCCounts {
- int clients; /* total */
- int invisible; /* invisible */
- unsigned short servers; /* servers */
- int operators; /* operators */
- int unknown; /* unknown local connections */
- int channels; /* channels */
- int me_clients; /* my clients */
- unsigned short me_servers; /* my servers */
- int me_max; /* local max */
- int global_max; /* global max */
+ int clients; /* total */
+ int invisible; /* invisible */
+ int servers; /* servers */
+ int operators; /* operators */
+ int unknown; /* unknown local connections */
+ int channels; /* channels */
+ int me_clients; /* my clients */
+ int me_servers; /* my servers */
+ int me_max; /* local max */
+ int global_max; /* global max */
};
/** The /LUSERS stats information */
extern MODVAR IRCCounts irccounts;
+typedef struct NameValue NameValue;
+/** Name and value list used in a static array, such as in conf.c */
+struct NameValue
+{
+ long value;
+ char *name;
+};
+
+/** Name and value list used in dynamic linked lists */
typedef struct NameValueList NameValueList;
struct NameValueList {
NameValueList *prev, *next;
@@ -1166,21 +1192,12 @@ struct CommandOverride {
OverrideCmdFunc func;
};
-extern MODVAR Umode *Usermode_Table;
-extern MODVAR short Usermode_highest;
-
-extern MODVAR Snomask *Snomask_Table;
-extern MODVAR short Snomask_highest;
-
-extern MODVAR Cmode *Channelmode_Table;
-extern MODVAR unsigned short Channelmode_highest;
+extern MODVAR Umode *usermodes;
+extern MODVAR Cmode *channelmodes;
extern Umode *UmodeAdd(Module *module, char ch, int options, int unset_on_deoper, int (*allowed)(Client *client, int what), long *mode);
extern void UmodeDel(Umode *umode);
-extern Snomask *SnomaskAdd(Module *module, char ch, int (*allowed)(Client *client, int what), long *mode);
-extern void SnomaskDel(Snomask *sno);
-
extern Cmode *CmodeAdd(Module *reserved, CmodeInfo req, Cmode_t *mode);
extern void CmodeDel(Cmode *cmode);
@@ -1199,16 +1216,13 @@ extern void unload_all_unused_moddata(void);
#define IsServersOnlyListener(x) ((x) && ((x)->options & LISTENER_SERVERSONLY))
#define CONNECT_TLS 0x000001
-//0x000002 unused (was ziplinks)
-#define CONNECT_AUTO 0x000004
-#define CONNECT_QUARANTINE 0x000008
-#define CONNECT_NODNSCACHE 0x000010
-#define CONNECT_NOHOSTCHECK 0x000020
-#define CONNECT_INSECURE 0x000040
+#define CONNECT_AUTO 0x000002
+#define CONNECT_QUARANTINE 0x000004
+#define CONNECT_INSECURE 0x000008
-#define TLSFLAG_FAILIFNOCERT 0x1
-#define TLSFLAG_NOSTARTTLS 0x8
-#define TLSFLAG_DISABLECLIENTCERT 0x10
+#define TLSFLAG_FAILIFNOCERT 0x0001
+#define TLSFLAG_NOSTARTTLS 0x0002
+#define TLSFLAG_DISABLECLIENTCERT 0x0004
/** Flood counters for local clients */
typedef struct FloodCounter {
@@ -1225,9 +1239,17 @@ typedef enum FloodOption {
FLD_INVITE = 3, /**< invite-flood */
FLD_KNOCK = 4, /**< knock-flood */
FLD_CONVERSATIONS = 5, /**< max-concurrent-conversations */
+ FLD_LAG_PENALTY = 6, /**< lag-penalty / lag-penalty-bytes */
} FloodOption;
#define MAXFLOODOPTIONS 10
+typedef struct TrafficStats TrafficStats;
+struct TrafficStats {
+ long long messages_sent; /* IRC lines sent */
+ long long messages_received; /* IRC lines received */
+ long long bytes_sent; /* Bytes sent */
+ long long bytes_received; /* Received bytes */
+};
/** 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
@@ -1242,7 +1264,7 @@ struct Client {
struct list_head special_node; /**< For special lists (server || unknown || oper) */
LocalClient *local; /**< Additional information regarding locally connected clients */
User *user; /**< Additional information, if this client is a user */
- Server *serv; /**< Additional information, if this is a server */
+ Server *server; /**< Additional information, if this is a server */
ClientStatus status; /**< Client status, one of CLIENT_STATUS_* */
struct list_head client_hash; /**< For name hash table (clientTable) */
char name[HOSTLEN + 1]; /**< Unique name of the client: nickname for users, hostname for servers */
@@ -1257,7 +1279,7 @@ struct Client {
char info[REALLEN + 1]; /**< Additional client information text. For users this is gecos/realname */
char id[IDLEN + 1]; /**< Unique ID: SID or UID */
struct list_head id_hash; /**< For UID/SID hash table (idTable) */
- Client *srvptr; /**< Server on where this client is connected to (can be &me) */
+ Client *uplink; /**< Server on where this client is connected to (can be &me) */
char *ip; /**< IP address of user or server (never NULL) */
ModData moddata[MODDATA_MAX_CLIENT]; /**< Client attached module data, used by the ModData system */
};
@@ -1266,10 +1288,11 @@ struct Client {
*/
struct LocalClient {
int fd; /**< File descriptor, can be <0 if socket has been closed already. */
- SSL *ssl; /**< OpenSSL/LibreSSL struct for SSL/TLS connection */
- time_t since; /**< Time when user will next be allowed to send something (actually since0 if SASL authentication was successful */
time_t sasl_sent_time; /**< SASL: 0 or the time that the (last) AUTHENTICATE command has been sent */
- char *sni_servername; /**< Servername as sent by client via SNI (Server Name Indication) in SSL/TLS, otherwise NULL */
+ char *sni_servername; /**< Servername as sent by client via SNI (Server Name Indication) in TLS, otherwise NULL */
int cap_protocol; /**< CAP protocol in use. At least 300 for any CAP capable client. 302 for 3.2, etc.. */
uint32_t nospoof; /**< Anti-spoofing random number (used in user handshake PING/PONG) */
char *passwd; /**< Password used during connect, if any (freed once connected and set to NULL) */
@@ -1315,38 +1327,27 @@ struct LocalClient {
*/
struct User {
Membership *channel; /**< Channels that the user is in (linked list) */
- Link *invited; /**< Channels has the user been invited to (linked list) */
Link *dccallow; /**< DCCALLOW list (linked list) */
- char *away; /**< AWAY message, or NULL if not away */
- char svid[SVIDLEN + 1]; /**< Services account name or ID (SVID) */
- unsigned short joined; /**< Number of channels joined */
+ char account[ACCOUNTLEN + 1]; /**< Services account name or ID (SVID) - use IsLoggedIn(client) to check if logged in */
+ int joined; /**< Number of channels joined */
char username[USERLEN + 1]; /**< Username, the user portion in nick!user@host. */
char realhost[HOSTLEN + 1]; /**< Realhost, the real host of the user (IP or hostname) - usually this is not shown to other users */
char cloakedhost[HOSTLEN + 1]; /**< Cloaked host - generated by cloaking algorithm */
char *virthost; /**< Virtual host - when user has user mode +x this is the active host */
char *server; /**< Server name the user is on (?) */
SWhois *swhois; /**< Special "additional" WHOIS entries such as "a Network Administrator" */
- aWhowas *whowas; /**< Something for whowas :D :D */
- int snomask; /**< Server Notice Mask (snomask) - only for IRCOps */
- char *operlogin; /**< Which oper { } block was used to oper up, otherwise NULL - used by oper::maxlogins */
- struct {
- time_t nick_t; /**< For set::anti-flood::nick-flood: time */
- time_t knock_t; /**< For set::anti-flood::knock-flood: time */
- time_t invite_t; /**< For set::anti-flood::invite-flood: time */
- unsigned char nick_c; /**< For set::anti-flood::nick-flood: counter */
- unsigned char knock_c; /**< For set::anti-flood::knock-flood: counter */
- unsigned char invite_c; /**< For set::anti-flood::invite-flood: counter */
- } flood; /**< Anti-flood counters */
- time_t lastaway; /**< Last time the user went AWAY */
+ WhoWas *whowas; /**< Something for whowas :D :D */
+ char *snomask; /**< Server Notice Mask (snomask) - only for IRCOps */
+ char *operlogin; /**< Which oper { } block was used to oper up, otherwise NULL - used for auditting and by oper::maxlogins */
+ char *away; /**< AWAY message, or NULL if not away */
+ time_t away_since; /**< Last time the user went AWAY */
};
-/** Server information (local servers and remote servers), you use client->serv to access these (see also @link Client @endlink).
+/** Server information (local servers and remote servers), you use client->server to access these (see also @link Client @endlink).
*/
struct Server {
- char *up; /**< Name of uplink for this server */
char by[NICKLEN + 1]; /**< Uhhhh - who activated this connection - AGAIN? */
ConfigItem_link *conf; /**< link { } block associated with this server, or NULL */
- time_t timestamp; /**< Remotely determined connect try time */
long users; /**< Number of users on this server */
time_t boottime; /**< Startup time of server (boot time) */
struct {
@@ -1424,20 +1425,29 @@ struct ConditionalConfig
char *opt; /**< Only for IF_VALUE */
};
+/** Configuration file (config parser) */
struct ConfigFile
{
- char *cf_filename;
- ConfigEntry *cf_entries;
- ConfigFile *cf_next;
+ char *filename; /**< Filename of configuration file */
+ ConfigEntry *items; /**< All items in the configuration file */
+ ConfigFile *next; /**< Next configuration file */
};
+/** Configuration entry (config parser) */
struct ConfigEntry
{
- ConfigFile *ce_fileptr;
- int ce_varlinenum, ce_fileposstart, ce_fileposend, ce_sectlinenum;
- char *ce_varname, *ce_vardata;
- ConfigEntry *ce_entries, *ce_prevlevel, *ce_next;
- ConditionalConfig *ce_cond;
+ char *name; /**< Variable name */
+ char *value; /**< Variable value, can be NULL */
+ ConfigEntry *next; /**< Next ConfigEntry */
+ ConfigEntry *items; /**< Items (children), can be NULL */
+ ConfigFile *file; /**< To which configfile does this belong? */
+ int line_number; /**< Line number of the variable name (this one is usually used for errors) */
+ int file_position_start; /**< Position (byte) within configuration file of the start of the block, rarely used */
+ int file_position_end; /**< Position (byte) within configuration file of the end of the block, rarely used */
+ int section_linenumber; /**< Line number of the section (only used internally for parse errors) */
+ ConfigEntry *parent; /**< Parent item, can be NULL */
+ ConditionalConfig *conditional_config; /**< Used for conditional config by the main parser */
+ unsigned escaped:1;
};
struct ConfigFlag
@@ -1524,8 +1534,7 @@ struct ConfigFlag_allow {
struct ConfigItem_allow {
ConfigItem_allow *prev, *next;
ConfigFlag flag;
- char *ip;
- char *hostname;
+ ConfigItem_mask *mask;
char *server;
AuthConfig *auth;
int maxperip; /**< Maximum connections permitted per IP address (locally) */
@@ -1533,7 +1542,7 @@ struct ConfigItem_allow {
int port;
ConfigItem_class *class;
ConfigFlag_allow flags;
- unsigned short ipv6_clone_mask;
+ int ipv6_clone_mask;
};
struct OperClassACLPath
@@ -1576,7 +1585,7 @@ struct OperClassCheckParams
Client *client;
Client *victim;
Channel *channel;
- void *extra;
+ const void *extra;
};
struct ConfigItem_operclass {
@@ -1596,9 +1605,10 @@ struct ConfigItem_oper {
unsigned long modes, require_modes;
char *vhost;
int maxlogins;
+ int server_notice_colors;
};
-/** The SSL/TLS options that are used in set::tls and otherblocks::tls-options.
+/** The TLS options that are used in set::tls and otherblocks::tls-options.
* NOTE: If you add something here then you must also update the
* conf_tlsblock() function in s_conf.c to have it inherited
* from set::tls to the other config blocks!
@@ -1645,7 +1655,8 @@ struct ConfigItem_ulines {
struct ConfigItem_tld {
ConfigItem_tld *prev, *next;
ConfigFlag_tld flag;
- char *mask, *channel;
+ ConfigItem_mask *mask;
+ char *channel;
char *motd_file, *rules_file, *smotd_file;
char *botmotd_file, *opermotd_file;
MOTDFile rules, motd, smotd, botmotd, opermotd;
@@ -1663,6 +1674,7 @@ struct ConfigItem_listen {
SSL_CTX *ssl_ctx;
TLSOptions *tls_options;
int websocket_options; /* should be in module, but lazy */
+ char *websocket_forward;
};
struct ConfigItem_sni {
@@ -1711,13 +1723,6 @@ struct ConfigItem_link {
TLSOptions *tls_options; /**< SSL Options for outgoing connection (optional) */
};
-struct ConfigItem_except {
- ConfigItem_except *prev, *next;
- ConfigFlag_except flag;
- int type;
- char *mask;
-};
-
struct ConfigItem_ban {
ConfigItem_ban *prev, *next;
ConfigFlag_ban flag;
@@ -1734,7 +1739,8 @@ struct ConfigItem_deny_dcc {
struct ConfigItem_deny_link {
ConfigItem_deny_link *prev, *next;
ConfigFlag_except flag;
- char *mask, *rule, *prettyrule;
+ ConfigItem_mask *mask;
+ char *rule, *prettyrule;
};
struct ConfigItem_deny_version {
@@ -1764,32 +1770,6 @@ struct ConfigItem_allow_dcc {
char *filename;
};
-struct ConfigItem_log {
- ConfigItem_log *prev, *next;
- ConfigFlag flag;
- char *file; /**< Filename to log to (either generated or specified) */
- char *filefmt; /**< Filename with dynamic % stuff */
- long maxsize;
- int flags;
- int logfd;
-};
-
-struct ConfigItem_unknown {
- ConfigItem_unknown *prev, *next;
- ConfigFlag flag;
- ConfigEntry *ce;
-};
-
-struct ConfigItem_unknown_ext {
- ConfigItem_unknown_ext *prev, *next;
- ConfigFlag flag;
- char *ce_varname, *ce_vardata;
- ConfigFile *ce_fileptr;
- int ce_varlinenum;
- ConfigEntry *ce_entries;
-};
-
-
typedef enum {
ALIAS_SERVICES=1, ALIAS_STATS, ALIAS_NORMAL, ALIAS_COMMAND, ALIAS_CHANNEL, ALIAS_REAL
} AliasType;
@@ -1812,33 +1792,23 @@ struct ConfigItem_alias_format {
Match *expr;
};
-/**
- * In a rehash scenario, conf_include will contain all of the included
- * configs that are actually in use. It also will contain includes
- * that are being processed so that the configuration may be updated.
- * INCLUDE_NOTLOADED is set on all of the config files that are being
- * loaded and unset on already-loaded files. See
- * unload_loaded_includes() and load_includes().
- */
-#define INCLUDE_NOTLOADED 0x1
-#define INCLUDE_REMOTE 0x2
-#define INCLUDE_DLQUEUED 0x4
-/**
- * Marks that an include was loaded without error. This seems to
- * overlap with the INCLUDE_NOTLOADED meaning(?). --binki
- */
-#define INCLUDE_USED 0x8
+#define RESOURCE_REMOTE 0x1
+#define RESOURCE_DLQUEUED 0x2
+#define RESOURCE_INCLUDE 0x4
+
+typedef struct ConfigEntryWrapper ConfigEntryWrapper;
+struct ConfigEntryWrapper {
+ ConfigEntryWrapper *prev, *next;
+ ConfigEntry *ce;
+};
-struct ConfigItem_include {
- ConfigItem_include *prev, *next;
- ConfigFlag_ban flag;
- char *file;
-#ifdef USE_LIBCURL
- char *url;
- char *errorbuf;
-#endif
- char *included_from;
- int included_from_line;
+struct ConfigResource {
+ ConfigResource *prev, *next;
+ int type;
+ ConfigEntryWrapper *wce; /**< The place(s) where this resource is begin used */
+ char *file; /**< File to read: can be a conf/something file or a downloaded file */
+ char *url; /**< URL, if it is an URL */
+ char *cache_file; /**< Set to filename of local cached copy, if it is available */
};
struct ConfigItem_blacklist_module {
@@ -1855,7 +1825,7 @@ struct ConfigItem_help {
struct ConfigItem_offchans {
ConfigItem_offchans *prev, *next;
- char chname[CHANNELLEN+1];
+ char name[CHANNELLEN+1];
char *topic;
};
@@ -1868,6 +1838,7 @@ struct SecurityGroup {
int reputation_score;
int webirc;
int tls;
+ ConfigItem_mask *include_mask;
};
#define HM_HOST 1
@@ -1885,14 +1856,6 @@ struct IRCStatistics {
unsigned int is_cl; /* number of client connections */
unsigned int is_sv; /* number of server connections */
unsigned int is_ni; /* connection but no idea who it was */
- unsigned short is_cbs; /* bytes sent to clients */
- unsigned short is_cbr; /* bytes received to clients */
- unsigned short is_sbs; /* bytes sent to servers */
- unsigned short is_sbr; /* bytes received to servers */
- unsigned long is_cks; /* k-bytes sent to clients */
- unsigned long is_ckr; /* k-bytes received to clients */
- unsigned long is_sks; /* k-bytes sent to servers */
- unsigned long is_skr; /* k-bytes received to servers */
time_t is_cti; /* time spent connected by clients */
time_t is_sti; /* time spent connected by servers */
unsigned int is_ac; /* connections accepted */
@@ -1910,11 +1873,6 @@ struct IRCStatistics {
unsigned int is_loc; /* local connections made */
};
-typedef struct MemoryInfo {
- unsigned int classes;
- unsigned long classesmem;
-} MemoryInfo;
-
#define EXTCMODETABLESZ 32
/* Number of maximum paramter modes to allow.
@@ -1928,13 +1886,30 @@ typedef struct MemoryInfo {
* Otherwise, see the extended channel modes API, CmodeAdd(), etc.
*/
struct Mode {
- long mode; /**< Core modes set on this channel (one of MODE_*) */
- Cmode_t extmode; /**< Other ("extended") channel modes set on this channel */
- void *extmodeparams[MAXPARAMMODES+1]; /**< Parameters for extended channel modes */
- int limit; /**< The +l limit in effect (eg: 40), if any - otherwise 0 */
- char key[KEYLEN + 1]; /**< The +k key in effect (eg: secret), if any - otherwise NULL */
+ Cmode_t mode; /**< Other ("extended") channel modes set on this channel */
+ void *mode_params[MAXPARAMMODES+1]; /**< Parameters for extended channel modes */
};
+/* flags for Link if used to contain Watch --k4be */
+
+/* WATCH type */
+#define WATCH_FLAG_TYPE_WATCH (1<<0) /* added via /WATCH command */
+#define WATCH_FLAG_TYPE_MONITOR (1<<1) /* added via /MONITOR command */
+
+/* behaviour switches */
+#define WATCH_FLAG_AWAYNOTIFY (1<<8) /* should send AWAY notifications */
+
+/* watch triggering events */
+#define WATCH_EVENT_ONLINE 0
+#define WATCH_EVENT_OFFLINE 1
+#define WATCH_EVENT_AWAY 2
+#define WATCH_EVENT_NOTAWAY 3
+#define WATCH_EVENT_REAWAY 4
+#define WATCH_EVENT_USERHOST 5
+#define WATCH_EVENT_REALNAME 6
+#define WATCH_EVENT_LOGGEDIN 7
+#define WATCH_EVENT_LOGGEDOUT 8
+
/* Used for notify-hash buckets... -Donwulff */
struct Watch {
@@ -1962,6 +1937,8 @@ struct Link {
} value;
};
+#define IsInvalidChannelTS(x) ((x) <= 1000000) /**< Invalid channel creation time */
+
/**
* @addtogroup CommonStructs
* @{
@@ -1979,13 +1956,12 @@ struct Channel {
time_t topic_time; /**< Time at which the topic was last set */
int users; /**< Number of users in the channel */
Member *members; /**< List of channel members (users in the channel) */
- Link *invites; /**< List of outstanding /INVITE's from ops */
Ban *banlist; /**< List of bans (+b) */
Ban *exlist; /**< List of ban exceptions (+e) */
Ban *invexlist; /**< List of invite exceptions (+I) */
char *mode_lock; /**< Mode lock (MLOCK) applied to channel - usually by Services */
ModData moddata[MODDATA_MAX_CHANNEL]; /**< Channel attached module data, used by the ModData system */
- char chname[1]; /**< Channel name */
+ char name[CHANNELLEN+1]; /**< Channel name */
};
/** user/channel member struct (channel->members).
@@ -1997,7 +1973,7 @@ struct Member
{
struct Member *next; /**< Next entry in list */
Client *client; /**< The client */
- int flags; /**< The access of the user on this channel (one or more of CHFL_*) */
+ char member_modes[MEMBERMODESLEN]; /**< The access of the user on this channel (eg "vhoqa") */
ModData moddata[MODDATA_MAX_MEMBER]; /** Member attached module data, used by the ModData system */
};
@@ -2010,7 +1986,7 @@ struct Membership
{
struct Membership *next; /**< Next entry in list */
struct Channel *channel; /**< The channel */
- int flags; /**< The access of the user on this channel (one or more of CHFL_*) */
+ char member_modes[MEMBERMODESLEN]; /**< The (new) access of the user on this channel (eg "vhoqa") */
ModData moddata[MODDATA_MAX_MEMBERSHIP]; /**< Membership attached module data, used by the ModData system */
};
@@ -2024,97 +2000,18 @@ struct Ban {
time_t when; /**< When the entry was added */
};
-/*
-** Channel Related macros follow
-*/
-
-/* Channel related flags */
-#ifdef PREFIX_AQ
- #define CHFL_CHANOP_OR_HIGHER (CHFL_CHANOP|CHFL_CHANADMIN|CHFL_CHANOWNER)
- #define CHFL_HALFOP_OR_HIGHER (CHFL_CHANOWNER|CHFL_CHANADMIN|CHFL_CHANOP|CHFL_HALFOP)
-#else
- #define CHFL_CHANOP_OR_HIGHER (CHFL_CHANOP)
- #define CHFL_HALFOP_OR_HIGHER (CHFL_CHANOP|CHFL_HALFOP)
-#endif
-
-/** Channel flags (privileges) of users on a channel.
- * This is used by Member and Membership (m->flags) to indicate the access rights of a user in a channel.
- * Also used by SJOIN and MODE to set some flags while a JOIN or MODE is in process.
- * @defgroup ChannelFlags Channel access flags
- * @{
- */
-/** Is channel owner (+q) */
-#define is_chanowner(cptr,channel) (get_access(cptr,channel) & CHFL_CHANOWNER)
-/** Is channel admin (+a) */
-#define is_chanadmin(cptr,channel) (get_access(cptr,channel) & CHFL_CHANADMIN)
-/** Is channel operator or higher (+o/+a/+q) */
-#define is_chan_op(cptr,channel) (get_access(cptr,channel) & CHFL_CHANOP_OR_HIGHER)
-/** Is some kind of channel op (+h/+o/+a/+q) */
-#define is_skochanop(cptr,channel) (get_access(cptr,channel) & CHFL_HALFOP_OR_HIGHER)
-/** Is half-op (+h) */
-#define is_half_op(cptr,channel) (get_access(cptr,channel) & CHFL_HALFOP)
-/** Has voice (+v) */
-#define has_voice(cptr,channel) (get_access(cptr,channel) & CHFL_VOICE)
-/* Important:
- * Do not blindly change the values of CHFL_* as they must match the
- * ones in MODE_*. I already screwed this up twice. -- Syzop
- * Obviously these should be decoupled in a code cleanup.
- */
-#define CHFL_CHANOP 0x0001 /**< Channel operator (+o) */
-#define CHFL_VOICE 0x0002 /**< Voice (+v, can speak through bans and +m) */
-#define CHFL_DEOPPED 0x0004 /**< De-oped by a server (temporary state) */
-#define CHFL_CHANOWNER 0x0040 /**< Channel owner (+q) */
-#define CHFL_CHANADMIN 0x0080 /**< Channel admin (+a) */
-#define CHFL_HALFOP 0x0100 /**< Channel halfop (+h) */
-#define CHFL_BAN 0x0200 /**< Channel ban (+b) - not a real flag, only used in sjoin.c */
-#define CHFL_EXCEPT 0x0400 /**< Channel except (+e) - not a real flag, only used in sjoin.c */
-#define CHFL_INVEX 0x0800 /**< Channel invite exception (+I) - not a real flag, only used in sjoin.c */
-/** @} */
-
-#define CHFL_REJOINING 0x8000 /* used internally by rejoin_* */
-
-#define CHFL_OVERLAP (CHFL_CHANOWNER|CHFL_CHANADMIN|CHFL_CHANOP|CHFL_VOICE|CHFL_HALFOP)
-
/* Channel macros */
-/* Don't blindly change these MODE_* values, see comment 20 lines up! */
-#define MODE_CHANOP CHFL_CHANOP
-#define MODE_VOICE CHFL_VOICE
-#define MODE_PRIVATE 0x0004
-#define MODE_SECRET 0x0008
-#define MODE_MODERATED 0x0010
-#define MODE_TOPICLIMIT 0x0020
-#define MODE_CHANOWNER 0x0040
-#define MODE_CHANADMIN 0x0080
-#define MODE_HALFOP 0x0100
#define MODE_EXCEPT 0x0200
#define MODE_BAN 0x0400
-#define MODE_INVITEONLY 0x0800
-#define MODE_NOPRIVMSGS 0x1000
-#define MODE_KEY 0x2000
-#define MODE_LIMIT 0x4000
-#define MODE_RGSTR 0x8000
#define MODE_INVEX 0x8000000
-/*
- * mode flags which take another parameter (With PARAmeterS)
- */
-#define MODE_WPARAS (MODE_HALFOP|MODE_CHANOP|MODE_VOICE|MODE_CHANOWNER|MODE_CHANADMIN|MODE_BAN|MODE_KEY|MODE_LIMIT|MODE_EXCEPT|MODE_INVEX)
-/*
- * Undefined here, these are used in conjunction with the above modes in
- * the source.
-#define MODE_DEL 0x200000000
-#define MODE_ADD 0x400000000
- */
-
-#define HoldChannel(x) (!(x))
/* name invisible */
-#define SecretChannel(x) ((x) && ((x)->mode.mode & MODE_SECRET))
+#define SecretChannel(x) ((x) && has_channel_mode((x), 's'))
/* channel not shown but names are */
-#define HiddenChannel(x) ((x) && ((x)->mode.mode & MODE_PRIVATE))
+#define HiddenChannel(x) ((x) && has_channel_mode((x), 'p'))
/* channel visible */
#define ShowChannel(v,c) (PubChannel(c) || IsMember((v),(c)))
-#define PubChannel(x) ((!x) || ((x)->mode.mode &\
- (MODE_PRIVATE | MODE_SECRET)) == 0)
+#define PubChannel(x) (!SecretChannel((x)) && !HiddenChannel((x)))
#define IsChannelName(name) ((name) && (*(name) == '#'))
@@ -2194,11 +2091,19 @@ struct ParseMode {
char modechar;
char *param;
Cmode *extm;
- char *modebuf; /* curr pos */
- char *parabuf; /* curr pos */
+ const char *modebuf; /* curr pos */
+ const char *parabuf; /* curr pos */
char buf[512]; /* internal parse buffer */
};
+#define MAXMULTILINEMODES 3
+typedef struct MultiLineMode MultiLineMode;
+struct MultiLineMode {
+ char *modeline[MAXMULTILINEMODES+1];
+ char *paramline[MAXMULTILINEMODES+1];
+ int numlines;
+};
+
typedef struct PendingServer PendingServer;
struct PendingServer {
PendingServer *prev, *next;
@@ -2230,15 +2135,13 @@ struct MaxTarget {
#define MARK_AS_OFFICIAL_MODULE(modinf) do { if (modinf && modinf->handle) ModuleSetOptions(modinfo->handle, MOD_OPT_OFFICIAL, 1); } while(0)
#define MARK_AS_GLOBAL_MODULE(modinf) do { if (modinf && modinf->handle) ModuleSetOptions(modinfo->handle, MOD_OPT_GLOBAL, 1); } while(0)
-/* old.. please don't use anymore */
-#define CHANOPPFX "@"
-
/* used for is_banned type field: */
-#define BANCHK_JOIN 0 /* checking if a ban forbids the person from joining */
-#define BANCHK_MSG 1 /* checking if a ban forbids the person from sending messages */
-#define BANCHK_NICK 2 /* checking if a ban forbids the person from changing his/her nick */
-#define BANCHK_LEAVE_MSG 3 /* checking if a ban forbids the person from leaving a message in PART or QUIT */
-#define BANCHK_TKL 4 /* called from a server ban routine, or other match_user() usage */
+#define BANCHK_JOIN 0x0001 /* checking if a ban forbids the person from joining */
+#define BANCHK_MSG 0x0002 /* checking if a ban forbids the person from sending messages */
+#define BANCHK_NICK 0x0004 /* checking if a ban forbids the person from changing his/her nick */
+#define BANCHK_LEAVE_MSG 0x0008 /* checking if a ban forbids the person from leaving a message in PART or QUIT */
+#define BANCHK_TKL 0x0010 /* called from a server ban routine, or other match_user() usage */
+#define BANCHK_ALL (BANCHK_JOIN|BANCHK_MSG|BANCHK_NICK|BANCHK_LEAVE_MSG) /* all events except BANCHK_TKL which is special */
#define TKLISTLEN 26
#define TKLIPHASHLEN1 4
@@ -2256,8 +2159,6 @@ struct MaxTarget {
#define MATCH_MASK_IS_UHOST 0x1000
#define MATCH_MASK_IS_HOST 0x2000
-#define MATCH_USE_IDENT 0x0100
-
typedef enum {
POLICY_ALLOW=1,
POLICY_WARN=2,
@@ -2303,6 +2204,19 @@ struct ConfigItem_badword {
#define SKIP_DEAF 0x4
#define SKIP_CTCP 0x8
+typedef struct GeoIPResult GeoIPResult;
+struct GeoIPResult {
+ char *country_code;
+ char *country_name;
+};
+
+typedef enum WhoisConfigDetails {
+ WHOIS_CONFIG_DETAILS_DEFAULT = 0,
+ WHOIS_CONFIG_DETAILS_NONE = 1,
+ WHOIS_CONFIG_DETAILS_LIMITED = 2,
+ WHOIS_CONFIG_DETAILS_FULL = 3,
+} WhoisConfigDetails;
+
#endif /* __struct_include__ */
#include "dynconf.h"
diff --git a/include/sys.h b/include/sys.h
index dcae59d..2ea06b5 100644
--- a/include/sys.h
+++ b/include/sys.h
@@ -55,9 +55,6 @@
#endif /* HAVE_INTTYPES_H */
#endif /* HAVE_STDINT_H */
-#ifdef SSL
-#include
-#endif
#ifndef _WIN32
#include
#include
diff --git a/include/unrealircd.h b/include/unrealircd.h
index 05e77f0..abd67c7 100644
--- a/include/unrealircd.h
+++ b/include/unrealircd.h
@@ -10,7 +10,6 @@
#include "numeric.h"
#include "msg.h"
#include "mempool.h"
-#include "proto.h"
#include "channel.h"
#include
#include
@@ -31,7 +30,6 @@
#include
#include
#include "h.h"
-#include "url.h"
#include "version.h"
#ifdef USE_LIBCURL
#include
diff --git a/include/url.h b/include/url.h
deleted file mode 100644
index 63584b0..0000000
--- a/include/url.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef URL_H
-#define URL_H
-#include "types.h"
-
-int MODFUNC url_is_valid(const char *);
-extern const char MODFUNC *displayurl(const char *url);
-char MODFUNC *url_getfilename(const char *url);
-char MODFUNC *download_file(const char *, char **);
-void MODFUNC download_file_async(const char *, time_t, vFP, void *callback_data);
-void MODFUNC url_do_transfers_async(void);
-void MODFUNC url_init(void);
-
-#endif
diff --git a/include/version.h b/include/version.h
index 281fdf9..00f5e62 100644
--- a/include/version.h
+++ b/include/version.h
@@ -54,9 +54,10 @@
* 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 202120
+#define UNREAL_VERSION_TIME 202148
-#define UnrealProtocol 5002
+#define UNREAL_VERSION ((UNREAL_VERSION_GENERATION << 24) + (UNREAL_VERSION_MAJOR << 16) + (UNREAL_VERSION_MINOR << 8))
+#define UnrealProtocol 6000
#define PATCH1 macro_to_str(UNREAL_VERSION_GENERATION)
#define PATCH2 "." macro_to_str(UNREAL_VERSION_MAJOR)
#define PATCH3 "." macro_to_str(UNREAL_VERSION_MINOR)
diff --git a/include/whowas.h b/include/whowas.h
index f639f89..ceaefed 100644
--- a/include/whowas.h
+++ b/include/whowas.h
@@ -59,7 +59,7 @@ void off_history(Client *);
** nickname within the timelimit. Returns NULL, if no
** one found...
*/
-Client *get_history(char *, time_t);
+Client *get_history(const char *, time_t);
/* Nick name */
/* Time limit in seconds */
diff --git a/include/windows/setup.h b/include/windows/setup.h
index f079072..12d49c4 100644
--- a/include/windows/setup.h
+++ b/include/windows/setup.h
@@ -35,8 +35,6 @@
#define PIDFILE PERMDATADIR"/unrealircd.pid"
#define NO_U_TYPES
#define NEED_U_INT32_T
-#define PREFIX_AQ
-#define LIST_SHOW_MODES
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#define HAVE_EXPLICIT_BZERO
@@ -57,13 +55,13 @@
#define _WIN32_WINNT 0x0601
/* Generation version number (e.g.: 3 for Unreal3*) */
-#define UNREAL_VERSION_GENERATION 5
+#define UNREAL_VERSION_GENERATION 6
/* Major version number (e.g.: 2 for Unreal3.2*) */
-#define UNREAL_VERSION_MAJOR 2
+#define UNREAL_VERSION_MAJOR 0
/* Minor version number (e.g.: 1 for Unreal3.2.1) */
-#define UNREAL_VERSION_MINOR 0
+#define UNREAL_VERSION_MINOR 1
/* Version suffix such as a beta marker or release candidate marker. (e.g.:
-rcX for unrealircd-3.2.9-rcX) */
diff --git a/src/Makefile.in b/src/Makefile.in
index a50e095..62d4388 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -24,15 +24,15 @@ 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 \
match.o modules.o parse.o mempool.o operclass.o \
- conf_preprocessor.o conf.o debug.o dispatch.o numeric.o \
+ conf_preprocessor.o conf.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 \
api-moddata.o api-extban.o api-isupport.o api-command.o \
api-clicap.o api-messagetag.o api-history-backend.o api-efunctions.o \
api-event.o \
- crypt_blowfish.o unrealdb.o updconf.o crashreport.o modulemanager.o \
- utf8.o \
+ crypt_blowfish.o unrealdb.o crashreport.o modulemanager.o \
+ utf8.o log.o \
openssl_hostname_validation.o $(URL)
SRC=$(OBJS:%.o=%.c)
@@ -48,13 +48,16 @@ INCLUDES = ../include/channel.h \
../include/ircsprintf.h \
../include/license.h \
../include/modules.h ../include/modversion.h ../include/msg.h \
- ../include/numeric.h ../include/proto.h \
+ ../include/numeric.h \
../include/resource.h ../include/setup.h \
../include/struct.h ../include/sys.h \
- ../include/types.h ../include/url.h \
+ ../include/types.h \
../include/version.h ../include/whowas.h \
../include/openssl_hostname_validation.h
+.SUFFIXES:
+.SUFFIXES: .c .h .o
+
all: build
build:
@@ -80,170 +83,16 @@ mods:
version.c: version.c.SH
$(SHELL) version.c.SH
-version.o: version.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c version.c
-
-parse.o: parse.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c parse.c
-
-socket.o: socket.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c socket.c
-
-dispatch.o: dispatch.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c dispatch.c
-
-dbuf.o: dbuf.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c dbuf.c
-
-auth.o: auth.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c auth.c
-
-send.o: send.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c send.c
-
-tls.o: tls.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c tls.c
-
-match.o: match.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c match.c
-
-modules.o: modules.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c modules.c
-
-mempool.o: mempool.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c mempool.c
-
-support.o: support.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c support.c
-
-userload.o: userload.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c userload.c
-
-aliases.o: aliases.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c aliases.c
+%.o: %.c $(INCLUDES)
+ $(CC) $(CFLAGS) $(BINCFLAGS) -c $<
clean:
$(RM) -f *.o *.so *~ core ircd version.c; \
- cd modules; make clean
+ cd modules; ${MAKE} clean
cleandir: clean
depend:
makedepend -I${INCLUDEDIR} ${SRC}
-channel.o: channel.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c channel.c
-
-ircd.o: ircd.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c ircd.c
-
-list.o: list.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c list.c
-
-dns.o: dns.c $(INCLUDES) ../include/dns.h
- $(CC) $(CFLAGS) $(BINCFLAGS) -c dns.c
-
-fdlist.o: fdlist.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c fdlist.c
-
-conf_preprocessor.o: conf_preprocessor.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c conf_preprocessor.c
-
-conf.o: conf.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c conf.c
-
-debug.o: debug.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c debug.c
-
-numeric.o: numeric.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c numeric.c
-
-misc.o: misc.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c misc.c
-
-scache.o: scache.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c scache.c
-
-ircsprintf.o: ircsprintf.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c ircsprintf.c
-
-user.o: user.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c user.c
-
-serv.o: serv.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c serv.c
-
-whowas.o: whowas.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c whowas.c
-
-hash.o: hash.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c hash.c
-
-crule.o: crule.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c crule.c
-
-random.o: random.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c random.c
-
-operclass.o: operclass.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c operclass.c
-
-api-usermode.o: api-usermode.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c api-usermode.c
-
-api-event.o: api-event.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c api-event.c
-
-api-channelmode.o: api-channelmode.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c api-channelmode.c
-
-api-moddata.o: api-moddata.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c api-moddata.c
-
-api-extban.o: api-extban.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c api-extban.c
-
-api-command.o: api-command.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c api-command.c
-
-api-isupport.o: api-isupport.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c api-isupport.c
-
-api-clicap.o: api-clicap.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c api-clicap.c
-
-api-messagetag.o: api-messagetag.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c api-messagetag.c
-
-api-history-backend.o: api-history-backend.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c api-history-backend.c
-
-api-efunctions.o: api-efunctions.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c api-efunctions.c
-
-crypt_blowfish.o: crypt_blowfish.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c crypt_blowfish.c
-
-unrealdb.o: unrealdb.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c unrealdb.c
-
-updconf.o: updconf.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c updconf.c
-
-crashreport.o: crashreport.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c crashreport.c
-
-modulemanager.o: modulemanager.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c modulemanager.c
-
-utf8.o: utf8.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c utf8.c
-
-openssl_hostname_validation.o: openssl_hostname_validation.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c openssl_hostname_validation.c
-
-url.o: url.c $(INCLUDES)
- $(CC) $(CFLAGS) $(BINCFLAGS) -c url.c
-
# DO NOT DELETE THIS LINE -- make depend depends on it.
-
diff --git a/src/aliases.c b/src/aliases.c
index 22f299b..7ec46f3 100644
--- a/src/aliases.c
+++ b/src/aliases.c
@@ -42,11 +42,12 @@ void strrangetok(char *in, char *out, char tok, short first, short last) {
/* cmd_alias is a special type of command, it has an extra argument 'cmd'. */
static int recursive_alias = 0;
-void cmd_alias(Client *client, MessageTag *mtags, int parc, char *parv[], char *cmd)
+void cmd_alias(Client *client, MessageTag *mtags, int parc, const char *parv[], const char *cmd)
{
ConfigItem_alias *alias;
Client *acptr;
int ret;
+ char request[BUFSIZE];
if (!(alias = find_alias(cmd)))
{
@@ -64,7 +65,7 @@ void cmd_alias(Client *client, MessageTag *mtags, int parc, char *parv[], char *
if (alias->type == ALIAS_SERVICES)
{
- if (SERVICES_NAME && (acptr = find_person(alias->nick, NULL)))
+ if (SERVICES_NAME && (acptr = find_user(alias->nick, NULL)))
{
if (alias->spamfilter && match_spamfilter(client, parv[1], SPAMF_USERMSG, cmd, alias->nick, 0, NULL))
return;
@@ -76,7 +77,7 @@ void cmd_alias(Client *client, MessageTag *mtags, int parc, char *parv[], char *
}
else if (alias->type == ALIAS_STATS)
{
- if (STATS_SERVER && (acptr = find_person(alias->nick, NULL)))
+ if (STATS_SERVER && (acptr = find_user(alias->nick, NULL)))
{
if (alias->spamfilter && match_spamfilter(client, parv[1], SPAMF_USERMSG, cmd, alias->nick, 0, NULL))
return;
@@ -88,7 +89,7 @@ void cmd_alias(Client *client, MessageTag *mtags, int parc, char *parv[], char *
}
else if (alias->type == ALIAS_NORMAL)
{
- if ((acptr = find_person(alias->nick, NULL)))
+ if ((acptr = find_user(alias->nick, NULL)))
{
if (alias->spamfilter && match_spamfilter(client, parv[1], SPAMF_USERMSG, cmd, alias->nick, 0, NULL))
return;
@@ -106,19 +107,19 @@ void cmd_alias(Client *client, MessageTag *mtags, int parc, char *parv[], char *
else if (alias->type == ALIAS_CHANNEL)
{
Channel *channel;
- if ((channel = find_channel(alias->nick, NULL)))
+ if ((channel = find_channel(alias->nick)))
{
- char *msg = parv[1];
- char *errmsg = NULL;
+ const char *msg = parv[1];
+ const char *errmsg = NULL;
if (can_send_to_channel(client, channel, &msg, &errmsg, 0))
{
- if (alias->spamfilter && match_spamfilter(client, parv[1], SPAMF_CHANMSG, cmd, channel->chname, 0, NULL))
+ if (alias->spamfilter && match_spamfilter(client, parv[1], SPAMF_CHANMSG, cmd, channel->name, 0, NULL))
return;
new_message(client, NULL, &mtags);
sendto_channel(channel, client, client->direction,
- PREFIX_ALL, 0, SEND_ALL|SKIP_DEAF, mtags,
+ NULL, 0, SEND_ALL|SKIP_DEAF, mtags,
":%s PRIVMSG %s :%s",
- client->name, channel->chname, parv[1]);
+ client->name, channel->name, parv[1]);
free_message_tags(mtags);
return;
}
@@ -132,7 +133,10 @@ void cmd_alias(Client *client, MessageTag *mtags, int parc, char *parv[], char *
char *ptr = "";
if (!(parc < 2 || *parv[1] == '\0'))
- ptr = parv[1];
+ {
+ strlcpy(request, parv[1], sizeof(request));
+ ptr = request;
+ }
for (format = alias->format; format; format = format->next)
{
@@ -201,7 +205,7 @@ void cmd_alias(Client *client, MessageTag *mtags, int parc, char *parv[], char *
if (format->type == ALIAS_SERVICES)
{
- if (SERVICES_NAME && (acptr = find_person(format->nick, NULL)))
+ if (SERVICES_NAME && (acptr = find_user(format->nick, NULL)))
{
if (alias->spamfilter && match_spamfilter(client, output, SPAMF_USERMSG, cmd, format->nick, 0, NULL))
return;
@@ -212,7 +216,7 @@ void cmd_alias(Client *client, MessageTag *mtags, int parc, char *parv[], char *
}
else if (format->type == ALIAS_STATS)
{
- if (STATS_SERVER && (acptr = find_person(format->nick, NULL)))
+ if (STATS_SERVER && (acptr = find_user(format->nick, NULL)))
{
if (alias->spamfilter && match_spamfilter(client, output, SPAMF_USERMSG, cmd, format->nick, 0, NULL))
return;
@@ -223,7 +227,7 @@ void cmd_alias(Client *client, MessageTag *mtags, int parc, char *parv[], char *
}
else if (format->type == ALIAS_NORMAL)
{
- if ((acptr = find_person(format->nick, NULL)))
+ if ((acptr = find_user(format->nick, NULL)))
{
if (alias->spamfilter && match_spamfilter(client, output, SPAMF_USERMSG, cmd, format->nick, 0, NULL))
return;
@@ -241,19 +245,19 @@ void cmd_alias(Client *client, MessageTag *mtags, int parc, char *parv[], char *
else if (format->type == ALIAS_CHANNEL)
{
Channel *channel;
- if ((channel = find_channel(format->nick, NULL)))
+ if ((channel = find_channel(format->nick)))
{
- char *msg = output;
- char *errmsg = NULL;
+ const char *msg = output;
+ const char *errmsg = NULL;
if (!can_send_to_channel(client, channel, &msg, &errmsg, 0))
{
- if (alias->spamfilter && match_spamfilter(client, output, SPAMF_CHANMSG, cmd, channel->chname, 0, NULL))
+ if (alias->spamfilter && match_spamfilter(client, output, SPAMF_CHANMSG, cmd, channel->name, 0, NULL))
return;
new_message(client, NULL, &mtags);
sendto_channel(channel, client, client->direction,
- PREFIX_ALL, 0, SEND_ALL|SKIP_DEAF, mtags,
+ NULL, 0, SEND_ALL|SKIP_DEAF, mtags,
":%s PRIVMSG %s :%s",
- client->name, channel->chname, parv[1]);
+ client->name, channel->name, parv[1]);
free_message_tags(mtags);
return;
}
diff --git a/src/api-channelmode.c b/src/api-channelmode.c
index 3237da9..1a5beee 100644
--- a/src/api-channelmode.c
+++ b/src/api-channelmode.c
@@ -33,10 +33,8 @@
* @{
*/
-/** Table with details on each channel mode handler */
-Cmode *Channelmode_Table = NULL;
-/** Highest index in Channelmode_Table */
-unsigned short Channelmode_highest = 0;
+/** List of all channel modes, their handlers, etc */
+Cmode *channelmodes = NULL;
/** @} */
@@ -48,6 +46,7 @@ char extchmstr[4][64];
/* Private functions (forward declaration) and variables */
static void make_cmodestr(void);
static char previous_chanmodes[256];
+static char previous_prefix[256];
static Cmode *ParamTable[MAXPARAMMODES+1];
static void unload_extcmode_commit(Cmode *cmode);
@@ -55,6 +54,7 @@ static void unload_extcmode_commit(Cmode *cmode);
void make_extcmodestr()
{
char *p;
+ Cmode *cm;
int i;
extchmstr[0][0] = extchmstr[1][0] = extchmstr[2][0] = extchmstr[3][0] = '\0';
@@ -64,31 +64,30 @@ void make_extcmodestr()
/* type 2: 1 par to set/unset (has .unset_with_param) */
p = extchmstr[1];
- for (i=0; i <= Channelmode_highest; i++)
- if (Channelmode_Table[i].paracount && Channelmode_Table[i].flag &&
- Channelmode_Table[i].unset_with_param)
- *p++ = Channelmode_Table[i].flag;
+ for (cm=channelmodes; cm; cm = cm->next)
+ if (cm->paracount && cm->letter && cm->unset_with_param && (cm->type != CMODE_MEMBER))
+ *p++ = cm->letter;
*p = '\0';
/* type 3: 1 param to set, 0 params to unset (does not have .unset_with_param) */
p = extchmstr[2];
- for (i=0; i <= Channelmode_highest; i++)
- if (Channelmode_Table[i].paracount && Channelmode_Table[i].flag &&
- !Channelmode_Table[i].unset_with_param)
- *p++ = Channelmode_Table[i].flag;
+ for (cm=channelmodes; cm; cm = cm->next)
+ if (cm->paracount && cm->letter && !cm->unset_with_param)
+ *p++ = cm->letter;
*p = '\0';
/* type 4: paramless modes */
p = extchmstr[3];
- for (i=0; i <= Channelmode_highest; i++)
- if (!Channelmode_Table[i].paracount && Channelmode_Table[i].flag)
- *p++ = Channelmode_Table[i].flag;
+ for (cm=channelmodes; cm; cm = cm->next)
+ if (!cm->paracount && cm->letter)
+ *p++ = cm->letter;
*p = '\0';
}
/** Create the string that is used in numeric 004 */
static void make_cmodestr(void)
{
+ Cmode *cm;
char *p = &cmodestring[0];
CoreChannelModeTable *tab = &corechannelmodetable[0];
int i;
@@ -98,35 +97,36 @@ static void make_cmodestr(void)
p++;
tab++;
}
- for (i=0; i <= Channelmode_highest; i++)
- if (Channelmode_Table[i].flag)
- *p++ = Channelmode_Table[i].flag;
+ for (cm=channelmodes; cm; cm = cm->next)
+ if (cm->letter)
+ *p++ = cm->letter;
*p = '\0';
}
/** Check for changes - if any are detected, we broadcast the change */
-void extcmodes_check_for_changes(void)
+void extcmodes_check_for_changed_channel_modes(void)
{
char chanmodes[256];
ISupport *isup;
+ //sort_cmodes();
make_cmodestr();
make_extcmodestr();
snprintf(chanmodes, sizeof(chanmodes), "%s%s", CHPAR1, EXPAR1);
- safe_strdup(me.serv->features.chanmodes[0], chanmodes);
- snprintf(chanmodes, sizeof(chanmodes), "%s%s", CHPAR2, EXPAR2);
- safe_strdup(me.serv->features.chanmodes[1], chanmodes);
- snprintf(chanmodes, sizeof(chanmodes), "%s%s", CHPAR3, EXPAR3);
- safe_strdup(me.serv->features.chanmodes[2], chanmodes);
- snprintf(chanmodes, sizeof(chanmodes), "%s%s", CHPAR4, EXPAR4);
- safe_strdup(me.serv->features.chanmodes[3], chanmodes);
+ safe_strdup(me.server->features.chanmodes[0], chanmodes);
+ snprintf(chanmodes, sizeof(chanmodes), "%s", EXPAR2);
+ safe_strdup(me.server->features.chanmodes[1], chanmodes);
+ snprintf(chanmodes, sizeof(chanmodes), "%s", EXPAR3);
+ safe_strdup(me.server->features.chanmodes[2], chanmodes);
+ snprintf(chanmodes, sizeof(chanmodes), "%s", EXPAR4);
+ safe_strdup(me.server->features.chanmodes[3], chanmodes);
ircsnprintf(chanmodes, sizeof(chanmodes), "%s,%s,%s,%s",
- me.serv->features.chanmodes[0],
- me.serv->features.chanmodes[1],
- me.serv->features.chanmodes[2],
- me.serv->features.chanmodes[3]);
+ me.server->features.chanmodes[0],
+ me.server->features.chanmodes[1],
+ me.server->features.chanmodes[2],
+ me.server->features.chanmodes[3]);
isup = ISupportFind("CHANMODES");
if (!isup)
@@ -139,10 +139,10 @@ void extcmodes_check_for_changes(void)
if (*previous_chanmodes && strcmp(chanmodes, previous_chanmodes))
{
- ircd_log(LOG_ERROR, "Channel modes changed at runtime: %s -> %s",
- previous_chanmodes, chanmodes);
- sendto_realops("Channel modes changed at runtime: %s -> %s",
- previous_chanmodes, chanmodes);
+ unreal_log(ULOG_INFO, "mode", "CHANNEL_MODES_CHANGED", NULL,
+ "Channel modes changed at runtime: $old_channel_modes -> $new_channel_modes",
+ log_data_string("old_channel_modes", previous_chanmodes),
+ log_data_string("new_channel_modes", chanmodes));
/* Broadcast change to all (locally connected) servers */
sendto_server(NULL, 0, 0, NULL, "PROTOCTL CHANMODES=%s", chanmodes);
}
@@ -150,40 +150,152 @@ void extcmodes_check_for_changes(void)
strlcpy(previous_chanmodes, chanmodes, sizeof(previous_chanmodes));
}
+void make_prefix(char **isupport_prefix, char **isupport_statusmsg)
+{
+ static char prefix[256];
+ static char prefix_prefix[256];
+ char prefix_modes[256];
+ int rank[256];
+ Cmode *cm;
+ int n;
+
+ *prefix = *prefix_prefix = *prefix_modes = '\0';
+
+ for (n=0, cm=channelmodes; cm && n < ARRAY_SIZEOF(rank)-1; cm = cm->next)
+ {
+ if ((cm->type == CMODE_MEMBER) && cm->letter)
+ {
+ strlcat_letter(prefix_prefix, cm->prefix, sizeof(prefix_prefix));
+ strlcat_letter(prefix_modes, cm->letter, sizeof(prefix_modes));
+ rank[n] = cm->rank;
+ n++;
+ }
+ }
+
+ if (*prefix_prefix)
+ {
+ int i, j;
+ /* Now sort the damn thing */
+ for (i=0; i < n; i++)
+ {
+ for (j=i+1; j < n; j++)
+ {
+ if (rank[i] < rank[j])
+ {
+ /* swap */
+ char save;
+ int save_rank;
+ save = prefix_prefix[i];
+ prefix_prefix[i] = prefix_prefix[j];
+ prefix_prefix[j] = save;
+ save = prefix_modes[i];
+ prefix_modes[i] = prefix_modes[j];
+ prefix_modes[j] = save;
+ save_rank = rank[i];
+ rank[i] = rank[j];
+ rank[j] = save_rank;
+ }
+ }
+ }
+ snprintf(prefix, sizeof(prefix), "(%s)%s", prefix_modes, prefix_prefix);
+ }
+
+ *isupport_prefix = prefix;
+ *isupport_statusmsg = prefix_prefix;
+}
+
+void extcmodes_check_for_changed_prefixes(void)
+{
+ ISupport *isup;
+ char *prefix, *statusmsg;
+
+ make_prefix(&prefix, &statusmsg);
+ ISupportSet(NULL, "PREFIX", prefix);
+ ISupportSet(NULL, "STATUSMSG", statusmsg);
+
+ if (*previous_prefix && strcmp(prefix, previous_prefix))
+ {
+ unreal_log(ULOG_INFO, "mode", "PREFIX_CHANGED", NULL,
+ "Prefix changed at runtime: $old_prefix -> $new_prefix",
+ log_data_string("old_prefix", previous_prefix),
+ log_data_string("new_prefix", prefix));
+ /* Broadcast change to all (locally connected) servers */
+ sendto_server(NULL, 0, 0, NULL, "PROTOCTL PREFIX=%s", prefix);
+ }
+
+ strlcpy(previous_prefix, prefix, sizeof(previous_prefix));
+}
+
+/** Check for changes - if any are detected, we broadcast the change */
+void extcmodes_check_for_changes(void)
+{
+ extcmodes_check_for_changed_channel_modes();
+ extcmodes_check_for_changed_prefixes();
+}
+
/** Initialize the extended channel modes system */
void extcmode_init(void)
{
- Cmode_t val = 1;
- int i;
- Channelmode_Table = safe_alloc(sizeof(Cmode) * EXTCMODETABLESZ);
- for (i = 0; i < EXTCMODETABLESZ; i++)
- {
- Channelmode_Table[i].mode = val;
- val *= 2;
- }
- Channelmode_highest = 0;
memset(&extchmstr, 0, sizeof(extchmstr));
memset(¶m_to_slot_mapping, 0, sizeof(param_to_slot_mapping));
*previous_chanmodes = '\0';
+ *previous_prefix = '\0';
}
/** Update letter->slot mapping and slot->handler mapping */
-void extcmode_para_addslot(Cmode *c, int slot)
+void extcmode_para_addslot(Cmode *cm, int slot)
{
if ((slot < 0) || (slot > MAXPARAMMODES))
abort();
- c->slot = slot;
- ParamTable[slot] = c;
- param_to_slot_mapping[c->flag] = slot;
+ cm->param_slot = slot;
+ ParamTable[slot] = cm;
+ param_to_slot_mapping[cm->letter] = slot;
}
/** Update letter->slot mapping and slot->handler mapping */
-void extcmode_para_delslot(Cmode *c, int slot)
+void extcmode_para_delslot(Cmode *cm, int slot)
{
if ((slot < 0) || (slot > MAXPARAMMODES))
abort();
ParamTable[slot] = NULL;
- param_to_slot_mapping[c->flag] = 0;
+ param_to_slot_mapping[cm->letter] = 0;
+}
+
+void channelmode_add_sorted(Cmode *n)
+{
+ Cmode *m;
+
+ if (channelmodes == NULL)
+ {
+ channelmodes = n;
+ return;
+ }
+
+ for (m = channelmodes; m; m = m->next)
+ {
+ if (m->letter == '\0')
+ abort();
+ if (sort_character_lowercase_before_uppercase(n->letter, m->letter))
+ {
+ /* Insert us before */
+ if (m->prev)
+ m->prev->next = n;
+ else
+ channelmodes = n; /* new head */
+ n->prev = m->prev;
+
+ n->next = m;
+ m->prev = n;
+ return;
+ }
+ if (!m->next)
+ {
+ /* Append us at end */
+ m->next = n;
+ n->prev = m;
+ return;
+ }
+ }
}
/** @defgroup ChannelModeAPI Channel mode API
@@ -198,19 +310,17 @@ void extcmode_para_delslot(Cmode *c, int slot)
*/
Cmode *CmodeAdd(Module *module, CmodeInfo req, Cmode_t *mode)
{
- short i = 0, j = 0;
int paraslot = -1;
int existing = 0;
+ Cmode *cm;
- while (i < EXTCMODETABLESZ)
+ for (cm=channelmodes; cm; cm = cm->next)
{
- if (!Channelmode_Table[i].flag)
- break;
- else if (Channelmode_Table[i].flag == req.flag)
+ if (cm->letter == req.letter)
{
- if (Channelmode_Table[i].unloaded)
+ if (cm->unloaded)
{
- Channelmode_Table[i].unloaded = 0;
+ cm->unloaded = 0;
existing = 1;
break;
} else {
@@ -219,22 +329,67 @@ Cmode *CmodeAdd(Module *module, CmodeInfo req, Cmode_t *mode)
return NULL;
}
}
- i++;
- }
- if (i == EXTCMODETABLESZ)
- {
- Debug((DEBUG_DEBUG, "CmodeAdd failed, no space"));
- if (module)
- module->errorcode = MODERR_NOSPACE;
- return NULL;
}
- if (req.paracount == 1)
+ if (!cm)
+ {
+ long l, found = 0;
+
+ if (req.type == CMODE_NORMAL)
+ {
+ for (l = 1; l < LONG_MAX/2; l *= 2)
+ {
+ found = 0;
+ for (cm=channelmodes; cm; cm = cm->next)
+ {
+ if (cm->mode == l)
+ {
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ break;
+ }
+ /* If 'found' is still true, then we are out of space */
+ if (found)
+ {
+ unreal_log(ULOG_ERROR, "module", "CHANNEL_MODE_OUT_OF_SPACE", NULL,
+ "CmodeAdd: out of space!!!");
+ if (module)
+ module->errorcode = MODERR_NOSPACE;
+ return NULL;
+ }
+ cm = safe_alloc(sizeof(Cmode));
+ cm->letter = req.letter;
+ cm->mode = l;
+ *mode = cm->mode;
+ } else if (req.type == CMODE_MEMBER)
+ {
+ if (!req.prefix || !req.sjoin_prefix || !req.paracount ||
+ !req.unset_with_param || !req.rank)
+ {
+ unreal_log(ULOG_ERROR, "module", "CMODEADD_API_ERROR", NULL,
+ "CmodeAdd(): module is missing required information. "
+ "Module: $module_name",
+ log_data_string("module_name", module->header->name));
+ module->errorcode = MODERR_INVALID;
+ return NULL;
+ }
+ cm = safe_alloc(sizeof(Cmode));
+ cm->letter = req.letter;
+ } else {
+ abort();
+ }
+ channelmode_add_sorted(cm);
+ }
+
+ if ((req.paracount == 1) && (req.type == CMODE_NORMAL))
{
if (existing)
{
/* Re-use parameter slot of the module with the same modechar that is unloading */
- paraslot = Channelmode_Table[i].slot;
+ paraslot = cm->param_slot;
}
else
{
@@ -243,7 +398,8 @@ Cmode *CmodeAdd(Module *module, CmodeInfo req, Cmode_t *mode)
{
if (paraslot == MAXPARAMMODES - 1)
{
- Debug((DEBUG_DEBUG, "CmodeAdd failed, no space for parameter"));
+ unreal_log(ULOG_ERROR, "module", "CHANNEL_MODE_OUT_OF_SPACE", NULL,
+ "CmodeAdd: out of space!!! Place 2.");
if (module)
module->errorcode = MODERR_NOSPACE;
return NULL;
@@ -252,39 +408,40 @@ Cmode *CmodeAdd(Module *module, CmodeInfo req, Cmode_t *mode)
}
}
- *mode = Channelmode_Table[i].mode;
- /* Update extended channel mode table highest */
- Channelmode_Table[i].flag = req.flag;
- Channelmode_Table[i].paracount = req.paracount;
- Channelmode_Table[i].is_ok = req.is_ok;
- Channelmode_Table[i].put_param = req.put_param;
- Channelmode_Table[i].get_param = req.get_param;
- Channelmode_Table[i].conv_param = req.conv_param;
- Channelmode_Table[i].free_param = req.free_param;
- Channelmode_Table[i].dup_struct = req.dup_struct;
- Channelmode_Table[i].sjoin_check = req.sjoin_check;
- Channelmode_Table[i].local = req.local;
- Channelmode_Table[i].unset_with_param = req.unset_with_param;
- Channelmode_Table[i].owner = module;
- Channelmode_Table[i].unloaded = 0;
-
- for (j = 0; j < EXTCMODETABLESZ; j++)
- if (Channelmode_Table[j].flag)
- if (j > Channelmode_highest)
- Channelmode_highest = j;
+ cm->letter = req.letter;
+ cm->type = req.type;
+ cm->prefix = req.prefix;
+ cm->sjoin_prefix = req.sjoin_prefix;
+ cm->rank = req.rank;
+ cm->paracount = req.paracount;
+ cm->is_ok = req.is_ok;
+ cm->put_param = req.put_param;
+ cm->get_param = req.get_param;
+ cm->conv_param = req.conv_param;
+ cm->free_param = req.free_param;
+ cm->dup_struct = req.dup_struct;
+ cm->sjoin_check = req.sjoin_check;
+ cm->local = req.local;
+ cm->unset_with_param = req.unset_with_param;
+ cm->owner = module;
+ cm->unloaded = 0;
+
+ if (cm->type == CMODE_NORMAL)
+ {
+ *mode = cm->mode;
+ if (cm->paracount == 1)
+ extcmode_para_addslot(cm, paraslot);
+ }
- if (Channelmode_Table[i].paracount == 1)
- extcmode_para_addslot(&Channelmode_Table[i], paraslot);
-
if (module)
{
ModuleObject *cmodeobj = safe_alloc(sizeof(ModuleObject));
- cmodeobj->object.cmode = &Channelmode_Table[i];
+ cmodeobj->object.cmode = cm;
cmodeobj->type = MOBJ_CMODE;
AddListItem(cmodeobj, module->objects);
module->errorcode = MODERR_NOERROR;
}
- return &(Channelmode_Table[i]);
+ return cm;
}
/** Delete a previously registered channel mode - not called by modules.
@@ -304,7 +461,7 @@ void CmodeDel(Cmode *cmode)
}
cmode->owner = NULL;
}
- if (loop.ircd_rehashing)
+ if (loop.rehashing)
cmode->unloaded = 1;
else
unload_extcmode_commit(cmode);
@@ -322,80 +479,110 @@ static void unload_extcmode_commit(Cmode *cmode)
Channel *channel;
if (!cmode)
- return;
+ return;
- /* Unset channel mode and send MODE to everyone */
-
- if (cmode->paracount == 0)
+ if (cmode->type == CMODE_NORMAL)
{
- /* Paramless mode, easy */
- for (channel = channels; channel; channel = channel->nextch)
+ /* Unset channel mode and send MODE to everyone */
+ if (cmode->paracount == 0)
{
- if (channel->mode.extmode & cmode->mode)
+ /* Paramless mode, easy */
+ for (channel = channels; channel; channel = channel->nextch)
{
- MessageTag *mtags = NULL;
-
- new_message(&me, NULL, &mtags);
- sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags,
- ":%s MODE %s -%c",
- me.name, channel->chname, cmode->flag);
- sendto_server(NULL, 0, 0, mtags,
- ":%s MODE %s -%c 0",
- me.id, channel->chname, cmode->flag);
- free_message_tags(mtags);
-
- channel->mode.extmode &= ~cmode->mode;
- }
- }
- } else
- {
- /* Parameter mode, more complicated */
- for (channel = channels; channel; channel = channel->nextch)
- {
- if (channel->mode.extmode & cmode->mode)
- {
- MessageTag *mtags = NULL;
-
- new_message(&me, NULL, &mtags);
- if (cmode->unset_with_param)
+ if (channel->mode.mode & cmode->mode)
{
- char *param = cmode->get_param(GETPARASTRUCT(channel, cmode->flag));
- sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags,
- ":%s MODE %s -%c %s",
- me.name, channel->chname, cmode->flag, param);
- sendto_server(NULL, 0, 0, mtags,
- ":%s MODE %s -%c %s 0",
- me.id, channel->chname, cmode->flag, param);
- } else {
+ MessageTag *mtags = NULL;
+
+ new_message(&me, NULL, &mtags);
sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags,
":%s MODE %s -%c",
- me.name, channel->chname, cmode->flag);
+ me.name, channel->name, cmode->letter);
sendto_server(NULL, 0, 0, mtags,
":%s MODE %s -%c 0",
- me.id, channel->chname, cmode->flag);
- }
- free_message_tags(mtags);
+ me.id, channel->name, cmode->letter);
+ free_message_tags(mtags);
- cmode->free_param(GETPARASTRUCT(channel, cmode->flag));
- channel->mode.extmode &= ~cmode->mode;
+ channel->mode.mode &= ~cmode->mode;
+ }
+ }
+ } else
+ {
+ /* Parameter mode, more complicated */
+ for (channel = channels; channel; channel = channel->nextch)
+ {
+ if (channel->mode.mode & cmode->mode)
+ {
+ MessageTag *mtags = NULL;
+
+ new_message(&me, NULL, &mtags);
+ if (cmode->unset_with_param)
+ {
+ const char *param = cmode->get_param(GETPARASTRUCT(channel, cmode->letter));
+ sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags,
+ ":%s MODE %s -%c %s",
+ me.name, channel->name, cmode->letter, param);
+ sendto_server(NULL, 0, 0, mtags,
+ ":%s MODE %s -%c %s 0",
+ me.id, channel->name, cmode->letter, param);
+ } else {
+ sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags,
+ ":%s MODE %s -%c",
+ me.name, channel->name, cmode->letter);
+ sendto_server(NULL, 0, 0, mtags,
+ ":%s MODE %s -%c 0",
+ me.id, channel->name, cmode->letter);
+ }
+ free_message_tags(mtags);
+
+ cmode->free_param(GETPARASTRUCT(channel, cmode->letter));
+ channel->mode.mode &= ~cmode->mode;
+ }
+ }
+ extcmode_para_delslot(cmode, cmode->param_slot);
+ }
+ } else
+ if (cmode->type == CMODE_MEMBER)
+ {
+ for (channel = channels; channel; channel = channel->nextch)
+ {
+ Member *m;
+ for (m = channel->members; m; m = m->next)
+ {
+ if (strchr(m->member_modes, cmode->letter))
+ {
+ MessageTag *mtags = NULL;
+
+ new_message(&me, NULL, &mtags);
+ sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags,
+ ":%s MODE %s -%c %s",
+ me.name, channel->name, cmode->letter, m->client->name);
+ sendto_server(NULL, 0, 0, mtags,
+ ":%s MODE %s -%c %s 0",
+ me.id, channel->name, cmode->letter, m->client->id);
+ free_message_tags(mtags);
+ del_member_mode(m->client, channel, cmode->letter);
+ }
}
}
- extcmode_para_delslot(cmode, cmode->slot);
}
- cmode->flag = '\0';
+ DelListItem(cmode, channelmodes);
+ safe_free(cmode);
}
/** Unload all unused channel modes after a REHASH */
void unload_all_unused_extcmodes(void)
{
- int i;
+ Cmode *cm, *cm_next;
- for (i = 0; i < EXTCMODETABLESZ; i++)
- if (Channelmode_Table[i].flag && Channelmode_Table[i].unloaded)
+ for (cm=channelmodes; cm; cm = cm_next)
+ {
+ cm_next = cm->next;
+ if (cm->letter && cm->unloaded)
{
- unload_extcmode_commit(&Channelmode_Table[i]);
+ unload_extcmode_commit(cm);
}
+ }
}
@@ -407,18 +594,29 @@ void unload_all_unused_extcmodes(void)
* @param channel The channel
* @param mode The mode character (eg: 'f')
*/
-char *cm_getparameter(Channel *channel, char mode)
+const char *cm_getparameter(Channel *channel, char mode)
{
return GETPARAMHANDLERBYLETTER(mode)->get_param(GETPARASTRUCT(channel, mode));
}
+/** Get parameter for a channel mode - special version for SJOIN.
+ * This version doesn't take a channel, but a mode.mode_params.
+ * It is only used by SJOIN and should not be used in 3rd party modules.
+ * @param p The list, eg oldmode.mode_params
+ * @param mode The mode letter
+ */
+const char *cm_getparameter_ex(void **p, char mode)
+{
+ return GETPARAMHANDLERBYLETTER(mode)->get_param(GETPARASTRUCTEX(p, mode));
+}
+
/** Set parameter for a channel mode.
* @param channel The channel
* @param mode The mode character (eg: 'f')
* @param str The parameter string
* @note Module users should not use this function directly, it is only used by MODE and SJOIN.
*/
-void cm_putparameter(Channel *channel, char mode, char *str)
+void cm_putparameter(Channel *channel, char mode, const char *str)
{
GETPARASTRUCT(channel, mode) = GETPARAMHANDLERBYLETTER(mode)->put_param(GETPARASTRUCT(channel, mode), str);
}
@@ -433,25 +631,15 @@ void cm_freeparameter(Channel *channel, char mode)
GETPARASTRUCT(channel, mode) = NULL;
}
-/** Get parameter for a channel mode - special version for SJOIN.
- * This version doesn't take a channel, but a mode.extmodeparams.
- * It is only used by SJOIN and should not be used in 3rd party modules.
- * @param p The list, eg oldmode.extmodeparams
- * @param mode The mode letter
- */
-char *cm_getparameter_ex(void **p, char mode)
-{
- return GETPARAMHANDLERBYLETTER(mode)->get_param(GETPARASTRUCTEX(p, mode));
-}
/** Set parameter for a channel mode - special version for SJOIN.
- * This version doesn't take a channel, but a mode.extmodeparams.
+ * This version doesn't take a channel, but a mode.mode_params.
* It is only used by SJOIN and should not be used in 3rd party modules.
- * @param p The list, eg oldmode.extmodeparams
+ * @param p The list, eg oldmode.mode_params
* @param mode The mode letter
* @param str The mode parameter string to set
*/
-void cm_putparameter_ex(void **p, char mode, char *str)
+void cm_putparameter_ex(void **p, char mode, const char *str)
{
GETPARASTRUCTEX(p, mode) = GETPARAMHANDLERBYLETTER(mode)->put_param(GETPARASTRUCTEX(p, mode), str);
}
@@ -465,9 +653,9 @@ void cm_putparameter_ex(void **p, char mode, char *str)
* @param what MODE_ADD / MODE_DEL (???)
* @returns EX_ALLOW or EX_DENY
*/
-int extcmode_default_requirechop(Client *client, Channel *channel, char mode, char *para, int checkt, int what)
+int extcmode_default_requirechop(Client *client, Channel *channel, char mode, const char *para, int checkt, int what)
{
- if (IsUser(client) && is_chan_op(client, channel))
+ if (IsUser(client) && check_channel_access(client, channel, "oaq"))
return EX_ALLOW;
if (checkt == EXCHK_ACCESS_ERR) /* can only be due to being halfop */
sendnumeric(client, ERR_NOTFORHALFOPS, mode);
@@ -483,9 +671,9 @@ int extcmode_default_requirechop(Client *client, Channel *channel, char mode, ch
* @param what MODE_ADD / MODE_DEL (???)
* @returns EX_ALLOW or EX_DENY
*/
-int extcmode_default_requirehalfop(Client *client, Channel *channel, char mode, char *para, int checkt, int what)
+int extcmode_default_requirehalfop(Client *client, Channel *channel, char mode, const char *para, int checkt, int what)
{
- if (IsUser(client) && (is_chan_op(client, channel) || is_half_op(client, channel)))
+ if (IsUser(client) && (check_channel_access(client, channel, "oaq") || check_channel_access(client, channel, "h")))
return EX_ALLOW;
return EX_DENY;
}
@@ -505,10 +693,10 @@ void extcmode_duplicate_paramlist(void **xi, void **xo)
handler = CMP_GETHANDLERBYSLOT(i);
if (!handler)
continue; /* nothing there.. */
- inx = xi[handler->slot]; /* paramter data of input is here */
+ inx = xi[handler->param_slot]; /* paramter data of input is here */
if (!inx)
continue; /* not set */
- xo[handler->slot] = handler->dup_struct(inx); /* call dup_struct with that input and set the output param to that */
+ xo[handler->param_slot] = handler->dup_struct(inx); /* call dup_struct with that input and set the output param to that */
}
}
@@ -525,8 +713,8 @@ void extcmode_free_paramlist(void **ar)
handler = GETPARAMHANDLERBYSLOT(i);
if (!handler)
continue; /* nothing here... */
- handler->free_param(ar[handler->slot]);
- ar[handler->slot] = NULL;
+ handler->free_param(ar[handler->param_slot]);
+ ar[handler->param_slot] = NULL;
}
}
@@ -535,17 +723,450 @@ void extcmode_free_paramlist(void **ar)
/** Internal function: returns 1 if the specified module has 1 or more extended channel modes registered */
int module_has_extcmode_param_mode(Module *mod)
{
- int i = 0;
+ Cmode *cm;
- while (i < EXTCMODETABLESZ)
- {
- if ((Channelmode_Table[i].flag) &&
- (Channelmode_Table[i].owner == mod) &&
- (Channelmode_Table[i].paracount))
- {
+ for (cm=channelmodes; cm; cm = cm->next)
+ if ((cm->letter) && (cm->owner == mod) && (cm->paracount))
return 1;
- }
- i++;
- }
+
return 0;
}
+
+/** Channel member privileges - getting, setting, checking vhoaq status, etc.
+ * These functions get or set the access rights of channel members, such as +vhoaq.
+ * They can also convert between modes (vhoaq), prefixes and sjoin prefixes.
+ * @defgroup ChannelMember Channel members access privileges
+ * @{
+ */
+
+/** Retrieve channel access for a user on a channel, returns modes eg "qao".
+ * @param client The client
+ * @param channel The channel
+ * @returns The modes, sorted by high ranking to lower ranking, eg "qao".
+ * An empty string ("") is returned when not in the channel or no modes.
+ */
+const char *get_channel_access(Client *client, Channel *channel)
+{
+ Membership *mb;
+
+ mb = find_membership_link(client->user->channel, channel);
+ if (!mb)
+ return "";
+ return mb->member_modes;
+}
+
+/** Check channel access for user.
+ * @param client The client to check
+ * @param channel The channel to check
+ * @param modes Which mode(s) to check for
+ * @returns If the client in channel has any of the modes set, 1 is returned.
+ * Otherwise 0 is returned, which is also the case if the user is
+ * not a user or is not in the channel at all.
+ */
+int check_channel_access(Client *client, Channel *channel, const char *modes)
+{
+ Membership *mb;
+ const char *p;
+
+ if (!IsUser(client))
+ return 0; /* eg server */
+
+ mb = find_membership_link(client->user->channel, channel);
+ if (!mb)
+ return 0; /* not a member */
+
+ for (p = mb->member_modes; *p; p++)
+ if (strchr(modes, *p))
+ return 1; /* match new style */
+
+ return 0; /* nomatch */
+}
+
+/** Check channel access for user.
+ * @param client The client to check
+ * @param channel The channel to check
+ * @param modes Which mode(s) to check for
+ * @returns If the client in channel has any of the modes set, 1 is returned.
+ * Otherwise 0 is returned, which is also the case if the user is
+ * not a user or is not in the channel at all.
+ */
+int check_channel_access_membership(Membership *mb, const char *modes)
+{
+ const char *p;
+
+ if (!mb)
+ return 0;
+
+ for (p = mb->member_modes; *p; p++)
+ if (strchr(modes, *p))
+ return 1; /* match new style */
+
+ return 0; /* nomatch */
+}
+
+/** Check channel access for user.
+ * @param client The client to check
+ * @param channel The channel to check
+ * @param modes Which mode(s) to check for
+ * @returns If the client in channel has any of the modes set, 1 is returned.
+ * Otherwise 0 is returned, which is also the case if the user is
+ * not a user or is not in the channel at all.
+ */
+int check_channel_access_member(Member *mb, const char *modes)
+{
+ const char *p;
+
+ if (!mb)
+ return 0;
+
+ for (p = mb->member_modes; *p; p++)
+ if (strchr(modes, *p))
+ return 1; /* match new style */
+
+ return 0; /* nomatch */
+}
+
+/** Check channel access for user.
+ * @param current Flags currently set on the client (eg mb->member_modes)
+ * @param modes Which mode(s) to check for
+ * @returns If the client in channel has any of the modes set, 1 is returned.
+ * Otherwise 0 is returned.
+ */
+int check_channel_access_string(const char *current_modes, const char *modes)
+{
+ const char *p;
+
+ for (p = current_modes; *p; p++)
+ if (strchr(modes, *p))
+ return 1;
+
+ return 0; /* nomatch */
+}
+
+/** Check channel access for user.
+ * @param current Flags currently set on the client (eg mb->member_modes)
+ * @param letter Which mode letter to check for
+ * @returns If the client in channel has any of the modes set, 1 is returned.
+ * Otherwise 0 is returned.
+ */
+int check_channel_access_letter(const char *current_modes, const char letter)
+{
+ return strchr(current_modes, letter) ? 1 : 0;
+}
+
+Cmode *find_channel_mode_handler(char letter)
+{
+ Cmode *cm;
+
+ for (cm=channelmodes; cm; cm = cm->next)
+ if (cm->letter == letter)
+ return cm;
+ return NULL;
+}
+
+/** Is 'letter' a valid mode used for access/levels/ranks? (vhoaq and such)
+ * @param letter The channel mode letter to check, eg 'v'
+ * @returns 1 if valid, 0 if the channel mode does not exist or is not a level mode.
+ */
+int valid_channel_access_mode_letter(char letter)
+{
+ Cmode *cm;
+
+ if ((cm = find_channel_mode_handler(letter)) && (cm->type == CMODE_MEMBER))
+ return 1;
+
+ return 0;
+}
+
+void addlettertomstring(char *str, char letter)
+{
+ Cmode *cm;
+ int n;
+ int my_rank;
+ char *p;
+
+ if (!(cm = find_channel_mode_handler(letter)) || (cm->type != CMODE_MEMBER))
+ return; // should we BUG on this? if something makes it this far, it can never be good right?
+
+ my_rank = cm->rank;
+
+ n = strlen(str);
+ if (n >= MEMBERMODESLEN-1)
+ return; // panic!
+
+ for (p = str; *p; p++)
+ {
+ cm = find_channel_mode_handler(*p);
+ if (!cm)
+ continue; /* wtf */
+ if (cm->rank < my_rank)
+ {
+ /* We need to insert us here */
+ n = strlen(p);
+ memmove(p+1, p, n+1); // +1 for NUL byte
+ *p = letter;
+ return;
+ }
+ }
+ /* We should be at the end */
+ str[n] = letter;
+ str[n+1] = '\0';
+}
+
+void add_member_mode_fast(Member *mb, Membership *mbs, char letter)
+{
+ addlettertomstring(mb->member_modes, letter);
+ addlettertomstring(mbs->member_modes, letter);
+}
+
+void del_member_mode_fast(Member *mb, Membership *mbs, char letter)
+{
+ delletterfromstring(mb->member_modes, letter);
+ delletterfromstring(mbs->member_modes, letter);
+}
+
+int find_mbs(Client *client, Channel *channel, Member **mb, Membership **mbs)
+{
+ *mbs = NULL;
+
+ if (!(*mb = find_member_link(channel->members, client)))
+ return 0;
+
+ if (!(*mbs = find_membership_link(client->user->channel, channel)))
+ return 0;
+
+ return 1;
+}
+
+void add_member_mode(Client *client, Channel *channel, char letter)
+{
+ Member *mb;
+ Membership *mbs;
+
+ if (!find_mbs(client, channel, &mb, &mbs))
+ return;
+
+ add_member_mode_fast(mb, mbs, letter);
+}
+
+void del_member_mode(Client *client, Channel *channel, char letter)
+{
+ Member *mb;
+ Membership *mbs;
+
+ if (!find_mbs(client, channel, &mb, &mbs))
+ return;
+
+ del_member_mode_fast(mb, mbs, letter);
+}
+
+char sjoin_prefix_to_mode(char s)
+{
+ Cmode *cm;
+
+ /* Filter this out early to avoid spurious results */
+ if (s == '\0')
+ return '\0';
+
+ /* First the hardcoded list modes: */
+ if (s == '&')
+ return 'b';
+ if (s == '"')
+ return 'e';
+ if (s == '\'')
+ return 'I';
+
+ /* Now the dynamic ones (+vhoaq): */
+ for (cm=channelmodes; cm; cm = cm->next)
+ if ((cm->sjoin_prefix == s) && (cm->type == CMODE_MEMBER))
+ return cm->letter;
+
+ /* Not found */
+ return '\0';
+}
+
+char mode_to_sjoin_prefix(char s)
+{
+ Cmode *cm;
+
+ /* Filter this out early to avoid spurious results */
+ if (s == '\0')
+ return '\0';
+
+ /* First the hardcoded list modes: */
+ if (s == 'b')
+ return '&';
+ if (s == 'e')
+ return '"';
+ if (s == 'I')
+ return '\'';
+
+ /* Now the dynamic ones (+vhoaq): */
+ for (cm=channelmodes; cm; cm = cm->next)
+ if ((cm->letter == s) && (cm->type == CMODE_MEMBER))
+ return cm->sjoin_prefix;
+
+ /* Not found */
+ return '\0';
+}
+
+const char *modes_to_sjoin_prefix(const char *modes)
+{
+ static char buf[MEMBERMODESLEN];
+ const char *m;
+ char f;
+
+ *buf = '\0';
+ for (m = modes; *m; m++)
+ {
+ f = mode_to_sjoin_prefix(*m);
+ if (f)
+ strlcat_letter(buf, f, sizeof(buf));
+ }
+
+ return buf;
+}
+
+char mode_to_prefix(char s)
+{
+ Cmode *cm;
+
+ /* Filter this out early to avoid spurious results */
+ if (s == '\0')
+ return '\0';
+
+ /* Now the dynamic ones (+vhoaq): */
+ for (cm=channelmodes; cm; cm = cm->next)
+ if ((cm->letter == s) && (cm->type == CMODE_MEMBER))
+ return cm->prefix;
+
+ /* Not found */
+ return '\0';
+}
+
+const char *modes_to_prefix(const char *modes)
+{
+ static char buf[MEMBERMODESLEN];
+ const char *m;
+ char f;
+
+ *buf = '\0';
+ for (m = modes; *m; m++)
+ {
+ f = mode_to_prefix(*m);
+ if (f)
+ strlcat_letter(buf, f, sizeof(buf));
+ }
+
+ return buf;
+}
+
+char prefix_to_mode(char s)
+{
+ Cmode *cm;
+
+ /* Filter this out early to avoid spurious results */
+ if (s == '\0')
+ return '\0';
+
+ /* Now the dynamic ones (+vhoaq): */
+ for (cm=channelmodes; cm; cm = cm->next)
+ if ((cm->prefix == s) && (cm->type == CMODE_MEMBER))
+ return cm->letter;
+
+ /* Not found */
+ return '\0';
+}
+
+char rank_to_mode(int rank)
+{
+ Cmode *cm;
+ for (cm=channelmodes; cm; cm = cm->next)
+ if ((cm->type == CMODE_MEMBER) && (cm->rank == rank))
+ return cm->letter;
+ return '\0';
+}
+
+int mode_to_rank(char mode)
+{
+ Cmode *cm;
+ for (cm=channelmodes; cm; cm = cm->next)
+ if ((cm->type == CMODE_MEMBER) && (cm->letter == mode))
+ return cm->rank;
+ return '\0';
+}
+
+int prefix_to_rank(char prefix)
+{
+ Cmode *cm;
+ for (cm=channelmodes; cm; cm = cm->next)
+ if ((cm->type == CMODE_MEMBER) && (cm->prefix == prefix))
+ return cm->rank;
+ return '\0';
+}
+
+char rank_to_prefix(int rank)
+{
+ Cmode *cm;
+ for (cm=channelmodes; cm; cm = cm->next)
+ if ((cm->type == CMODE_MEMBER) && (cm->rank == rank))
+ return cm->prefix;
+ return '\0';
+}
+
+char lowest_ranking_prefix(const char *prefix)
+{
+ const char *p;
+ int winning_rank = INT_MAX;
+
+ for (p = prefix; *p; p++)
+ {
+ int rank = prefix_to_rank(*p);
+ if (rank < winning_rank)
+ winning_rank = rank;
+ }
+ if (winning_rank == INT_MAX)
+ return '\0'; /* No result */
+ return rank_to_prefix(winning_rank);
+}
+
+char lowest_ranking_mode(const char *mode)
+{
+ const char *p;
+ int winning_rank = INT_MAX;
+
+ for (p = mode; *p; p++)
+ {
+ int rank = mode_to_rank(*p);
+ if (rank < winning_rank)
+ winning_rank = rank;
+ }
+ if (winning_rank == INT_MAX)
+ return '\0'; /* No result */
+ return rank_to_mode(winning_rank);
+}
+
+/** Generate all member modes that are equal or greater than 'modes'.
+ * Eg calling this with "o" would generate "oaq" with the default loaded modules.
+ * This is used in sendto_channel() to make multiple check_channel_access_member()
+ * calls more easy / faster.
+ */
+void channel_member_modes_generate_equal_or_greater(const char *modes, char *buf, size_t buflen)
+{
+ const char *p;
+ int rank;
+ Cmode *cm;
+
+ *buf = '\0';
+
+ /* First we must grab the lowest ranking mode, eg 'vhoaq' results in rank for 'v' */
+ rank = lowest_ranking_mode(modes);
+ if (!rank)
+ return; /* zero matches */
+
+ for (cm=channelmodes; cm; cm = cm->next)
+ if ((cm->type == CMODE_MEMBER) && (cm->rank >= rank))
+ strlcat_letter(buf, cm->letter, buflen);
+}
+
+/** @} */
diff --git a/src/api-clicap.c b/src/api-clicap.c
index 79daa26..f760b90 100644
--- a/src/api-clicap.c
+++ b/src/api-clicap.c
@@ -79,7 +79,9 @@ long ClientCapabilityBit(const char *token)
#ifdef DEBUGMODE
if (!clicap)
{
- ircd_log(LOG_ERROR, "WARNING: ClientCapabilityBit(): unknown token '%s'", token);
+ unreal_log(ULOG_WARNING, "main", "BUG_CLIENTCAPABILITYBIT_UNKNOWN_TOKEN", NULL,
+ "[BUG] ClientCapabilityBit() check for unknown token: $token",
+ log_data_string("token", token));
}
#endif
@@ -102,7 +104,7 @@ long clicap_allocate_cap(void)
ClientCapability *clicap;
/* The first bit (v=1) is used by the "invert" marker */
- for (v=2; v < LONG_MAX; v = v * 2)
+ for (v=2; v; v <<= 1)
{
unsigned char found = 0;
for (clicap = clicaps; clicap; clicap = clicap->next)
@@ -162,8 +164,8 @@ ClientCapability *ClientCapabilityAdd(Module *module, ClientCapabilityInfo *clic
v = clicap_allocate_cap();
if (v == 0)
{
- sendto_realops("ClientCapabilityAdd: out of space!!!");
- ircd_log(LOG_ERROR, "ClientCapabilityAdd: out of space!!!");
+ unreal_log(ULOG_ERROR, "module", "CLIENTCAPABILITY_OUT_OF_SPACE", NULL,
+ "ClientCapabilityAdd: out of space!!!");
if (module)
module->errorcode = MODERR_NOSPACE;
return NULL;
@@ -204,8 +206,9 @@ ClientCapability *ClientCapabilityAdd(Module *module, ClientCapabilityInfo *clic
void unload_clicap_commit(ClientCapability *clicap)
{
/* This is an unusual operation, I think we should log it. */
- ircd_log(LOG_ERROR, "Unloading client capability '%s'", clicap->name);
- sendto_realops("Unloading client capability '%s'", clicap->name);
+ unreal_log(ULOG_INFO, "module", "UNLOAD_CLICAP", NULL,
+ "Unloading client capability '$token'",
+ log_data_string("token", clicap->name));
/* NOTE: Stripping the CAP from local clients is done
* in clicap_post_rehash(), so not here.
@@ -245,7 +248,7 @@ void ClientCapabilityDel(ClientCapability *clicap)
clicap->owner = NULL;
}
- if (loop.ircd_rehashing)
+ if (loop.rehashing)
clicap->unloaded = 1;
else
unload_clicap_commit(clicap);
@@ -263,7 +266,12 @@ void unload_all_unused_caps(void)
}
}
-#define MAXCLICAPS 64
+#define ADVERTISEONLYCAPS 16
+/* Advertise only caps are not counted anywhere, this only provides space in rehash temporary storage arrays.
+ * If exceeded, the caps just won't be stored and will be re-added safely. --k4be
+ */
+
+#define MAXCLICAPS ((int)(sizeof(long)*8 - 1 + ADVERTISEONLYCAPS)) /* how many cap bits will fit in `long`? */
static char *old_caps[MAXCLICAPS]; /**< List of old CAP names - used for /rehash */
int old_caps_proto[MAXCLICAPS]; /**< List of old CAP protocol values - used for /rehash */
@@ -279,7 +287,9 @@ void clicap_pre_rehash(void)
{
if (i == MAXCLICAPS)
{
- ircd_log(LOG_ERROR, "More than %d caps loaded - what???", MAXCLICAPS);
+ unreal_log(ULOG_ERROR, "module", "BUG_TOO_MANY_CLIENTCAPABILITIES", NULL,
+ "[BUG] clicap_pre_rehash: More than $count caps loaded - this should never happen",
+ log_data_integer("count", MAXCLICAPS));
break;
}
safe_strdup(old_caps[i], clicap->name);
@@ -318,13 +328,13 @@ void clicap_post_rehash(void)
int i;
int found;
- if (!loop.ircd_rehashing)
+ if (!loop.rehashing)
return; /* First boot */
/* Let's deal with CAP DEL first:
* Go through the old caps and see what's missing now.
*/
- for (i = 0; old_caps[i]; i++)
+ for (i = 0; i < MAXCLICAPS && old_caps[i]; i++)
{
name = old_caps[i];
found = 0;
@@ -351,7 +361,7 @@ void clicap_post_rehash(void)
{
name = clicap->name;
found = 0;
- for (i = 0; old_caps[i]; i++)
+ for (i = 0; i < MAXCLICAPS && old_caps[i]; i++)
{
if (!strcmp(old_caps[i], name))
{
@@ -368,6 +378,6 @@ void clicap_post_rehash(void)
}
/* Now free the old caps. */
- for (i = 0; old_caps[i]; i++)
+ for (i = 0; i < MAXCLICAPS && old_caps[i]; i++)
safe_free(old_caps[i]);
}
diff --git a/src/api-command.c b/src/api-command.c
index e32b5c7..f61e2bf 100644
--- a/src/api-command.c
+++ b/src/api-command.c
@@ -23,8 +23,8 @@
#include "unrealircd.h"
/* Forward declarations */
-static Command *CommandAddInternal(Module *module, char *cmd, CmdFunc func, AliasCmdFunc aliasfunc, unsigned char params, int flags);
-static RealCommand *add_Command_backend(char *cmd);
+static Command *CommandAddInternal(Module *module, const char *cmd, CmdFunc func, AliasCmdFunc aliasfunc, unsigned char params, int flags);
+static RealCommand *add_Command_backend(const char *cmd);
/** @defgroup CommandAPI Command API
* @{
@@ -32,7 +32,7 @@ static RealCommand *add_Command_backend(char *cmd);
/** Returns 1 if the specified command exists
*/
-int CommandExists(char *name)
+int CommandExists(const char *name)
{
RealCommand *p;
@@ -53,7 +53,7 @@ int CommandExists(char *name)
* @param flags Who may execute this command - one or more CMD_* flags
* @returns The newly registered command, or NULL in case of error (eg: already exist)
*/
-Command *CommandAdd(Module *module, char *cmd, CmdFunc func, unsigned char params, int flags)
+Command *CommandAdd(Module *module, const char *cmd, CmdFunc func, unsigned char params, int flags)
{
if (flags & CMD_ALIAS)
{
@@ -75,7 +75,7 @@ Command *CommandAdd(Module *module, char *cmd, CmdFunc func, unsigned char param
* @param flags Who may execute this command - one or more CMD_* flags
* @returns The newly registered command (alias), or NULL in case of error (eg: already exist)
*/
-Command *AliasAdd(Module *module, char *cmd, AliasCmdFunc aliasfunc, unsigned char params, int flags)
+Command *AliasAdd(Module *module, const char *cmd, AliasCmdFunc aliasfunc, unsigned char params, int flags)
{
if (!(flags & CMD_ALIAS))
flags |= CMD_ALIAS;
@@ -84,7 +84,7 @@ Command *AliasAdd(Module *module, char *cmd, AliasCmdFunc aliasfunc, unsigned ch
/** @} */
-static Command *CommandAddInternal(Module *module, char *cmd, CmdFunc func, AliasCmdFunc aliasfunc, unsigned char params, int flags)
+static Command *CommandAddInternal(Module *module, const char *cmd, CmdFunc func, AliasCmdFunc aliasfunc, unsigned char params, int flags)
{
Command *command = NULL;
RealCommand *c;
@@ -191,7 +191,7 @@ void CommandDel(Command *command)
* @note If mtags is NULL then new message tags are created for the command
* (and destroyed before return).
*/
-void do_cmd(Client *client, MessageTag *mtags, char *cmd, int parc, char *parv[])
+void do_cmd(Client *client, MessageTag *mtags, const char *cmd, int parc, const char *parv[])
{
RealCommand *cmptr;
@@ -233,7 +233,7 @@ void init_CommandHash(void)
CommandAdd(NULL, MSG_MODULE, cmd_module, MAXPARA, CMD_USER);
}
-static RealCommand *add_Command_backend(char *cmd)
+static RealCommand *add_Command_backend(const char *cmd)
{
RealCommand *c = safe_alloc(sizeof(RealCommand));
@@ -250,7 +250,7 @@ static RealCommand *add_Command_backend(char *cmd)
*/
/** Find a command by name and flags */
-RealCommand *find_command(char *cmd, int flags)
+RealCommand *find_command(const char *cmd, int flags)
{
RealCommand *p;
for (p = CommandHash[toupper(*cmd)]; p; p = p->next) {
@@ -269,7 +269,7 @@ RealCommand *find_command(char *cmd, int flags)
}
/** Find a command by name (no access rights check) */
-RealCommand *find_command_simple(char *cmd)
+RealCommand *find_command_simple(const char *cmd)
{
RealCommand *c;
diff --git a/src/api-efunctions.c b/src/api-efunctions.c
index 4412af1..d6dbfdc 100644
--- a/src/api-efunctions.c
+++ b/src/api-efunctions.c
@@ -34,47 +34,50 @@ static Efunction *Efunctions[MAXEFUNCTIONS]; /* Efunction objects (used for reha
static EfunctionsList efunction_table[MAXEFUNCTIONS];
/* Efuncs */
-void (*do_join)(Client *client, int parc, char *parv[]);
-void (*join_channel)(Channel *channel, Client *client, MessageTag *mtags, int flags);
-int (*can_join)(Client *client, Channel *channel, char *key, char *parv[]);
-void (*do_mode)(Channel *channel, Client *client, MessageTag *mtags, int parc, char *parv[], time_t sendts, int samode);
-void (*set_mode)(Channel *channel, Client *client, int parc, char *parv[], u_int *pcount,
- char pvar[MAXMODEPARAMS][MODEBUFLEN + 3], int bounce);
-void (*cmd_umode)(Client *client, MessageTag *mtags, int parc, char *parv[]);
-int (*register_user)(Client *client, char *nick, char *username, char *umode, char *virthost, char *ip);
+void (*do_join)(Client *client, int parc, const char *parv[]);
+void (*join_channel)(Channel *channel, Client *client, MessageTag *mtags, const char *member_modes);
+int (*can_join)(Client *client, Channel *channel, const char *key, char **errmsg);
+void (*do_mode)(Channel *channel, Client *client, MessageTag *mtags, int parc, const char *parv[], time_t sendts, int samode);
+MultiLineMode *(*set_mode)(Channel *channel, Client *client, int parc, const char *parv[], u_int *pcount,
+ char pvar[MAXMODEPARAMS][MODEBUFLEN + 3]);
+void (*set_channel_mode)(Channel *channel, char *modes, char *parameters);
+void (*cmd_umode)(Client *client, MessageTag *mtags, int parc, const char *parv[]);
+int (*register_user)(Client *client);
int (*tkl_hash)(unsigned int c);
char (*tkl_typetochar)(int type);
int (*tkl_chartotype)(char c);
-char *(*tkl_type_string)(TKL *tk);
-TKL *(*tkl_add_serverban)(int type, char *usermask, char *hostmask, char *reason, char *setby,
+const char *(*tkl_type_string)(TKL *tk);
+const char *(*tkl_type_config_string)(TKL *tk);
+char *(*tkl_uhost)(TKL *tkl, char *buf, size_t buflen, int options);
+TKL *(*tkl_add_serverban)(int type, const char *usermask, const char *hostmask, const char *reason, const char *setby,
time_t expire_at, time_t set_at, int soft, int flags);
-TKL *(*tkl_add_nameban)(int type, char *name, int hold, char *reason, char *setby,
+TKL *(*tkl_add_nameban)(int type, const char *name, int hold, const char *reason, const char *setby,
time_t expire_at, time_t set_at, int flags);
-TKL *(*tkl_add_spamfilter)(int type, unsigned short target, unsigned short action, Match *match, char *setby,
+TKL *(*tkl_add_spamfilter)(int type, unsigned short target, unsigned short action, Match *match, const char *setby,
time_t expire_at, time_t set_at,
- time_t spamf_tkl_duration, char *spamf_tkl_reason,
+ time_t spamf_tkl_duration, const char *spamf_tkl_reason,
int flags);
-TKL *(*tkl_add_banexception)(int type, char *usermask, char *hostmask, char *reason, char *set_by,
- time_t expire_at, time_t set_at, int soft, char *bantypes, int flags);
+TKL *(*tkl_add_banexception)(int type, const char *usermask, const char *hostmask, const char *reason, const char *set_by,
+ time_t expire_at, time_t set_at, int soft, const char *bantypes, int flags);
TKL *(*tkl_del_line)(TKL *tkl);
void (*tkl_check_local_remove_shun)(TKL *tmp);
int (*find_tkline_match)(Client *client, int skip_soft);
int (*find_shun)(Client *client);
int(*find_spamfilter_user)(Client *client, int flags);
-TKL *(*find_qline)(Client *client, char *nick, int *ishold);
+TKL *(*find_qline)(Client *client, const char *nick, int *ishold);
TKL *(*find_tkline_match_zap)(Client *client);
-void (*tkl_stats)(Client *client, int type, char *para, int *cnt);
+void (*tkl_stats)(Client *client, int type, const char *para, int *cnt);
void (*tkl_sync)(Client *client);
-void (*cmd_tkl)(Client *client, MessageTag *mtags, int parc, char *parv[]);
-int (*place_host_ban)(Client *client, BanAction action, char *reason, long duration);
-int (*match_spamfilter)(Client *client, char *str_in, int type, char *cmd, char *target, int flags, TKL **rettk);
-int (*match_spamfilter_mtags)(Client *client, MessageTag *mtags, char *cmd);
+void (*cmd_tkl)(Client *client, MessageTag *mtags, int parc, const char *parv[]);
+int (*place_host_ban)(Client *client, BanAction action, const char *reason, long duration);
+int (*match_spamfilter)(Client *client, const char *str_in, int type, const char *cmd, const char *target, int flags, TKL **rettk);
+int (*match_spamfilter_mtags)(Client *client, MessageTag *mtags, const char *cmd);
int (*join_viruschan)(Client *client, TKL *tk, int type);
-unsigned char *(*StripColors)(unsigned char *text);
-const char *(*StripControlCodes)(unsigned char *text);
-void (*spamfilter_build_user_string)(char *buf, char *nick, Client *client);
+const char *(*StripColors)(const char *text);
+const char *(*StripControlCodes)(const char *text);
+void (*spamfilter_build_user_string)(char *buf, const char *nick, Client *client);
void (*send_protoctl_servers)(Client *client, int response);
-int (*verify_link)(Client *client, char *servername, ConfigItem_link **link_out);
+int (*verify_link)(Client *client, ConfigItem_link **link_out);
void (*introduce_user)(Client *to, Client *client);
void (*send_server_message)(Client *client);
void (*broadcast_md_client)(ModDataInfo *mdi, Client *client, ModData *md);
@@ -82,37 +85,40 @@ void (*broadcast_md_channel)(ModDataInfo *mdi, Channel *channel, ModData *md);
void (*broadcast_md_member)(ModDataInfo *mdi, Channel *channel, Member *m, ModData *md);
void (*broadcast_md_membership)(ModDataInfo *mdi, Client *client, Membership *m, ModData *md);
int (*check_banned)(Client *client, int exitflags);
-int (*check_deny_version)(Client *client, char *software, int protocol, char *flags);
-void (*broadcast_md_client_cmd)(Client *except, Client *sender, Client *acptr, char *varname, char *value);
-void (*broadcast_md_channel_cmd)(Client *except, Client *sender, Channel *channel, char *varname, char *value);
-void (*broadcast_md_member_cmd)(Client *except, Client *sender, Channel *channel, Client *acptr, char *varname, char *value);
-void (*broadcast_md_membership_cmd)(Client *except, Client *sender, Client *acptr, Channel *channel, char *varname, char *value);
+int (*check_deny_version)(Client *client, const char *software, int protocol, const char *flags);
+void (*broadcast_md_client_cmd)(Client *except, Client *sender, Client *acptr, const char *varname, const char *value);
+void (*broadcast_md_channel_cmd)(Client *except, Client *sender, Channel *channel, const char *varname, const char *value);
+void (*broadcast_md_member_cmd)(Client *except, Client *sender, Channel *channel, Client *acptr, const char *varname, const char *value);
+void (*broadcast_md_membership_cmd)(Client *except, Client *sender, Client *acptr, Channel *channel, const char *varname, const char *value);
+void (*moddata_add_s2s_mtags)(Client *client, MessageTag **mtags);
+void (*moddata_extract_s2s_mtags)(Client *client, MessageTag *mtags);
void (*send_moddata_client)(Client *srv, Client *client);
void (*send_moddata_channel)(Client *srv, Channel *channel);
void (*send_moddata_members)(Client *srv);
void (*broadcast_moddata_client)(Client *client);
-int (*match_user)(char *rmask, Client *client, int options);
+int (*match_user)(const char *rmask, Client *client, int options);
void (*userhost_changed)(Client *client);
void (*userhost_save_current)(Client *client);
void (*send_join_to_local_users)(Client *client, Channel *channel, MessageTag *mtags);
int (*do_nick_name)(char *nick);
int (*do_remote_nick_name)(char *nick);
-char *(*charsys_get_current_languages)(void);
+const char *(*charsys_get_current_languages)(void);
void (*broadcast_sinfo)(Client *client, Client *to, Client *except);
+void (*connect_server)(ConfigItem_link *aconf, Client *by, struct hostent *hp);
void (*parse_message_tags)(Client *client, char **str, MessageTag **mtag_list);
-char *(*mtags_to_string)(MessageTag *m, Client *client);
-int (*can_send_to_channel)(Client *client, Channel *channel, char **msgtext, char **errmsg, int notice);
+const char *(*mtags_to_string)(MessageTag *m, Client *client);
+int (*can_send_to_channel)(Client *client, Channel *channel, const char **msgtext, const char **errmsg, int notice);
void (*broadcast_md_globalvar)(ModDataInfo *mdi, ModData *md);
-void (*broadcast_md_globalvar_cmd)(Client *except, Client *sender, char *varname, char *value);
-int (*tkl_ip_hash)(char *ip);
+void (*broadcast_md_globalvar_cmd)(Client *except, Client *sender, const char *varname, const char *value);
+int (*tkl_ip_hash)(const char *ip);
int (*tkl_ip_hash_type)(int type);
-void (*sendnotice_tkl_del)(char *removed_by, TKL *tkl);
+void (*sendnotice_tkl_del)(const char *removed_by, TKL *tkl);
void (*sendnotice_tkl_add)(TKL *tkl);
void (*free_tkl)(TKL *tkl);
-TKL *(*find_tkl_serverban)(int type, char *usermask, char *hostmask, int softban);
-TKL *(*find_tkl_banexception)(int type, char *usermask, char *hostmask, int softban);
-TKL *(*find_tkl_nameban)(int type, char *name, int hold);
-TKL *(*find_tkl_spamfilter)(int type, char *match_string, unsigned short action, unsigned short target);
+TKL *(*find_tkl_serverban)(int type, const char *usermask, const char *hostmask, int softban);
+TKL *(*find_tkl_banexception)(int type, const char *usermask, const char *hostmask, int softban);
+TKL *(*find_tkl_nameban)(int type, const char *name, int hold);
+TKL *(*find_tkl_spamfilter)(int type, const char *match_string, unsigned short action, unsigned short target);
int (*find_tkl_exception)(int ban_type, Client *client);
int (*is_silenced)(Client *client, Client *acptr);
int (*del_silence)(Client *client, const char *mask);
@@ -120,9 +126,17 @@ int (*add_silence)(Client *client, const char *mask, int senderr);
void *(*labeled_response_save_context)(void);
void (*labeled_response_set_context)(void *ctx);
void (*labeled_response_force_end)(void);
-void (*kick_user)(MessageTag *mtags, Channel *channel, Client *client, Client *victim, char *comment);
+void (*kick_user)(MessageTag *mtags, Channel *channel, Client *client, Client *victim, const char *comment);
+int (*watch_add)(const char *nick, Client *client, int flags);
+int (*watch_del)(const char *nick, Client *client, int flags);
+int (*watch_del_list)(Client *client, int flags);
+Watch *(*watch_get)(const char *nick);
+int (*watch_check)(Client *client, int reply, int (*watch_notify)(Client *client, Watch *watch, Link *lp, int event));
+void (*do_unreal_log_remote_deliver)(LogLevel loglevel, const char *subsystem, const char *event_id, MultiLine *msg, const char *json_serialized);
+char *(*get_chmodes_for_user)(Client *client, const char *flags);
+WhoisConfigDetails (*whois_get_policy)(Client *client, Client *target, const char *name);
-Efunction *EfunctionAddMain(Module *module, EfunctionType eftype, int (*func)(), void (*vfunc)(), void *(*pvfunc)(), char *(*cfunc)())
+Efunction *EfunctionAddMain(Module *module, EfunctionType eftype, int (*func)(), void (*vfunc)(), void *(*pvfunc)(), char *(*stringfunc)(), const char *(*conststringfunc)())
{
Efunction *p;
@@ -140,8 +154,10 @@ Efunction *EfunctionAddMain(Module *module, EfunctionType eftype, int (*func)(),
p->func.voidfunc = vfunc;
if (pvfunc)
p->func.pvoidfunc = pvfunc;
- if (cfunc)
- p->func.pcharfunc = cfunc;
+ if (stringfunc)
+ p->func.stringfunc = stringfunc;
+ if (conststringfunc)
+ p->func.conststringfunc = conststringfunc;
p->type = eftype;
p->owner = module;
AddListItem(p, Efunctions[eftype]);
@@ -256,7 +272,9 @@ void efunctions_switchover(void)
continue;
if (!efunction_table[i].funcptr)
{
- ircd_log(LOG_ERROR, "[BUG] efunctions_switchover(): someone forgot to initialize the function table for efunc %d", i);
+ unreal_log(ULOG_FATAL, "module", "BUG_EFUNCTIONS_SWITCHOVER", NULL,
+ "[BUG] efunctions_switchover(): someone forgot to initialize the function table for efunc $efunction_number",
+ log_data_integer("efunction_number", i));
abort();
}
*efunction_table[i].funcptr = e->func.voidfunc; /* This is the new one. */
@@ -273,10 +291,19 @@ void efunctions_switchover(void)
}
}
-#define efunc_init_function(what, func, default_func) efunc_init_function_(what, #func, (void *)&func, default_func)
+#define efunc_init_function(what, func, default_func) efunc_init_function_(what, #func, (void *)&func, (void *)default_func)
void efunc_init_function_(EfunctionType what, char *name, void *func, void *default_func)
{
+ if (what >= MAXEFUNCTIONS)
+ {
+ /* increase MAXEFUNCTIONS if you ever encounter that --k4be */
+ unreal_log(ULOG_FATAL, "module", "BUG_EFUNC_INIT_FUNCTION_TOO_MANY", NULL,
+ "Too many efunctions! ($efunctions_request > $efunctions_max)",
+ log_data_integer("efunctions_request", what),
+ log_data_integer("efunctions_max", MAXEFUNCTIONS));
+ abort();
+ }
safe_strdup(efunction_table[what].name, name);
efunction_table[what].funcptr = func;
efunction_table[what].deffunc = default_func;
@@ -290,6 +317,7 @@ void efunctions_init(void)
efunc_init_function(EFUNC_CAN_JOIN, can_join, NULL);
efunc_init_function(EFUNC_DO_MODE, do_mode, NULL);
efunc_init_function(EFUNC_SET_MODE, set_mode, NULL);
+ efunc_init_function(EFUNC_SET_CHANNEL_MODE, set_channel_mode, NULL);
efunc_init_function(EFUNC_CMD_UMODE, cmd_umode, NULL);
efunc_init_function(EFUNC_REGISTER_USER, register_user, NULL);
efunc_init_function(EFUNC_TKL_HASH, tkl_hash, NULL);
@@ -327,6 +355,8 @@ void efunctions_init(void)
efunc_init_function(EFUNC_BROADCAST_MD_CHANNEL_CMD, broadcast_md_channel_cmd, NULL);
efunc_init_function(EFUNC_BROADCAST_MD_MEMBER_CMD, broadcast_md_member_cmd, NULL);
efunc_init_function(EFUNC_BROADCAST_MD_MEMBERSHIP_CMD, broadcast_md_membership_cmd, NULL);
+ efunc_init_function(EFUNC_MODDATA_ADD_S2S_MTAGS, moddata_add_s2s_mtags, NULL);
+ efunc_init_function(EFUNC_MODDATA_EXTRACT_S2S_MTAGS, moddata_extract_s2s_mtags, NULL);
efunc_init_function(EFUNC_SEND_MODDATA_CLIENT, send_moddata_client, NULL);
efunc_init_function(EFUNC_SEND_MODDATA_CHANNEL, send_moddata_channel, NULL);
efunc_init_function(EFUNC_SEND_MODDATA_MEMBERS, send_moddata_members, NULL);
@@ -339,10 +369,12 @@ void efunctions_init(void)
efunc_init_function(EFUNC_DO_REMOTE_NICK_NAME, do_remote_nick_name, NULL);
efunc_init_function(EFUNC_CHARSYS_GET_CURRENT_LANGUAGES, charsys_get_current_languages, NULL);
efunc_init_function(EFUNC_BROADCAST_SINFO, broadcast_sinfo, NULL);
+ efunc_init_function(EFUNC_CONNECT_SERVER, connect_server, NULL);
efunc_init_function(EFUNC_PARSE_MESSAGE_TAGS, parse_message_tags, &parse_message_tags_default_handler);
efunc_init_function(EFUNC_MTAGS_TO_STRING, mtags_to_string, &mtags_to_string_default_handler);
efunc_init_function(EFUNC_TKL_CHARTOTYPE, tkl_chartotype, NULL);
efunc_init_function(EFUNC_TKL_TYPE_STRING, tkl_type_string, NULL);
+ efunc_init_function(EFUNC_TKL_TYPE_CONFIG_STRING, tkl_type_config_string, NULL);
efunc_init_function(EFUNC_CAN_SEND_TO_CHANNEL, can_send_to_channel, NULL);
efunc_init_function(EFUNC_BROADCAST_MD_GLOBALVAR, broadcast_md_globalvar, NULL);
efunc_init_function(EFUNC_BROADCAST_MD_GLOBALVAR_CMD, broadcast_md_globalvar_cmd, NULL);
@@ -365,4 +397,13 @@ void efunctions_init(void)
efunc_init_function(EFUNC_LABELED_RESPONSE_SET_CONTEXT, labeled_response_set_context, labeled_response_set_context_default_handler);
efunc_init_function(EFUNC_LABELED_RESPONSE_FORCE_END, labeled_response_force_end, labeled_response_force_end_default_handler);
efunc_init_function(EFUNC_KICK_USER, kick_user, NULL);
+ efunc_init_function(EFUNC_WATCH_ADD, watch_add, NULL);
+ efunc_init_function(EFUNC_WATCH_DEL, watch_del, NULL);
+ efunc_init_function(EFUNC_WATCH_DEL_LIST, watch_del_list, NULL);
+ efunc_init_function(EFUNC_WATCH_GET, watch_get, NULL);
+ efunc_init_function(EFUNC_WATCH_CHECK, watch_check, NULL);
+ efunc_init_function(EFUNC_TKL_UHOST, tkl_uhost, NULL);
+ efunc_init_function(EFUNC_DO_UNREAL_LOG_REMOTE_DELIVER, do_unreal_log_remote_deliver, do_unreal_log_remote_deliver_default_handler);
+ efunc_init_function(EFUNC_GET_CHMODES_FOR_USER, get_chmodes_for_user, NULL);
+ efunc_init_function(EFUNC_WHOIS_GET_POLICY, whois_get_policy, NULL);
}
diff --git a/src/api-event.c b/src/api-event.c
index 8c328d2..799edb7 100644
--- a/src/api-event.c
+++ b/src/api-event.c
@@ -45,7 +45,7 @@ extern EVENT(unrealdb_expire_secret_cache);
* can be later, in case of high load, in very extreme cases even up to 1000 or 2000
* msec later but that would be very unusual. Just saying, it's not a guarantee..
*/
-Event *EventAdd(Module *module, char *name, vFP event, void *data, long every_msec, int count)
+Event *EventAdd(Module *module, const char *name, vFP event, void *data, long every_msec, int count)
{
Event *newevent;
@@ -56,16 +56,6 @@ Event *EventAdd(Module *module, char *name, vFP event, void *data, long every_ms
return NULL;
}
- if ((every_msec < 100) && (count == 0))
- {
- ircd_log(LOG_ERROR, "[BUG] EventAdd() '%s' from module '%s' with suspiciously low every_msec value (%ld). "
- "Note that it is in milliseconds now (1000 = 1 second)!",
- name,
- module ? module->header->name : "???",
- every_msec);
- every_msec = 100;
- }
-
newevent = safe_alloc(sizeof(Event));
safe_strdup(newevent->name, name);
newevent->count = count;
@@ -128,12 +118,16 @@ static void EventDelReal(Event *e)
{
if (!e->deleted)
{
- ircd_log(LOG_ERROR, "EventDelReal called while e->deleted is 0. This cannot happen. Event name: %s.", e->name);
+ unreal_log(ULOG_FATAL, "module", "BUG_EVENTDELREAL_ZERO", NULL,
+ "[BUG] EventDelReal called while e->deleted is 0. This cannot happen. Event name: $event_name",
+ log_data_string("event_name", e->name));
abort();
}
if (e->owner)
{
- ircd_log(LOG_ERROR, "EventDelReal called while e->owner is non-NULL. This cannot happen. Event name: %s.", e->name);
+ unreal_log(ULOG_FATAL, "module", "BUG_EVENTDELREAL_NULL", NULL,
+ "[BUG] EventDelReal called while e->owner is NULL. This cannot happen. Event name: $event_name",
+ log_data_string("event_name", e->name));
abort();
}
safe_free(e->name);
@@ -153,7 +147,7 @@ static void CleanupEvents(void)
}
}
-Event *EventFind(char *name)
+Event *EventFind(const char *name)
{
Event *eventptr;
@@ -173,19 +167,7 @@ int EventMod(Event *event, EventInfo *mods)
}
if (mods->flags & EMOD_EVERY)
- {
- if (mods->every_msec < 100)
- {
- ircd_log(LOG_ERROR, "[BUG] EventMod() for '%s' from module '%s' with suspiciously low every_msec value (%lld). "
- "Note that it is in milliseconds now (1000 = 1 second)!",
- event->name,
- event->owner ? event->owner->header->name : "???",
- (long long)mods->every_msec);
- mods->every_msec = 100;
- }
-
event->every_msec = mods->every_msec;
- }
if (mods->flags & EMOD_HOWMANY)
event->count = mods->count;
if (mods->flags & EMOD_NAME)
@@ -240,7 +222,7 @@ void SetupEvents(void)
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, "try_connections", try_connections, NULL, 2000, 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);
}
diff --git a/src/api-extban.c b/src/api-extban.c
index fdf7f8b..a750689 100644
--- a/src/api-extban.c
+++ b/src/api-extban.c
@@ -22,144 +22,285 @@
#include "unrealircd.h"
-Extban MODVAR ExtBan_Table[EXTBANTABLESZ]; /* this should be fastest */
-unsigned MODVAR short ExtBan_highest = 0;
+/** List of all extbans, their handlers, etc */
+MODVAR Extban *extbans = NULL;
void set_isupport_extban(void)
{
- int i;
- char extbanstr[EXTBANTABLESZ+1], *m;
+ char extbanstr[512];
+ Extban *e;
+ char *p = extbanstr;
+
+ for (e = extbans; e; e = e->next)
+ *p++ = e->letter;
+ *p = '\0';
- m = extbanstr;
- for (i = 0; i <= ExtBan_highest; i++)
- {
- if (ExtBan_Table[i].flag)
- *m++ = ExtBan_Table[i].flag;
- }
- *m = 0;
ISupportSetFmt(NULL, "EXTBAN", "~,%s", extbanstr);
}
-Extban *findmod_by_bantype(char c)
+Extban *findmod_by_bantype(const char *str, const char **remainder)
{
-int i;
+ Extban *e;
+ int ban_name_length;
+ const char *p = strchr(str, ':');
- for (i=0; i <= ExtBan_highest; i++)
- if (ExtBan_Table[i].flag == c)
- return &ExtBan_Table[i];
+ if (!p || !p[1])
+ {
+ if (remainder)
+ *remainder = NULL;
+ return NULL;
+ }
+ if (remainder)
+ *remainder = p+1;
+
+ ban_name_length = p - str - 1;
+
+ for (e=extbans; e; e = e->next)
+ {
+ if ((ban_name_length == 1) && (e->letter == str[1]))
+ return e;
+ if (e->name)
+ {
+ int namelen = strlen(e->name);
+ if ((namelen == ban_name_length) && !strncmp(e->name, str+1, namelen))
+ return e;
+ }
+ }
return NULL;
}
+/* Check if this is a valid extended ban name */
+int is_valid_extban_name(const char *p)
+{
+ if (!*p)
+ return 0; /* empty name */
+ for (; *p; p++)
+ if (!isalnum(*p) && !strchr("_-", *p))
+ return 0;
+ return 1;
+}
+
+static void extban_add_sorted(Extban *n)
+{
+ Extban *m;
+
+ if (extbans == NULL)
+ {
+ extbans = n;
+ return;
+ }
+
+ for (m = extbans; m; m = m->next)
+ {
+ if (m->letter == '\0')
+ abort();
+ if (sort_character_lowercase_before_uppercase(n->letter, m->letter))
+ {
+ /* Insert us before */
+ if (m->prev)
+ m->prev->next = n;
+ else
+ extbans = n; /* new head */
+ n->prev = m->prev;
+
+ n->next = m;
+ m->prev = n;
+ return;
+ }
+ if (!m->next)
+ {
+ /* Append us at end */
+ m->next = n;
+ n->prev = m;
+ return;
+ }
+ }
+}
+
Extban *ExtbanAdd(Module *module, ExtbanInfo req)
{
- int slot;
+ Extban *e;
+ int existing = 0;
- if (findmod_by_bantype(req.flag))
+ if (!req.name)
{
- if (module)
- module->errorcode = MODERR_EXISTS;
- return NULL;
- }
-
- /* TODO: perhaps some sanity checking on a-zA-Z0-9? */
- for (slot = 0; slot < EXTBANTABLESZ; slot++)
- if (ExtBan_Table[slot].flag == '\0')
- break;
- if (slot >= EXTBANTABLESZ - 1)
- {
- if (module)
- module->errorcode = MODERR_NOSPACE;
+ module->errorcode = MODERR_INVALID;
+ unreal_log(ULOG_ERROR, "module", "EXTBANADD_API_ERROR", NULL,
+ "ExtbanAdd(): name must be specified for ban (new in U6). Module: $module_name",
+ log_data_string("module_name", module->header->name));
return NULL;
}
- ExtBan_Table[slot].flag = req.flag;
- ExtBan_Table[slot].is_ok = req.is_ok;
- ExtBan_Table[slot].conv_param = req.conv_param;
- ExtBan_Table[slot].is_banned = req.is_banned;
- ExtBan_Table[slot].owner = module;
- ExtBan_Table[slot].options = req.options;
+
+ if (!req.is_banned_events && req.is_banned)
+ {
+ module->errorcode = MODERR_INVALID;
+ unreal_log(ULOG_ERROR, "module", "EXTBANADD_API_ERROR", NULL,
+ "ExtbanAdd(): module must indicate via .is_banned_events on which BANCHK_* "
+ "events to listen on (new in U6). Module: $module_name",
+ log_data_string("module_name", module->header->name));
+ return NULL;
+ }
+
+ if (!isalnum(req.letter))
+ {
+ module->errorcode = MODERR_INVALID;
+ unreal_log(ULOG_ERROR, "module", "EXTBANADD_API_ERROR", NULL,
+ "ExtbanAdd(): module tried to add extban which is not alphanumeric. "
+ "Module: $module_name",
+ log_data_string("module_name", module->header->name));
+ return NULL;
+ }
+
+ if (!is_valid_extban_name(req.name))
+ {
+ module->errorcode = MODERR_INVALID;
+ unreal_log(ULOG_ERROR, "module", "EXTBANADD_API_ERROR", NULL,
+ "ExtbanAdd(): module tried to add extban with an invalid name ($extban_name). "
+ "Module: $module_name",
+ log_data_string("module_name", module->header->name),
+ log_data_string("extban_name", req.name));
+ return NULL;
+ }
+
+ for (e=extbans; e; e = e->next)
+ {
+ if (e->letter == req.letter)
+ {
+ if (e->unloaded)
+ {
+ e->unloaded = 0;
+ existing = 1;
+ break;
+ } else {
+ if (module)
+ module->errorcode = MODERR_EXISTS;
+ return NULL;
+ }
+ }
+ }
+
+ if (!e)
+ {
+ /* Not found, create */
+ e = safe_alloc(sizeof(Extban));
+ e->letter = req.letter;
+ extban_add_sorted(e);
+ }
+ e->letter = req.letter;
+ safe_strdup(e->name, req.name);
+ e->is_ok = req.is_ok;
+ e->conv_param = req.conv_param;
+ e->is_banned = req.is_banned;
+ e->is_banned_events = req.is_banned_events;
+ e->owner = module;
+ e->options = req.options;
if (module)
{
ModuleObject *banobj = safe_alloc(sizeof(ModuleObject));
- banobj->object.extban = &ExtBan_Table[slot];
+ banobj->object.extban = e;
banobj->type = MOBJ_EXTBAN;
AddListItem(banobj, module->objects);
module->errorcode = MODERR_NOERROR;
}
- ExtBan_highest = slot;
set_isupport_extban();
- return &ExtBan_Table[slot];
+ return e;
}
-void ExtbanDel(Extban *eb)
+static void unload_extban_commit(Extban *e)
{
- /* Just zero it all away.. */
+ /* Should we mass unban everywhere?
+ * Hmmm. Not needed per se, user can always unset
+ * themselves. Leaning towards no atm.
+ */
+ // noop
- if (eb->owner)
+ /* Then unload the extban */
+ DelListItem(e, extbans);
+ safe_free(e);
+ set_isupport_extban();
+}
+
+void ExtbanDel(Extban *e)
+{
+ /* Always free the module object */
+ if (e->owner)
{
ModuleObject *banobj;
- for (banobj = eb->owner->objects; banobj; banobj = banobj->next)
+ for (banobj = e->owner->objects; banobj; banobj = banobj->next)
{
- if (banobj->type == MOBJ_EXTBAN && banobj->object.extban == eb)
+ if (banobj->type == MOBJ_EXTBAN && banobj->object.extban == e)
{
- DelListItem(banobj, eb->owner->objects);
+ DelListItem(banobj, e->owner->objects);
safe_free(banobj);
break;
}
}
}
- memset(eb, 0, sizeof(Extban));
- set_isupport_extban();
- /* Hmm do we want to go trough all chans and remove the bans?
- * I would say 'no' because perhaps we are just reloading,
- * and else.. well... screw them?
- */
-}
-/* NOTE: the routines below can safely assume the ban has at
- * least the '~t:' part (t=type). -- Syzop
- */
+ /* Whether we can actually (already) free the Extban, it depends... */
+ if (loop.rehashing)
+ e->unloaded = 1;
+ else
+ unload_extban_commit(e);
+}
/** General is_ok for n!u@h stuff that also deals with recursive extbans.
*/
-int extban_is_ok_nuh_extban(Client *client, Channel* channel, char *para, int checkt, int what, int what2)
+int extban_is_ok_nuh_extban(BanContext *b)
{
- char *mask = (para + 3);
- Extban *p = NULL;
int isok;
static int extban_is_ok_recursion = 0;
/* Mostly copied from clean_ban_mask - but note MyUser checks aren't needed here: extban->is_ok() according to cmd_mode isn't called for nonlocal. */
- if (is_extended_ban(mask))
+ if (is_extended_ban(b->banstr))
{
- if (extban_is_ok_recursion)
- return 0; /* Fail: more than one stacked extban */
+ const char *nextbanstr;
+ Extban *extban = NULL;
- if ((checkt == EXBCHK_PARAM) && RESTRICT_EXTENDEDBANS && !ValidatePermissionsForPath("immune:restrict-extendedbans",client,NULL,channel,NULL))
+ /* We're dealing with a stacked extended ban.
+ * Rules:
+ * 1) You can only stack once, so: ~x:~y:something and not ~x:~y:~z...
+ * 2) The second item may never be an action modifier, nor have the
+ * EXTBOPT_NOSTACKCHILD letter set (for things like a textban).
+ */
+
+ if (extban_is_ok_recursion)
+ return 0; /* Rule #1 violation (more than one stacked extban) */
+
+ if ((b->is_ok_check == EXBCHK_PARAM) && RESTRICT_EXTENDEDBANS && !ValidatePermissionsForPath("immune:restrict-extendedbans",b->client,NULL,b->channel,NULL))
{
/* Test if this specific extban has been disabled.
* (We can be sure RESTRICT_EXTENDEDBANS is not *. Else this extended ban wouldn't be happening at all.)
*/
- if (strchr(RESTRICT_EXTENDEDBANS, mask[1]))
+ if (strchr(RESTRICT_EXTENDEDBANS, b->banstr[1]))
{
- sendnotice(client, "Setting/removing of extended bantypes '%s' has been disabled.", RESTRICT_EXTENDEDBANS);
+ sendnotice(b->client, "Setting/removing of extended bantypes '%s' has been disabled.", RESTRICT_EXTENDEDBANS);
return 0; /* Fail */
}
}
- p = findmod_by_bantype(mask[1]);
- if (!p)
+ extban = findmod_by_bantype(b->banstr, &nextbanstr);
+ if (!extban)
{
- if (what == MODE_DEL)
+ if (b->what == MODE_DEL)
{
return 1; /* Always allow killing unknowns. */
}
return 0; /* Don't add unknown extbans. */
}
- /* Now we have to ask the stacked extban if it's ok. */
- if (p->is_ok)
+
+ if ((extban->options & EXTBOPT_ACTMODIFIER) || (extban->options & EXTBOPT_NOSTACKCHILD))
{
+ /* Rule #2 violation */
+ return 0;
+ }
+
+ /* Now we have to ask the stacked extban if it's ok. */
+ if (extban->is_ok)
+ {
+ b->banstr = nextbanstr;
extban_is_ok_recursion++;
- isok = p->is_ok(client, channel, mask, checkt, what, what2);
+ isok = extban->is_ok(b);
extban_is_ok_recursion--;
return isok;
}
@@ -171,19 +312,15 @@ int extban_is_ok_nuh_extban(Client *client, Channel* channel, char *para, int ch
* to ensure the parameter is nick!user@host.
* most of the code is just copied from clean_ban_mask.
*/
-char *extban_conv_param_nuh(char *para)
+const char *extban_conv_param_nuh(BanContext *b, Extban *extban)
{
char *cp, *user, *host, *mask, *ret = NULL;
static char retbuf[USERLEN + NICKLEN + HOSTLEN + 32];
char tmpbuf[USERLEN + NICKLEN + HOSTLEN + 32];
- char pfix[8];
- if (strlen(para)<3)
- return NULL; /* normally impossible */
-
- strlcpy(tmpbuf, para, sizeof(retbuf));
- mask = tmpbuf + 3;
- strlcpy(pfix, tmpbuf, mask - tmpbuf + 1);
+ /* Work on a copy */
+ strlcpy(tmpbuf, b->banstr, sizeof(retbuf));
+ mask = tmpbuf;
if (!*mask)
return NULL; /* empty extban */
@@ -202,13 +339,13 @@ char *extban_conv_param_nuh(char *para)
if (!ret)
ret = make_nick_user_host(trim_str(cp,NICKLEN), trim_str(user,USERLEN), trim_str(host,HOSTLEN));
- ircsnprintf(retbuf, sizeof(retbuf), "%s%s", pfix, ret);
+ strlcpy(retbuf, ret, sizeof(retbuf));
return retbuf;
}
/** conv_param to deal with stacked extbans.
*/
-char *extban_conv_param_nuh_or_extban(char *para)
+const char *extban_conv_param_nuh_or_extban(BanContext *b, Extban *self_extban)
{
#if (USERLEN + NICKLEN + HOSTLEN + 32) > 256
#error "wtf?"
@@ -217,83 +354,77 @@ char *extban_conv_param_nuh_or_extban(char *para)
static char printbuf[256];
char *mask;
char tmpbuf[USERLEN + NICKLEN + HOSTLEN + 32];
- char bantype = para[1];
- char *ret = NULL;
- Extban *p = NULL;
+ const char *ret = NULL;
+ const char *nextbanstr;
+ Extban *extban = NULL;
static int extban_recursion = 0;
- if ((strlen(para)>3) && is_extended_ban(para+3))
- {
- /* We're dealing with a stacked extended ban.
- * Rules:
- * 1) You can only stack once, so: ~x:~y:something and not ~x:~y:~z...
- * 2) The first item must be an action modifier, such as ~q/~n/~j
- * 3) The second item may never be an action modifier, nor have the
- * EXTBOPT_NOSTACKCHILD flag set (for things like a textban).
- */
-
- /* Rule #1. Yes the recursion check is also in extban_is_ok_nuh_extban,
- * but it's possible to get here without the is_ok() function ever
- * being called (think: non-local client). And no, don't delete it
- * there either. It needs to be in BOTH places. -- Syzop
- */
- if (extban_recursion)
- return NULL;
+ if (!is_extended_ban(b->banstr))
+ return extban_conv_param_nuh(b, self_extban);
- /* Rule #2 */
- p = findmod_by_bantype(para[1]);
- if (p && !(p->options & EXTBOPT_ACTMODIFIER))
- {
- /* Rule #2 violation */
- return NULL;
- }
-
- strlcpy(tmpbuf, para, sizeof(tmpbuf));
- mask = tmpbuf + 3;
- /* Already did restrict-extended bans check. */
- p = findmod_by_bantype(mask[1]);
- if (!p)
- {
- /* Handling unknown bantypes in is_ok. Assume that it's ok here. */
- return para;
- }
- if ((p->options & EXTBOPT_ACTMODIFIER) || (p->options & EXTBOPT_NOSTACKCHILD))
- {
- /* Rule #3 violation */
- return NULL;
- }
-
- if (p->conv_param)
- {
- extban_recursion++;
- ret = p->conv_param(mask);
- extban_recursion--;
- if (ret)
- {
- /*
- * If bans are stacked, then we have to use two buffers
- * to prevent ircsnprintf() from going into a loop.
- */
- ircsnprintf(printbuf, sizeof(printbuf), "~%c:%s", bantype, ret); /* Make sure our extban prefix sticks. */
- memcpy(retbuf, printbuf, sizeof(retbuf));
- return retbuf;
- }
- else
- {
- return NULL; /* Fail. */
- }
- }
- /* I honestly don't know what the deal is with the 80 char cap in clean_ban_mask is about. So I'm leaving it out here. -- aquanight */
- /* I don't know why it's 80, but I like a limit anyway. A ban of 500 characters can never be good... -- Syzop */
- if (strlen(para) > 80)
- {
- strlcpy(retbuf, para, 128);
- return retbuf;
- }
- return para;
- }
- else
+ /* We're dealing with a stacked extended ban.
+ * Rules:
+ * 1) You can only stack once, so: ~x:~y:something and not ~x:~y:~z...
+ * 2) The second item may never be an action modifier, nor have the
+ * EXTBOPT_NOSTACKCHILD letter set (for things like a textban).
+ */
+
+ /* Rule #1. Yes the recursion check is also in extban_is_ok_nuh_extban,
+ * but it's possible to get here without the is_ok() function ever
+ * being called (think: non-local client). And no, don't delete it
+ * there either. It needs to be in BOTH places. -- Syzop
+ */
+ if (extban_recursion)
+ return NULL;
+
+ strlcpy(tmpbuf, b->banstr, sizeof(tmpbuf));
+ extban = findmod_by_bantype(tmpbuf, &nextbanstr);
+
+ if (!extban)
{
- return extban_conv_param_nuh(para);
+ /* Handling unknown bantypes in is_ok. Assume that it's ok here. */
+ return b->banstr;
}
+
+ b->banstr = nextbanstr;
+
+ if ((extban->options & EXTBOPT_ACTMODIFIER) || (extban->options & EXTBOPT_NOSTACKCHILD))
+ {
+ /* Rule #2 violation */
+ return NULL;
+ }
+
+ if (extban->conv_param)
+ {
+ //BanContext *b = safe_alloc(sizeof(BanContext));
+ //b->banstr = mask; <-- this is redundant right? we can use existing 'b' context??
+ extban_recursion++;
+ ret = extban->conv_param(b, extban);
+ extban_recursion--;
+ ret = prefix_with_extban(ret, b, extban, retbuf, sizeof(retbuf));
+ //safe_free(b);
+ return ret;
+ }
+ /* I honestly don't know what the deal is with the 80 char cap in clean_ban_mask is about. So I'm leaving it out here. -- aquanight */
+ /* I don't know why it's 80, but I like a limit anyway. A ban of 500 characters can never be good... -- Syzop */
+ if (strlen(b->banstr) > 80)
+ {
+ strlcpy(retbuf, b->banstr, 128);
+ return retbuf;
+ }
+ return b->banstr;
+}
+
+char *prefix_with_extban(const char *remainder, BanContext *b, Extban *extban, char *buf, size_t buflen)
+{
+ /* Yes, we support this because it makes code at the caller cleaner */
+ if (remainder == NULL)
+ return NULL;
+
+ if (iConf.named_extended_bans && !(b->conv_options & BCTX_CONV_OPTION_WRITE_LETTER_BANS))
+ snprintf(buf, buflen, "~%s:%s", extban->name, remainder);
+ else
+ snprintf(buf, buflen, "~%c:%s", extban->letter, remainder);
+
+ return buf;
}
diff --git a/src/api-history-backend.c b/src/api-history-backend.c
index 2c1668d..a569b55 100644
--- a/src/api-history-backend.c
+++ b/src/api-history-backend.c
@@ -60,13 +60,15 @@ HistoryBackend *HistoryBackendAdd(Module *module, HistoryBackendInfo *mreq)
{
HistoryBackend *m;
int exists = 0;
+ ModuleObject *mobj;
if (!mreq->history_add || !mreq->history_request ||
!mreq->history_destroy || !mreq->history_set_limit)
{
- if (module)
- module->errorcode = MODERR_INVALID;
- ircd_log(LOG_ERROR, "HistoryBackendAdd(): missing a handler for add/del/request/destroy/set_limit");
+ module->errorcode = MODERR_INVALID;
+ unreal_log(ULOG_ERROR, "module", "HISTORYBACKENDADD_API_ERROR", NULL,
+ "HistoryBackendAdd(): missing a handler for add/del/request/destroy/set_limit. Module: $module_name",
+ log_data_string("module_name", module->header->name));
return NULL;
}
m = HistoryBackendFind(mreq->name);
@@ -77,8 +79,7 @@ HistoryBackend *HistoryBackendAdd(Module *module, HistoryBackendInfo *mreq)
{
m->unloaded = 0;
} else {
- if (module)
- module->errorcode = MODERR_EXISTS;
+ module->errorcode = MODERR_EXISTS;
return NULL;
}
} else {
@@ -97,14 +98,11 @@ HistoryBackend *HistoryBackendAdd(Module *module, HistoryBackendInfo *mreq)
if (!exists)
AddListItem(m, historybackends);
- if (module)
- {
- ModuleObject *mobj = safe_alloc(sizeof(ModuleObject));
- mobj->type = MOBJ_HISTORY_BACKEND;
- mobj->object.history_backend = m;
- AddListItem(mobj, module->objects);
- module->errorcode = MODERR_NOERROR;
- }
+ mobj = safe_alloc(sizeof(ModuleObject));
+ mobj->type = MOBJ_HISTORY_BACKEND;
+ mobj->object.history_backend = m;
+ AddListItem(mobj, module->objects);
+ module->errorcode = MODERR_NOERROR;
return m;
}
@@ -138,7 +136,7 @@ void HistoryBackendDel(HistoryBackend *m)
m->owner = NULL;
}
- if (loop.ircd_rehashing)
+ if (loop.rehashing)
m->unloaded = 1;
else
unload_history_backend_commit(m);
@@ -156,7 +154,7 @@ void unload_all_unused_history_backends(void)
}
}
-int history_add(char *object, MessageTag *mtags, char *line)
+int history_add(const char *object, MessageTag *mtags, const char *line)
{
HistoryBackend *hb;
@@ -166,7 +164,7 @@ int history_add(char *object, MessageTag *mtags, char *line)
return 1;
}
-HistoryResult *history_request(char *object, HistoryFilter *filter)
+HistoryResult *history_request(const char *object, HistoryFilter *filter)
{
HistoryBackend *hb = historybackends;
HistoryResult *r;
@@ -183,7 +181,7 @@ HistoryResult *history_request(char *object, HistoryFilter *filter)
return NULL;
}
-int history_destroy(char *object)
+int history_destroy(const char *object)
{
HistoryBackend *hb;
@@ -193,7 +191,7 @@ int history_destroy(char *object)
return 1;
}
-int history_set_limit(char *object, int max_lines, long max_t)
+int history_set_limit(const char *object, int max_lines, long max_t)
{
HistoryBackend *hb;
@@ -230,7 +228,7 @@ int can_receive_history(Client *client)
return 0;
}
-static void history_send_result_line(Client *client, HistoryLogLine *l, char *batchid)
+static void history_send_result_line(Client *client, HistoryLogLine *l, const char *batchid)
{
if (BadPtr(batchid))
{
@@ -238,9 +236,10 @@ static void history_send_result_line(Client *client, HistoryLogLine *l, char *ba
} else {
MessageTag *m = safe_alloc(sizeof(MessageTag));
m->name = "batch";
- m->value = batchid;
+ m->value = strdup(batchid);
AddListItem(m, l->mtags);
sendto_one(client, l->mtags, "%s", l->line);
+ safe_free(m->value);
DelListItem(m, l->mtags);
safe_free(m);
}
diff --git a/src/api-isupport.c b/src/api-isupport.c
index a378e5b..29c0433 100644
--- a/src/api-isupport.c
+++ b/src/api-isupport.c
@@ -86,18 +86,12 @@ void isupport_init(void)
{
ISupportSet(NULL, "INVEX", NULL);
ISupportSet(NULL, "EXCEPTS", NULL);
-#ifdef PREFIX_AQ
- ISupportSet(NULL, "STATUSMSG", "~&@%+");
-#else
- ISupportSet(NULL, "STATUSMSG", "@%+");
-#endif
ISupportSet(NULL, "ELIST", "MNUCT");
ISupportSet(NULL, "CASEMAPPING", "ascii");
- ISupportSet(NULL, "NETWORK", ircnet005);
+ ISupportSet(NULL, "NETWORK", NETWORK_NAME_005);
ISupportSetFmt(NULL, "CHANMODES",
- CHPAR1 "%s," CHPAR2 "%s," CHPAR3 "%s," CHPAR4 "%s",
+ CHPAR1 "%s,%s,%s,%s",
EXPAR1, EXPAR2, EXPAR3, EXPAR4);
- ISupportSet(NULL, "PREFIX", CHPFIX);
ISupportSet(NULL, "CHANTYPES", "#");
ISupportSetFmt(NULL, "MODES", "%d", MAXMODEPARAMS);
ISupportSetFmt(NULL, "SILENCE", "%d", SILENCE_LIMIT);
@@ -118,7 +112,6 @@ void isupport_init(void)
ISupportSetFmt(NULL, "MAXLIST", "b:%d,e:%d,I:%d", MAXBANS, MAXBANS, MAXBANS);
ISupportSetFmt(NULL, "CHANLIMIT", "#:%d", MAXCHANNELSPERUSER);
ISupportSetFmt(NULL, "MAXCHANNELS", "%d", MAXCHANNELSPERUSER);
- ISupportSet(NULL, "HCN", NULL);
ISupportSet(NULL, "SAFELIST", NULL);
ISupportSet(NULL, "NAMESX", NULL);
if (UHNAMES_ENABLED)
diff --git a/src/api-messagetag.c b/src/api-messagetag.c
index 293848d..074f8fc 100644
--- a/src/api-messagetag.c
+++ b/src/api-messagetag.c
@@ -52,15 +52,21 @@ MessageTagHandler *MessageTagHandlerAdd(Module *module, MessageTagHandlerInfo *m
/* Some consistency checks to avoid a headache for module devs later on: */
if ((mreq->flags & MTAG_HANDLER_FLAGS_NO_CAP_NEEDED) && mreq->clicap_handler)
{
- ircd_log(LOG_ERROR, "MessageTagHandlerAdd(): .flags is set to MTAG_HANDLER_FLAGS_NO_CAP_NEEDED "
- "but a .clicap_handler is passed as well. These options are mutually "
- "exclusive, choose one or the other.");
+ unreal_log(ULOG_ERROR, "module", "MESSAGETAGHANDLERADD_API_ERROR", NULL,
+ "MessageTagHandlerAdd() from module $module_name: "
+ ".flags is set to MTAG_HANDLER_FLAGS_NO_CAP_NEEDED "
+ "but a .clicap_handler is passed as well. These options are mutually "
+ "exclusive, choose one or the other.",
+ log_data_string("module_name", module->header->name));
abort();
} else if (!(mreq->flags & MTAG_HANDLER_FLAGS_NO_CAP_NEEDED) && !mreq->clicap_handler)
{
- ircd_log(LOG_ERROR, "MessageTagHandlerAdd(): no .clicap_handler is passed. If the "
- "message tag really does not require a cap then you must "
- "set .flags to MTAG_HANDLER_FLAGS_NO_CAP_NEEDED");
+ unreal_log(ULOG_ERROR, "module", "MESSAGETAGHANDLERADD_API_ERROR", NULL,
+ "MessageTagHandlerAdd() from module $module_name: "
+ "no .clicap_handler is passed. If the "
+ "message tag really does not require a cap then you must "
+ "set .flags to MTAG_HANDLER_FLAGS_NO_CAP_NEEDED",
+ log_data_string("module_name", module->header->name));
abort();
}
@@ -85,7 +91,7 @@ MessageTagHandler *MessageTagHandlerAdd(Module *module, MessageTagHandlerInfo *m
m->owner = module;
m->flags = mreq->flags;
m->is_ok = mreq->is_ok;
- m->can_send = mreq->can_send;
+ m->should_send_to_client = mreq->should_send_to_client;
m->clicap_handler = mreq->clicap_handler;
/* Update reverse dependency (if any) */
@@ -141,7 +147,7 @@ void MessageTagHandlerDel(MessageTagHandler *m)
m->owner = NULL;
}
- if (loop.ircd_rehashing)
+ if (loop.rehashing)
m->unloaded = 1;
else
unload_mtag_handler_commit(m);
@@ -152,8 +158,9 @@ void MessageTagHandlerDel(MessageTagHandler *m)
static void unload_mtag_handler_commit(MessageTagHandler *m)
{
/* This is an unusual operation, I think we should log it. */
- ircd_log(LOG_ERROR, "Unloading message-tag handler for '%s'", m->name);
- sendto_realops("Unloading message-tag handler for '%s'", m->name);
+ unreal_log(ULOG_INFO, "module", "UNLOAD_MESSAGE_TAG", NULL,
+ "Unloading message-tag handler for '$token'",
+ log_data_string("token", m->name));
/* Remove reverse dependency, if any */
if (m->clicap_handler)
diff --git a/src/api-moddata.c b/src/api-moddata.c
index 84be03b..1dd5035 100644
--- a/src/api-moddata.c
+++ b/src/api-moddata.c
@@ -65,6 +65,8 @@ ModDataInfo *ModDataAdd(Module *module, ModDataInfo req)
((req.type == MODDATATYPE_MEMBER) && (slotav >= MODDATA_MAX_MEMBER)) ||
((req.type == MODDATATYPE_MEMBERSHIP) && (slotav >= MODDATA_MAX_MEMBERSHIP)))
{
+ unreal_log(ULOG_ERROR, "module", "MOD_DATA_OUT_OF_SPACE", NULL,
+ "ModDataAdd: out of space!!!");
if (module)
module->errorcode = MODERR_NOSPACE;
return NULL;
@@ -80,6 +82,8 @@ moddataadd_isok:
m->serialize = req.serialize;
m->unserialize = req.unserialize;
m->sync = req.sync;
+ m->remote_write = req.remote_write;
+ m->self_write = req.self_write;
m->owner = module;
if (new_struct)
@@ -272,7 +276,7 @@ void ModDataDel(ModDataInfo *md)
md->owner = NULL;
}
- if (loop.ircd_rehashing)
+ if (loop.rehashing)
md->unloaded = 1;
else
unload_moddata_commit(md);
@@ -290,7 +294,7 @@ ModDataInfo *md, *md_next;
}
}
-ModDataInfo *findmoddata_byname(char *name, ModDataType type)
+ModDataInfo *findmoddata_byname(const char *name, ModDataType type)
{
ModDataInfo *md;
@@ -313,7 +317,7 @@ int module_has_moddata(Module *mod)
}
/** Set ModData for client (via variable name, string value) */
-int moddata_client_set(Client *client, char *varname, char *value)
+int moddata_client_set(Client *client, const char *varname, const char *value)
{
ModDataInfo *md;
@@ -344,7 +348,7 @@ int moddata_client_set(Client *client, char *varname, char *value)
}
/** Get ModData for client (via variable name) */
-char *moddata_client_get(Client *client, char *varname)
+const char *moddata_client_get(Client *client, const char *varname)
{
ModDataInfo *md;
@@ -356,8 +360,21 @@ char *moddata_client_get(Client *client, char *varname)
return md->serialize(&moddata_client(client, md)); /* can be NULL */
}
+/** Get ModData for client (via variable name) */
+ModData *moddata_client_get_raw(Client *client, const char *varname)
+{
+ ModDataInfo *md;
+
+ md = findmoddata_byname(varname, MODDATATYPE_CLIENT);
+
+ if (!md)
+ return NULL;
+
+ return &moddata_client(client, md); /* can be NULL */
+}
+
/** Set ModData for LocalClient (via variable name, string value) */
-int moddata_local_client_set(Client *client, char *varname, char *value)
+int moddata_local_client_set(Client *client, const char *varname, const char *value)
{
ModDataInfo *md;
@@ -391,7 +408,7 @@ int moddata_local_client_set(Client *client, char *varname, char *value)
}
/** Get ModData for LocalClient (via variable name) */
-char *moddata_local_client_get(Client *client, char *varname)
+const char *moddata_local_client_get(Client *client, const char *varname)
{
ModDataInfo *md;
@@ -407,7 +424,7 @@ char *moddata_local_client_get(Client *client, char *varname)
}
/** Set local variable moddata (via variable name, string value) */
-int moddata_local_variable_set(char *varname, char *value)
+int moddata_local_variable_set(const char *varname, const char *value)
{
ModDataInfo *md;
@@ -432,7 +449,7 @@ int moddata_local_variable_set(char *varname, char *value)
}
/** Set global variable moddata (via variable name, string value) */
-int moddata_global_variable_set(char *varname, char *value)
+int moddata_global_variable_set(const char *varname, const char *value)
{
ModDataInfo *md;
diff --git a/src/api-usermode.c b/src/api-usermode.c
index b195c4f..0789840 100644
--- a/src/api-usermode.c
+++ b/src/api-usermode.c
@@ -24,16 +24,11 @@
char umodestring[UMODETABLESZ+1];
-Umode *Usermode_Table = NULL;
-short Usermode_highest = 0;
+/** User modes and their handlers */
+Umode *usermodes = NULL;
-Snomask *Snomask_Table = NULL;
-short Snomask_highest = 0;
-
-/* client->umodes (32 bits): 26 used, 6 free */
long UMODE_INVISIBLE = 0L; /* makes user invisible */
long UMODE_OPER = 0L; /* Operator */
-long UMODE_WALLOP = 0L; /* send wallops to them */
long UMODE_REGNICK = 0L; /* Nick set by services as registered */
long UMODE_SERVNOTICE = 0L; /* server notices such as kill */
long UMODE_HIDE = 0L; /* Hide from Nukes */
@@ -63,32 +58,13 @@ long SendUmodes; /* All umodes which are sent to other servers (global umodes) *
/* Forward declarations */
int umode_hidle_allow(Client *client, int what);
+static void unload_usermode_commit(Umode *m);
-void umode_init(void)
+void umode_init(void)
{
- long val = 1;
- int i;
- Usermode_Table = safe_alloc(sizeof(Umode) * UMODETABLESZ);
- for (i = 0; i < UMODETABLESZ; i++)
- {
- Usermode_Table[i].mode = val;
- val *= 2;
- }
- Usermode_highest = 0;
-
- Snomask_Table = safe_alloc(sizeof(Snomask) * UMODETABLESZ);
- val = 1;
- for (i = 0; i < UMODETABLESZ; i++)
- {
- Snomask_Table[i].mode = val;
- val *= 2;
- }
- Snomask_highest = 0;
-
- /* Set up modes */
+ /* Some built-in modes */
UmodeAdd(NULL, 'i', UMODE_GLOBAL, 0, umode_allow_all, &UMODE_INVISIBLE);
UmodeAdd(NULL, 'o', UMODE_GLOBAL, 1, umode_allow_opers, &UMODE_OPER);
- UmodeAdd(NULL, 'w', UMODE_GLOBAL, 0, umode_allow_all, &UMODE_WALLOP);
UmodeAdd(NULL, 'r', UMODE_GLOBAL, 0, umode_allow_none, &UMODE_REGNICK);
UmodeAdd(NULL, 's', UMODE_LOCAL, 0, umode_allow_all, &UMODE_SERVNOTICE);
UmodeAdd(NULL, 'x', UMODE_GLOBAL, 0, umode_allow_all, &UMODE_HIDE);
@@ -97,34 +73,17 @@ void umode_init(void)
UmodeAdd(NULL, 'H', UMODE_GLOBAL, 1, umode_allow_opers, &UMODE_HIDEOPER);
UmodeAdd(NULL, 't', UMODE_GLOBAL, 0, umode_allow_unset, &UMODE_SETHOST);
UmodeAdd(NULL, 'I', UMODE_GLOBAL, 0, umode_hidle_allow, &UMODE_HIDLE);
- SnomaskAdd(NULL, 'k', umode_allow_opers, &SNO_KILLS);
- SnomaskAdd(NULL, 'c', umode_allow_opers, &SNO_CLIENT);
- SnomaskAdd(NULL, 'f', umode_allow_opers, &SNO_FLOOD);
- SnomaskAdd(NULL, 'F', umode_allow_opers, &SNO_FCLIENT);
- SnomaskAdd(NULL, 'j', umode_allow_opers, &SNO_JUNK);
- SnomaskAdd(NULL, 'v', umode_allow_opers, &SNO_VHOST);
- SnomaskAdd(NULL, 'e', umode_allow_opers, &SNO_EYES);
- SnomaskAdd(NULL, 'G', umode_allow_opers, &SNO_TKL);
- SnomaskAdd(NULL, 'n', umode_allow_opers, &SNO_NICKCHANGE);
- SnomaskAdd(NULL, 'N', umode_allow_opers, &SNO_FNICKCHANGE);
- SnomaskAdd(NULL, 'q', umode_allow_opers, &SNO_QLINE);
- SnomaskAdd(NULL, 'S', umode_allow_opers, &SNO_SPAMF);
- SnomaskAdd(NULL, 's', umode_allow_opers, &SNO_SNOTICE);
- SnomaskAdd(NULL, 'o', umode_allow_opers, &SNO_OPER);
}
void make_umodestr(void)
{
- int i;
- char *m;
+ Umode *um;
+ char *p = umodestring;
- m = umodestring;
- for (i = 0; i <= Usermode_highest; i++)
- {
- if (Usermode_Table[i].flag)
- *m++ = Usermode_Table[i].flag;
- }
- *m = '\0';
+ for (um=usermodes; um; um = um->next)
+ if (um->letter)
+ *p++ = um->letter;
+ *p = '\0';
}
static char previous_umodestring[256];
@@ -132,7 +91,7 @@ static char previous_umodestring[256];
void umodes_check_for_changes(void)
{
make_umodestr();
- safe_strdup(me.serv->features.usermodes, umodestring);
+ safe_strdup(me.server->features.usermodes, umodestring);
if (!*previous_umodestring)
{
@@ -142,10 +101,10 @@ void umodes_check_for_changes(void)
if (*previous_umodestring && strcmp(umodestring, previous_umodestring))
{
- ircd_log(LOG_ERROR, "User modes changed at runtime: %s -> %s",
- previous_umodestring, umodestring);
- sendto_realops("User modes changed at runtime: %s -> %s",
- previous_umodestring, umodestring);
+ unreal_log(ULOG_INFO, "mode", "USER_MODES_CHANGED", NULL,
+ "User modes changed at runtime: $old_user_modes -> $new_user_modes",
+ log_data_string("old_user_modes", previous_umodestring),
+ log_data_string("new_user_modes", umodestring));
/* Broadcast change to all (locally connected) servers */
sendto_server(NULL, 0, 0, NULL, "PROTOCTL USERMODES=%s", umodestring);
}
@@ -153,102 +112,134 @@ void umodes_check_for_changes(void)
strlcpy(previous_umodestring, umodestring, sizeof(previous_umodestring));
}
+void usermode_add_sorted(Umode *n)
+{
+ Umode *m;
+
+ if (usermodes == NULL)
+ {
+ usermodes = n;
+ return;
+ }
+
+ for (m = usermodes; m; m = m->next)
+ {
+ if (m->letter == '\0')
+ abort();
+ if (sort_character_lowercase_before_uppercase(n->letter, m->letter))
+ {
+ /* Insert us before */
+ if (m->prev)
+ m->prev->next = n;
+ else
+ usermodes = n; /* new head */
+ n->prev = m->prev;
+
+ n->next = m;
+ m->prev = n;
+ return;
+ }
+ if (!m->next)
+ {
+ /* Append us at end */
+ m->next = n;
+ n->prev = m;
+ return;
+ }
+ }
+}
+
+
/* UmodeAdd:
* Add a usermode with character 'ch', if global is set to 1 the usermode is global
* (sent to other servers) otherwise it's a local usermode
*/
Umode *UmodeAdd(Module *module, char ch, int global, int unset_on_deoper, int (*allowed)(Client *client, int what), long *mode)
{
- short i = 0;
- short j = 0;
- short save = -1;
- while (i < UMODETABLESZ)
+ Umode *um;
+ int existing = 0;
+
+ for (um=usermodes; um; um = um->next)
{
- if (!Usermode_Table[i].flag && save == -1)
- save = i;
- else if (Usermode_Table[i].flag == ch)
+ if (um->letter == ch)
{
- if (Usermode_Table[i].unloaded)
+ if (um->unloaded)
{
- save = i;
- Usermode_Table[i].unloaded = 0;
+ um->unloaded = 0;
+ existing = 1;
break;
- }
- else
- {
+ } else {
if (module)
module->errorcode = MODERR_EXISTS;
return NULL;
}
}
- i++;
}
- i = save;
- if (i != UMODETABLESZ)
+
+ if (!um)
{
- Usermode_Table[i].flag = ch;
- Usermode_Table[i].allowed = allowed;
- Usermode_Table[i].unset_on_deoper = unset_on_deoper;
- Debug((DEBUG_DEBUG, "UmodeAdd(%c) returning %04lx",
- ch, Usermode_Table[i].mode));
- /* Update usermode table highest */
- for (j = 0; j < UMODETABLESZ; j++)
- if (Usermode_Table[i].flag)
- if (i > Usermode_highest)
- Usermode_highest = i;
- make_umodestr();
- AllUmodes |= Usermode_Table[i].mode;
- if (global)
- SendUmodes |= Usermode_Table[i].mode;
- *mode = Usermode_Table[i].mode;
- Usermode_Table[i].owner = module;
- if (module)
+ /* Not found, create */
+ long l, found = 0;
+ for (l = 1; l < LONG_MAX/2; l *= 2)
{
- ModuleObject *umodeobj = safe_alloc(sizeof(ModuleObject));
- umodeobj->object.umode = &(Usermode_Table[i]);
- umodeobj->type = MOBJ_UMODE;
- AddListItem(umodeobj, module->objects);
- module->errorcode = MODERR_NOERROR;
+ found = 0;
+ for (um=usermodes; um; um = um->next)
+ {
+ if (um->mode == l)
+ {
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ break;
}
- return &(Usermode_Table[i]);
+ /* If 'found' is still true, then we are out of space */
+ if (found)
+ {
+ unreal_log(ULOG_ERROR, "module", "USER_MODE_OUT_OF_SPACE", NULL,
+ "UmodeAdd: out of space!!!");
+ if (module)
+ module->errorcode = MODERR_NOSPACE;
+ return NULL;
+ }
+ um = safe_alloc(sizeof(Umode));
+ um->letter = ch;
+ um->mode = l;
+ usermode_add_sorted(um);
}
- else
+
+ um->letter = ch;
+ um->allowed = allowed;
+ um->unset_on_deoper = unset_on_deoper;
+ make_umodestr();
+ AllUmodes |= um->mode;
+ if (global)
+ SendUmodes |= um->mode;
+ *mode = um->mode;
+ um->owner = module;
+ if (module)
{
- Debug((DEBUG_DEBUG, "UmodeAdd failed, no space"));
- if (module)
- module->errorcode = MODERR_NOSPACE;
- return NULL;
+ ModuleObject *umodeobj = safe_alloc(sizeof(ModuleObject));
+ umodeobj->object.umode = um;
+ umodeobj->type = MOBJ_UMODE;
+ AddListItem(umodeobj, module->objects);
+ module->errorcode = MODERR_NOERROR;
}
+ return um;
}
void UmodeDel(Umode *umode)
{
- if (loop.ircd_rehashing)
- umode->unloaded = 1;
- else
+ /* Always free the module object */
+ if (umode->owner)
{
- Client *client;
- list_for_each_entry(client, &client_list, client_node)
- {
- long oldumode = 0;
- if (!IsUser(client))
- continue;
- oldumode = client->umodes;
- client->umodes &= ~umode->mode;
- if (MyUser(client))
- send_umode_out(client, 1, oldumode);
- }
- umode->flag = '\0';
- AllUmodes &= ~(umode->mode);
- SendUmodes &= ~(umode->mode);
- make_umodestr();
- }
-
- if (umode->owner) {
ModuleObject *umodeobj;
- for (umodeobj = umode->owner->objects; umodeobj; umodeobj = umodeobj->next) {
- if (umodeobj->type == MOBJ_UMODE && umodeobj->object.umode == umode) {
+ for (umodeobj = umode->owner->objects; umodeobj; umodeobj = umodeobj->next)
+ {
+ if (umodeobj->type == MOBJ_UMODE && umodeobj->object.umode == umode)
+ {
DelListItem(umodeobj, umode->owner->objects);
safe_free(umodeobj);
break;
@@ -256,100 +247,13 @@ void UmodeDel(Umode *umode)
}
umode->owner = NULL;
}
- return;
-}
-Snomask *SnomaskAdd(Module *module, char ch, int (*allowed)(Client *client, int what), long *mode)
-{
- short i = 0;
- short j = 0;
- short save = -1;
- while (i < UMODETABLESZ)
- {
- if (!Snomask_Table[i].flag && save == -1)
- save = i;
- else if (Snomask_Table[i].flag == ch)
- {
- if (Snomask_Table[i].unloaded)
- {
- save = i;
- Snomask_Table[i].unloaded = 0;
- break;
- }
- else
- {
- if (module)
- module->errorcode = MODERR_EXISTS;
- return NULL;
- }
- }
- i++;
- }
- i = save;
- if (i != UMODETABLESZ)
- {
- Snomask_Table[i].flag = ch;
- Snomask_Table[i].allowed = allowed;
- /* Update usermode table highest */
- for (j = 0; j < UMODETABLESZ; j++)
- if (Snomask_Table[i].flag)
- if (i > Snomask_highest)
- Snomask_highest = i;
- *mode = Snomask_Table[i].mode;
- Snomask_Table[i].owner = module;
- if (module)
- {
- ModuleObject *snoobj = safe_alloc(sizeof(ModuleObject));
- snoobj->object.snomask = &(Snomask_Table[i]);
- snoobj->type = MOBJ_SNOMASK;
- AddListItem(snoobj, module->objects);
- module->errorcode = MODERR_NOERROR;
- }
- return &(Snomask_Table[i]);
- }
+ /* Whether we can actually (already) free the Umode depends... */
+
+ if (loop.rehashing)
+ umode->unloaded = 1;
else
- {
- Debug((DEBUG_DEBUG, "SnomaskAdd failed, no space"));
- *mode = 0;
- if (module)
- module->errorcode = MODERR_NOSPACE;
- return NULL;
- }
-}
-
-void SnomaskDel(Snomask *sno)
-{
- if (loop.ircd_rehashing)
- sno->unloaded = 1;
- else
- {
- Client *client;
-
- list_for_each_entry(client, &lclient_list, lclient_node)
- {
- long oldsno;
- if (!client || !IsUser(client))
- continue;
- oldsno = client->user->snomask;
- client->user->snomask &= ~sno->mode;
- if (oldsno != client->user->snomask)
- sendnumeric(client, RPL_SNOMASK, get_snomask_string_raw(client->user->snomask));
- }
-
- sno->flag = '\0';
- }
- if (sno->owner) {
- ModuleObject *snoobj;
- for (snoobj = sno->owner->objects; snoobj; snoobj = snoobj->next) {
- if (snoobj->type == MOBJ_SNOMASK && snoobj->object.snomask == sno) {
- DelListItem(snoobj, sno->owner->objects);
- safe_free(snoobj);
- break;
- }
- }
- sno->owner = NULL;
- }
- return;
+ unload_usermode_commit(umode);
}
int umode_allow_all(Client *client, int what)
@@ -392,68 +296,42 @@ int umode_hidle_allow(Client *client, int what)
return 0; /* if set::hide-idle-time is 'never' or 'always' then +I makes no sense */
}
-void unload_all_unused_umodes(void)
+static void unload_usermode_commit(Umode *um)
{
- long removed_umode = 0;
- int i;
Client *client;
- for (i = 0; i < UMODETABLESZ; i++)
- {
- if (Usermode_Table[i].unloaded)
- removed_umode |= Usermode_Table[i].mode;
- }
- if (!removed_umode) /* Nothing was unloaded */
+ long removed_umode;
+
+ if (!um)
return;
+
+ removed_umode = um->mode;
+
+ /* First send the -mode regarding all users */
list_for_each_entry(client, &lclient_list, lclient_node)
{
- long oldumode = 0;
- if (!IsUser(client))
- continue;
- oldumode = client->umodes;
- client->umodes &= ~(removed_umode);
- if (MyUser(client))
- send_umode_out(client, 1, oldumode);
- }
- for (i = 0; i < UMODETABLESZ; i++)
- {
- if (Usermode_Table[i].unloaded)
+ if (MyUser(client) && (client->umodes & removed_umode))
{
- AllUmodes &= ~(Usermode_Table[i].mode);
- SendUmodes &= ~(Usermode_Table[i].mode);
- Usermode_Table[i].flag = '\0';
- Usermode_Table[i].unloaded = 0;
+ long oldumode = client->umodes;
+ client->umodes &= ~(removed_umode);
+ send_umode_out(client, 1, oldumode);
}
}
+
+ /* Then unload the mode */
+ DelListItem(um, usermodes);
+ safe_free(um);
make_umodestr();
}
-void unload_all_unused_snomasks(void)
+void unload_all_unused_umodes(void)
{
- Client *client;
- long removed_sno = 0;
- int i;
+ Umode *um, *um_next;
- for (i = 0; i < UMODETABLESZ; i++)
+ for (um=usermodes; um; um = um_next)
{
- if (Snomask_Table[i].unloaded)
- {
- removed_sno |= Snomask_Table[i].mode;
- Snomask_Table[i].flag = '\0';
- Snomask_Table[i].unloaded = 0;
- }
- }
- if (!removed_sno) /* Nothing was unloaded */
- return;
-
- list_for_each_entry(client, &lclient_list, lclient_node)
- {
- long oldsno;
- if (!client || !IsUser(client))
- continue;
- oldsno = client->user->snomask;
- client->user->snomask &= ~(removed_sno);
- if (oldsno != client->user->snomask)
- sendnumeric(client, RPL_SNOMASK, get_snomask_string_raw(client->user->snomask));
+ um_next = um->next;
+ if (um->letter && um->unloaded)
+ unload_usermode_commit(um);
}
}
@@ -463,25 +341,24 @@ void unload_all_unused_snomasks(void)
* This used to be a bit more complex but nowadays we just erase all
* snomasks since all of them are IRCOp-only. Easy.
*/
-void remove_oper_snomasks(Client *client)
+void remove_all_snomasks(Client *client)
{
- client->user->snomask = 0;
+ safe_free(client->user->snomask);
+ client->umodes &= ~UMODE_SERVNOTICE;
}
/*
* This function removes any oper-only user modes from the user.
- * You may also want to call remove_oper_snomasks(), see above.
+ * You may also want to call remove_all_snomasks(), see above.
*/
void remove_oper_modes(Client *client)
{
-int i;
+ Umode *um;
- for (i = 0; i <= Usermode_highest; i++)
+ for (um = usermodes; um; um = um->next)
{
- if (!Usermode_Table[i].flag)
- continue;
- if (Usermode_Table[i].unset_on_deoper)
- client->umodes &= ~Usermode_Table[i].mode;
+ if (um->unset_on_deoper)
+ client->umodes &= ~um->mode;
}
/* Bit of a hack, since this is a dynamic permission umode */
@@ -493,7 +370,7 @@ void remove_oper_privileges(Client *client, int broadcast_mode_change)
{
long oldumodes = client->umodes;
remove_oper_modes(client);
- remove_oper_snomasks(client);
+ remove_all_snomasks(client);
if (broadcast_mode_change && (client->umodes != oldumodes))
send_umode_out(client, 1, oldumodes);
if (MyUser(client)) /* only do if it's our client, remote servers will send a SWHOIS cmd */
@@ -501,15 +378,14 @@ void remove_oper_privileges(Client *client, int broadcast_mode_change)
}
/** Return long integer mode for a user mode character (eg: 'x' -> 0x10) */
-long find_user_mode(char flag)
+long find_user_mode(char letter)
{
- int i;
+ Umode *um;
+
+ for (um = usermodes; um; um = um->next)
+ if ((um->letter == letter) && !um->unloaded)
+ return um->mode;
- for (i = 0; i < UMODETABLESZ; i++)
- {
- if ((Usermode_Table[i].flag == flag) && !(Usermode_Table[i].unloaded))
- return Usermode_Table[i].mode;
- }
return 0;
}
diff --git a/src/auth.c b/src/auth.c
index 39403a5..4cf28e0 100644
--- a/src/auth.c
+++ b/src/auth.c
@@ -46,10 +46,10 @@ AuthTypeList MODVAR AuthTypeLists[] = {
};
/* Helper function for Auth_AutoDetectHashType() */
-static int parsepass(char *str, char **salt, char **hash)
+static int parsepass(const char *str, char **salt, char **hash)
{
static char saltbuf[512], hashbuf[512];
- char *p;
+ const char *p;
int max;
/* Syntax: $$ */
@@ -72,7 +72,7 @@ static int parsepass(char *str, char **salt, char **hash)
/** Auto detect hash type for input hash 'hash'.
* Will fallback to AUTHTYPE_PLAINTEXT when not found (or invalid).
*/
-int Auth_AutoDetectHashType(char *hash)
+int Auth_AutoDetectHashType(const char *hash)
{
static char hashbuf[256];
char *saltstr, *hashstr;
@@ -80,12 +80,12 @@ int Auth_AutoDetectHashType(char *hash)
if (!strchr(hash, '$'))
{
- /* SHA256 SSL fingerprint perhaps?
+ /* SHA256 certificate fingerprint perhaps?
* These are exactly 64 bytes (00112233..etc..) or 95 bytes (00:11:22:33:etc) in size.
*/
if ((strlen(hash) == 64) || (strlen(hash) == 95))
{
- char *p;
+ const char *p;
char *hexchars = "0123456789abcdefABCDEF";
for (p = hash; *p; p++)
if ((*p != ':') && !strchr(hexchars, *p))
@@ -96,7 +96,7 @@ int Auth_AutoDetectHashType(char *hash)
if (strlen(hash) == 44)
{
- char *p;
+ const char *p;
char *b64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
for (p = hash; *p; p++)
if (!strchr(b64chars, *p))
@@ -134,7 +134,7 @@ int Auth_AutoDetectHashType(char *hash)
* than trying to determine the type on the 'hash' parameter.
* Or leave NULL, then we use hash autodetection.
*/
-AuthenticationType Auth_FindType(char *hash, char *type)
+AuthenticationType Auth_FindType(const char *hash, const char *type)
{
if (type)
{
@@ -163,25 +163,25 @@ int Auth_CheckError(ConfigEntry *ce)
AuthenticationType type = AUTHTYPE_PLAINTEXT;
X509 *x509_filecert = NULL;
FILE *x509_f = NULL;
- if (!ce->ce_vardata)
+ if (!ce->value)
{
config_error("%s:%i: authentication module failure: missing parameter",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
return -1;
}
- if (ce->ce_entries && ce->ce_entries->ce_next)
+ if (ce->items && ce->items->next)
{
config_error("%s:%i: you may not have multiple authentication methods",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
return -1;
}
- type = Auth_FindType(ce->ce_vardata, ce->ce_entries ? ce->ce_entries->ce_varname : NULL);
+ type = Auth_FindType(ce->value, ce->items ? ce->items->name : NULL);
if (type == -1)
{
config_error("%s:%i: authentication module failure: %s is not an implemented/enabled authentication method",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- ce->ce_entries->ce_varname);
+ ce->file->filename, ce->line_number,
+ ce->items->name);
return -1;
}
@@ -189,19 +189,19 @@ int Auth_CheckError(ConfigEntry *ce)
{
case AUTHTYPE_UNIXCRYPT:
/* If our data is like 1 or none, we just let em through .. */
- if (strlen(ce->ce_vardata) < 2)
+ if (strlen(ce->value) < 2)
{
config_error("%s:%i: authentication module failure: AUTHTYPE_UNIXCRYPT: no salt (crypt strings will always be >2 in length)",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
return -1;
}
break;
case AUTHTYPE_TLS_CLIENTCERT:
- convert_to_absolute_path(&ce->ce_vardata, CONFDIR);
- if (!(x509_f = fopen(ce->ce_vardata, "r")))
+ convert_to_absolute_path(&ce->value, CONFDIR);
+ if (!(x509_f = fopen(ce->value, "r")))
{
config_error("%s:%i: authentication module failure: AUTHTYPE_TLS_CLIENTCERT: error opening file %s: %s",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_vardata, strerror(errno));
+ ce->file->filename, ce->line_number, ce->value, strerror(errno));
return -1;
}
x509_filecert = PEM_read_X509(x509_f, NULL, NULL, NULL);
@@ -209,7 +209,7 @@ int Auth_CheckError(ConfigEntry *ce)
if (!x509_filecert)
{
config_error("%s:%i: authentication module failure: AUTHTYPE_TLS_CLIENTCERT: PEM_read_X509 errored in file %s (format error?)",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_vardata);
+ ce->file->filename, ce->line_number, ce->value);
return -1;
}
X509_free(x509_filecert);
@@ -226,19 +226,19 @@ int Auth_CheckError(ConfigEntry *ce)
* with normally at least 5000 rounds (unless deliberately weakened
* by the user).
*/
- if ((type == AUTHTYPE_UNIXCRYPT) && strncmp(ce->ce_vardata, "$5", 2) &&
- strncmp(ce->ce_vardata, "$6", 2) && !strstr(ce->ce_vardata, "$rounds"))
+ if ((type == AUTHTYPE_UNIXCRYPT) && strncmp(ce->value, "$5", 2) &&
+ strncmp(ce->value, "$6", 2) && !strstr(ce->value, "$rounds"))
{
config_warn("%s:%i: Using simple crypt for authentication is not recommended. "
"Consider using the more secure auth-type 'argon2' instead. "
"See https://www.unrealircd.org/docs/Authentication_types for the complete list.",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
/* do not return, not an error. */
}
- if ((type == AUTHTYPE_PLAINTEXT) && (strlen(ce->ce_vardata) > PASSWDLEN))
+ if ((type == AUTHTYPE_PLAINTEXT) && (strlen(ce->value) > PASSWDLEN))
{
config_error("%s:%i: passwords length may not exceed %d",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum, PASSWDLEN);
+ ce->file->filename, ce->line_number, PASSWDLEN);
return -1;
}
return 1;
@@ -252,12 +252,12 @@ AuthConfig *AuthBlockToAuthConfig(ConfigEntry *ce)
AuthenticationType type = AUTHTYPE_PLAINTEXT;
AuthConfig *as = NULL;
- type = Auth_FindType(ce->ce_vardata, ce->ce_entries ? ce->ce_entries->ce_varname : NULL);
+ type = Auth_FindType(ce->value, ce->items ? ce->items->name : NULL);
if (type == AUTHTYPE_INVALID)
type = AUTHTYPE_PLAINTEXT;
as = safe_alloc(sizeof(AuthConfig));
- safe_strdup(as->data, ce->ce_vardata);
+ safe_strdup(as->data, ce->value);
as->type = type;
return as;
}
@@ -279,7 +279,7 @@ void Auth_FreeAuthConfig(AuthConfig *as)
#define RAWSALTLEN 6
#define REALSALTLEN 12
-static int authcheck_argon2(Client *client, AuthConfig *as, char *para)
+static int authcheck_argon2(Client *client, AuthConfig *as, const char *para)
{
argon2_type hashtype;
@@ -304,7 +304,7 @@ static int authcheck_argon2(Client *client, AuthConfig *as, char *para)
return 0; /* NO MATCH or error */
}
-static int authcheck_bcrypt(Client *client, AuthConfig *as, char *para)
+static int authcheck_bcrypt(Client *client, AuthConfig *as, const char *para)
{
char data[512]; /* NOTE: only 64 required by BF_crypt() */
char *str;
@@ -324,7 +324,7 @@ static int authcheck_bcrypt(Client *client, AuthConfig *as, char *para)
return 0; /* NO MATCH */
}
-static int authcheck_tls_clientcert(Client *client, AuthConfig *as, char *para)
+static int authcheck_tls_clientcert(Client *client, AuthConfig *as, const char *para)
{
X509 *x509_clientcert = NULL;
X509 *x509_filecert = NULL;
@@ -358,11 +358,11 @@ static int authcheck_tls_clientcert(Client *client, AuthConfig *as, char *para)
return 1;
}
-static int authcheck_tls_clientcert_fingerprint(Client *client, AuthConfig *as, char *para)
+static int authcheck_tls_clientcert_fingerprint(Client *client, AuthConfig *as, const char *para)
{
int i, k;
char hexcolon[EVP_MAX_MD_SIZE * 3 + 1];
- char *fp;
+ const char *fp;
if (!client->local->ssl)
return 0;
@@ -389,12 +389,12 @@ static int authcheck_tls_clientcert_fingerprint(Client *client, AuthConfig *as,
return 1;
}
-static int authcheck_spkifp(Client *client, AuthConfig *as, char *para)
+static int authcheck_spkifp(Client *client, AuthConfig *as, const char *para)
{
- char *fp = spki_fingerprint(client);
+ const char *fp = spki_fingerprint(client);
if (!fp)
- return 0; /* auth failed: not SSL (or other failure) */
+ return 0; /* auth failed: not TLS or some other failure */
if (strcasecmp(as->data, fp))
return 0; /* auth failed: mismatch */
@@ -420,7 +420,7 @@ static int authcheck_spkifp(Client *client, AuthConfig *as, char *para)
* - The return value was different in versions before UnrealIRCd 5.0.0!
* - In older versions a NULL 'as' was treated as an allow, now it's deny.
*/
-int Auth_Check(Client *client, AuthConfig *as, char *para)
+int Auth_Check(Client *client, AuthConfig *as, const char *para)
{
extern char *crypt();
char *res;
@@ -435,8 +435,9 @@ int Auth_Check(Client *client, AuthConfig *as, char *para)
return 0;
if (!strcmp(as->data, "changemeplease") && !strcmp(para, as->data))
{
- sendto_realops("Rejecting default password 'changemeplease'. "
- "Please change the password in the configuration file.");
+ unreal_log(ULOG_INFO, "auth", "AUTH_REJECT_DEFAULT_PASSWORD", client,
+ "Rejecting default password 'changemeplease'. "
+ "Please change the password in the configuration file.");
return 0;
}
/* plain text compare */
@@ -479,7 +480,7 @@ int Auth_Check(Client *client, AuthConfig *as, char *para)
#define UNREALIRCD_ARGON2_DEFAULT_HASH_LENGTH 32
#define UNREALIRCD_ARGON2_DEFAULT_SALT_LENGTH (128/8)
-static char *mkpass_argon2(char *para)
+static char *mkpass_argon2(const char *para)
{
static char buf[512];
char salt[UNREALIRCD_ARGON2_DEFAULT_SALT_LENGTH];
@@ -511,7 +512,7 @@ static char *mkpass_argon2(char *para)
return buf;
}
-static char *mkpass_bcrypt(char *para)
+static char *mkpass_bcrypt(const char *para)
{
static char buf[128];
char data[512]; /* NOTE: only 64 required by BF_crypt() */
@@ -547,7 +548,7 @@ static char *mkpass_bcrypt(char *para)
* @param text The password in plaintext.
* @returns The hashed password.
*/
-char *Auth_Hash(AuthenticationType type, char *text)
+const char *Auth_Hash(AuthenticationType type, const char *text)
{
switch (type)
{
diff --git a/src/buildmod b/src/buildmod
index 6fdfe22..da21717 100755
--- a/src/buildmod
+++ b/src/buildmod
@@ -1,4 +1,5 @@
#!/bin/sh
+MAKE="$1"
echo ""
echo "Checking for updates for third party modules..."
# We can't use the "unrealircd" script, since possibly the ircd
@@ -13,7 +14,7 @@ if [ "$x" != "*.c" ]; then
x="`echo $x|sed 's/\.c//'`"
if [ ! -f $x.so -o $x.c -nt $x.so ]; then
echo "Building 3rd party module $x..."
- make custommodule MODULEFILE=$x || (echo "*****"; echo "Building 3rd party module $x failed."; echo "Contact the module author of the $x module (not the UnrealIRCd team), or simply delete the $PWD/$x.c file"; echo "*****"; exit 1)
+ $MAKE custommodule MODULEFILE=$x || (echo "*****"; echo "Building 3rd party module $x failed."; echo "Contact the module author of the $x module (not the UnrealIRCd team), or simply delete the $PWD/$x.c file"; echo "*****"; exit 1)
fi
fi
done
diff --git a/src/channel.c b/src/channel.c
index a15fddf..a465f20 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -40,31 +40,15 @@ long sajoinmode = 0;
*/
Channel *channels = NULL;
-/* some buffers for rebuilding channel/nick lists with comma's */
+/* A buffer for rebuilding channel/nick lists with comma's */
static char buf[BUFSIZE];
-/** Mode buffer (eg: "+sntkl") */
-MODVAR char modebuf[BUFSIZE];
-/** Parameter buffer (eg: "key 123") */
-MODVAR char parabuf[BUFSIZE];
+
+static mp_pool_t *channel_pool = NULL;
/** This describes the letters, modes and options for core channel modes.
* These are +ntmispklr and also the list modes +vhoaq and +beI.
*/
CoreChannelModeTable corechannelmodetable[] = {
- {MODE_LIMIT, 'l', 1, 1},
- {MODE_VOICE, 'v', 1, 1},
- {MODE_HALFOP, 'h', 0, 1},
- {MODE_CHANOP, 'o', 0, 1},
- {MODE_PRIVATE, 'p', 0, 0},
- {MODE_SECRET, 's', 0, 0},
- {MODE_MODERATED, 'm', 1, 0},
- {MODE_NOPRIVMSGS, 'n', 1, 0},
- {MODE_TOPICLIMIT, 't', 1, 0},
- {MODE_INVITEONLY, 'i', 1, 0},
- {MODE_KEY, 'k', 1, 1},
- {MODE_RGSTR, 'r', 0, 0},
- {MODE_CHANADMIN, 'a', 0, 1},
- {MODE_CHANOWNER, 'q', 0, 1},
{MODE_BAN, 'b', 1, 1},
{MODE_EXCEPT, 'e', 1, 1}, /* exception ban */
{MODE_INVEX, 'I', 1, 1}, /* invite-only exception */
@@ -74,14 +58,8 @@ CoreChannelModeTable corechannelmodetable[] = {
/** The advertised supported channel modes in the 004 numeric */
char cmodestring[512];
-/* Some forward declarations */
-char *clean_ban_mask(char *, int, Client *);
-void channel_modes(Client *client, char *mbuf, char *pbuf, size_t mbuf_size, size_t pbuf_size, Channel *channel);
-int sub1_from_channel(Channel *);
-void del_invite(Client *, Channel *);
-
/** Returns 1 if the IRCOp can override or is a remote connection */
-inline int op_can_override(char *acl, Client *client,Channel *channel,void* extra)
+inline int op_can_override(const char *acl, Client *client, Channel *channel, void* extra)
{
#ifndef NO_OPEROVERRIDE
if (MyUser(client) && !(ValidatePermissionsForPath(acl,client,NULL,channel,extra)))
@@ -106,17 +84,6 @@ int Halfop_mode(long mode)
return TRUE;
}
-
-/** Returns the length (entry count) of a +beI list */
-static int list_length(Link *lp)
-{
- int count = 0;
-
- for (; lp; lp = lp->next)
- count++;
- return count;
-}
-
/** Find client in a Member linked list (eg: channel->members) */
Member *find_member_link(Member *lp, Client *ptr)
{
@@ -156,8 +123,6 @@ static Member *make_member(void)
for (i = 1; i <= (4072/sizeof(Member)); ++i)
{
lp = safe_alloc(sizeof(Member));
- lp->client = NULL;
- lp->flags = 0;
lp->next = freemember;
freemember = lp;
}
@@ -176,8 +141,6 @@ static void free_member(Member *lp)
moddata_free_member(lp);
memset(lp, 0, sizeof(Member));
lp->next = freemember;
- lp->client = NULL;
- lp->flags = 0;
freemember = lp;
}
@@ -228,7 +191,7 @@ static void free_membership(Membership *m)
* only after searching through the nick history.
* @returns The client (if found) or NULL (if not found).
*/
-Client *find_chasing(Client *client, char *user, int *chasing)
+Client *find_chasing(Client *client, const char *user, int *chasing)
{
Client *who = find_client(user, NULL);
@@ -254,9 +217,10 @@ Client *find_chasing(Client *client, char *user, int *chasing)
}
/** Return 1 if the bans are identical, taking into account special handling for extbans */
-int identical_ban(char *one, char *two)
+int identical_ban(const char *one, const char *two)
{
- if (is_extended_ban(one))
+#if 0
+ if (is_extended_ban(one) && is_extended_ban(two))
{
/* compare the first 3 characters case-sensitive and if identical then compare
* the remainder of the string case-insensitive.
@@ -267,6 +231,14 @@ int identical_ban(char *one, char *two)
if (!mycmp(one, two))
return 1;
}
+#else
+ /* Actually I think we can live with this nowadays.
+ * We are pushing towards named extbans, and all the
+ * letter extbans that could clash no longer exist.
+ */
+ if (!mycmp(one, two))
+ return 1;
+#endif
return 0;
}
@@ -274,14 +246,14 @@ int identical_ban(char *one, char *two)
* the specified channel. (Extended version with
* set by nick and set on timestamp)
*/
-int add_listmode_ex(Ban **list, Client *client, Channel *channel, char *banid, char *setby, time_t seton)
+int add_listmode_ex(Ban **list, Client *client, Channel *channel, const char *banid, const char *setby, time_t seton)
{
Ban *ban;
int cnt = 0, len;
int do_not_add = 0;
- if (MyUser(client))
- collapse(banid);
+ //if (MyUser(client))
+ // collapse(banid);
len = strlen(banid);
if (!*list && ((len > MAXBANLENGTH) || (MAXBANS < 1)))
@@ -289,7 +261,7 @@ int add_listmode_ex(Ban **list, Client *client, Channel *channel, char *banid, c
if (MyUser(client))
{
/* Only send the error to local clients */
- sendnumeric(client, ERR_BANLISTFULL, channel->chname, banid);
+ sendnumeric(client, ERR_BANLISTFULL, channel->name, banid);
}
do_not_add = 1;
}
@@ -318,7 +290,7 @@ int add_listmode_ex(Ban **list, Client *client, Channel *channel, char *banid, c
if (MyUser(client))
{
/* Only send the error to local clients */
- sendnumeric(client, ERR_BANLISTFULL, channel->chname, banid);
+ sendnumeric(client, ERR_BANLISTFULL, channel->name, banid);
}
return -1;
}
@@ -345,20 +317,20 @@ int add_listmode_ex(Ban **list, Client *client, Channel *channel, char *banid, c
/** Add a listmode (+beI) with the specified banid to
* the specified channel. (Simplified version)
*/
-int add_listmode(Ban **list, Client *client, Channel *channel, char *banid)
+int add_listmode(Ban **list, Client *client, Channel *channel, const char *banid)
{
char *setby = client->name;
char nuhbuf[NICKLEN+USERLEN+HOSTLEN+4];
if (IsUser(client) && (iConf.ban_setter == SETTER_NICK_USER_HOST))
- setby = make_nick_user_host_r(nuhbuf, client->name, client->user->username, GetHost(client));
+ setby = make_nick_user_host_r(nuhbuf, sizeof(nuhbuf), client->name, client->user->username, GetHost(client));
return add_listmode_ex(list, client, channel, banid, setby, TStime());
}
/** Delete a listmode (+beI) from a channel that matches the specified banid.
*/
-int del_listmode(Ban **list, Channel *channel, char *banid)
+int del_listmode(Ban **list, Channel *channel, const char *banid)
{
Ban **ban;
Ban *tmp;
@@ -390,43 +362,37 @@ int del_listmode(Ban **list, Channel *channel, char *banid)
* @returns A pointer to the ban struct if banned, otherwise NULL.
* @comments Simple wrapper for is_banned_with_nick()
*/
-inline Ban *is_banned(Client *client, Channel *channel, int type, char **msg, char **errmsg)
+inline Ban *is_banned(Client *client, Channel *channel, int type, const char **msg, const char **errmsg)
{
return is_banned_with_nick(client, channel, type, NULL, msg, errmsg);
}
/** ban_check_mask - Checks if the user matches the specified n!u@h mask -or- run an extended ban.
- * @param client Client to check (can be remote client)
- * @param channel Channel to check
- * @param banstr Mask string to check user
- * @param type Type of ban to check for (BANCHK_*)
- * @param msg Message, only for some BANCHK_* types, otherwise NULL.
- * @param errmsg Error message, could be NULL
- * @param no_extbans 0 to check extbans, nonzero to disable extban checking.
- * @returns Nonzero if the mask/extban succeeds. Zero if it doesn't.
- * @comments This is basically extracting the mask and extban check from is_banned_with_nick, but with being a bit more strict in what an extban is.
- * Strange things could happen if this is called outside standard ban checking.
+ * This is basically extracting the mask and extban check from is_banned_with_nick,
+ * but with being a bit more strict in what an extban is.
+ * Strange things could happen if this is called outside standard ban checking.
+ * @param b Ban context, see BanContext
+ * @returns Nonzero if the mask/extban succeeds. Zero if it doesn't.
*/
-inline int ban_check_mask(Client *client, Channel *channel, char *banstr, int type, char **msg, char **errmsg, int no_extbans)
+inline int ban_check_mask(BanContext *b)
{
- Extban *extban = NULL;
- if (!no_extbans && is_extended_ban(banstr))
+ if (!b->no_extbans && is_extended_ban(b->banstr))
{
/* Is an extended ban. */
- extban = findmod_by_bantype(banstr[1]);
- if (!extban)
+ const char *nextbanstr;
+ Extban *extban = findmod_by_bantype(b->banstr, &nextbanstr);
+ if (!extban || !(extban->is_banned_events & b->ban_check_types))
{
return 0;
- }
- else
- {
- return extban->is_banned(client, channel, banstr, type, msg, errmsg);
+ } else {
+ b->banstr = nextbanstr;
+ return extban->is_banned(b);
}
}
else
{
/* Is a n!u@h mask. */
- return match_user(banstr, client, MATCH_CHECK_ALL);
+ return match_user(b->banstr, b->client, MATCH_CHECK_ALL);
}
}
@@ -438,10 +404,11 @@ inline int ban_check_mask(Client *client, Channel *channel, char *banstr, int ty
* @param msg Message, only for some BANCHK_* types, otherwise NULL
* @returns A pointer to the ban struct if banned, otherwise NULL.
*/
-Ban *is_banned_with_nick(Client *client, Channel *channel, int type, char *nick, char **msg, char **errmsg)
+Ban *is_banned_with_nick(Client *client, Channel *channel, int type, const char *nick, const char **msg, const char **errmsg)
{
Ban *ban, *ex;
char savednick[NICKLEN+1];
+ BanContext *b = safe_alloc(sizeof(BanContext));
/* It's not really doable to pass 'nick' to all the ban layers,
* including extbans (with stacking) and so on. Or at least not
@@ -460,13 +427,20 @@ Ban *is_banned_with_nick(Client *client, Channel *channel, int type, char *nick,
strlcpy(client->name, nick, sizeof(client->name));
}
+ b->client = client;
+ b->channel = channel;
+ b->ban_check_types = type;
+ if (msg)
+ b->msg = *msg;
+
/* We check +b first, if a +b is found we then see if there is a +e.
* If a +e was found we return NULL, if not, we return the ban.
*/
for (ban = channel->banlist; ban; ban = ban->next)
{
- if (ban_check_mask(client, channel, ban->banstr, type, msg, errmsg, 0))
+ b->banstr = ban->banstr;
+ if (ban_check_mask(b))
break;
}
@@ -475,7 +449,8 @@ Ban *is_banned_with_nick(Client *client, Channel *channel, int type, char *nick,
/* Ban found, now check for +e */
for (ex = channel->exlist; ex; ex = ex->next)
{
- if (ban_check_mask(client, channel, ex->banstr, type, msg, errmsg, 0))
+ b->banstr = ex->banstr;
+ if (ban_check_mask(b))
{
/* except matched */
ban = NULL;
@@ -491,6 +466,13 @@ Ban *is_banned_with_nick(Client *client, Channel *channel, int type, char *nick,
strlcpy(client->name, savednick, sizeof(client->name));
}
+ /* OUT: */
+ if (msg)
+ *msg = b->msg;
+ if (errmsg)
+ *errmsg = b->error_msg;
+
+ safe_free(b);
return ban;
}
@@ -499,37 +481,43 @@ Ban *is_banned_with_nick(Client *client, Channel *channel, int type, char *nick,
* and also the Membership struct to the client->user->channel linked list.
* @note This does NOT send the JOIN, it only does the linked list stuff.
*/
-void add_user_to_channel(Channel *channel, Client *who, int flags)
+void add_user_to_channel(Channel *channel, Client *client, const char *modes)
{
Member *m;
Membership *mb;
+ const char *p;
- if (who->user)
- {
- m = make_member();
- m->client = who;
- m->flags = flags;
- m->next = channel->members;
- channel->members = m;
- channel->users++;
+ if (!client->user)
+ return;
- mb = make_membership();
- mb->channel = channel;
- mb->next = who->user->channel;
- mb->flags = flags;
- who->user->channel = mb;
- who->user->joined++;
- RunHook2(HOOKTYPE_JOIN_DATA, who, channel);
- }
+ m = make_member();
+ m->client = client;
+ m->next = channel->members;
+ channel->members = m;
+ channel->users++;
+
+ mb = make_membership();
+ mb->channel = channel;
+ mb->next = client->user->channel;
+ client->user->channel = mb;
+ client->user->joined++;
+
+ for (p = modes; *p; p++)
+ add_member_mode_fast(m, mb, *p);
+
+ RunHook(HOOKTYPE_JOIN_DATA, client, channel);
}
/** Remove the user from the channel.
- * This doesn't send any PART etc. It does the free'ing of
- * membership etc. It will also DESTROY the channel if the
- * user was the last user (and the channel is not +P),
- * via sub1_from_channel(), that is.
+ * This frees the memberships, decreases the user counts,
+ * destroys the channel if needed, etc.
+ * This does not send any PART/KICK/..!
+ * @param client The client that is removed from the channel
+ * @param channel The channel
+ * @param dont_log Set to 1 if it should not be logged as a part,
+ * for example if you are already logging it as a kick.
*/
-int remove_user_from_channel(Client *client, Channel *channel)
+int remove_user_from_channel(Client *client, Channel *channel, int dont_log)
{
Member **m;
Member *m2;
@@ -561,56 +549,46 @@ int remove_user_from_channel(Client *client, Channel *channel)
/* Update user record to reflect 1 less joined */
client->user->joined--;
+ if (!dont_log)
+ {
+ if (MyUser(client))
+ {
+ unreal_log(ULOG_INFO, "part", "LOCAL_CLIENT_PART", client,
+ "User $client left $channel",
+ log_data_channel("channel", channel));
+ } else {
+ unreal_log(ULOG_INFO, "part", "REMOTE_CLIENT_PART", client,
+ "User $client left $channel",
+ log_data_channel("channel", channel));
+ }
+ }
+
/* Now sub1_from_channel() will deal with the channel record
* and destroy the channel if needed.
*/
return sub1_from_channel(channel);
}
-/** Get channel access flags (CHFL_*) for a client in a channel.
- * @param client The client
- * @param channel The channel
- * @returns One or more of CHFL_* (eg: CHFL_CHANOP|CHFL_CHANADMIN)
- * @note If the user is not found, then 0 is returned.
- * If the user has no access rights, then 0 is returned as well.
- */
-long get_access(Client *client, Channel *channel)
-{
- Membership *lp;
- if (channel && IsUser(client))
- if ((lp = find_membership_link(client->user->channel, channel)))
- return lp->flags;
- return 0;
-}
-
/** Returns 1 if channel has this channel mode set and 0 if not */
int has_channel_mode(Channel *channel, char mode)
{
- CoreChannelModeTable *tab = &corechannelmodetable[0];
- int i;
+ Cmode *cm;
- /* Extended channel modes */
- for (i=0; i <= Channelmode_highest; i++)
- {
- if ((Channelmode_Table[i].flag == mode) && (channel->mode.extmode & Channelmode_Table[i].mode))
+ for (cm=channelmodes; cm; cm = cm->next)
+ if ((cm->letter == mode) && (channel->mode.mode & cm->mode))
return 1;
- }
- /* Built-in channel modes */
- while (tab->mode != 0x0)
- {
- if ((channel->mode.mode & tab->mode) && (tab->flag == mode))
+ return 0; /* Not found */
+}
+
+/** Returns 1 if channel has this mode is set and 0 if not */
+int has_channel_mode_raw(Cmode_t m, char mode)
+{
+ Cmode *cm;
+
+ for (cm=channelmodes; cm; cm = cm->next)
+ if ((cm->letter == mode) && (m & cm->mode))
return 1;
- tab++;
- }
-
- /* Special handling for +l (needed??) */
- if (channel->mode.limit && (mode == 'l'))
- return 1;
-
- /* Special handling for +k (needed??) */
- if (channel->mode.key[0] && (mode == 'k'))
- return 1;
return 0; /* Not found */
}
@@ -618,126 +596,88 @@ int has_channel_mode(Channel *channel, char mode)
/** Get the extended channel mode 'bit' value (eg: 0x20) by character (eg: 'Z') */
Cmode_t get_extmode_bitbychar(char m)
{
- int extm;
- for (extm=0; extm <= Channelmode_highest; extm++)
- {
- if (Channelmode_Table[extm].flag == m)
- return Channelmode_Table[extm].mode;
- }
+ Cmode *cm;
+
+ for (cm=channelmodes; cm; cm = cm->next)
+ if (cm->letter == m)
+ return cm->mode;
+
return 0;
}
-/** Get the extended channel mode character (eg: 'Z') by the 'bit' value (eg: 0x20) */
-long get_mode_bitbychar(char m)
-{
- CoreChannelModeTable *tab = &corechannelmodetable[0];
-
- while(tab->mode != 0x0)
- {
- if (tab->flag == m)
- return tab->mode;
- tab++;;
- }
- return 0;
-}
-
/** Write the "simple" list of channel modes for channel channel onto buffer mbuf with the parameters in pbuf.
+ * @param client The client requesting the mode list (can be NULL)
+ * @param mbuf Modes will be stored here
+ * @param pbuf Mode parameters will be stored here
+ * @param mbuf_size Length of the mbuf buffer
+ * @param pbuf_size Length of the pbuf buffer
+ * @param channel The channel to fetch modes from
+ * @param hide_local_modes If set to 1 then we will hide local channel modes like Z and d
+ * (eg: if you intend to send the buffer to a remote server)
*/
-/* TODO: this function has many security issues and needs an audit, maybe even a recode */
-void channel_modes(Client *client, char *mbuf, char *pbuf, size_t mbuf_size, size_t pbuf_size, Channel *channel)
+void channel_modes(Client *client, char *mbuf, char *pbuf, size_t mbuf_size, size_t pbuf_size, Channel *channel, int hide_local_modes)
{
- CoreChannelModeTable *tab = &corechannelmodetable[0];
- int ismember;
- int i;
+ int ismember = 0;
+ Cmode *cm;
- if (!(mbuf_size && pbuf_size)) return;
+ if (!mbuf_size || !pbuf_size)
+ return;
- ismember = (IsMember(client, channel) || IsServer(client) || IsMe(client) || IsULine(client)) ? 1 : 0;
+ if (!client || IsMember(client, channel) || IsServer(client) || IsMe(client) || IsULine(client))
+ ismember = 1;
*pbuf = '\0';
+ strlcpy(mbuf, "+", mbuf_size);
- *mbuf++ = '+';
- mbuf_size--;
/* Paramless first */
- while (mbuf_size && tab->mode != 0x0)
+ for (cm=channelmodes; cm; cm = cm->next)
{
- if ((channel->mode.mode & tab->mode))
- if (!tab->parameters) {
- *mbuf++ = tab->flag;
- mbuf_size--;
- }
- tab++;
- }
- for (i=0; i <= Channelmode_highest; i++)
- {
- if (!mbuf_size) break;
- if (Channelmode_Table[i].flag && !Channelmode_Table[i].paracount &&
- (channel->mode.extmode & Channelmode_Table[i].mode)) {
- *mbuf++ = Channelmode_Table[i].flag;
- mbuf_size--;
- }
- }
- if (channel->mode.limit)
- {
- if (mbuf_size) {
- *mbuf++ = 'l';
- mbuf_size--;
- }
- if (ismember) {
- ircsnprintf(pbuf, pbuf_size, "%d ", channel->mode.limit);
- pbuf_size-=strlen(pbuf);
- pbuf+=strlen(pbuf);
- }
- }
- if (*channel->mode.key)
- {
- if (mbuf_size) {
- *mbuf++ = 'k';
- mbuf_size--;
- }
- if (ismember && pbuf_size) {
- ircsnprintf(pbuf, pbuf_size, "%s ", channel->mode.key);
- pbuf_size-=strlen(pbuf);
- pbuf+=strlen(pbuf);
+ if (cm->letter &&
+ !cm->paracount &&
+ !(hide_local_modes && cm->local) &&
+ (channel->mode.mode & cm->mode))
+ {
+ strlcat_letter(mbuf, cm->letter, mbuf_size);
}
}
- for (i=0; i <= Channelmode_highest; i++)
+ for (cm=channelmodes; cm; cm = cm->next)
{
- if (Channelmode_Table[i].flag && Channelmode_Table[i].paracount &&
- (channel->mode.extmode & Channelmode_Table[i].mode)) {
- char flag = Channelmode_Table[i].flag;
- if (mbuf_size) {
- *mbuf++ = flag;
- mbuf_size--;
- }
+ if (cm->letter &&
+ cm->paracount &&
+ !(hide_local_modes && cm->local) &&
+ (channel->mode.mode & cm->mode))
+ {
+ char flag = cm->letter;
+
+ if (mbuf_size)
+ strlcat_letter(mbuf, flag, mbuf_size);
+
if (ismember)
{
- ircsnprintf(pbuf, pbuf_size, "%s ", cm_getparameter(channel, flag));
- pbuf_size-=strlen(pbuf);
- pbuf+=strlen(pbuf);
+ strlcat(pbuf, cm_getparameter(channel, flag), pbuf_size);
+ strlcat(pbuf, " ", pbuf_size);
}
}
}
/* Remove the trailing space from the parameters -- codemastr */
- if (*pbuf) pbuf[strlen(pbuf)-1]=0;
-
- if (!mbuf_size) mbuf--;
- *mbuf++ = '\0';
- return;
+ if (*pbuf)
+ pbuf[strlen(pbuf)-1]='\0';
}
/** Make a pretty mask from the input string - only used by SILENCE
*/
-char *pretty_mask(char *mask)
+char *pretty_mask(const char *mask_in)
{
- char *cp;
- char *user;
- char *host;
+ char mask[512];
+ char *cp, *user, *host;
+
+ strlcpy(mask, mask_in, sizeof(mask));
if ((user = strchr((cp = mask), '!')))
*user++ = '\0';
+
if ((host = strrchr(user ? user : cp, '@')))
{
*host++ = '\0';
@@ -745,7 +685,9 @@ char *pretty_mask(char *mask)
return make_nick_user_host(NULL, cp, host);
}
else if (!user && strchr(cp, '.'))
+ {
return make_nick_user_host(NULL, NULL, cp);
+ }
return make_nick_user_host(cp, user, host);
}
@@ -772,31 +714,30 @@ char *trim_str(char *str, int len)
* @param mask The ban mask
* @param what MODE_DEL or MODE_ADD
* @param client The client adding/removing this ban mask
+ * @param conv_options Options for BanContext.conv_options (eg BCTX_CONV_OPTION_WRITE_LETTER_BANS)
* @returns pointer to correct banmask or NULL in case of error
* @note A pointer is returned to a static buffer, which is overwritten
* on next clean_ban_mask or make_nick_user_host call.
*/
-char *clean_ban_mask(char *mask, int what, Client *client)
+const char *clean_ban_mask(const char *mask_in, int what, Client *client, int conv_options)
{
char *cp, *x;
char *user;
char *host;
- Extban *p;
- static char maskbuf[512];
+ static char mask[512];
+
+ /* Strip any ':' at beginning since that would cause a desync */
+ for (; (*mask_in && (*mask_in == ':')); mask_in++);
+ if (!*mask_in)
+ return NULL;
/* Work on a copy */
- strlcpy(maskbuf, mask, sizeof(maskbuf));
- mask = maskbuf;
+ strlcpy(mask, mask_in, sizeof(mask));
cp = strchr(mask, ' ');
if (cp)
*cp = '\0';
- /* Strip any ':' at beginning since that would cause a desync */
- for (; (*mask && (*mask == ':')); mask++);
- if (!*mask)
- return NULL;
-
/* Forbid ASCII <= 32 in all bans */
for (x = mask; *x; x++)
if (*x <= ' ')
@@ -805,6 +746,9 @@ char *clean_ban_mask(char *mask, int what, Client *client)
/* Extended ban? */
if (is_extended_ban(mask))
{
+ const char *nextbanstr;
+ Extban *extban;
+
if (RESTRICT_EXTENDEDBANS && MyUser(client) && !ValidatePermissionsForPath("immune:restrict-extendedbans",client,NULL,NULL,NULL))
{
if (!strcmp(RESTRICT_EXTENDEDBANS, "*"))
@@ -819,8 +763,9 @@ char *clean_ban_mask(char *mask, int what, Client *client)
return NULL;
}
}
- p = findmod_by_bantype(mask[1]);
- if (!p)
+
+ extban = findmod_by_bantype(mask, &nextbanstr);
+ if (!extban)
{
/* extended bantype not supported, what to do?
* Here are the rules:
@@ -833,8 +778,21 @@ char *clean_ban_mask(char *mask, int what, Client *client)
return mask; /* allow it */
return NULL; /* reject */
}
- if (p->conv_param)
- return p->conv_param(mask);
+
+ if (extban->conv_param)
+ {
+ const char *ret;
+ static char retbuf[512];
+ BanContext *b = safe_alloc(sizeof(BanContext));
+ b->client = client;
+ b->what = what;
+ b->banstr = nextbanstr;
+ b->conv_options = conv_options;
+ ret = extban->conv_param(b, extban);
+ ret = prefix_with_extban(ret, b, extban, retbuf, sizeof(retbuf));
+ safe_free(b);
+ return ret;
+ }
/* else, do some basic sanity checks and cut it off at 80 bytes */
if ((mask[1] != ':') || (mask[2] == '\0'))
return NULL; /* require a ":" after extban type */
@@ -864,11 +822,23 @@ char *clean_ban_mask(char *mask, int what, Client *client)
int find_invex(Channel *channel, Client *client)
{
Ban *inv;
+ BanContext *b = safe_alloc(sizeof(BanContext));
+
+ b->client = client;
+ b->channel = channel;
+ b->ban_check_types = BANCHK_JOIN;
for (inv = channel->invexlist; inv; inv = inv->next)
- if (ban_check_mask(client, channel, inv->banstr, BANCHK_JOIN, NULL, NULL, 0))
+ {
+ b->banstr = inv->banstr;
+ if (ban_check_mask(b))
+ {
+ safe_free(b);
return 1;
+ }
+ }
+ safe_free(b);
return 0;
}
@@ -924,134 +894,77 @@ int valid_channelname(const char *cname)
return 1; /* Valid */
}
-/** Get existing channel 'chname' or create a new one.
- * @param client User creating or searching this channel
- * @param chname Channel name
+void initlist_channels(void)
+{
+ channel_pool = mp_pool_new(sizeof(Channel), 512 * 1024);
+}
+
+/** Create channel 'name' (or if it exists, return the existing one)
+ * @param name Channel name
* @param flag If set to 'CREATE' then the channel is
* created if it does not exist.
* @returns Pointer to channel (new or existing).
* @note Be sure to call valid_channelname() first before
* you blindly call this function!
*/
-Channel *get_channel(Client *client, char *chname, int flag)
+Channel *make_channel(const char *name)
{
Channel *channel;
- int len;
+ int len;
+ char *p;
+ char namebuf[CHANNELLEN+1];
- if (BadPtr(chname))
+ if (BadPtr(name))
return NULL;
- len = strlen(chname);
- if (MyUser(client) && len > CHANNELLEN)
+ /* Copy and silently truncate */
+ strlcpy(namebuf, name, sizeof(namebuf));
+
+ /* Copied from valid_channelname(), the minimal requirements */
+ for (p = namebuf; *p; p++)
{
- len = CHANNELLEN;
- *(chname + CHANNELLEN) = '\0';
- }
- if ((channel = find_channel(chname, NULL)))
- return (channel);
- if (flag == CREATE)
- {
- channel = safe_alloc(sizeof(Channel) + len);
- strlcpy(channel->chname, chname, len + 1);
- if (channels)
- channels->prevch = channel;
- channel->topic = NULL;
- channel->topic_nick = NULL;
- channel->prevch = NULL;
- channel->nextch = channels;
- channel->creationtime = MyUser(client) ? TStime() : 0;
- channels = channel;
- add_to_channel_hash_table(chname, channel);
- irccounts.channels++;
- RunHook2(HOOKTYPE_CHANNEL_CREATE, client, channel);
+ if (*p < 33 || *p == ',' || *p == ':')
+ {
+ *p = '\0';
+ break;
+ }
}
+
+ /* Exists? Return it. */
+ if ((channel = find_channel(name)))
+ return channel;
+
+ channel = mp_pool_get(channel_pool);
+ memset(channel, 0, sizeof(Channel));
+
+ strlcpy(channel->name, name, sizeof(channel->name));
+
+ if (channels)
+ channels->prevch = channel;
+
+ channel->topic = NULL;
+ channel->topic_nick = NULL;
+ channel->prevch = NULL;
+ channel->nextch = channels;
+ channel->creationtime = TStime();
+ channels = channel;
+ add_to_channel_hash_table(channel->name, channel);
+ irccounts.channels++;
+
+ RunHook(HOOKTYPE_CHANNEL_CREATE, channel);
+
return channel;
}
-/** Register an invite from someone to a channel - so they can bypass +i etc.
- * @param from The person sending the invite
- * @param to The person who is invited to join
- * @param channel The channel
- * @param mtags Message tags associated with this INVITE command
- */
-void add_invite(Client *from, Client *to, Channel *channel, MessageTag *mtags)
-{
- Link *inv, *tmp;
-
- del_invite(to, channel);
- /* If too many invite entries then delete the oldest one */
- if (list_length(to->user->invited) >= MAXCHANNELSPERUSER)
- {
- for (tmp = to->user->invited; tmp->next; tmp = tmp->next)
- ;
- del_invite(to, tmp->value.channel);
-
- }
- /* We get pissy over too many invites per channel as well now,
- * since otherwise mass-inviters could take up some major
- * resources -Donwulff
- */
- if (list_length(channel->invites) >= MAXCHANNELSPERUSER)
- {
- for (tmp = channel->invites; tmp->next; tmp = tmp->next)
- ;
- del_invite(tmp->value.client, channel);
- }
- /*
- * add client to the beginning of the channel invite list
- */
- inv = make_link();
- inv->value.client = to;
- inv->next = channel->invites;
- channel->invites = inv;
- /*
- * add channel to the beginning of the client invite list
- */
- inv = make_link();
- inv->value.channel = channel;
- inv->next = to->user->invited;
- to->user->invited = inv;
-
- RunHook4(HOOKTYPE_INVITE, from, to, channel, mtags);
-}
-
-/** Delete a previous invite of someone to a channel.
- * @param client The client who was invited
- * @param channel The channel to which the person was invited
- */
-void del_invite(Client *client, Channel *channel)
-{
- Link **inv, *tmp;
-
- for (inv = &(channel->invites); (tmp = *inv); inv = &tmp->next)
- if (tmp->value.client == client)
- {
- *inv = tmp->next;
- free_link(tmp);
- break;
- }
-
- for (inv = &(client->user->invited); (tmp = *inv); inv = &tmp->next)
- if (tmp->value.channel == channel)
- {
- *inv = tmp->next;
- free_link(tmp);
- break;
- }
-}
-
/** Is the user 'client' invited to channel 'channel' by a chanop?
* @param client The client who was invited
* @param channel The channel to which the person was invited
*/
int is_invited(Client *client, Channel *channel)
{
- Link *lp;
-
- for (lp = client->user->invited; lp; lp = lp->next)
- if (lp->value.channel == channel)
- return 1;
- return 0;
+ int invited = 0;
+ RunHook(HOOKTYPE_IS_INVITED, client, channel, &invited);
+ return invited;
}
/** Subtract one user from channel i. Free the channel if it became empty.
@@ -1072,7 +985,7 @@ int sub1_from_channel(Channel *channel)
channel->users = 0; /* to be sure */
/* If the channel is +P then this hook will actually stop destruction. */
- RunHook2(HOOKTYPE_CHANNEL_DESTROY, channel, &should_destroy);
+ RunHook(HOOKTYPE_CHANNEL_DESTROY, channel, &should_destroy);
if (!should_destroy)
return 0;
@@ -1082,9 +995,6 @@ int sub1_from_channel(Channel *channel)
moddata_free_channel(channel);
- while ((lp = channel->invites))
- del_invite(lp->value.client, channel);
-
while (channel->banlist)
{
ban = channel->banlist;
@@ -1111,7 +1021,7 @@ int sub1_from_channel(Channel *channel)
}
/* free extcmode params */
- extcmode_free_paramlist(channel->mode.extmodeparams);
+ extcmode_free_paramlist(channel->mode.mode_params);
safe_free(channel->mode_lock);
safe_free(channel->topic);
@@ -1124,10 +1034,10 @@ int sub1_from_channel(Channel *channel)
if (channel->nextch)
channel->nextch->prevch = channel->prevch;
- del_from_channel_hash_table(channel->chname, channel);
+ del_from_channel_hash_table(channel->name, channel);
irccounts.channels--;
- safe_free(channel);
+ mp_pool_release(channel);
return 1;
}
@@ -1143,7 +1053,7 @@ void set_channel_mlock(Client *client, Channel *channel, const char *newmlock, i
if (propagate)
{
sendto_server(client, 0, 0, NULL, ":%s MLOCK %lld %s :%s",
- client->id, (long long)channel->creationtime, channel->chname,
+ client->id, (long long)channel->creationtime, channel->name,
BadPtr(channel->mode_lock) ? "" : channel->mode_lock);
}
}
@@ -1159,14 +1069,14 @@ void set_channel_mlock(Client *client, Channel *channel, const char *newmlock, i
* int ret;
* for (ret = parse_chanmode(&pm, modebuf, parabuf); ret; ret = parse_chanmode(&pm, NULL, NULL))
* {
- * ircd_log(LOG_ERROR, "Got %c%c %s",
- * pm.what == MODE_ADD ? '+' : '-',
- * pm.modechar,
- * pm.param ? pm.param : "");
+ * unreal_log(ULOG_INFO, "test", "TEST", "Got %c%c %s",
+ * pm.what == MODE_ADD ? '+' : '-',
+ * pm.modechar,
+ * pm.param ? pm.param : "");
* }
* @endcode
*/
-int parse_chanmode(ParseMode *pm, char *modebuf_in, char *parabuf_in)
+int parse_chanmode(ParseMode *pm, const char *modebuf_in, const char *parabuf_in)
{
if (modebuf_in)
{
@@ -1196,7 +1106,7 @@ int parse_chanmode(ParseMode *pm, char *modebuf_in, char *parabuf_in)
else
{
CoreChannelModeTable *tab = &corechannelmodetable[0];
- int i;
+ Cmode *cm;
int eatparam = 0;
/* Set some defaults */
@@ -1216,32 +1126,31 @@ int parse_chanmode(ParseMode *pm, char *modebuf_in, char *parabuf_in)
/* INTERNAL MODE */
if (tab->parameters)
{
- if ((pm->what == MODE_DEL) && (tab->flag == 'l'))
- eatparam = 0; /* -l is special: no parameter required */
- else
- eatparam = 1; /* all other internal parameter modes do require a parameter on unset */
+ eatparam = 1;
}
} else {
/* EXTENDED CHANNEL MODE */
int found = 0;
- for (i=0; i <= Channelmode_highest; i++)
- if (Channelmode_Table[i].flag == *pm->modebuf)
+ for (cm=channelmodes; cm; cm = cm->next)
+ {
+ if (cm->letter == *pm->modebuf)
{
found = 1;
break;
}
+ }
if (!found)
{
/* Not found. Will be ignored, just move on.. */
pm->modebuf++;
continue;
}
- pm->extm = &Channelmode_Table[i];
- if (Channelmode_Table[i].paracount == 1)
+ pm->extm = cm;
+ if (cm->paracount == 1)
{
if (pm->what == MODE_ADD)
eatparam = 1;
- else if (Channelmode_Table[i].unset_with_param)
+ else if (cm->unset_with_param)
eatparam = 1;
/* else 0 (if MODE_DEL && !unset_with_param) */
}
@@ -1252,7 +1161,7 @@ int parse_chanmode(ParseMode *pm, char *modebuf_in, char *parabuf_in)
/* Hungry.. */
if (pm->parabuf && *pm->parabuf)
{
- char *start, *end;
+ const char *start, *end;
for (; *pm->parabuf == ' '; pm->parabuf++); /* skip whitespace */
start = pm->parabuf;
if (*pm->parabuf == '\0')
@@ -1274,6 +1183,7 @@ int parse_chanmode(ParseMode *pm, char *modebuf_in, char *parabuf_in)
strlcpy(pm->buf, start, sizeof(pm->buf));
pm->parabuf = pm->parabuf + strlen(pm->parabuf); /* point to \0 at end */
}
+ stripcrlf(pm->buf); /* needed for unreal_server_compat.c */
pm->param = pm->buf;
} else {
pm->modebuf++;
@@ -1319,7 +1229,7 @@ int user_can_see_member(Client *user, Client *target, Channel *channel)
}
/* We must ensure that user is allowed to "see" target */
- if (j != 0 && !(is_skochanop(target, channel) || has_voice(target,channel)) && !is_skochanop(user, channel))
+ if (j != 0 && !(check_channel_access(target, channel, "hoaq") || check_channel_access(target,channel, "v")) && !check_channel_access(user, channel, "hoaq"))
return 0;
return 1;
@@ -1341,7 +1251,7 @@ int invisible_user_in_channel(Client *target, Channel *channel)
}
/* We must ensure that user is allowed to "see" target */
- if (j != 0 && !(is_skochanop(target, channel) || has_voice(target,channel)))
+ if (j != 0 && !(check_channel_access(target, channel, "hoaq") || check_channel_access(target,channel, "v")))
return 1;
return 0;
@@ -1352,9 +1262,9 @@ int invisible_user_in_channel(Client *target, Channel *channel)
* @param client The client to send the message to.
* @param channelname The (invalid) channel that the user tried to join.
*/
-void send_invalid_channelname(Client *client, char *channelname)
+void send_invalid_channelname(Client *client, const char *channelname)
{
- char *reason;
+ const char *reason;
if (*channelname != '#')
{
@@ -1383,10 +1293,60 @@ void send_invalid_channelname(Client *client, char *channelname)
/** Is the provided string possibly an extended ban?
* Note that it still may not exist, it just tests the first part.
+ * @param str The string to check (eg "~account:xyz")
*/
int is_extended_ban(const char *str)
{
- if ((str[0] == '~') && (str[1] != '\0') && (str[2] == ':'))
+ const char *p;
+
+ if (*str != '~')
+ return 0;
+ for (p = str+1; *p; p++)
+ {
+ if (!isalnum(*p))
+ {
+ if (*p == ':')
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/** Is the provided string possibly an extended server ban?
+ * Actually this is only a very light check.
+ * It may still not exist, it just tests the first part.
+ * @param str The string to check (eg "~account:xyz")
+ * The only difference between this and is_extended_ban()
+ * is that we allow a % at the beginning for soft-bans.
+ * @see is_extended_ban()
+ */
+int is_extended_server_ban(const char *str)
+{
+ if (*str == '%')
+ str++;
+ return is_extended_ban(str);
+}
+
+/** Check if it is an empty (useless) mode, namely "", "+" or "-".
+ * Typically called as: empty_mode(modebuf)
+ */
+int empty_mode(const char *m)
+{
+ if (!*m || (((m[0] == '+') || (m[0] == '-')) && m[1] == '\0'))
return 1;
return 0;
}
+
+/** Free everything of/in a MultiLineMode */
+void free_multilinemode(MultiLineMode *m)
+{
+ int i;
+ if (m == NULL)
+ return;
+ for (i=0; i < m->numlines; i++)
+ {
+ safe_free(m->modeline[i]);
+ safe_free(m->paramline[i]);
+ }
+ safe_free(m);
+}
diff --git a/src/conf.c b/src/conf.c
index 694f266..f3d78df 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -31,13 +31,6 @@ struct ConfigCommand
int (*testfunc)(ConfigFile *conf, ConfigEntry *ce);
};
-typedef struct NameValue NameValue;
-struct NameValue
-{
- long flag;
- char *name;
-};
-
/* Config commands */
@@ -65,7 +58,6 @@ static int _conf_deny_version (ConfigFile *conf, ConfigEntry *ce);
static int _conf_require (ConfigFile *conf, ConfigEntry *ce);
static int _conf_allow_channel (ConfigFile *conf, ConfigEntry *ce);
static int _conf_loadmodule (ConfigFile *conf, ConfigEntry *ce);
-static int _conf_log (ConfigFile *conf, ConfigEntry *ce);
static int _conf_alias (ConfigFile *conf, ConfigEntry *ce);
static int _conf_help (ConfigFile *conf, ConfigEntry *ce);
static int _conf_offchans (ConfigFile *conf, ConfigEntry *ce);
@@ -99,7 +91,6 @@ static int _test_deny (ConfigFile *conf, ConfigEntry *ce);
static int _test_allow_channel (ConfigFile *conf, ConfigEntry *ce);
static int _test_loadmodule (ConfigFile *conf, ConfigEntry *ce);
static int _test_blacklist_module (ConfigFile *conf, ConfigEntry *ce);
-static int _test_log (ConfigFile *conf, ConfigEntry *ce);
static int _test_alias (ConfigFile *conf, ConfigEntry *ce);
static int _test_help (ConfigFile *conf, ConfigEntry *ce);
static int _test_offchans (ConfigFile *conf, ConfigEntry *ce);
@@ -124,7 +115,7 @@ static ConfigCommand _ConfigCommands[] = {
{ "link", _conf_link, _test_link },
{ "listen", _conf_listen, _test_listen },
{ "loadmodule", NULL, _test_loadmodule},
- { "log", _conf_log, _test_log },
+ { "log", config_run_log, config_test_log },
{ "me", _conf_me, _test_me },
{ "official-channels", _conf_offchans, _test_offchans },
{ "oper", _conf_oper, _test_oper },
@@ -158,22 +149,6 @@ static NameValue _LinkFlags[] = {
{ CONNECT_TLS, "tls" },
};
-/* This MUST be alphabetized */
-static NameValue _LogFlags[] = {
- { LOG_CHGCMDS, "chg-commands" },
- { LOG_CLIENT, "connects" },
- { LOG_ERROR, "errors" },
- { LOG_FLOOD, "flood" },
- { LOG_KILL, "kills" },
- { LOG_KLINE, "kline" },
- { LOG_OPER, "oper" },
- { LOG_OVERRIDE, "oper-override" },
- { LOG_SACMDS, "sadmin-commands" },
- { LOG_SERVER, "server-connects" },
- { LOG_SPAMFILTER, "spamfilter" },
- { LOG_TKL, "tkl" },
-};
-
/* This MUST be alphabetized */
static NameValue _TLSFlags[] = {
{ TLSFLAG_FAILIFNOCERT, "fail-if-no-clientcert" },
@@ -194,28 +169,25 @@ struct SetCheck settings;
* Utilities
*/
-void port_range(char *string, int *start, int *end);
-long config_checkval(char *value, unsigned short flags);
+void port_range(const char *string, int *start, int *end);
+long config_checkval(const char *value, unsigned short flags);
/*
* Parser
*/
-ConfigFile *config_load(char *filename, char *displayname);
+ConfigFile *config_load(const char *filename, const char *displayname);
void config_free(ConfigFile *cfptr);
-ConfigFile *config_parse_with_offset(char *filename, char *confdata, unsigned int line_offset);
-ConfigFile *config_parse(char *filename, char *confdata);
-ConfigEntry *config_find_entry(ConfigEntry *ce, char *name);
+ConfigFile *config_parse_with_offset(const char *filename, char *confdata, unsigned int line_offset);
+ConfigFile *config_parse(const char *filename, char *confdata);
+ConfigEntry *config_find_entry(ConfigEntry *ce, const char *name);
-extern void add_entropy_configfile(struct stat *st, char *buf);
-extern void unload_all_unused_snomasks(void);
+extern void add_entropy_configfile(struct stat *st, const char *buf);
extern void unload_all_unused_umodes(void);
extern void unload_all_unused_extcmodes(void);
extern void unload_all_unused_caps(void);
extern void unload_all_unused_history_backends(void);
-
int reloadable_perm_module_unloaded(void);
-
int tls_tests(void);
/* Conf sub-sub-functions */
@@ -226,10 +198,11 @@ void free_tls_options(TLSOptions *tlsoptions);
/*
* Config parser (IRCd)
*/
-int init_conf(char *rootconf, int rehash);
-int load_conf(char *filename, const char *original_path);
+int config_read_file(const char *filename, const char *display_name);
void config_rehash();
-int config_run();
+int config_run_blocks();
+int config_test_blocks();
+
/*
* Configuration linked lists
*/
@@ -247,7 +220,6 @@ ConfigItem_operclass *conf_operclass = NULL;
ConfigItem_listen *conf_listen = NULL;
ConfigItem_sni *conf_sni = NULL;
ConfigItem_allow *conf_allow = NULL;
-ConfigItem_except *conf_except = NULL;
ConfigItem_vhost *conf_vhost = NULL;
ConfigItem_link *conf_link = NULL;
ConfigItem_ban *conf_ban = NULL;
@@ -255,9 +227,8 @@ ConfigItem_deny_channel *conf_deny_channel = NULL;
ConfigItem_allow_channel *conf_allow_channel = NULL;
ConfigItem_deny_link *conf_deny_link = NULL;
ConfigItem_deny_version *conf_deny_version = NULL;
-ConfigItem_log *conf_log = NULL;
ConfigItem_alias *conf_alias = NULL;
-ConfigItem_include *conf_include = NULL;
+ConfigResource *config_resources = NULL;
ConfigItem_blacklist_module *conf_blacklist_module = NULL;
ConfigItem_help *conf_help = NULL;
ConfigItem_offchans *conf_offchans = NULL;
@@ -274,25 +245,19 @@ MODVAR Client *remote_rehash_client = NULL;
MODVAR int config_error_flag = 0;
int config_verbose = 0;
-MODVAR int need_34_upgrade = 0;
int need_operclass_permissions_upgrade = 0;
+int invalid_snomasks_encountered = 0;
int have_tls_listeners = 0;
char *port_6667_ip = NULL;
-void add_include(const char *filename, const char *included_from, int included_from_line);
-#ifdef USE_LIBCURL
-void add_remote_include(const char *, const char *, int, const char *, const char *included_from, int included_from_line);
-void update_remote_include(ConfigItem_include *inc, const char *file, int, const char *errorbuf);
-int remote_include(ConfigEntry *ce);
-#endif
-void unload_notloaded_includes(void);
-void load_includes(void);
-void unload_loaded_includes(void);
-int rehash_internal(Client *client, int sig);
-int is_blacklisted_module(char *name);
+int add_config_resource(const char *resource, int type, ConfigEntry *ce);
+void resource_download_complete(const char *url, const char *file, const char *errorbuf, int cached, void *rs_key);
+void free_all_config_resources(void);
+int rehash_internal(Client *client);
+int is_blacklisted_module(const char *name);
/** Return the printable string of a 'cep' location, such as set::something::xyz */
-char *config_var(ConfigEntry *cep)
+const char *config_var(ConfigEntry *cep)
{
static char buf[256];
ConfigEntry *e;
@@ -305,9 +270,9 @@ char *config_var(ConfigEntry *cep)
buf[0] = '\0';
/* First, walk back to the top */
- for (e = cep; e; e = e->ce_prevlevel)
+ for (e = cep; e; e = e->parent)
{
- elem[numel++] = e->ce_varname;
+ elem[numel++] = e->name;
if (numel == 15)
break;
}
@@ -323,9 +288,12 @@ char *config_var(ConfigEntry *cep)
return buf;
}
-void port_range(char *string, int *start, int *end)
+void port_range(const char *string, int *start, int *end)
{
- char *c = strchr(string, '-');
+ char buf[256];
+ char *c;
+ strlcpy(buf, string, sizeof(buf));
+ c = strchr(buf, '-');
if (!c)
{
int tmp = atoi(string);
@@ -346,18 +314,21 @@ void port_range(char *string, int *start, int *end)
* RETURNS: 0 for parse error, 1 if ok.
* REMARK: times&period should be ints!
*/
-int config_parse_flood(char *orig, int *times, int *period)
+int config_parse_flood(const char *orig, int *times, int *period)
{
-char *x;
+ char buf[256];
+ char *x;
+
+ strlcpy(buf, orig, sizeof(buf));
*times = *period = 0;
- x = strchr(orig, ':');
+ x = strchr(buf, ':');
/* 'blah', ':blah', '1:' */
- if (!x || (x == orig) || (*(x+1) == '\0'))
+ if (!x || (x == buf) || (*(x+1) == '\0'))
return 0;
*x = '\0';
- *times = atoi(orig);
+ *times = atoi(buf);
*period = config_checkval(x+1, CFG_TIME);
*x = ':'; /* restore */
return 1;
@@ -441,6 +412,12 @@ int flood_option_is_for_everyone(const char *name)
return text_in_array(name, opts);
}
+/** Free a FloodSettings struct */
+void free_floodsettings(FloodSettings *f)
+{
+ safe_free(f->name);
+ safe_free(f);
+}
/** Parses a value like '5:60s' into a flood setting that we can store.
* @param str The string to parse (eg: '5:60s')
@@ -485,7 +462,8 @@ int config_parse_flood_generic(const char *str, Configuration *conf, char *block
return 1;
}
-long config_checkval(char *orig, unsigned short flags) {
+long config_checkval(const char *orig, unsigned short flags)
+{
char *value = raw_strdup(orig);
char *text;
long ret = 0;
@@ -594,24 +572,20 @@ long config_checkval(char *orig, unsigned short flags) {
/** Free configuration setting for set::modes-on-join */
void free_conf_channelmodes(struct ChMode *store)
{
- int i;
-
- store->mode = 0;
- store->extmodes = 0;
- for (i = 0; i < EXTCMODETABLESZ; i++)
- safe_free(store->extparams[i]);
+ memset(store, 0, sizeof(struct ChMode));
}
/* Set configuration, used for set::modes-on-join */
-void conf_channelmodes(char *modes, struct ChMode *store, int warn)
+void conf_channelmodes(const char *modes, struct ChMode *store)
{
- CoreChannelModeTable *tab;
+ Cmode *cm;
+ const char *m;
char *params = strchr(modes, ' ');
char *parambuf = NULL;
- char *param = NULL;
+ const char *param = NULL;
+ const char *param_in;
char *save = NULL;
-
- warn = 0; // warn is broken
+ int found;
/* Free existing parameters first (no inheritance) */
free_conf_channelmodes(store);
@@ -623,107 +597,86 @@ void conf_channelmodes(char *modes, struct ChMode *store, int warn)
param = strtoken(&save, parambuf, " ");
}
- for (; *modes && *modes != ' '; modes++)
+ for (m = modes; *m && *m != ' '; m++)
{
- if (*modes == '+')
+ if (*m == '+')
continue;
- if (*modes == '-')
- /* When a channel is created it has no modes, so just ignore if the
- * user asks us to unset anything -- codemastr
- */
+
+ if (*m == '-')
{
- while (*modes && *modes != '+')
- modes++;
+ /* When a channel is created it has no modes, so just ignore if the
+ * user asks us to unset anything -- codemastr
+ */
+ while (*m && *m != '+')
+ m++;
continue;
}
- for (tab = &corechannelmodetable[0]; tab->mode; tab++)
+
+ found = 0;
+ for (cm=channelmodes; cm; cm = cm->next)
{
- if (tab->flag == *modes)
+ if (!(cm->letter))
+ continue;
+ if (*m == cm->letter)
{
- if (tab->parameters)
+ found = 1;
+ if (cm->paracount)
{
- /* INCOMPATIBLE */
- break;
+ if (!param)
+ {
+ config_warn("set::modes-on-join '%s'. Parameter missing for mode %c.", modes, *m);
+ break;
+ }
+ param_in = param; /* save it */
+ param = cm->conv_param(param, NULL, NULL);
+ if (!param)
+ {
+ config_warn("set::modes-on-join '%s'. Parameter for mode %c is invalid (%s).", modes, *m, param_in);
+ break; /* invalid parameter fmt, do not set mode. */
+ }
+ safe_strdup(store->extparams[cm->letter], param);
+ /* Get next parameter */
+ param = strtoken(&save, NULL, " ");
}
- store->mode |= tab->mode;
+ store->extmodes |= cm->mode;
break;
}
}
- /* Try extcmodes */
- if (!tab->mode)
- {
- int i;
- for (i=0; i <= Channelmode_highest; i++)
- {
- if (!(Channelmode_Table[i].flag))
- continue;
- if (*modes == Channelmode_Table[i].flag)
- {
- if (Channelmode_Table[i].paracount)
- {
- if (!param)
- break;
- param = Channelmode_Table[i].conv_param(param, NULL, NULL);
- if (!param)
- break; /* invalid parameter fmt, do not set mode. */
- store->extparams[i] = raw_strdup(param);
- /* Get next parameter */
- param = strtoken(&save, NULL, " ");
- }
- store->extmodes |= Channelmode_Table[i].mode;
- break;
- }
- }
- }
+ if (!found)
+ config_warn("set::modes-on-join '%s'. Channel mode %c not found.", modes, *m);
}
safe_free(parambuf);
}
void chmode_str(struct ChMode *modes, char *mbuf, char *pbuf, size_t mbuf_size, size_t pbuf_size)
{
- CoreChannelModeTable *tab;
- int i;
+ Cmode *cm;
if (!(mbuf_size && pbuf_size))
return;
*pbuf = 0;
*mbuf++ = '+';
- if (--mbuf_size == 0) return;
- for (tab = &corechannelmodetable[0]; tab->mode; tab++)
+
+ for (cm=channelmodes; cm; cm = cm->next)
{
- if (modes->mode & tab->mode)
- {
- if (!tab->parameters)
- {
- *mbuf++ = tab->flag;
- if (!--mbuf_size)
- {
- *--mbuf=0;
- break;
- }
- }
- }
- }
- for (i=0; i <= Channelmode_highest; i++)
- {
- if (!(Channelmode_Table[i].flag))
+ if (!(cm->letter))
continue;
- if (modes->extmodes & Channelmode_Table[i].mode)
+ if (modes->extmodes & cm->mode)
{
if (mbuf_size)
{
- *mbuf++ = Channelmode_Table[i].flag;
+ *mbuf++ = cm->letter;
if (!--mbuf_size)
{
*--mbuf=0;
break;
}
}
- if (Channelmode_Table[i].paracount)
+ if (cm->paracount)
{
- strlcat(pbuf, modes->extparams[i], pbuf_size);
+ strlcat(pbuf, modes->extparams[cm->letter], pbuf_size);
strlcat(pbuf, " ", pbuf_size);
}
}
@@ -731,87 +684,26 @@ void chmode_str(struct ChMode *modes, char *mbuf, char *pbuf, size_t mbuf_size,
*mbuf=0;
}
-int channellevel_to_int(char *s)
+const char *channellevel_to_string(const char *s)
{
/* Requested at http://bugs.unrealircd.org/view.php?id=3852 */
if (!strcmp(s, "none"))
- return CHFL_DEOPPED;
+ return "";
if (!strcmp(s, "voice"))
- return CHFL_VOICE;
+ return "v";
if (!strcmp(s, "halfop"))
- return CHFL_HALFOP;
+ return "h";
if (!strcmp(s, "op") || !strcmp(s, "chanop"))
- return CHFL_CHANOP;
- if (!strcmp(s, "protect") || !strcmp(s, "chanprot"))
-#ifdef PREFIX_AQ
- return CHFL_CHANADMIN;
-#else
- return CHFL_CHANOP|CHFL_CHANADMIN;
-#endif
+ return "o";
+ if (!strcmp(s, "protect") || !strcmp(s, "chanprot") || !strcmp(s, "chanadmin") || !strcmp(s, "admin"))
+ return "a";
if (!strcmp(s, "owner") || !strcmp(s, "chanowner"))
-#ifdef PREFIX_AQ
- return CHFL_CHANOWNER;
-#else
- return CHFL_CHANOP|CHFL_CHANOWNER;
-#endif
+ return "q";
- return 0; /* unknown or unsupported */
+ return NULL; /* unknown or unsupported */
}
-/* Channel flag (eg: CHFL_CHANOWNER) to SJOIN symbol (eg: *).
- * WARNING: Do not confuse SJOIN symbols with prefixes in /NAMES!
- */
-char *chfl_to_sjoin_symbol(int s)
-{
- switch(s)
- {
- case CHFL_VOICE:
- return "+";
- case CHFL_HALFOP:
- return "%";
- case CHFL_CHANOP:
- return "@";
- case CHFL_CHANADMIN:
-#ifdef PREFIX_AQ
- return "~";
-#else
- return "~@";
-#endif
- case CHFL_CHANOWNER:
-#ifdef PREFIX_AQ
- return "*";
-#else
- return "*@";
-#endif
- case CHFL_DEOPPED:
- default:
- return "";
- }
- /* NOT REACHED */
-}
-
-char chfl_to_chanmode(int s)
-{
- switch(s)
- {
- case CHFL_VOICE:
- return 'v';
- case CHFL_HALFOP:
- return 'h';
- case CHFL_CHANOP:
- return 'o';
- case CHFL_CHANADMIN:
- return 'a';
- case CHFL_CHANOWNER:
- return 'q';
- case CHFL_DEOPPED:
- default:
- return '\0';
- }
- /* NOT REACHED */
-}
-
-Policy policy_strtoval(char *s)
+Policy policy_strtoval(const char *s)
{
if (!s)
return 0;
@@ -828,7 +720,7 @@ Policy policy_strtoval(char *s)
return 0;
}
-char *policy_valtostr(Policy policy)
+const char *policy_valtostr(Policy policy)
{
if (policy == POLICY_ALLOW)
return "allow";
@@ -850,7 +742,7 @@ char policy_valtochar(Policy policy)
return '?';
}
-AllowedChannelChars allowed_channelchars_strtoval(char *str)
+AllowedChannelChars allowed_channelchars_strtoval(const char *str)
{
if (!strcmp(str, "ascii"))
return ALLOWED_CHANNELCHARS_ASCII;
@@ -861,7 +753,7 @@ AllowedChannelChars allowed_channelchars_strtoval(char *str)
return 0;
}
-char *allowed_channelchars_valtostr(AllowedChannelChars v)
+const char *allowed_channelchars_valtostr(AllowedChannelChars v)
{
switch(v)
{
@@ -879,7 +771,7 @@ char *allowed_channelchars_valtostr(AllowedChannelChars v)
}
/* Used for set::automatic-ban-target and set::manual-ban-target */
-BanTarget ban_target_strtoval(char *str)
+BanTarget ban_target_strtoval(const char *str)
{
if (!strcmp(str, "ip"))
return BAN_TARGET_IP;
@@ -897,7 +789,7 @@ BanTarget ban_target_strtoval(char *str)
}
/* Used for set::automatic-ban-target and set::manual-ban-target */
-char *ban_target_valtostr(BanTarget v)
+const char *ban_target_valtostr(BanTarget v)
{
switch(v)
{
@@ -918,7 +810,7 @@ char *ban_target_valtostr(BanTarget v)
}
}
-HideIdleTimePolicy hideidletime_strtoval(char *str)
+HideIdleTimePolicy hideidletime_strtoval(const char *str)
{
if (!strcmp(str, "never"))
return HIDE_IDLE_TIME_NEVER;
@@ -931,7 +823,7 @@ HideIdleTimePolicy hideidletime_strtoval(char *str)
return 0;
}
-char *hideidletime_valtostr(HideIdleTimePolicy v)
+const char *hideidletime_valtostr(HideIdleTimePolicy v)
{
switch(v)
{
@@ -948,7 +840,7 @@ char *hideidletime_valtostr(HideIdleTimePolicy v)
}
}
-ConfigFile *config_load(char *filename, char *displayname)
+ConfigFile *config_load(const char *filename, const char *displayname)
{
struct stat sb;
int fd;
@@ -1013,10 +905,10 @@ void config_free(ConfigFile *cfptr)
for(;cfptr;cfptr=nptr)
{
- nptr = cfptr->cf_next;
- if (cfptr->cf_entries)
- config_entry_free_all(cfptr->cf_entries);
- safe_free(cfptr->cf_filename);
+ nptr = cfptr->next;
+ if (cfptr->items)
+ config_entry_free_all(cfptr->items);
+ safe_free(cfptr->filename);
safe_free(cfptr);
}
}
@@ -1043,7 +935,7 @@ void unreal_del_quotes(char *i)
}
/** Add quotes to a line, eg some"thing becomes some\"thing - extended version */
-int unreal_add_quotes_r(char *i, char *o, size_t len)
+int unreal_add_quotes_r(const char *i, char *o, size_t len)
{
if (len == 0)
return 0;
@@ -1079,7 +971,7 @@ int unreal_add_quotes_r(char *i, char *o, size_t len)
}
/** Add quotes to a line, eg some"thing becomes some\"thing */
-char *unreal_add_quotes(char *str)
+const char *unreal_add_quotes(const char *str)
{
static char qbuf[2048];
@@ -1088,14 +980,15 @@ char *unreal_add_quotes(char *str)
return qbuf;
}
-ConfigFile *config_parse(char *filename, char *confdata){
+ConfigFile *config_parse(const char *filename, char *confdata)
+{
return config_parse_with_offset(filename, confdata, 0);
}
/* This is the internal parser, made by Chris Behrens & Fred Jacobs <2005.
* Enhanced (or mutilated) by Bram Matthys over the years (2015-2019).
*/
-ConfigFile *config_parse_with_offset(char *filename, char *confdata, unsigned int line_offset)
+ConfigFile *config_parse_with_offset(const char *filename, char *confdata, unsigned int line_offset)
{
char *ptr;
char *start;
@@ -1110,8 +1003,8 @@ ConfigFile *config_parse_with_offset(char *filename, char *confdata, unsigned in
ConditionalConfig *cc, *cc_list = NULL;
curcf = safe_alloc(sizeof(ConfigFile));
- safe_strdup(curcf->cf_filename, filename);
- lastce = &(curcf->cf_entries);
+ safe_strdup(curcf->filename, filename);
+ lastce = &(curcf->items);
curce = NULL;
cursection = NULL;
/* Replace \r's with spaces .. ugly ugly -Stskeeps */
@@ -1131,8 +1024,8 @@ ConfigFile *config_parse_with_offset(char *filename, char *confdata, unsigned in
break;
}
*lastce = curce;
- lastce = &(curce->ce_next);
- curce->ce_fileposend = (ptr - confdata);
+ lastce = &(curce->next);
+ curce->file_position_end = (ptr - confdata);
curce = NULL;
break;
case '{':
@@ -1144,7 +1037,7 @@ ConfigFile *config_parse_with_offset(char *filename, char *confdata, unsigned in
errors++;
continue;
}
- else if (curce->ce_entries)
+ else if (curce->items)
{
config_error("%s:%i: New section start but previous section did not end properly. "
"Check line %d and the line(s) before, you are likely missing a '};' there.\n",
@@ -1152,8 +1045,8 @@ ConfigFile *config_parse_with_offset(char *filename, char *confdata, unsigned in
errors++;
continue;
}
- curce->ce_sectlinenum = linenumber;
- lastce = &(curce->ce_entries);
+ curce->section_linenumber = linenumber;
+ lastce = &(curce->items);
cursection = curce;
curce = NULL;
break;
@@ -1176,20 +1069,20 @@ ConfigFile *config_parse_with_offset(char *filename, char *confdata, unsigned in
continue;
}
curce = cursection;
- cursection->ce_fileposend = (ptr - confdata);
- cursection = cursection->ce_prevlevel;
+ cursection->file_position_end = (ptr - confdata);
+ cursection = cursection->parent;
if (!cursection)
- lastce = &(curcf->cf_entries);
+ lastce = &(curcf->items);
else
- lastce = &(cursection->ce_entries);
- for(;*lastce;lastce = &((*lastce)->ce_next))
+ lastce = &(cursection->items);
+ for(;*lastce;lastce = &((*lastce)->next))
continue;
if (*(ptr+1) != ';')
{
/* Simulate closing ; so you can get away with } instead of ugly }; */
*lastce = curce;
- lastce = &(curce->ce_next);
- curce->ce_fileposend = (ptr - confdata);
+ lastce = &(curce->next);
+ curce->file_position_end = (ptr - confdata);
curce = NULL;
}
break;
@@ -1239,17 +1132,21 @@ ConfigFile *config_parse_with_offset(char *filename, char *confdata, unsigned in
}
}
break;
+ case '\'':
+ if (curce)
+ curce->escaped = 1;
+ /* fallthrough */
case '\"':
- if (curce && curce->ce_varlinenum != linenumber && cursection)
+ if (curce && curce->line_number != linenumber && cursection)
{
config_error("%s:%i: Missing semicolon (';') at end of line. "
"Line %d must end with a ; character\n",
- filename, curce->ce_varlinenum, curce->ce_varlinenum);
+ filename, curce->line_number, curce->line_number);
errors++;
*lastce = curce;
- lastce = &(curce->ce_next);
- curce->ce_fileposend = (ptr - confdata);
+ lastce = &(curce->next);
+ curce->file_position_end = (ptr - confdata);
curce = NULL;
}
@@ -1258,14 +1155,18 @@ ConfigFile *config_parse_with_offset(char *filename, char *confdata, unsigned in
{
if (*ptr == '\\')
{
- if ((ptr[1] == '\\') || (ptr[1] == '"'))
+ if (strchr("\\\"'", ptr[1]))
{
/* \\ or \" in config file (escaped) */
ptr++; /* skip */
continue;
}
}
- else if ((*ptr == '\"') || (*ptr == '\n'))
+ else if (*ptr == '\n')
+ break;
+ else if (curce && curce->escaped && (*ptr == '\''))
+ break;
+ else if ((!curce || !curce->escaped) && (*ptr == '"'))
break;
}
if (!*ptr || (*ptr == '\n'))
@@ -1279,7 +1180,7 @@ ConfigFile *config_parse_with_offset(char *filename, char *confdata, unsigned in
}
if (curce)
{
- if (curce->ce_vardata)
+ if (curce->value)
{
config_error("%s:%i: Extra data detected. Perhaps missing a ';' or one too many?\n",
filename, linenumber);
@@ -1287,22 +1188,22 @@ ConfigFile *config_parse_with_offset(char *filename, char *confdata, unsigned in
}
else
{
- safe_strldup(curce->ce_vardata, start, ptr-start+1);
- preprocessor_replace_defines(&curce->ce_vardata, curce);
- unreal_del_quotes(curce->ce_vardata);
+ safe_strldup(curce->value, start, ptr-start+1);
+ preprocessor_replace_defines(&curce->value, curce);
+ unreal_del_quotes(curce->value);
}
}
else
{
curce = safe_alloc(sizeof(ConfigEntry));
- curce->ce_varlinenum = linenumber;
- curce->ce_fileptr = curcf;
- curce->ce_prevlevel = cursection;
- curce->ce_fileposstart = (start - confdata);
- safe_strldup(curce->ce_varname, start, ptr-start+1);
- preprocessor_replace_defines(&curce->ce_varname, curce);
- unreal_del_quotes(curce->ce_varname);
- preprocessor_cc_duplicate_list(cc_list, &curce->ce_cond);
+ curce->line_number = linenumber;
+ curce->file = curcf;
+ curce->parent = cursection;
+ curce->file_position_start = (start - confdata);
+ safe_strldup(curce->name, start, ptr-start+1);
+ preprocessor_replace_defines(&curce->name, curce);
+ unreal_del_quotes(curce->name);
+ preprocessor_cc_duplicate_list(cc_list, &curce->conditional_config);
}
break;
case '\n':
@@ -1372,11 +1273,11 @@ ConfigFile *config_parse_with_offset(char *filename, char *confdata, unsigned in
if (curce)
config_error("%s: End of file reached but directive or block at line %i did not end properly. "
"Perhaps a missing ; (semicolon) somewhere?\n",
- filename, curce->ce_varlinenum);
+ filename, curce->line_number);
else if (cursection)
config_error("%s: End of file reached but the section which starts at line %i did never end properly. "
"Perhaps a missing }; ?\n",
- filename, cursection->ce_sectlinenum);
+ filename, cursection->section_linenumber);
else
config_error("%s: Unexpected end of file. Some line or block did not end properly. "
"Look for any missing } and };\n", filename);
@@ -1387,7 +1288,7 @@ ConfigFile *config_parse_with_offset(char *filename, char *confdata, unsigned in
}
if (curce)
{
- if (curce->ce_vardata)
+ if (curce->value)
{
config_error("%s:%i: Extra data detected. Check for a missing ; character at or around line %d\n",
filename, linenumber, linenumber-1);
@@ -1395,23 +1296,23 @@ ConfigFile *config_parse_with_offset(char *filename, char *confdata, unsigned in
}
else
{
- safe_strldup(curce->ce_vardata, start, ptr-start+1);
- preprocessor_replace_defines(&curce->ce_vardata, curce);
+ safe_strldup(curce->value, start, ptr-start+1);
+ preprocessor_replace_defines(&curce->value, curce);
}
}
else
{
curce = safe_alloc(sizeof(ConfigEntry));
memset(curce, 0, sizeof(ConfigEntry));
- curce->ce_varlinenum = linenumber;
- curce->ce_fileptr = curcf;
- curce->ce_prevlevel = cursection;
- curce->ce_fileposstart = (start - confdata);
- safe_strldup(curce->ce_varname, start, ptr-start+1);
- preprocessor_replace_defines(&curce->ce_varname, curce);
- if (curce->ce_cond)
- abort(); // hmm this can be reached? FIXME!
- preprocessor_cc_duplicate_list(cc_list, &curce->ce_cond);
+ curce->line_number = linenumber;
+ curce->file = curcf;
+ curce->parent = cursection;
+ curce->file_position_start = (start - confdata);
+ safe_strldup(curce->name, start, ptr-start+1);
+ preprocessor_replace_defines(&curce->name, curce);
+ if (curce->conditional_config)
+ abort();
+ preprocessor_cc_duplicate_list(cc_list, &curce->conditional_config);
}
if ((*ptr == ';') || (*ptr == '\n'))
ptr--;
@@ -1425,7 +1326,7 @@ breakout:
{
config_error("%s: End of file reached but directive or block at line %i did not end properly. "
"Perhaps a missing ; (semicolon) somewhere?\n",
- filename, curce->ce_varlinenum);
+ filename, curce->line_number);
errors++;
config_entry_free_all(curce);
}
@@ -1433,7 +1334,7 @@ breakout:
{
config_error("%s: End of file reached but the section which starts at line %i did never end properly. "
"Perhaps a missing }; ?\n",
- filename, cursection->ce_sectlinenum);
+ filename, cursection->section_linenumber);
errors++;
}
@@ -1455,13 +1356,13 @@ void config_entry_free_all(ConfigEntry *ce)
for(;ce;ce=nptr)
{
- nptr = ce->ce_next;
- if (ce->ce_entries)
- config_entry_free_all(ce->ce_entries);
- safe_free(ce->ce_varname);
- safe_free(ce->ce_vardata);
- if (ce->ce_cond)
- preprocessor_cc_free_list(ce->ce_cond);
+ nptr = ce->next;
+ if (ce->items)
+ config_entry_free_all(ce->items);
+ safe_free(ce->name);
+ safe_free(ce->value);
+ if (ce->conditional_config)
+ preprocessor_cc_free_list(ce->conditional_config);
safe_free(ce);
}
}
@@ -1471,21 +1372,21 @@ void config_entry_free_all(ConfigEntry *ce)
*/
void config_entry_free(ConfigEntry *ce)
{
- if (ce->ce_entries)
- config_entry_free_all(ce->ce_entries);
- safe_free(ce->ce_varname);
- safe_free(ce->ce_vardata);
- if (ce->ce_cond)
- preprocessor_cc_free_list(ce->ce_cond);
+ if (ce->items)
+ config_entry_free_all(ce->items);
+ safe_free(ce->name);
+ safe_free(ce->value);
+ if (ce->conditional_config)
+ preprocessor_cc_free_list(ce->conditional_config);
safe_free(ce);
}
-ConfigEntry *config_find_entry(ConfigEntry *ce, char *name)
+ConfigEntry *config_find_entry(ConfigEntry *ce, const char *name)
{
ConfigEntry *cep;
- for (cep = ce; cep; cep = cep->ce_next)
- if (cep->ce_varname && !strcmp(cep->ce_varname, name))
+ for (cep = ce; cep; cep = cep->next)
+ if (cep->name && !strcmp(cep->name, name))
break;
return cep;
}
@@ -1501,8 +1402,7 @@ void config_error(FORMAT_STRING(const char *format), ...)
va_end(ap);
if ((ptr = strchr(buffer, '\n')) != NULL)
*ptr = '\0';
- ircd_log(LOG_ERROR, "config error: %s", buffer);
- sendto_realops("error: %s", buffer);
+ unreal_log_raw(ULOG_ERROR, "config", "CONFIG_ERROR_GENERIC", NULL, buffer);
if (remote_rehash_client)
sendnotice(remote_rehash_client, "error: %s", buffer);
/* We cannot live with this */
@@ -1560,8 +1460,7 @@ void config_status(FORMAT_STRING(const char *format), ...)
va_end(ap);
if ((ptr = strchr(buffer, '\n')) != NULL)
*ptr = '\0';
- ircd_log(LOG_ERROR, "%s", buffer);
- sendto_realops("%s", buffer);
+ unreal_log_raw(ULOG_INFO, "config", "CONFIG_INFO_GENERIC", NULL, buffer);
if (remote_rehash_client)
sendnotice(remote_rehash_client, "%s", buffer);
}
@@ -1577,8 +1476,7 @@ void config_warn(FORMAT_STRING(const char *format), ...)
va_end(ap);
if ((ptr = strchr(buffer, '\n')) != NULL)
*ptr = '\0';
- ircd_log(LOG_ERROR, "[warning] %s", buffer);
- sendto_realops("[warning] %s", buffer);
+ unreal_log_raw(ULOG_WARNING, "config", "CONFIG_WARNING_GENERIC", NULL, buffer);
if (remote_rehash_client)
sendnotice(remote_rehash_client, "[warning] %s", buffer);
}
@@ -1593,50 +1491,38 @@ int config_test_openfile(ConfigEntry *cep, int flags, mode_t mode, const char *e
{
int fd;
- if(!cep->ce_vardata)
+ if (!cep->value)
{
- if(fatal)
+ if (fatal)
config_error("%s:%i: %s: : no file specified",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum,
+ cep->file->filename,
+ cep->line_number,
entry);
else
config_warn("%s:%i: %s: : no file specified",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum,
+ cep->file->filename,
+ cep->line_number,
entry);
return 1;
}
/* There's not much checking that can be done for asynchronously downloaded files */
-#ifdef USE_LIBCURL
- if(url_is_valid(cep->ce_vardata))
+ if (url_is_valid(cep->value))
{
- if(allow_url)
+ if (allow_url)
return 0;
/* but we can check if a URL is used wrongly :-) */
config_warn("%s:%i: %s: %s: URL used where not allowed",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum,
- entry, cep->ce_vardata);
- if(fatal)
+ cep->file->filename,
+ cep->line_number,
+ entry, cep->value);
+ if (fatal)
return 1;
else
return 0;
}
-#else
- if (strstr(cep->ce_vardata, "://"))
- {
- config_error("%s:%d: %s: UnrealIRCd was not compiled with remote includes support "
- "so you cannot use URLs here.",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum,
- entry);
- return 1;
- }
-#endif /* USE_LIBCURL */
/*
* Make sure that files are created with the correct mode. This is
@@ -1645,25 +1531,25 @@ int config_test_openfile(ConfigEntry *cep, int flags, mode_t mode, const char *e
* and that we deal with all of the bugs that come with complexity.
* The only files we may be creating are the tunefile and pidfile so far.
*/
- if(flags & O_CREAT)
- fd = open(cep->ce_vardata, flags, mode);
+ if (flags & O_CREAT)
+ fd = open(cep->value, flags, mode);
else
- fd = open(cep->ce_vardata, flags);
- if(fd == -1)
+ fd = open(cep->value, flags);
+ if (fd == -1)
{
- if(fatal)
+ if (fatal)
config_error("%s:%i: %s: %s: %s",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum,
+ cep->file->filename,
+ cep->line_number,
entry,
- cep->ce_vardata,
+ cep->value,
strerror(errno));
else
config_warn("%s:%i: %s: %s: %s",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum,
+ cep->file->filename,
+ cep->line_number,
entry,
- cep->ce_vardata,
+ cep->value,
strerror(errno));
return 1;
}
@@ -1673,16 +1559,16 @@ int config_test_openfile(ConfigEntry *cep, int flags, mode_t mode, const char *e
int config_is_blankorempty(ConfigEntry *cep, const char *block)
{
- if (!cep->ce_vardata)
+ if (!cep->value)
{
- config_error_empty(cep->ce_fileptr->cf_filename, cep->ce_varlinenum, block,
- cep->ce_varname);
+ config_error_empty(cep->file->filename, cep->line_number, block,
+ cep->name);
return 1;
}
return 0;
}
-ConfigCommand *config_binary_search(char *cmd) {
+ConfigCommand *config_binary_search(const char *cmd) {
int start = 0;
int stop = ARRAY_SIZEOF(_ConfigCommands)-1;
int mid;
@@ -1702,7 +1588,8 @@ ConfigCommand *config_binary_search(char *cmd) {
void free_iConf(Configuration *i)
{
- safe_free(i->dns_bindip);
+ FloodSettings *f, *f_next;
+
safe_free(i->link_bindip);
safe_free(i->kline_address);
safe_free(i->gline_address);
@@ -1711,7 +1598,6 @@ void free_iConf(Configuration *i)
safe_free(i->oper_auto_join_chans);
safe_free(i->allow_user_stats);
// allow_user_stats_ext is freed elsewhere
- safe_free(i->egd_path);
safe_free(i->static_quit);
safe_free(i->static_part);
free_tls_options(i->tls_options);
@@ -1725,6 +1611,7 @@ void free_iConf(Configuration *i)
safe_free(i->restrict_channelmodes);
safe_free(i->restrict_extendedbans);
safe_free(i->channel_command_prefix);
+ safe_free(i->level_on_join);
safe_free(i->spamfilter_ban_reason);
safe_free(i->spamfilter_virus_help_channel);
// spamexcept is freed elsewhere
@@ -1734,25 +1621,30 @@ void free_iConf(Configuration *i)
safe_free(i->reject_message_unauthorized);
safe_free(i->reject_message_kline);
safe_free(i->reject_message_gline);
- // network struct:
- safe_free(i->network.x_ircnetwork);
- safe_free(i->network.x_ircnet005);
- safe_free(i->network.x_defserv);
- safe_free(i->network.x_services_name);
- safe_free(i->network.x_hidden_host);
- safe_free(i->network.x_prefix_quit);
- safe_free(i->network.x_helpchan);
- safe_free(i->network.x_stats_server);
- safe_free(i->network.x_sasl_server);
+ safe_free(i->network_name);
+ safe_free(i->network_name_005);
+ safe_free(i->default_server);
+ safe_free(i->services_name);
+ safe_free(i->cloak_prefix);
+ safe_free(i->prefix_quit);
+ safe_free(i->helpchan);
+ safe_free(i->stats_server);
+ safe_free(i->sasl_server);
+ // anti-flood:
+ for (f = i->floodsettings; f; f = f_next)
+ {
+ f_next = f->next;
+ free_floodsettings(f);
+ }
+ i->floodsettings = NULL;
}
-int config_test();
-
void config_setdefaultsettings(Configuration *i)
{
char tmp[512];
- safe_strdup(i->oper_snomask, SNO_DEFOPER);
+ safe_strdup(i->oper_snomask, OPER_SNOMASKS);
+ i->server_notice_colors = 1;
i->ident_read_timeout = 7;
i->ident_connect_timeout = 3;
i->ban_version_tkl_time = 86400; /* 1d */
@@ -1765,12 +1657,11 @@ void config_setdefaultsettings(Configuration *i)
i->maxchannelsperuser = 10;
i->maxdccallow = 10;
safe_strdup(i->channel_command_prefix, "`!.");
- conf_channelmodes("+nt", &i->modes_on_join, 0);
i->conn_modes = set_usermode("+ixw");
i->check_target_nick_bans = 1;
i->maxbans = 60;
i->maxbanlength = 2048;
- i->level_on_join = CHFL_CHANOP;
+ safe_strdup(i->level_on_join, "o");
i->watch_away_notification = 1;
i->uhnames = 1;
i->ping_cookie = 1;
@@ -1783,10 +1674,10 @@ void config_setdefaultsettings(Configuration *i)
i->kick_length = 307;
i->quit_length = 307;
safe_strdup(i->link_bindip, "*");
- safe_strdup(i->network.x_hidden_host, "Clk");
+ safe_strdup(i->cloak_prefix, "Clk");
if (!ipv6_capable())
DISABLE_IPV6 = 1;
- safe_strdup(i->network.x_prefix_quit, "Quit");
+ safe_strdup(i->prefix_quit, "Quit");
i->max_unknown_connections_per_ip = 3;
i->handshake_timeout = 30;
i->sasl_timeout = 15;
@@ -1807,6 +1698,7 @@ void config_setdefaultsettings(Configuration *i)
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 */
config_parse_flood_generic("10:15", i, "known-users", FLD_CONVERSATIONS); /* 10 users, new user every 15s */
+ config_parse_flood_generic("180:750", i, "known-users", FLD_LAG_PENALTY); /* 180 bytes / 750 msec */
/* - 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 */
@@ -1814,8 +1706,9 @@ void config_setdefaultsettings(Configuration *i)
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 */
config_parse_flood_generic("4:15", i, "unknown-users", FLD_CONVERSATIONS); /* 4 users, new user every 15s */
+ config_parse_flood_generic("90:1000", i, "unknown-users", FLD_LAG_PENALTY); /* 90 bytes / 1000 msec */
- /* SSL/TLS options */
+ /* TLS options */
i->tls_options = safe_alloc(sizeof(TLSOptions));
snprintf(tmp, sizeof(tmp), "%s/tls/server.cert.pem", CONFDIR);
safe_strdup(i->tls_options->certificate_file, tmp);
@@ -1862,19 +1755,8 @@ void config_setdefaultsettings(Configuration *i)
i->hide_idle_time = HIDE_IDLE_TIME_OPER_USERMODE;
i->who_limit = 100;
-}
-static void make_default_logblock(void)
-{
- ConfigItem_log *ca = safe_alloc(sizeof(ConfigItem_log));
-
- config_status("No log { } block found -- logging everything to 'ircd.log'");
-
- safe_strdup(ca->file, "ircd.log");
- convert_to_absolute_path(&ca->file, LOGDIR);
- ca->flags |= LOG_CHGCMDS|LOG_CLIENT|LOG_ERROR|LOG_KILL|LOG_KLINE|LOG_OPER|LOG_OVERRIDE|LOG_SACMDS|LOG_SERVER|LOG_SPAMFILTER|LOG_TKL;
- ca->logfd = -1;
- AddListItem(ca, conf_log);
+ i->named_extended_bans = 1;
}
/** Similar to config_setdefaultsettings but this one is applied *AFTER*
@@ -1886,13 +1768,20 @@ void postconf_defaults(void)
TKL *tk;
char *encoded;
+ if (!iConf.modes_on_join_set)
+ {
+ /* We could not do this in config_setdefaultsettings()
+ * because the channel mode modules were not initialized yet.
+ */
+ conf_channelmodes("+nt", &iConf.modes_on_join);
+ }
if (!iConf.plaintext_policy_user_message)
{
/* The message depends on whether it's reject or warn.. */
if (iConf.plaintext_policy_user == POLICY_DENY)
- addmultiline(&iConf.plaintext_policy_user_message, "Insecure connection. Please reconnect using SSL/TLS.");
+ addmultiline(&iConf.plaintext_policy_user_message, "Insecure connection. Please reconnect using TLS.");
else if (iConf.plaintext_policy_user == POLICY_WARN)
- addmultiline(&iConf.plaintext_policy_user_message, "WARNING: Insecure connection. Please consider using SSL/TLS.");
+ addmultiline(&iConf.plaintext_policy_user_message, "WARNING: Insecure connection. Please consider using TLS.");
}
if (!iConf.plaintext_policy_oper_message)
@@ -1900,76 +1789,32 @@ void postconf_defaults(void)
/* The message depends on whether it's reject or warn.. */
if (iConf.plaintext_policy_oper == POLICY_DENY)
{
- addmultiline(&iConf.plaintext_policy_oper_message, "You need to use a secure connection (SSL/TLS) in order to /OPER.");
+ addmultiline(&iConf.plaintext_policy_oper_message, "You need to use a secure connection (TLS) in order to /OPER.");
addmultiline(&iConf.plaintext_policy_oper_message, "See https://www.unrealircd.org/docs/FAQ#oper-requires-tls");
}
else if (iConf.plaintext_policy_oper == POLICY_WARN)
- addmultiline(&iConf.plaintext_policy_oper_message, "WARNING: You /OPER'ed up from an insecure connection. Please consider using SSL/TLS.");
+ addmultiline(&iConf.plaintext_policy_oper_message, "WARNING: You /OPER'ed up from an insecure connection. Please consider using TLS.");
}
if (!iConf.outdated_tls_policy_user_message)
{
/* The message depends on whether it's reject or warn.. */
if (iConf.outdated_tls_policy_user == POLICY_DENY)
- safe_strdup(iConf.outdated_tls_policy_user_message, "Your IRC client is using an outdated SSL/TLS protocol or ciphersuite ($protocol-$cipher). Please upgrade your IRC client.");
+ safe_strdup(iConf.outdated_tls_policy_user_message, "Your IRC client is using an outdated TLS protocol or ciphersuite ($protocol-$cipher). Please upgrade your IRC client.");
else if (iConf.outdated_tls_policy_user == POLICY_WARN)
- safe_strdup(iConf.outdated_tls_policy_user_message, "WARNING: Your IRC client is using an outdated SSL/TLS protocol or ciphersuite ($protocol-$cipher). Please upgrade your IRC client.");
+ safe_strdup(iConf.outdated_tls_policy_user_message, "WARNING: Your IRC client is using an outdated TLS protocol or ciphersuite ($protocol-$cipher). Please upgrade your IRC client.");
}
if (!iConf.outdated_tls_policy_oper_message)
{
/* The message depends on whether it's reject or warn.. */
if (iConf.outdated_tls_policy_oper == POLICY_DENY)
- safe_strdup(iConf.outdated_tls_policy_oper_message, "Your IRC client is using an outdated SSL/TLS protocol or ciphersuite ($protocol-$cipher). Please upgrade your IRC client.");
+ safe_strdup(iConf.outdated_tls_policy_oper_message, "Your IRC client is using an outdated TLS protocol or ciphersuite ($protocol-$cipher). Please upgrade your IRC client.");
else if (iConf.outdated_tls_policy_oper == POLICY_WARN)
- safe_strdup(iConf.outdated_tls_policy_oper_message, "WARNING: Your IRC client is using an outdated SSL/TLS protocol or ciphersuite ($protocol-$cipher). Please upgrade your IRC client.");
+ safe_strdup(iConf.outdated_tls_policy_oper_message, "WARNING: Your IRC client is using an outdated TLS protocol or ciphersuite ($protocol-$cipher). Please upgrade your IRC client.");
}
- /* We got a chicken-and-egg problem here.. antries added without reason or ban-time
- * field should use the config default (set::spamfilter::ban-reason/ban-time) but
- * this isn't (or might not) be known yet when parsing spamfilter entries..
- * so we do a VERY UGLY mass replace here.. unless someone else has a better idea.
- */
-
- encoded = unreal_encodespace(SPAMFILTER_BAN_REASON);
- if (!encoded)
- abort(); /* hack to trace 'impossible' bug... */
- // FIXME: remove this stuff with ~server~, why not just use -config-
- // which is more meaningful.
- for (tk = tklines[tkl_hash('q')]; tk; tk = tk->next)
- {
- if (tk->type != TKL_NAME)
- continue;
- if (!tk->set_by)
- {
- if (me.name[0] != '\0')
- safe_strdup(tk->set_by, me.name);
- else
- safe_strdup(tk->set_by, conf_me->name ? conf_me->name : "~server~");
- }
- }
-
- for (tk = tklines[tkl_hash('f')]; tk; tk = tk->next)
- {
- if (tk->type != TKL_SPAMF)
- continue; /* global entry or something else.. */
- if (!strcmp(tk->ptr.spamfilter->tkl_reason, ""))
- {
- safe_strdup(tk->ptr.spamfilter->tkl_reason, encoded);
- tk->ptr.spamfilter->tkl_duration = SPAMFILTER_BAN_TIME;
- }
- /* This one is even more ugly, but our config crap is VERY confusing :[ */
- if (!tk->set_by)
- {
- if (me.name[0] != '\0')
- safe_strdup(tk->set_by, me.name);
- else
- safe_strdup(tk->set_by, conf_me->name ? conf_me->name : "~server~");
- }
- }
-
- if (!conf_log)
- make_default_logblock();
+ postconf_defaults_log_block();
}
void postconf_fixes(void)
@@ -2007,7 +1852,7 @@ RealCommand *cmptr;
* has been read and almost all values have been set. This is to deal with
* things like adding a default log { } block if there is none and that kind
* of things.
- * This function is called by init_conf(), both on boot and on rehash.
+ * This function is called by config_test(), both on boot and on rehash.
*/
void postconf(void)
{
@@ -2016,6 +1861,11 @@ void postconf(void)
do_weird_shun_stuff();
isupport_init(); /* for all the 005 values that changed.. */
tls_check_expiry(NULL);
+
+#if OPENSSL_VERSION_NUMBER >= 0x10101000L
+ if (loop.rehashing)
+ reinit_tls();
+#endif
}
int isanyserverlinked(void)
@@ -2044,41 +1894,11 @@ void applymeblock(void)
strlcpy(me.id, conf_me->sid, sizeof(me.id));
}
-void upgrade_conf_to_34(void)
-{
- config_error("******************************************************************");
- config_error("This *seems* an UnrealIRCd 3.2.x configuration file.");
-
-#ifdef _WIN32
- if (!IsService)
- config_error("In next screen you will be prompted to automatically upgrade the configuration file(s).");
- else
- {
- config_error("We offer a configuration file converter to convert 3.2.x conf's to 4.x, however this "
- "is not available when running as a service. If you want to use it, make UnrealIRCd "
- "run in GUI mode by running 'unreal uninstall'. Then start UnrealIRCd.exe and when "
- "it prompts you to convert the configuration click 'Yes'. Check if UnrealIRCd boots properly. "
- "Once everything is looking good you can run 'unreal install' to make UnrealIRCd run "
- "as a service again."); /* TODO: make this unnecessary :D */
- }
-#else
- config_error("To upgrade it to the new 4.x format, run: ./unrealircd upgrade-conf");
-#endif
-
- config_error("******************************************************************");
- /* TODO: win32 may require a different error */
-}
-
-/** Reset config tests (before running the config test) */
-void config_test_reset(void)
-{
-}
-
/** Run config test and all post config tests. */
int config_test_all(void)
{
- if ((config_test() < 0) || (callbacks_check() < 0) || (efunctions_check() < 0) ||
- reloadable_perm_module_unloaded() || !tls_tests())
+ if ((config_test_blocks() < 0) || (callbacks_check() < 0) || (efunctions_check() < 0) ||
+ reloadable_perm_module_unloaded() || !tls_tests() || !log_tests())
{
return 0;
}
@@ -2101,19 +1921,19 @@ int config_loadmodules(void)
int fatal_ret = 0, ret;
- for (cfptr = conf; cfptr; cfptr = cfptr->cf_next)
+ for (cfptr = conf; cfptr; cfptr = cfptr->next)
{
if (config_verbose > 1)
- config_status("Testing %s", cfptr->cf_filename);
- for (ce = cfptr->cf_entries; ce; ce = ce->ce_next)
+ config_status("Testing %s", cfptr->filename);
+ for (ce = cfptr->items; ce; ce = ce->next)
{
- if (!strcmp(ce->ce_varname, "loadmodule"))
+ if (!strcmp(ce->name, "loadmodule"))
{
- if (ce->ce_cond)
+ if (ce->conditional_config)
{
config_error("%s:%d: Currently you cannot have a 'loadmodule' statement "
"within an @if block, sorry.",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
return 0;
}
ret = _conf_loadmodule(cfptr, ce);
@@ -2139,262 +1959,299 @@ int config_loadmodules(void)
return 1; /* SUCCESS */
}
-int init_conf(char *rootconf, int rehash)
+/** Reject the configuration load.
+ * This is called both from boot and from rehash.
+ */
+void config_load_failed(void)
{
- char *old_pid_file = NULL;
+ if (conf)
+ unreal_log(ULOG_ERROR, "config", "CONFIG_NOT_LOADED", NULL, "IRCd configuration failed to load");
+ Unload_all_testing_modules();
+ free_all_config_resources();
+ config_free(conf);
+ conf = NULL;
+ free_iConf(&tempiConf);
+#ifdef _WIN32
+ if (!loop.rehashing)
+ win_error(); /* GUI popup */
+#endif
+}
+
+int config_read_start(void)
+{
+ int ret;
config_status("Loading IRCd configuration..");
+ loop.config_load_failed = 0;
+
if (conf)
{
config_error("%s:%i - Someone forgot to clean up", __FILE__, __LINE__);
return -1;
}
+
+ /* We set this to 1 because otherwise we may call rehash_internal()
+ * already from config_read_file() which is too soon (race).
+ */
+ loop.rehash_download_busy = 1;
+ add_config_resource(configfile, RESOURCE_INCLUDE, NULL);
+ ret = config_read_file(configfile, configfile);
+ loop.rehash_download_busy = 0;
+ if (ret < 0)
+ {
+ config_load_failed();
+ return -1;
+ }
+ return 1;
+}
+
+int is_config_read_finished(void)
+{
+ ConfigResource *rs;
+
+ if (loop.rehash_download_busy)
+ return 0;
+
+ for (rs = config_resources; rs; rs = rs->next)
+ {
+ if (rs->type & RESOURCE_DLQUEUED)
+ {
+ //config_status("Waiting for %s...", rs->url);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int config_test(void)
+{
+ char *old_pid_file = NULL;
+
+ if (loop.config_load_failed)
+ {
+ /* An error was already printed to the user.
+ * This happens in case of a failed loaded remote URL
+ */
+ config_load_failed();
+ return -1;
+ }
+
+ config_status("Testing IRCd configuration..");
+
memset(&tempiConf, 0, sizeof(iConf));
memset(&settings, 0, sizeof(settings));
memset(&requiredstuff, 0, sizeof(requiredstuff));
memset(&nicklengths, 0, sizeof(nicklengths));
config_setdefaultsettings(&tempiConf);
clicap_pre_rehash();
+ log_pre_rehash();
free_config_defines();
- /*
- * the rootconf must be listed in the conf_include for include
- * recursion prevention code and sanity checking code to be
- * made happy :-). Think of it as us implicitly making an
- * in-memory config file that looks like:
- *
- * include "unrealircd.conf";
- */
- add_include(rootconf, "[thin air]", -1);
- if ((load_conf(rootconf, rootconf) > 0) && config_loadmodules())
- {
- preprocessor_resolve_conditionals_all(PREPROCESSOR_PHASE_MODULE);
- config_test_reset();
- if (!config_test_all())
- {
- config_error("IRCd configuration failed to pass testing");
-#ifdef _WIN32
- if (!rehash)
- win_error();
-#endif
- Unload_all_testing_modules();
- unload_notloaded_includes();
- config_free(conf);
- conf = NULL;
- free_iConf(&tempiConf);
- return -1;
- }
- callbacks_switchover();
- efunctions_switchover();
- set_targmax_defaults();
- set_security_group_defaults();
- if (rehash)
- {
- Hook *h;
- safe_strdup(old_pid_file, conf_files->pid_file);
- unrealdns_delasyncconnects();
- config_rehash();
- Unload_all_loaded_modules();
- /* Notify permanent modules of the rehash */
- for (h = Hooks[HOOKTYPE_REHASH]; h; h = h->next)
- {
- if (!h->owner)
- continue;
- if (!(h->owner->options & MOD_OPT_PERM))
- continue;
- (*(h->func.intfunc))();
- }
- unload_loaded_includes();
- }
- load_includes();
- Init_all_testing_modules();
- if (config_run() < 0)
- {
- config_error("Bad case of config errors. Server will now die. This really shouldn't happen");
-#ifdef _WIN32
- if (!rehash)
- win_error();
-#endif
- abort();
- }
- applymeblock();
- if (old_pid_file && strcmp(old_pid_file, conf_files->pid_file))
- {
- sendto_ops("pidfile is being rewritten to %s, please delete %s",
- conf_files->pid_file,
- old_pid_file);
- write_pidfile();
- }
- safe_free(old_pid_file);
- }
- else
+ if (!config_loadmodules())
{
- config_error("IRCd configuration failed to load");
- Unload_all_testing_modules();
- unload_notloaded_includes();
- config_free(conf);
- conf = NULL;
- free_iConf(&tempiConf);
-#ifdef _WIN32
- if (!rehash)
- win_error();
-#endif
+ config_load_failed();
return -1;
}
+
+ preprocessor_resolve_conditionals_all(PREPROCESSOR_PHASE_MODULE);
+
+ if (!config_test_all())
+ {
+ config_error("IRCd configuration failed to pass testing");
+ config_load_failed();
+ return -1;
+ }
+ callbacks_switchover();
+ efunctions_switchover();
+ set_targmax_defaults();
+ set_security_group_defaults();
+ if (loop.rehashing)
+ {
+ Hook *h;
+ safe_strdup(old_pid_file, conf_files->pid_file);
+ unrealdns_delasyncconnects();
+ config_rehash();
+ Unload_all_loaded_modules();
+
+ /* Notify permanent modules of the rehash */
+ for (h = Hooks[HOOKTYPE_REHASH]; h; h = h->next)
+ {
+ if (!h->owner)
+ continue;
+ if (!(h->owner->options & MOD_OPT_PERM))
+ continue;
+ (*(h->func.intfunc))();
+ }
+ }
+ config_pre_run_log();
+
+ Init_all_testing_modules();
+
+ if (config_run_blocks() < 0)
+ {
+ config_error("Bad case of config errors. Server will now die. This really shouldn't happen");
+#ifdef _WIN32
+ if (!loop.rehashing)
+ win_error();
+#endif
+ abort();
+ }
+
+ applymeblock();
+
+ if (old_pid_file && strcmp(old_pid_file, conf_files->pid_file))
+ {
+ write_pidfile();
+ unlink(old_pid_file);
+ }
+ safe_free(old_pid_file);
+
config_free(conf);
conf = NULL;
- if (rehash)
+ if (loop.rehashing)
{
module_loadall();
- RunHook0(HOOKTYPE_REHASH_COMPLETE);
+ RunHook(HOOKTYPE_REHASH_COMPLETE);
}
postconf();
- config_status("Configuration loaded.");
+ unreal_log(ULOG_INFO, "config", "CONFIG_LOADED", NULL, "Configuration loaded");
clicap_post_rehash();
unload_all_unused_mtag_handlers();
return 0;
}
+void config_parse_and_queue_urls(ConfigEntry *ce)
+{
+ for (; ce; ce = ce->next)
+ {
+ if (loop.config_load_failed)
+ break;
+ if (ce->name && !strcmp(ce->name, "include"))
+ continue; /* handled elsewhere */
+ if (ce->value && !ce->escaped && url_is_valid(ce->value))
+ add_config_resource(ce->value, 0, ce);
+ if (ce->items)
+ config_parse_and_queue_urls(ce->items);
+ }
+}
+
/**
- * Processes filename as part of the IRCd's configuration.
+ * Read configuration file into ConfigEntry items and add it to the 'conf'
+ * list. This checks the file for parse errors, but doesn't do much
+ * otherwise. Only: module blacklist checking and checking for "include"
+ * items to see if we need to read and parse more configuration files
+ * that are included from this one.
*
- * One _must_ call add_include() or add_remote_include() before
- * calling load_conf(). This way, include recursion may be detected
- * and reported to the user as an error instead of causing the IRCd to
- * hang in an infinite recursion, eat up memory, and eventually
- * overflow its stack ;-). (reported by warg).
- *
- * This function will set INCLUDE_USED on the config_include list
- * entry if the config file loaded without error.
+ * One _must_ call add_config_resource() before calling config_read_file().
+ * This way, include recursion may be detected and reported to the user
+ * as an error instead of causing the IRCd to hang in an infinite
+ * recursion, eat up memory, and eventually overflow its stack ;-).
*
* @param filename the file where the conf may be read from
- * @param original_path the path or URL used to refer to this file.
+ * @param display_name The path or URL used to refer to this file.
* (mostly to support remote includes' URIs for recursive include detection).
* @return 1 on success, a negative number on error
*/
-int load_conf(char *filename, const char *original_path)
+int config_read_file(const char *filename, const char *display_name)
{
ConfigFile *cfptr, *cfptr2, **cfptr3;
ConfigEntry *ce;
- ConfigItem_include *inc, *my_inc;
+ ConfigResource *rs;
int ret;
int counter;
if (config_verbose > 0)
config_status("Loading config file %s ..", filename);
- need_34_upgrade = 0;
need_operclass_permissions_upgrade = 0;
- /*
- * Check if we're accidentally including a file a second
+ /* Check if we're accidentally including a file a second
* time. We should expect to find one entry in this list: the
* entry for our current file.
+ * Note that no user should be able to trigger this, this
+ * can only happen if we have buggy code somewhere.
*/
counter = 0;
- my_inc = NULL;
- for (inc = conf_include; inc; inc = inc->next)
+ for (rs = config_resources; rs; rs = rs->next)
{
- /*
- * ignore files which were part of a _previous_
- * successful rehash.
- */
- if (!(inc->flag.type & INCLUDE_NOTLOADED))
- continue;
-
- if (!counter)
- my_inc = inc;
-
- if (!strcmp(filename, inc->file))
- {
- counter ++;
- continue;
- }
-#ifdef _WIN32
- if (!strcasecmp(filename, inc->file))
- {
- counter ++;
- continue;
- }
+#ifndef _WIN32
+ if (rs->file && !strcmp(filename, rs->file))
+#else
+ if (rs->file && !strcasecmp(filename, rs->file))
#endif
-#ifdef USE_LIBCURL
- if (inc->url && !strcmp(original_path, inc->url))
{
counter ++;
continue;
}
-#endif
+ if (rs->url && !strcmp(display_name, rs->url))
+ {
+ counter ++;
+ continue;
+ }
}
- if (counter < 1 || !my_inc)
+ if (counter > 1)
{
- /*
- * The following is simply for debugging/[sanity
- * checking]. To make sure that functions call
- * add_include() or add_remote_include() before
- * calling us.
- */
- config_error("I don't have a record for %s being included."
- " Perhaps someone forgot to call add_include()?",
- filename);
- abort();
- }
- if (counter > 1 || my_inc->flag.type & INCLUDE_USED)
- {
- config_error("%s:%d:include: Config file %s has been loaded before %d time."
- " You may include each file only once.",
- my_inc->included_from, my_inc->included_from_line,
- filename, counter - 1);
+ unreal_log(ULOG_ERROR, "config", "CONFIG_BUG_DUPLICATE_RESOURCE", NULL,
+ "[BUG] Config file $file has been loaded $counter times. "
+ "This should not happen. Someone forgot to call "
+ "add_config_resource() or check its return value!",
+ log_data_string("file", filename),
+ log_data_integer("counter", counter));
return -1;
}
/* end include recursion checking code */
- if ((cfptr = config_load(filename, NULL)))
+ if ((cfptr = config_load(filename, display_name)))
{
- for (cfptr3 = &conf, cfptr2 = conf; cfptr2; cfptr2 = cfptr2->cf_next)
- cfptr3 = &cfptr2->cf_next;
+ for (cfptr3 = &conf, cfptr2 = conf; cfptr2; cfptr2 = cfptr2->next)
+ cfptr3 = &cfptr2->next;
*cfptr3 = cfptr;
if (config_verbose > 1)
config_status("Loading module blacklist in %s", filename);
- preprocessor_resolve_conditionals_ce(&cfptr->cf_entries, PREPROCESSOR_PHASE_INITIAL);
+ preprocessor_resolve_conditionals_ce(&cfptr->items, PREPROCESSOR_PHASE_INITIAL);
- for (ce = cfptr->cf_entries; ce; ce = ce->ce_next)
- if (!strcmp(ce->ce_varname, "blacklist-module"))
+ for (ce = cfptr->items; ce; ce = ce->next)
+ if (!strcmp(ce->name, "blacklist-module"))
_test_blacklist_module(cfptr, ce);
- /* Load modules */
- if (config_verbose > 1)
- config_status("Loading modules in %s", filename);
- if (need_34_upgrade)
- upgrade_conf_to_34();
+ /* Load urls */
+ config_parse_and_queue_urls(cfptr->items);
+
+ if(loop.config_load_failed) /* something bad happened while processing urls */
+ return -1;
/* Load includes */
if (config_verbose > 1)
config_status("Searching through %s for include files..", filename);
- for (ce = cfptr->cf_entries; ce; ce = ce->ce_next)
- if (!strcmp(ce->ce_varname, "include"))
+
+ for (ce = cfptr->items; ce; ce = ce->next)
+ {
+ if (!strcmp(ce->name, "include"))
{
- if (ce->ce_cond)
+ if (ce->conditional_config)
{
config_error("%s:%d: Currently you cannot have an 'include' statement "
"within an @if block, sorry. However, you CAN do it the other "
"way around, that is: put the @if within the included file itself.",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
return -1;
}
ret = _conf_include(cfptr, ce);
- if (need_34_upgrade)
- upgrade_conf_to_34();
if (ret < 0)
return ret;
}
- my_inc->flag.type |= INCLUDE_USED;
+ }
return 1;
}
else
{
- config_error("Could not load config file %s", filename);
+ unreal_log(ULOG_ERROR, "config", "CONFIG_LOAD_FILE_FAILED", NULL,
+ "Could not load configuration file: $resource",
+ log_data_string("resource", display_name),
+ log_data_string("filename", filename));
#ifdef _WIN32
if (!strcmp(filename, "conf/unrealircd.conf"))
{
@@ -2445,13 +2302,12 @@ void remove_config_tkls(void)
}
}
-void config_rehash()
+void config_rehash()
{
ConfigItem_oper *oper_ptr;
ConfigItem_class *class_ptr;
ConfigItem_ulines *uline_ptr;
ConfigItem_allow *allow_ptr;
- ConfigItem_except *except_ptr;
ConfigItem_ban *ban_ptr;
ConfigItem_link *link_ptr;
ConfigItem_listen *listen_ptr;
@@ -2462,7 +2318,6 @@ void config_rehash()
ConfigItem_allow_channel *allow_channel_ptr;
ConfigItem_admin *admin_ptr;
ConfigItem_deny_version *deny_version_ptr;
- ConfigItem_log *log_ptr;
ConfigItem_alias *alias_ptr;
ConfigItem_help *help_ptr;
ConfigItem_offchans *of_ptr;
@@ -2507,13 +2362,10 @@ void config_rehash()
next = (ListStruct *)link_ptr->next;
if (link_ptr->refcount == 0)
{
- Debug((DEBUG_ERROR, "s_conf: deleting block %s (refcount 0)", link_ptr->servername));
delete_linkblock(link_ptr);
}
else
{
- Debug((DEBUG_ERROR, "s_conf: marking block %s (refcount %d) as temporary",
- link_ptr->servername, link_ptr->refcount));
link_ptr->flag.temporary = 1;
}
}
@@ -2540,19 +2392,11 @@ void config_rehash()
for (allow_ptr = conf_allow; allow_ptr; allow_ptr = (ConfigItem_allow *) next)
{
next = (ListStruct *)allow_ptr->next;
- safe_free(allow_ptr->ip);
- safe_free(allow_ptr->hostname);
+ unreal_delete_masks(allow_ptr->mask);
Auth_FreeAuthConfig(allow_ptr->auth);
DelListItem(allow_ptr, conf_allow);
safe_free(allow_ptr);
}
- for (except_ptr = conf_except; except_ptr; except_ptr = (ConfigItem_except *) next)
- {
- next = (ListStruct *)except_ptr->next;
- safe_free(except_ptr->mask);
- DelListItem(except_ptr, conf_except);
- safe_free(except_ptr);
- }
/* Free ban realname { }, ban server { } and ban version { } */
for (ban_ptr = conf_ban; ban_ptr; ban_ptr = (ConfigItem_ban *) next)
{
@@ -2614,7 +2458,7 @@ void config_rehash()
for (deny_link_ptr = conf_deny_link; deny_link_ptr; deny_link_ptr = (ConfigItem_deny_link *) next) {
next = (ListStruct *)deny_link_ptr->next;
safe_free(deny_link_ptr->prettyrule);
- safe_free(deny_link_ptr->mask);
+ unreal_delete_masks(deny_link_ptr->mask);
crule_free(&deny_link_ptr->rule);
DelListItem(deny_link_ptr, conf_deny_link);
safe_free(deny_link_ptr);
@@ -2657,14 +2501,6 @@ void config_rehash()
conf_drpass->dieauth = NULL;
safe_free(conf_drpass);
}
- for (log_ptr = conf_log; log_ptr; log_ptr = (ConfigItem_log *)next) {
- next = (ListStruct *)log_ptr->next;
- if (log_ptr->logfd != -1)
- fd_close(log_ptr->logfd);
- safe_free(log_ptr->file);
- DelListItem(log_ptr, conf_log);
- safe_free(log_ptr);
- }
for (alias_ptr = conf_alias; alias_ptr; alias_ptr = (ConfigItem_alias *)next) {
RealCommand *cmptr = find_command(alias_ptr->alias, 0);
ConfigItem_alias_format *fmt;
@@ -2797,7 +2633,16 @@ int config_post_test()
return errors;
}
-int config_run()
+/** Make the "read" config the "live" config */
+void config_switchover(void)
+{
+ free_iConf(&iConf);
+ memcpy(&iConf, &tempiConf, sizeof(iConf));
+ memset(&tempiConf, 0, sizeof(tempiConf));
+ log_blocks_switchover();
+}
+
+int config_run_blocks()
{
ConfigEntry *ce;
ConfigFile *cfptr;
@@ -2807,13 +2652,13 @@ int config_run()
ConfigItem_allow *allow;
/* Stage 1: set block first */
- for (cfptr = conf; cfptr; cfptr = cfptr->cf_next)
+ for (cfptr = conf; cfptr; cfptr = cfptr->next)
{
if (config_verbose > 1)
- config_status("Running %s", cfptr->cf_filename);
- for (ce = cfptr->cf_entries; ce; ce = ce->ce_next)
+ config_status("Running %s", cfptr->filename);
+ for (ce = cfptr->items; ce; ce = ce->next)
{
- if (!strcmp(ce->ce_varname, "set"))
+ if (!strcmp(ce->name, "set"))
{
if (_conf_set(cfptr, ce) < 0)
errors++;
@@ -2822,13 +2667,13 @@ int config_run()
}
/* Stage 2: now class blocks */
- for (cfptr = conf; cfptr; cfptr = cfptr->cf_next)
+ for (cfptr = conf; cfptr; cfptr = cfptr->next)
{
if (config_verbose > 1)
- config_status("Running %s", cfptr->cf_filename);
- for (ce = cfptr->cf_entries; ce; ce = ce->ce_next)
+ config_status("Running %s", cfptr->filename);
+ for (ce = cfptr->items; ce; ce = ce->next)
{
- if (!strcmp(ce->ce_varname, "class"))
+ if (!strcmp(ce->name, "class"))
{
if (_conf_class(cfptr, ce) < 0)
errors++;
@@ -2837,23 +2682,23 @@ int config_run()
}
/* Stage 3: now all the rest */
- for (cfptr = conf; cfptr; cfptr = cfptr->cf_next)
+ for (cfptr = conf; cfptr; cfptr = cfptr->next)
{
if (config_verbose > 1)
- config_status("Running %s", cfptr->cf_filename);
- for (ce = cfptr->cf_entries; ce; ce = ce->ce_next)
+ 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() (secret).
+ * or via config_test_blocks() (secret).
*/
- if (!strcmp(ce->ce_varname, "set") ||
- !strcmp(ce->ce_varname, "class") ||
- !strcmp(ce->ce_varname, "secret"))
+ if (!strcmp(ce->name, "set") ||
+ !strcmp(ce->name, "class") ||
+ !strcmp(ce->name, "secret"))
{
continue;
}
- if ((cc = config_binary_search(ce->ce_varname))) {
+ if ((cc = config_binary_search(ce->name))) {
if ((cc->conffunc) && (cc->conffunc(cfptr, ce) < 0))
errors++;
}
@@ -2870,31 +2715,15 @@ int config_run()
}
}
- /*
- * transfer default values from set::ipv6_clones_mask into
- * each individual allow block. If other similar things like
- * this stack up here, perhaps this shoul be moved to another
- * function.
- */
- for(allow = conf_allow; allow; allow = allow->next)
- if(!allow->ipv6_clone_mask)
- allow->ipv6_clone_mask = tempiConf.default_ipv6_clone_mask;
-
- /* ^^^ TODO: due to the two-stage model now we can do it in conf_allow again
- * and remove it here.
- */
-
close_unbound_listeners();
listen_cleanup();
close_unbound_listeners();
loop.do_bancheck = 1;
- free_iConf(&iConf);
- memcpy(&iConf, &tempiConf, sizeof(iConf));
- memset(&tempiConf, 0, sizeof(tempiConf));
+ config_switchover();
update_throttling_timer_settings();
/* initialize conf_files with defaults if the block isn't set: */
- if(!conf_files)
+ if (!conf_files)
_conf_files(NULL, NULL);
if (errors > 0)
@@ -2905,26 +2734,7 @@ int config_run()
}
-NameValue *config_binary_flags_search(NameValue *table, char *cmd, int size) {
- int start = 0;
- int stop = size-1;
- int mid;
- while (start <= stop) {
- mid = (start+stop)/2;
-
- if (smycmp(cmd,table[mid].name) < 0) {
- stop = mid-1;
- }
- else if (strcmp(cmd,table[mid].name) == 0) {
- return &(table[mid]);
- }
- else
- start = mid+1;
- }
- return NULL;
-}
-
-int config_test()
+int config_test_blocks()
{
ConfigEntry *ce;
ConfigFile *cfptr;
@@ -2932,16 +2742,29 @@ int config_test()
int errors = 0;
Hook *h;
- need_34_upgrade = 0;
+ invalid_snomasks_encountered = 0;
- for (cfptr = conf; cfptr; cfptr = cfptr->cf_next)
+ /* First, all the log { } blocks everywhere */
+ for (cfptr = conf; cfptr; cfptr = cfptr->next)
{
if (config_verbose > 1)
- config_status("Testing %s", cfptr->cf_filename);
- /* First test and run the secret { } blocks */
- for (ce = cfptr->cf_entries; ce; ce = ce->ce_next)
+ config_status("Testing %s", cfptr->filename);
+ /* First test and run the log { } blocks */
+ for (ce = cfptr->items; ce; ce = ce->next)
{
- if (!strcmp(ce->ce_varname, "secret"))
+ 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"))
{
int n = _test_secret(cfptr, ce);
errors += n;
@@ -2950,21 +2773,22 @@ int config_test()
}
}
/* First test the set { } block */
- for (ce = cfptr->cf_entries; ce; ce = ce->ce_next)
+ for (ce = cfptr->items; ce; ce = ce->next)
{
- if (!strcmp(ce->ce_varname, "set"))
+ if (!strcmp(ce->name, "set"))
errors += _test_set(cfptr, ce);
}
/* Now test all the rest */
- for (ce = cfptr->cf_entries; ce; ce = ce->ce_next)
+ for (ce = cfptr->items; ce; ce = ce->next)
{
/* These are already processed, so skip them here.. */
- if (!strcmp(ce->ce_varname, "secret") ||
- !strcmp(ce->ce_varname, "set"))
+ if (!strcmp(ce->name, "secret") ||
+ !strcmp(ce->name, "set") ||
+ !strcmp(ce->name, "log"))
{
continue;
}
- if ((cc = config_binary_search(ce->ce_varname))) {
+ if ((cc = config_binary_search(ce->name))) {
if (cc->testfunc)
errors += (cc->testfunc(cfptr, ce));
}
@@ -3003,10 +2827,10 @@ int config_test()
if (!used)
{
config_error("%s:%i: unknown directive %s",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- ce->ce_varname);
+ ce->file->filename, ce->line_number,
+ ce->name);
errors++;
- if (strchr(ce->ce_varname, ':'))
+ if (strchr(ce->name, ':'))
{
config_error("You cannot use :: in a directive, you have to write them out. "
"For example 'set::auto-join #something' needs to be written as: "
@@ -3023,10 +2847,12 @@ int config_test()
config_error("%i errors encountered", errors);
}
- if (need_34_upgrade)
+ if (invalid_snomasks_encountered)
{
- upgrade_conf_to_34();
+ config_error("It seems your set::snomask-on-oper and/or oper::snomask needs to be updated. Are you perhaps upgrading from an older version to UnrealIRCd 6?");
+ config_error("See https://www.unrealircd.org/docs/Upgrading_from_5.x#Update_your_snomasks");
}
+
return (errors > 0 ? -1 : 1);
}
@@ -3034,7 +2860,7 @@ int config_test()
* Service functions
*/
-ConfigItem_alias *find_alias(char *name)
+ConfigItem_alias *find_alias(const char *name)
{
ConfigItem_alias *e;
@@ -3049,7 +2875,7 @@ ConfigItem_alias *find_alias(char *name)
return NULL;
}
-ConfigItem_class *find_class(char *name)
+ConfigItem_class *find_class(const char *name)
{
ConfigItem_class *e;
@@ -3065,7 +2891,7 @@ ConfigItem_class *find_class(char *name)
}
-ConfigItem_oper *find_oper(char *name)
+ConfigItem_oper *find_oper(const char *name)
{
ConfigItem_oper *e;
@@ -3080,7 +2906,7 @@ ConfigItem_oper *find_oper(char *name)
return NULL;
}
-ConfigItem_operclass *find_operclass(char *name)
+ConfigItem_operclass *find_operclass(const char *name)
{
ConfigItem_operclass *e;
@@ -3095,7 +2921,7 @@ ConfigItem_operclass *find_operclass(char *name)
return NULL;
}
-int count_oper_sessions(char *name)
+int count_oper_sessions(const char *name)
{
int count = 0;
Client *client;
@@ -3109,7 +2935,7 @@ int count_oper_sessions(char *name)
return count;
}
-ConfigItem_listen *find_listen(char *ipmask, int port, int ipv6)
+ConfigItem_listen *find_listen(const char *ipmask, int port, int ipv6)
{
ConfigItem_listen *e;
@@ -3126,7 +2952,7 @@ ConfigItem_listen *find_listen(char *ipmask, int port, int ipv6)
/** Find an SNI match.
* @param name The hostname to look for (eg: irc.xyz.com).
*/
-ConfigItem_sni *find_sni(char *name)
+ConfigItem_sni *find_sni(const char *name)
{
ConfigItem_sni *e;
@@ -3141,7 +2967,7 @@ ConfigItem_sni *find_sni(char *name)
return NULL;
}
-ConfigItem_ulines *find_uline(char *host)
+ConfigItem_ulines *find_uline(const char *host)
{
ConfigItem_ulines *ulines;
@@ -3157,28 +2983,13 @@ ConfigItem_ulines *find_uline(char *host)
}
-ConfigItem_except *find_except(Client *client, short type)
-{
- ConfigItem_except *excepts;
-
- for(excepts = conf_except; excepts; excepts = excepts->next)
- {
- if (excepts->flag.type == type)
- {
- if (match_user(excepts->mask, client, MATCH_CHECK_REAL))
- return excepts;
- }
- }
- return NULL;
-}
-
ConfigItem_tld *find_tld(Client *client)
{
ConfigItem_tld *tld;
for (tld = conf_tld; tld; tld = tld->next)
{
- if (match_user(tld->mask, client, MATCH_CHECK_REAL))
+ if (unreal_mask_match(client, tld->mask))
{
if ((tld->options & TLD_TLS) && !IsSecureConnect(client))
continue;
@@ -3192,7 +3003,7 @@ ConfigItem_tld *find_tld(Client *client)
}
-ConfigItem_link *find_link(char *servername, Client *client)
+ConfigItem_link *find_link(const char *servername, Client *client)
{
ConfigItem_link *link;
@@ -3209,7 +3020,7 @@ ConfigItem_link *find_link(char *servername, Client *client)
/** Find a ban of type CONF_BAN_*, which is currently only
* CONF_BAN_SERVER, CONF_BAN_VERSION and CONF_BAN_REALNAME
*/
-ConfigItem_ban *find_ban(Client *client, char *host, short type)
+ConfigItem_ban *find_ban(Client *client, const char *host, short type)
{
ConfigItem_ban *ban;
@@ -3233,7 +3044,7 @@ ConfigItem_ban *find_ban(Client *client, char *host, short type)
* CONF_BAN_SERVER, CONF_BAN_VERSION and CONF_BAN_REALNAME
* This is the extended version, only used by cmd_svsnline.
*/
-ConfigItem_ban *find_banEx(Client *client, char *host, short type, short type2)
+ConfigItem_ban *find_banEx(Client *client, const char *host, short type, short type2)
{
ConfigItem_ban *ban;
@@ -3253,7 +3064,7 @@ ConfigItem_ban *find_banEx(Client *client, char *host, short type, short type2)
return NULL;
}
-ConfigItem_vhost *find_vhost(char *name)
+ConfigItem_vhost *find_vhost(const char *name)
{
ConfigItem_vhost *vhost;
@@ -3268,7 +3079,7 @@ ConfigItem_vhost *find_vhost(char *name)
/** returns NULL if allowed and struct if denied */
-ConfigItem_deny_channel *find_channel_allowed(Client *client, char *name)
+ConfigItem_deny_channel *find_channel_allowed(Client *client, const char *name)
{
ConfigItem_deny_channel *dchannel;
ConfigItem_allow_channel *achannel;
@@ -3313,29 +3124,33 @@ void init_dynconf(void)
memset(&tempiConf, 0, sizeof(iConf));
}
-char *pretty_time_val(long timeval)
+const char *pretty_time_val_r(char *buf, size_t buflen, long timeval)
{
- static char buf[512];
-
if (timeval == 0)
return "0";
buf[0] = 0;
if (timeval/86400)
- snprintf(buf, sizeof(buf), "%ldd", timeval/86400);
+ snprintf(buf, buflen, "%ldd", timeval/86400);
if ((timeval/3600) % 24)
- snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%ldh", (timeval/3600)%24);
+ snprintf(buf+strlen(buf), buflen-strlen(buf), "%ldh", (timeval/3600)%24);
if ((timeval/60)%60)
- snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%ldm", (timeval/60)%60);
+ snprintf(buf+strlen(buf), buflen-strlen(buf), "%ldm", (timeval/60)%60);
if ((timeval%60))
- snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%lds", timeval%60);
+ snprintf(buf+strlen(buf), buflen-strlen(buf), "%lds", timeval%60);
return buf;
}
+const char *pretty_time_val(long timeval)
+{
+ static char buf[512];
+ return pretty_time_val_r(buf, sizeof(buf), timeval);
+}
+
/* This converts a relative path to an absolute path, but only if necessary. */
-void convert_to_absolute_path(char **path, char *reldir)
+void convert_to_absolute_path(char **path, const char *reldir)
{
char *s;
@@ -3345,6 +3160,11 @@ void convert_to_absolute_path(char **path, char *reldir)
if (strstr(*path, "://"))
return; /* URL: don't touch */
+#ifdef _WIN32
+ if (!strncmp(*path, "cache/", 6))
+ return; /* downloaded from URL: don't touch (is only relative path on Windows) */
+#endif
+
if ((**path == '/') || (**path == '\\'))
return; /* already absolute path */
@@ -3371,7 +3191,7 @@ char *convert_to_absolute_path_duplicate(char *path, char *reldir)
* Actual config parser funcs
*/
-int _conf_include(ConfigFile *conf, ConfigEntry *ce)
+int _conf_include(ConfigFile *conf, ConfigEntry *ce)
{
int ret = 0;
#ifdef GLOBH
@@ -3382,75 +3202,64 @@ int _conf_include(ConfigFile *conf, ConfigEntry *ce)
WIN32_FIND_DATA FindData;
char cPath[MAX_PATH], *cSlash = NULL, *path;
#endif
- if (!ce->ce_vardata)
+ if (!ce->value)
{
config_status("%s:%i: include: no filename given",
- ce->ce_fileptr->cf_filename,
- ce->ce_varlinenum);
+ ce->file->filename,
+ ce->line_number);
return -1;
}
- if (!strcmp(ce->ce_vardata, "help.conf"))
- need_34_upgrade = 1;
+ convert_to_absolute_path(&ce->value, CONFDIR);
- convert_to_absolute_path(&ce->ce_vardata, CONFDIR);
-
-#ifdef USE_LIBCURL
- if (url_is_valid(ce->ce_vardata))
- return remote_include(ce);
-#else
- if (strstr(ce->ce_vardata, "://"))
+ if (url_is_valid(ce->value))
{
- config_error("%s:%d: URL specified: %s",
- ce->ce_fileptr->cf_filename,
- ce->ce_varlinenum,
- ce->ce_vardata);
- config_error("UnrealIRCd was not compiled with remote includes support "
- "so you cannot use URLs. You are suggested to re-run ./Config "
- "and answer YES to the question about remote includes.");
- return -1;
+ add_config_resource(ce->value, RESOURCE_INCLUDE, ce);
+ return 0;
}
-#endif
#if !defined(_WIN32) && !defined(_AMIGA) && !defined(OSXTIGER) && DEFAULT_PERMISSIONS != 0
- (void)chmod(ce->ce_vardata, DEFAULT_PERMISSIONS);
+ (void)chmod(ce->value, DEFAULT_PERMISSIONS);
#endif
#ifdef GLOBH
#if defined(__OpenBSD__) && defined(GLOB_LIMIT)
- glob(ce->ce_vardata, GLOB_NOSORT|GLOB_NOCHECK|GLOB_LIMIT, NULL, &files);
+ glob(ce->value, GLOB_NOSORT|GLOB_NOCHECK|GLOB_LIMIT, NULL, &files);
#else
- glob(ce->ce_vardata, GLOB_NOSORT|GLOB_NOCHECK, NULL, &files);
+ glob(ce->value, GLOB_NOSORT|GLOB_NOCHECK, NULL, &files);
#endif
if (!files.gl_pathc) {
globfree(&files);
config_status("%s:%i: include %s: invalid file given",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- ce->ce_vardata);
+ ce->file->filename, ce->line_number,
+ ce->value);
return -1;
}
- for (i = 0; i < files.gl_pathc; i++) {
- add_include(files.gl_pathv[i], ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
- ret = load_conf(files.gl_pathv[i], files.gl_pathv[i]);
- if (ret < 0)
+ for (i = 0; i < files.gl_pathc; i++)
+ {
+ if (add_config_resource(files.gl_pathv[i], RESOURCE_INCLUDE, ce))
{
- globfree(&files);
- return ret;
+ ret = config_read_file(files.gl_pathv[i], files.gl_pathv[i]);
+ if (ret < 0)
+ {
+ globfree(&files);
+ return ret;
+ }
}
}
globfree(&files);
#elif defined(_WIN32)
memset(cPath, 0, MAX_PATH);
- if (strchr(ce->ce_vardata, '/') || strchr(ce->ce_vardata, '\\')) {
- strlcpy(cPath,ce->ce_vardata,MAX_PATH);
+ if (strchr(ce->value, '/') || strchr(ce->value, '\\')) {
+ strlcpy(cPath,ce->value,MAX_PATH);
cSlash=cPath+strlen(cPath);
while(*cSlash != '\\' && *cSlash != '/' && cSlash > cPath)
cSlash--;
*(cSlash+1)=0;
}
- if ( (hFind = FindFirstFile(ce->ce_vardata, &FindData)) == INVALID_HANDLE_VALUE )
+ if ( (hFind = FindFirstFile(ce->value, &FindData)) == INVALID_HANDLE_VALUE )
{
config_status("%s:%i: include %s: invalid file given",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- ce->ce_vardata);
+ ce->file->filename, ce->line_number,
+ ce->value);
return -1;
}
if (cPath) {
@@ -3458,15 +3267,16 @@ int _conf_include(ConfigFile *conf, ConfigEntry *ce)
strcpy(path, cPath);
strcat(path, FindData.cFileName);
- add_include(path, ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
- ret = load_conf(path, path);
- safe_free(path);
-
+ if (add_config_resource(path, RESOURCE_INCLUDE, ce))
+ {
+ ret = config_read_file(path, path);
+ safe_free(path);
+ }
}
else
{
- add_include(FindData.cFileName, ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
- ret = load_conf(FindData.cFileName, FindData.cFileName);
+ if (add_config_resource(FindData.cFileName, RESOURCE_INCLUDE, ce))
+ ret = config_read_file(FindData.cFileName, FindData.cFileName);
}
if (ret < 0)
{
@@ -3481,24 +3291,26 @@ int _conf_include(ConfigFile *conf, ConfigEntry *ce)
strcpy(path,cPath);
strcat(path,FindData.cFileName);
- add_include(path, ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
- ret = load_conf(path, path);
- safe_free(path);
- if (ret < 0)
- break;
+ if (add_config_resource(path, RESOURCE_INCLUDE, ce))
+ {
+ ret = config_read_file(path, path);
+ safe_free(path);
+ if (ret < 0)
+ break;
+ }
}
else
{
- add_include(FindData.cFileName, ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
- ret = load_conf(FindData.cFileName, FindData.cFileName);
+ if (add_config_resource(FindData.cFileName, RESOURCE_INCLUDE, ce))
+ ret = config_read_file(FindData.cFileName, FindData.cFileName);
}
}
FindClose(hFind);
if (ret < 0)
return ret;
#else
- add_include(ce->ce_vardata, ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
- ret = load_conf(ce->ce_vardata, ce->ce_vardata);
+ if (add_config_resource(ce->value, RESOURCE_INCLUDE, ce))
+ ret = config_read_file(ce->value, ce->value);
return ret;
#endif
return 1;
@@ -3514,12 +3326,12 @@ int _conf_admin(ConfigFile *conf, ConfigEntry *ce)
ConfigEntry *cep;
ConfigItem_admin *ca;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
ca = safe_alloc(sizeof(ConfigItem_admin));
if (!conf_admin)
conf_admin_tail = ca;
- safe_strdup(ca->line, cep->ce_varname);
+ safe_strdup(ca->line, cep->name);
AddListItem(ca, conf_admin);
}
return 1;
@@ -3532,17 +3344,17 @@ int _test_admin(ConfigFile *conf, ConfigEntry *ce)
if (requiredstuff.conf_admin)
{
- config_warn_duplicate(ce->ce_fileptr->cf_filename, ce->ce_varlinenum, "admin");
+ config_warn_duplicate(ce->file->filename, ce->line_number, "admin");
return 0;
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (strlen(cep->ce_varname) > 500)
+ if (strlen(cep->name) > 500)
{
config_error("%s:%i: oversized data in admin block",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum);
+ cep->file->filename,
+ cep->line_number);
errors++;
continue;
}
@@ -3558,19 +3370,19 @@ int _conf_me(ConfigFile *conf, ConfigEntry *ce)
if (!conf_me)
conf_me = safe_alloc(sizeof(ConfigItem_me));
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "name"))
+ if (!strcmp(cep->name, "name"))
{
- safe_strdup(conf_me->name, cep->ce_vardata);
+ safe_strdup(conf_me->name, cep->value);
}
- else if (!strcmp(cep->ce_varname, "info"))
+ else if (!strcmp(cep->name, "info"))
{
- safe_strdup(conf_me->info, cep->ce_vardata);
+ safe_strdup(conf_me->info, cep->value);
}
- else if (!strcmp(cep->ce_varname, "sid"))
+ else if (!strcmp(cep->name, "sid"))
{
- safe_strdup(conf_me->sid, cep->ce_vardata);
+ safe_strdup(conf_me->sid, cep->value);
}
}
return 1;
@@ -3584,69 +3396,69 @@ int _test_me(ConfigFile *conf, ConfigEntry *ce)
if (requiredstuff.conf_me)
{
- config_warn_duplicate(ce->ce_fileptr->cf_filename, ce->ce_varlinenum, "me");
+ config_warn_duplicate(ce->file->filename, ce->line_number, "me");
return 0;
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
if (config_is_blankorempty(cep, "me"))
continue;
/* me::name */
- if (!strcmp(cep->ce_varname, "name"))
+ if (!strcmp(cep->name, "name"))
{
if (has_name)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "me::name");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "me::name");
continue;
}
has_name = 1;
- if (!strchr(cep->ce_vardata, '.'))
+ if (!strchr(cep->value, '.'))
{
config_error("%s:%i: illegal me::name, must be fully qualified hostname",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum);
+ cep->file->filename,
+ cep->line_number);
errors++;
}
- if (!valid_host(cep->ce_vardata))
- {
- config_error("%s:%i: illegal me::name contains invalid character(s) [only a-z, 0-9, _, -, . are allowed]",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum);
- errors++;
- }
- if (strlen(cep->ce_vardata) > HOSTLEN)
+ if (strlen(cep->value) > HOSTLEN)
{
config_error("%s:%i: illegal me::name, must be less or equal to %i characters",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, HOSTLEN);
+ cep->file->filename,
+ cep->line_number, HOSTLEN);
+ errors++;
+ }
+ if (!valid_server_name(cep->value))
+ {
+ config_error("%s:%i: illegal me::name contains invalid character(s) [only a-z, 0-9, _, -, . are allowed]",
+ cep->file->filename,
+ cep->line_number);
errors++;
}
}
/* me::info */
- else if (!strcmp(cep->ce_varname, "info"))
+ else if (!strcmp(cep->name, "info"))
{
char *p;
char valid = 0;
if (has_info)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "me::info");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "me::info");
continue;
}
has_info = 1;
- if (strlen(cep->ce_vardata) > (REALLEN-1))
+ if (strlen(cep->value) > (REALLEN-1))
{
config_error("%s:%i: too long me::info, must be max. %i characters",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
+ cep->file->filename, cep->line_number,
REALLEN-1);
errors++;
}
/* Valid me::info? Any data except spaces is ok */
- for (p=cep->ce_vardata; *p; p++)
+ for (p=cep->value; *p; p++)
{
if (*p != ' ')
{
@@ -3657,65 +3469,65 @@ int _test_me(ConfigFile *conf, ConfigEntry *ce)
if (!valid)
{
config_error("%s:%i: empty me::info, should be a server description.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "numeric"))
+ else if (!strcmp(cep->name, "numeric"))
{
config_error("%s:%i: me::numeric has been removed, you must now specify a Server ID (SID) instead. "
"Edit your configuration file and change 'numeric' to 'sid' and make up "
"a server id of exactly 3 characters, starting with a digit, eg: \"001\" or \"0AB\".",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
- else if (!strcmp(cep->ce_varname, "sid"))
+ else if (!strcmp(cep->name, "sid"))
{
if (has_sid)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "me::sid");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "me::sid");
continue;
}
has_sid = 1;
- if (!valid_sid(cep->ce_vardata))
+ if (!valid_sid(cep->value))
{
config_error("%s:%i: me::sid must be 3 characters long, begin with a number, "
"and the 2nd and 3rd character must be a number or uppercase letter. "
"Example: \"001\" and \"0AB\" is good. \"AAA\" and \"0ab\" are bad. ",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
- if (!isdigit(*cep->ce_vardata))
+ if (!isdigit(*cep->value))
{
config_error("%s:%i: me::sid must be 3 characters long and begin with a number",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
}
/* Unknown entry */
else
{
- config_error_unknown(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- "me", cep->ce_varname);
+ config_error_unknown(ce->file->filename, ce->line_number,
+ "me", cep->name);
errors++;
}
}
if (!has_name)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum, "me::name");
+ config_error_missing(ce->file->filename, ce->line_number, "me::name");
errors++;
}
if (!has_info)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum, "me::info");
+ config_error_missing(ce->file->filename, ce->line_number, "me::info");
errors++;
}
if (!has_sid)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum, "me::sid");
+ config_error_missing(ce->file->filename, ce->line_number, "me::sid");
errors++;
}
requiredstuff.conf_me = 1;
@@ -3750,29 +3562,29 @@ int _conf_files(ConfigFile *conf, ConfigEntry *ce)
* hack to allow initialization of conf_files (above) when there is no files block in
* CPATH. The caller calls _conf_files(NULL, NULL); to do this. We return here because
* the for loop's initialization of cep would segfault otherwise. We return 1 because
- * if config_run() calls us with a NULL ce, it's got a bug...but we can't detect that.
+ * if config_run_blocks() calls us with a NULL ce, it's got a bug...but we can't detect that.
*/
- if(!ce)
+ if (!ce)
return 1;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "motd"))
- safe_strdup(conf_files->motd_file, cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "shortmotd"))
- safe_strdup(conf_files->smotd_file, cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "opermotd"))
- safe_strdup(conf_files->opermotd_file, cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "svsmotd"))
- safe_strdup(conf_files->svsmotd_file, cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "botmotd"))
- safe_strdup(conf_files->botmotd_file, cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "rules"))
- safe_strdup(conf_files->rules_file, cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "tunefile"))
- safe_strdup(conf_files->tune_file, cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "pidfile"))
- safe_strdup(conf_files->pid_file, cep->ce_vardata);
+ if (!strcmp(cep->name, "motd"))
+ safe_strdup(conf_files->motd_file, cep->value);
+ else if (!strcmp(cep->name, "shortmotd"))
+ safe_strdup(conf_files->smotd_file, cep->value);
+ else if (!strcmp(cep->name, "opermotd"))
+ safe_strdup(conf_files->opermotd_file, cep->value);
+ else if (!strcmp(cep->name, "svsmotd"))
+ safe_strdup(conf_files->svsmotd_file, cep->value);
+ else if (!strcmp(cep->name, "botmotd"))
+ safe_strdup(conf_files->botmotd_file, cep->value);
+ else if (!strcmp(cep->name, "rules"))
+ safe_strdup(conf_files->rules_file, cep->value);
+ else if (!strcmp(cep->name, "tunefile"))
+ safe_strdup(conf_files->tune_file, cep->value);
+ else if (!strcmp(cep->name, "pidfile"))
+ safe_strdup(conf_files->pid_file, cep->value);
}
return 1;
}
@@ -3785,120 +3597,120 @@ int _test_files(ConfigFile *conf, ConfigEntry *ce)
char has_botmotd = 0, has_opermotd = 0, has_svsmotd = 0;
char has_pidfile = 0, has_tunefile = 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
/* files::motd */
- if (!strcmp(cep->ce_varname, "motd"))
+ if (!strcmp(cep->name, "motd"))
{
if (has_motd)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "files::motd");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "files::motd");
continue;
}
- convert_to_absolute_path(&cep->ce_vardata, CONFDIR);
+ convert_to_absolute_path(&cep->value, CONFDIR);
config_test_openfile(cep, O_RDONLY, 0, "files::motd", 0, 1);
has_motd = 1;
}
/* files::smotd */
- else if (!strcmp(cep->ce_varname, "shortmotd"))
+ else if (!strcmp(cep->name, "shortmotd"))
{
if (has_smotd)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "files::shortmotd");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "files::shortmotd");
continue;
}
- convert_to_absolute_path(&cep->ce_vardata, CONFDIR);
+ convert_to_absolute_path(&cep->value, CONFDIR);
config_test_openfile(cep, O_RDONLY, 0, "files::shortmotd", 0, 1);
has_smotd = 1;
}
/* files::rules */
- else if (!strcmp(cep->ce_varname, "rules"))
+ else if (!strcmp(cep->name, "rules"))
{
if (has_rules)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "files::rules");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "files::rules");
continue;
}
- convert_to_absolute_path(&cep->ce_vardata, CONFDIR);
+ convert_to_absolute_path(&cep->value, CONFDIR);
config_test_openfile(cep, O_RDONLY, 0, "files::rules", 0, 1);
has_rules = 1;
}
/* files::botmotd */
- else if (!strcmp(cep->ce_varname, "botmotd"))
+ else if (!strcmp(cep->name, "botmotd"))
{
if (has_botmotd)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "files::botmotd");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "files::botmotd");
continue;
}
- convert_to_absolute_path(&cep->ce_vardata, CONFDIR);
+ convert_to_absolute_path(&cep->value, CONFDIR);
config_test_openfile(cep, O_RDONLY, 0, "files::botmotd", 0, 1);
has_botmotd = 1;
}
/* files::opermotd */
- else if (!strcmp(cep->ce_varname, "opermotd"))
+ else if (!strcmp(cep->name, "opermotd"))
{
if (has_opermotd)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "files::opermotd");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "files::opermotd");
continue;
}
- convert_to_absolute_path(&cep->ce_vardata, CONFDIR);
+ convert_to_absolute_path(&cep->value, CONFDIR);
config_test_openfile(cep, O_RDONLY, 0, "files::opermotd", 0, 1);
has_opermotd = 1;
}
/* files::svsmotd
* This config stuff should somehow be inside of modules/svsmotd.c!!!... right?
*/
- else if (!strcmp(cep->ce_varname, "svsmotd"))
+ else if (!strcmp(cep->name, "svsmotd"))
{
if (has_svsmotd)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "files::svsmotd");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "files::svsmotd");
continue;
}
- convert_to_absolute_path(&cep->ce_vardata, CONFDIR);
+ convert_to_absolute_path(&cep->value, CONFDIR);
/* svsmotd can't be a URL because we have to be able to write to it */
config_test_openfile(cep, O_RDONLY, 0, "files::svsmotd", 0, 0);
has_svsmotd = 1;
}
/* files::pidfile */
- else if (!strcmp(cep->ce_varname, "pidfile"))
+ else if (!strcmp(cep->name, "pidfile"))
{
if (has_pidfile)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "files::pidfile");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "files::pidfile");
continue;
}
- convert_to_absolute_path(&cep->ce_vardata, PERMDATADIR);
+ convert_to_absolute_path(&cep->value, PERMDATADIR);
errors += config_test_openfile(cep, O_WRONLY | O_CREAT, 0600, "files::pidfile", 1, 0);
has_pidfile = 1;
}
/* files::tunefile */
- else if (!strcmp(cep->ce_varname, "tunefile"))
+ else if (!strcmp(cep->name, "tunefile"))
{
if (has_tunefile)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "files::tunefile");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "files::tunefile");
continue;
}
- convert_to_absolute_path(&cep->ce_vardata, PERMDATADIR);
+ convert_to_absolute_path(&cep->value, PERMDATADIR);
errors += config_test_openfile(cep, O_RDWR | O_CREAT, 0600, "files::tunefile", 1, 0);
has_tunefile = 1;
}
/* */
else
{
- config_error("%s:%d: Unknown directive: \"%s\" in files {}", cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, cep->ce_varname);
+ config_error("%s:%d: Unknown directive: \"%s\" in files {}", cep->file->filename,
+ cep->line_number, cep->name);
errors ++;
}
}
@@ -3915,18 +3727,18 @@ OperClassACLEntry* _conf_parseACLEntry(ConfigEntry *ce)
OperClassACLEntry *entry = NULL;
entry = safe_alloc(sizeof(OperClassACLEntry));
- if (!strcmp(ce->ce_varname,"allow"))
+ if (!strcmp(ce->name,"allow"))
entry->type = OPERCLASSENTRY_ALLOW;
else
entry->type = OPERCLASSENTRY_DENY;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
OperClassACLEntryVar *var = safe_alloc(sizeof(OperClassACLEntryVar));
- safe_strdup(var->name, cep->ce_varname);
- if (cep->ce_vardata)
+ safe_strdup(var->name, cep->name);
+ if (cep->value)
{
- safe_strdup(var->value, cep->ce_vardata);
+ safe_strdup(var->value, cep->value);
}
AddListItem(var,entry->variables);
}
@@ -3934,7 +3746,7 @@ OperClassACLEntry* _conf_parseACLEntry(ConfigEntry *ce)
return entry;
}
-OperClassACL* _conf_parseACL(char *name, ConfigEntry *ce)
+OperClassACL* _conf_parseACL(const char *name, ConfigEntry *ce)
{
ConfigEntry *cep;
OperClassACL *acl = NULL;
@@ -3942,15 +3754,15 @@ OperClassACL* _conf_parseACL(char *name, ConfigEntry *ce)
acl = safe_alloc(sizeof(OperClassACL));
safe_strdup(acl->name, name);
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "deny") || !strcmp(cep->ce_varname, "allow"))
+ if (!strcmp(cep->name, "deny") || !strcmp(cep->name, "allow"))
{
OperClassACLEntry *entry = _conf_parseACLEntry(cep);
AddListItem(entry,acl->entries);
}
else {
- OperClassACL *subAcl = _conf_parseACL(cep->ce_varname,cep);
+ OperClassACL *subAcl = _conf_parseACL(cep->name,cep);
AddListItem(subAcl,acl->acls);
}
}
@@ -3965,19 +3777,19 @@ int _conf_operclass(ConfigFile *conf, ConfigEntry *ce)
ConfigItem_operclass *operClass = NULL;
operClass = safe_alloc(sizeof(ConfigItem_operclass));
operClass->classStruct = safe_alloc(sizeof(OperClass));
- safe_strdup(operClass->classStruct->name, ce->ce_vardata);
+ safe_strdup(operClass->classStruct->name, ce->value);
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "parent"))
+ if (!strcmp(cep->name, "parent"))
{
- safe_strdup(operClass->classStruct->ISA, cep->ce_vardata);
+ safe_strdup(operClass->classStruct->ISA, cep->value);
}
- else if (!strcmp(cep->ce_varname, "permissions"))
+ else if (!strcmp(cep->name, "permissions"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- OperClassACL *acl = _conf_parseACL(cepp->ce_varname,cepp);
+ OperClassACL *acl = _conf_parseACL(cepp->name,cepp);
AddListItem(acl,operClass->classStruct->acls);
}
}
@@ -3993,7 +3805,7 @@ void new_permissions_system(ConfigFile *conf, ConfigEntry *ce)
return; /* error already shown */
config_error("%s:%i: UnrealIRCd 4.2.1 and higher have a new operclass permissions system.",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
config_error("Please see https://www.unrealircd.org/docs/FAQ#New_operclass_permissions");
config_error("(additional errors regarding this are suppressed)");
/*
@@ -4011,44 +3823,44 @@ int _test_operclass(ConfigFile *conf, ConfigEntry *ce)
ConfigEntry *cep;
int errors = 0;
- if (!ce->ce_vardata)
+ if (!ce->value)
{
- config_error_noname(ce->ce_fileptr->cf_filename, ce->ce_varlinenum, "operclass");
+ config_error_noname(ce->file->filename, ce->line_number, "operclass");
errors++;
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "parent"))
+ if (!strcmp(cep->name, "parent"))
{
if (has_parent)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "operclass::parent");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "operclass::parent");
continue;
}
has_parent = 1;
continue;
} else
- if (!strcmp(cep->ce_varname, "permissions"))
+ if (!strcmp(cep->name, "permissions"))
{
if (has_permissions)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "oper::permissions");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "oper::permissions");
continue;
}
has_permissions = 1;
continue;
} else
- if (!strcmp(cep->ce_varname, "privileges"))
+ if (!strcmp(cep->name, "privileges"))
{
new_permissions_system(conf, cep);
errors++;
return errors;
} else
{
- config_error_unknown(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "operclass", cep->ce_varname);
+ config_error_unknown(cep->file->filename,
+ cep->line_number, "operclass", cep->name);
errors++;
continue;
}
@@ -4056,7 +3868,7 @@ int _test_operclass(ConfigFile *conf, ConfigEntry *ce)
if (!has_permissions)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"oper::permissions");
errors++;
}
@@ -4075,69 +3887,75 @@ int _conf_oper(ConfigFile *conf, ConfigEntry *ce)
ConfigItem_oper *oper = NULL;
oper = safe_alloc(sizeof(ConfigItem_oper));
- safe_strdup(oper->name, ce->ce_vardata);
+ safe_strdup(oper->name, ce->value);
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ oper->server_notice_colors = tempiConf.server_notice_colors; /* default */
+
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "operclass"))
- safe_strdup(oper->operclass, cep->ce_vardata);
- if (!strcmp(cep->ce_varname, "password"))
+ if (!strcmp(cep->name, "operclass"))
+ safe_strdup(oper->operclass, cep->value);
+ if (!strcmp(cep->name, "password"))
oper->auth = AuthBlockToAuthConfig(cep);
- else if (!strcmp(cep->ce_varname, "class"))
+ else if (!strcmp(cep->name, "class"))
{
- oper->class = find_class(cep->ce_vardata);
+ oper->class = find_class(cep->value);
if (!oper->class || (oper->class->flag.temporary == 1))
{
config_status("%s:%i: illegal oper::class, unknown class '%s' using default of class 'default'",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- cep->ce_vardata);
+ cep->file->filename, cep->line_number,
+ cep->value);
oper->class = default_class;
}
}
- else if (!strcmp(cep->ce_varname, "swhois"))
+ else if (!strcmp(cep->name, "swhois"))
{
SWhois *s;
- if (cep->ce_entries)
+ if (cep->items)
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
s = safe_alloc(sizeof(SWhois));
- safe_strdup(s->line, cepp->ce_varname);
+ safe_strdup(s->line, cepp->name);
safe_strdup(s->setby, "oper");
AddListItem(s, oper->swhois);
}
} else
- if (cep->ce_vardata)
+ if (cep->value)
{
s = safe_alloc(sizeof(SWhois));
- safe_strdup(s->line, cep->ce_vardata);
+ safe_strdup(s->line, cep->value);
safe_strdup(s->setby, "oper");
AddListItem(s, oper->swhois);
}
}
- else if (!strcmp(cep->ce_varname, "snomask"))
+ else if (!strcmp(cep->name, "snomask"))
{
- safe_strdup(oper->snomask, cep->ce_vardata);
+ safe_strdup(oper->snomask, cep->value);
}
- else if (!strcmp(cep->ce_varname, "modes"))
+ else if (!strcmp(cep->name, "server-notice-colors"))
{
- oper->modes = set_usermode(cep->ce_vardata);
+ oper->server_notice_colors = config_checkval(cep->value, CFG_YESNO);
}
- else if (!strcmp(cep->ce_varname, "require-modes"))
+ else if (!strcmp(cep->name, "modes"))
{
- oper->require_modes = set_usermode(cep->ce_vardata);
+ oper->modes = set_usermode(cep->value);
}
- else if (!strcmp(cep->ce_varname, "maxlogins"))
+ else if (!strcmp(cep->name, "require-modes"))
{
- oper->maxlogins = atoi(cep->ce_vardata);
+ oper->require_modes = set_usermode(cep->value);
}
- else if (!strcmp(cep->ce_varname, "mask"))
+ else if (!strcmp(cep->name, "maxlogins"))
+ {
+ oper->maxlogins = atoi(cep->value);
+ }
+ else if (!strcmp(cep->name, "mask"))
{
unreal_add_masks(&oper->mask, cep);
}
- else if (!strcmp(cep->ce_varname, "vhost"))
+ else if (!strcmp(cep->name, "vhost"))
{
- safe_strdup(oper->vhost, cep->ce_vardata);
+ safe_strdup(oper->vhost, cep->value);
}
}
AddListItem(oper, conf_oper);
@@ -4152,15 +3970,15 @@ int _test_oper(ConfigFile *conf, ConfigEntry *ce)
ConfigEntry *cep;
int errors = 0;
- if (!ce->ce_vardata)
+ if (!ce->value)
{
- config_error_noname(ce->ce_fileptr->cf_filename, ce->ce_varlinenum, "oper");
+ config_error_noname(ce->file->filename, ce->line_number, "oper");
errors++;
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
/* Regular variables */
- if (!cep->ce_entries)
+ if (!cep->items)
{
if (config_is_blankorempty(cep, "oper"))
{
@@ -4168,154 +3986,157 @@ int _test_oper(ConfigFile *conf, ConfigEntry *ce)
continue;
}
/* oper::password */
- if (!strcmp(cep->ce_varname, "password"))
+ if (!strcmp(cep->name, "password"))
{
if (has_password)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "oper::password");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "oper::password");
continue;
}
has_password = 1;
if (Auth_CheckError(cep) < 0)
errors++;
- if (ce->ce_vardata && cep->ce_vardata &&
- !strcmp(ce->ce_vardata, "bobsmith") &&
- !strcmp(cep->ce_vardata, "test"))
+ if (ce->value && cep->value &&
+ !strcmp(ce->value, "bobsmith") &&
+ !strcmp(cep->value, "test"))
{
config_error("%s:%i: please change the the name and password of the "
"default 'bobsmith' oper block",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
}
continue;
}
/* oper::operclass */
- else if (!strcmp(cep->ce_varname, "operclass"))
+ else if (!strcmp(cep->name, "operclass"))
{
if (has_operclass)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "oper::operclass");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "oper::operclass");
continue;
}
has_operclass = 1;
continue;
}
/* oper::class */
- else if (!strcmp(cep->ce_varname, "class"))
+ else if (!strcmp(cep->name, "class"))
{
if (has_class)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "oper::class");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "oper::class");
continue;
}
has_class = 1;
}
/* oper::swhois */
- else if (!strcmp(cep->ce_varname, "swhois"))
+ else if (!strcmp(cep->name, "swhois"))
{
}
/* oper::vhost */
- else if (!strcmp(cep->ce_varname, "vhost"))
+ else if (!strcmp(cep->name, "vhost"))
{
if (has_vhost)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "oper::vhost");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "oper::vhost");
continue;
}
has_vhost = 1;
}
/* oper::snomask */
- else if (!strcmp(cep->ce_varname, "snomask"))
+ else if (!strcmp(cep->name, "snomask"))
{
+ char *wrong_snomask;
if (has_snomask)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "oper::snomask");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "oper::snomask");
continue;
}
+ if (!is_valid_snomask_string_testing(cep->value, &wrong_snomask))
+ {
+ config_error("%s:%i: oper::snomask contains unknown snomask letter(s) '%s'",
+ cep->file->filename, cep->line_number, wrong_snomask);
+ errors++;
+ invalid_snomasks_encountered++;
+ }
has_snomask = 1;
}
+ else if (!strcmp(cep->name, "server-notice-colors"))
+ {
+ }
/* oper::modes */
- else if (!strcmp(cep->ce_varname, "modes"))
+ else if (!strcmp(cep->name, "modes"))
{
char *p;
- for (p = cep->ce_vardata; *p; p++)
+ for (p = cep->value; *p; p++)
if (strchr("orzS", *p))
{
config_error("%s:%i: oper::modes may not include mode '%c'",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, *p);
+ cep->file->filename, cep->line_number, *p);
errors++;
}
if (has_modes)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "oper::modes");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "oper::modes");
continue;
}
has_modes = 1;
}
/* oper::require-modes */
- else if (!strcmp(cep->ce_varname, "require-modes"))
+ else if (!strcmp(cep->name, "require-modes"))
{
char *p;
- for (p = cep->ce_vardata; *p; p++)
+ for (p = cep->value; *p; p++)
if (strchr("o", *p))
{
config_warn("%s:%i: oper::require-modes probably shouldn't include mode '%c'",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, *p);
+ cep->file->filename, cep->line_number, *p);
}
if (has_require_modes)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "oper::require-modes");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "oper::require-modes");
continue;
}
has_require_modes = 1;
}
/* oper::maxlogins */
- else if (!strcmp(cep->ce_varname, "maxlogins"))
+ else if (!strcmp(cep->name, "maxlogins"))
{
int l;
if (has_maxlogins)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "oper::maxlogins");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "oper::maxlogins");
continue;
}
has_maxlogins = 1;
- l = atoi(cep->ce_vardata);
+ l = atoi(cep->value);
if ((l < 0) || (l > 5000))
{
config_error("%s:%i: oper::maxlogins: value out of range (%d) should be 0-5000",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, l);
+ cep->file->filename, cep->line_number, l);
errors++;
continue;
}
}
- /* oper::flags */
- else if (!strcmp(cep->ce_varname, "flags"))
+ else if (!strcmp(cep->name, "mask"))
{
- config_error("%s:%i: oper::flags no longer exists. UnrealIRCd 4 uses a new style oper block.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
- errors++;
- need_34_upgrade = 1;
- }
- else if (!strcmp(cep->ce_varname, "mask"))
- {
- if (cep->ce_vardata || cep->ce_entries)
+ if (cep->value || cep->items)
has_mask = 1;
}
else
{
- config_error_unknown(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "oper", cep->ce_varname);
+ config_error_unknown(cep->file->filename,
+ cep->line_number, "oper", cep->name);
errors++;
continue;
}
@@ -4323,39 +4144,21 @@ int _test_oper(ConfigFile *conf, ConfigEntry *ce)
/* Sections */
else
{
- /* oper::flags {} */
- if (!strcmp(cep->ce_varname, "flags"))
- {
- config_error("%s:%i: oper::flags no longer exists. UnrealIRCd 4 uses a new style oper block.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
- errors++;
- need_34_upgrade = 1;
- continue;
- }
- /* oper::from {} */
- else if (!strcmp(cep->ce_varname, "from"))
- {
- config_error("%s:%i: oper::from::userhost is now called oper::mask",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
- errors++;
- need_34_upgrade = 1;
- continue;
- }
- else if (!strcmp(cep->ce_varname, "swhois"))
+ if (!strcmp(cep->name, "swhois"))
{
/* ok */
}
- else if (!strcmp(cep->ce_varname, "mask"))
+ else if (!strcmp(cep->name, "mask"))
{
- if (cep->ce_vardata || cep->ce_entries)
+ if (cep->value || cep->items)
has_mask = 1;
}
- else if (!strcmp(cep->ce_varname, "password"))
+ else if (!strcmp(cep->name, "password"))
{
if (has_password)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "oper::password");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "oper::password");
continue;
}
has_password = 1;
@@ -4364,8 +4167,8 @@ int _test_oper(ConfigFile *conf, ConfigEntry *ce)
}
else
{
- config_error_unknown(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "oper", cep->ce_varname);
+ config_error_unknown(cep->file->filename,
+ cep->line_number, "oper", cep->name);
errors++;
continue;
}
@@ -4373,27 +4176,26 @@ int _test_oper(ConfigFile *conf, ConfigEntry *ce)
}
if (!has_password)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"oper::password");
errors++;
}
if (!has_mask)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"oper::mask");
errors++;
}
if (!has_class)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"oper::class");
errors++;
}
if (!has_operclass)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"oper::operclass");
- need_34_upgrade = 1;
errors++;
}
@@ -4410,10 +4212,10 @@ int _conf_class(ConfigFile *conf, ConfigEntry *ce)
ConfigItem_class *class;
unsigned char isnew = 0;
- if (!(class = find_class(ce->ce_vardata)))
+ if (!(class = find_class(ce->value)))
{
class = safe_alloc(sizeof(ConfigItem_class));
- safe_strdup(class->name, ce->ce_vardata);
+ safe_strdup(class->name, ce->value);
isnew = 1;
}
else
@@ -4422,26 +4224,26 @@ int _conf_class(ConfigFile *conf, ConfigEntry *ce)
class->flag.temporary = 0;
class->options = 0; /* RESET OPTIONS */
}
- safe_strdup(class->name, ce->ce_vardata);
+ safe_strdup(class->name, ce->value);
class->connfreq = 15; /* default */
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "pingfreq"))
- class->pingfreq = config_checkval(cep->ce_vardata,CFG_TIME);
- else if (!strcmp(cep->ce_varname, "connfreq"))
- class->connfreq = config_checkval(cep->ce_vardata,CFG_TIME);
- else if (!strcmp(cep->ce_varname, "maxclients"))
- class->maxclients = atol(cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "sendq"))
- class->sendq = config_checkval(cep->ce_vardata,CFG_SIZE);
- else if (!strcmp(cep->ce_varname, "recvq"))
- class->recvq = config_checkval(cep->ce_vardata,CFG_SIZE);
- else if (!strcmp(cep->ce_varname, "options"))
+ if (!strcmp(cep->name, "pingfreq"))
+ class->pingfreq = config_checkval(cep->value,CFG_TIME);
+ else if (!strcmp(cep->name, "connfreq"))
+ class->connfreq = config_checkval(cep->value,CFG_TIME);
+ else if (!strcmp(cep->name, "maxclients"))
+ class->maxclients = atol(cep->value);
+ else if (!strcmp(cep->name, "sendq"))
+ class->sendq = config_checkval(cep->value,CFG_SIZE);
+ else if (!strcmp(cep->name, "recvq"))
+ class->recvq = config_checkval(cep->value,CFG_SIZE);
+ else if (!strcmp(cep->name, "options"))
{
- for (cep2 = cep->ce_entries; cep2; cep2 = cep2->ce_next)
- if (!strcmp(cep2->ce_varname, "nofakelag"))
+ for (cep2 = cep->items; cep2; cep2 = cep2->next)
+ if (!strcmp(cep2->name, "nofakelag"))
class->options |= CLASS_OPT_NOFAKELAG;
}
}
@@ -4457,32 +4259,32 @@ int _test_class(ConfigFile *conf, ConfigEntry *ce)
char has_pingfreq = 0, has_connfreq = 0, has_maxclients = 0, has_sendq = 0;
char has_recvq = 0;
- if (!ce->ce_vardata)
+ if (!ce->value)
{
- config_error_noname(ce->ce_fileptr->cf_filename, ce->ce_varlinenum, "class");
+ config_error_noname(ce->file->filename, ce->line_number, "class");
return 1;
}
- if (!strcasecmp(ce->ce_vardata, "default"))
+ if (!strcasecmp(ce->value, "default"))
{
config_error("%s:%d: Class cannot be named 'default', this class name is reserved for internal use.",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "options"))
+ if (!strcmp(cep->name, "options"))
{
- for (cep2 = cep->ce_entries; cep2; cep2 = cep2->ce_next)
+ for (cep2 = cep->items; cep2; cep2 = cep2->next)
{
#ifdef FAKELAG_CONFIGURABLE
- if (!strcmp(cep2->ce_varname, "nofakelag"))
+ if (!strcmp(cep2->name, "nofakelag"))
;
else
#endif
{
config_error("%s:%d: Unknown option '%s' in class::options",
- cep2->ce_fileptr->cf_filename, cep2->ce_varlinenum, cep2->ce_varname);
+ cep2->file->filename, cep2->line_number, cep2->name);
errors++;
}
}
@@ -4493,124 +4295,124 @@ int _test_class(ConfigFile *conf, ConfigEntry *ce)
continue;
}
/* class::pingfreq */
- else if (!strcmp(cep->ce_varname, "pingfreq"))
+ else if (!strcmp(cep->name, "pingfreq"))
{
- int v = config_checkval(cep->ce_vardata,CFG_TIME);
+ int v = config_checkval(cep->value,CFG_TIME);
if (has_pingfreq)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "class::pingfreq");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "class::pingfreq");
continue;
}
has_pingfreq = 1;
if ((v < 30) || (v > 600))
{
config_error("%s:%i: class::pingfreq should be a reasonable value (30-600)",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
continue;
}
}
/* class::maxclients */
- else if (!strcmp(cep->ce_varname, "maxclients"))
+ else if (!strcmp(cep->name, "maxclients"))
{
long l;
if (has_maxclients)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "class::maxclients");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "class::maxclients");
continue;
}
has_maxclients = 1;
- l = atol(cep->ce_vardata);
+ l = atol(cep->value);
if ((l < 1) || (l > 1000000))
{
config_error("%s:%i: class::maxclients with illegal value",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
}
/* class::connfreq */
- else if (!strcmp(cep->ce_varname, "connfreq"))
+ else if (!strcmp(cep->name, "connfreq"))
{
long l;
if (has_connfreq)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "class::connfreq");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "class::connfreq");
continue;
}
has_connfreq = 1;
- l = config_checkval(cep->ce_vardata,CFG_TIME);
+ l = config_checkval(cep->value,CFG_TIME);
if ((l < 5) || (l > 604800))
{
config_error("%s:%i: class::connfreq with illegal value (must be >5 and <7d)",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
}
/* class::sendq */
- else if (!strcmp(cep->ce_varname, "sendq"))
+ else if (!strcmp(cep->name, "sendq"))
{
long l;
if (has_sendq)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "class::sendq");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "class::sendq");
continue;
}
has_sendq = 1;
- l = config_checkval(cep->ce_vardata,CFG_SIZE);
+ l = config_checkval(cep->value,CFG_SIZE);
if ((l <= 0) || (l > 2000000000))
{
config_error("%s:%i: class::sendq with illegal value",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
}
/* class::recvq */
- else if (!strcmp(cep->ce_varname, "recvq"))
+ else if (!strcmp(cep->name, "recvq"))
{
long l;
if (has_recvq)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "class::recvq");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "class::recvq");
continue;
}
has_recvq = 1;
- l = config_checkval(cep->ce_vardata,CFG_SIZE);
+ l = config_checkval(cep->value,CFG_SIZE);
if ((l < 512) || (l > 32768))
{
config_error("%s:%i: class::recvq with illegal value (must be >512 and <32k)",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
}
/* Unknown */
else
{
- config_error_unknown(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- "class", cep->ce_varname);
+ config_error_unknown(cep->file->filename, cep->line_number,
+ "class", cep->name);
errors++;
continue;
}
}
if (!has_pingfreq)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"class::pingfreq");
errors++;
}
if (!has_maxclients)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"class::maxclients");
errors++;
}
if (!has_sendq)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"class::sendq");
errors++;
}
@@ -4627,16 +4429,16 @@ int _conf_drpass(ConfigFile *conf, ConfigEntry *ce)
conf_drpass = safe_alloc(sizeof(ConfigItem_drpass));
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "restart"))
+ if (!strcmp(cep->name, "restart"))
{
if (conf_drpass->restartauth)
Auth_FreeAuthConfig(conf_drpass->restartauth);
conf_drpass->restartauth = AuthBlockToAuthConfig(cep);
}
- else if (!strcmp(cep->ce_varname, "die"))
+ else if (!strcmp(cep->name, "die"))
{
if (conf_drpass->dieauth)
Auth_FreeAuthConfig(conf_drpass->dieauth);
@@ -4653,7 +4455,7 @@ int _test_drpass(ConfigFile *conf, ConfigEntry *ce)
int errors = 0;
char has_restart = 0, has_die = 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
if (config_is_blankorempty(cep, "drpass"))
{
@@ -4661,12 +4463,12 @@ int _test_drpass(ConfigFile *conf, ConfigEntry *ce)
continue;
}
/* drpass::restart */
- if (!strcmp(cep->ce_varname, "restart"))
+ if (!strcmp(cep->name, "restart"))
{
if (has_restart)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "drpass::restart");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "drpass::restart");
continue;
}
has_restart = 1;
@@ -4675,12 +4477,12 @@ int _test_drpass(ConfigFile *conf, ConfigEntry *ce)
continue;
}
/* drpass::die */
- else if (!strcmp(cep->ce_varname, "die"))
+ else if (!strcmp(cep->name, "die"))
{
if (has_die)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "drpass::die");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "drpass::die");
continue;
}
has_die = 1;
@@ -4691,8 +4493,8 @@ int _test_drpass(ConfigFile *conf, ConfigEntry *ce)
/* Unknown */
else
{
- config_error_unknown(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- "drpass", cep->ce_varname);
+ config_error_unknown(cep->file->filename, cep->line_number,
+ "drpass", cep->name);
errors++;
continue;
}
@@ -4708,10 +4510,10 @@ int _conf_ulines(ConfigFile *conf, ConfigEntry *ce)
ConfigEntry *cep;
ConfigItem_ulines *ca;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
ca = safe_alloc(sizeof(ConfigItem_ulines));
- safe_strdup(ca->servername, cep->ce_varname);
+ safe_strdup(ca->servername, cep->name);
AddListItem(ca, conf_ulines);
}
return 1;
@@ -4730,48 +4532,48 @@ int _conf_tld(ConfigFile *conf, ConfigEntry *ce)
ca = safe_alloc(sizeof(ConfigItem_tld));
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "mask"))
- safe_strdup(ca->mask, cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "motd"))
+ if (!strcmp(cep->name, "mask"))
+ unreal_add_masks(&ca->mask, cep);
+ else if (!strcmp(cep->name, "motd"))
{
- safe_strdup(ca->motd_file, cep->ce_vardata);
- read_motd(cep->ce_vardata, &ca->motd);
+ safe_strdup(ca->motd_file, cep->value);
+ read_motd(cep->value, &ca->motd);
}
- else if (!strcmp(cep->ce_varname, "shortmotd"))
+ else if (!strcmp(cep->name, "shortmotd"))
{
- safe_strdup(ca->smotd_file, cep->ce_vardata);
- read_motd(cep->ce_vardata, &ca->smotd);
+ safe_strdup(ca->smotd_file, cep->value);
+ read_motd(cep->value, &ca->smotd);
}
- else if (!strcmp(cep->ce_varname, "opermotd"))
+ else if (!strcmp(cep->name, "opermotd"))
{
- safe_strdup(ca->opermotd_file, cep->ce_vardata);
- read_motd(cep->ce_vardata, &ca->opermotd);
+ safe_strdup(ca->opermotd_file, cep->value);
+ read_motd(cep->value, &ca->opermotd);
}
- else if (!strcmp(cep->ce_varname, "botmotd"))
+ else if (!strcmp(cep->name, "botmotd"))
{
- safe_strdup(ca->botmotd_file, cep->ce_vardata);
- read_motd(cep->ce_vardata, &ca->botmotd);
+ safe_strdup(ca->botmotd_file, cep->value);
+ read_motd(cep->value, &ca->botmotd);
}
- else if (!strcmp(cep->ce_varname, "rules"))
+ else if (!strcmp(cep->name, "rules"))
{
- safe_strdup(ca->rules_file, cep->ce_vardata);
- read_motd(cep->ce_vardata, &ca->rules);
+ safe_strdup(ca->rules_file, cep->value);
+ read_motd(cep->value, &ca->rules);
}
- else if (!strcmp(cep->ce_varname, "options"))
+ else if (!strcmp(cep->name, "options"))
{
ConfigEntry *cepp;
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "ssl") || !strcmp(cepp->ce_varname, "tls"))
+ if (!strcmp(cepp->name, "ssl") || !strcmp(cepp->name, "tls"))
ca->options |= TLD_TLS;
- else if (!strcmp(cepp->ce_varname, "remote"))
+ else if (!strcmp(cepp->name, "remote"))
ca->options |= TLD_REMOTE;
}
}
- else if (!strcmp(cep->ce_varname, "channel"))
- safe_strdup(ca->channel, cep->ce_vardata);
+ else if (!strcmp(cep->name, "channel"))
+ safe_strdup(ca->channel, cep->value);
}
AddListItem(ca, conf_tld);
return 1;
@@ -4785,189 +4587,184 @@ int _test_tld(ConfigFile *conf, ConfigEntry *ce)
char has_mask = 0, has_motd = 0, has_rules = 0, has_shortmotd = 0, has_channel = 0;
char has_opermotd = 0, has_botmotd = 0, has_options = 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!cep->ce_vardata && strcmp(cep->ce_varname, "options"))
+ if (!cep->value && strcmp(cep->name, "options"))
{
- config_error_empty(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- "tld", cep->ce_varname);
+ config_error_empty(cep->file->filename, cep->line_number,
+ "tld", cep->name);
errors++;
continue;
}
/* tld::mask */
- if (!strcmp(cep->ce_varname, "mask"))
+ if (!strcmp(cep->name, "mask"))
{
- if (has_mask)
- {
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "tld::mask");
- continue;
- }
- has_mask = 1;
+ if (cep->value || cep->items)
+ has_mask = 1;
}
/* tld::motd */
- else if (!strcmp(cep->ce_varname, "motd"))
+ else if (!strcmp(cep->name, "motd"))
{
if (has_motd)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "tld::motd");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "tld::motd");
continue;
}
has_motd = 1;
- convert_to_absolute_path(&cep->ce_vardata, CONFDIR);
- if (((fd = open(cep->ce_vardata, O_RDONLY)) == -1))
+ convert_to_absolute_path(&cep->value, CONFDIR);
+ if (((fd = open(cep->value, O_RDONLY)) == -1))
{
config_error("%s:%i: tld::motd: %s: %s",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- cep->ce_vardata, strerror(errno));
+ cep->file->filename, cep->line_number,
+ cep->value, strerror(errno));
errors++;
}
else
close(fd);
}
/* tld::rules */
- else if (!strcmp(cep->ce_varname, "rules"))
+ else if (!strcmp(cep->name, "rules"))
{
if (has_rules)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "tld::rules");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "tld::rules");
continue;
}
has_rules = 1;
- convert_to_absolute_path(&cep->ce_vardata, CONFDIR);
- if (((fd = open(cep->ce_vardata, O_RDONLY)) == -1))
+ convert_to_absolute_path(&cep->value, CONFDIR);
+ if (((fd = open(cep->value, O_RDONLY)) == -1))
{
config_error("%s:%i: tld::rules: %s: %s",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- cep->ce_vardata, strerror(errno));
+ cep->file->filename, cep->line_number,
+ cep->value, strerror(errno));
errors++;
}
else
close(fd);
}
/* tld::channel */
- else if (!strcmp(cep->ce_varname, "channel"))
+ else if (!strcmp(cep->name, "channel"))
{
if (has_channel)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "tld::channel");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "tld::channel");
continue;
}
has_channel = 1;
}
/* tld::shortmotd */
- else if (!strcmp(cep->ce_varname, "shortmotd"))
+ else if (!strcmp(cep->name, "shortmotd"))
{
if (has_shortmotd)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "tld::shortmotd");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "tld::shortmotd");
continue;
}
has_shortmotd = 1;
- convert_to_absolute_path(&cep->ce_vardata, CONFDIR);
- if (((fd = open(cep->ce_vardata, O_RDONLY)) == -1))
+ convert_to_absolute_path(&cep->value, CONFDIR);
+ if (((fd = open(cep->value, O_RDONLY)) == -1))
{
config_error("%s:%i: tld::shortmotd: %s: %s",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- cep->ce_vardata, strerror(errno));
+ cep->file->filename, cep->line_number,
+ cep->value, strerror(errno));
errors++;
}
else
close(fd);
}
/* tld::opermotd */
- else if (!strcmp(cep->ce_varname, "opermotd"))
+ else if (!strcmp(cep->name, "opermotd"))
{
if (has_opermotd)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "tld::opermotd");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "tld::opermotd");
continue;
}
has_opermotd = 1;
- convert_to_absolute_path(&cep->ce_vardata, CONFDIR);
- if (((fd = open(cep->ce_vardata, O_RDONLY)) == -1))
+ convert_to_absolute_path(&cep->value, CONFDIR);
+ if (((fd = open(cep->value, O_RDONLY)) == -1))
{
config_error("%s:%i: tld::opermotd: %s: %s",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- cep->ce_vardata, strerror(errno));
+ cep->file->filename, cep->line_number,
+ cep->value, strerror(errno));
errors++;
}
else
close(fd);
}
/* tld::botmotd */
- else if (!strcmp(cep->ce_varname, "botmotd"))
+ else if (!strcmp(cep->name, "botmotd"))
{
if (has_botmotd)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "tld::botmotd");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "tld::botmotd");
continue;
}
has_botmotd = 1;
- convert_to_absolute_path(&cep->ce_vardata, CONFDIR);
- if (((fd = open(cep->ce_vardata, O_RDONLY)) == -1))
+ convert_to_absolute_path(&cep->value, CONFDIR);
+ if (((fd = open(cep->value, O_RDONLY)) == -1))
{
config_error("%s:%i: tld::botmotd: %s: %s",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- cep->ce_vardata, strerror(errno));
+ cep->file->filename, cep->line_number,
+ cep->value, strerror(errno));
errors++;
}
else
close(fd);
}
/* tld::options */
- else if (!strcmp(cep->ce_varname, "options")) {
+ else if (!strcmp(cep->name, "options")) {
ConfigEntry *cep2;
if (has_options)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "tld::options");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "tld::options");
continue;
}
has_options = 1;
- for (cep2 = cep->ce_entries; cep2; cep2 = cep2->ce_next)
+ for (cep2 = cep->items; cep2; cep2 = cep2->next)
{
- if (strcmp(cep2->ce_varname, "ssl") &&
- strcmp(cep2->ce_varname, "tls") &&
- strcmp(cep2->ce_varname, "remote"))
+ if (strcmp(cep2->name, "ssl") &&
+ strcmp(cep2->name, "tls") &&
+ strcmp(cep2->name, "remote"))
{
- config_error_unknownopt(cep2->ce_fileptr->cf_filename,
- cep2->ce_varlinenum, "tld", cep2->ce_varname);
+ config_error_unknownopt(cep2->file->filename,
+ cep2->line_number, "tld", cep2->name);
errors++;
}
}
}
else
{
- config_error_unknown(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- "tld", cep->ce_varname);
+ config_error_unknown(cep->file->filename, cep->line_number,
+ "tld", cep->name);
errors++;
continue;
}
}
if (!has_mask)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"tld::mask");
errors++;
}
if (!has_motd)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"tld::motd");
errors++;
}
if (!has_rules)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"tld::rules");
errors++;
}
@@ -4985,26 +4782,26 @@ int _conf_listen(ConfigFile *conf, ConfigEntry *ce)
int tmpflags =0;
Hook *h;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "ip"))
+ if (!strcmp(cep->name, "ip"))
{
- ip = cep->ce_vardata;
+ ip = cep->value;
} else
- if (!strcmp(cep->ce_varname, "port"))
+ if (!strcmp(cep->name, "port"))
{
- port_range(cep->ce_vardata, &start, &end);
+ port_range(cep->value, &start, &end);
if ((start < 0) || (start > 65535) || (end < 0) || (end > 65535))
return -1; /* this is already validated in _test_listen, but okay.. */
} else
- if (!strcmp(cep->ce_varname, "options"))
+ if (!strcmp(cep->name, "options"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- NameValue *ofp;
- if ((ofp = config_binary_flags_search(_ListenerFlags, cepp->ce_varname, ARRAY_SIZEOF(_ListenerFlags))))
+ long v;
+ if ((v = nv_find_by_name(_ListenerFlags, cepp->name)))
{
- tmpflags |= ofp->flag;
+ tmpflags |= v;
} else {
for (h = Hooks[HOOKTYPE_CONFIGRUN]; h; h = h->next)
{
@@ -5015,7 +4812,7 @@ int _conf_listen(ConfigFile *conf, ConfigEntry *ce)
}
}
} else
- if (!strcmp(cep->ce_varname, "ssl-options") || !strcmp(cep->ce_varname, "tls-options"))
+ if (!strcmp(cep->name, "ssl-options") || !strcmp(cep->name, "tls-options"))
{
tlsconfig = cep;
} else
@@ -5070,23 +4867,25 @@ int _conf_listen(ConfigFile *conf, ConfigEntry *ce)
conf_tlsblock(conf, tlsconfig, listen->tls_options);
listen->ssl_ctx = init_ctx(listen->tls_options, 1);
}
+
+ safe_free(listen->websocket_forward);
/* For modules that hook CONFIG_LISTEN and CONFIG_LISTEN_OPTIONS.
* Yeah, ugly we have this here..
* and again about 100 lines down too.
*/
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "ip"))
+ if (!strcmp(cep->name, "ip"))
;
- else if (!strcmp(cep->ce_varname, "port"))
+ else if (!strcmp(cep->name, "port"))
;
- else if (!strcmp(cep->ce_varname, "options"))
+ else if (!strcmp(cep->name, "options"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
NameValue *ofp;
- if (!config_binary_flags_search(_ListenerFlags, cepp->ce_varname, ARRAY_SIZEOF(_ListenerFlags)))
+ if (!nv_find_by_name(_ListenerFlags, cepp->name))
{
for (h = Hooks[HOOKTYPE_CONFIGRUN_EX]; h; h = h->next)
{
@@ -5097,7 +4896,7 @@ int _conf_listen(ConfigFile *conf, ConfigEntry *ce)
}
}
} else
- if (!strcmp(cep->ce_varname, "ssl-options") || !strcmp(cep->ce_varname, "tls-options"))
+ if (!strcmp(cep->name, "ssl-options") || !strcmp(cep->name, "tls-options"))
;
else
{
@@ -5153,21 +4952,23 @@ int _conf_listen(ConfigFile *conf, ConfigEntry *ce)
conf_tlsblock(conf, tlsconfig, listen->tls_options);
listen->ssl_ctx = init_ctx(listen->tls_options, 1);
}
+
+ safe_free(listen->websocket_forward);
+
/* For modules that hook CONFIG_LISTEN and CONFIG_LISTEN_OPTIONS.
* Yeah, ugly we have this here..
*/
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "ip"))
+ if (!strcmp(cep->name, "ip"))
;
- else if (!strcmp(cep->ce_varname, "port"))
+ else if (!strcmp(cep->name, "port"))
;
- else if (!strcmp(cep->ce_varname, "options"))
+ else if (!strcmp(cep->name, "options"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- NameValue *ofp;
- if (!config_binary_flags_search(_ListenerFlags, cepp->ce_varname, ARRAY_SIZEOF(_ListenerFlags)))
+ if (!nv_find_by_name(_ListenerFlags, cepp->name))
{
for (h = Hooks[HOOKTYPE_CONFIGRUN_EX]; h; h = h->next)
{
@@ -5178,7 +4979,7 @@ int _conf_listen(ConfigFile *conf, ConfigEntry *ce)
}
}
} else
- if (!strcmp(cep->ce_varname, "ssl-options") || !strcmp(cep->ce_varname, "tls-options"))
+ if (!strcmp(cep->name, "ssl-options") || !strcmp(cep->name, "tls-options"))
;
else
{
@@ -5205,16 +5006,14 @@ int _test_listen(ConfigFile *conf, ConfigEntry *ce)
char *ip = NULL;
Hook *h;
- if (ce->ce_vardata)
+ if (ce->value)
{
config_error("%s:%i: listen block has a new syntax, see https://www.unrealircd.org/docs/Listen_block",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
-
- need_34_upgrade = 1;
+ ce->file->filename, ce->line_number);
return 1;
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
int used_by_module = 0;
@@ -5247,19 +5046,18 @@ int _test_listen(ConfigFile *conf, ConfigEntry *ce)
errors += errs;
}
}
- if (!strcmp(cep->ce_varname, "options"))
+ if (!strcmp(cep->name, "options"))
{
if (has_options)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "listen::options");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "listen::options");
continue;
}
has_options = 1;
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- NameValue *ofp;
- if (!(ofp = config_binary_flags_search(_ListenerFlags, cepp->ce_varname, ARRAY_SIZEOF(_ListenerFlags))))
+ if (!nv_find_by_name(_ListenerFlags, cepp->name))
{
/* Check if a module knows about this listen::options::something */
int used_by_module = 0;
@@ -5293,63 +5091,63 @@ int _test_listen(ConfigFile *conf, ConfigEntry *ce)
}
if (!used_by_module)
{
- config_error_unknownopt(cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum, "listen::options", cepp->ce_varname);
+ config_error_unknownopt(cepp->file->filename,
+ cepp->line_number, "listen::options", cepp->name);
errors++;
continue;
}
}
- if (!strcmp(cepp->ce_varname, "ssl") || !strcmp(cepp->ce_varname, "tls"))
+ if (!strcmp(cepp->name, "ssl") || !strcmp(cepp->name, "tls"))
have_tls_listeners = 1; /* for ssl config test */
}
}
else
- if (!strcmp(cep->ce_varname, "ssl-options") || !strcmp(cep->ce_varname, "tls-options"))
+ if (!strcmp(cep->name, "ssl-options") || !strcmp(cep->name, "tls-options"))
{
test_tlsblock(conf, cep, &errors);
}
else
- if (!cep->ce_vardata)
+ if (!cep->value)
{
if (!used_by_module)
{
- config_error_empty(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "listen", cep->ce_varname);
+ config_error_empty(cep->file->filename,
+ cep->line_number, "listen", cep->name);
errors++;
}
continue; /* always */
} else
- if (!strcmp(cep->ce_varname, "ip"))
+ if (!strcmp(cep->name, "ip"))
{
has_ip = 1;
- if (strcmp(cep->ce_vardata, "*") && !is_valid_ip(cep->ce_vardata))
+ if (strcmp(cep->value, "*") && !is_valid_ip(cep->value))
{
config_error("%s:%i: listen: illegal listen::ip (%s). Must be either '*' or contain a valid IP.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_vardata);
+ cep->file->filename, cep->line_number, cep->value);
return 1;
}
- ip = cep->ce_vardata;
+ ip = cep->value;
} else
- if (!strcmp(cep->ce_varname, "host"))
+ if (!strcmp(cep->name, "host"))
{
config_error("%s:%i: listen: unknown option listen::host, did you mean listen::ip?",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
} else
- if (!strcmp(cep->ce_varname, "port"))
+ if (!strcmp(cep->name, "port"))
{
int start = 0, end = 0;
has_port = 1;
- port_range(cep->ce_vardata, &start, &end);
+ port_range(cep->value, &start, &end);
if (start == end)
{
if ((start < 1) || (start > 65535))
{
config_error("%s:%i: listen: illegal port (must be 1..65535)",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
return 1;
}
}
@@ -5358,21 +5156,21 @@ int _test_listen(ConfigFile *conf, ConfigEntry *ce)
if (end < start)
{
config_error("%s:%i: listen: illegal port range end value is less than starting value",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
return 1;
}
if (end - start >= 100)
{
config_error("%s:%i: listen: you requested port %d-%d, that's %d ports "
"(and thus consumes %d sockets) this is probably not what you want.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, start, end,
+ cep->file->filename, cep->line_number, start, end,
end - start + 1, end - start + 1);
return 1;
}
if ((start < 1) || (start > 65535) || (end < 1) || (end > 65535))
{
config_error("%s:%i: listen: illegal port range values must be between 1 and 65535",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
return 1;
}
}
@@ -5383,8 +5181,8 @@ int _test_listen(ConfigFile *conf, ConfigEntry *ce)
{
if (!used_by_module)
{
- config_error_unknown(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- "listen", cep->ce_varname);
+ config_error_unknown(cep->file->filename, cep->line_number,
+ "listen", cep->name);
errors++;
}
continue; /* always */
@@ -5394,14 +5192,14 @@ int _test_listen(ConfigFile *conf, ConfigEntry *ce)
if (!has_ip)
{
config_error("%s:%d: listen block requires an listen::ip",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
}
if (!has_port)
{
config_error("%s:%d: listen block requires an listen::port",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
}
@@ -5419,9 +5217,9 @@ int _conf_allow(ConfigFile *conf, ConfigEntry *ce)
ConfigItem_allow *allow;
Hook *h;
- if (ce->ce_vardata)
+ if (ce->value)
{
- if (!strcmp(ce->ce_vardata, "channel"))
+ if (!strcmp(ce->value, "channel"))
return (_conf_allow_channel(conf, ce));
else
{
@@ -5436,68 +5234,61 @@ int _conf_allow(ConfigFile *conf, ConfigEntry *ce)
}
}
allow = safe_alloc(sizeof(ConfigItem_allow));
+ allow->ipv6_clone_mask = tempiConf.default_ipv6_clone_mask;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "ip"))
+ if (!strcmp(cep->name, "mask") || !strcmp(cep->name, "ip") || !strcmp(cep->name, "hostname"))
{
- safe_strdup(allow->ip, cep->ce_vardata);
+ unreal_add_masks(&allow->mask, cep);
}
- else if (!strcmp(cep->ce_varname, "hostname"))
- safe_strdup(allow->hostname, cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "password"))
+ else if (!strcmp(cep->name, "password"))
allow->auth = AuthBlockToAuthConfig(cep);
- else if (!strcmp(cep->ce_varname, "class"))
+ else if (!strcmp(cep->name, "class"))
{
- allow->class = find_class(cep->ce_vardata);
+ allow->class = find_class(cep->value);
if (!allow->class || (allow->class->flag.temporary == 1))
{
config_status("%s:%i: illegal allow::class, unknown class '%s' using default of class 'default'",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum,
- cep->ce_vardata);
+ cep->file->filename,
+ cep->line_number,
+ cep->value);
allow->class = default_class;
}
}
- else if (!strcmp(cep->ce_varname, "maxperip"))
- allow->maxperip = atoi(cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "global-maxperip"))
- allow->global_maxperip = atoi(cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "redirect-server"))
- safe_strdup(allow->server, cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "redirect-port"))
- allow->port = atoi(cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "ipv6-clone-mask"))
+ else if (!strcmp(cep->name, "maxperip"))
+ allow->maxperip = atoi(cep->value);
+ else if (!strcmp(cep->name, "global-maxperip"))
+ allow->global_maxperip = atoi(cep->value);
+ else if (!strcmp(cep->name, "redirect-server"))
+ safe_strdup(allow->server, cep->value);
+ else if (!strcmp(cep->name, "redirect-port"))
+ allow->port = atoi(cep->value);
+ else if (!strcmp(cep->name, "ipv6-clone-mask"))
{
/*
* If this item isn't set explicitly by the
* user, the value will temporarily be
- * zero. Defaults are applied in config_run().
+ * zero. Defaults are applied in config_run_blocks().
*/
- allow->ipv6_clone_mask = atoi(cep->ce_vardata);
+ allow->ipv6_clone_mask = atoi(cep->value);
}
- else if (!strcmp(cep->ce_varname, "options"))
+ else if (!strcmp(cep->name, "options"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "noident"))
+ if (!strcmp(cepp->name, "noident"))
allow->flags.noident = 1;
- else if (!strcmp(cepp->ce_varname, "useip"))
+ else if (!strcmp(cepp->name, "useip"))
allow->flags.useip = 1;
- else if (!strcmp(cepp->ce_varname, "ssl") || !strcmp(cepp->ce_varname, "tls"))
+ else if (!strcmp(cepp->name, "ssl") || !strcmp(cepp->name, "tls"))
allow->flags.tls = 1;
- else if (!strcmp(cepp->ce_varname, "reject-on-auth-failure"))
+ else if (!strcmp(cepp->name, "reject-on-auth-failure"))
allow->flags.reject_on_auth_failure = 1;
}
}
}
- if (!allow->hostname)
- safe_strdup(allow->hostname, "*@NOMATCH");
-
- if (!allow->ip)
- safe_strdup(allow->ip, "*@NOMATCH");
-
/* Default: global-maxperip = maxperip+1 */
if (allow->global_maxperip == 0)
allow->global_maxperip = allow->maxperip+1;
@@ -5515,13 +5306,14 @@ int _test_allow(ConfigFile *conf, ConfigEntry *ce)
ConfigEntry *cep, *cepp;
int errors = 0;
Hook *h;
- char has_ip = 0, has_hostname = 0, has_maxperip = 0, has_global_maxperip = 0, has_password = 0, has_class = 0;
+ char has_ip = 0, has_hostname = 0, has_mask = 0;
+ char has_maxperip = 0, has_global_maxperip = 0, has_password = 0, has_class = 0;
char has_redirectserver = 0, has_redirectport = 0, has_options = 0;
int hostname_possible_silliness = 0;
- if (ce->ce_vardata)
+ if (ce->value)
{
- if (!strcmp(ce->ce_vardata, "channel"))
+ if (!strcmp(ce->value, "channel"))
return (_test_allow_channel(conf, ce));
else
{
@@ -5554,106 +5346,112 @@ int _test_allow(ConfigFile *conf, ConfigEntry *ce)
}
if (!used) {
config_error("%s:%i: allow item with unknown type",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
return 1;
}
return errors;
}
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (strcmp(cep->ce_varname, "options") && config_is_blankorempty(cep, "allow"))
+ if (strcmp(cep->name, "options") &&
+ strcmp(cep->name, "mask") &&
+ config_is_blankorempty(cep, "allow"))
{
errors++;
continue;
}
- if (!strcmp(cep->ce_varname, "ip"))
+ if (!strcmp(cep->name, "ip"))
{
if (has_ip)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "allow::ip");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "allow::ip");
continue;
}
has_ip = 1;
}
- else if (!strcmp(cep->ce_varname, "maxperip"))
+ else if (!strcmp(cep->name, "hostname"))
{
- int v = atoi(cep->ce_vardata);
+ if (has_hostname)
+ {
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "allow::hostname");
+ continue;
+ }
+ has_hostname = 1;
+ if (!strcmp(cep->value, "*@*") || !strcmp(cep->value, "*"))
+ hostname_possible_silliness = 1;
+ }
+ else if (!strcmp(cep->name, "mask"))
+ {
+ has_mask = 1;
+ }
+ else if (!strcmp(cep->name, "maxperip"))
+ {
+ int v = atoi(cep->value);
if (has_maxperip)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "allow::maxperip");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "allow::maxperip");
continue;
}
has_maxperip = 1;
if ((v <= 0) || (v > 1000000))
{
config_error("%s:%i: allow::maxperip with illegal value (must be 1-1000000)",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "global-maxperip"))
+ else if (!strcmp(cep->name, "global-maxperip"))
{
- int v = atoi(cep->ce_vardata);
+ int v = atoi(cep->value);
if (has_global_maxperip)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "allow::global-maxperip");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "allow::global-maxperip");
continue;
}
has_global_maxperip = 1;
if ((v <= 0) || (v > 1000000))
{
config_error("%s:%i: allow::global-maxperip with illegal value (must be 1-1000000)",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "ipv6-clone-mask"))
+ else if (!strcmp(cep->name, "ipv6-clone-mask"))
{
/* keep this in sync with _test_set() */
int ipv6mask;
- ipv6mask = atoi(cep->ce_vardata);
+ ipv6mask = atoi(cep->value);
if (ipv6mask == 0)
{
config_error("%s:%d: allow::ipv6-clone-mask given a value of zero. This cannnot be correct, as it would treat all IPv6 hosts as one host.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
if (ipv6mask > 128)
{
config_error("%s:%d: set::default-ipv6-clone-mask was set to %d. The maximum value is 128.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
+ cep->file->filename, cep->line_number,
ipv6mask);
errors++;
}
if (ipv6mask <= 32)
{
config_warn("%s:%d: allow::ipv6-clone-mask was given a very small value.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
}
}
- else if (!strcmp(cep->ce_varname, "hostname"))
- {
- if (has_hostname)
- {
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "allow::hostname");
- continue;
- }
- has_hostname = 1;
- if (!strcmp(cep->ce_vardata, "*@*") || !strcmp(cep->ce_vardata, "*"))
- hostname_possible_silliness = 1;
- }
- else if (!strcmp(cep->ce_varname, "password"))
+ else if (!strcmp(cep->name, "password"))
{
if (has_password)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "allow::password");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "allow::password");
continue;
}
has_password = 1;
@@ -5661,112 +5459,131 @@ int _test_allow(ConfigFile *conf, ConfigEntry *ce)
if (Auth_CheckError(cep) < 0)
errors++;
}
- else if (!strcmp(cep->ce_varname, "class"))
+ else if (!strcmp(cep->name, "class"))
{
if (has_class)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "allow::class");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "allow::class");
continue;
}
has_class = 1;
}
- else if (!strcmp(cep->ce_varname, "redirect-server"))
+ else if (!strcmp(cep->name, "redirect-server"))
{
if (has_redirectserver)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "allow::redirect-server");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "allow::redirect-server");
continue;
}
has_redirectserver = 1;
}
- else if (!strcmp(cep->ce_varname, "redirect-port"))
+ else if (!strcmp(cep->name, "redirect-port"))
{
if (has_redirectport)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "allow::redirect-port");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "allow::redirect-port");
continue;
}
has_redirectport = 1;
}
- else if (!strcmp(cep->ce_varname, "options"))
+ else if (!strcmp(cep->name, "options"))
{
if (has_options)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "allow::options");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "allow::options");
continue;
}
has_options = 1;
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "noident"))
+ if (!strcmp(cepp->name, "noident"))
{}
- else if (!strcmp(cepp->ce_varname, "useip"))
+ else if (!strcmp(cepp->name, "useip"))
{}
- else if (!strcmp(cepp->ce_varname, "ssl") || !strcmp(cepp->ce_varname, "tls"))
+ else if (!strcmp(cepp->name, "ssl") || !strcmp(cepp->name, "tls"))
{}
- else if (!strcmp(cepp->ce_varname, "reject-on-auth-failure"))
+ else if (!strcmp(cepp->name, "reject-on-auth-failure"))
{}
- else if (!strcmp(cepp->ce_varname, "sasl"))
+ else if (!strcmp(cepp->name, "sasl"))
{
config_error("%s:%d: The option allow::options::sasl no longer exists. "
"Please use a require authentication { } block instead, which "
"is more flexible and provides the same functionality. See "
"https://www.unrealircd.org/docs/Require_authentication_block",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum);
+ cepp->file->filename, cepp->line_number);
errors++;
}
else
{
- config_error_unknownopt(cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum, "allow", cepp->ce_varname);
+ config_error_unknownopt(cepp->file->filename,
+ cepp->line_number, "allow", cepp->name);
errors++;
}
}
}
else
{
- config_error_unknown(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- "allow", cep->ce_varname);
+ config_error_unknown(cep->file->filename, cep->line_number,
+ "allow", cep->name);
errors++;
continue;
}
}
- if (!has_ip && !has_hostname)
+ if (has_mask && (has_ip || has_hostname))
{
- config_error("%s:%d: allow block needs an allow::ip or allow::hostname",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ config_error("%s:%d: The allow block uses allow::mask, but you also have an allow::ip and allow::hostname.",
+ ce->file->filename, ce->line_number);
+ config_error("Please delete your allow::ip and allow::hostname entries and/or integrate them into allow::mask");
+ } else
+ if (has_ip)
+ {
+ config_warn("%s:%d: The allow block uses allow::mask nowadays. Rename your allow::ip item to allow::mask.",
+ ce->file->filename, ce->line_number);
+ config_warn("See https://www.unrealircd.org/docs/FAQ#allow-mask for more information");
+ } else
+ if (has_hostname)
+ {
+ config_warn("%s:%d: The allow block uses allow::mask nowadays. Rename your allow::hostname item to allow::mask.",
+ ce->file->filename, ce->line_number);
+ config_warn("See https://www.unrealircd.org/docs/FAQ#allow-mask for more information");
+ } else
+ if (!has_mask)
+ {
+ config_error("%s:%d: allow block needs an allow::mask",
+ ce->file->filename, ce->line_number);
errors++;
}
if (has_ip && has_hostname)
{
- config_warn("%s:%d: allow block has both allow::ip and allow::hostname which is no longer permitted.",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
- need_34_upgrade = 1;
+ config_error("%s:%d: allow block has both allow::ip and allow::hostname, this is no longer permitted.",
+ ce->file->filename, ce->line_number);
+ config_error("Please integrate your allow::ip and allow::hostname items into a single allow::mask block");
+ errors++;
} else
if (hostname_possible_silliness)
{
- config_warn("%s:%d: allow block contains 'hostname *;'. This means means that users "
- "without a valid hostname (unresolved IP's) will be unable to connect. "
- "You most likely want to use 'ip *;' instead.",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ config_error("%s:%d: allow block contains 'hostname *;'. This means means that users "
+ "without a valid hostname (unresolved IP's) will be unable to connect. "
+ "You most likely want to use 'mask *;' instead.",
+ ce->file->filename, ce->line_number);
}
if (!has_class)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"allow::class");
errors++;
}
if (!has_maxperip)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"allow::maxperip");
errors++;
}
@@ -5781,21 +5598,21 @@ int _conf_allow_channel(ConfigFile *conf, ConfigEntry *ce)
ConfigEntry *mask = NULL;
/* First, search for ::class, if any */
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "class"))
- class = cep->ce_vardata;
- else if (!strcmp(cep->ce_varname, "mask"))
+ if (!strcmp(cep->name, "class"))
+ class = cep->value;
+ else if (!strcmp(cep->name, "mask"))
mask = cep;
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "channel"))
+ if (!strcmp(cep->name, "channel"))
{
/* This way, we permit multiple ::channel items in one allow block */
allow = safe_alloc(sizeof(ConfigItem_allow_channel));
- safe_strdup(allow->channel, cep->ce_vardata);
+ safe_strdup(allow->channel, cep->value);
if (class)
safe_strdup(allow->class, class);
if (mask)
@@ -5811,7 +5628,7 @@ int _test_allow_channel(ConfigFile *conf, ConfigEntry *ce)
ConfigEntry *cep;
int errors = 0;
char has_channel = 0, has_class = 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
if (config_is_blankorempty(cep, "allow channel"))
{
@@ -5819,34 +5636,34 @@ int _test_allow_channel(ConfigFile *conf, ConfigEntry *ce)
continue;
}
- if (!strcmp(cep->ce_varname, "channel"))
+ if (!strcmp(cep->name, "channel"))
{
has_channel = 1;
}
- else if (!strcmp(cep->ce_varname, "class"))
+ else if (!strcmp(cep->name, "class"))
{
if (has_class)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "allow channel::class");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "allow channel::class");
continue;
}
has_class = 1;
}
- else if (!strcmp(cep->ce_varname, "mask"))
+ else if (!strcmp(cep->name, "mask"))
{
}
else
{
- config_error_unknown(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- "allow channel", cep->ce_varname);
+ config_error_unknown(cep->file->filename, cep->line_number,
+ "allow channel", cep->name);
errors++;
}
}
if (!has_channel)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"allow channel::channel");
errors++;
}
@@ -5874,20 +5691,20 @@ int _test_except(ConfigFile *conf, ConfigEntry *ce)
Hook *h;
int used = 0;
- if (!ce->ce_vardata)
+ if (!ce->value)
{
config_error("%s:%i: except without type",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
return 1;
}
- if (!strcmp(ce->ce_vardata, "tkl"))
+ if (!strcmp(ce->value, "tkl"))
{
config_warn("%s:%i: except tkl { } is now called except ban { }. "
"Simply rename the block from 'except tkl' to 'except ban' "
"to get rid of this warning.",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
- safe_strdup(ce->ce_vardata, "ban"); /* awww */
+ ce->file->filename, ce->line_number);
+ safe_strdup(ce->value, "ban"); /* awww */
}
for (h = Hooks[HOOKTYPE_CONFIGTEST]; h; h = h->next)
@@ -5920,8 +5737,8 @@ int _test_except(ConfigFile *conf, ConfigEntry *ce)
if (!used)
{
config_error("%s:%i: unknown except type %s",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- ce->ce_vardata);
+ ce->file->filename, ce->line_number,
+ ce->value);
return 1;
}
@@ -5937,12 +5754,12 @@ int _conf_vhost(ConfigFile *conf, ConfigEntry *ce)
ConfigEntry *cep, *cepp;
vhost = safe_alloc(sizeof(ConfigItem_vhost));
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "vhost"))
+ if (!strcmp(cep->name, "vhost"))
{
char *user, *host;
- user = strtok(cep->ce_vardata, "@");
+ user = strtok(cep->value, "@");
host = strtok(NULL, "");
if (!host)
safe_strdup(vhost->virthost, user);
@@ -5952,31 +5769,31 @@ int _conf_vhost(ConfigFile *conf, ConfigEntry *ce)
safe_strdup(vhost->virthost, host);
}
}
- else if (!strcmp(cep->ce_varname, "login"))
- safe_strdup(vhost->login, cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "password"))
+ else if (!strcmp(cep->name, "login"))
+ safe_strdup(vhost->login, cep->value);
+ else if (!strcmp(cep->name, "password"))
vhost->auth = AuthBlockToAuthConfig(cep);
- else if (!strcmp(cep->ce_varname, "mask"))
+ else if (!strcmp(cep->name, "mask"))
{
unreal_add_masks(&vhost->mask, cep);
}
- else if (!strcmp(cep->ce_varname, "swhois"))
+ else if (!strcmp(cep->name, "swhois"))
{
SWhois *s;
- if (cep->ce_entries)
+ if (cep->items)
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
s = safe_alloc(sizeof(SWhois));
- safe_strdup(s->line, cepp->ce_varname);
+ safe_strdup(s->line, cepp->name);
safe_strdup(s->setby, "vhost");
AddListItem(s, vhost->swhois);
}
} else
- if (cep->ce_vardata)
+ if (cep->value)
{
s = safe_alloc(sizeof(SWhois));
- safe_strdup(s->line, cep->ce_vardata);
+ safe_strdup(s->line, cep->value);
safe_strdup(s->setby, "vhost");
AddListItem(s, vhost->swhois);
}
@@ -5992,30 +5809,30 @@ int _test_vhost(ConfigFile *conf, ConfigEntry *ce)
ConfigEntry *cep;
char has_vhost = 0, has_login = 0, has_password = 0, has_mask = 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "vhost"))
+ if (!strcmp(cep->name, "vhost"))
{
char *at, *tmp, *host;
if (has_vhost)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "vhost::vhost");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "vhost::vhost");
continue;
}
has_vhost = 1;
- if (!cep->ce_vardata)
+ if (!cep->value)
{
- config_error_empty(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "vhost", "vhost");
+ config_error_empty(cep->file->filename,
+ cep->line_number, "vhost", "vhost");
errors++;
continue;
}
- if ((at = strchr(cep->ce_vardata, '@')))
+ if ((at = strchr(cep->value, '@')))
{
- for (tmp = cep->ce_vardata; tmp != at; tmp++)
+ for (tmp = cep->value; tmp != at; tmp++)
{
- if (*tmp == '~' && tmp == cep->ce_vardata)
+ if (*tmp == '~' && tmp == cep->value)
continue;
if (!isallowed(*tmp))
break;
@@ -6023,112 +5840,103 @@ int _test_vhost(ConfigFile *conf, ConfigEntry *ce)
if (tmp != at)
{
config_error("%s:%i: vhost::vhost contains an invalid ident",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
host = at+1;
}
else
- host = cep->ce_vardata;
+ host = cep->value;
if (!*host)
{
config_error("%s:%i: vhost::vhost does not have a host set",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
else
{
- if (!valid_host(host))
+ if (!valid_host(host, 0))
{
config_error("%s:%i: vhost::vhost contains an invalid host",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
}
}
- else if (!strcmp(cep->ce_varname, "login"))
+ else if (!strcmp(cep->name, "login"))
{
if (has_login)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "vhost::login");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "vhost::login");
}
has_login = 1;
- if (!cep->ce_vardata)
+ if (!cep->value)
{
- config_error_empty(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "vhost", "login");
+ config_error_empty(cep->file->filename,
+ cep->line_number, "vhost", "login");
errors++;
continue;
}
}
- else if (!strcmp(cep->ce_varname, "password"))
+ else if (!strcmp(cep->name, "password"))
{
if (has_password)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "vhost::password");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "vhost::password");
}
has_password = 1;
- if (!cep->ce_vardata)
+ if (!cep->value)
{
- config_error_empty(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "vhost", "password");
+ config_error_empty(cep->file->filename,
+ cep->line_number, "vhost", "password");
errors++;
continue;
}
if (Auth_CheckError(cep) < 0)
errors++;
}
- else if (!strcmp(cep->ce_varname, "from"))
- {
- config_error("%s:%i: vhost::from::userhost is now called oper::mask",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
- errors++;
- need_34_upgrade = 1;
- continue;
- }
- else if (!strcmp(cep->ce_varname, "mask"))
+ else if (!strcmp(cep->name, "mask"))
{
has_mask = 1;
}
- else if (!strcmp(cep->ce_varname, "swhois"))
+ else if (!strcmp(cep->name, "swhois"))
{
/* multiple is ok */
}
else
{
- config_error_unknown(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- "vhost", cep->ce_varname);
+ config_error_unknown(cep->file->filename, cep->line_number,
+ "vhost", cep->name);
errors++;
}
}
if (!has_vhost)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"vhost::vhost");
errors++;
}
if (!has_login)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"vhost::login");
errors++;
}
if (!has_password)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"vhost::password");
errors++;
}
if (!has_mask)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"vhost::mask");
errors++;
}
- // TODO: 3.2.x -> 4.x upgrading hints
return errors;
}
@@ -6137,22 +5945,22 @@ int _test_sni(ConfigFile *conf, ConfigEntry *ce)
int errors = 0;
ConfigEntry *cep;
- if (!ce->ce_vardata)
+ if (!ce->value)
{
config_error("%s:%i: sni block needs a name, eg: sni irc.xyz.com {",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "ssl-options") || !strcmp(cep->ce_varname, "tls-options"))
+ if (!strcmp(cep->name, "ssl-options") || !strcmp(cep->name, "tls-options"))
{
test_tlsblock(conf, cep, &errors);
} else
{
- config_error_unknown(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- "sni", cep->ce_varname);
+ config_error_unknown(cep->file->filename, cep->line_number,
+ "sni", cep->name);
errors++;
continue;
}
@@ -6168,13 +5976,13 @@ int _conf_sni(ConfigFile *conf, ConfigEntry *ce)
char *name;
ConfigItem_sni *sni = NULL;
- name = ce->ce_vardata;
+ name = ce->value;
if (!name)
return 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "ssl-options") || !strcmp(cep->ce_varname, "tls-options"))
+ if (!strcmp(cep->name, "ssl-options") || !strcmp(cep->name, "tls-options"))
{
tlsconfig = cep;
}
@@ -6200,15 +6008,15 @@ int _conf_help(ConfigFile *conf, ConfigEntry *ce)
MOTDLine *last = NULL, *temp;
ca = safe_alloc(sizeof(ConfigItem_help));
- if (!ce->ce_vardata)
+ if (!ce->value)
ca->command = NULL;
else
- safe_strdup(ca->command, ce->ce_vardata);
+ safe_strdup(ca->command, ce->value);
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
temp = safe_alloc(sizeof(MOTDLine));
- safe_strdup(temp->line, cep->ce_varname);
+ safe_strdup(temp->line, cep->name);
temp->next = NULL;
if (!last)
ca->text = temp;
@@ -6224,18 +6032,18 @@ int _conf_help(ConfigFile *conf, ConfigEntry *ce)
int _test_help(ConfigFile *conf, ConfigEntry *ce) {
int errors = 0;
ConfigEntry *cep;
- if (!ce->ce_entries)
+ if (!ce->items)
{
config_error("%s:%i: empty help block",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
return 1;
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (strlen(cep->ce_varname) > 500)
+ if (strlen(cep->name) > 500)
{
config_error("%s:%i: oversized help item",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
continue;
}
@@ -6243,179 +6051,47 @@ int _test_help(ConfigFile *conf, ConfigEntry *ce) {
return errors;
}
-int _conf_log(ConfigFile *conf, ConfigEntry *ce)
-{
- ConfigEntry *cep, *cepp;
- ConfigItem_log *ca;
- NameValue *ofp = NULL;
-
- ca = safe_alloc(sizeof(ConfigItem_log));
- ca->logfd = -1;
- if (strchr(ce->ce_vardata, '%'))
- safe_strdup(ca->filefmt, ce->ce_vardata);
- else
- safe_strdup(ca->file, ce->ce_vardata);
-
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
- {
- if (!strcmp(cep->ce_varname, "maxsize"))
- {
- ca->maxsize = config_checkval(cep->ce_vardata,CFG_SIZE);
- }
- else if (!strcmp(cep->ce_varname, "flags"))
- {
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
- {
- if ((ofp = config_binary_flags_search(_LogFlags, cepp->ce_varname, ARRAY_SIZEOF(_LogFlags))))
- ca->flags |= ofp->flag;
- }
- }
- }
- AddListItem(ca, conf_log);
- return 1;
-
-}
-
-int _test_log(ConfigFile *conf, ConfigEntry *ce) {
- int fd, errors = 0;
- ConfigEntry *cep, *cepp;
- char has_flags = 0, has_maxsize = 0;
- char *fname;
-
- if (!ce->ce_vardata)
- {
- config_error("%s:%i: log block without filename",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
- return 1;
- }
- if (!ce->ce_entries)
- {
- config_error("%s:%i: empty log block",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
- return 1;
- }
-
- /* Convert to absolute path (if needed) unless it's "syslog" */
- if (strcmp(ce->ce_vardata, "syslog"))
- convert_to_absolute_path(&ce->ce_vardata, LOGDIR);
-
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
- {
- if (!strcmp(cep->ce_varname, "flags"))
- {
- if (has_flags)
- {
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "log::flags");
- continue;
- }
- has_flags = 1;
- if (!cep->ce_entries)
- {
- config_error_empty(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "log", cep->ce_varname);
- errors++;
- continue;
- }
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
- {
- if (!config_binary_flags_search(_LogFlags, cepp->ce_varname, ARRAY_SIZEOF(_LogFlags)))
- {
- config_error_unknownflag(cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum, "log", cepp->ce_varname);
- errors++;
- }
- }
- }
- else if (!strcmp(cep->ce_varname, "maxsize"))
- {
- if (has_maxsize)
- {
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "log::maxsize");
- continue;
- }
- has_maxsize = 1;
- if (!cep->ce_vardata)
- {
- config_error_empty(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "log", cep->ce_varname);
- errors++;
- }
- }
- else
- {
- config_error_unknown(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- "log", cep->ce_varname);
- errors++;
- continue;
- }
- }
-
- if (!has_flags)
- {
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- "log::flags");
- errors++;
- }
-
- fname = unreal_strftime(ce->ce_vardata);
- if ((fd = fd_fileopen(fname, O_WRONLY|O_CREAT)) == -1)
- {
- config_error("%s:%i: Couldn't open logfile (%s) for writing: %s",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- fname, strerror(errno));
- errors++;
- } else
- {
- fd_close(fd);
- }
-
- return errors;
-}
-
int _conf_link(ConfigFile *conf, ConfigEntry *ce)
{
ConfigEntry *cep, *cepp, *ceppp;
ConfigItem_link *link = NULL;
- NameValue *ofp;
link = safe_alloc(sizeof(ConfigItem_link));
- safe_strdup(link->servername, ce->ce_vardata);
+ safe_strdup(link->servername, ce->value);
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "incoming"))
+ if (!strcmp(cep->name, "incoming"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "mask"))
+ if (!strcmp(cepp->name, "mask"))
{
unreal_add_masks(&link->incoming.mask, cepp);
}
}
}
- else if (!strcmp(cep->ce_varname, "outgoing"))
+ else if (!strcmp(cep->name, "outgoing"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "bind-ip"))
- safe_strdup(link->outgoing.bind_ip, cepp->ce_vardata);
- else if (!strcmp(cepp->ce_varname, "hostname"))
- safe_strdup(link->outgoing.hostname, cepp->ce_vardata);
- else if (!strcmp(cepp->ce_varname, "port"))
- link->outgoing.port = atoi(cepp->ce_vardata);
- else if (!strcmp(cepp->ce_varname, "options"))
+ if (!strcmp(cepp->name, "bind-ip"))
+ safe_strdup(link->outgoing.bind_ip, cepp->value);
+ else if (!strcmp(cepp->name, "hostname"))
+ safe_strdup(link->outgoing.hostname, cepp->value);
+ else if (!strcmp(cepp->name, "port"))
+ link->outgoing.port = atoi(cepp->value);
+ else if (!strcmp(cepp->name, "options"))
{
- /* TODO: options still need to be split */
link->outgoing.options = 0;
- for (ceppp = cepp->ce_entries; ceppp; ceppp = ceppp->ce_next)
+ for (ceppp = cepp->items; ceppp; ceppp = ceppp->next)
{
- if ((ofp = config_binary_flags_search(_LinkFlags, ceppp->ce_varname, ARRAY_SIZEOF(_LinkFlags))))
- link->outgoing.options |= ofp->flag;
+ long v;
+ if ((v = nv_find_by_name(_LinkFlags, ceppp->name)))
+ link->outgoing.options |= v;
}
}
- else if (!strcmp(cepp->ce_varname, "ssl-options") || !strcmp(cepp->ce_varname, "tls-options"))
+ else if (!strcmp(cepp->name, "ssl-options") || !strcmp(cepp->name, "tls-options"))
{
link->tls_options = safe_alloc(sizeof(TLSOptions));
conf_tlsblock(conf, cepp, link->tls_options);
@@ -6423,38 +6099,39 @@ int _conf_link(ConfigFile *conf, ConfigEntry *ce)
}
}
}
- else if (!strcmp(cep->ce_varname, "password"))
+ else if (!strcmp(cep->name, "password"))
link->auth = AuthBlockToAuthConfig(cep);
- else if (!strcmp(cep->ce_varname, "hub"))
- safe_strdup(link->hub, cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "leaf"))
- safe_strdup(link->leaf, cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "leaf-depth") || !strcmp(cep->ce_varname, "leafdepth"))
- link->leaf_depth = atoi(cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "class"))
+ else if (!strcmp(cep->name, "hub"))
+ safe_strdup(link->hub, cep->value);
+ else if (!strcmp(cep->name, "leaf"))
+ safe_strdup(link->leaf, cep->value);
+ else if (!strcmp(cep->name, "leaf-depth") || !strcmp(cep->name, "leafdepth"))
+ link->leaf_depth = atoi(cep->value);
+ else if (!strcmp(cep->name, "class"))
{
- link->class = find_class(cep->ce_vardata);
+ link->class = find_class(cep->value);
if (!link->class || (link->class->flag.temporary == 1))
{
config_status("%s:%i: illegal link::class, unknown class '%s' using default of class 'default'",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum,
- cep->ce_vardata);
+ cep->file->filename,
+ cep->line_number,
+ cep->value);
link->class = default_class;
}
link->class->xrefcount++;
}
- else if (!strcmp(cep->ce_varname, "verify-certificate"))
+ else if (!strcmp(cep->name, "verify-certificate"))
{
- link->verify_certificate = config_checkval(cep->ce_vardata, CFG_YESNO);
+ link->verify_certificate = config_checkval(cep->value, CFG_YESNO);
}
- else if (!strcmp(cep->ce_varname, "options"))
+ else if (!strcmp(cep->name, "options"))
{
link->options = 0;
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if ((ofp = config_binary_flags_search(_LinkFlags, cepp->ce_varname, ARRAY_SIZEOF(_LinkFlags))))
- link->options |= ofp->flag;
+ long v;
+ if ((v = nv_find_by_name(_LinkFlags, cepp->name)))
+ link->options |= v;
}
}
}
@@ -6463,20 +6140,19 @@ int _conf_link(ConfigFile *conf, ConfigEntry *ce)
if (!link->hub && !link->leaf)
safe_strdup(link->hub, "*");
- AddListItem(link, conf_link);
+ AppendListItem(link, conf_link);
return 0;
}
/** Helper function for erroring on duplicate items.
- * TODO: make even more friendy for dev's?
*/
int config_detect_duplicate(int *var, ConfigEntry *ce, int *errors)
{
if (*var)
{
config_error("%s:%d: Duplicate %s directive",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- ce->ce_varname);
+ ce->file->filename, ce->line_number,
+ ce->name);
(*errors)++;
return 1;
} else {
@@ -6495,31 +6171,31 @@ int _test_link(ConfigFile *conf, ConfigEntry *ce)
int has_outgoing_options = 0, has_hub = 0, has_leaf = 0, has_leaf_depth = 0;
int has_password = 0, has_class = 0, has_options = 0;
- if (!ce->ce_vardata)
+ if (!ce->value)
{
config_error("%s:%i: link without servername. Expected: link servername { ... }",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
return 1;
}
- if (!strchr(ce->ce_vardata, '.'))
+ if (!strchr(ce->value, '.'))
{
config_error("%s:%i: link: bogus server name. Expected: link servername { ... }",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
return 1;
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "incoming"))
+ if (!strcmp(cep->name, "incoming"))
{
config_detect_duplicate(&has_incoming, cep, &errors);
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "mask"))
+ if (!strcmp(cepp->name, "mask"))
{
- if (cepp->ce_vardata || cepp->ce_entries)
+ if (cepp->value || cepp->items)
has_incoming_mask = 1;
else
if (config_is_blankorempty(cepp, "link::incoming"))
@@ -6530,12 +6206,12 @@ int _test_link(ConfigFile *conf, ConfigEntry *ce)
}
}
}
- else if (!strcmp(cep->ce_varname, "outgoing"))
+ else if (!strcmp(cep->name, "outgoing"))
{
config_detect_duplicate(&has_outgoing, cep, &errors);
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "bind-ip"))
+ if (!strcmp(cepp->name, "bind-ip"))
{
if (config_is_blankorempty(cepp, "link::outgoing"))
{
@@ -6545,7 +6221,7 @@ int _test_link(ConfigFile *conf, ConfigEntry *ce)
config_detect_duplicate(&has_outgoing_bind_ip, cepp, &errors);
// todo: ipv4 vs ipv6
}
- else if (!strcmp(cepp->ce_varname, "hostname"))
+ else if (!strcmp(cepp->name, "hostname"))
{
if (config_is_blankorempty(cepp, "link::outgoing"))
{
@@ -6553,14 +6229,14 @@ int _test_link(ConfigFile *conf, ConfigEntry *ce)
continue;
}
config_detect_duplicate(&has_outgoing_hostname, cepp, &errors);
- if (strchr(cepp->ce_vardata, '*') || strchr(cepp->ce_vardata, '?'))
+ if (strchr(cepp->value, '*') || strchr(cepp->value, '?'))
{
config_error("%s:%i: hostname in link::outgoing(!) cannot contain wildcards",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum);
+ cepp->file->filename, cepp->line_number);
errors++;
}
}
- else if (!strcmp(cepp->ce_varname, "port"))
+ else if (!strcmp(cepp->name, "port"))
{
if (config_is_blankorempty(cepp, "link::outgoing"))
{
@@ -6569,40 +6245,39 @@ int _test_link(ConfigFile *conf, ConfigEntry *ce)
}
config_detect_duplicate(&has_outgoing_port, cepp, &errors);
}
- else if (!strcmp(cepp->ce_varname, "options"))
+ else if (!strcmp(cepp->name, "options"))
{
config_detect_duplicate(&has_outgoing_options, cepp, &errors);
- for (ceppp = cepp->ce_entries; ceppp; ceppp = ceppp->ce_next)
+ for (ceppp = cepp->items; ceppp; ceppp = ceppp->next)
{
- if (!strcmp(ceppp->ce_varname, "autoconnect"))
+ if (!strcmp(ceppp->name, "autoconnect"))
;
- else if (!strcmp(ceppp->ce_varname, "ssl") || !strcmp(ceppp->ce_varname, "tls"))
+ else if (!strcmp(ceppp->name, "ssl") || !strcmp(ceppp->name, "tls"))
;
- else if (!strcmp(ceppp->ce_varname, "insecure"))
+ else if (!strcmp(ceppp->name, "insecure"))
;
else
{
- config_error_unknownopt(ceppp->ce_fileptr->cf_filename,
- ceppp->ce_varlinenum, "link::outgoing", ceppp->ce_varname);
+ config_error_unknownopt(ceppp->file->filename,
+ ceppp->line_number, "link::outgoing", ceppp->name);
errors++;
}
- // TODO: validate more options (?) and use list rather than code here...
}
}
- else if (!strcmp(cepp->ce_varname, "ssl-options") || !strcmp(cepp->ce_varname, "tls-options"))
+ else if (!strcmp(cepp->name, "ssl-options") || !strcmp(cepp->name, "tls-options"))
{
test_tlsblock(conf, cepp, &errors);
}
else
{
config_error("%s:%d: Unknown directive '%s'",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum,
+ cepp->file->filename, cepp->line_number,
config_var(cepp));
errors++;
}
}
}
- else if (!strcmp(cep->ce_varname, "password"))
+ else if (!strcmp(cep->name, "password"))
{
config_detect_duplicate(&has_password, cep, &errors);
if (Auth_CheckError(cep) < 0)
@@ -6615,15 +6290,14 @@ int _test_link(ConfigFile *conf, ConfigEntry *ce)
(auth->type != AUTHTYPE_TLS_CLIENTCERTFP) && (auth->type != AUTHTYPE_SPKIFP))
{
config_error("%s:%i: password in link block should be plaintext OR should be the "
- "SSL or SPKI fingerprint of the remote link (=better)",
- /* TODO: mention some faq or wiki item for more information */
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ "certificate or SPKI fingerprint of the remote link (=better)",
+ cep->file->filename, cep->line_number);
errors++;
}
Auth_FreeAuthConfig(auth);
}
}
- else if (!strcmp(cep->ce_varname, "hub"))
+ else if (!strcmp(cep->name, "hub"))
{
if (config_is_blankorempty(cep, "link"))
{
@@ -6632,7 +6306,7 @@ int _test_link(ConfigFile *conf, ConfigEntry *ce)
}
config_detect_duplicate(&has_hub, cep, &errors);
}
- else if (!strcmp(cep->ce_varname, "leaf"))
+ else if (!strcmp(cep->name, "leaf"))
{
if (config_is_blankorempty(cep, "link"))
{
@@ -6641,7 +6315,7 @@ int _test_link(ConfigFile *conf, ConfigEntry *ce)
}
config_detect_duplicate(&has_leaf, cep, &errors);
}
- else if (!strcmp(cep->ce_varname, "leaf-depth") || !strcmp(cep->ce_varname, "leafdepth"))
+ else if (!strcmp(cep->name, "leaf-depth") || !strcmp(cep->name, "leafdepth"))
{
if (config_is_blankorempty(cep, "link"))
{
@@ -6650,7 +6324,7 @@ int _test_link(ConfigFile *conf, ConfigEntry *ce)
}
config_detect_duplicate(&has_leaf_depth, cep, &errors);
}
- else if (!strcmp(cep->ce_varname, "class"))
+ else if (!strcmp(cep->name, "class"))
{
if (config_is_blankorempty(cep, "link"))
{
@@ -6659,14 +6333,14 @@ int _test_link(ConfigFile *conf, ConfigEntry *ce)
}
config_detect_duplicate(&has_class, cep, &errors);
}
- else if (!strcmp(cep->ce_varname, "ciphers"))
+ else if (!strcmp(cep->name, "ciphers"))
{
config_error("%s:%d: link::ciphers has been moved to link::outgoing::ssl-options::ciphers, "
"see https://www.unrealircd.org/docs/FAQ#link::ciphers_no_longer_works",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
- else if (!strcmp(cep->ce_varname, "verify-certificate"))
+ else if (!strcmp(cep->name, "verify-certificate"))
{
if (config_is_blankorempty(cep, "link"))
{
@@ -6674,27 +6348,27 @@ int _test_link(ConfigFile *conf, ConfigEntry *ce)
continue;
}
}
- else if (!strcmp(cep->ce_varname, "options"))
+ else if (!strcmp(cep->name, "options"))
{
config_detect_duplicate(&has_options, cep, &errors);
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "quarantine"))
+ if (!strcmp(cepp->name, "quarantine"))
;
else
{
config_error("%s:%d: link::options only has one possible option ('quarantine', rarely used). "
"Option '%s' is unrecognized. "
"Perhaps you meant to set an outgoing option in link::outgoing::options instead?",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum, cepp->ce_varname);
+ cepp->file->filename, cepp->line_number, cepp->name);
errors++;
}
}
}
else
{
- config_error_unknown(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "link", cep->ce_varname);
+ config_error_unknown(cep->file->filename,
+ cep->line_number, "link", cep->name);
errors++;
continue;
}
@@ -6703,9 +6377,8 @@ int _test_link(ConfigFile *conf, ConfigEntry *ce)
if (!has_incoming && !has_outgoing)
{
config_error("%s:%d: link block needs at least an incoming or outgoing section.",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
- need_34_upgrade = 1;
}
if (has_incoming)
@@ -6713,7 +6386,7 @@ int _test_link(ConfigFile *conf, ConfigEntry *ce)
/* If we have an incoming sub-block then we need at least 'mask' and 'password' */
if (!has_incoming_mask)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum, "link::incoming::mask");
+ config_error_missing(ce->file->filename, ce->line_number, "link::incoming::mask");
errors++;
}
}
@@ -6723,12 +6396,12 @@ int _test_link(ConfigFile *conf, ConfigEntry *ce)
/* If we have an outgoing sub-block then we need at least a hostname and port */
if (!has_outgoing_hostname)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum, "link::outgoing::hostname");
+ config_error_missing(ce->file->filename, ce->line_number, "link::outgoing::hostname");
errors++;
}
if (!has_outgoing_port)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum, "link::outgoing::port");
+ config_error_missing(ce->file->filename, ce->line_number, "link::outgoing::port");
errors++;
}
}
@@ -6736,12 +6409,12 @@ int _test_link(ConfigFile *conf, ConfigEntry *ce)
/* The only other generic options that are required are 'class' and 'password' */
if (!has_password)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum, "link::password");
+ config_error_missing(ce->file->filename, ce->line_number, "link::password");
errors++;
}
if (!has_class)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"link::class");
errors++;
}
@@ -6756,11 +6429,11 @@ int _conf_ban(ConfigFile *conf, ConfigEntry *ce)
Hook *h;
ca = safe_alloc(sizeof(ConfigItem_ban));
- if (!strcmp(ce->ce_vardata, "realname"))
+ if (!strcmp(ce->value, "realname"))
ca->flag.type = CONF_BAN_REALNAME;
- else if (!strcmp(ce->ce_vardata, "server"))
+ else if (!strcmp(ce->value, "server"))
ca->flag.type = CONF_BAN_SERVER;
- else if (!strcmp(ce->ce_vardata, "version"))
+ else if (!strcmp(ce->value, "version"))
{
ca->flag.type = CONF_BAN_VERSION;
tempiConf.use_ban_version = 1; /* enable CTCP VERSION on connect */
@@ -6776,16 +6449,16 @@ int _conf_ban(ConfigFile *conf, ConfigEntry *ce)
}
return 0;
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "mask"))
+ if (!strcmp(cep->name, "mask"))
{
- safe_strdup(ca->mask, cep->ce_vardata);
+ safe_strdup(ca->mask, cep->value);
}
- else if (!strcmp(cep->ce_varname, "reason"))
- safe_strdup(ca->reason, cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "action"))
- ca->action = banact_stringtoval(cep->ce_vardata);
+ else if (!strcmp(cep->name, "reason"))
+ safe_strdup(ca->reason, cep->value);
+ else if (!strcmp(cep->name, "action"))
+ ca->action = banact_stringtoval(cep->value);
}
AddListItem(ca, conf_ban);
return 0;
@@ -6799,17 +6472,17 @@ int _test_ban(ConfigFile *conf, ConfigEntry *ce)
char type = 0;
char has_mask = 0, has_action = 0, has_reason = 0;
- if (!ce->ce_vardata)
+ if (!ce->value)
{
config_error("%s:%i: ban without type",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
return 1;
}
- else if (!strcmp(ce->ce_vardata, "server"))
+ else if (!strcmp(ce->value, "server"))
{}
- else if (!strcmp(ce->ce_vardata, "realname"))
+ else if (!strcmp(ce->value, "realname"))
{}
- else if (!strcmp(ce->ce_vardata, "version"))
+ else if (!strcmp(ce->value, "version"))
type = 'v';
else
{
@@ -6842,53 +6515,53 @@ int _test_ban(ConfigFile *conf, ConfigEntry *ce)
}
if (!used) {
config_error("%s:%i: unknown ban type %s",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- ce->ce_vardata);
+ ce->file->filename, ce->line_number,
+ ce->value);
return 1;
}
return errors;
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
if (config_is_blankorempty(cep, "ban"))
{
errors++;
continue;
}
- if (!strcmp(cep->ce_varname, "mask"))
+ if (!strcmp(cep->name, "mask"))
{
if (has_mask)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "ban::mask");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "ban::mask");
continue;
}
has_mask = 1;
}
- else if (!strcmp(cep->ce_varname, "reason"))
+ else if (!strcmp(cep->name, "reason"))
{
if (has_reason)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "ban::reason");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "ban::reason");
continue;
}
has_reason = 1;
}
- else if (!strcmp(cep->ce_varname, "action"))
+ else if (!strcmp(cep->name, "action"))
{
if (has_action)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "ban::action");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "ban::action");
}
has_action = 1;
- if (!banact_stringtoval(cep->ce_vardata))
+ if (!banact_stringtoval(cep->value))
{
config_error("%s:%i: ban::action has unknown action type '%s'",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- cep->ce_vardata);
+ cep->file->filename, cep->line_number,
+ cep->value);
errors++;
}
}
@@ -6896,20 +6569,20 @@ int _test_ban(ConfigFile *conf, ConfigEntry *ce)
if (!has_mask)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"ban::mask");
errors++;
}
if (!has_reason)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"ban::reason");
errors++;
}
if (has_action && type != 'v')
{
config_error("%s:%d: ban::action specified even though type is not 'version'",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
}
return errors;
@@ -6923,7 +6596,7 @@ int _conf_require(ConfigFile *conf, ConfigEntry *ce)
char *hostmask = NULL;
char *reason = NULL;
- if (strcmp(ce->ce_vardata, "authentication") && strcmp(ce->ce_vardata, "sasl"))
+ if (strcmp(ce->value, "authentication") && strcmp(ce->value, "sasl"))
{
/* Some other block... run modules... */
int value;
@@ -6936,12 +6609,12 @@ int _conf_require(ConfigFile *conf, ConfigEntry *ce)
return 0;
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "mask"))
+ if (!strcmp(cep->name, "mask"))
{
char buf[512], *p;
- strlcpy(buf, cep->ce_vardata, sizeof(buf));
+ strlcpy(buf, cep->value, sizeof(buf));
p = strchr(buf, '@');
if (p)
{
@@ -6949,11 +6622,11 @@ int _conf_require(ConfigFile *conf, ConfigEntry *ce)
safe_strdup(usermask, buf);
safe_strdup(hostmask, p);
} else {
- safe_strdup(hostmask, cep->ce_vardata);
+ safe_strdup(hostmask, cep->value);
}
}
- else if (!strcmp(cep->ce_varname, "reason"))
- safe_strdup(reason, cep->ce_vardata);
+ else if (!strcmp(cep->name, "reason"))
+ safe_strdup(reason, cep->value);
}
if (!usermask)
@@ -6976,18 +6649,18 @@ int _test_require(ConfigFile *conf, ConfigEntry *ce)
Hook *h;
char has_mask = 0, has_reason = 0;
- if (!ce->ce_vardata)
+ if (!ce->value)
{
config_error("%s:%i: require without type, did you mean 'require authentication'?",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
return 1;
}
- if (!strcmp(ce->ce_vardata, "authentication"))
+ if (!strcmp(ce->value, "authentication"))
{}
- else if (!strcmp(ce->ce_vardata, "sasl"))
+ else if (!strcmp(ce->value, "sasl"))
{
config_warn("%s:%i: the 'require sasl' block is now called 'require authentication'",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
}
else
{
@@ -7020,36 +6693,36 @@ int _test_require(ConfigFile *conf, ConfigEntry *ce)
}
if (!used) {
config_error("%s:%i: unknown require type '%s'",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- ce->ce_vardata);
+ ce->file->filename, ce->line_number,
+ ce->value);
return 1;
}
return errors;
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
if (config_is_blankorempty(cep, "require"))
{
errors++;
continue;
}
- if (!strcmp(cep->ce_varname, "mask"))
+ if (!strcmp(cep->name, "mask"))
{
if (has_mask)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "require::mask");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "require::mask");
continue;
}
has_mask = 1;
}
- else if (!strcmp(cep->ce_varname, "reason"))
+ else if (!strcmp(cep->name, "reason"))
{
if (has_reason)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "require::reason");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "require::reason");
continue;
}
has_reason = 1;
@@ -7058,45 +6731,43 @@ int _test_require(ConfigFile *conf, ConfigEntry *ce)
if (!has_mask)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"require::mask");
errors++;
}
if (!has_reason)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"require::reason");
errors++;
}
return errors;
}
-#define CheckNull(x) if ((!(x)->ce_vardata) || (!(*((x)->ce_vardata)))) { config_error("%s:%i: missing parameter", (x)->ce_fileptr->cf_filename, (x)->ce_varlinenum); errors++; continue; }
-#define CheckNullAllowEmpty(x) if ((!(x)->ce_vardata)) { config_error("%s:%i: missing parameter", (x)->ce_fileptr->cf_filename, (x)->ce_varlinenum); errors++; continue; }
-#define CheckDuplicate(cep, name, display) if (settings.has_##name) { config_warn_duplicate((cep)->ce_fileptr->cf_filename, cep->ce_varlinenum, "set::" display); continue; } else settings.has_##name = 1
+#define CheckDuplicate(cep, name, display) if (settings.has_##name) { config_warn_duplicate((cep)->file->filename, cep->line_number, "set::" display); continue; } else settings.has_##name = 1
void test_tlsblock(ConfigFile *conf, ConfigEntry *cep, int *totalerrors)
{
ConfigEntry *cepp, *ceppp;
int errors = 0;
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "renegotiate-timeout"))
+ if (!strcmp(cepp->name, "renegotiate-timeout"))
{
}
- else if (!strcmp(cepp->ce_varname, "renegotiate-bytes"))
+ else if (!strcmp(cepp->name, "renegotiate-bytes"))
{
}
- else if (!strcmp(cepp->ce_varname, "ciphers") || !strcmp(cepp->ce_varname, "server-cipher-list"))
+ else if (!strcmp(cepp->name, "ciphers") || !strcmp(cepp->name, "server-cipher-list"))
{
CheckNull(cepp);
}
- else if (!strcmp(cepp->ce_varname, "ciphersuites"))
+ else if (!strcmp(cepp->name, "ciphersuites"))
{
CheckNull(cepp);
}
- else if (!strcmp(cepp->ce_varname, "ecdh-curves"))
+ else if (!strcmp(cepp->name, "ecdh-curves"))
{
CheckNull(cepp);
#ifndef HAS_SSL_CTX_SET1_CURVES_LIST
@@ -7107,7 +6778,7 @@ void test_tlsblock(ConfigFile *conf, ConfigEntry *cep, int *totalerrors)
errors++;
#endif
}
- else if (!strcmp(cepp->ce_varname, "protocols"))
+ else if (!strcmp(cepp->name, "protocols"))
{
char copy[512], *p, *name;
int v = 0;
@@ -7115,7 +6786,7 @@ void test_tlsblock(ConfigFile *conf, ConfigEntry *cep, int *totalerrors)
char modifier;
CheckNull(cepp);
- strlcpy(copy, cepp->ce_vardata, sizeof(copy));
+ strlcpy(copy, cepp->value, sizeof(copy));
for (name = strtoken(&p, copy, ","); name; name = strtoken(&p, NULL, ","))
{
modifier = '\0';
@@ -7142,11 +6813,11 @@ void test_tlsblock(ConfigFile *conf, ConfigEntry *cep, int *totalerrors)
#ifdef SSL_OP_NO_TLSv1_3
config_warn("%s:%i: %s: unknown protocol '%s'. "
"Valid protocols are: TLSv1,TLSv1.1,TLSv1.2,TLSv1.3",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum, config_var(cepp), name);
+ cepp->file->filename, cepp->line_number, config_var(cepp), name);
#else
config_warn("%s:%i: %s: unknown protocol '%s'. "
"Valid protocols are: TLSv1,TLSv1.1,TLSv1.2",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum, config_var(cepp), name);
+ cepp->file->filename, cepp->line_number, config_var(cepp), name);
#endif
}
@@ -7163,28 +6834,28 @@ void test_tlsblock(ConfigFile *conf, ConfigEntry *cep, int *totalerrors)
if (v == 0)
{
config_error("%s:%i: %s: no protocols enabled. Hint: set at least TLSv1.2",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum, config_var(cepp));
+ cepp->file->filename, cepp->line_number, config_var(cepp));
errors++;
}
}
- else if (!strcmp(cepp->ce_varname, "certificate") ||
- !strcmp(cepp->ce_varname, "key") ||
- !strcmp(cepp->ce_varname, "trusted-ca-file"))
+ else if (!strcmp(cepp->name, "certificate") ||
+ !strcmp(cepp->name, "key") ||
+ !strcmp(cepp->name, "trusted-ca-file"))
{
char *path;
CheckNull(cepp);
- path = convert_to_absolute_path_duplicate(cepp->ce_vardata, CONFDIR);
+ path = convert_to_absolute_path_duplicate(cepp->value, CONFDIR);
if (!file_exists(path))
{
config_error("%s:%i: %s: could not open '%s': %s",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum, config_var(cepp),
+ cepp->file->filename, cepp->line_number, config_var(cepp),
path, strerror(errno));
safe_free(path);
errors++;
}
safe_free(path);
}
- else if (!strcmp(cepp->ce_varname, "dh"))
+ else if (!strcmp(cepp->name, "dh"))
{
/* Support for this undocumented option was silently dropped in 5.0.0.
* Since 5.0.7 we print a warning about it, since you never know
@@ -7192,10 +6863,10 @@ void test_tlsblock(ConfigFile *conf, ConfigEntry *cep, int *totalerrors)
*/
config_warn("%s:%d: Not reading DH file '%s'. UnrealIRCd does not support old DH(E), we use modern ECDHE/EECDH. "
"Just remove the 'dh' directive from your config file to get rid of this warning.",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum,
- cepp->ce_vardata ? cepp->ce_vardata : "");
+ cepp->file->filename, cepp->line_number,
+ cepp->value ? cepp->value : "");
}
- else if (!strcmp(cepp->ce_varname, "outdated-protocols"))
+ else if (!strcmp(cepp->name, "outdated-protocols"))
{
char copy[512], *p, *name;
int v = 0;
@@ -7203,7 +6874,7 @@ void test_tlsblock(ConfigFile *conf, ConfigEntry *cep, int *totalerrors)
char modifier;
CheckNull(cepp);
- strlcpy(copy, cepp->ce_vardata, sizeof(copy));
+ strlcpy(copy, cepp->value, sizeof(copy));
for (name = strtoken(&p, copy, ","); name; name = strtoken(&p, NULL, ","))
{
if (!strcasecmp(name, "All"))
@@ -7221,64 +6892,66 @@ void test_tlsblock(ConfigFile *conf, ConfigEntry *cep, int *totalerrors)
#ifdef SSL_OP_NO_TLSv1_3
config_warn("%s:%i: %s: unknown protocol '%s'. "
"Valid protocols are: TLSv1,TLSv1.1,TLSv1.2,TLSv1.3",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum, config_var(cepp), name);
+ cepp->file->filename, cepp->line_number, config_var(cepp), name);
#else
config_warn("%s:%i: %s: unknown protocol '%s'. "
"Valid protocols are: TLSv1,TLSv1.1,TLSv1.2",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum, config_var(cepp), name);
+ cepp->file->filename, cepp->line_number, config_var(cepp), name);
#endif
}
}
}
- else if (!strcmp(cepp->ce_varname, "outdated-ciphers"))
+ else if (!strcmp(cepp->name, "outdated-ciphers"))
{
CheckNull(cepp);
}
- else if (!strcmp(cepp->ce_varname, "options"))
+ else if (!strcmp(cepp->name, "options"))
{
- for (ceppp = cepp->ce_entries; ceppp; ceppp = ceppp->ce_next)
- if (!config_binary_flags_search(_TLSFlags, ceppp->ce_varname, ARRAY_SIZEOF(_TLSFlags)))
+ for (ceppp = cepp->items; ceppp; ceppp = ceppp->next)
+ {
+ if (!nv_find_by_name(_TLSFlags, ceppp->name))
{
- config_error("%s:%i: unknown SSL/TLS option '%s'",
- ceppp->ce_fileptr->cf_filename,
- ceppp->ce_varlinenum, ceppp->ce_varname);
+ config_error("%s:%i: unknown TLS option '%s'",
+ ceppp->file->filename,
+ ceppp->line_number, ceppp->name);
errors ++;
}
+ }
}
- else if (!strcmp(cepp->ce_varname, "sts-policy"))
+ else if (!strcmp(cepp->name, "sts-policy"))
{
int has_port = 0;
int has_duration = 0;
- for (ceppp = cepp->ce_entries; ceppp; ceppp = ceppp->ce_next)
+ for (ceppp = cepp->items; ceppp; ceppp = ceppp->next)
{
- if (!strcmp(ceppp->ce_varname, "port"))
+ if (!strcmp(ceppp->name, "port"))
{
int port;
CheckNull(ceppp);
- port = atoi(ceppp->ce_vardata);
+ port = atoi(ceppp->value);
if ((port < 1) || (port > 65535))
{
config_error("%s:%i: invalid port number specified in sts-policy::port (%d)",
- ceppp->ce_fileptr->cf_filename, ceppp->ce_varlinenum, port);
+ ceppp->file->filename, ceppp->line_number, port);
errors++;
}
has_port = 1;
}
- else if (!strcmp(ceppp->ce_varname, "duration"))
+ else if (!strcmp(ceppp->name, "duration"))
{
long duration;
CheckNull(ceppp);
- duration = config_checkval(ceppp->ce_vardata, CFG_TIME);
+ duration = config_checkval(ceppp->value, CFG_TIME);
if (duration < 1)
{
config_error("%s:%i: invalid duration specified in sts-policy::duration (%ld seconds)",
- ceppp->ce_fileptr->cf_filename, ceppp->ce_varlinenum, duration);
+ ceppp->file->filename, ceppp->line_number, duration);
errors++;
}
has_duration = 1;
}
- else if (!strcmp(ceppp->ce_varname, "preload"))
+ else if (!strcmp(ceppp->name, "preload"))
{
CheckNull(ceppp);
}
@@ -7286,20 +6959,20 @@ void test_tlsblock(ConfigFile *conf, ConfigEntry *cep, int *totalerrors)
if (!has_port)
{
config_error("%s:%i: sts-policy block without port",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum);
+ cepp->file->filename, cepp->line_number);
errors++;
}
if (!has_duration)
{
config_error("%s:%i: sts-policy block without duration",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum);
+ cepp->file->filename, cepp->line_number);
errors++;
}
}
else
{
config_error("%s:%i: unknown directive %s",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum,
+ cepp->file->filename, cepp->line_number,
config_var(cepp));
errors++;
}
@@ -7351,27 +7024,27 @@ void conf_tlsblock(ConfigFile *conf, ConfigEntry *cep, TLSOptions *tlsoptions)
}
/* Now process the options */
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "ciphers") || !strcmp(cepp->ce_varname, "server-cipher-list"))
+ if (!strcmp(cepp->name, "ciphers") || !strcmp(cepp->name, "server-cipher-list"))
{
- safe_strdup(tlsoptions->ciphers, cepp->ce_vardata);
+ safe_strdup(tlsoptions->ciphers, cepp->value);
}
- else if (!strcmp(cepp->ce_varname, "ciphersuites"))
+ else if (!strcmp(cepp->name, "ciphersuites"))
{
- safe_strdup(tlsoptions->ciphersuites, cepp->ce_vardata);
+ safe_strdup(tlsoptions->ciphersuites, cepp->value);
}
- else if (!strcmp(cepp->ce_varname, "ecdh-curves"))
+ else if (!strcmp(cepp->name, "ecdh-curves"))
{
- safe_strdup(tlsoptions->ecdh_curves, cepp->ce_vardata);
+ safe_strdup(tlsoptions->ecdh_curves, cepp->value);
}
- else if (!strcmp(cepp->ce_varname, "protocols"))
+ else if (!strcmp(cepp->name, "protocols"))
{
char copy[512], *p, *name;
int option;
char modifier;
- strlcpy(copy, cepp->ce_vardata, sizeof(copy));
+ strlcpy(copy, cepp->value, sizeof(copy));
tlsoptions->protocols = 0;
for (name = strtoken(&p, copy, ","); name; name = strtoken(&p, NULL, ","))
{
@@ -7406,61 +7079,60 @@ void conf_tlsblock(ConfigFile *conf, ConfigEntry *cep, TLSOptions *tlsoptions)
}
}
}
- else if (!strcmp(cepp->ce_varname, "certificate"))
+ else if (!strcmp(cepp->name, "certificate"))
{
- convert_to_absolute_path(&cepp->ce_vardata, CONFDIR);
- safe_strdup(tlsoptions->certificate_file, cepp->ce_vardata);
+ convert_to_absolute_path(&cepp->value, CONFDIR);
+ safe_strdup(tlsoptions->certificate_file, cepp->value);
}
- else if (!strcmp(cepp->ce_varname, "key"))
+ else if (!strcmp(cepp->name, "key"))
{
- convert_to_absolute_path(&cepp->ce_vardata, CONFDIR);
- safe_strdup(tlsoptions->key_file, cepp->ce_vardata);
+ convert_to_absolute_path(&cepp->value, CONFDIR);
+ safe_strdup(tlsoptions->key_file, cepp->value);
}
- else if (!strcmp(cepp->ce_varname, "trusted-ca-file"))
+ else if (!strcmp(cepp->name, "trusted-ca-file"))
{
- convert_to_absolute_path(&cepp->ce_vardata, CONFDIR);
- safe_strdup(tlsoptions->trusted_ca_file, cepp->ce_vardata);
+ convert_to_absolute_path(&cepp->value, CONFDIR);
+ safe_strdup(tlsoptions->trusted_ca_file, cepp->value);
}
- else if (!strcmp(cepp->ce_varname, "outdated-protocols"))
+ else if (!strcmp(cepp->name, "outdated-protocols"))
{
- safe_strdup(tlsoptions->outdated_protocols, cepp->ce_vardata);
+ safe_strdup(tlsoptions->outdated_protocols, cepp->value);
}
- else if (!strcmp(cepp->ce_varname, "outdated-ciphers"))
+ else if (!strcmp(cepp->name, "outdated-ciphers"))
{
- safe_strdup(tlsoptions->outdated_ciphers, cepp->ce_vardata);
+ safe_strdup(tlsoptions->outdated_ciphers, cepp->value);
}
- else if (!strcmp(cepp->ce_varname, "renegotiate-bytes"))
+ else if (!strcmp(cepp->name, "renegotiate-bytes"))
{
- tlsoptions->renegotiate_bytes = config_checkval(cepp->ce_vardata, CFG_SIZE);
+ tlsoptions->renegotiate_bytes = config_checkval(cepp->value, CFG_SIZE);
}
- else if (!strcmp(cepp->ce_varname, "renegotiate-timeout"))
+ else if (!strcmp(cepp->name, "renegotiate-timeout"))
{
- tlsoptions->renegotiate_timeout = config_checkval(cepp->ce_vardata, CFG_TIME);
+ tlsoptions->renegotiate_timeout = config_checkval(cepp->value, CFG_TIME);
}
- else if (!strcmp(cepp->ce_varname, "options"))
+ else if (!strcmp(cepp->name, "options"))
{
tlsoptions->options = 0;
- for (ceppp = cepp->ce_entries; ceppp; ceppp = ceppp->ce_next)
+ for (ceppp = cepp->items; ceppp; ceppp = ceppp->next)
{
- ofl = config_binary_flags_search(_TLSFlags, ceppp->ce_varname, ARRAY_SIZEOF(_TLSFlags));
- if (ofl) /* this should always be true */
- tlsoptions->options |= ofl->flag;
+ long v = nv_find_by_name(_TLSFlags, ceppp->name);
+ tlsoptions->options |= v;
}
}
- else if (!strcmp(cepp->ce_varname, "sts-policy"))
+ else if (!strcmp(cepp->name, "sts-policy"))
{
/* We do not inherit ::sts-policy if there is a specific block for this one... */
tlsoptions->sts_port = 0;
tlsoptions->sts_duration = 0;
tlsoptions->sts_preload = 0;
- for (ceppp = cepp->ce_entries; ceppp; ceppp = ceppp->ce_next)
+ for (ceppp = cepp->items; ceppp; ceppp = ceppp->next)
{
- if (!strcmp(ceppp->ce_varname, "port"))
- tlsoptions->sts_port = atoi(ceppp->ce_vardata);
- else if (!strcmp(ceppp->ce_varname, "duration"))
- tlsoptions->sts_duration = config_checkval(ceppp->ce_vardata, CFG_TIME);
- else if (!strcmp(ceppp->ce_varname, "preload"))
- tlsoptions->sts_preload = config_checkval(ceppp->ce_vardata, CFG_YESNO);
+ if (!strcmp(ceppp->name, "port"))
+ tlsoptions->sts_port = atoi(ceppp->value);
+ else if (!strcmp(ceppp->name, "duration"))
+ tlsoptions->sts_duration = config_checkval(ceppp->value, CFG_TIME);
+ else if (!strcmp(ceppp->name, "preload"))
+ tlsoptions->sts_preload = config_checkval(ceppp->value, CFG_YESNO);
}
}
}
@@ -7471,258 +7143,291 @@ int _conf_set(ConfigFile *conf, ConfigEntry *ce)
ConfigEntry *cep, *cepp, *ceppp, *cep4;
Hook *h;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "kline-address")) {
- safe_strdup(tempiConf.kline_address, cep->ce_vardata);
+ if (!strcmp(cep->name, "kline-address")) {
+ safe_strdup(tempiConf.kline_address, cep->value);
}
- if (!strcmp(cep->ce_varname, "gline-address")) {
- safe_strdup(tempiConf.gline_address, cep->ce_vardata);
+ if (!strcmp(cep->name, "gline-address")) {
+ safe_strdup(tempiConf.gline_address, cep->value);
}
- else if (!strcmp(cep->ce_varname, "modes-on-connect")) {
- tempiConf.conn_modes = (long) set_usermode(cep->ce_vardata);
+ else if (!strcmp(cep->name, "modes-on-connect")) {
+ tempiConf.conn_modes = (long) set_usermode(cep->value);
}
- else if (!strcmp(cep->ce_varname, "modes-on-oper")) {
- tempiConf.oper_modes = (long) set_usermode(cep->ce_vardata);
+ else if (!strcmp(cep->name, "modes-on-oper")) {
+ tempiConf.oper_modes = (long) set_usermode(cep->value);
}
- else if (!strcmp(cep->ce_varname, "modes-on-join")) {
- conf_channelmodes(cep->ce_vardata, &tempiConf.modes_on_join, 0);
+ else if (!strcmp(cep->name, "modes-on-join")) {
+ conf_channelmodes(cep->value, &tempiConf.modes_on_join);
+ tempiConf.modes_on_join_set = 1;
}
- else if (!strcmp(cep->ce_varname, "snomask-on-oper")) {
- safe_strdup(tempiConf.oper_snomask, cep->ce_vardata);
+ else if (!strcmp(cep->name, "snomask-on-oper")) {
+ safe_strdup(tempiConf.oper_snomask, cep->value);
}
- else if (!strcmp(cep->ce_varname, "level-on-join")) {
- tempiConf.level_on_join = channellevel_to_int(cep->ce_vardata);
+ else if (!strcmp(cep->name, "server-notice-colors")) {
+ tempiConf.server_notice_colors = config_checkval(cep->value, CFG_YESNO);
}
- else if (!strcmp(cep->ce_varname, "static-quit")) {
- safe_strdup(tempiConf.static_quit, cep->ce_vardata);
+ else if (!strcmp(cep->name, "level-on-join")) {
+ const char *res = channellevel_to_string(cep->value); /* 'halfop', etc */
+ if (!res)
+ {
+ /* This check needs to be here, in config run, because
+ * now the channel modules are initialized and we know
+ * which ones are available. This same information is
+ * not available during config test, so we can't test
+ * for it there like we normally do.
+ */
+ if (!valid_channel_access_mode_letter(*cep->value))
+ {
+ config_warn("%s:%d: set::level-on-join: Unknown mode (access level) '%c'. "
+ "That mode does not exist or is not a valid access mode "
+ "like vhoaq.",
+ cep->file->filename, cep->line_number,
+ *cep->value);
+ config_warn("Falling back to to set::level-on-join none; now. "
+ "This is probably not what you want!!!");
+ }
+ res = cep->value; /* if we reach this.. then it is a single letter */
+ }
+ safe_strdup(tempiConf.level_on_join, res);
}
- else if (!strcmp(cep->ce_varname, "static-part")) {
- safe_strdup(tempiConf.static_part, cep->ce_vardata);
+ else if (!strcmp(cep->name, "static-quit")) {
+ safe_strdup(tempiConf.static_quit, cep->value);
}
- else if (!strcmp(cep->ce_varname, "who-limit")) {
- tempiConf.who_limit = atol(cep->ce_vardata);
+ else if (!strcmp(cep->name, "static-part")) {
+ safe_strdup(tempiConf.static_part, cep->value);
}
- else if (!strcmp(cep->ce_varname, "maxbans")) {
- tempiConf.maxbans = atol(cep->ce_vardata);
+ else if (!strcmp(cep->name, "who-limit")) {
+ tempiConf.who_limit = atol(cep->value);
}
- else if (!strcmp(cep->ce_varname, "maxbanlength")) {
- tempiConf.maxbanlength = atol(cep->ce_vardata);
+ else if (!strcmp(cep->name, "maxbans")) {
+ tempiConf.maxbans = atol(cep->value);
}
- else if (!strcmp(cep->ce_varname, "silence-limit")) {
- tempiConf.silence_limit = atol(cep->ce_vardata);
+ else if (!strcmp(cep->name, "maxbanlength")) {
+ tempiConf.maxbanlength = atol(cep->value);
}
- else if (!strcmp(cep->ce_varname, "auto-join")) {
- safe_strdup(tempiConf.auto_join_chans, cep->ce_vardata);
+ else if (!strcmp(cep->name, "silence-limit")) {
+ tempiConf.silence_limit = atol(cep->value);
}
- else if (!strcmp(cep->ce_varname, "oper-auto-join")) {
- safe_strdup(tempiConf.oper_auto_join_chans, cep->ce_vardata);
+ else if (!strcmp(cep->name, "auto-join")) {
+ safe_strdup(tempiConf.auto_join_chans, cep->value);
}
- else if (!strcmp(cep->ce_varname, "check-target-nick-bans")) {
- tempiConf.check_target_nick_bans = config_checkval(cep->ce_vardata, CFG_YESNO);
+ else if (!strcmp(cep->name, "oper-auto-join")) {
+ safe_strdup(tempiConf.oper_auto_join_chans, cep->value);
}
- else if (!strcmp(cep->ce_varname, "ping-cookie")) {
- tempiConf.ping_cookie = config_checkval(cep->ce_vardata, CFG_YESNO);
+ else if (!strcmp(cep->name, "check-target-nick-bans")) {
+ tempiConf.check_target_nick_bans = config_checkval(cep->value, CFG_YESNO);
}
- else if (!strcmp(cep->ce_varname, "watch-away-notification")) {
- tempiConf.watch_away_notification = config_checkval(cep->ce_vardata, CFG_YESNO);
+ else if (!strcmp(cep->name, "ping-cookie")) {
+ tempiConf.ping_cookie = config_checkval(cep->value, CFG_YESNO);
}
- else if (!strcmp(cep->ce_varname, "uhnames")) {
- tempiConf.uhnames = config_checkval(cep->ce_vardata, CFG_YESNO);
+ else if (!strcmp(cep->name, "watch-away-notification")) {
+ tempiConf.watch_away_notification = config_checkval(cep->value, CFG_YESNO);
}
- else if (!strcmp(cep->ce_varname, "allow-userhost-change")) {
- if (!strcasecmp(cep->ce_vardata, "always"))
+ else if (!strcmp(cep->name, "uhnames")) {
+ tempiConf.uhnames = config_checkval(cep->value, CFG_YESNO);
+ }
+ else if (!strcmp(cep->name, "allow-userhost-change")) {
+ if (!strcasecmp(cep->value, "always"))
tempiConf.userhost_allowed = UHALLOW_ALWAYS;
- else if (!strcasecmp(cep->ce_vardata, "never"))
+ else if (!strcasecmp(cep->value, "never"))
tempiConf.userhost_allowed = UHALLOW_NEVER;
- else if (!strcasecmp(cep->ce_vardata, "not-on-channels"))
+ else if (!strcasecmp(cep->value, "not-on-channels"))
tempiConf.userhost_allowed = UHALLOW_NOCHANS;
else
tempiConf.userhost_allowed = UHALLOW_REJOIN;
}
- else if (!strcmp(cep->ce_varname, "channel-command-prefix")) {
- safe_strdup(tempiConf.channel_command_prefix, cep->ce_vardata);
+ else if (!strcmp(cep->name, "channel-command-prefix")) {
+ safe_strdup(tempiConf.channel_command_prefix, cep->value);
}
- else if (!strcmp(cep->ce_varname, "restrict-usermodes")) {
+ else if (!strcmp(cep->name, "restrict-usermodes")) {
int i;
- char *p = safe_alloc(strlen(cep->ce_vardata) + 1), *x = p;
+ char *p = safe_alloc(strlen(cep->value) + 1), *x = p;
/* The data should be something like 'Gw' or something,
* but just in case users use '+Gw' then ignore the + (and -).
*/
- for (i=0; i < strlen(cep->ce_vardata); i++)
- if ((cep->ce_vardata[i] != '+') && (cep->ce_vardata[i] != '-'))
- *x++ = cep->ce_vardata[i];
+ for (i=0; i < strlen(cep->value); i++)
+ if ((cep->value[i] != '+') && (cep->value[i] != '-'))
+ *x++ = cep->value[i];
*x = '\0';
tempiConf.restrict_usermodes = p;
}
- else if (!strcmp(cep->ce_varname, "restrict-channelmodes")) {
+ else if (!strcmp(cep->name, "restrict-channelmodes")) {
int i;
- char *p = safe_alloc(strlen(cep->ce_vardata) + 1), *x = p;
+ char *p = safe_alloc(strlen(cep->value) + 1), *x = p;
/* The data should be something like 'GL' or something,
* but just in case users use '+GL' then ignore the + (and -).
*/
- for (i=0; i < strlen(cep->ce_vardata); i++)
- if ((cep->ce_vardata[i] != '+') && (cep->ce_vardata[i] != '-'))
- *x++ = cep->ce_vardata[i];
+ for (i=0; i < strlen(cep->value); i++)
+ if ((cep->value[i] != '+') && (cep->value[i] != '-'))
+ *x++ = cep->value[i];
*x = '\0';
tempiConf.restrict_channelmodes = p;
}
- else if (!strcmp(cep->ce_varname, "restrict-extendedbans")) {
- safe_strdup(tempiConf.restrict_extendedbans, cep->ce_vardata);
+ else if (!strcmp(cep->name, "restrict-extendedbans")) {
+ safe_strdup(tempiConf.restrict_extendedbans, cep->value);
}
- else if (!strcmp(cep->ce_varname, "anti-spam-quit-message-time")) {
- tempiConf.anti_spam_quit_message_time = config_checkval(cep->ce_vardata,CFG_TIME);
+ else if (!strcmp(cep->name, "named-extended-bans")) {
+ tempiConf.named_extended_bans = config_checkval(cep->value, CFG_YESNO);
}
- else if (!strcmp(cep->ce_varname, "allow-user-stats")) {
- if (!cep->ce_entries)
+ else if (!strcmp(cep->name, "anti-spam-quit-message-time")) {
+ tempiConf.anti_spam_quit_message_time = config_checkval(cep->value,CFG_TIME);
+ }
+ else if (!strcmp(cep->name, "allow-user-stats")) {
+ if (!cep->items)
{
- safe_strdup(tempiConf.allow_user_stats, cep->ce_vardata);
+ safe_strdup(tempiConf.allow_user_stats, cep->value);
}
else
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
OperStat *os = safe_alloc(sizeof(OperStat));
- safe_strdup(os->flag, cepp->ce_varname);
+ safe_strdup(os->flag, cepp->name);
AddListItem(os, tempiConf.allow_user_stats_ext);
}
}
}
- else if (!strcmp(cep->ce_varname, "maxchannelsperuser")) {
- tempiConf.maxchannelsperuser = atoi(cep->ce_vardata);
+ else if (!strcmp(cep->name, "maxchannelsperuser")) {
+ tempiConf.maxchannelsperuser = atoi(cep->value);
}
- else if (!strcmp(cep->ce_varname, "ping-warning")) {
- tempiConf.ping_warning = atoi(cep->ce_vardata);
+ else if (!strcmp(cep->name, "ping-warning")) {
+ tempiConf.ping_warning = atoi(cep->value);
}
- else if (!strcmp(cep->ce_varname, "maxdccallow")) {
- tempiConf.maxdccallow = atoi(cep->ce_vardata);
+ else if (!strcmp(cep->name, "maxdccallow")) {
+ tempiConf.maxdccallow = atoi(cep->value);
}
- else if (!strcmp(cep->ce_varname, "max-targets-per-command"))
+ else if (!strcmp(cep->name, "max-targets-per-command"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
int v;
- if (!strcmp(cepp->ce_vardata, "max"))
+ if (!strcmp(cepp->value, "max"))
v = MAXTARGETS_MAX;
else
- v = atoi(cepp->ce_vardata);
- setmaxtargets(cepp->ce_varname, v);
+ v = atoi(cepp->value);
+ setmaxtargets(cepp->name, v);
}
}
- else if (!strcmp(cep->ce_varname, "network-name")) {
+ else if (!strcmp(cep->name, "network-name")) {
char *tmp;
- safe_strdup(tempiConf.network.x_ircnetwork, cep->ce_vardata);
- for (tmp = cep->ce_vardata; *cep->ce_vardata; cep->ce_vardata++) {
- if (*cep->ce_vardata == ' ')
- *cep->ce_vardata='-';
+ safe_strdup(tempiConf.network_name, cep->value);
+ for (tmp = cep->value; *cep->value; cep->value++) {
+ if (*cep->value == ' ')
+ *cep->value='-';
}
- safe_strdup(tempiConf.network.x_ircnet005, tmp);
- cep->ce_vardata = tmp;
+ safe_strdup(tempiConf.network_name_005, tmp);
+ cep->value = tmp;
}
- else if (!strcmp(cep->ce_varname, "default-server")) {
- safe_strdup(tempiConf.network.x_defserv, cep->ce_vardata);
+ else if (!strcmp(cep->name, "default-server")) {
+ safe_strdup(tempiConf.default_server, cep->value);
}
- else if (!strcmp(cep->ce_varname, "services-server")) {
- safe_strdup(tempiConf.network.x_services_name, cep->ce_vardata);
+ else if (!strcmp(cep->name, "services-server")) {
+ safe_strdup(tempiConf.services_name, cep->value);
}
- else if (!strcmp(cep->ce_varname, "sasl-server")) {
- safe_strdup(tempiConf.network.x_sasl_server, cep->ce_vardata);
+ else if (!strcmp(cep->name, "sasl-server")) {
+ safe_strdup(tempiConf.sasl_server, cep->value);
}
- else if (!strcmp(cep->ce_varname, "stats-server")) {
- safe_strdup(tempiConf.network.x_stats_server, cep->ce_vardata);
+ else if (!strcmp(cep->name, "stats-server")) {
+ safe_strdup(tempiConf.stats_server, cep->value);
}
- else if (!strcmp(cep->ce_varname, "help-channel")) {
- safe_strdup(tempiConf.network.x_helpchan, cep->ce_vardata);
+ else if (!strcmp(cep->name, "help-channel")) {
+ safe_strdup(tempiConf.helpchan, cep->value);
}
- else if (!strcmp(cep->ce_varname, "hiddenhost-prefix")) {
- safe_strdup(tempiConf.network.x_hidden_host, cep->ce_vardata);
+ else if (!strcmp(cep->name, "cloak-prefix") || !strcmp(cep->name, "hiddenhost-prefix")) {
+ safe_strdup(tempiConf.cloak_prefix, cep->value);
}
- else if (!strcmp(cep->ce_varname, "hide-ban-reason")) {
- tempiConf.hide_ban_reason = config_checkval(cep->ce_vardata, CFG_YESNO);
+ else if (!strcmp(cep->name, "hide-ban-reason")) {
+ tempiConf.hide_ban_reason = config_checkval(cep->value, CFG_YESNO);
}
- else if (!strcmp(cep->ce_varname, "prefix-quit")) {
- if (!strcmp(cep->ce_vardata, "0") || !strcmp(cep->ce_vardata, "no"))
- safe_free(tempiConf.network.x_prefix_quit);
+ else if (!strcmp(cep->name, "prefix-quit")) {
+ if (!strcmp(cep->value, "0") || !strcmp(cep->value, "no"))
+ safe_free(tempiConf.prefix_quit);
else
- safe_strdup(tempiConf.network.x_prefix_quit, cep->ce_vardata);
+ safe_strdup(tempiConf.prefix_quit, cep->value);
}
- else if (!strcmp(cep->ce_varname, "link")) {
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next) {
- if (!strcmp(cepp->ce_varname, "bind-ip")) {
- safe_strdup(tempiConf.link_bindip, cepp->ce_vardata);
+ else if (!strcmp(cep->name, "link")) {
+ for (cepp = cep->items; cepp; cepp = cepp->next) {
+ if (!strcmp(cepp->name, "bind-ip")) {
+ safe_strdup(tempiConf.link_bindip, cepp->value);
}
}
}
- else if (!strcmp(cep->ce_varname, "dns")) {
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next) {
- if (!strcmp(cepp->ce_varname, "bind-ip")) {
- safe_strdup(tempiConf.dns_bindip, cepp->ce_vardata);
- }
- }
- }
- else if (!strcmp(cep->ce_varname, "anti-flood")) {
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ else if (!strcmp(cep->name, "anti-flood")) {
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- for (ceppp = cepp->ce_entries; ceppp; ceppp = ceppp->ce_next)
+ int lag_penalty = -1;
+ int lag_penalty_bytes = -1;
+ for (ceppp = cepp->items; ceppp; ceppp = ceppp->next)
{
- if (!strcmp(ceppp->ce_varname, "handshake-data-flood"))
+ if (!strcmp(ceppp->name, "handshake-data-flood"))
{
- for (cep4 = ceppp->ce_entries; cep4; cep4 = cep4->ce_next)
+ for (cep4 = ceppp->items; cep4; cep4 = cep4->next)
{
- if (!strcmp(cep4->ce_varname, "amount"))
- tempiConf.handshake_data_flood_amount = config_checkval(cep4->ce_vardata, CFG_SIZE);
- else if (!strcmp(cep4->ce_varname, "ban-time"))
- tempiConf.handshake_data_flood_ban_time = config_checkval(cep4->ce_vardata, CFG_TIME);
- else if (!strcmp(cep4->ce_varname, "ban-action"))
- tempiConf.handshake_data_flood_ban_action = banact_stringtoval(cep4->ce_vardata);
+ if (!strcmp(cep4->name, "amount"))
+ tempiConf.handshake_data_flood_amount = config_checkval(cep4->value, CFG_SIZE);
+ else if (!strcmp(cep4->name, "ban-time"))
+ tempiConf.handshake_data_flood_ban_time = config_checkval(cep4->value, CFG_TIME);
+ else if (!strcmp(cep4->name, "ban-action"))
+ tempiConf.handshake_data_flood_ban_action = banact_stringtoval(cep4->value);
}
}
- else if (!strcmp(ceppp->ce_varname, "away-flood"))
+ else if (!strcmp(ceppp->name, "away-flood"))
{
- config_parse_flood_generic(ceppp->ce_vardata, &tempiConf, cepp->ce_varname, FLD_AWAY);
+ config_parse_flood_generic(ceppp->value, &tempiConf, cepp->name, FLD_AWAY);
}
- else if (!strcmp(ceppp->ce_varname, "nick-flood"))
+ else if (!strcmp(ceppp->name, "nick-flood"))
{
- config_parse_flood_generic(ceppp->ce_vardata, &tempiConf, cepp->ce_varname, FLD_NICK);
+ config_parse_flood_generic(ceppp->value, &tempiConf, cepp->name, FLD_NICK);
}
- else if (!strcmp(ceppp->ce_varname, "join-flood"))
+ else if (!strcmp(ceppp->name, "join-flood"))
{
- config_parse_flood_generic(ceppp->ce_vardata, &tempiConf, cepp->ce_varname, FLD_JOIN);
+ config_parse_flood_generic(ceppp->value, &tempiConf, cepp->name, FLD_JOIN);
}
- else if (!strcmp(ceppp->ce_varname, "invite-flood"))
+ else if (!strcmp(ceppp->name, "invite-flood"))
{
- config_parse_flood_generic(ceppp->ce_vardata, &tempiConf, cepp->ce_varname, FLD_INVITE);
+ config_parse_flood_generic(ceppp->value, &tempiConf, cepp->name, FLD_INVITE);
}
- else if (!strcmp(ceppp->ce_varname, "knock-flood"))
+ else if (!strcmp(ceppp->name, "knock-flood"))
{
- config_parse_flood_generic(ceppp->ce_vardata, &tempiConf, cepp->ce_varname, FLD_KNOCK);
+ config_parse_flood_generic(ceppp->value, &tempiConf, cepp->name, FLD_KNOCK);
}
- else if (!strcmp(ceppp->ce_varname, "connect-flood"))
+ else if (!strcmp(ceppp->name, "lag-penalty"))
+ {
+ lag_penalty = atoi(ceppp->value);
+ }
+ else if (!strcmp(ceppp->name, "lag-penalty-bytes"))
+ {
+ lag_penalty_bytes = config_checkval(ceppp->value, CFG_SIZE);
+ if (lag_penalty_bytes <= 0)
+ lag_penalty_bytes = INT_MAX;
+ }
+ else if (!strcmp(ceppp->name, "connect-flood"))
{
int cnt, period;
- config_parse_flood(ceppp->ce_vardata, &cnt, &period);
+ config_parse_flood(ceppp->value, &cnt, &period);
tempiConf.throttle_count = cnt;
tempiConf.throttle_period = period;
}
- if (!strcmp(ceppp->ce_varname, "max-concurrent-conversations"))
+ if (!strcmp(ceppp->name, "max-concurrent-conversations"))
{
/* We use a hack here to make it fit our storage format */
char buf[64];
int users=0;
long every=0;
- for (cep4 = ceppp->ce_entries; cep4; cep4 = cep4->ce_next)
+ for (cep4 = ceppp->items; cep4; cep4 = cep4->next)
{
- if (!strcmp(cep4->ce_varname, "users"))
+ if (!strcmp(cep4->name, "users"))
{
- users = atoi(cep4->ce_vardata);
+ users = atoi(cep4->value);
} else
- if (!strcmp(cep4->ce_varname, "new-user-every"))
+ if (!strcmp(cep4->name, "new-user-every"))
{
- every = config_checkval(cep4->ce_vardata, CFG_TIME);
+ every = config_checkval(cep4->value, CFG_TIME);
}
}
snprintf(buf, sizeof(buf), "%d:%ld", users, every);
- config_parse_flood_generic(buf, &tempiConf, cepp->ce_varname, FLD_CONVERSATIONS);
+ config_parse_flood_generic(buf, &tempiConf, cepp->name, FLD_CONVERSATIONS);
}
else
{
@@ -7734,52 +7439,59 @@ int _conf_set(ConfigFile *conf, ConfigEntry *ce)
}
}
}
+ if ((lag_penalty != -1) && (lag_penalty_bytes != -1))
+ {
+ /* We use a hack here to make it fit our storage format */
+ char buf[64];
+ snprintf(buf, sizeof(buf), "%d:%d", lag_penalty_bytes, lag_penalty);
+ config_parse_flood_generic(buf, &tempiConf, cepp->name, FLD_LAG_PENALTY);
+ }
}
}
- else if (!strcmp(cep->ce_varname, "options")) {
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next) {
- if (!strcmp(cepp->ce_varname, "hide-ulines")) {
+ else if (!strcmp(cep->name, "options")) {
+ for (cepp = cep->items; cepp; cepp = cepp->next) {
+ if (!strcmp(cepp->name, "hide-ulines")) {
tempiConf.hide_ulines = 1;
}
- else if (!strcmp(cepp->ce_varname, "flat-map")) {
+ else if (!strcmp(cepp->name, "flat-map")) {
tempiConf.flat_map = 1;
}
- else if (!strcmp(cepp->ce_varname, "show-opermotd")) {
- tempiConf.som = 1;
+ else if (!strcmp(cepp->name, "show-opermotd")) {
+ tempiConf.show_opermotd = 1;
}
- else if (!strcmp(cepp->ce_varname, "identd-check")) {
+ else if (!strcmp(cepp->name, "identd-check")) {
tempiConf.ident_check = 1;
}
- else if (!strcmp(cepp->ce_varname, "fail-oper-warn")) {
+ else if (!strcmp(cepp->name, "fail-oper-warn")) {
tempiConf.fail_oper_warn = 1;
}
- else if (!strcmp(cepp->ce_varname, "show-connect-info")) {
+ else if (!strcmp(cepp->name, "show-connect-info")) {
tempiConf.show_connect_info = 1;
}
- else if (!strcmp(cepp->ce_varname, "no-connect-tls-info")) {
+ else if (!strcmp(cepp->name, "no-connect-tls-info")) {
tempiConf.no_connect_tls_info = 1;
}
- else if (!strcmp(cepp->ce_varname, "dont-resolve")) {
+ else if (!strcmp(cepp->name, "dont-resolve")) {
tempiConf.dont_resolve = 1;
}
- else if (!strcmp(cepp->ce_varname, "mkpasswd-for-everyone")) {
+ else if (!strcmp(cepp->name, "mkpasswd-for-everyone")) {
tempiConf.mkpasswd_for_everyone = 1;
}
- else if (!strcmp(cepp->ce_varname, "allow-insane-bans")) {
+ else if (!strcmp(cepp->name, "allow-insane-bans")) {
tempiConf.allow_insane_bans = 1;
}
- else if (!strcmp(cepp->ce_varname, "allow-part-if-shunned")) {
+ else if (!strcmp(cepp->name, "allow-part-if-shunned")) {
tempiConf.allow_part_if_shunned = 1;
}
- else if (!strcmp(cepp->ce_varname, "disable-cap")) {
+ else if (!strcmp(cepp->name, "disable-cap")) {
tempiConf.disable_cap = 1;
}
- else if (!strcmp(cepp->ce_varname, "disable-ipv6")) {
+ else if (!strcmp(cepp->name, "disable-ipv6")) {
/* other code handles this */
}
}
}
- else if (!strcmp(cep->ce_varname, "cloak-keys"))
+ else if (!strcmp(cep->name, "cloak-keys"))
{
for (h = Hooks[HOOKTYPE_CONFIGRUN]; h; h = h->next)
{
@@ -7789,34 +7501,34 @@ int _conf_set(ConfigFile *conf, ConfigEntry *ce)
break;
}
}
- else if (!strcmp(cep->ce_varname, "ident"))
+ else if (!strcmp(cep->name, "ident"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "connect-timeout"))
- tempiConf.ident_connect_timeout = config_checkval(cepp->ce_vardata,CFG_TIME);
- if (!strcmp(cepp->ce_varname, "read-timeout"))
- tempiConf.ident_read_timeout = config_checkval(cepp->ce_vardata,CFG_TIME);
+ if (!strcmp(cepp->name, "connect-timeout"))
+ tempiConf.ident_connect_timeout = config_checkval(cepp->value,CFG_TIME);
+ if (!strcmp(cepp->name, "read-timeout"))
+ tempiConf.ident_read_timeout = config_checkval(cepp->value,CFG_TIME);
}
}
- else if (!strcmp(cep->ce_varname, "spamfilter"))
+ else if (!strcmp(cep->name, "spamfilter"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "ban-time"))
- tempiConf.spamfilter_ban_time = config_checkval(cepp->ce_vardata,CFG_TIME);
- else if (!strcmp(cepp->ce_varname, "ban-reason"))
- safe_strdup(tempiConf.spamfilter_ban_reason, cepp->ce_vardata);
- else if (!strcmp(cepp->ce_varname, "virus-help-channel"))
- safe_strdup(tempiConf.spamfilter_virus_help_channel, cepp->ce_vardata);
- else if (!strcmp(cepp->ce_varname, "virus-help-channel-deny"))
- tempiConf.spamfilter_vchan_deny = config_checkval(cepp->ce_vardata,CFG_YESNO);
- else if (!strcmp(cepp->ce_varname, "except"))
+ if (!strcmp(cepp->name, "ban-time"))
+ tempiConf.spamfilter_ban_time = config_checkval(cepp->value,CFG_TIME);
+ else if (!strcmp(cepp->name, "ban-reason"))
+ safe_strdup(tempiConf.spamfilter_ban_reason, cepp->value);
+ else if (!strcmp(cepp->name, "virus-help-channel"))
+ safe_strdup(tempiConf.spamfilter_virus_help_channel, cepp->value);
+ else if (!strcmp(cepp->name, "virus-help-channel-deny"))
+ tempiConf.spamfilter_vchan_deny = config_checkval(cepp->value,CFG_YESNO);
+ else if (!strcmp(cepp->name, "except"))
{
char *name, *p;
SpamExcept *e;
- safe_strdup(tempiConf.spamexcept_line, cepp->ce_vardata);
- for (name = strtoken(&p, cepp->ce_vardata, ","); name; name = strtoken(&p, NULL, ","))
+ safe_strdup(tempiConf.spamexcept_line, cepp->value);
+ for (name = strtoken(&p, cepp->value, ","); name; name = strtoken(&p, NULL, ","))
{
if (*name == ' ')
name++;
@@ -7828,186 +7540,185 @@ int _conf_set(ConfigFile *conf, ConfigEntry *ce)
}
}
}
- else if (!strcmp(cepp->ce_varname, "detect-slow-warn"))
+ else if (!strcmp(cepp->name, "detect-slow-warn"))
{
- tempiConf.spamfilter_detectslow_warn = atol(cepp->ce_vardata);
+ tempiConf.spamfilter_detectslow_warn = atol(cepp->value);
}
- else if (!strcmp(cepp->ce_varname, "detect-slow-fatal"))
+ else if (!strcmp(cepp->name, "detect-slow-fatal"))
{
- tempiConf.spamfilter_detectslow_fatal = atol(cepp->ce_vardata);
+ tempiConf.spamfilter_detectslow_fatal = atol(cepp->value);
}
- else if (!strcmp(cepp->ce_varname, "stop-on-first-match"))
+ else if (!strcmp(cepp->name, "stop-on-first-match"))
{
- tempiConf.spamfilter_stop_on_first_match = config_checkval(cepp->ce_vardata, CFG_YESNO);
+ tempiConf.spamfilter_stop_on_first_match = config_checkval(cepp->value, CFG_YESNO);
}
}
}
- else if (!strcmp(cep->ce_varname, "default-bantime"))
+ else if (!strcmp(cep->name, "default-bantime"))
{
- tempiConf.default_bantime = config_checkval(cep->ce_vardata,CFG_TIME);
+ tempiConf.default_bantime = config_checkval(cep->value,CFG_TIME);
}
- else if (!strcmp(cep->ce_varname, "ban-version-tkl-time"))
+ else if (!strcmp(cep->name, "ban-version-tkl-time"))
{
- tempiConf.ban_version_tkl_time = config_checkval(cep->ce_vardata,CFG_TIME);
+ tempiConf.ban_version_tkl_time = config_checkval(cep->value,CFG_TIME);
}
- else if (!strcmp(cep->ce_varname, "min-nick-length")) {
- int v = atoi(cep->ce_vardata);
+ else if (!strcmp(cep->name, "min-nick-length")) {
+ int v = atoi(cep->value);
tempiConf.min_nick_length = v;
}
- else if (!strcmp(cep->ce_varname, "nick-length")) {
- int v = atoi(cep->ce_vardata);
+ else if (!strcmp(cep->name, "nick-length")) {
+ int v = atoi(cep->value);
tempiConf.nick_length = v;
}
- else if (!strcmp(cep->ce_varname, "topic-length")) {
- int v = atoi(cep->ce_vardata);
+ else if (!strcmp(cep->name, "topic-length")) {
+ int v = atoi(cep->value);
tempiConf.topic_length = v;
}
- else if (!strcmp(cep->ce_varname, "away-length")) {
- int v = atoi(cep->ce_vardata);
+ else if (!strcmp(cep->name, "away-length")) {
+ int v = atoi(cep->value);
tempiConf.away_length = v;
}
- else if (!strcmp(cep->ce_varname, "kick-length")) {
- int v = atoi(cep->ce_vardata);
+ else if (!strcmp(cep->name, "kick-length")) {
+ int v = atoi(cep->value);
tempiConf.kick_length = v;
}
- else if (!strcmp(cep->ce_varname, "quit-length")) {
- int v = atoi(cep->ce_vardata);
+ else if (!strcmp(cep->name, "quit-length")) {
+ int v = atoi(cep->value);
tempiConf.quit_length = v;
}
- else if (!strcmp(cep->ce_varname, "ssl") || !strcmp(cep->ce_varname, "tls")) {
+ else if (!strcmp(cep->name, "ssl") || !strcmp(cep->name, "tls")) {
/* no need to alloc tempiConf.tls_options since config_defaults() already ensures it exists */
conf_tlsblock(conf, cep, tempiConf.tls_options);
}
- else if (!strcmp(cep->ce_varname, "plaintext-policy"))
+ else if (!strcmp(cep->name, "plaintext-policy"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "user"))
- tempiConf.plaintext_policy_user = policy_strtoval(cepp->ce_vardata);
- else if (!strcmp(cepp->ce_varname, "oper"))
- tempiConf.plaintext_policy_oper = policy_strtoval(cepp->ce_vardata);
- else if (!strcmp(cepp->ce_varname, "server"))
- tempiConf.plaintext_policy_server = policy_strtoval(cepp->ce_vardata);
- else if (!strcmp(cepp->ce_varname, "user-message"))
- addmultiline(&tempiConf.plaintext_policy_user_message, cepp->ce_vardata);
- else if (!strcmp(cepp->ce_varname, "oper-message"))
- addmultiline(&tempiConf.plaintext_policy_oper_message, cepp->ce_vardata);
+ if (!strcmp(cepp->name, "user"))
+ tempiConf.plaintext_policy_user = policy_strtoval(cepp->value);
+ else if (!strcmp(cepp->name, "oper"))
+ tempiConf.plaintext_policy_oper = policy_strtoval(cepp->value);
+ else if (!strcmp(cepp->name, "server"))
+ tempiConf.plaintext_policy_server = policy_strtoval(cepp->value);
+ else if (!strcmp(cepp->name, "user-message"))
+ addmultiline(&tempiConf.plaintext_policy_user_message, cepp->value);
+ else if (!strcmp(cepp->name, "oper-message"))
+ addmultiline(&tempiConf.plaintext_policy_oper_message, cepp->value);
}
}
- else if (!strcmp(cep->ce_varname, "outdated-tls-policy"))
+ else if (!strcmp(cep->name, "outdated-tls-policy"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "user"))
- tempiConf.outdated_tls_policy_user = policy_strtoval(cepp->ce_vardata);
- else if (!strcmp(cepp->ce_varname, "oper"))
- tempiConf.outdated_tls_policy_oper = policy_strtoval(cepp->ce_vardata);
- else if (!strcmp(cepp->ce_varname, "server"))
- tempiConf.outdated_tls_policy_server = policy_strtoval(cepp->ce_vardata);
- else if (!strcmp(cepp->ce_varname, "user-message"))
- safe_strdup(tempiConf.outdated_tls_policy_user_message, cepp->ce_vardata);
- else if (!strcmp(cepp->ce_varname, "oper-message"))
- safe_strdup(tempiConf.outdated_tls_policy_oper_message, cepp->ce_vardata);
+ if (!strcmp(cepp->name, "user"))
+ tempiConf.outdated_tls_policy_user = policy_strtoval(cepp->value);
+ else if (!strcmp(cepp->name, "oper"))
+ tempiConf.outdated_tls_policy_oper = policy_strtoval(cepp->value);
+ else if (!strcmp(cepp->name, "server"))
+ tempiConf.outdated_tls_policy_server = policy_strtoval(cepp->value);
+ else if (!strcmp(cepp->name, "user-message"))
+ safe_strdup(tempiConf.outdated_tls_policy_user_message, cepp->value);
+ else if (!strcmp(cepp->name, "oper-message"))
+ safe_strdup(tempiConf.outdated_tls_policy_oper_message, cepp->value);
}
}
- else if (!strcmp(cep->ce_varname, "default-ipv6-clone-mask"))
+ else if (!strcmp(cep->name, "default-ipv6-clone-mask"))
{
- tempiConf.default_ipv6_clone_mask = atoi(cep->ce_vardata);
+ tempiConf.default_ipv6_clone_mask = atoi(cep->value);
}
- else if (!strcmp(cep->ce_varname, "hide-list")) {
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ else if (!strcmp(cep->name, "hide-list")) {
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "deny-channel"))
+ if (!strcmp(cepp->name, "deny-channel"))
{
tempiConf.hide_list = 1;
/* if we would expand this later then change this to a bitmask or struct or whatever */
}
}
}
- else if (!strcmp(cep->ce_varname, "max-unknown-connections-per-ip"))
+ else if (!strcmp(cep->name, "max-unknown-connections-per-ip"))
{
- tempiConf.max_unknown_connections_per_ip = atoi(cep->ce_vardata);
+ tempiConf.max_unknown_connections_per_ip = atoi(cep->value);
}
- else if (!strcmp(cep->ce_varname, "handshake-timeout"))
+ else if (!strcmp(cep->name, "handshake-timeout"))
{
- tempiConf.handshake_timeout = config_checkval(cep->ce_vardata, CFG_TIME);
+ tempiConf.handshake_timeout = config_checkval(cep->value, CFG_TIME);
}
- else if (!strcmp(cep->ce_varname, "sasl-timeout"))
+ else if (!strcmp(cep->name, "sasl-timeout"))
{
- tempiConf.sasl_timeout = config_checkval(cep->ce_vardata, CFG_TIME);
+ tempiConf.sasl_timeout = config_checkval(cep->value, CFG_TIME);
}
- else if (!strcmp(cep->ce_varname, "handshake-delay"))
+ else if (!strcmp(cep->name, "handshake-delay"))
{
- tempiConf.handshake_delay = config_checkval(cep->ce_vardata, CFG_TIME);
+ tempiConf.handshake_delay = config_checkval(cep->value, CFG_TIME);
}
- else if (!strcmp(cep->ce_varname, "automatic-ban-target"))
+ else if (!strcmp(cep->name, "automatic-ban-target"))
{
- tempiConf.automatic_ban_target = ban_target_strtoval(cep->ce_vardata);
+ tempiConf.automatic_ban_target = ban_target_strtoval(cep->value);
}
- else if (!strcmp(cep->ce_varname, "manual-ban-target"))
+ else if (!strcmp(cep->name, "manual-ban-target"))
{
- tempiConf.manual_ban_target = ban_target_strtoval(cep->ce_vardata);
+ tempiConf.manual_ban_target = ban_target_strtoval(cep->value);
}
- else if (!strcmp(cep->ce_varname, "reject-message"))
+ else if (!strcmp(cep->name, "reject-message"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "too-many-connections"))
- safe_strdup(tempiConf.reject_message_too_many_connections, cepp->ce_vardata);
- else if (!strcmp(cepp->ce_varname, "server-full"))
- safe_strdup(tempiConf.reject_message_server_full, cepp->ce_vardata);
- else if (!strcmp(cepp->ce_varname, "unauthorized"))
- safe_strdup(tempiConf.reject_message_unauthorized, cepp->ce_vardata);
- else if (!strcmp(cepp->ce_varname, "kline"))
- safe_strdup(tempiConf.reject_message_kline, cepp->ce_vardata);
- else if (!strcmp(cepp->ce_varname, "gline"))
- safe_strdup(tempiConf.reject_message_gline, cepp->ce_vardata);
+ if (!strcmp(cepp->name, "too-many-connections"))
+ safe_strdup(tempiConf.reject_message_too_many_connections, cepp->value);
+ else if (!strcmp(cepp->name, "server-full"))
+ safe_strdup(tempiConf.reject_message_server_full, cepp->value);
+ else if (!strcmp(cepp->name, "unauthorized"))
+ safe_strdup(tempiConf.reject_message_unauthorized, cepp->value);
+ else if (!strcmp(cepp->name, "kline"))
+ safe_strdup(tempiConf.reject_message_kline, cepp->value);
+ else if (!strcmp(cepp->name, "gline"))
+ safe_strdup(tempiConf.reject_message_gline, cepp->value);
}
}
- else if (!strcmp(cep->ce_varname, "topic-setter"))
+ else if (!strcmp(cep->name, "topic-setter"))
{
- if (!strcmp(cep->ce_vardata, "nick"))
+ if (!strcmp(cep->value, "nick"))
tempiConf.topic_setter = SETTER_NICK;
- else if (!strcmp(cep->ce_vardata, "nick-user-host"))
+ else if (!strcmp(cep->value, "nick-user-host"))
tempiConf.topic_setter = SETTER_NICK_USER_HOST;
}
- else if (!strcmp(cep->ce_varname, "ban-setter"))
+ else if (!strcmp(cep->name, "ban-setter"))
{
- if (!strcmp(cep->ce_vardata, "nick"))
+ if (!strcmp(cep->value, "nick"))
tempiConf.ban_setter = SETTER_NICK;
- else if (!strcmp(cep->ce_vardata, "nick-user-host"))
+ else if (!strcmp(cep->value, "nick-user-host"))
tempiConf.ban_setter = SETTER_NICK_USER_HOST;
}
- else if (!strcmp(cep->ce_varname, "ban-setter-sync") || !strcmp(cep->ce_varname, "ban-setter-synch"))
+ else if (!strcmp(cep->name, "ban-setter-sync") || !strcmp(cep->name, "ban-setter-synch"))
{
- tempiConf.ban_setter_sync = config_checkval(cep->ce_vardata, CFG_YESNO);
+ tempiConf.ban_setter_sync = config_checkval(cep->value, CFG_YESNO);
}
- else if (!strcmp(cep->ce_varname, "part-instead-of-quit-on-comment-change"))
+ else if (!strcmp(cep->name, "part-instead-of-quit-on-comment-change"))
{
- tempiConf.part_instead_of_quit_on_comment_change = config_checkval(cep->ce_vardata, CFG_YESNO);
+ tempiConf.part_instead_of_quit_on_comment_change = config_checkval(cep->value, CFG_YESNO);
}
- else if (!strcmp(cep->ce_varname, "broadcast-channel-messages"))
+ else if (!strcmp(cep->name, "broadcast-channel-messages"))
{
- if (!strcmp(cep->ce_vardata, "auto"))
+ if (!strcmp(cep->value, "auto"))
tempiConf.broadcast_channel_messages = BROADCAST_CHANNEL_MESSAGES_AUTO;
- else if (!strcmp(cep->ce_vardata, "always"))
+ else if (!strcmp(cep->value, "always"))
tempiConf.broadcast_channel_messages = BROADCAST_CHANNEL_MESSAGES_ALWAYS;
- else if (!strcmp(cep->ce_vardata, "never"))
+ else if (!strcmp(cep->value, "never"))
tempiConf.broadcast_channel_messages = BROADCAST_CHANNEL_MESSAGES_NEVER;
}
- else if (!strcmp(cep->ce_varname, "allowed-channelchars"))
+ else if (!strcmp(cep->name, "allowed-channelchars"))
{
- tempiConf.allowed_channelchars = allowed_channelchars_strtoval(cep->ce_vardata);
+ tempiConf.allowed_channelchars = allowed_channelchars_strtoval(cep->value);
}
- else if (!strcmp(cep->ce_varname, "hide-idle-time"))
+ else if (!strcmp(cep->name, "hide-idle-time"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "policy"))
- tempiConf.hide_idle_time = hideidletime_strtoval(cepp->ce_vardata);
+ if (!strcmp(cepp->name, "policy"))
+ tempiConf.hide_idle_time = hideidletime_strtoval(cepp->value);
}
- }
- else
+ } else
{
int value;
for (h = Hooks[HOOKTYPE_CONFIGRUN]; h; h = h->next)
@@ -8028,62 +7739,61 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
int errors = 0;
Hook *h;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "kline-address")) {
+ if (!strcmp(cep->name, "kline-address")) {
CheckNull(cep);
CheckDuplicate(cep, kline_address, "kline-address");
- if (!strchr(cep->ce_vardata, '@') && !strchr(cep->ce_vardata, ':'))
+ if (!strchr(cep->value, '@') && !strchr(cep->value, ':'))
{
config_error("%s:%i: set::kline-address must be an e-mail or an URL",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
continue;
}
- else if (match_simple("*@unrealircd.com", cep->ce_vardata) || match_simple("*@unrealircd.org",cep->ce_vardata) || match_simple("unreal-*@lists.sourceforge.net",cep->ce_vardata))
+ else if (match_simple("*@unrealircd.com", cep->value) || match_simple("*@unrealircd.org",cep->value) || match_simple("unreal-*@lists.sourceforge.net",cep->value))
{
config_error("%s:%i: set::kline-address may not be an UnrealIRCd Team address",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++; continue;
}
}
- else if (!strcmp(cep->ce_varname, "gline-address")) {
+ else if (!strcmp(cep->name, "gline-address")) {
CheckNull(cep);
CheckDuplicate(cep, gline_address, "gline-address");
- if (!strchr(cep->ce_vardata, '@') && !strchr(cep->ce_vardata, ':'))
+ if (!strchr(cep->value, '@') && !strchr(cep->value, ':'))
{
config_error("%s:%i: set::gline-address must be an e-mail or an URL",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
continue;
}
- else if (match_simple("*@unrealircd.com", cep->ce_vardata) || match_simple("*@unrealircd.org",cep->ce_vardata) || match_simple("unreal-*@lists.sourceforge.net",cep->ce_vardata))
+ else if (match_simple("*@unrealircd.com", cep->value) || match_simple("*@unrealircd.org",cep->value) || match_simple("unreal-*@lists.sourceforge.net",cep->value))
{
config_error("%s:%i: set::gline-address may not be an UnrealIRCd Team address",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++; continue;
}
}
- else if (!strcmp(cep->ce_varname, "modes-on-connect")) {
+ else if (!strcmp(cep->name, "modes-on-connect")) {
char *p;
CheckNull(cep);
CheckDuplicate(cep, modes_on_connect, "modes-on-connect");
- for (p = cep->ce_vardata; *p; p++)
+ for (p = cep->value; *p; p++)
if (strchr("orzSHqtW", *p))
{
config_error("%s:%i: set::modes-on-connect may not include mode '%c'",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, *p);
+ cep->file->filename, cep->line_number, *p);
errors++;
}
- set_usermode(cep->ce_vardata);
}
- else if (!strcmp(cep->ce_varname, "modes-on-join")) {
+ else if (!strcmp(cep->name, "modes-on-join")) {
char *c;
struct ChMode temp;
memset(&temp, 0, sizeof(temp));
CheckNull(cep);
CheckDuplicate(cep, modes_on_join, "modes-on-join");
- for (c = cep->ce_vardata; *c; c++)
+ for (c = cep->value; *c; c++)
{
if (*c == ' ')
break; /* don't check the parameter ;p */
@@ -8097,340 +7807,340 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
case 'b':
case 'e':
case 'I':
- case 'k':
- case 'l':
config_error("%s:%i: set::modes-on-join may not contain +%c",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, *c);
+ cep->file->filename, cep->line_number, *c);
errors++;
break;
}
}
- conf_channelmodes(cep->ce_vardata, &temp, 1);
- if (temp.mode & MODE_SECRET && temp.mode & MODE_PRIVATE)
- {
- config_error("%s:%i: set::modes-on-join has both +s and +p",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
- errors++;
- }
-
+ /* We can't really verify much here.
+ * The channel mode modules have not been initialized
+ * yet at this point, so we can't really verify much
+ * here.
+ */
}
- else if (!strcmp(cep->ce_varname, "modes-on-oper")) {
+ else if (!strcmp(cep->name, "modes-on-oper")) {
char *p;
CheckNull(cep);
CheckDuplicate(cep, modes_on_oper, "modes-on-oper");
- for (p = cep->ce_vardata; *p; p++)
+ for (p = cep->value; *p; p++)
if (strchr("orzS", *p))
{
config_error("%s:%i: set::modes-on-oper may not include mode '%c'",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, *p);
+ cep->file->filename, cep->line_number, *p);
errors++;
}
- set_usermode(cep->ce_vardata);
+ set_usermode(cep->value);
}
- else if (!strcmp(cep->ce_varname, "snomask-on-oper")) {
+ else if (!strcmp(cep->name, "snomask-on-oper")) {
+ char *wrong_snomask;
CheckNull(cep);
CheckDuplicate(cep, snomask_on_oper, "snomask-on-oper");
+ if (!is_valid_snomask_string_testing(cep->value, &wrong_snomask))
+ {
+ config_error("%s:%i: set::snomask-on-oper contains unknown snomask letter(s) '%s'",
+ cep->file->filename, cep->line_number, wrong_snomask);
+ errors++;
+ invalid_snomasks_encountered++;
+ }
}
- else if (!strcmp(cep->ce_varname, "level-on-join")) {
+ else if (!strcmp(cep->name, "server-notice-colors")) {
+ CheckNull(cep);
+ }
+ else if (!strcmp(cep->name, "level-on-join")) {
CheckNull(cep);
CheckDuplicate(cep, level_on_join, "level-on-join");
- if (!channellevel_to_int(cep->ce_vardata))
+ if (!channellevel_to_string(cep->value) && (strlen(cep->value) != 1))
{
- config_error("%s:%i: set::level-on-join: unknown value '%s', should be one of: none, voice, halfop, op, protect, owner",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_vardata);
+ config_error("%s:%i: set::level-on-join: unknown value '%s', should be one of: "
+ "'none', 'voice', 'halfop', 'op', 'admin', 'owner', or a single letter (eg 'o')",
+ cep->file->filename, cep->line_number, cep->value);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "static-quit")) {
+ else if (!strcmp(cep->name, "static-quit")) {
CheckNull(cep);
CheckDuplicate(cep, static_quit, "static-quit");
}
- else if (!strcmp(cep->ce_varname, "static-part")) {
+ else if (!strcmp(cep->name, "static-part")) {
CheckNull(cep);
CheckDuplicate(cep, static_part, "static-part");
}
- else if (!strcmp(cep->ce_varname, "who-limit")) {
+ else if (!strcmp(cep->name, "who-limit")) {
CheckNull(cep);
CheckDuplicate(cep, who_limit, "who-limit");
- if (!config_checkval(cep->ce_vardata,CFG_SIZE))
+ if (!config_checkval(cep->value,CFG_SIZE))
{
config_error("%s:%i: set::who-limit: value must be at least 1",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "maxbans")) {
+ else if (!strcmp(cep->name, "maxbans")) {
CheckNull(cep);
CheckDuplicate(cep, maxbans, "maxbans");
}
- else if (!strcmp(cep->ce_varname, "maxbanlength")) {
+ else if (!strcmp(cep->name, "maxbanlength")) {
CheckNull(cep);
CheckDuplicate(cep, maxbanlength, "maxbanlength");
}
- else if (!strcmp(cep->ce_varname, "silence-limit")) {
+ else if (!strcmp(cep->name, "silence-limit")) {
CheckNull(cep);
CheckDuplicate(cep, silence_limit, "silence-limit");
}
- else if (!strcmp(cep->ce_varname, "auto-join")) {
+ else if (!strcmp(cep->name, "auto-join")) {
CheckNull(cep);
CheckDuplicate(cep, auto_join, "auto-join");
}
- else if (!strcmp(cep->ce_varname, "oper-auto-join")) {
+ else if (!strcmp(cep->name, "oper-auto-join")) {
CheckNull(cep);
CheckDuplicate(cep, oper_auto_join, "oper-auto-join");
}
- else if (!strcmp(cep->ce_varname, "check-target-nick-bans")) {
+ else if (!strcmp(cep->name, "check-target-nick-bans")) {
CheckNull(cep);
CheckDuplicate(cep, check_target_nick_bans, "check-target-nick-bans");
}
- else if (!strcmp(cep->ce_varname, "pingpong-warning")) {
+ else if (!strcmp(cep->name, "pingpong-warning")) {
config_error("%s:%i: set::pingpong-warning no longer exists (the warning is always off)",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
- need_34_upgrade = 1;
+ cep->file->filename, cep->line_number);
errors++;
}
- else if (!strcmp(cep->ce_varname, "ping-cookie")) {
+ else if (!strcmp(cep->name, "ping-cookie")) {
CheckNull(cep);
CheckDuplicate(cep, ping_cookie, "ping-cookie");
}
- else if (!strcmp(cep->ce_varname, "watch-away-notification")) {
+ else if (!strcmp(cep->name, "watch-away-notification")) {
CheckNull(cep);
CheckDuplicate(cep, watch_away_notification, "watch-away-notification");
}
- else if (!strcmp(cep->ce_varname, "uhnames")) {
+ else if (!strcmp(cep->name, "uhnames")) {
CheckNull(cep);
CheckDuplicate(cep, uhnames, "uhnames");
}
- else if (!strcmp(cep->ce_varname, "channel-command-prefix")) {
+ else if (!strcmp(cep->name, "channel-command-prefix")) {
CheckNullAllowEmpty(cep);
CheckDuplicate(cep, channel_command_prefix, "channel-command-prefix");
}
- else if (!strcmp(cep->ce_varname, "allow-userhost-change")) {
+ else if (!strcmp(cep->name, "allow-userhost-change")) {
CheckNull(cep);
CheckDuplicate(cep, allow_userhost_change, "allow-userhost-change");
- if (strcasecmp(cep->ce_vardata, "always") &&
- strcasecmp(cep->ce_vardata, "never") &&
- strcasecmp(cep->ce_vardata, "not-on-channels") &&
- strcasecmp(cep->ce_vardata, "force-rejoin"))
+ if (strcasecmp(cep->value, "always") &&
+ strcasecmp(cep->value, "never") &&
+ strcasecmp(cep->value, "not-on-channels") &&
+ strcasecmp(cep->value, "force-rejoin"))
{
config_error("%s:%i: set::allow-userhost-change is invalid",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum);
+ cep->file->filename,
+ cep->line_number);
errors++;
continue;
}
}
- else if (!strcmp(cep->ce_varname, "anti-spam-quit-message-time")) {
+ else if (!strcmp(cep->name, "anti-spam-quit-message-time")) {
CheckNull(cep);
CheckDuplicate(cep, anti_spam_quit_message_time, "anti-spam-quit-message-time");
}
- else if (!strcmp(cep->ce_varname, "oper-only-stats"))
+ else if (!strcmp(cep->name, "oper-only-stats"))
{
config_warn("%s:%d: We no longer use a blacklist for stats (set::oper-only-stats) but "
"have a whitelist now instead (set::allow-user-stats). ",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
config_warn("Simply delete the oper-only-stats line from your configuration file %s around line %d to get rid of this warning",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
continue;
}
- else if (!strcmp(cep->ce_varname, "allow-user-stats"))
+ else if (!strcmp(cep->name, "allow-user-stats"))
{
CheckDuplicate(cep, allow_user_stats, "allow-user-stats");
- if (!cep->ce_entries)
- {
- CheckNull(cep);
- }
- else
- {
- /* TODO: check the entries for existence?
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
- {
- } */
- }
+ CheckNull(cep);
}
- else if (!strcmp(cep->ce_varname, "maxchannelsperuser")) {
+ else if (!strcmp(cep->name, "maxchannelsperuser")) {
CheckNull(cep);
CheckDuplicate(cep, maxchannelsperuser, "maxchannelsperuser");
- tempi = atoi(cep->ce_vardata);
+ tempi = atoi(cep->value);
if (tempi < 1)
{
config_error("%s:%i: set::maxchannelsperuser must be > 0",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum);
+ cep->file->filename,
+ cep->line_number);
errors++;
continue;
}
}
- else if (!strcmp(cep->ce_varname, "ping-warning")) {
+ else if (!strcmp(cep->name, "ping-warning")) {
CheckNull(cep);
CheckDuplicate(cep, ping_warning, "ping-warning");
- tempi = atoi(cep->ce_vardata);
+ tempi = atoi(cep->value);
/* it is pointless to allow setting higher than 170 */
if (tempi > 170)
{
config_error("%s:%i: set::ping-warning must be < 170",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum);
+ cep->file->filename,
+ cep->line_number);
errors++;
continue;
}
}
- else if (!strcmp(cep->ce_varname, "maxdccallow")) {
+ else if (!strcmp(cep->name, "maxdccallow")) {
CheckNull(cep);
CheckDuplicate(cep, maxdccallow, "maxdccallow");
}
- else if (!strcmp(cep->ce_varname, "max-targets-per-command"))
+ else if (!strcmp(cep->name, "max-targets-per-command"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
CheckNull(cepp);
- if (!strcasecmp(cepp->ce_varname, "NAMES") || !strcasecmp(cepp->ce_varname, "WHOWAS"))
+ if (!strcasecmp(cepp->name, "NAMES") || !strcasecmp(cepp->name, "WHOWAS"))
{
- if (atoi(cepp->ce_vardata) != 1)
+ if (atoi(cepp->value) != 1)
{
config_error("%s:%i: set::max-targets-per-command::%s: "
"this command is hardcoded at a maximum of 1 "
"and cannot be configured to accept more.",
- cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum,
- cepp->ce_varname);
+ cepp->file->filename,
+ cepp->line_number,
+ cepp->name);
errors++;
}
} else
- if (!strcasecmp(cepp->ce_varname, "USERHOST") ||
- !strcasecmp(cepp->ce_varname, "USERIP") ||
- !strcasecmp(cepp->ce_varname, "ISON") ||
- !strcasecmp(cepp->ce_varname, "WATCH"))
+ if (!strcasecmp(cepp->name, "USERHOST") ||
+ !strcasecmp(cepp->name, "USERIP") ||
+ !strcasecmp(cepp->name, "ISON") ||
+ !strcasecmp(cepp->name, "WATCH"))
{
- if (strcmp(cepp->ce_vardata, "max"))
+ if (strcmp(cepp->value, "max"))
{
config_error("%s:%i: set::max-targets-per-command::%s: "
"this command is hardcoded at a maximum of 'max' "
"and cannot be changed. This because it is "
"highly discouraged to change it.",
- cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum,
- cepp->ce_varname);
+ cepp->file->filename,
+ cepp->line_number,
+ cepp->name);
errors++;
}
}
/* Now check the value syntax in general: */
- if (strcmp(cepp->ce_vardata, "max")) /* anything other than 'max'.. */
+ if (strcmp(cepp->value, "max")) /* anything other than 'max'.. */
{
- int v = atoi(cepp->ce_vardata);
+ int v = atoi(cepp->value);
if ((v < 1) || (v > 20))
{
config_error("%s:%i: set::max-targets-per-command::%s: "
"value should be 1-20 or 'max'",
- cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum,
- cepp->ce_varname);
+ cepp->file->filename,
+ cepp->line_number,
+ cepp->name);
errors++;
}
}
}
}
- else if (!strcmp(cep->ce_varname, "network-name")) {
+ else if (!strcmp(cep->name, "network-name")) {
char *p;
CheckNull(cep);
CheckDuplicate(cep, network_name, "network-name");
- for (p = cep->ce_vardata; *p; p++)
+ for (p = cep->value; *p; p++)
if ((*p < ' ') || (*p > '~'))
{
config_error("%s:%i: set::network-name can only contain ASCII characters 33-126. Invalid character = '%c'",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, *p);
+ cep->file->filename, cep->line_number, *p);
errors++;
break;
}
}
- else if (!strcmp(cep->ce_varname, "default-server")) {
+ else if (!strcmp(cep->name, "default-server")) {
CheckNull(cep);
CheckDuplicate(cep, default_server, "default-server");
}
- else if (!strcmp(cep->ce_varname, "services-server")) {
+ else if (!strcmp(cep->name, "services-server")) {
CheckNull(cep);
CheckDuplicate(cep, services_server, "services-server");
}
- else if (!strcmp(cep->ce_varname, "sasl-server")) {
+ else if (!strcmp(cep->name, "sasl-server")) {
CheckNull(cep);
CheckDuplicate(cep, sasl_server, "sasl-server");
}
- else if (!strcmp(cep->ce_varname, "stats-server")) {
+ else if (!strcmp(cep->name, "stats-server")) {
CheckNull(cep);
CheckDuplicate(cep, stats_server, "stats-server");
}
- else if (!strcmp(cep->ce_varname, "help-channel")) {
+ else if (!strcmp(cep->name, "help-channel")) {
CheckNull(cep);
CheckDuplicate(cep, help_channel, "help-channel");
}
- else if (!strcmp(cep->ce_varname, "hiddenhost-prefix")) {
+ else if (!strcmp(cep->name, "cloak-prefix") || !strcmp(cep->name, "hiddenhost-prefix")) {
CheckNull(cep);
- CheckDuplicate(cep, hiddenhost_prefix, "hiddenhost-prefix");
- if (strchr(cep->ce_vardata, ' ') || (*cep->ce_vardata == ':'))
+ CheckDuplicate(cep, hiddenhost_prefix, "cloak-prefix");
+ if (strchr(cep->value, ' ') || (*cep->value == ':'))
{
- config_error("%s:%i: set::hiddenhost-prefix must not contain spaces or be prefixed with ':'",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ config_error("%s:%i: set::cloak-prefix must not contain spaces or be prefixed with ':'",
+ cep->file->filename, cep->line_number);
errors++;
continue;
}
}
- else if (!strcmp(cep->ce_varname, "prefix-quit")) {
+ else if (!strcmp(cep->name, "prefix-quit")) {
CheckNull(cep);
CheckDuplicate(cep, prefix_quit, "prefix-quit");
}
- else if (!strcmp(cep->ce_varname, "hide-ban-reason")) {
+ else if (!strcmp(cep->name, "hide-ban-reason")) {
CheckNull(cep);
CheckDuplicate(cep, hide_ban_reason, "hide-ban-reason");
}
- else if (!strcmp(cep->ce_varname, "restrict-usermodes"))
+ else if (!strcmp(cep->name, "restrict-usermodes"))
{
CheckNull(cep);
CheckDuplicate(cep, restrict_usermodes, "restrict-usermodes");
- if (cep->ce_varname) {
+ if (cep->name) {
int warn = 0;
char *p;
- for (p = cep->ce_vardata; *p; p++)
+ for (p = cep->value; *p; p++)
if ((*p == '+') || (*p == '-'))
warn = 1;
if (warn) {
config_status("%s:%i: warning: set::restrict-usermodes: should only contain modechars, no + or -.\n",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
}
}
}
- else if (!strcmp(cep->ce_varname, "restrict-channelmodes"))
+ else if (!strcmp(cep->name, "restrict-channelmodes"))
{
CheckNull(cep);
CheckDuplicate(cep, restrict_channelmodes, "restrict-channelmodes");
- if (cep->ce_varname) {
+ if (cep->name) {
int warn = 0;
char *p;
- for (p = cep->ce_vardata; *p; p++)
+ for (p = cep->value; *p; p++)
if ((*p == '+') || (*p == '-'))
warn = 1;
if (warn) {
config_status("%s:%i: warning: set::restrict-channelmodes: should only contain modechars, no + or -.\n",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
}
}
}
- else if (!strcmp(cep->ce_varname, "restrict-extendedbans"))
+ else if (!strcmp(cep->name, "restrict-extendedbans"))
{
CheckDuplicate(cep, restrict_extendedbans, "restrict-extendedbans");
CheckNull(cep);
}
- else if (!strcmp(cep->ce_varname, "link")) {
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next) {
+ else if (!strcmp(cep->name, "named-extended-bans"))
+ {
+ CheckNull(cep);
+ }
+ else if (!strcmp(cep->name, "link")) {
+ for (cepp = cep->items; cepp; cepp = cepp->next) {
CheckNull(cepp);
- if (!strcmp(cepp->ce_varname, "bind-ip")) {
+ if (!strcmp(cepp->name, "bind-ip")) {
CheckDuplicate(cepp, link_bind_ip, "link::bind-ip");
- if (strcmp(cepp->ce_vardata, "*"))
+ if (strcmp(cepp->value, "*"))
{
- if (!is_valid_ip(cepp->ce_vardata))
+ if (!is_valid_ip(cepp->value))
{
config_error("%s:%i: set::link::bind-ip (%s) is not a valid IP",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum,
- cepp->ce_vardata);
+ cepp->file->filename, cepp->line_number,
+ cepp->value);
errors++;
continue;
}
@@ -8438,66 +8148,33 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
}
}
}
- else if (!strcmp(cep->ce_varname, "dns")) {
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next) {
- CheckNull(cepp);
- if (!strcmp(cepp->ce_varname, "nameserver") ||
- !strcmp(cepp->ce_varname, "timeout") ||
- !strcmp(cepp->ce_varname, "retries"))
- {
- config_error("%s:%i: set::dns::%s no longer exist in UnrealIRCd 4. "
- "Please remove it from your configuration file.",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum, cepp->ce_varname);
- errors++;
- } else
- if (!strcmp(cepp->ce_varname, "bind-ip")) {
- CheckDuplicate(cepp, dns_bind_ip, "dns::bind-ip");
- if (strcmp(cepp->ce_vardata, "*"))
- {
- if (!is_valid_ip(cepp->ce_vardata))
- {
- config_error("%s:%i: set::dns::bind-ip (%s) is not a valid IP",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum,
- cepp->ce_vardata);
- errors++;
- continue;
- }
- }
- }
- else
- {
- config_error_unknownopt(cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum, "set::dns",
- cepp->ce_varname);
- errors++;
- }
- }
- }
- else if (!strcmp(cep->ce_varname, "throttle")) {
+ else if (!strcmp(cep->name, "throttle")) {
config_error("%s:%i: set::throttle has been renamed. you now use "
"set::anti-flood::connect-flood :. "
"Or just remove the throttle block and you get the default "
"of 3 per 60 seconds.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
- need_34_upgrade = 1;
continue;
}
- else if (!strcmp(cep->ce_varname, "anti-flood"))
+ else if (!strcmp(cep->name, "anti-flood"))
{
int anti_flood_old = 0;
int anti_flood_old_and_default = 0;
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
+ int has_lag_penalty = 0;
+ int has_lag_penalty_bytes = 0;
+
/* Test for old options: */
- if (flood_option_is_old(cepp->ce_varname))
+ if (flood_option_is_old(cepp->name))
{
/* Special code if the user is using 100% of the defaults */
- if (cepp->ce_vardata &&
- ((!strcmp(cepp->ce_varname, "nick-flood") && !strcmp(cepp->ce_vardata, "3:60")) ||
- (!strcmp(cepp->ce_varname, "connect-flood") && cepp->ce_vardata && !strcmp(cepp->ce_vardata, "3:60")) ||
- (!strcmp(cepp->ce_varname, "away-flood") && cepp->ce_vardata && !strcmp(cepp->ce_vardata, "4:120"))))
+ if (cepp->value &&
+ ((!strcmp(cepp->name, "nick-flood") && !strcmp(cepp->value, "3:60")) ||
+ (!strcmp(cepp->name, "connect-flood") && cepp->value && !strcmp(cepp->value, "3:60")) ||
+ (!strcmp(cepp->name, "away-flood") && cepp->value && !strcmp(cepp->value, "4:120"))))
{
anti_flood_old_and_default = 1;
} else
@@ -8507,219 +8184,237 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
continue;
}
- for (ceppp = cepp->ce_entries; ceppp; ceppp = ceppp->ce_next)
+ for (ceppp = cepp->items; ceppp; ceppp = ceppp->next)
{
- int everyone = !strcmp(cepp->ce_varname, "everyone") ? 1 : 0;
- int for_everyone = flood_option_is_for_everyone(ceppp->ce_varname);
+ int everyone = !strcmp(cepp->name, "everyone") ? 1 : 0;
+ int for_everyone = flood_option_is_for_everyone(ceppp->name);
if (everyone && !for_everyone)
{
config_error("%s:%i: %s cannot be in the set::anti-flood::everyone block. "
"You can put it in 'known-users' or 'unknown-users' instead.",
- ceppp->ce_fileptr->cf_filename, ceppp->ce_varlinenum,
- ceppp->ce_varname);
+ ceppp->file->filename, ceppp->line_number,
+ ceppp->name);
errors++;
continue;
} else
if (!everyone && for_everyone)
{
config_error("%s:%i: %s must be in the set::anti-flood::everyone block, not anywhere else.",
- ceppp->ce_fileptr->cf_filename, ceppp->ce_varlinenum,
- ceppp->ce_varname);
+ ceppp->file->filename, ceppp->line_number,
+ ceppp->name);
errors++;
continue;
}
/* Now comes the actual config check for each element... */
- if (!strcmp(ceppp->ce_varname, "max-concurrent-conversations"))
+ if (!strcmp(ceppp->name, "max-concurrent-conversations"))
{
- for (cep4 = ceppp->ce_entries; cep4; cep4 = cep4->ce_next)
+ for (cep4 = ceppp->items; cep4; cep4 = cep4->next)
{
CheckNull(cep4);
- if (!strcmp(cep4->ce_varname, "users"))
+ if (!strcmp(cep4->name, "users"))
{
- int v = atoi(cep4->ce_vardata);
+ int v = atoi(cep4->value);
if ((v < 1) || (v > MAXCCUSERS))
{
config_error("%s:%i: set::anti-flood::max-concurrent-conversations::users: "
"value should be between 1 and %d",
- cep4->ce_fileptr->cf_filename, cep4->ce_varlinenum, MAXCCUSERS);
+ cep4->file->filename, cep4->line_number, MAXCCUSERS);
errors++;
}
} else
- if (!strcmp(cep4->ce_varname, "new-user-every"))
+ if (!strcmp(cep4->name, "new-user-every"))
{
- long v = config_checkval(cep4->ce_vardata, CFG_TIME);
+ long v = config_checkval(cep4->value, CFG_TIME);
if ((v < 1) || (v > 120))
{
config_error("%s:%i: set::anti-flood::max-concurrent-conversations::new-user-every: "
"value should be between 1 and 120 seconds",
- cep4->ce_fileptr->cf_filename, cep4->ce_varlinenum);
+ cep4->file->filename, cep4->line_number);
errors++;
}
} else
{
- config_error_unknownopt(cep4->ce_fileptr->cf_filename,
- cep4->ce_varlinenum, "set::anti-flood",
- cep4->ce_varname);
+ config_error_unknownopt(cep4->file->filename,
+ cep4->line_number, "set::anti-flood",
+ cep4->name);
errors++;
}
}
continue; /* required here, due to checknull directly below */
}
- else if (!strcmp(ceppp->ce_varname, "unknown-flood-amount") ||
- !strcmp(ceppp->ce_varname, "unknown-flood-bantime"))
+ else if (!strcmp(ceppp->name, "unknown-flood-amount") ||
+ !strcmp(ceppp->name, "unknown-flood-bantime"))
{
config_error("%s:%i: set::anti-flood::%s: this setting has been moved. "
"See https://www.unrealircd.org/docs/Anti-flood_settings#handshake-data-flood",
- ceppp->ce_fileptr->cf_filename, ceppp->ce_varlinenum, ceppp->ce_varname);
+ ceppp->file->filename, ceppp->line_number, ceppp->name);
errors++;
continue;
}
- else if (!strcmp(ceppp->ce_varname, "handshake-data-flood"))
+ else if (!strcmp(ceppp->name, "handshake-data-flood"))
{
- for (cep4 = ceppp->ce_entries; cep4; cep4 = cep4->ce_next)
+ for (cep4 = ceppp->items; cep4; cep4 = cep4->next)
{
- if (!strcmp(cep4->ce_varname, "amount"))
+ if (!strcmp(cep4->name, "amount"))
{
long v;
CheckNull(cep4);
- v = config_checkval(cep4->ce_vardata, CFG_SIZE);
+ v = config_checkval(cep4->value, CFG_SIZE);
if (v < 1024)
{
config_error("%s:%i: set::anti-flood::handshake-data-flood::amount must be at least 1024 bytes",
- cep4->ce_fileptr->cf_filename, cep4->ce_varlinenum);
+ cep4->file->filename, cep4->line_number);
errors++;
}
} else
- if (!strcmp(cep4->ce_varname, "ban-action"))
+ if (!strcmp(cep4->name, "ban-action"))
{
CheckNull(cep4);
- if (!banact_stringtoval(cep4->ce_vardata))
+ if (!banact_stringtoval(cep4->value))
{
config_error("%s:%i: set::anti-flood::handshake-data-flood::ban-action has unknown action type '%s'",
- cep4->ce_fileptr->cf_filename, cep4->ce_varlinenum,
- cep4->ce_vardata);
+ cep4->file->filename, cep4->line_number,
+ cep4->value);
errors++;
}
} else
- if (!strcmp(cep4->ce_varname, "ban-time"))
+ if (!strcmp(cep4->name, "ban-time"))
{
CheckNull(cep4);
} else
{
- config_error_unknownopt(cep4->ce_fileptr->cf_filename,
- cep4->ce_varlinenum, "set::anti-flood::handshake-data-flood",
- cep4->ce_varname);
+ config_error_unknownopt(cep4->file->filename,
+ cep4->line_number, "set::anti-flood::handshake-data-flood",
+ cep4->name);
errors++;
}
}
}
- else if (!strcmp(ceppp->ce_varname, "away-count"))
+ else if (!strcmp(ceppp->name, "away-count"))
{
- int temp = atol(ceppp->ce_vardata);
+ int temp = atol(ceppp->value);
CheckNull(ceppp);
if (temp < 1 || temp > 255)
{
config_error("%s:%i: set::anti-flood::away-count must be between 1 and 255",
- ceppp->ce_fileptr->cf_filename, ceppp->ce_varlinenum);
+ ceppp->file->filename, ceppp->line_number);
errors++;
}
}
- else if (!strcmp(ceppp->ce_varname, "away-period"))
+ else if (!strcmp(ceppp->name, "away-period"))
{
CheckNull(ceppp);
- int temp = config_checkval(ceppp->ce_vardata, CFG_TIME);
+ int temp = config_checkval(ceppp->value, CFG_TIME);
if (temp < 10)
{
config_error("%s:%i: set::anti-flood::away-period must be greater than 9",
- ceppp->ce_fileptr->cf_filename, ceppp->ce_varlinenum);
+ ceppp->file->filename, ceppp->line_number);
errors++;
}
}
- else if (!strcmp(ceppp->ce_varname, "away-flood"))
+ else if (!strcmp(ceppp->name, "away-flood"))
{
int cnt, period;
CheckNull(ceppp);
- if (!config_parse_flood(ceppp->ce_vardata, &cnt, &period) ||
+ if (!config_parse_flood(ceppp->value, &cnt, &period) ||
(cnt < 1) || (cnt > 255) || (period < 10))
{
config_error("%s:%i: set::anti-flood::away-flood error. Syntax is ':' (eg 5:60), "
"count should be 1-255, period should be greater than 9",
- ceppp->ce_fileptr->cf_filename, ceppp->ce_varlinenum);
+ ceppp->file->filename, ceppp->line_number);
errors++;
}
}
- else if (!strcmp(ceppp->ce_varname, "nick-flood"))
+ else if (!strcmp(ceppp->name, "nick-flood"))
{
int cnt, period;
CheckNull(ceppp);
- if (!config_parse_flood(ceppp->ce_vardata, &cnt, &period) ||
+ if (!config_parse_flood(ceppp->value, &cnt, &period) ||
(cnt < 1) || (cnt > 255) || (period < 5))
{
config_error("%s:%i: set::anti-flood::nick-flood error. Syntax is ':' (eg 5:60), "
"count should be 1-255, period should be greater than 4",
- ceppp->ce_fileptr->cf_filename, ceppp->ce_varlinenum);
+ ceppp->file->filename, ceppp->line_number);
errors++;
}
}
- else if (!strcmp(ceppp->ce_varname, "join-flood"))
+ else if (!strcmp(ceppp->name, "join-flood"))
{
int cnt, period;
CheckNull(ceppp);
- if (!config_parse_flood(ceppp->ce_vardata, &cnt, &period) ||
+ if (!config_parse_flood(ceppp->value, &cnt, &period) ||
(cnt < 1) || (cnt > 255) || (period < 5))
{
config_error("%s:%i: join-flood error. Syntax is ':' (eg 5:60), "
"count should be 1-255, period should be greater than 4",
- ceppp->ce_fileptr->cf_filename, ceppp->ce_varlinenum);
+ ceppp->file->filename, ceppp->line_number);
errors++;
}
}
- else if (!strcmp(ceppp->ce_varname, "invite-flood"))
+ else if (!strcmp(ceppp->name, "invite-flood"))
{
int cnt, period;
CheckNull(ceppp);
- if (!config_parse_flood(ceppp->ce_vardata, &cnt, &period) ||
+ if (!config_parse_flood(ceppp->value, &cnt, &period) ||
(cnt < 1) || (cnt > 255) || (period < 5))
{
config_error("%s:%i: set::anti-flood::invite-flood error. Syntax is ':' (eg 5:60), "
"count should be 1-255, period should be greater than 4",
- ceppp->ce_fileptr->cf_filename, ceppp->ce_varlinenum);
+ ceppp->file->filename, ceppp->line_number);
errors++;
}
}
- else if (!strcmp(ceppp->ce_varname, "knock-flood"))
+ else if (!strcmp(ceppp->name, "knock-flood"))
{
int cnt, period;
CheckNull(ceppp);
- if (!config_parse_flood(ceppp->ce_vardata, &cnt, &period) ||
+ if (!config_parse_flood(ceppp->value, &cnt, &period) ||
(cnt < 1) || (cnt > 255) || (period < 5))
{
config_error("%s:%i: set::anti-flood::knock-flood error. Syntax is ':' (eg 5:60), "
"count should be 1-255, period should be greater than 4",
- ceppp->ce_fileptr->cf_filename, ceppp->ce_varlinenum);
+ ceppp->file->filename, ceppp->line_number);
errors++;
}
}
- else if (!strcmp(ceppp->ce_varname, "connect-flood"))
+ else if (!strcmp(ceppp->name, "lag-penalty"))
+ {
+ int v;
+ CheckNull(ceppp);
+ v = atoi(ceppp->value);
+ has_lag_penalty = 1;
+ if ((v < 0) || (v > 10000))
+ {
+ config_error("%s:%i: set::anti-flood::%s::lag-penalty: value is in milliseconds and should be between 0 and 10000",
+ ceppp->file->filename, ceppp->line_number, cepp->name);
+ errors++;
+ }
+ }
+ else if (!strcmp(ceppp->name, "lag-penalty-bytes"))
+ {
+ has_lag_penalty_bytes = 1;
+ CheckNull(ceppp);
+ }
+ else if (!strcmp(ceppp->name, "connect-flood"))
{
int cnt, period;
CheckNull(ceppp);
- if (strcmp(cepp->ce_varname, "everyone"))
+ if (strcmp(cepp->name, "everyone"))
{
config_error("%s:%i: connect-flood must be in the set::anti-flood::everyone block, not anywhere else.",
- ceppp->ce_fileptr->cf_filename, ceppp->ce_varlinenum);
+ ceppp->file->filename, ceppp->line_number);
errors++;
continue;
}
- if (!config_parse_flood(ceppp->ce_vardata, &cnt, &period) ||
+ if (!config_parse_flood(ceppp->value, &cnt, &period) ||
(cnt < 1) || (cnt > 255) || (period < 1) || (period > 3600))
{
config_error("%s:%i: set::anti-flood::connect-flood: Syntax is ':' (eg 5:60), "
"count should be 1-255, period should be 1-3600",
- ceppp->ce_fileptr->cf_filename, ceppp->ce_varlinenum);
+ ceppp->file->filename, ceppp->line_number);
errors++;
}
}
@@ -8756,21 +8451,27 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
}
if (!used)
{
- config_error_unknownopt(ceppp->ce_fileptr->cf_filename,
- ceppp->ce_varlinenum, "set::anti-flood",
- ceppp->ce_varname);
+ config_error_unknownopt(ceppp->file->filename,
+ ceppp->line_number, "set::anti-flood",
+ ceppp->name);
errors++;
}
continue;
}
}
+ if (has_lag_penalty+has_lag_penalty_bytes == 1)
+ {
+ config_error("%s:%i: set::anti-flood::%s: if you use lag-penalty then you must also add an lag-penalty-bytes item (and vice-versa)",
+ cepp->file->filename, cepp->line_number, cepp->name);
+ errors++;
+ }
}
/* Now the warnings: */
if (anti_flood_old == 1)
{
config_warn("%s:%d: the set::anti-flood block has been reorganized to be more flexible. "
"Your custom anti-flood settings have NOT been read.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
config_warn("See https://www.unrealircd.org/docs/Anti-flood_settings for the new block style,");
config_warn("OR: simply remove all the anti-flood options from the conf to get rid of this "
"warning and use the built-in defaults.");
@@ -8778,74 +8479,73 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
if (anti_flood_old_and_default == 1)
{
config_warn("%s:%d: the set::anti-flood block has been reorganized to be more flexible.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
config_warn("To fix this warning, delete the anti-flood block from your configuration file "
"(file %s around line %d), this will make UnrealIRCd use the built-in defaults.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
config_warn("If you want to learn more about the new functionality you can visit "
"https://www.unrealircd.org/docs/Anti-flood_settings");
}
}
- else if (!strcmp(cep->ce_varname, "options")) {
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next) {
- if (!strcmp(cepp->ce_varname, "hide-ulines"))
+ else if (!strcmp(cep->name, "options")) {
+ for (cepp = cep->items; cepp; cepp = cepp->next) {
+ if (!strcmp(cepp->name, "hide-ulines"))
{
CheckDuplicate(cepp, options_hide_ulines, "options::hide-ulines");
}
- else if (!strcmp(cepp->ce_varname, "flat-map")) {
+ else if (!strcmp(cepp->name, "flat-map")) {
CheckDuplicate(cepp, options_flat_map, "options::flat-map");
}
- else if (!strcmp(cepp->ce_varname, "show-opermotd")) {
+ else if (!strcmp(cepp->name, "show-opermotd")) {
CheckDuplicate(cepp, options_show_opermotd, "options::show-opermotd");
}
- else if (!strcmp(cepp->ce_varname, "identd-check")) {
+ else if (!strcmp(cepp->name, "identd-check")) {
CheckDuplicate(cepp, options_identd_check, "options::identd-check");
}
- else if (!strcmp(cepp->ce_varname, "fail-oper-warn")) {
+ else if (!strcmp(cepp->name, "fail-oper-warn")) {
CheckDuplicate(cepp, options_fail_oper_warn, "options::fail-oper-warn");
}
- else if (!strcmp(cepp->ce_varname, "show-connect-info")) {
+ else if (!strcmp(cepp->name, "show-connect-info")) {
CheckDuplicate(cepp, options_show_connect_info, "options::show-connect-info");
}
- else if (!strcmp(cepp->ce_varname, "no-connect-tls-info")) {
+ else if (!strcmp(cepp->name, "no-connect-tls-info")) {
CheckDuplicate(cepp, options_no_connect_tls_info, "options::no-connect-tls-info");
}
- else if (!strcmp(cepp->ce_varname, "dont-resolve")) {
+ else if (!strcmp(cepp->name, "dont-resolve")) {
CheckDuplicate(cepp, options_dont_resolve, "options::dont-resolve");
}
- else if (!strcmp(cepp->ce_varname, "mkpasswd-for-everyone")) {
+ else if (!strcmp(cepp->name, "mkpasswd-for-everyone")) {
CheckDuplicate(cepp, options_mkpasswd_for_everyone, "options::mkpasswd-for-everyone");
}
- else if (!strcmp(cepp->ce_varname, "allow-insane-bans")) {
+ else if (!strcmp(cepp->name, "allow-insane-bans")) {
CheckDuplicate(cepp, options_allow_insane_bans, "options::allow-insane-bans");
}
- else if (!strcmp(cepp->ce_varname, "allow-part-if-shunned")) {
+ else if (!strcmp(cepp->name, "allow-part-if-shunned")) {
CheckDuplicate(cepp, options_allow_part_if_shunned, "options::allow-part-if-shunned");
}
- else if (!strcmp(cepp->ce_varname, "disable-cap")) {
+ else if (!strcmp(cepp->name, "disable-cap")) {
CheckDuplicate(cepp, options_disable_cap, "options::disable-cap");
}
- else if (!strcmp(cepp->ce_varname, "disable-ipv6")) {
+ else if (!strcmp(cepp->name, "disable-ipv6")) {
CheckDuplicate(cepp, options_disable_ipv6, "options::disable-ipv6");
DISABLE_IPV6 = 1; /* ugly ugly. needs to be done here because at conf runtime is too late. */
}
else
{
- config_error_unknownopt(cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum, "set::options",
- cepp->ce_varname);
+ config_error_unknownopt(cepp->file->filename,
+ cepp->line_number, "set::options",
+ cepp->name);
errors++;
continue;
}
}
}
- else if (!strcmp(cep->ce_varname, "hosts")) {
- config_error("%s:%i: set::hosts has been removed in UnrealIRCd 4. You can use oper::vhost now.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ else if (!strcmp(cep->name, "hosts")) {
+ config_error("%s:%i: set::hosts has been removed. You can use oper::vhost now.",
+ cep->file->filename, cep->line_number);
errors++;
- need_34_upgrade = 1;
}
- else if (!strcmp(cep->ce_varname, "cloak-keys"))
+ else if (!strcmp(cep->name, "cloak-keys"))
{
CheckDuplicate(cep, cloak_keys, "cloak-keys");
for (h = Hooks[HOOKTYPE_CONFIGTEST]; h; h = h->next)
@@ -8867,488 +8567,486 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
errors += errs;
}
}
- else if (!strcmp(cep->ce_varname, "ident")) {
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ else if (!strcmp(cep->name, "ident")) {
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
int is_ok = 0;
CheckNull(cepp);
- if (!strcmp(cepp->ce_varname, "connect-timeout"))
+ if (!strcmp(cepp->name, "connect-timeout"))
{
is_ok = 1;
CheckDuplicate(cepp, ident_connect_timeout, "ident::connect-timeout");
}
- else if (!strcmp(cepp->ce_varname, "read-timeout"))
+ else if (!strcmp(cepp->name, "read-timeout"))
{
is_ok = 1;
CheckDuplicate(cepp, ident_read_timeout, "ident::read-timeout");
}
if (is_ok)
{
- int v = config_checkval(cepp->ce_vardata,CFG_TIME);
+ int v = config_checkval(cepp->value,CFG_TIME);
if ((v > 60) || (v < 1))
{
config_error("%s:%i: set::ident::%s value out of range (%d), should be between 1 and 60.",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum, cepp->ce_varname, v);
+ cepp->file->filename, cepp->line_number, cepp->name, v);
errors++;
continue;
}
} else {
- config_error_unknown(cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum, "set::ident",
- cepp->ce_varname);
+ config_error_unknown(cepp->file->filename,
+ cepp->line_number, "set::ident",
+ cepp->name);
errors++;
continue;
}
}
}
- else if (!strcmp(cep->ce_varname, "timesync") || !strcmp(cep->ce_varname, "timesynch"))
+ else if (!strcmp(cep->name, "timesync") || !strcmp(cep->name, "timesynch"))
{
config_warn("%s:%i: Timesync support has been removed from UnrealIRCd. "
"Please remove any set::timesync blocks you may have.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
config_warn("Use the time synchronization feature of your OS/distro instead!");
}
- else if (!strcmp(cep->ce_varname, "spamfilter")) {
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ else if (!strcmp(cep->name, "spamfilter")) {
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
CheckNull(cepp);
- if (!strcmp(cepp->ce_varname, "ban-time"))
+ if (!strcmp(cepp->name, "ban-time"))
{
long x;
CheckDuplicate(cepp, spamfilter_ban_time, "spamfilter::ban-time");
- x = config_checkval(cepp->ce_vardata,CFG_TIME);
+ x = config_checkval(cepp->value,CFG_TIME);
if ((x < 0) > (x > 2000000000))
{
config_error("%s:%i: set::spamfilter:ban-time: value '%ld' out of range",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, x);
+ cep->file->filename, cep->line_number, x);
errors++;
continue;
}
} else
- if (!strcmp(cepp->ce_varname, "ban-reason"))
+ if (!strcmp(cepp->name, "ban-reason"))
{
CheckDuplicate(cepp, spamfilter_ban_reason, "spamfilter::ban-reason");
}
- else if (!strcmp(cepp->ce_varname, "virus-help-channel"))
+ else if (!strcmp(cepp->name, "virus-help-channel"))
{
CheckDuplicate(cepp, spamfilter_virus_help_channel, "spamfilter::virus-help-channel");
- if ((cepp->ce_vardata[0] != '#') || (strlen(cepp->ce_vardata) > CHANNELLEN))
+ if ((cepp->value[0] != '#') || (strlen(cepp->value) > CHANNELLEN))
{
config_error("%s:%i: set::spamfilter:virus-help-channel: "
"specified channelname is too long or contains invalid characters (%s)",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- cepp->ce_vardata);
+ cep->file->filename, cep->line_number,
+ cepp->value);
errors++;
continue;
}
} else
- if (!strcmp(cepp->ce_varname, "virus-help-channel-deny"))
+ if (!strcmp(cepp->name, "virus-help-channel-deny"))
{
CheckDuplicate(cepp, spamfilter_virus_help_channel_deny, "spamfilter::virus-help-channel-deny");
} else
- if (!strcmp(cepp->ce_varname, "except"))
+ if (!strcmp(cepp->name, "except"))
{
CheckDuplicate(cepp, spamfilter_except, "spamfilter::except");
} else
#ifdef SPAMFILTER_DETECTSLOW
- if (!strcmp(cepp->ce_varname, "detect-slow-warn"))
+ if (!strcmp(cepp->name, "detect-slow-warn"))
{
} else
- if (!strcmp(cepp->ce_varname, "detect-slow-fatal"))
+ if (!strcmp(cepp->name, "detect-slow-fatal"))
{
} else
#endif
- if (!strcmp(cepp->ce_varname, "stop-on-first-match"))
+ if (!strcmp(cepp->name, "stop-on-first-match"))
{
} else
{
- config_error_unknown(cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum, "set::spamfilter",
- cepp->ce_varname);
+ config_error_unknown(cepp->file->filename,
+ cepp->line_number, "set::spamfilter",
+ cepp->name);
errors++;
continue;
}
}
}
-/* TODO: FIX THIS */
- else if (!strcmp(cep->ce_varname, "default-bantime"))
+ else if (!strcmp(cep->name, "default-bantime"))
{
long x;
CheckDuplicate(cep, default_bantime, "default-bantime");
CheckNull(cep);
- x = config_checkval(cep->ce_vardata,CFG_TIME);
+ x = config_checkval(cep->value,CFG_TIME);
if ((x < 0) > (x > 2000000000))
{
config_error("%s:%i: set::default-bantime: value '%ld' out of range",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, x);
+ cep->file->filename, cep->line_number, x);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "ban-version-tkl-time")) {
+ else if (!strcmp(cep->name, "ban-version-tkl-time")) {
long x;
CheckDuplicate(cep, ban_version_tkl_time, "ban-version-tkl-time");
CheckNull(cep);
- x = config_checkval(cep->ce_vardata,CFG_TIME);
+ x = config_checkval(cep->value,CFG_TIME);
if ((x < 0) > (x > 2000000000))
{
config_error("%s:%i: set::ban-version-tkl-time: value '%ld' out of range",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, x);
+ cep->file->filename, cep->line_number, x);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "min-nick-length")) {
+ else if (!strcmp(cep->name, "min-nick-length")) {
int v;
CheckDuplicate(cep, min_nick_length, "min-nick-length");
CheckNull(cep);
- v = atoi(cep->ce_vardata);
+ v = atoi(cep->value);
if ((v <= 0) || (v > NICKLEN))
{
config_error("%s:%i: set::min-nick-length: value '%d' out of range (should be 1-%d)",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, v, NICKLEN);
+ cep->file->filename, cep->line_number, v, NICKLEN);
errors++;
}
else
nicklengths.min = v;
}
- else if (!strcmp(cep->ce_varname, "nick-length")) {
+ else if (!strcmp(cep->name, "nick-length")) {
int v;
CheckDuplicate(cep, nick_length, "nick-length");
CheckNull(cep);
- v = atoi(cep->ce_vardata);
+ v = atoi(cep->value);
if ((v <= 0) || (v > NICKLEN))
{
config_error("%s:%i: set::nick-length: value '%d' out of range (should be 1-%d)",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, v, NICKLEN);
+ cep->file->filename, cep->line_number, v, NICKLEN);
errors++;
}
else
nicklengths.max = v;
}
- else if (!strcmp(cep->ce_varname, "topic-length")) {
+ else if (!strcmp(cep->name, "topic-length")) {
int v;
CheckNull(cep);
- v = atoi(cep->ce_vardata);
+ v = atoi(cep->value);
if ((v <= 0) || (v > MAXTOPICLEN))
{
config_error("%s:%i: set::topic-length: value '%d' out of range (should be 1-%d)",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, v, MAXTOPICLEN);
+ cep->file->filename, cep->line_number, v, MAXTOPICLEN);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "away-length")) {
+ else if (!strcmp(cep->name, "away-length")) {
int v;
CheckNull(cep);
- v = atoi(cep->ce_vardata);
+ v = atoi(cep->value);
if ((v <= 0) || (v > MAXAWAYLEN))
{
config_error("%s:%i: set::away-length: value '%d' out of range (should be 1-%d)",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, v, MAXAWAYLEN);
+ cep->file->filename, cep->line_number, v, MAXAWAYLEN);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "kick-length")) {
+ else if (!strcmp(cep->name, "kick-length")) {
int v;
CheckNull(cep);
- v = atoi(cep->ce_vardata);
+ v = atoi(cep->value);
if ((v <= 0) || (v > MAXKICKLEN))
{
config_error("%s:%i: set::kick-length: value '%d' out of range (should be 1-%d)",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, v, MAXKICKLEN);
+ cep->file->filename, cep->line_number, v, MAXKICKLEN);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "quit-length")) {
+ else if (!strcmp(cep->name, "quit-length")) {
int v;
CheckNull(cep);
- v = atoi(cep->ce_vardata);
+ v = atoi(cep->value);
if ((v <= 0) || (v > MAXQUITLEN))
{
config_error("%s:%i: set::quit-length: value '%d' out of range (should be 1-%d)",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, v, MAXQUITLEN);
+ cep->file->filename, cep->line_number, v, MAXQUITLEN);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "ssl") || !strcmp(cep->ce_varname, "tls")) {
+ else if (!strcmp(cep->name, "ssl") || !strcmp(cep->name, "tls")) {
test_tlsblock(conf, cep, &errors);
}
- else if (!strcmp(cep->ce_varname, "plaintext-policy"))
+ else if (!strcmp(cep->name, "plaintext-policy"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "user") ||
- !strcmp(cepp->ce_varname, "oper") ||
- !strcmp(cepp->ce_varname, "server"))
+ if (!strcmp(cepp->name, "user") ||
+ !strcmp(cepp->name, "oper") ||
+ !strcmp(cepp->name, "server"))
{
Policy policy;
CheckNull(cepp);
- policy = policy_strtoval(cepp->ce_vardata);
+ policy = policy_strtoval(cepp->value);
if (!policy)
{
config_error("%s:%i: set::plaintext-policy::%s: needs to be one of: 'allow', 'warn' or 'reject'",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum, cepp->ce_varname);
+ cepp->file->filename, cepp->line_number, cepp->name);
errors++;
}
- } else if (!strcmp(cepp->ce_varname, "user-message") ||
- !strcmp(cepp->ce_varname, "oper-message"))
+ } else if (!strcmp(cepp->name, "user-message") ||
+ !strcmp(cepp->name, "oper-message"))
{
CheckNull(cepp);
} else {
- config_error_unknown(cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum, "set::plaintext-policy",
- cepp->ce_varname);
+ config_error_unknown(cepp->file->filename,
+ cepp->line_number, "set::plaintext-policy",
+ cepp->name);
errors++;
continue;
}
}
}
- else if (!strcmp(cep->ce_varname, "outdated-tls-policy"))
+ else if (!strcmp(cep->name, "outdated-tls-policy"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "user") ||
- !strcmp(cepp->ce_varname, "oper") ||
- !strcmp(cepp->ce_varname, "server"))
+ if (!strcmp(cepp->name, "user") ||
+ !strcmp(cepp->name, "oper") ||
+ !strcmp(cepp->name, "server"))
{
Policy policy;
CheckNull(cepp);
- policy = policy_strtoval(cepp->ce_vardata);
+ policy = policy_strtoval(cepp->value);
if (!policy)
{
config_error("%s:%i: set::outdated-tls-policy::%s: needs to be one of: 'allow', 'warn' or 'reject'",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum, cepp->ce_varname);
+ cepp->file->filename, cepp->line_number, cepp->name);
errors++;
}
- } else if (!strcmp(cepp->ce_varname, "user-message") ||
- !strcmp(cepp->ce_varname, "oper-message"))
+ } else if (!strcmp(cepp->name, "user-message") ||
+ !strcmp(cepp->name, "oper-message"))
{
CheckNull(cepp);
} else {
- config_error_unknown(cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum, "set::outdated-tls-policy",
- cepp->ce_varname);
+ config_error_unknown(cepp->file->filename,
+ cepp->line_number, "set::outdated-tls-policy",
+ cepp->name);
errors++;
continue;
}
}
}
- else if (!strcmp(cep->ce_varname, "default-ipv6-clone-mask"))
+ else if (!strcmp(cep->name, "default-ipv6-clone-mask"))
{
/* keep this in sync with _test_allow() */
int ipv6mask;
- ipv6mask = atoi(cep->ce_vardata);
+ ipv6mask = atoi(cep->value);
if (ipv6mask == 0)
{
config_error("%s:%d: set::default-ipv6-clone-mask given a value of zero. This cannnot be correct, as it would treat all IPv6 hosts as one host.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
if (ipv6mask > 128)
{
config_error("%s:%d: set::default-ipv6-clone-mask was set to %d. The maximum value is 128.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
+ cep->file->filename, cep->line_number,
ipv6mask);
errors++;
}
if (ipv6mask <= 32)
{
config_warn("%s:%d: set::default-ipv6-clone-mask was given a very small value.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
}
}
- else if (!strcmp(cep->ce_varname, "hide-list")) {
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ else if (!strcmp(cep->name, "hide-list")) {
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "deny-channel"))
+ if (!strcmp(cepp->name, "deny-channel"))
{
} else
{
- config_error_unknown(cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum, "set::hide-list",
- cepp->ce_varname);
+ config_error_unknown(cepp->file->filename,
+ cepp->line_number, "set::hide-list",
+ cepp->name);
errors++;
continue;
}
}
}
- else if (!strcmp(cep->ce_varname, "max-unknown-connections-per-ip")) {
+ else if (!strcmp(cep->name, "max-unknown-connections-per-ip")) {
int v;
CheckNull(cep);
- v = atoi(cep->ce_vardata);
+ v = atoi(cep->value);
if (v < 1)
{
config_error("%s:%i: set::max-unknown-connections-per-ip: value should be at least 1.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "handshake-timeout")) {
+ else if (!strcmp(cep->name, "handshake-timeout")) {
int v;
CheckNull(cep);
- v = config_checkval(cep->ce_vardata, CFG_TIME);
+ v = config_checkval(cep->value, CFG_TIME);
if (v < 5)
{
config_error("%s:%i: set::handshake-timeout: value should be at least 5 seconds.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "sasl-timeout")) {
+ else if (!strcmp(cep->name, "sasl-timeout")) {
int v;
CheckNull(cep);
- v = config_checkval(cep->ce_vardata, CFG_TIME);
+ v = config_checkval(cep->value, CFG_TIME);
if (v < 5)
{
config_error("%s:%i: set::sasl-timeout: value should be at least 5 seconds.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "handshake-delay"))
+ else if (!strcmp(cep->name, "handshake-delay"))
{
int v;
CheckNull(cep);
- v = config_checkval(cep->ce_vardata, CFG_TIME);
+ v = config_checkval(cep->value, CFG_TIME);
if (v >= 10)
{
config_error("%s:%i: set::handshake-delay: value should be less than 10 seconds.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "ban-include-username"))
+ else if (!strcmp(cep->name, "ban-include-username"))
{
config_error("%s:%i: set::ban-include-username is no longer supported. "
"Use set { automatic-ban-target userip; }; instead.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
config_error("See https://www.unrealircd.org/docs/Set_block#set::automatic-ban-target "
"for more information and options.");
errors++;
}
- else if (!strcmp(cep->ce_varname, "automatic-ban-target"))
+ else if (!strcmp(cep->name, "automatic-ban-target"))
{
CheckNull(cep);
- if (!ban_target_strtoval(cep->ce_vardata))
+ if (!ban_target_strtoval(cep->value))
{
config_error("%s:%i: set::automatic-ban-target: value '%s' is not recognized. "
"See https://www.unrealircd.org/docs/Set_block#set::automatic-ban-target",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_vardata);
+ cep->file->filename, cep->line_number, cep->value);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "manual-ban-target"))
+ else if (!strcmp(cep->name, "manual-ban-target"))
{
CheckNull(cep);
- if (!ban_target_strtoval(cep->ce_vardata))
+ if (!ban_target_strtoval(cep->value))
{
config_error("%s:%i: set::manual-ban-target: value '%s' is not recognized. "
"See https://www.unrealircd.org/docs/Set_block#set::manual-ban-target",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_vardata);
+ cep->file->filename, cep->line_number, cep->value);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "reject-message"))
+ else if (!strcmp(cep->name, "reject-message"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
CheckNull(cepp);
- if (!strcmp(cepp->ce_varname, "password-mismatch"))
+ if (!strcmp(cepp->name, "password-mismatch"))
;
- else if (!strcmp(cepp->ce_varname, "too-many-connections"))
+ else if (!strcmp(cepp->name, "too-many-connections"))
;
- else if (!strcmp(cepp->ce_varname, "server-full"))
+ else if (!strcmp(cepp->name, "server-full"))
;
- else if (!strcmp(cepp->ce_varname, "unauthorized"))
+ else if (!strcmp(cepp->name, "unauthorized"))
;
- else if (!strcmp(cepp->ce_varname, "kline"))
+ else if (!strcmp(cepp->name, "kline"))
;
- else if (!strcmp(cepp->ce_varname, "gline"))
+ else if (!strcmp(cepp->name, "gline"))
;
else
{
- config_error_unknown(cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum, "set::reject-message",
- cepp->ce_varname);
+ config_error_unknown(cepp->file->filename,
+ cepp->line_number, "set::reject-message",
+ cepp->name);
errors++;
continue;
}
}
}
- else if (!strcmp(cep->ce_varname, "topic-setter"))
+ else if (!strcmp(cep->name, "topic-setter"))
{
CheckNull(cep);
- if (strcmp(cep->ce_vardata, "nick") && strcmp(cep->ce_vardata, "nick-user-host"))
+ if (strcmp(cep->value, "nick") && strcmp(cep->value, "nick-user-host"))
{
config_error("%s:%i: set::topic-setter: value should be 'nick' or 'nick-user-host'",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "ban-setter"))
+ else if (!strcmp(cep->name, "ban-setter"))
{
CheckNull(cep);
- if (strcmp(cep->ce_vardata, "nick") && strcmp(cep->ce_vardata, "nick-user-host"))
+ if (strcmp(cep->value, "nick") && strcmp(cep->value, "nick-user-host"))
{
config_error("%s:%i: set::ban-setter: value should be 'nick' or 'nick-user-host'",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "ban-setter-sync") || !strcmp(cep->ce_varname, "ban-setter-synch"))
+ else if (!strcmp(cep->name, "ban-setter-sync") || !strcmp(cep->name, "ban-setter-synch"))
{
CheckNull(cep);
}
- else if (!strcmp(cep->ce_varname, "part-instead-of-quit-on-comment-change"))
+ else if (!strcmp(cep->name, "part-instead-of-quit-on-comment-change"))
{
CheckNull(cep);
}
- else if (!strcmp(cep->ce_varname, "broadcast-channel-messages"))
+ else if (!strcmp(cep->name, "broadcast-channel-messages"))
{
CheckNull(cep);
- if (strcmp(cep->ce_vardata, "auto") &&
- strcmp(cep->ce_vardata, "always") &&
- strcmp(cep->ce_vardata, "never"))
+ if (strcmp(cep->value, "auto") &&
+ strcmp(cep->value, "always") &&
+ strcmp(cep->value, "never"))
{
config_error("%s:%i: set::broadcast-channel-messages: value should be 'auto', 'always' or 'never'",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "allowed-channelchars"))
+ else if (!strcmp(cep->name, "allowed-channelchars"))
{
CheckNull(cep);
- if (!allowed_channelchars_strtoval(cep->ce_vardata))
+ if (!allowed_channelchars_strtoval(cep->value))
{
config_error("%s:%i: set::allowed-channelchars: value should be one of: 'ascii', 'utf8' or 'any'",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "hide-idle-time"))
+ else if (!strcmp(cep->name, "hide-idle-time"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
CheckNull(cepp);
- if (!strcmp(cepp->ce_varname, "policy"))
+ if (!strcmp(cepp->name, "policy"))
{
- if (!hideidletime_strtoval(cepp->ce_vardata))
+ if (!hideidletime_strtoval(cepp->value))
{
config_error("%s:%i: set::hide-idle-time::policy: value should be one of: 'never', 'always', 'usermode' or 'oper-usermode'",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum);
+ cepp->file->filename, cepp->line_number);
errors++;
}
}
else
{
- config_error_unknown(cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum, "set::hide-idle-time",
- cepp->ce_varname);
+ config_error_unknown(cepp->file->filename,
+ cepp->line_number, "set::hide-idle-time",
+ cepp->name);
errors++;
continue;
}
}
- }
- else
+ } else
{
int used = 0;
for (h = Hooks[HOOKTYPE_CONFIGTEST]; h; h = h->next)
@@ -9379,8 +9077,8 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
}
if (!used) {
config_error("%s:%i: unknown directive set::%s",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- cep->ce_varname);
+ cep->file->filename, cep->line_number,
+ cep->name);
errors++;
}
}
@@ -9390,44 +9088,25 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
int _conf_loadmodule(ConfigFile *conf, ConfigEntry *ce)
{
- char *ret;
- if (!ce->ce_vardata)
+ const char *ret;
+ if (!ce->value)
{
config_status("%s:%i: loadmodule without filename",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
return -1;
}
- if (strstr(ce->ce_vardata, "commands.so") || strstr(ce->ce_vardata, "commands.dll"))
- {
- config_error("%s:%i: You are trying to load the 'commands' module, this is no longer supported. "
- "Fix this by editing your configuration file: remove the loadmodule line for commands and add the following line instead: "
- "include \"modules.default.conf\";",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
- need_34_upgrade = 1;
- return -1;
- }
- if (strstr(ce->ce_vardata, "modules/cloak") && !strcmp(conf->cf_filename, "modules.conf"))
- {
- config_error("You seem to have an include for 'modules.conf'.");
- config_error("If you have this because you are upgrading from 3.4-alpha3 to");
- config_error("UnrealIRCd 4 then please change the include \"modules.conf\";");
- config_error("into an include \"modules.default.conf\"; (probably in your");
- config_error("conf/unrealircd.conf). Yeah, we changed the file name.");
- // TODO ^: silly win32 wrapping prevents this from being displayed otherwise. PLZ FIX! !
- /* let it continue to load anyway? */
- }
- if (is_blacklisted_module(ce->ce_vardata))
+ if (is_blacklisted_module(ce->value))
{
/* config_warn("%s:%i: Module '%s' is blacklisted, not loading",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_vardata); */
+ ce->file->filename, ce->line_number, ce->value); */
return 1;
}
- if ((ret = Module_Create(ce->ce_vardata))) {
- config_status("%s:%i: loadmodule %s: failed to load: %s",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- ce->ce_vardata, ret);
+ if ((ret = Module_Create(ce->value))) {
+ config_error("%s:%i: loadmodule %s: failed to load: %s",
+ ce->file->filename, ce->line_number,
+ ce->value, ret);
return -1;
}
return 1;
@@ -9440,17 +9119,17 @@ int _test_loadmodule(ConfigFile *conf, ConfigEntry *ce)
int _test_blacklist_module(ConfigFile *conf, ConfigEntry *ce)
{
- char *path;
+ const char *path;
ConfigItem_blacklist_module *m;
- if (!ce->ce_vardata)
+ if (!ce->value)
{
config_status("%s:%i: blacklist-module: no module name given to blacklist",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
return -1;
}
- path = Module_TransformPath(ce->ce_vardata);
+ path = Module_TransformPath(ce->value);
/* Is it a good idea to warn about this?
* Yes, the user may have made a typo, thinking (s)he blacklisted something
@@ -9462,20 +9141,20 @@ int _test_blacklist_module(ConfigFile *conf, ConfigEntry *ce)
if (!file_exists(path))
{
config_warn("%s:%i: blacklist-module for '%s' but module does not exist anyway",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_vardata);
+ ce->file->filename, ce->line_number, ce->value);
/* fallthrough */
}
m = safe_alloc(sizeof(ConfigItem_blacklist_module));
- safe_strdup(m->name, ce->ce_vardata);
+ safe_strdup(m->name, ce->value);
AddListItem(m, conf_blacklist_module);
return 0;
}
-int is_blacklisted_module(char *name)
+int is_blacklisted_module(const char *name)
{
- char *path = Module_TransformPath(name);
+ const char *path = Module_TransformPath(name);
ConfigItem_blacklist_module *m;
for (m = conf_blacklist_module; m; m = m->next)
@@ -9487,37 +9166,39 @@ int is_blacklisted_module(char *name)
void start_listeners(void)
{
- ConfigItem_listen *listenptr;
+ ConfigItem_listen *listener;
int failed = 0, ports_bound = 0;
char boundmsg_ipv4[512], boundmsg_ipv6[512];
+ int last_errno = 0;
*boundmsg_ipv4 = *boundmsg_ipv6 = '\0';
- for (listenptr = conf_listen; listenptr; listenptr = listenptr->next)
+ for (listener = conf_listen; listener; listener = listener->next)
{
/* Try to bind to any ports that are not yet bound and not marked as temporary */
- if (!(listenptr->options & LISTENER_BOUND) && !listenptr->flag.temporary)
+ if (!(listener->options & LISTENER_BOUND) && !listener->flag.temporary)
{
- if (add_listener(listenptr) == -1)
+ if (add_listener(listener) == -1)
{
- ircd_log(LOG_ERROR, "Failed to bind to %s:%i", listenptr->ip, listenptr->port);
+ /* Error already printed upstream */
failed = 1;
+ last_errno = ERRNO;
} else {
- if (loop.ircd_booted)
+ if (loop.booted)
{
- ircd_log(LOG_ERROR, "UnrealIRCd is now also listening on %s:%d (%s)%s",
- listenptr->ip, listenptr->port,
- listenptr->ipv6 ? "IPv6" : "IPv4",
- listenptr->options & LISTENER_TLS ? " (SSL/TLS)" : "");
+ unreal_log(ULOG_INFO, "listen", "LISTEN_ADDED", NULL,
+ "UnrealIRCd is now also listening on $listen_ip:$listen_port",
+ log_data_string("listen_ip", listener->ip),
+ log_data_integer("listen_port", listener->port));
} else {
- if (listenptr->ipv6)
+ if (listener->ipv6)
snprintf(boundmsg_ipv6+strlen(boundmsg_ipv6), sizeof(boundmsg_ipv6)-strlen(boundmsg_ipv6),
- "%s:%d%s, ", listenptr->ip, listenptr->port,
- listenptr->options & LISTENER_TLS ? "(SSL/TLS)" : "");
+ "%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, ", listenptr->ip, listenptr->port,
- listenptr->options & LISTENER_TLS ? "(SSL/TLS)" : "");
+ "%s:%d%s, ", listener->ip, listener->port,
+ listener->options & LISTENER_TLS ? "(TLS)" : "");
}
}
}
@@ -9525,58 +9206,83 @@ void start_listeners(void)
/* NOTE: do not merge this with code above (nor in an else block),
* as add_listener() affects this flag.
*/
- if (listenptr->options & LISTENER_BOUND)
+ if (listener->options & LISTENER_BOUND)
ports_bound++;
}
if (ports_bound == 0)
{
- ircd_log(LOG_ERROR, "IRCd could not listen on any ports. If you see 'Address already in use' errors "
- "above then most likely the IRCd is already running (or something else is using the "
- "specified ports). If you are sure the IRCd is not running then verify your "
- "listen blocks, maybe you have to bind to a specific IP rather than \"*\".");
+#ifdef _WIN32
+ if (last_errno == WSAEADDRINUSE)
+#else
+ if (last_errno == EADDRINUSE)
+#endif
+ {
+ /* We can be specific */
+ unreal_log(ULOG_FATAL, "listen", "ALL_LISTEN_PORTS_FAILED", NULL,
+ "Unable to listen on any ports. "
+ "Most likely UnrealIRCd is already running.");
+ } else {
+ unreal_log(ULOG_FATAL, "listen", "ALL_LISTEN_PORTS_FAILED", NULL,
+ "Unable to listen on any ports. "
+ "Please verify that no other process is using the ports. "
+ "Also, on some IRCd shells you may have to use listen::bind-ip "
+ "with a specific IP assigned to you (rather than \"*\").");
+ }
exit(-1);
}
- if (failed && !loop.ircd_booted)
+ if (failed && !loop.booted)
{
- ircd_log(LOG_ERROR, "Could not listen on all specified addresses/ports. See errors above. "
- "Please fix your listen { } blocks and/or make sure no other programs "
- "are listening on the same port.");
+ unreal_log(ULOG_FATAL, "listen", "SOME_LISTEN_PORTS_FAILED", NULL,
+ "Unable to listen on all ports (some of them succeeded, some of them failed). "
+ "Please verify that no other process is using the port(s). "
+ "Also, on some IRCd shells you may have to use listen::bind-ip "
+ "with a specific IP assigned to you (rather than \"*\").");
exit(-1);
}
- if (!loop.ircd_booted)
+ if (!loop.booted)
{
if (strlen(boundmsg_ipv4) > 2)
boundmsg_ipv4[strlen(boundmsg_ipv4)-2] = '\0';
if (strlen(boundmsg_ipv6) > 2)
boundmsg_ipv6[strlen(boundmsg_ipv6)-2] = '\0';
- ircd_log(LOG_ERROR, "UnrealIRCd is now listening on the following addresses/ports:");
- ircd_log(LOG_ERROR, "IPv4: %s", *boundmsg_ipv4 ? boundmsg_ipv4 : "");
- ircd_log(LOG_ERROR, "IPv6: %s", *boundmsg_ipv6 ? boundmsg_ipv6 : "");
+ if (!*boundmsg_ipv4)
+ strlcpy(boundmsg_ipv4, "", sizeof(boundmsg_ipv4));
+ if (!*boundmsg_ipv6)
+ strlcpy(boundmsg_ipv6, "", sizeof(boundmsg_ipv6));
+
+ unreal_log(ULOG_INFO, "listen", "LISTENING", NULL,
+ "UnrealIRCd is now listening on the following addresses/ports:\n"
+ "IPv4: $ipv4_port_list\n"
+ "IPv6: $ipv6_port_list\n",
+ log_data_string("ipv4_port_list", boundmsg_ipv4),
+ log_data_string("ipv6_port_list", boundmsg_ipv6));
}
}
/* Actually use configuration */
-void run_configuration(void)
+void config_run(void)
{
+ extcmodes_check_for_changes();
start_listeners();
+ free_all_config_resources();
}
int _conf_offchans(ConfigFile *conf, ConfigEntry *ce)
{
ConfigEntry *cep, *cepp;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
ConfigItem_offchans *of = safe_alloc(sizeof(ConfigItem_offchans));
- strlcpy(of->chname, cep->ce_varname, CHANNELLEN+1);
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ strlcpy(of->name, cep->name, CHANNELLEN+1);
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "topic"))
- safe_strdup(of->topic, cepp->ce_vardata);
+ if (!strcmp(cepp->name, "topic"))
+ safe_strdup(of->topic, cepp->value);
}
AddListItem(of, conf_offchans);
}
@@ -9588,10 +9294,10 @@ int _test_offchans(ConfigFile *conf, ConfigEntry *ce)
int errors = 0;
ConfigEntry *cep, *cep2;
- if (!ce->ce_entries)
+ if (!ce->items)
{
config_error("%s:%i: empty official-channels block",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
return 1;
}
@@ -9600,45 +9306,45 @@ int _test_offchans(ConfigFile *conf, ConfigEntry *ce)
"and then making the channel permanent (MODE #channel +P). "
"The channel will then be stored in a database to preserve it between restarts.");
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (strlen(cep->ce_varname) > CHANNELLEN)
+ if (strlen(cep->name) > CHANNELLEN)
{
config_error("%s:%i: official-channels: '%s' name too long (max %d characters).",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname, CHANNELLEN);
+ cep->file->filename, cep->line_number, cep->name, CHANNELLEN);
errors++;
continue;
}
- if (!valid_channelname(cep->ce_varname))
+ if (!valid_channelname(cep->name))
{
config_error("%s:%i: official-channels: '%s' is not a valid channel name.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname);
+ cep->file->filename, cep->line_number, cep->name);
errors++;
continue;
}
- for (cep2 = cep->ce_entries; cep2; cep2 = cep2->ce_next)
+ for (cep2 = cep->items; cep2; cep2 = cep2->next)
{
- if (!cep2->ce_vardata)
+ if (!cep2->value)
{
- config_error_empty(cep2->ce_fileptr->cf_filename,
- cep2->ce_varlinenum, "official-channels",
- cep2->ce_varname);
+ config_error_empty(cep2->file->filename,
+ cep2->line_number, "official-channels",
+ cep2->name);
errors++;
continue;
}
- if (!strcmp(cep2->ce_varname, "topic"))
+ if (!strcmp(cep2->name, "topic"))
{
- if (strlen(cep2->ce_vardata) > MAXTOPICLEN)
+ if (strlen(cep2->value) > MAXTOPICLEN)
{
config_error("%s:%i: official-channels::%s: topic too long (max %d characters).",
- cep2->ce_fileptr->cf_filename, cep2->ce_varlinenum, cep->ce_varname, MAXTOPICLEN);
+ cep2->file->filename, cep2->line_number, cep->name, MAXTOPICLEN);
errors++;
continue;
}
} else {
- config_error_unknown(cep2->ce_fileptr->cf_filename,
- cep2->ce_varlinenum, "official-channels",
- cep2->ce_varname);
+ config_error_unknown(cep2->file->filename,
+ cep2->line_number, "official-channels",
+ cep2->name);
errors++;
continue;
}
@@ -9654,70 +9360,70 @@ int _conf_alias(ConfigFile *conf, ConfigEntry *ce)
ConfigEntry *cep, *cepp;
RealCommand *cmptr;
- if ((cmptr = find_command(ce->ce_vardata, CMD_ALIAS)))
+ if ((cmptr = find_command(ce->value, CMD_ALIAS)))
CommandDelX(NULL, cmptr);
- if (find_command_simple(ce->ce_vardata))
+ if (find_command_simple(ce->value))
{
config_warn("%s:%i: Alias '%s' would conflict with command (or server token) '%s', alias not added.",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- ce->ce_vardata, ce->ce_vardata);
+ ce->file->filename, ce->line_number,
+ ce->value, ce->value);
return 0;
}
- if ((alias = find_alias(ce->ce_vardata)))
+ if ((alias = find_alias(ce->value)))
DelListItem(alias, conf_alias);
alias = safe_alloc(sizeof(ConfigItem_alias));
- safe_strdup(alias->alias, ce->ce_vardata);
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ safe_strdup(alias->alias, ce->value);
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "format")) {
+ if (!strcmp(cep->name, "format")) {
format = safe_alloc(sizeof(ConfigItem_alias_format));
- safe_strdup(format->format, cep->ce_vardata);
- format->expr = unreal_create_match(MATCH_PCRE_REGEX, cep->ce_vardata, NULL);
+ safe_strdup(format->format, cep->value);
+ format->expr = unreal_create_match(MATCH_PCRE_REGEX, cep->value, NULL);
if (!format->expr)
abort(); /* Impossible due to _test_alias earlier */
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next) {
- if (!strcmp(cepp->ce_varname, "nick") ||
- !strcmp(cepp->ce_varname, "target") ||
- !strcmp(cepp->ce_varname, "command")) {
- safe_strdup(format->nick, cepp->ce_vardata);
+ for (cepp = cep->items; cepp; cepp = cepp->next) {
+ if (!strcmp(cepp->name, "nick") ||
+ !strcmp(cepp->name, "target") ||
+ !strcmp(cepp->name, "command")) {
+ safe_strdup(format->nick, cepp->value);
}
- else if (!strcmp(cepp->ce_varname, "parameters")) {
- safe_strdup(format->parameters, cepp->ce_vardata);
+ else if (!strcmp(cepp->name, "parameters")) {
+ safe_strdup(format->parameters, cepp->value);
}
- else if (!strcmp(cepp->ce_varname, "type")) {
- if (!strcmp(cepp->ce_vardata, "services"))
+ else if (!strcmp(cepp->name, "type")) {
+ if (!strcmp(cepp->value, "services"))
format->type = ALIAS_SERVICES;
- else if (!strcmp(cepp->ce_vardata, "stats"))
+ else if (!strcmp(cepp->value, "stats"))
format->type = ALIAS_STATS;
- else if (!strcmp(cepp->ce_vardata, "normal"))
+ else if (!strcmp(cepp->value, "normal"))
format->type = ALIAS_NORMAL;
- else if (!strcmp(cepp->ce_vardata, "channel"))
+ else if (!strcmp(cepp->value, "channel"))
format->type = ALIAS_CHANNEL;
- else if (!strcmp(cepp->ce_vardata, "real"))
+ else if (!strcmp(cepp->value, "real"))
format->type = ALIAS_REAL;
}
}
AddListItem(format, alias->format);
}
- else if (!strcmp(cep->ce_varname, "nick") || !strcmp(cep->ce_varname, "target"))
+ else if (!strcmp(cep->name, "nick") || !strcmp(cep->name, "target"))
{
- safe_strdup(alias->nick, cep->ce_vardata);
+ safe_strdup(alias->nick, cep->value);
}
- else if (!strcmp(cep->ce_varname, "type")) {
- if (!strcmp(cep->ce_vardata, "services"))
+ else if (!strcmp(cep->name, "type")) {
+ if (!strcmp(cep->value, "services"))
alias->type = ALIAS_SERVICES;
- else if (!strcmp(cep->ce_vardata, "stats"))
+ else if (!strcmp(cep->value, "stats"))
alias->type = ALIAS_STATS;
- else if (!strcmp(cep->ce_vardata, "normal"))
+ else if (!strcmp(cep->value, "normal"))
alias->type = ALIAS_NORMAL;
- else if (!strcmp(cep->ce_vardata, "channel"))
+ else if (!strcmp(cep->value, "channel"))
alias->type = ALIAS_CHANNEL;
- else if (!strcmp(cep->ce_vardata, "command"))
+ else if (!strcmp(cep->value, "command"))
alias->type = ALIAS_COMMAND;
}
- else if (!strcmp(cep->ce_varname, "spamfilter"))
- alias->spamfilter = config_checkval(cep->ce_vardata, CFG_YESNO);
+ else if (!strcmp(cep->name, "spamfilter"))
+ alias->spamfilter = config_checkval(cep->value, CFG_YESNO);
}
if (BadPtr(alias->nick) && alias->type != ALIAS_COMMAND) {
safe_strdup(alias->nick, alias->alias);
@@ -9735,99 +9441,97 @@ int _test_alias(ConfigFile *conf, ConfigEntry *ce) {
char has_type = 0, has_target = 0, has_format = 0;
char type = 0;
- if (!ce->ce_entries)
+ if (!ce->items)
{
config_error("%s:%i: empty alias block",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
return 1;
}
- if (!ce->ce_vardata)
+ if (!ce->value)
{
config_error("%s:%i: alias without name",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
}
- else if (!find_command(ce->ce_vardata, CMD_ALIAS) && find_command(ce->ce_vardata, 0)) {
+ else if (!find_command(ce->value, CMD_ALIAS) && find_command(ce->value, 0)) {
config_status("%s:%i: %s is an existing command, can not add alias",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_vardata);
+ ce->file->filename, ce->line_number, ce->value);
errors++;
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
if (config_is_blankorempty(cep, "alias"))
{
errors++;
continue;
}
- if (!strcmp(cep->ce_varname, "format")) {
+ if (!strcmp(cep->name, "format")) {
char *err = NULL;
Match *expr;
char has_type = 0, has_target = 0, has_parameters = 0;
has_format = 1;
- expr = unreal_create_match(MATCH_PCRE_REGEX, cep->ce_vardata, &err);
+ expr = unreal_create_match(MATCH_PCRE_REGEX, cep->value, &err);
if (!expr)
{
config_error("%s:%i: alias::format contains an invalid regex: %s",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, err);
- config_error("Upgrading from 3.2.x to UnrealIRCd 4? Note that regex changed from POSIX Regex "
- "to PCRE Regex!"); /* TODO: refer to some url ? */
+ cep->file->filename, cep->line_number, err);
} else {
unreal_delete_match(expr);
}
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next) {
+ for (cepp = cep->items; cepp; cepp = cepp->next) {
if (config_is_blankorempty(cepp, "alias::format"))
{
errors++;
continue;
}
- if (!strcmp(cepp->ce_varname, "nick") ||
- !strcmp(cepp->ce_varname, "command") ||
- !strcmp(cepp->ce_varname, "target"))
+ if (!strcmp(cepp->name, "nick") ||
+ !strcmp(cepp->name, "command") ||
+ !strcmp(cepp->name, "target"))
{
if (has_target)
{
- config_warn_duplicate(cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum,
+ config_warn_duplicate(cepp->file->filename,
+ cepp->line_number,
"alias::format::target");
continue;
}
has_target = 1;
}
- else if (!strcmp(cepp->ce_varname, "type"))
+ else if (!strcmp(cepp->name, "type"))
{
if (has_type)
{
- config_warn_duplicate(cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum,
+ config_warn_duplicate(cepp->file->filename,
+ cepp->line_number,
"alias::format::type");
continue;
}
has_type = 1;
- if (!strcmp(cepp->ce_vardata, "services"))
+ if (!strcmp(cepp->value, "services"))
;
- else if (!strcmp(cepp->ce_vardata, "stats"))
+ else if (!strcmp(cepp->value, "stats"))
;
- else if (!strcmp(cepp->ce_vardata, "normal"))
+ else if (!strcmp(cepp->value, "normal"))
;
- else if (!strcmp(cepp->ce_vardata, "channel"))
+ else if (!strcmp(cepp->value, "channel"))
;
- else if (!strcmp(cepp->ce_vardata, "real"))
+ else if (!strcmp(cepp->value, "real"))
;
else
{
config_error("%s:%i: unknown alias type",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum);
+ cepp->file->filename, cepp->line_number);
errors++;
}
}
- else if (!strcmp(cepp->ce_varname, "parameters"))
+ else if (!strcmp(cepp->name, "parameters"))
{
if (has_parameters)
{
- config_warn_duplicate(cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum,
+ config_warn_duplicate(cepp->file->filename,
+ cepp->line_number,
"alias::format::parameters");
continue;
}
@@ -9835,89 +9539,89 @@ int _test_alias(ConfigFile *conf, ConfigEntry *ce) {
}
else
{
- config_error_unknown(cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum, "alias::format",
- cepp->ce_varname);
+ config_error_unknown(cepp->file->filename,
+ cepp->line_number, "alias::format",
+ cepp->name);
errors++;
}
}
if (!has_target)
{
- config_error_missing(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "alias::format::target");
+ config_error_missing(cep->file->filename,
+ cep->line_number, "alias::format::target");
errors++;
}
if (!has_type)
{
- config_error_missing(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "alias::format::type");
+ config_error_missing(cep->file->filename,
+ cep->line_number, "alias::format::type");
errors++;
}
if (!has_parameters)
{
- config_error_missing(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "alias::format::parameters");
+ config_error_missing(cep->file->filename,
+ cep->line_number, "alias::format::parameters");
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "nick") || !strcmp(cep->ce_varname, "target"))
+ else if (!strcmp(cep->name, "nick") || !strcmp(cep->name, "target"))
{
if (has_target)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "alias::target");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "alias::target");
continue;
}
has_target = 1;
}
- else if (!strcmp(cep->ce_varname, "type")) {
+ else if (!strcmp(cep->name, "type")) {
if (has_type)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "alias::type");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "alias::type");
continue;
}
has_type = 1;
- if (!strcmp(cep->ce_vardata, "services"))
+ if (!strcmp(cep->value, "services"))
;
- else if (!strcmp(cep->ce_vardata, "stats"))
+ else if (!strcmp(cep->value, "stats"))
;
- else if (!strcmp(cep->ce_vardata, "normal"))
+ else if (!strcmp(cep->value, "normal"))
;
- else if (!strcmp(cep->ce_vardata, "channel"))
+ else if (!strcmp(cep->value, "channel"))
;
- else if (!strcmp(cep->ce_vardata, "command"))
+ else if (!strcmp(cep->value, "command"))
type = 'c';
else {
config_error("%s:%i: unknown alias type",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "spamfilter"))
+ else if (!strcmp(cep->name, "spamfilter"))
;
else {
- config_error_unknown(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- "alias", cep->ce_varname);
+ config_error_unknown(cep->file->filename, cep->line_number,
+ "alias", cep->name);
errors++;
}
}
if (!has_type)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"alias::type");
errors++;
}
if (!has_format && type == 'c')
{
config_error("%s:%d: alias::type is 'command' but no alias::format was specified",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
}
else if (has_format && type != 'c')
{
config_error("%s:%d: alias::format specified when type is not 'command'",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
}
return errors;
@@ -9927,11 +9631,11 @@ int _conf_deny(ConfigFile *conf, ConfigEntry *ce)
{
Hook *h;
- if (!strcmp(ce->ce_vardata, "channel"))
+ if (!strcmp(ce->value, "channel"))
_conf_deny_channel(conf, ce);
- else if (!strcmp(ce->ce_vardata, "link"))
+ else if (!strcmp(ce->value, "link"))
_conf_deny_link(conf, ce);
- else if (!strcmp(ce->ce_vardata, "version"))
+ else if (!strcmp(ce->value, "version"))
_conf_deny_version(conf, ce);
else
{
@@ -9953,29 +9657,29 @@ int _conf_deny_channel(ConfigFile *conf, ConfigEntry *ce)
ConfigEntry *cep;
deny = safe_alloc(sizeof(ConfigItem_deny_channel));
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "channel"))
+ if (!strcmp(cep->name, "channel"))
{
- safe_strdup(deny->channel, cep->ce_vardata);
+ safe_strdup(deny->channel, cep->value);
}
- else if (!strcmp(cep->ce_varname, "redirect"))
+ else if (!strcmp(cep->name, "redirect"))
{
- safe_strdup(deny->redirect, cep->ce_vardata);
+ safe_strdup(deny->redirect, cep->value);
}
- else if (!strcmp(cep->ce_varname, "reason"))
+ else if (!strcmp(cep->name, "reason"))
{
- safe_strdup(deny->reason, cep->ce_vardata);
+ safe_strdup(deny->reason, cep->value);
}
- else if (!strcmp(cep->ce_varname, "warn"))
+ else if (!strcmp(cep->name, "warn"))
{
- deny->warn = config_checkval(cep->ce_vardata,CFG_YESNO);
+ deny->warn = config_checkval(cep->value,CFG_YESNO);
}
- else if (!strcmp(cep->ce_varname, "class"))
+ else if (!strcmp(cep->name, "class"))
{
- safe_strdup(deny->class, cep->ce_vardata);
+ safe_strdup(deny->class, cep->value);
}
- else if (!strcmp(cep->ce_varname, "mask"))
+ else if (!strcmp(cep->name, "mask"))
{
unreal_add_masks(&deny->mask, cep);
}
@@ -9989,21 +9693,21 @@ int _conf_deny_link(ConfigFile *conf, ConfigEntry *ce)
ConfigEntry *cep;
deny = safe_alloc(sizeof(ConfigItem_deny_link));
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "mask"))
+ if (!strcmp(cep->name, "mask"))
{
- safe_strdup(deny->mask, cep->ce_vardata);
+ unreal_add_masks(&deny->mask, cep);
}
- else if (!strcmp(cep->ce_varname, "rule"))
+ else if (!strcmp(cep->name, "rule"))
{
- deny->rule = (char *)crule_parse(cep->ce_vardata);
- safe_strdup(deny->prettyrule, cep->ce_vardata);
+ deny->rule = (char *)crule_parse(cep->value);
+ safe_strdup(deny->prettyrule, cep->value);
}
- else if (!strcmp(cep->ce_varname, "type")) {
- if (!strcmp(cep->ce_vardata, "all"))
+ else if (!strcmp(cep->name, "type")) {
+ if (!strcmp(cep->value, "all"))
deny->flag.type = CRULE_ALL;
- else if (!strcmp(cep->ce_vardata, "auto"))
+ else if (!strcmp(cep->value, "auto"))
deny->flag.type = CRULE_AUTO;
}
}
@@ -10017,19 +9721,19 @@ int _conf_deny_version(ConfigFile *conf, ConfigEntry *ce)
ConfigEntry *cep;
deny = safe_alloc(sizeof(ConfigItem_deny_version));
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "mask"))
+ if (!strcmp(cep->name, "mask"))
{
- safe_strdup(deny->mask, cep->ce_vardata);
+ safe_strdup(deny->mask, cep->value);
}
- else if (!strcmp(cep->ce_varname, "version"))
+ else if (!strcmp(cep->name, "version"))
{
- safe_strdup(deny->version, cep->ce_vardata);
+ safe_strdup(deny->version, cep->value);
}
- else if (!strcmp(cep->ce_varname, "flags"))
+ else if (!strcmp(cep->name, "flags"))
{
- safe_strdup(deny->flags, cep->ce_vardata);
+ safe_strdup(deny->flags, cep->value);
}
}
AddListItem(deny, conf_deny_version);
@@ -10042,241 +9746,253 @@ int _test_deny(ConfigFile *conf, ConfigEntry *ce)
int errors = 0;
Hook *h;
- if (!ce->ce_vardata)
+ if (!ce->value)
{
config_error("%s:%i: deny without type",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
return 1;
}
- if (!strcmp(ce->ce_vardata, "channel"))
+ if (!strcmp(ce->value, "channel"))
{
char has_channel = 0, has_warn = 0, has_reason = 0, has_redirect = 0, has_class = 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
if (config_is_blankorempty(cep, "deny channel"))
{
errors++;
continue;
}
- if (!strcmp(cep->ce_varname, "channel"))
+ if (!strcmp(cep->name, "channel"))
{
if (has_channel)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny channel::channel");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "deny channel::channel");
continue;
}
has_channel = 1;
}
- else if (!strcmp(cep->ce_varname, "redirect"))
+ else if (!strcmp(cep->name, "redirect"))
{
if (has_redirect)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny channel::redirect");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "deny channel::redirect");
continue;
}
has_redirect = 1;
}
- else if (!strcmp(cep->ce_varname, "reason"))
+ else if (!strcmp(cep->name, "reason"))
{
if (has_reason)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny channel::reason");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "deny channel::reason");
continue;
}
has_reason = 1;
}
- else if (!strcmp(cep->ce_varname, "warn"))
+ else if (!strcmp(cep->name, "warn"))
{
if (has_warn)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny channel::warn");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "deny channel::warn");
continue;
}
has_warn = 1;
}
- else if (!strcmp(cep->ce_varname, "class"))
+ else if (!strcmp(cep->name, "class"))
{
if (has_class)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny channel::class");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "deny channel::class");
continue;
}
has_class = 1;
}
- else if (!strcmp(cep->ce_varname, "mask"))
+ else if (!strcmp(cep->name, "mask"))
{
}
else
{
- config_error_unknown(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny channel", cep->ce_varname);
+ config_error_unknown(cep->file->filename,
+ cep->line_number, "deny channel", cep->name);
errors++;
}
}
if (!has_channel)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"deny channel::channel");
errors++;
}
if (!has_reason)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"deny channel::reason");
errors++;
}
}
- else if (!strcmp(ce->ce_vardata, "link"))
+ else if (!strcmp(ce->value, "link"))
{
char has_mask = 0, has_rule = 0, has_type = 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (config_is_blankorempty(cep, "deny link"))
+ if (!cep->items)
{
- errors++;
- continue;
- }
- if (!strcmp(cep->ce_varname, "mask"))
- {
- if (has_mask)
+ if (config_is_blankorempty(cep, "deny link"))
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny link::mask");
- continue;
- }
- has_mask = 1;
- }
- else if (!strcmp(cep->ce_varname, "rule"))
- {
- int val = 0;
- if (has_rule)
- {
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny link::rule");
- continue;
- }
- has_rule = 1;
- if ((val = crule_test(cep->ce_vardata)))
- {
- config_error("%s:%i: deny link::rule contains an invalid expression: %s",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum,
- crule_errstring(val));
errors++;
- }
- }
- else if (!strcmp(cep->ce_varname, "type"))
- {
- if (has_type)
- {
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny link::type");
continue;
}
- has_type = 1;
- if (!strcmp(cep->ce_vardata, "auto"))
- ;
- else if (!strcmp(cep->ce_vardata, "all"))
- ;
- else {
- config_status("%s:%i: unknown deny link type",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ else if (!strcmp(cep->name, "mask"))
+ {
+ has_mask = 1;
+ } else if (!strcmp(cep->name, "rule"))
+ {
+ int val = 0;
+ if (has_rule)
+ {
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "deny link::rule");
+ continue;
+ }
+ has_rule = 1;
+ if ((val = crule_test(cep->value)))
+ {
+ config_error("%s:%i: deny link::rule contains an invalid expression: %s",
+ cep->file->filename,
+ cep->line_number,
+ crule_errstring(val));
+ errors++;
+ }
+ }
+ else if (!strcmp(cep->name, "type"))
+ {
+ if (has_type)
+ {
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "deny link::type");
+ continue;
+ }
+ has_type = 1;
+ if (!strcmp(cep->value, "auto"))
+ ;
+ else if (!strcmp(cep->value, "all"))
+ ;
+ else {
+ config_status("%s:%i: unknown deny link type",
+ cep->file->filename, cep->line_number);
+ errors++;
+ }
+ }
+ else
+ {
+ config_error_unknown(cep->file->filename,
+ cep->line_number, "deny link", cep->name);
errors++;
}
}
else
{
- config_error_unknown(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny link", cep->ce_varname);
- errors++;
+ // Sections
+ if (!strcmp(cep->name, "mask"))
+ {
+ if (cep->value || cep->items)
+ has_mask = 1;
+ }
+ else
+ {
+ config_error_unknown(cep->file->filename,
+ cep->line_number, "deny link", cep->name);
+ errors++;
+ continue;
+ }
}
}
if (!has_mask)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"deny link::mask");
errors++;
}
if (!has_rule)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"deny link::rule");
errors++;
}
if (!has_type)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"deny link::type");
errors++;
}
}
- else if (!strcmp(ce->ce_vardata, "version"))
+ else if (!strcmp(ce->value, "version"))
{
char has_mask = 0, has_version = 0, has_flags = 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
if (config_is_blankorempty(cep, "deny version"))
{
errors++;
continue;
}
- if (!strcmp(cep->ce_varname, "mask"))
+ if (!strcmp(cep->name, "mask"))
{
if (has_mask)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny version::mask");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "deny version::mask");
continue;
}
has_mask = 1;
}
- else if (!strcmp(cep->ce_varname, "version"))
+ else if (!strcmp(cep->name, "version"))
{
if (has_version)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny version::version");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "deny version::version");
continue;
}
has_version = 1;
}
- else if (!strcmp(cep->ce_varname, "flags"))
+ else if (!strcmp(cep->name, "flags"))
{
if (has_flags)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny version::flags");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "deny version::flags");
continue;
}
has_flags = 1;
}
else
{
- config_error_unknown(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny version", cep->ce_varname);
+ config_error_unknown(cep->file->filename,
+ cep->line_number, "deny version", cep->name);
errors++;
}
}
if (!has_mask)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"deny version::mask");
errors++;
}
if (!has_version)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"deny version::version");
errors++;
}
if (!has_flags)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"deny version::flags");
errors++;
}
@@ -10312,8 +10028,8 @@ int _test_deny(ConfigFile *conf, ConfigEntry *ce)
}
if (!used) {
config_error("%s:%i: unknown deny type %s",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- ce->ce_vardata);
+ ce->file->filename, ce->line_number,
+ ce->value);
return 1;
}
return errors;
@@ -10327,59 +10043,62 @@ int _test_security_group(ConfigFile *conf, ConfigEntry *ce)
int errors = 0;
ConfigEntry *cep;
- if (!ce->ce_vardata)
+ if (!ce->value)
{
config_error("%s:%i: security-group block needs a name, eg: security-group web-users {",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
} else {
- if (!strcasecmp(ce->ce_vardata, "unknown-users"))
+ if (!strcasecmp(ce->value, "unknown-users"))
{
config_error("%s:%i: The 'unknown-users' group is a special group that is the "
"inverse of 'known-users', you cannot create or adjust it in the "
"config file, as it is created automatically by UnrealIRCd.",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
return errors;
}
- if (!security_group_valid_name(ce->ce_vardata))
+ if (!security_group_valid_name(ce->value))
{
config_error("%s:%i: security-group block name '%s' contains invalid characters or is too long. "
"Only letters, numbers, underscore and hyphen are allowed.",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_vardata);
+ ce->file->filename, ce->line_number, ce->value);
errors++;
}
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "webirc"))
+ if (!strcmp(cep->name, "webirc"))
{
CheckNull(cep);
} else
- if (!strcmp(cep->ce_varname, "identified"))
+ if (!strcmp(cep->name, "identified"))
{
CheckNull(cep);
} else
- if (!strcmp(cep->ce_varname, "tls"))
+ if (!strcmp(cep->name, "tls"))
{
CheckNull(cep);
} else
- if (!strcmp(cep->ce_varname, "reputation-score"))
+ if (!strcmp(cep->name, "reputation-score"))
{
int v;
CheckNull(cep);
- v = atoi(cep->ce_vardata);
+ v = atoi(cep->value);
if ((v < 1) || (v > 10000))
{
config_error("%s:%i: security-group::reputation-score needs to be a value of 1-10000",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
} else
+ if (!strcmp(cep->name, "include-mask"))
{
- config_error_unknown(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- "security-group", cep->ce_varname);
+ } else
+ {
+ config_error_unknown(cep->file->filename, cep->line_number,
+ "security-group", cep->name);
errors++;
continue;
}
@@ -10391,29 +10110,33 @@ int _test_security_group(ConfigFile *conf, ConfigEntry *ce)
int _conf_security_group(ConfigFile *conf, ConfigEntry *ce)
{
ConfigEntry *cep;
- SecurityGroup *s = add_security_group(ce->ce_vardata, 1);
+ SecurityGroup *s = add_security_group(ce->value, 1);
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "webirc"))
- s->webirc = config_checkval(cep->ce_vardata, CFG_YESNO);
- else if (!strcmp(cep->ce_varname, "identified"))
- s->identified = config_checkval(cep->ce_vardata, CFG_YESNO);
- else if (!strcmp(cep->ce_varname, "tls"))
- s->tls = config_checkval(cep->ce_vardata, CFG_YESNO);
- else if (!strcmp(cep->ce_varname, "reputation-score"))
- s->reputation_score = atoi(cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "priority"))
+ if (!strcmp(cep->name, "webirc"))
+ s->webirc = config_checkval(cep->value, CFG_YESNO);
+ else if (!strcmp(cep->name, "identified"))
+ s->identified = config_checkval(cep->value, CFG_YESNO);
+ else if (!strcmp(cep->name, "tls"))
+ s->tls = config_checkval(cep->value, CFG_YESNO);
+ else if (!strcmp(cep->name, "reputation-score"))
+ s->reputation_score = atoi(cep->value);
+ else if (!strcmp(cep->name, "priority"))
{
- s->priority = atoi(cep->ce_vardata);
+ s->priority = atoi(cep->value);
DelListItem(s, securitygroups);
AddListItemPrio(s, securitygroups, s->priority);
}
+ else if (!strcmp(cep->name, "include-mask"))
+ {
+ unreal_add_masks(&s->include_mask, cep);
+ }
}
return 1;
}
-Secret *find_secret(char *secret_name)
+Secret *find_secret(const char *secret_name)
{
Secret *s;
for (s = secrets; s; s = s->next)
@@ -10444,7 +10167,7 @@ void free_secret(Secret *s)
safe_free(s);
}
-char *_conf_secret_read_password_file(char *fname)
+char *_conf_secret_read_password_file(const char *fname)
{
char *pwd, *err;
int fd, n;
@@ -10482,7 +10205,7 @@ char *_conf_secret_read_password_file(char *fname)
return pwd;
}
-char *_conf_secret_read_prompt(char *blockname)
+char *_conf_secret_read_prompt(const char *blockname)
{
char *pwd, *pwd_prompt;
char buf[256];
@@ -10513,54 +10236,54 @@ int _test_secret(ConfigFile *conf, ConfigEntry *ce)
char *err;
Secret *existing;
- if (!ce->ce_vardata)
+ if (!ce->value)
{
config_error("%s:%i: secret block needs a name, eg: secret xyz {",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
- return errors; /* need to return here since we dereference ce->ce_vardata later.. */
+ return errors; /* need to return here since we dereference ce->value later.. */
} else {
- if (!security_group_valid_name(ce->ce_vardata))
+ if (!security_group_valid_name(ce->value))
{
config_error("%s:%i: secret block name '%s' contains invalid characters or is too long. "
"Only letters, numbers, underscore and hyphen are allowed.",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_vardata);
+ ce->file->filename, ce->line_number, ce->value);
errors++;
}
}
- existing = find_secret(ce->ce_vardata);
+ existing = find_secret(ce->value);
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "password"))
+ if (!strcmp(cep->name, "password"))
{
int n;
has_password = 1;
CheckNull(cep);
- if (cep->ce_entries ||
- (((n = Auth_AutoDetectHashType(cep->ce_vardata))) && ((n == AUTHTYPE_BCRYPT) || (n == AUTHTYPE_ARGON2))))
+ if (cep->items ||
+ (((n = Auth_AutoDetectHashType(cep->value))) && ((n == AUTHTYPE_BCRYPT) || (n == AUTHTYPE_ARGON2))))
{
config_error("%s:%d: you cannot use hashed passwords here, see "
"https://www.unrealircd.org/docs/Secret_block#secret-plaintext",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
continue;
}
- if (!valid_secret_password(cep->ce_vardata, &err))
+ if (!valid_secret_password(cep->value, &err))
{
config_error("%s:%d: secret::password does not meet password complexity requirements: %s",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, err);
+ cep->file->filename, cep->line_number, err);
errors++;
}
} else
- if (!strcmp(cep->ce_varname, "password-file"))
+ if (!strcmp(cep->name, "password-file"))
{
char *str;
has_password_file = 1;
CheckNull(cep);
- convert_to_absolute_path(&cep->ce_vardata, CONFDIR);
- if (!file_exists(cep->ce_vardata) && existing && existing->password)
+ convert_to_absolute_path(&cep->value, CONFDIR);
+ if (!file_exists(cep->value) && existing && existing->password)
{
/* Silently ignore the case where a secret block already
* has the password read and now the file is no longer available.
@@ -10569,59 +10292,59 @@ int _test_secret(ConfigFile *conf, ConfigEntry *ce)
*/
} else
{
- str = _conf_secret_read_password_file(cep->ce_vardata);
+ str = _conf_secret_read_password_file(cep->value);
if (!str)
{
config_error("%s:%d: secret::password-file: error reading password from file, see error from above.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
safe_free_sensitive(str);
}
} else
- if (!strcmp(cep->ce_varname, "password-prompt"))
+ if (!strcmp(cep->name, "password-prompt"))
{
#ifdef _WIN32
config_error("%s:%d: secret::password-prompt is not implemented in Windows at the moment, sorry!",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
config_error("Choose a different method to enter passwords or use *NIX");
errors++;
return errors;
#endif
has_password_prompt = 1;
- if (loop.ircd_booted && !find_secret(ce->ce_vardata))
+ if (loop.booted && !find_secret(ce->value))
{
config_error("%s:%d: you cannot add a new secret { } block that uses password-prompt and then /REHASH. "
"With 'password-prompt' you can only add such a password on boot.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
config_error("Either use a different method to enter passwords or restart the IRCd on the console.");
errors++;
}
- if (!loop.ircd_booted && !running_interactively())
+ if (!loop.booted && !running_interactively())
{
config_error("ERROR: IRCd is not running interactively, but via a cron job or something similar.");
config_error("%s:%d: unable to prompt for password since IRCd is not started in a terminal",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
config_error("Either use a different method to enter passwords or start the IRCd in a terminal/SSH/..");
}
} else
- if (!strcmp(cep->ce_varname, "password-url"))
+ if (!strcmp(cep->name, "password-url"))
{
config_error("%s:%d: secret::password-url is not supported yet in this UnrealIRCd version.",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
} else
{
- config_error_unknown(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- "secret", cep->ce_varname);
+ config_error_unknown(cep->file->filename, cep->line_number,
+ "secret", cep->name);
errors++;
continue;
}
- if (cep->ce_entries)
+ if (cep->items)
{
config_error("%s:%d: secret::%s does not support sub-options (%s)",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- cep->ce_varname, cep->ce_entries->ce_varname);
+ cep->file->filename, cep->line_number,
+ cep->name, cep->items->name);
errors++;
}
}
@@ -10629,7 +10352,7 @@ int _test_secret(ConfigFile *conf, ConfigEntry *ce)
if (!has_password && !has_password_file && !has_password_prompt)
{
config_error("%s:%d: secret { } block must contain 1 of: password OR password-file OR password-prompt",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
}
@@ -10645,21 +10368,21 @@ int _conf_secret(ConfigFile *conf, ConfigEntry *ce)
{
ConfigEntry *cep;
Secret *s;
- Secret *existing = find_secret(ce->ce_vardata);
+ Secret *existing = find_secret(ce->value);
s = safe_alloc(sizeof(Secret));
- safe_strdup(s->name, ce->ce_vardata);
+ safe_strdup(s->name, ce->value);
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "password"))
+ if (!strcmp(cep->name, "password"))
{
- safe_strdup_sensitive(s->password, cep->ce_vardata);
- destroy_string(cep->ce_vardata); /* destroy the original */
+ safe_strdup_sensitive(s->password, cep->value);
+ destroy_string(cep->value); /* destroy the original */
} else
- if (!strcmp(cep->ce_varname, "password-file"))
+ if (!strcmp(cep->name, "password-file"))
{
- if (!file_exists(cep->ce_vardata) && existing && existing->password)
+ if (!file_exists(cep->value) && existing && existing->password)
{
/* Silently ignore the case where a secret block already
* has the password read and now the file is no longer available.
@@ -10668,14 +10391,14 @@ int _conf_secret(ConfigFile *conf, ConfigEntry *ce)
*/
} else
{
- s->password = _conf_secret_read_password_file(cep->ce_vardata);
+ s->password = _conf_secret_read_password_file(cep->value);
}
} else
- if (!strcmp(cep->ce_varname, "password-prompt"))
+ if (!strcmp(cep->name, "password-prompt"))
{
- if (!loop.ircd_booted && running_interactively())
+ if (!loop.booted && running_interactively())
{
- s->password = _conf_secret_read_prompt(ce->ce_vardata);
+ s->password = _conf_secret_read_prompt(ce->value);
if (!s->password || !valid_secret_password(s->password, NULL))
{
config_error("Invalid password entered on console (does not meet complexity requirements)");
@@ -10713,150 +10436,128 @@ int _conf_secret(ConfigFile *conf, ConfigEntry *ce)
return 1;
}
-#ifdef USE_LIBCURL
-static void conf_download_complete(const char *url, const char *file, const char *errorbuf, int cached, void *inc_key)
+void resource_download_complete(const char *url, const char *file, const char *errorbuf, int cached, void *rs_key)
{
- ConfigItem_include *inc;
+ ConfigResource *rs = (ConfigResource *)rs_key;
- if (!loop.ircd_rehashing)
- return;
+ rs->type &= ~RESOURCE_DLQUEUED;
- /*
- use inc_key to find the correct include block. This
- should be cheaper than using the full URL.
- */
- for (inc = conf_include; inc; inc = inc->next)
- {
- if ( inc_key != (void *)inc )
- continue;
- if (!(inc->flag.type & INCLUDE_REMOTE))
- continue;
- if (inc->flag.type & INCLUDE_NOTLOADED)
- continue;
- if (strcasecmp(url, inc->url))
- continue;
-
- inc->flag.type &= ~INCLUDE_DLQUEUED;
- break;
- }
- if (!inc)
- {
- ircd_log(LOG_ERROR, "Downloaded remote include which matches no include statement.");
- return;
- }
+ if (config_verbose)
+ config_status("resource_download_complete() for %s [%s]", url, errorbuf?errorbuf:"success");
if (!file && !cached)
- update_remote_include(inc, file, 0, errorbuf); /* DOWNLOAD FAILED */
+ {
+ /* DOWNLOAD FAILED */
+ if (rs->cache_file)
+ {
+ unreal_log(ULOG_ERROR, "config", "DOWNLOAD_FAILED_SOFT", NULL,
+ "$file:$line_number: Failed to download '$url': $error_message\n"
+ "Using a cached copy instead.",
+ log_data_string("file", rs->wce->ce->file->filename),
+ log_data_integer("line_number", rs->wce->ce->line_number),
+ log_data_string("url", displayurl(url)),
+ log_data_string("error_message", errorbuf));
+ safe_strdup(rs->file, rs->cache_file);
+ } else {
+ unreal_log(ULOG_ERROR, "config", "DOWNLOAD_FAILED_HARD", NULL,
+ "$file:$line_number: Failed to download '$url': $error_message",
+ log_data_string("file", rs->wce->ce->file->filename),
+ log_data_integer("line_number", rs->wce->ce->line_number),
+ log_data_string("url", displayurl(url)),
+ log_data_string("error_message", errorbuf));
+ /* Set error condition, this so config_read_file() later will stop. */
+ loop.config_load_failed = 1;
+ /* We keep the other transfers running since they may raise (more) errors.
+ * Which can be helpful so you can differentiate between an error of an
+ * include on one server, or complete lack of internet connectvitity.
+ */
+ }
+ }
else
{
- char *urlfile = url_getfilename(url);
- char *file_basename = unreal_getfilename(urlfile);
- char *tmp = unreal_mktemp(TMPDIR, file_basename ? file_basename : "download.conf");
- safe_free(urlfile);
-
if (cached)
{
- unreal_copyfileex(inc->file, tmp, 1);
- unreal_copyfileex(inc->file, unreal_mkcache(url), 0);
- update_remote_include(inc, tmp, 0, NULL);
+ /* Copy from cache */
+ safe_strdup(rs->file, rs->cache_file);
+ } else {
+ /* Copy to cache */
+ const char *cache_file = unreal_mkcache(url);
+ unreal_copyfileex(file, cache_file, 1);
+ safe_strdup(rs->file, cache_file);
}
- else
+ }
+
+ if (rs->file)
+ {
+ if (rs->type & RESOURCE_INCLUDE)
{
- /*
- copy/hardlink file to another file because our caller will
- remove(file).
- */
- unreal_copyfileex(file, tmp, 1);
- update_remote_include(inc, tmp, 0, NULL);
- unreal_copyfileex(file, unreal_mkcache(url), 0);
+ if (config_read_file(rs->file, (char *)displayurl(rs->url)) < 0)
+ loop.config_load_failed = 1;
+ } else {
+ ConfigEntryWrapper *wce;
+ for (wce = rs->wce; wce; wce = wce->next)
+ safe_strdup(wce->ce->value, rs->file); // now information of url is lost, hm!!
}
}
- for (inc = conf_include; inc; inc = inc->next)
- {
- if (inc->flag.type & INCLUDE_DLQUEUED)
- return;
- }
- rehash_internal(loop.rehash_save_client, loop.rehash_save_sig);
-}
-#endif
-int rehash(Client *client, int sig)
+ /* 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.
+ * There is no guarantee that the request will be done immediately
+ * (eg: it won't in case of remote includes).
+ * @param client The client requesting the /REHASH.
+ * If this is NULL then the rehash was requested
+ * via a signal to the process or GUI.
+ */
+void request_rehash(Client *client)
{
-#ifdef USE_LIBCURL
- ConfigItem_include *inc;
- char found_remote = 0;
- if (loop.ircd_rehashing)
+ if (loop.rehashing)
{
- if (!sig)
+ if (client)
sendnotice(client, "A rehash is already in progress");
- return 0;
+ return;
}
- /* Log who or what did the rehash: */
- if (sig)
- {
- ircd_log(LOG_ERROR, "Rehashing configuration file (SIGHUP signal received)");
- } else
- if (client && client->user)
- {
- ircd_log(LOG_ERROR, "Rehashing configuration file (requested by %s!%s@%s)",
- client->name, client->user->username, client->user->realhost);
- } else
- if (client)
- {
- ircd_log(LOG_ERROR, "Rehashing configuration file (requested by %s)",
- client->name);
- }
-
- loop.ircd_rehashing = 1;
+ loop.rehashing = 1;
loop.rehash_save_client = client;
- loop.rehash_save_sig = sig;
- for (inc = conf_include; inc; inc = inc->next)
+ config_read_start();
+ /* If we already have everything, then can we proceed with the rehash */
+ if (is_config_read_finished())
{
- time_t modtime;
- if (!(inc->flag.type & INCLUDE_REMOTE))
- continue;
-
- if (inc->flag.type & INCLUDE_NOTLOADED)
- continue;
- found_remote = 1;
- modtime = unreal_getfilemodtime(inc->file);
- inc->flag.type |= INCLUDE_DLQUEUED;
-
- /*
- use (void *)inc as the key for finding which
- include block conf_download_complete() should use.
- */
- download_file_async(inc->url, modtime, conf_download_complete, (void *)inc);
+ rehash_internal(client);
+ return;
}
- if (!found_remote)
- return rehash_internal(client, sig);
- return 0;
-#else
- loop.ircd_rehashing = 1;
- return rehash_internal(client, sig);
-#endif
+ /* Otherwise, I/O events will take care of it later
+ * after all remote includes have been downloaded.
+ */
}
-int rehash_internal(Client *client, int sig)
+int rehash_internal(Client *client)
{
- if (sig == 1)
- sendto_ops("Got signal SIGHUP, reloading %s file", configfile);
- loop.ircd_rehashing = 1; /* double checking.. */
- if (init_conf(configfile, 1) == 0)
- run_configuration();
- if (sig == 1)
- reread_motdsandrules();
- unload_all_unused_snomasks();
+ /* 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.. */
+
+ if (config_test() == 0)
+ config_run();
+ /* TODO: uh.. are we supposed to do all this for a failed rehash too? maybe some but not all? */
+ reread_motdsandrules();
unload_all_unused_umodes();
unload_all_unused_extcmodes();
unload_all_unused_caps();
unload_all_unused_history_backends();
// unload_all_unused_moddata(); -- this will crash
- extcmodes_check_for_changes();
umodes_check_for_changes();
charsys_check_for_changes();
- loop.ircd_rehashing = 0;
+ loop.rehashing = 0;
remote_rehash_client = NULL;
return 1;
}
@@ -10884,8 +10585,6 @@ void link_cleanup(ConfigItem_link *link_ptr)
void delete_linkblock(ConfigItem_link *link_ptr)
{
- Debug((DEBUG_ERROR, "delete_linkblock: deleting %s, refcount=%d",
- link_ptr->servername, link_ptr->refcount));
if (link_ptr->class)
{
link_ptr->class->xrefcount--;
@@ -10904,8 +10603,6 @@ void delete_linkblock(ConfigItem_link *link_ptr)
void delete_classblock(ConfigItem_class *class_ptr)
{
- Debug((DEBUG_ERROR, "delete_classblock: deleting %s, clients=%d, xrefcount=%d",
- class_ptr->name, class_ptr->clients, class_ptr->xrefcount));
safe_free(class_ptr->name);
DelListItem(class_ptr, conf_class);
safe_free(class_ptr);
@@ -10924,6 +10621,7 @@ void listen_cleanup()
safe_free(listen_ptr->ip);
free_tls_options(listen_ptr->tls_options);
DelListItem(listen_ptr, conf_listen);
+ safe_free(listen_ptr->websocket_forward);
safe_free(listen_ptr);
i++;
}
@@ -10933,279 +10631,153 @@ void listen_cleanup()
close_unbound_listeners();
}
-#ifdef USE_LIBCURL
-char *find_remote_include(char *url, char **errorbuf)
+ConfigResource *find_config_resource(const char *resource)
{
- ConfigItem_include *inc;
+ ConfigResource *rs;
- for (inc = conf_include; inc; inc = inc->next)
+ for (rs = config_resources; rs; rs = rs->next)
{
- if (!(inc->flag.type & INCLUDE_NOTLOADED))
- continue;
- if (!(inc->flag.type & INCLUDE_REMOTE))
- continue;
- if (!strcasecmp(url, inc->url))
- {
- *errorbuf = inc->errorbuf;
- return inc->file;
- }
+#ifdef _WIN32
+ if (rs->file && !strcasecmp(resource, rs->file))
+ return rs;
+#else
+ if (rs->file && !strcmp(resource, rs->file))
+ return rs;
+#endif
+ if (rs->url && !strcasecmp(resource, rs->url))
+ return rs;
}
return NULL;
}
-char *find_loaded_remote_include(char *url)
+/* Add configuration resource to list.
+ * For files this doesn't do terribly much, except that you can use
+ * the return value to judge on whether you should call config_read_file() or not.
+ * For urls this adds the resource to the list of links to be downloaded.
+ * @param resource File or URL of the resource
+ * @param type A RESOURCE_ type such as RESOURCE_INCLUDE
+ * @param ce The ConfigEntry where the add_config_resource() happened
+ * for, such as the include block, etc.
+ * @returns 0 if the file is already on our list (so no need to load it!)
+ */
+int add_config_resource(const char *resource, int type, ConfigEntry *ce)
{
- ConfigItem_include *inc;
+ ConfigResource *rs;
+ ConfigEntryWrapper *wce;
- for (inc = conf_include; inc; inc = inc->next)
+ if (config_verbose)
+ config_status("add_config_resource() for '%s", resource);
+
+ wce = safe_alloc(sizeof(ConfigEntryWrapper));
+ wce->ce = ce;
+
+ rs = find_config_resource(resource);
+ if (rs)
{
- if ((inc->flag.type & INCLUDE_NOTLOADED))
- continue;
- if (!(inc->flag.type & INCLUDE_REMOTE))
- continue;
- if (!strcasecmp(url, inc->url))
- return inc->file;
+ /* Existing entry, add us to the list of
+ * items who are interested in this resource ;)
+ */
+ AddListItem(wce, rs->wce);
+ return 0;
}
- return NULL;
-}
+ /* New entry */
+ rs = safe_alloc(sizeof(ConfigResource));
+ rs->wce = wce;
+ AddListItem(rs, config_resources);
-/**
- * Non-asynchronous remote inclusion to give a user better feedback
- * when first starting his IRCd.
- *
- * The asynchronous friend is rehash() which merely queues remote
- * includes for download using download_file_async().
- */
-int remote_include(ConfigEntry *ce)
-{
- char *errorbuf = NULL;
- char *url = ce->ce_vardata;
- char *file = find_remote_include(url, &errorbuf);
- int ret;
- if (!loop.ircd_rehashing || (loop.ircd_rehashing && !file && !errorbuf))
+ if (!url_is_valid(resource))
{
- char *error;
- if (config_verbose > 0)
- config_status("Downloading %s", displayurl(url));
- file = download_file(url, &error);
- if (!file)
+ safe_strdup(rs->file, resource);
+ } else {
+ const char *cache_file;
+ time_t modtime;
+
+ safe_strdup(rs->url, resource);
+ rs->type = type|RESOURCE_REMOTE|RESOURCE_DLQUEUED;
+
+ cache_file = unreal_mkcache(rs->url);
+ modtime = unreal_getfilemodtime(cache_file);
+ if (modtime > 0)
{
- if (has_cached_version(url))
+ safe_strdup(rs->cache_file, cache_file); /* Cached copy is available */
+ /* Check if there is an "url-refresh" argument */
+ ConfigEntry *cep, *prev = NULL;
+ for (cep = ce->items; cep; cep = cep->next)
{
- config_warn("%s:%i: include: error downloading '%s': %s -- using cached version instead.",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- displayurl(url), error);
- safe_strdup(file, unreal_mkcache(url));
- /* Let it pass to load_conf()... */
- } else {
- config_error("%s:%i: include: error downloading '%s': %s",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- displayurl(url), error);
- return -1;
- }
- } else {
- unreal_copyfileex(file, unreal_mkcache(url), 0);
- }
- add_remote_include(file, url, 0, NULL, ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
- ret = load_conf(file, url);
- safe_free(file);
- return ret;
- }
- else
- {
- if (errorbuf)
- {
- if (has_cached_version(url))
- {
- config_warn("%s:%i: include: error downloading '%s': %s -- using cached version instead.",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- displayurl(url), errorbuf);
- /* Let it pass to load_conf()... */
- safe_strdup(file, unreal_mkcache(url));
- } else {
- config_error("%s:%i: include: error downloading '%s': %s",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- displayurl(url), errorbuf);
- return -1;
- }
- }
- if (config_verbose > 0)
- config_status("Loading %s from download", url);
- add_remote_include(file, url, 0, NULL, ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
- ret = load_conf(file, url);
- return ret;
- }
- return 0;
-}
-#endif
-
-/**
- * Add an item to the conf_include list for the specified file.
- *
- * Checks for whether or not we're performing recursive includes
- * belong in conf_load() because that function is able to return an
- * error code. Any checks in here will end up being ignored by callers
- * and thus will gain us nothing.
- *
- * @param file path to the include file.
- */
-void add_include(const char *file, const char *included_from, int included_from_line)
-{
- ConfigItem_include *inc;
-
- inc = safe_alloc(sizeof(ConfigItem_include));
- safe_strdup(inc->file, file);
- inc->flag.type = INCLUDE_NOTLOADED;
- safe_strdup(inc->included_from, included_from);
- inc->included_from_line = included_from_line;
- AddListItem(inc, conf_include);
-}
-
-#ifdef USE_LIBCURL
-/**
- * Adds a remote include entry to the config_include list.
- *
- * This is to be called whenever the included_from and
- * included_from_line parameters are known. This means that during a
- * rehash when downloads are done asynchronously, you call this with
- * the inclued_from and included_from_line information. After the
- * download is complete and you know there it is stored in the FS,
- * call update_remote_include().
- */
-void add_remote_include(const char *file, const char *url, int flags, const char *errorbuf, const char *included_from, int included_from_line)
-{
- ConfigItem_include *inc;
-
- /* we rely on safe_alloc() zeroing the ConfigItem_include */
- inc = safe_alloc(sizeof(ConfigItem_include));
- if (included_from)
- {
- safe_strdup(inc->included_from, included_from);
- inc->included_from_line = included_from_line;
- }
- safe_strdup(inc->url, url);
-
- update_remote_include(inc, file, INCLUDE_NOTLOADED|INCLUDE_REMOTE|flags, errorbuf);
- AddListItem(inc, conf_include);
-}
-
-/**
- * Update certain information in a remote include's config_include list entry.
- *
- * @param file the place on disk where the downloaded remote include
- * may be found
- * @param flags additional flags to set on the config_include entry
- * @param errorbuf non-NULL if there were errors encountered in
- * downloading. The error will be stored into the config_include
- * entry.
- */
-void update_remote_include(ConfigItem_include *inc, const char *file, int flags, const char *errorbuf)
-{
- /*
- * file may be NULL when errorbuf is non-NULL and vice-versa.
- */
- if (file)
- safe_strdup(inc->file, file);
- inc->flag.type |= flags;
-
- if (errorbuf)
- safe_strdup(inc->errorbuf, errorbuf);
-}
-#endif
-
-/**
- * Clean up conf_include after a rehash fails because of a
- * configuration file error.
- *
- * Duplicates some in unload_loaded_include().
- */
-void unload_notloaded_includes(void)
-{
- ConfigItem_include *inc, *next;
-
- for (inc = conf_include; inc; inc = next)
- {
- next = inc->next;
- if ((inc->flag.type & INCLUDE_NOTLOADED) || !(inc->flag.type & INCLUDE_USED))
- {
-#ifdef USE_LIBCURL
- if (inc->flag.type & INCLUDE_REMOTE)
- {
- /* Delete the file, but only if it's not a cached version */
- if (strncmp(inc->file, CACHEDIR, strlen(CACHEDIR)))
+ if (!strcmp(cep->name, "url-refresh"))
{
- remove(inc->file);
+ /* First find out the time value of url-refresh... (eg '7d' -> 86400*7) */
+ long refresh_time = 0;
+ if (cep->value)
+ refresh_time = config_checkval(cep->value, CFG_TIME);
+ /* Then remove the config item so it is not seen by the rest of unrealircd.
+ * Can't use DelListItem() here as ConfigEntry has no ->prev, only ->next.
+ */
+ if (prev)
+ prev->next = cep->next; /* (skip over us) */
+ else
+ ce->items = cep->next; /* (new head) */
+ /* ..and free it */
+ config_entry_free(cep);
+ /* And now check if the current cached copy is recent enough */
+ if (TStime() - modtime < refresh_time)
+ {
+ /* Don't download, use cached copy */
+ //config_status("DEBUG: using cached copy due to url-refresh %ld", refresh_time);
+ resource_download_complete(rs->url, NULL, NULL, 1, rs);
+ return 1;
+ } else {
+ //config_status("DEBUG: requires download attempt, out of date url-refresh %ld < %ld", refresh_time, TStime() - modtime);
+ }
+ break; // MUST break now as we touched the linked list.
}
- safe_free(inc->url);
- safe_free(inc->errorbuf);
+ prev = cep;
}
-#endif
- safe_free(inc->file);
- safe_free(inc->included_from);
- DelListItem(inc, conf_include);
- safe_free(inc);
}
+ download_file_async(rs->url, modtime, resource_download_complete, (void *)rs, NULL, DOWNLOAD_MAX_REDIRECTS);
}
+ return 1;
}
-/**
- * Clean up conf_include after a successful rehash to make way for
- * load_includes().
- */
-void unload_loaded_includes(void)
+void free_all_config_resources(void)
{
- ConfigItem_include *inc, *next;
+ ConfigResource *rs, *next;
+ ConfigEntryWrapper *wce, *wce_next;
- for (inc = conf_include; inc; inc = next)
+ for (rs = config_resources; rs; rs = next)
{
- next = inc->next;
- if (!(inc->flag.type & INCLUDE_NOTLOADED) || !(inc->flag.type & INCLUDE_USED))
+ next = rs->next;
+ for (wce = rs->wce; wce; wce = wce_next)
{
-#ifdef USE_LIBCURL
- if (inc->flag.type & INCLUDE_REMOTE)
- {
- /* Delete the file, but only if it's not a cached version */
- if (strncmp(inc->file, CACHEDIR, strlen(CACHEDIR)))
- {
- remove(inc->file);
- }
- safe_free(inc->url);
- safe_free(inc->errorbuf);
- }
-#endif
- safe_free(inc->file);
- safe_free(inc->included_from);
- DelListItem(inc, conf_include);
- safe_free(inc);
+ wce_next = wce->next;
+ safe_free(wce);
}
+ rs->wce = NULL;
+ if (rs->type & RESOURCE_REMOTE)
+ {
+ /* Delete the file, but only if it's not a cached version */
+ if (rs->file && strncmp(rs->file, CACHEDIR, strlen(CACHEDIR)))
+ {
+ remove(rs->file);
+ }
+ safe_free(rs->url);
+ }
+ safe_free(rs->file);
+ safe_free(rs->cache_file);
+ DelListItem(rs, config_resources);
+ safe_free(rs);
}
}
-/**
- * Mark loaded includes as loaded by removing the INCLUDE_NOTLOADED
- * flag. Meant to be called only after calling
- * unload_loaded_includes().
- */
-void load_includes(void)
-{
- ConfigItem_include *inc;
-
- /* Doing this for all the includes should actually be faster
- * than only doing it for includes that are not-loaded
- */
- for (inc = conf_include; inc; inc = inc->next)
- inc->flag.type &= ~INCLUDE_NOTLOADED;
-}
-
int tls_tests(void)
{
if (have_tls_listeners == 0)
{
- config_error("Your server is not listening on any SSL/TLS ports.");
+ config_error("Your server is not listening on any TLS ports.");
config_status("Add this to your unrealircd.conf: listen { ip %s; port 6697; options { tls; }; };",
port_6667_ip ? port_6667_ip : "*");
- config_status("See https://www.unrealircd.org/docs/FAQ#Your_server_is_not_listening_on_any_SSL_ports");
+ config_status("See https://www.unrealircd.org/docs/FAQ#no-tls-ports");
return 0;
}
@@ -11245,7 +10817,7 @@ int reloadable_perm_module_unloaded(void)
return ret;
}
-char *link_generator_spkifp(TLSOptions *tlsoptions)
+const char *link_generator_spkifp(TLSOptions *tlsoptions)
{
SSL_CTX *ctx;
SSL *ssl;
@@ -11267,7 +10839,7 @@ void link_generator(void)
TLSOptions *tlsopt = iConf.tls_options; /* never null */
int port = 0;
char *ip = NULL;
- char *spkifp;
+ const char *spkifp;
for (lstn = conf_listen; lstn; lstn = lstn->next)
{
@@ -11286,7 +10858,7 @@ void link_generator(void)
if (!port)
{
- printf("You don't have any listen { } blocks that are serversonly.\n");
+ printf("You don't have any listen { } blocks that are serversonly (and have tls enabled).\n");
printf("It is recommended to have at least one. Add this to your configuration file:\n");
printf("listen { ip *; port 6900; options { tls; serversonly; }; };\n");
exit(1);
@@ -11295,7 +10867,7 @@ void link_generator(void)
spkifp = link_generator_spkifp(tlsopt);
if (!spkifp)
{
- printf("Could not calculate spkifp. Maybe you have uncommon SSL/TLS options set? Odd...\n");
+ printf("Could not calculate spkifp. Maybe you have uncommon TLS options set? Odd...\n");
exit(1);
}
diff --git a/src/conf_preprocessor.c b/src/conf_preprocessor.c
index 6551fcb..9be3338 100644
--- a/src/conf_preprocessor.c
+++ b/src/conf_preprocessor.c
@@ -19,7 +19,7 @@ static inline int ValidVarCharacter(char x)
return 0;
}
-PreprocessorItem evaluate_preprocessor_if(char *statement, char *filename, int linenumber, ConditionalConfig **cc_out)
+PreprocessorItem evaluate_preprocessor_if(char *statement, const char *filename, int linenumber, ConditionalConfig **cc_out)
{
char *p=statement, *name;
int negative = 0;
@@ -176,7 +176,7 @@ PreprocessorItem evaluate_preprocessor_if(char *statement, char *filename, int l
return PREPROCESSOR_ERROR;
}
-PreprocessorItem evaluate_preprocessor_define(char *statement, char *filename, int linenumber)
+PreprocessorItem evaluate_preprocessor_define(char *statement, const char *filename, int linenumber)
{
char *p = statement;
char *name, *name_terminator;
@@ -246,7 +246,7 @@ PreprocessorItem evaluate_preprocessor_define(char *statement, char *filename,
return PREPROCESSOR_DEFINE;
}
-PreprocessorItem parse_preprocessor_item(char *start, char *end, char *filename, int linenumber, ConditionalConfig **cc)
+PreprocessorItem parse_preprocessor_item(char *start, char *end, const char *filename, int linenumber, ConditionalConfig **cc)
{
char buf[512];
int max;
@@ -262,7 +262,7 @@ PreprocessorItem parse_preprocessor_item(char *start, char *end, char *filename
return evaluate_preprocessor_define(buf+7, filename, linenumber);
else if (!strncmp(buf, "@if ", 4))
return evaluate_preprocessor_if(buf+4, filename, linenumber, cc);
- else if (!strcmp(buf, "@endif"))
+ else if (!strncmp(buf, "@endif", 6))
return PREPROCESSOR_ENDIF;
config_error("%s:%i: Unknown preprocessor directive: %s", filename, linenumber, buf);
@@ -382,29 +382,29 @@ int preprocessor_resolve_if(ConditionalConfig *cc, PreprocessorPhase phase)
void preprocessor_resolve_conditionals_ce(ConfigEntry **ce_list, PreprocessorPhase phase)
{
- ConfigEntry *ce, *ce_next, *ce_prev;
+ ConfigEntry *ce, *next, *ce_prev;
ConfigEntry *cep, *cep_next, *cep_prev;
ce_prev = NULL;
- for (ce = *ce_list; ce; ce = ce_next)
+ for (ce = *ce_list; ce; ce = next)
{
- ce_next = ce->ce_next;
+ next = ce->next;
/* This is for an @if before a block start */
- if (!preprocessor_resolve_if(ce->ce_cond, phase))
+ if (!preprocessor_resolve_if(ce->conditional_config, phase))
{
/* Delete this entry */
if (ce == *ce_list)
{
/* we are head, so new head */
- *ce_list = ce->ce_next; /* can be NULL now */
+ *ce_list = ce->next; /* can be NULL now */
} else {
/* non-head */
- ce_prev->ce_next = ce->ce_next; /* can be NULL now */
+ ce_prev->next = ce->next; /* can be NULL now */
}
config_entry_free(ce);
continue;
}
- preprocessor_resolve_conditionals_ce(&ce->ce_entries, phase);
+ preprocessor_resolve_conditionals_ce(&ce->items, phase);
ce_prev = ce;
}
}
@@ -413,8 +413,8 @@ void preprocessor_resolve_conditionals_all(PreprocessorPhase phase)
{
ConfigFile *cfptr;
- for (cfptr = conf; cfptr; cfptr = cfptr->cf_next)
- preprocessor_resolve_conditionals_ce(&cfptr->cf_entries, phase);
+ for (cfptr = conf; cfptr; cfptr = cfptr->next)
+ preprocessor_resolve_conditionals_ce(&cfptr->items, phase);
}
/** Frees the list of config_defines, so all @defines */
@@ -502,7 +502,7 @@ void preprocessor_replace_defines(char **item, ConfigEntry *ce)
if ((limit > 2) && ((*varend == '\0') || strchr("\t ,.", *varend)))
{
config_warn("%s:%d: Variable %s used here but there's no @define for it earlier.",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum, varname);
+ ce->file->filename, ce->line_number, varname);
}
#endif
value = varname; /* not found? then use varname, including the '$' */
diff --git a/src/crashreport.c b/src/crashreport.c
index bd7e83c..270c363 100644
--- a/src/crashreport.c
+++ b/src/crashreport.c
@@ -109,7 +109,7 @@ char *find_best_asan_log(void)
}
}
closedir(fd);
- return BadPtr(best_fname) ? NULL : best_fname;
+ return *best_fname ? best_fname : NULL;
#else
return NULL;
#endif
@@ -531,7 +531,7 @@ char *generate_crash_report(char *coredump, int *thirdpartymods)
#define CRASH_REPORT_HOST "crash.unrealircd.org"
-SSL_CTX *crashreport_init_ssl(void)
+SSL_CTX *crashreport_init_tls(void)
{
SSL_CTX *ctx_client;
char buf[512];
@@ -587,7 +587,7 @@ int crashreport_send(char *fname)
delimiter);
snprintf(footer, sizeof(footer), "\r\n--%s--\r\n", delimiter);
- ctx_client = crashreport_init_ssl();
+ ctx_client = crashreport_init_tls();
if (!ctx_client)
{
printf("ERROR: TLS initalization failure (I)\n");
diff --git a/src/crule.c b/src/crule.c
index faa9e6a..4baf20e 100644
--- a/src/crule.c
+++ b/src/crule.c
@@ -186,7 +186,7 @@ int crule_via(int numargs, void *crulearg[])
{
if (!match_simple((char *)crulearg[1], client->name))
continue;
- if (!match_simple((char *)crulearg[0], client->serv->up))
+ if (!match_simple((char *)crulearg[0], client->uplink->name))
continue;
return (1);
}
@@ -372,11 +372,6 @@ char *crule_parse(char *rule)
}
if (ruleroot != NULL)
crule_free((char **)&ruleroot);
-#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
- Debug((DEBUG_ERROR, "%s in rule: %s", crule_errstr[errcode], rule));
-#else
- (void)fprintf(stderr, "%s in rule: %s\n", crule_errstr[errcode], rule);
-#endif
return NULL;
}
diff --git a/src/dbuf.c b/src/dbuf.c
index 62cb40f..23786d5 100644
--- a/src/dbuf.c
+++ b/src/dbuf.c
@@ -61,7 +61,7 @@ void dbuf_queue_init(dbuf *dyn)
INIT_LIST_HEAD(&dyn->dbuf_list);
}
-void dbuf_put(dbuf *dyn, char *buf, size_t length)
+void dbuf_put(dbuf *dyn, const char *buf, size_t length)
{
struct dbufbuf *block;
size_t amount;
diff --git a/src/debug.c b/src/debug.c
index e28f898..e4d7635 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -48,9 +48,6 @@ MODVAR char serveropts[] = {
'Y',
#endif
'6',
-#ifdef USE_SSL
- 'e',
-#endif
#ifndef NO_OPEROVERRIDE
'O',
#endif
@@ -150,11 +147,16 @@ void debug(int level, FORMAT_STRING(const char *form), ...)
SET_ERRNO(err);
}
-int checkprotoflags(Client *client, int flags, char *file, int line)
+int checkprotoflags(Client *client, int flags, const char *file, int line)
{
if (!MyConnect(client))
- ircd_log(LOG_ERROR, "[Debug] [BUG] ERROR: %s:%d: IsToken(<%s>,%d) on remote client",
- file, line, client->name, flags);
+ {
+ unreal_log(ULOG_ERROR, "main", "BUG_ISTOKEN_REMOTE_CLIENT", client,
+ "IsToken($token_value) used on remote client in $file:$line",
+ log_data_integer("token_value", flags),
+ log_data_string("file", file),
+ log_data_integer("line", line));
+ }
return ((client->local->proto & flags) == flags) ? 1 : 0;
}
#endif
diff --git a/src/dispatch.c b/src/dispatch.c
index 37540f3..096243c 100644
--- a/src/dispatch.c
+++ b/src/dispatch.c
@@ -39,6 +39,11 @@
#include
#endif
+/* Not sure if this is suitable for production,
+ * but let's turn it on for U6 development.
+ */
+//#define DETECT_HIGH_CPU
+
/***************************************************************************************
* Backend-independent functions. fd_setselect() and friends *
***************************************************************************************/
@@ -47,14 +52,18 @@ void fd_setselect(int fd, int flags, IOCallbackFunc iocb, void *data)
FDEntry *fde;
int changed = 0;
#if 0
- ircd_log(LOG_ERROR, "fd_setselect(): fd %d flags %d func %p", fd, flags, &iocb);
+ unreal_log(ULOG_DEBUG, "io", "IO_DEBUG_FD_SETSELECT", NULL,
+ "fd_setselect(): fd $fd flags $fd_flags function $function_pointer",
+ log_data_integer("fd", fd),
+ log_data_integer("fd_flags", flags),
+ log_data_integer("function_pointer", (long long)iocb));
#endif
if ((fd < 0) || (fd >= MAXCONNECTIONS))
{
- sendto_realops("[BUG] trying to modify fd #%d in fd table, but MAXCONNECTIONS is %d",
- fd, MAXCONNECTIONS);
- ircd_log(LOG_ERROR, "[BUG] trying to modify fd #%d in fd table, but MAXCONNECTIONS is %d",
- fd, MAXCONNECTIONS);
+ unreal_log(ULOG_ERROR, "io", "BUG_FD_SETSELECT_OUT_OF_RANGE", NULL,
+ "[BUG] trying to modify fd $fd in fd table, but MAXCONNECTIONS is $maxconnections",
+ log_data_integer("fd", fd),
+ log_data_integer("maxconnections", MAXCONNECTIONS));
#ifdef DEBUGMODE
abort();
#endif
@@ -143,7 +152,11 @@ void fd_debug(fd_set *f, int highest, char *name)
//if (fcntl(i, F_GETFL) < 0)
int nonb = 1;
if (ioctlsocket(i, FIONBIO, &nonb) < 0)
- ircd_log(LOG_ERROR, "fd_debug: FD #%d is invalid!!!", i);
+ {
+ unreal_log(ULOG_ERROR, "io", "FD_DEBUG", NULL,
+ "[BUG] fd_debug: fd $fd is invalid!!!",
+ log_data_integer("fd", i));
+ }
}
}
}
@@ -168,10 +181,6 @@ void fd_select(time_t delay)
to.tv_sec = delay / 1000;
to.tv_usec = (delay % 1000) * 1000;
-#ifdef DEBUGMODE
- ircd_log(LOG_ERROR, "fd_select() on 0-%d...", highest_fd+1);
-#endif
-
#ifdef _WIN32
num = select(highest_fd + 1, &work_read_fds, &work_write_fds, &work_except_fds, &to);
#else
@@ -179,8 +188,9 @@ void fd_select(time_t delay)
#endif
if (num < 0)
{
- extern void report_baderror(char *text, Client *client);
- report_baderror("select %s:%s", &me);
+ unreal_log(ULOG_FATAL, "io", "SELECT_ERROR", NULL,
+ "select() returned error ($socket_error) -- SERIOUS TROUBLE!",
+ log_data_socket_error(-1));
/* DEBUG the actual problem: */
memcpy(&work_read_fds, &read_fds, sizeof(fd_set));
memcpy(&work_write_fds, &write_fds, sizeof(fd_set));
@@ -204,10 +214,6 @@ void fd_select(time_t delay)
if (!fde->is_open)
continue;
-#ifdef DEBUGMODE
- ircd_log(LOG_ERROR, "fd_select(): checking %d...", fd);
-#endif
-
if (FD_ISSET(fd, &work_read_fds))
evflags |= FD_SELECT_READ;
@@ -223,10 +229,6 @@ void fd_select(time_t delay)
if (!evflags)
continue;
-#ifdef DEBUGMODE
- ircd_log(LOG_ERROR, "fd_select(): events for %d (%d)... processing...", fd, evflags);
-#endif
-
if (evflags & FD_SELECT_READ)
{
iocb = fde->read_callback;
@@ -280,7 +282,9 @@ void fd_fork()
continue;
#ifdef DEBUGMODE
- ircd_log(LOG_ERROR, "[BUG?] kevent returned %d", errno);
+ unreal_log(ULOG_ERROR, "io", "KEVENT_FAILED", NULL,
+ "[io] fd_fork(): kevent returned error: $system_error",
+ log_data_string("system_error", strerror(errno)));
#endif
}
}
@@ -308,8 +312,13 @@ void fd_refresh(int fd)
#ifdef DEBUGMODE
if (ERRNO != P_EWOULDBLOCK && ERRNO != P_EAGAIN)
{
- ircd_log(LOG_ERROR, "[BUG?] fd_refresh(): kevent returned %d for fd %d for read callback (%s)",
- errno, fd, (fde->read_callback ? "add" : "delete"));
+ int save_err = errno;
+ unreal_log(ULOG_ERROR, "io", "KEVENT_FAILED_REFRESH", NULL,
+ "fd_refresh(): kevent returned error for fd $fd ($fd_action) ($callback): $system_error",
+ log_data_string("system_error", strerror(save_err)),
+ log_data_integer("fd", fd),
+ log_data_string("fd_action", (fde->read_callback ? "add" : "delete")),
+ log_data_string("callback", "read_callback"));
}
#endif
}
@@ -323,8 +332,13 @@ void fd_refresh(int fd)
#ifdef DEBUGMODE
if (ERRNO != P_EWOULDBLOCK && ERRNO != P_EAGAIN && fde->write_callback)
{
- ircd_log(LOG_ERROR, "[BUG?] fd_refresh(): kevent returned %d for fd %d for write callback (%s)",
- errno, fd, "add" /*(fde->write_callback ? "add" : "delete")*/);
+ int save_err = errno;
+ unreal_log(ULOG_ERROR, "io", "KEVENT_FAILED_REFRESH", NULL,
+ "[io] fd_refresh(): kevent returned error for fd $fd ($fd_action) ($callback): $system_error",
+ log_data_string("system_error", strerror(save_err)),
+ log_data_integer("fd", fd),
+ log_data_string("fd_action", "add"),
+ log_data_string("callback", "write_callback"));
}
#endif
}
@@ -440,11 +454,15 @@ void fd_refresh(int fd)
if (epoll_ctl(epoll_fd, op, fd, &ep_event) != 0)
{
- if (ERRNO == P_EWOULDBLOCK || ERRNO == P_EAGAIN)
+ int save_errno = errno;
+ if ((save_errno == P_EWOULDBLOCK) || (save_errno == P_EAGAIN))
return;
- ircd_log(LOG_ERROR, "[BUG] fd_refresh(): epoll_ctl returned error %d (%s) for fd %d (%s)",
- errno, STRERROR(ERRNO), fd, fde->desc);
+ unreal_log(ULOG_ERROR, "io", "EPOLL_CTL_FAILED", NULL,
+ "[io] fd_refresh(): epoll_ctl returned error for fd $fd ($fd_description): $system_error",
+ log_data_string("system_error", strerror(save_errno)),
+ log_data_integer("fd", fd),
+ log_data_string("fd_description", fde->desc));
return;
}
@@ -455,7 +473,7 @@ void fd_select(time_t delay)
{
int num, p, revents, fd;
struct epoll_event *epfd;
-#ifdef DEBUG_IOENGINE
+#ifdef DETECT_HIGH_CPU
int read_callbacks = 0, write_callbacks = 0;
struct timeval oldt, t;
long long tdiff;
@@ -467,7 +485,7 @@ void fd_select(time_t delay)
if (num <= 0)
return;
-#ifdef DEBUG_IOENGINE
+#ifdef DETECT_HIGH_CPU
gettimeofday(&oldt, NULL);
#endif
@@ -499,7 +517,7 @@ void fd_select(time_t delay)
if (iocb != NULL)
iocb(fd, evflags, fde->data);
-#ifdef DEBUG_IOENGINE
+#ifdef DETECT_HIGH_CPU
read_callbacks++;
#endif
}
@@ -511,7 +529,7 @@ void fd_select(time_t delay)
if (iocb != NULL)
iocb(fd, evflags, fde->data);
-#ifdef DEBUG_IOENGINE
+#ifdef DETECT_HIGH_CPU
write_callbacks++;
#endif
}
@@ -524,14 +542,18 @@ void fd_select(time_t delay)
#endif
}
-#ifdef DEBUG_IOENGINE
+#ifdef DETECT_HIGH_CPU
gettimeofday(&t, NULL);
tdiff = ((t.tv_sec - oldt.tv_sec) * 1000000) + (t.tv_usec - oldt.tv_usec);
if (tdiff > 1000000)
{
- sendto_realops_and_log("WARNING: Slow I/O engine or high load: fd_select() took %lld ms! read_callbacks=%d, write_callbacks=%d",
- tdiff / 1000, read_callbacks, write_callbacks);
+ unreal_log(ULOG_WARNING, "io", "HIGH_LOAD", NULL,
+ "HIGH CPU LOAD! fd_select() took $time_msec msec "
+ "(read: $num_read_callbacks, write: $num_write_callbacks)",
+ log_data_integer("time_msec", tdiff/1000),
+ log_data_integer("num_read_callbacks", read_callbacks),
+ log_data_integer("num_write_callbacks", write_callbacks));
}
#endif
}
@@ -601,7 +623,7 @@ void fd_select(time_t delay)
pfd = &pollfds[p];
revents = pfd->revents;
- fd = pfd->local->fd;
+ fd = pfd->fd;
if (revents == 0 || fd == -1)
continue;
diff --git a/src/dns.c b/src/dns.c
index edaa674..d8cb660 100644
--- a/src/dns.c
+++ b/src/dns.c
@@ -40,9 +40,9 @@ void unrealdns_cb_nametoip_verify(void *arg, int status, int timeouts, struct ho
void unrealdns_cb_nametoip_link(void *arg, int status, int timeouts, struct hostent *he);
void unrealdns_delasyncconnects(void);
static uint64_t unrealdns_hash_ip(const char *ip);
-static void unrealdns_addtocache(char *name, char *ip);
-static char *unrealdns_findcache_ip(char *ip);
-struct hostent *unreal_create_hostent(char *name, char *ip);
+static void unrealdns_addtocache(const char *name, const char *ip);
+static const char *unrealdns_findcache_ip(const char *ip);
+struct hostent *unreal_create_hostent(const char *name, const char *ip);
static void unrealdns_freeandremovereq(DNSReq *r);
void unrealdns_removecacherecord(DNSCache *c);
@@ -87,10 +87,7 @@ static void unrealdns_sock_state_cb(void *data, ares_socket_t fd, int read, int
if (!read && !write)
{
- /* Socket is going to be closed *BY C-ARES*..
- * so don't call fd_close() but fd_unmap().
- */
- fd_unmap(fd);
+ fd_close(fd);
return;
}
@@ -108,7 +105,11 @@ static void unrealdns_sock_state_cb(void *data, ares_socket_t fd, int read, int
*/
static int unrealdns_sock_create_cb(ares_socket_t fd, int type, void *data)
{
- fd_open(fd, "DNS Resolver Socket");
+ /* NOTE: We use FDCLOSE_NONE here because c-ares
+ * will take care of the closing. So *WE* must
+ * never close the socket.
+ */
+ fd_open(fd, "DNS Resolver Socket", FDCLOSE_NONE);
return ARES_SUCCESS;
}
@@ -174,12 +175,10 @@ void reinit_resolver(Client *client)
{
EventDel(unrealdns_timeout_hdl);
- sendto_ops_and_log("%s requested reinitalization of resolver!", client->name);
- sendto_realops("Destroying resolver channel, along with all currently pending queries...");
+ unreal_log(ULOG_INFO, "dns", "REINIT_RESOLVER", client,
+ "$client requested reinitalization of the DNS resolver");
ares_destroy(resolver_channel);
- sendto_realops("Initializing resolver again...");
init_resolver(0);
- sendto_realops("Reinitalization finished successfully.");
}
void unrealdns_addreqtolist(DNSReq *r)
@@ -202,7 +201,7 @@ void unrealdns_addreqtolist(DNSReq *r)
struct hostent *unrealdns_doclient(Client *client)
{
DNSReq *r;
- char *cache_name;
+ const char *cache_name;
cache_name = unrealdns_findcache_ip(client->ip);
if (cache_name)
@@ -233,7 +232,7 @@ struct hostent *unrealdns_doclient(Client *client)
/** Resolve a name to an IP, for a link block.
*/
-void unrealdns_gethostbyname_link(char *name, ConfigItem_link *conf, int ipv4_only)
+void unrealdns_gethostbyname_link(const char *name, ConfigItem_link *conf, int ipv4_only)
{
DNSReq *r;
@@ -283,27 +282,6 @@ void unrealdns_cb_iptoname(void *arg, int status, int timeouts, struct hostent *
ares_gethostbyname(resolver_channel, he->h_name, ipv6 ? AF_INET6 : AF_INET, unrealdns_cb_nametoip_verify, newr);
}
-/*
- returns:
- 1 = good hostname
- 0 = bad hostname
- */
-int verify_hostname(char *name)
-{
-char *p;
-
- if (strlen(name) > HOSTLEN)
- return 0;
-
- /* No underscores or other illegal characters */
- for (p = name; *p; p++)
- if (!isalnum(*p) && !strchr(".-", *p))
- return 0;
-
- return 1;
-}
-
-
void unrealdns_cb_nametoip_verify(void *arg, int status, int timeouts, struct hostent *he)
{
DNSReq *r = (DNSReq *)arg;
@@ -348,13 +326,16 @@ void unrealdns_cb_nametoip_verify(void *arg, int status, int timeouts, struct ho
goto bad;
}
- if (!verify_hostname(r->name))
+ if (!valid_host(r->name, 1))
{
/* Hostname is bad, don't cache and consider unresolved */
proceed_normal_client_handshake(client, NULL);
goto bad;
}
+ /* Get rid of stupid uppercase DNS names... */
+ strtolower(r->name);
+
/* Entry was found, verified, and can be added to cache */
unrealdns_addtocache(r->name, client->ip);
@@ -372,7 +353,7 @@ void unrealdns_cb_nametoip_link(void *arg, int status, int timeouts, struct host
int n;
struct hostent *he2;
char ipbuf[HOSTLEN+1];
- char *ip = NULL;
+ const char *ip = NULL;
if (!r->linkblock)
{
@@ -393,8 +374,9 @@ void unrealdns_cb_nametoip_link(void *arg, int status, int timeouts, struct host
}
/* fatal error while resolving */
- sendto_ops_and_log("Unable to resolve hostname '%s', when trying to connect to server %s.",
- r->name, r->linkblock->servername);
+ unreal_log(ULOG_ERROR, "link", "LINK_ERROR_RESOLVING", NULL,
+ "Unable to resolve hostname $link_block.hostname, when trying to connect to server $link_block.",
+ log_data_link_block(r->linkblock));
r->linkblock->refcount--;
unrealdns_freeandremovereq(r);
return;
@@ -405,8 +387,9 @@ void unrealdns_cb_nametoip_link(void *arg, int status, int timeouts, struct host
!(ip = inetntop(r->ipv6 ? AF_INET6 : AF_INET, he->h_addr_list[0], ipbuf, sizeof(ipbuf))))
{
/* Illegal response -- fatal */
- sendto_ops_and_log("Unable to resolve hostname '%s', when trying to connect to server %s.",
- r->name, r->linkblock->servername);
+ unreal_log(ULOG_ERROR, "link", "LINK_ERROR_RESOLVING", NULL,
+ "Unable to resolve hostname $link_block.hostname, when trying to connect to server $link_block.",
+ log_data_link_block(r->linkblock));
unrealdns_freeandremovereq(r);
return;
}
@@ -417,22 +400,9 @@ void unrealdns_cb_nametoip_link(void *arg, int status, int timeouts, struct host
safe_strdup(r->linkblock->connect_ip, ip);
he2 = unreal_create_hostent(he->h_name, ip);
- switch ((n = connect_server(r->linkblock, r->client, he2)))
- {
- case 0:
- sendto_ops_and_log("Trying to activate link with server %s[%s]...", r->linkblock->servername, ip);
- break;
- case -1:
- sendto_ops_and_log("Couldn't connect to server %s[%s].", r->linkblock->servername, ip);
- break;
- case -2:
- /* Should not happen since he is not NULL */
- sendto_ops_and_log("Hostname %s is unknown for server %s (!?).", r->linkblock->outgoing.hostname, r->linkblock->servername);
- break;
- default:
- sendto_ops_and_log("Connection to server %s failed: %s", r->linkblock->servername, STRERROR(n));
- }
-
+ /* Try to connect to the server */
+ connect_server(r->linkblock, r->client, he2);
+
unrealdns_freeandremovereq(r);
/* DONE */
}
@@ -442,7 +412,7 @@ static uint64_t unrealdns_hash_ip(const char *ip)
return siphash(ip, siphashkey_dns_ip) % DNS_HASH_SIZE;
}
-static void unrealdns_addtocache(char *name, char *ip)
+static void unrealdns_addtocache(const char *name, const char *ip)
{
unsigned int hashv;
DNSCache *c;
@@ -494,7 +464,7 @@ static void unrealdns_addtocache(char *name, char *ip)
/** Search the cache for a confirmed ip->name and name->ip match, by address.
* @returns The resolved hostname, or NULL if not found in cache.
*/
-static char *unrealdns_findcache_ip(char *ip)
+static const char *unrealdns_findcache_ip(const char *ip)
{
unsigned int hashv;
DNSCache *c;
@@ -562,17 +532,11 @@ DNSCache *c, *next;
{
next = c->next;
if (c->expires < TStime())
- {
-#if 0
- sendto_realops(client, "[Syzop/DNS] Expire: %s [%s] (%ld < %ld)",
- c->name, c->ip, c->expires, TStime());
-#endif
unrealdns_removecacherecord(c);
- }
}
}
-struct hostent *unreal_create_hostent(char *name, char *ip)
+struct hostent *unreal_create_hostent(const char *name, const char *ip)
{
struct hostent *he;
@@ -646,7 +610,7 @@ CMD_FUNC(cmd_dns)
{
DNSCache *c;
DNSReq *r;
- char *param;
+ const char *param;
if (!ValidatePermissionsForPath("server:dns",client,NULL,NULL,NULL))
{
@@ -673,8 +637,8 @@ CMD_FUNC(cmd_dns)
} else
if (*param == 'c') /* CLEAR CACHE */
{
- sendto_realops("%s (%s@%s) cleared the DNS cache list (/QUOTE DNS c)",
- client->name, client->user->username, client->user->realhost);
+ unreal_log(ULOG_INFO, "dns", "DNS_CACHE_CLEARED", client,
+ "DNS cache cleared by $client");
while (cache_list)
{
@@ -702,7 +666,8 @@ CMD_FUNC(cmd_dns)
ares_get_servers(resolver_channel, &serverlist);
for (ns = serverlist; ns; ns = ns->next)
{
- char ipbuf[128], *ip;
+ char ipbuf[128];
+ const char *ip;
i++;
ip = inetntop(ns->family, &ns->addr, ipbuf, sizeof(ipbuf));
diff --git a/src/fdlist.c b/src/fdlist.c
index 0d9dc98..ae57aee 100644
--- a/src/fdlist.c
+++ b/src/fdlist.c
@@ -24,16 +24,23 @@
*/
FDEntry fd_table[MAXCONNECTIONS + 1];
-int fd_open(int fd, const char *desc)
+/** Notify I/O engine that a file descriptor opened.
+ * @param fd The file descriptor
+ * @param desc Description for in the fd table
+ * @param close_method Tell what a subsequent call to fd_close() should do,
+ * eg close the socket, file or don't close anything.
+ * @returns The file descriptor 'fd' or -1 in case of fatal error.
+ */
+int fd_open(int fd, const char *desc, FDCloseMethod close_method)
{
FDEntry *fde;
if ((fd < 0) || (fd >= MAXCONNECTIONS))
{
- sendto_realops("[BUG] trying to add fd #%d to fd table, but MAXCONNECTIONS is %d",
- fd, MAXCONNECTIONS);
- ircd_log(LOG_ERROR, "[BUG] trying to add fd #%d to fd table, but MAXCONNECTIONS is %d",
- fd, MAXCONNECTIONS);
+ unreal_log(ULOG_ERROR, "io", "BUG_FD_OPEN_OUT_OF_RANGE", NULL,
+ "[BUG] trying to add fd $fd to fd table, but MAXCONNECTIONS is $maxconnections",
+ log_data_integer("fd", fd),
+ log_data_integer("maxconnections", MAXCONNECTIONS));
#ifdef DEBUGMODE
abort();
#endif
@@ -46,6 +53,7 @@ int fd_open(int fd, const char *desc)
fde->fd = fd;
fde->is_open = 1;
fde->backend_flags = 0;
+ fde->close_method = close_method;
strlcpy(fde->desc, desc, FD_DESC_SZ);
return fde->fd;
@@ -71,20 +79,28 @@ int fd_fileopen(const char *path, unsigned int flags)
snprintf(comment, sizeof comment, "File: %s", unreal_getfilename(pathbuf));
- return fd_open(fd, comment);
+ return fd_open(fd, comment, FDCLOSE_FILE);
}
-int fd_unmap(int fd)
+/** Internal function to unmap and optionally close the fd.
+ */
+/** Remove file descriptor from our table and possibly close the fd.
+ * The fd is closed (or not) according to the method specified in fd_open().
+ * @param fd The file descriptor
+ * @returns 1 on success, 0 on failure
+ */
+int fd_close(int fd)
{
FDEntry *fde;
unsigned int befl;
+ FDCloseMethod close_method;
if ((fd < 0) || (fd >= MAXCONNECTIONS))
{
- sendto_realops("[BUG] trying to close fd #%d in fd table, but MAXCONNECTIONS is %d",
- fd, MAXCONNECTIONS);
- ircd_log(LOG_ERROR, "[BUG] trying to close fd #%d in fd table, but MAXCONNECTIONS is %d",
- fd, MAXCONNECTIONS);
+ unreal_log(ULOG_ERROR, "io", "BUG_FD_CLOSE_OUT_OF_RANGE", NULL,
+ "[BUG] trying to close fd $fd to fd table, but MAXCONNECTIONS is $maxconnections",
+ log_data_integer("fd", fd),
+ log_data_integer("maxconnections", MAXCONNECTIONS));
#ifdef DEBUGMODE
abort();
#endif
@@ -94,10 +110,9 @@ int fd_unmap(int fd)
fde = &fd_table[fd];
if (!fde->is_open)
{
- sendto_realops("[BUG] trying to close fd #%d in fd table, but this FD isn't reported open",
- fd);
- ircd_log(LOG_ERROR, "[BUG] trying to close fd #%d in fd table, but this FD isn't reported open",
- fd);
+ unreal_log(ULOG_ERROR, "io", "BUG_FD_CLOSE_NOT_OPEN", NULL,
+ "[BUG] trying to close fd $fd to fd table, but FD is (already) closed",
+ log_data_integer("fd", fd));
#ifdef DEBUGMODE
abort();
#endif
@@ -105,6 +120,7 @@ int fd_unmap(int fd)
}
befl = fde->backend_flags;
+ close_method = fde->close_method;
memset(fde, 0, sizeof(FDEntry));
fde->fd = fd;
@@ -112,25 +128,29 @@ int fd_unmap(int fd)
/* only notify the backend if it is actively tracking the FD */
if (befl)
fd_refresh(fd);
-
+
+ /* Finally, close the file or socket if requested to do so */
+ switch (close_method)
+ {
+ case FDCLOSE_SOCKET:
+ CLOSE_SOCK(fd);
+ break;
+ case FDCLOSE_FILE:
+ close(fd);
+ break;
+ case FDCLOSE_NONE:
+ default:
+ break;
+ }
+
return 1;
}
-void fd_close(int fd)
-{
- if (!fd_unmap(fd))
- return;
-
- CLOSE_SOCK(fd);
-}
-
/* Deregister I/O notification for this file descriptor */
void fd_unnotify(int fd)
{
-FDEntry *fde;
-#ifdef DEBUGMODE
- ircd_log(LOG_ERROR, "fd_unnotify(): fd=%d", fd);
-#endif
+ FDEntry *fde;
+
if ((fd < 0) || (fd >= MAXCONNECTIONS))
return;
@@ -150,7 +170,7 @@ int fd_socket(int family, int type, int protocol, const char *desc)
if (fd < 0)
return -1;
- return fd_open(fd, desc);
+ return fd_open(fd, desc, FDCLOSE_SOCKET);
}
int fd_accept(int sockfd)
@@ -162,7 +182,7 @@ int fd_accept(int sockfd)
if (fd < 0)
return -1;
- return fd_open(fd, buf);
+ return fd_open(fd, buf, FDCLOSE_SOCKET);
}
void fd_desc(int fd, const char *desc)
@@ -171,10 +191,10 @@ void fd_desc(int fd, const char *desc)
if ((fd < 0) || (fd >= MAXCONNECTIONS))
{
- sendto_realops("[BUG] trying to modify fd #%d in fd table, but MAXCONNECTIONS is %d",
- fd, MAXCONNECTIONS);
- ircd_log(LOG_ERROR, "[BUG] trying to modify fd #%d in fd table, but MAXCONNECTIONS is %d",
- fd, MAXCONNECTIONS);
+ unreal_log(ULOG_ERROR, "io", "BUG_FD_DESC_OUT_OF_RANGE", NULL,
+ "[BUG] trying to fd_desc fd $fd in fd table, but MAXCONNECTIONS is $maxconnections",
+ log_data_integer("fd", fd),
+ log_data_integer("maxconnections", MAXCONNECTIONS));
#ifdef DEBUGMODE
abort();
#endif
@@ -184,10 +204,9 @@ void fd_desc(int fd, const char *desc)
fde = &fd_table[fd];
if (!fde->is_open)
{
- sendto_realops("[BUG] trying to modify fd #%d in fd table, but this FD isn't reported open",
- fd);
- ircd_log(LOG_ERROR, "[BUG] trying to modify fd #%d in fd table, but this FD isn't reported open",
- fd);
+ unreal_log(ULOG_ERROR, "io", "BUG_FD_DESC_NOT_OPEN", NULL,
+ "[BUG] trying to fd_desc fd $fd in fd table, but FD is (already) closed",
+ log_data_integer("fd", fd));
#ifdef DEBUGMODE
abort();
#endif
diff --git a/src/hash.c b/src/hash.c
index e5dd203..0901af9 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -260,11 +260,9 @@ void siphash_generate_key(char *k)
static struct list_head clientTable[NICK_HASH_TABLE_SIZE];
static struct list_head idTable[NICK_HASH_TABLE_SIZE];
static Channel *channelTable[CHAN_HASH_TABLE_SIZE];
-static Watch *watchTable[WATCH_HASH_TABLE_SIZE];
static char siphashkey_nick[SIPHASH_KEY_LENGTH];
static char siphashkey_chan[SIPHASH_KEY_LENGTH];
-static char siphashkey_watch[SIPHASH_KEY_LENGTH];
static char siphashkey_whowas[SIPHASH_KEY_LENGTH];
static char siphashkey_throttling[SIPHASH_KEY_LENGTH];
@@ -277,7 +275,6 @@ void init_hash(void)
siphash_generate_key(siphashkey_nick);
siphash_generate_key(siphashkey_chan);
- siphash_generate_key(siphashkey_watch);
siphash_generate_key(siphashkey_whowas);
siphash_generate_key(siphashkey_throttling);
@@ -288,7 +285,6 @@ void init_hash(void)
INIT_LIST_HEAD(&idTable[i]);
memset(channelTable, 0, sizeof(channelTable));
- memset(watchTable, 0, sizeof(watchTable));
memset(ThrottlingHash, 0, sizeof(ThrottlingHash));
/* do not call init_throttling() here, as
@@ -310,11 +306,6 @@ uint64_t hash_channel_name(const char *name)
return siphash_nocase(name, siphashkey_chan) % CHAN_HASH_TABLE_SIZE;
}
-uint64_t hash_watch_nick_name(const char *name)
-{
- return siphash_nocase(name, siphashkey_watch) % WATCH_HASH_TABLE_SIZE;
-}
-
uint64_t hash_whowas_name(const char *name)
{
return siphash_nocase(name, siphashkey_whowas) % WHOWAS_HASH_TABLE_SIZE;
@@ -323,7 +314,7 @@ uint64_t hash_whowas_name(const char *name)
/*
* add_to_client_hash_table
*/
-int add_to_client_hash_table(char *name, Client *client)
+int add_to_client_hash_table(const char *name, Client *client)
{
unsigned int hashv;
/*
@@ -349,7 +340,7 @@ int add_to_client_hash_table(char *name, Client *client)
/*
* add_to_client_hash_table
*/
-int add_to_id_hash_table(char *name, Client *client)
+int add_to_id_hash_table(const char *name, Client *client)
{
unsigned int hashv;
hashv = hash_client_name(name);
@@ -360,7 +351,7 @@ int add_to_id_hash_table(char *name, Client *client)
/*
* add_to_channel_hash_table
*/
-int add_to_channel_hash_table(char *name, Channel *channel)
+int add_to_channel_hash_table(const char *name, Channel *channel)
{
unsigned int hashv;
@@ -372,7 +363,7 @@ int add_to_channel_hash_table(char *name, Channel *channel)
/*
* del_from_client_hash_table
*/
-int del_from_client_hash_table(char *name, Client *client)
+int del_from_client_hash_table(const char *name, Client *client)
{
if (!list_empty(&client->client_hash))
list_del(&client->client_hash);
@@ -382,7 +373,7 @@ int del_from_client_hash_table(char *name, Client *client)
return 0;
}
-int del_from_id_hash_table(char *name, Client *client)
+int del_from_id_hash_table(const char *name, Client *client)
{
if (!list_empty(&client->id_hash))
list_del(&client->id_hash);
@@ -395,7 +386,7 @@ int del_from_id_hash_table(char *name, Client *client)
/*
* del_from_channel_hash_table
*/
-void del_from_channel_hash_table(char *name, Channel *channel)
+void del_from_channel_hash_table(const char *name, Channel *channel)
{
Channel *tmp, *prev = NULL;
unsigned int hashv;
@@ -465,7 +456,7 @@ Client *hash_find_nickatserver(const char *str, Client *def)
if (serv)
*serv++ = '\0';
- client = find_person(nick, NULL);
+ client = find_user(nick, NULL);
if (!client)
return NULL; /* client not found */
@@ -509,14 +500,14 @@ Client *hash_find_server(const char *server, Client *def)
/** Find a client by name.
* This searches in the list of all types of clients, user/person, servers or an unregistered clients.
- * If you know what type of client to search for, then use find_server() or find_person() instead!
+ * If you know what type of client to search for, then use find_server() or find_user() instead!
* @param name The name to search for (eg: "nick" or "irc.example.net")
* @param requester The client that is searching for this name
* @note If 'requester' is a server or NULL, then we also check
* the ID table, otherwise not.
* @returns If the client is found then the Client is returned, otherwise NULL.
*/
-Client *find_client(char *name, Client *requester)
+Client *find_client(const char *name, Client *requester)
{
if (requester == NULL || IsServer(requester))
{
@@ -537,7 +528,7 @@ Client *find_client(char *name, Client *requester)
* the ID table, otherwise not.
* @returns If the server is found then the Client is returned, otherwise NULL.
*/
-Client *find_server(char *name, Client *requester)
+Client *find_server(const char *name, Client *requester)
{
if (name)
{
@@ -550,14 +541,14 @@ Client *find_server(char *name, Client *requester)
return NULL;
}
-/** Find a person (a user).
+/** Find a user (a person)
* @param name The name to search for (eg: "nick" or "001ABCDEFG")
* @param requester The client that is searching for this name
* @note If 'requester' is a server or NULL, then we also check
* the ID table, otherwise not.
* @returns If the user is found then the Client is returned, otherwise NULL.
*/
-Client *find_person(char *name, Client *requester) /* TODO: this should have been called find_user() to be consistent */
+Client *find_user(const char *name, Client *requester)
{
Client *c2ptr;
@@ -572,22 +563,20 @@ Client *find_person(char *name, Client *requester) /* TODO: this should have bee
/** Find a channel by name.
* @param name The channel name to search for
- * @param default_result If the channel is not found, this value is returned.
- * @returns If the channel exists then the Channel is returned, otherwise default_result is returned.
+ * @returns If the channel exists then the Channel is returned, otherwise NULL.
*/
-Channel *find_channel(char *name, Channel *default_result)
+Channel *find_channel(const char *name)
{
unsigned int hashv;
- Channel *tmp;
+ Channel *channel;
hashv = hash_channel_name(name);
- for (tmp = channelTable[hashv]; tmp; tmp = tmp->hnextch)
- {
- if (smycmp(name, tmp->chname) == 0)
- return tmp;
- }
- return default_result;
+ for (channel = channelTable[hashv]; channel; channel = channel->hnextch)
+ if (smycmp(name, channel->name) == 0)
+ return channel;
+
+ return NULL;
}
/** @} */
@@ -599,303 +588,6 @@ Channel *hash_get_chan_bucket(uint64_t hashv)
return channelTable[hashv];
}
-void count_watch_memory(int *count, u_long *memory)
-{
- int i = WATCH_HASH_TABLE_SIZE;
- Watch *anptr;
-
- while (i--)
- {
- anptr = watchTable[i];
- while (anptr)
- {
- (*count)++;
- (*memory) += sizeof(Watch)+strlen(anptr->nick);
- anptr = anptr->hnext;
- }
- }
-}
-
-/*
- * add_to_watch_hash_table
- */
-int add_to_watch_hash_table(char *nick, Client *client, int awaynotify)
-{
- unsigned int hashv;
- Watch *anptr;
- Link *lp;
-
-
- /* Get the right bucket... */
- hashv = hash_watch_nick_name(nick);
-
- /* Find the right nick (header) in the bucket, or NULL... */
- if ((anptr = (Watch *)watchTable[hashv]))
- while (anptr && mycmp(anptr->nick, nick))
- anptr = anptr->hnext;
-
- /* If found NULL (no header for this nick), make one... */
- if (!anptr) {
- anptr = (Watch *)safe_alloc(sizeof(Watch)+strlen(nick));
- anptr->lasttime = timeofday;
- strcpy(anptr->nick, nick);
-
- anptr->watch = NULL;
-
- anptr->hnext = watchTable[hashv];
- watchTable[hashv] = anptr;
- }
- /* Is this client already on the watch-list? */
- if ((lp = anptr->watch))
- while (lp && (lp->value.client != client))
- lp = lp->next;
-
- /* No it isn't, so add it in the bucket and client addint it */
- if (!lp) {
- lp = anptr->watch;
- anptr->watch = make_link();
- anptr->watch->value.client = client;
- anptr->watch->flags = awaynotify;
- anptr->watch->next = lp;
-
- lp = make_link();
- lp->next = client->local->watch;
- lp->value.wptr = anptr;
- lp->flags = awaynotify;
- client->local->watch = lp;
- client->local->watches++;
- }
-
- return 0;
-}
-
-/*
- * hash_check_watch
- */
-int hash_check_watch(Client *client, int reply)
-{
- unsigned int hashv;
- Watch *anptr;
- Link *lp;
- int awaynotify = 0;
-
- if ((reply == RPL_GONEAWAY) || (reply == RPL_NOTAWAY) || (reply == RPL_REAWAY))
- awaynotify = 1;
-
- /* Get us the right bucket */
- hashv = hash_watch_nick_name(client->name);
-
- /* Find the right header in this bucket */
- if ((anptr = (Watch *)watchTable[hashv]))
- while (anptr && mycmp(anptr->nick, client->name))
- anptr = anptr->hnext;
- if (!anptr)
- return 0; /* This nick isn't on watch */
-
- /* Update the time of last change to item */
- anptr->lasttime = TStime();
-
- /* Send notifies out to everybody on the list in header */
- for (lp = anptr->watch; lp; lp = lp->next)
- {
- if (!awaynotify)
- {
- sendnumeric(lp->value.client, reply,
- client->name,
- (IsUser(client) ? client->user->username : ""),
- (IsUser(client) ?
- (IsHidden(client) ? client->user->virthost : client->
- user->realhost) : ""), anptr->lasttime, client->info);
- }
- else
- {
- /* AWAY or UNAWAY */
- if (!lp->flags)
- continue; /* skip away/unaway notification for users not interested in them */
-
- if (reply == RPL_NOTAWAY)
- sendnumeric(lp->value.client, reply,
- client->name,
- (IsUser(client) ? client->user->username : ""),
- (IsUser(client) ?
- (IsHidden(client) ? client->user->virthost : client->
- user->realhost) : ""), client->user->lastaway);
- else /* RPL_GONEAWAY / RPL_REAWAY */
- sendnumeric(lp->value.client, reply,
- client->name,
- (IsUser(client) ? client->user->username : ""),
- (IsUser(client) ?
- (IsHidden(client) ? client->user->virthost : client->
- user->realhost) : ""), client->user->lastaway, client->user->away);
- }
- }
-
- return 0;
-}
-
-/*
- * hash_get_watch
- */
-Watch *hash_get_watch(char *nick)
-{
- unsigned int hashv;
- Watch *anptr;
-
- hashv = hash_watch_nick_name(nick);
-
- if ((anptr = (Watch *)watchTable[hashv]))
- while (anptr && mycmp(anptr->nick, nick))
- anptr = anptr->hnext;
-
- return anptr;
-}
-
-/*
- * del_from_watch_hash_table
- */
-int del_from_watch_hash_table(char *nick, Client *client)
-{
- unsigned int hashv;
- Watch *anptr, *nlast = NULL;
- Link *lp, *last = NULL;
-
- /* Get the bucket for this nick... */
- hashv = hash_watch_nick_name(nick);
-
- /* Find the right header, maintaining last-link pointer... */
- if ((anptr = (Watch *)watchTable[hashv]))
- while (anptr && mycmp(anptr->nick, nick)) {
- nlast = anptr;
- anptr = anptr->hnext;
- }
- if (!anptr)
- return 0; /* No such watch */
-
- /* Find this client from the list of notifies... with last-ptr. */
- if ((lp = anptr->watch))
- while (lp && (lp->value.client != client)) {
- last = lp;
- lp = lp->next;
- }
- if (!lp)
- return 0; /* No such client to watch */
-
- /* Fix the linked list under header, then remove the watch entry */
- if (!last)
- anptr->watch = lp->next;
- else
- last->next = lp->next;
- free_link(lp);
-
- /* Do the same regarding the links in client-record... */
- last = NULL;
- if ((lp = client->local->watch))
- while (lp && (lp->value.wptr != anptr)) {
- last = lp;
- lp = lp->next;
- }
-
- /*
- * Give error on the odd case... probobly not even neccessary
- * No error checking in ircd is unneccessary ;) -Cabal95
- */
- if (!lp)
- sendto_ops("WATCH debug error: del_from_watch_hash_table "
- "found a watch entry with no client "
- "counterpoint processing nick %s on client %p!",
- nick, client->user);
- else {
- if (!last) /* First one matched */
- client->local->watch = lp->next;
- else
- last->next = lp->next;
- free_link(lp);
- }
- /* In case this header is now empty of notices, remove it */
- if (!anptr->watch) {
- if (!nlast)
- watchTable[hashv] = anptr->hnext;
- else
- nlast->hnext = anptr->hnext;
- safe_free(anptr);
- }
-
- /* Update count of notifies on nick */
- client->local->watches--;
-
- return 0;
-}
-
-/*
- * hash_del_watch_list
- */
-int hash_del_watch_list(Client *client)
-{
- unsigned int hashv;
- Watch *anptr;
- Link *np, *lp, *last;
-
-
- if (!(np = client->local->watch))
- return 0; /* Nothing to do */
-
- client->local->watch = NULL; /* Break the watch-list for client */
- while (np) {
- /* Find the watch-record from hash-table... */
- anptr = np->value.wptr;
- last = NULL;
- for (lp = anptr->watch; lp && (lp->value.client != client);
- lp = lp->next)
- last = lp;
-
- /* Not found, another "worst case" debug error */
- if (!lp)
- sendto_ops("WATCH Debug error: hash_del_watch_list "
- "found a WATCH entry with no table "
- "counterpoint processing client %s!",
- client->name);
- else {
- /* Fix the watch-list and remove entry */
- if (!last)
- anptr->watch = lp->next;
- else
- last->next = lp->next;
- free_link(lp);
-
- /*
- * If this leaves a header without notifies,
- * remove it. Need to find the last-pointer!
- */
- if (!anptr->watch) {
- Watch *np2, *nl;
-
- hashv = hash_watch_nick_name(anptr->nick);
-
- nl = NULL;
- np2 = watchTable[hashv];
- while (np2 != anptr) {
- nl = np2;
- np2 = np2->hnext;
- }
-
- if (nl)
- nl->hnext = anptr->hnext;
- else
- watchTable[hashv] = anptr->hnext;
- safe_free(anptr);
- }
- }
-
- lp = np; /* Save last pointer processed */
- np = np->next; /* Jump to the next pointer */
- free_link(lp); /* Free the previous */
- }
-
- client->local->watches = 0;
-
- return 0;
-}
-
/* Throttling - originally by Stskeeps */
/* Note that we call this set::anti-flood::connect-flood nowadays */
@@ -925,15 +617,7 @@ void update_throttling_timer_settings(void)
EventMod(EventFind("throttling_check_expire"), &eInfo);
}
-void init_throttling()
-{
- EventAdd(NULL, "throttling_check_expire", throttling_check_expire, NULL, 123456, 0);
- /* Note: the every_ms value (123,456) will be adjusted on boot and rehash
- * via the update_throttling_timer_settings() function.
- */
-}
-
-uint64_t hash_throttling(char *ip)
+uint64_t hash_throttling(const char *ip)
{
return siphash(ip, siphashkey_throttling) % THROTTLING_HASH_TABLE_SIZE;
}
diff --git a/src/ircd.c b/src/ircd.c
index ed1e0d4..dbb5554 100644
--- a/src/ircd.c
+++ b/src/ircd.c
@@ -34,7 +34,6 @@ time_t timeofday = 0;
struct timeval timeofday_tv;
int tainted = 0;
LoopStruct loop;
-MODVAR MemoryInfo StatsZ;
#ifndef _WIN32
uid_t irc_uid = 0;
gid_t irc_gid = 0;
@@ -51,12 +50,8 @@ extern SERVICE_STATUS IRCDStatus;
MODVAR unsigned char conf_debuglevel = 0;
-#ifdef USE_LIBCURL
-extern void url_init(void);
-#endif
-
-void server_reboot(char *);
-void restart(char *);
+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);
@@ -82,7 +77,7 @@ void s_die()
Client *client;
if (!IsService)
{
- loop.ircd_terminating = 1;
+ loop.terminating = 1;
unload_all_modules();
list_for_each_entry(client, &lclient_list, lclient_node)
@@ -97,7 +92,7 @@ void s_die()
ControlService(hService, SERVICE_CONTROL_STOP, &status);
}
#else
- loop.ircd_terminating = 1;
+ loop.terminating = 1;
unload_all_modules();
unlink(conf_files ? conf_files->pid_file : IRCD_PIDFILE);
exit(0);
@@ -128,7 +123,7 @@ static void s_reloadcert()
}
#endif // #ifndef _WIN32
-void restart(char *mesg)
+void restart(const char *mesg)
{
server_reboot(mesg);
}
@@ -174,12 +169,13 @@ void ignore_this_signal()
#endif /* #ifndef _WIN32 */
-void server_reboot(char *mesg)
+void server_reboot(const char *mesg)
{
int i;
Client *client;
- sendto_realops("Aieeeee!!! Restarting server... %s", mesg);
- Debug((DEBUG_NOTICE, "Restarting server... %s", mesg));
+ 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);
@@ -206,12 +202,6 @@ void server_reboot(char *mesg)
CleanUp();
WinExec(cmdLine, SW_SHOWDEFAULT);
}
-#endif
-#ifndef _WIN32
- Debug((DEBUG_FATAL, "Couldn't restart server: %s", strerror(errno)));
-#else
- Debug((DEBUG_FATAL, "Couldn't restart server: %s",
- strerror(GetLastError())));
#endif
unload_all_modules();
#ifdef _WIN32
@@ -254,7 +244,7 @@ EVENT(garbage_collect)
int ii;
if (loop.do_garbage_collect == 1)
- sendto_realops("Doing garbage collection ..");
+ unreal_log(ULOG_INFO, "main", "GARBAGE_COLLECT_STARTED", NULL, "Doing garbage collection...");
if (freelinks > HOW_MANY_FREELINKS_ALLOWED) {
ii = freelinks;
while (freelink && (freelinks > HOW_MANY_FREELINKS_ALLOWED)) {
@@ -265,65 +255,20 @@ EVENT(garbage_collect)
}
if (loop.do_garbage_collect == 1) {
loop.do_garbage_collect = 0;
- sendto_realops
- ("Cleaned up %i garbage blocks", (ii - freelinks));
+ unreal_log(ULOG_INFO, "main", "GARBAGE_COLLECT_STARTED", NULL, "Cleaned up $count garbage blocks",
+ (ii - freelinks));
}
}
if (loop.do_garbage_collect == 1)
loop.do_garbage_collect = 0;
}
-/** Perform autoconnect to servers that are not linked yet. */
-EVENT(try_connections)
-{
- ConfigItem_link *aconf;
- ConfigItem_deny_link *deny;
- Client *client;
- int confrq;
- ConfigItem_class *class;
-
- for (aconf = conf_link; aconf; aconf = aconf->next)
- {
- /* We're only interested in autoconnect blocks that are valid. Also, we ignore temporary link blocks. */
- if (!(aconf->outgoing.options & CONNECT_AUTO) || !aconf->outgoing.hostname || (aconf->flag.temporary == 1))
- continue;
-
- class = aconf->class;
-
- /* Only do one connection attempt per seconds (for the same server) */
- if ((aconf->hold > TStime()))
- continue;
-
- confrq = class->connfreq;
- aconf->hold = TStime() + confrq;
-
- client = find_client(aconf->servername, NULL);
- if (client)
- continue; /* Server already connected (or connecting) */
-
- if (class->clients >= class->maxclients)
- continue; /* Class is full */
-
- /* Check connect rules to see if we're allowed to try the link */
- for (deny = conf_deny_link; deny; deny = deny->next)
- if (match_simple(deny->mask, aconf->servername) && crule_eval(deny->rule))
- break;
-
- if (!deny && connect_server(aconf, NULL, NULL) == 0)
- sendto_ops_and_log("Trying to activate link with server %s[%s]...",
- aconf->servername, aconf->outgoing.hostname);
-
- }
-}
-
/** Does this user match any TKL's? */
int match_tkls(Client *client)
{
ConfigItem_ban *bconf = NULL;
char banbuf[1024];
- char killflag = 0;
-
/* Process dynamic *LINES */
if (find_tkline_match(client, 0))
return 1; /* user killed */
@@ -334,35 +279,25 @@ int match_tkls(Client *client)
{
/* Check ban realname { } */
if (!ValidatePermissionsForPath("immune",client,NULL,NULL,NULL) && (bconf = find_ban(NULL, client->info, CONF_BAN_REALNAME)))
- killflag++;
- }
+ {
+ unreal_log(ULOG_INFO, "tkl", "BAN_REALNAME", client,
+ "Banned client $client.details due to realname ban: $reason",
+ bconf->reason ? bconf->reason : "no reason");
- /* If user is meant to be killed, take action: */
- if (killflag)
- {
- if (IsUser(client))
- sendto_realops("Ban active for %s (%s)",
- get_client_name(client, FALSE),
- bconf->reason ? bconf->reason : "no reason");
-
- if (IsServer(client))
- sendto_realops("Ban active for server %s (%s)",
- get_client_name(client, FALSE),
- bconf->reason ? bconf->reason : "no reason");
-
- if (bconf->reason) {
- if (IsUser(client))
- snprintf(banbuf, sizeof(banbuf), "User has been banned (%s)", bconf->reason);
- else
- snprintf(banbuf, sizeof(banbuf), "Banned (%s)", bconf->reason);
- exit_client(client, NULL, banbuf);
- } else {
- if (IsUser(client))
- exit_client(client, NULL, "User has been banned");
- else
- exit_client(client, NULL, "Banned");
+ if (bconf->reason) {
+ if (IsUser(client))
+ snprintf(banbuf, sizeof(banbuf), "User has been banned (%s)", bconf->reason);
+ else
+ snprintf(banbuf, sizeof(banbuf), "Banned (%s)", bconf->reason);
+ exit_client(client, NULL, banbuf);
+ } else {
+ if (IsUser(client))
+ exit_client(client, NULL, "User has been banned");
+ else
+ exit_client(client, NULL, "Banned");
+ }
+ return 1; /* stop processing, client is dead now */
}
- return 1; /* stop processing this user, as (s)he is dead now. */
}
if (loop.do_bancheck_spamf_user && IsUser(client) && find_spamfilter_user(client, SPAMFLAG_NOWARN))
@@ -385,14 +320,10 @@ EVENT(handshake_timeout)
list_for_each_entry_safe(client, next, &unknown_list, lclient_node)
{
- if (client->local->firsttime && ((TStime() - client->local->firsttime) > iConf.handshake_timeout))
+ if (client->local->creationtime && ((TStime() - client->local->creationtime) > iConf.handshake_timeout))
{
- if (client->serv && *client->serv->by)
- {
- /* If this is a handshake timeout to an outgoing server then notify ops & log it */
- sendto_ops_and_log("Connection handshake timeout while trying to link to server '%s' (%s)",
- client->name, client->ip?client->ip:"");
- }
+ if (client->server && *client->server->by)
+ continue; /* handled by server module */
exit_client(client, NULL, "Registration Timeout");
continue;
@@ -407,37 +338,31 @@ void check_ping(Client *client)
int ping = 0;
ping = client->local->class ? client->local->class->pingfreq : iConf.handshake_timeout;
- Debug((DEBUG_DEBUG, "c(%s)=%d p %d a %lld", client->name,
- client->status, ping,
- (long long)(TStime() - client->local->lasttime)));
/* If ping is less than or equal to the last time we received a command from them */
- if (ping > (TStime() - client->local->lasttime))
+ if (ping > (TStime() - client->local->last_msg_received))
return; /* some recent command was executed */
if (
/* If we have sent a ping */
(IsPingSent(client)
/* And they had 2x ping frequency to respond */
- && ((TStime() - client->local->lasttime) >= (2 * ping)))
+ && ((TStime() - client->local->last_msg_received) >= (2 * ping)))
||
/* Or isn't registered and time spent is larger than ping (CONNECTTIMEOUT).. */
- (!IsRegistered(client) && (TStime() - client->local->since >= ping))
+ (!IsRegistered(client) && (TStime() - client->local->fake_lag >= ping))
)
{
if (IsServer(client) || IsConnecting(client) ||
IsHandshake(client) || IsTLSConnectHandshake(client))
{
- sendto_umode_global(UMODE_OPER, "No response from %s, closing link",
- get_client_name(client, FALSE));
- ircd_log(LOG_ERROR, "No response from %s, closing link",
- get_client_name(client, FALSE));
+ unreal_log(ULOG_ERROR, "link", "LINK_DISCONNECTED", client,
+ "Lost server link to $client [$client.ip]: No response (Ping timeout)",
+ client->server->conf ? log_data_link_block(client->server->conf) : NULL);
+ SetServerDisconnectLogged(client);
}
- if (IsTLSAcceptHandshake(client))
- Debug((DEBUG_DEBUG, "ssl accept handshake timeout: %s (%lld-%lld > %lld)", client->local->sockhost,
- (long long)TStime(), (long long)client->local->since, (long long)ping));
ircsnprintf(scratch, sizeof(scratch), "Ping timeout: %lld seconds",
- (long long) (TStime() - client->local->lasttime));
+ (long long) (TStime() - client->local->last_msg_received));
exit_client(client, NULL, scratch);
return;
}
@@ -447,17 +372,19 @@ void check_ping(Client *client)
SetPingSent(client);
ClearPingWarning(client);
/* not nice but does the job */
- client->local->lasttime = TStime() - ping;
+ client->local->last_msg_received = TStime() - ping;
sendto_one(client, NULL, "PING :%s", me.name);
}
else if (!IsPingWarning(client) && PINGWARNING > 0 &&
(IsServer(client) || IsHandshake(client) || IsConnecting(client) ||
IsTLSConnectHandshake(client)) &&
- (TStime() - client->local->lasttime) >= (ping + PINGWARNING))
+ (TStime() - client->local->last_msg_received) >= (ping + PINGWARNING))
{
SetPingWarning(client);
- sendto_realops("Warning, no response from %s for %d seconds",
- get_client_name(client, FALSE), PINGWARNING);
+ unreal_log(ULOG_WARNING, "link", "LINK_UNRELIABLE", client,
+ "Warning, no response from $client for $time_delta seconds",
+ log_data_integer("time_delta", PINGWARNING),
+ client->server->conf ? log_data_link_block(client->server->conf) : NULL);
}
return;
@@ -496,9 +423,6 @@ EVENT(check_deadsockets)
/* No need to notify opers here. It's already done when dead socket is set */
if (IsDeadSocket(client))
{
-#ifdef DEBUGMODE
- ircd_log(LOG_ERROR, "Closing deadsock: %d/%s", client->local->fd, client->name);
-#endif
ClearDeadSocket(client); /* CPR. So we send the error. */
exit_client(client, NULL, client->local->error_str ? client->local->error_str : "Dead socket");
continue;
@@ -510,9 +434,6 @@ EVENT(check_deadsockets)
/* No need to notify opers here. It's already done when dead socket is set */
if (IsDeadSocket(client))
{
-#ifdef DEBUGMODE
- ircd_log(LOG_ERROR, "Closing deadsock: %d/%s", client->local->fd, client->name);
-#endif
ClearDeadSocket(client); /* CPR. So we send the error. */
exit_client(client, NULL, client->local->error_str ? client->local->error_str : "Dead socket");
continue;
@@ -562,21 +483,6 @@ char chess[] = {
85, 110, 114, 101, 97, 108, 0
};
-static void version_check_logerror(char *fmt, ...)
-{
-va_list va;
-char buf[1024];
-
- va_start(va, fmt);
- vsnprintf(buf, sizeof(buf), fmt, va);
- va_end(va);
-#ifndef _WIN32
- fprintf(stderr, "[!!!] %s\n", buf);
-#else
- win_log("[!!!] %s", buf);
-#endif
-}
-
extern void applymeblock(void);
extern MODVAR Event *events;
@@ -595,41 +501,20 @@ void fix_timers(void)
list_for_each_entry(client, &lclient_list, lclient_node)
{
- if (client->local->since > TStime())
- {
- Debug((DEBUG_DEBUG, "fix_timers(): %s: client->local->since %ld -> %ld",
- client->name, client->local->since, TStime()));
- client->local->since = TStime();
- }
- if (client->local->lasttime > TStime())
- {
- Debug((DEBUG_DEBUG, "fix_timers(): %s: client->local->lasttime %ld -> %ld",
- client->name, client->local->lasttime, TStime()));
- client->local->lasttime = TStime();
- }
- if (client->local->last > TStime())
- {
- Debug((DEBUG_DEBUG, "fix_timers(): %s: client->local->last %ld -> %ld",
- client->name, client->local->last, TStime()));
- client->local->last = TStime();
- }
+ if (client->local->fake_lag > TStime())
+ client->local->fake_lag = TStime();
+ if (client->local->last_msg_received > TStime())
+ client->local->last_msg_received = TStime();
+ if (client->local->idle_since > TStime())
+ client->local->idle_since = TStime();
/* users */
if (MyUser(client))
{
- if (client->local->nextnick > TStime())
- {
- Debug((DEBUG_DEBUG, "fix_timers(): %s: client->local->nextnick %ld -> %ld",
- client->name, client->local->nextnick, TStime()));
- client->local->nextnick = TStime();
- }
+ if (client->local->next_nick_allowed > TStime())
+ client->local->next_nick_allowed = TStime();
if (client->local->nexttarget > TStime())
- {
- Debug((DEBUG_DEBUG, "fix_timers(): %s: client->local->nexttarget %ld -> %ld",
- client->name, client->local->nexttarget, TStime()));
client->local->nexttarget = TStime();
- }
-
}
}
@@ -658,7 +543,6 @@ void fix_timers(void)
thr->since = TStime();
}
}
- Debug((DEBUG_DEBUG, "fix_timers(): removed %d throttling item(s)", cnt));
/* Make sure autoconnect for servers still works (lnk->hold) */
for (lnk = conf_link; lnk; lnk = lnk->next)
@@ -668,37 +552,34 @@ void fix_timers(void)
if (lnk->hold > TStime() + t)
{
lnk->hold = TStime() + (t / 2); /* compromise */
- Debug((DEBUG_DEBUG, "fix_timers(): link '%s' hold-time adjusted to %ld", lnk->servername, lnk->hold));
}
}
}
#ifndef _WIN32
+/* Generate 3 cloak keys and print to console */
static void generate_cloakkeys()
{
- /* Generate 3 cloak keys */
-#define GENERATE_CLOAKKEY_MINLEN 50
-#define GENERATE_CLOAKKEY_MAXLEN 60 /* Length of cloak keys to generate. */
- char keyBuf[GENERATE_CLOAKKEY_MAXLEN + 1];
+ #define GENERATE_CLOAKKEY_LEN 80 /* Length of cloak keys to generate. */
+ char keyBuf[GENERATE_CLOAKKEY_LEN + 1];
int keyNum;
- int keyLen;
int charIndex;
short has_upper;
short has_lower;
short has_num;
- fprintf(stderr, "Here are 3 random cloak keys:\n");
+ 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;
- keyLen = (getrandom8() % (GENERATE_CLOAKKEY_MAXLEN - GENERATE_CLOAKKEY_MINLEN + 1)) + GENERATE_CLOAKKEY_MINLEN;
- for (charIndex = 0; charIndex < keyLen; ++charIndex)
+ for (charIndex = 0; charIndex < sizeof(keyBuf)-1; ++charIndex)
{
switch (getrandom8() % 3)
{
@@ -716,14 +597,15 @@ static void generate_cloakkeys()
break;
}
}
- keyBuf[keyLen] = '\0';
+ keyBuf[sizeof(keyBuf)-1] = '\0';
if (has_upper && has_lower && has_num)
- (void)fprintf(stderr, "%s\n", keyBuf);
+ 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
@@ -743,38 +625,35 @@ void detect_timeshift_and_warn(void)
if (oldtimeofday == 0)
oldtimeofday = timeofday; /* pretend everything is ok the first time.. */
- if (mytdiff(timeofday, oldtimeofday) < NEGATIVE_SHIFT_WARN) {
+ if (mytdiff(timeofday, oldtimeofday) < NEGATIVE_SHIFT_WARN)
+ {
/* tdiff = # of seconds of time set backwards (positive number! eg: 60) */
time_t tdiff = oldtimeofday - timeofday;
- ircd_log(LOG_ERROR, "WARNING: Time running backwards! Clock set back ~%lld seconds (%lld -> %lld)",
- (long long)tdiff, (long long)oldtimeofday, (long long)timeofday);
- ircd_log(LOG_ERROR, "[TimeShift] Resetting a few timers to prevent IRCd freeze!");
- sendto_realops("WARNING: Time running backwards! Clock set back ~%lld seconds (%lld -> %lld)",
- (long long)tdiff, (long long)oldtimeofday, (long long)timeofday);
- sendto_realops("Incorrect time for IRC servers is a serious problem. "
- "Time being set backwards (system clock changed) is "
- "even more serious and can cause clients to freeze, channels to be "
- "taken over, and other issues.");
- sendto_realops("Please be sure your clock is always synchronized before "
- "the IRCd is started!");
- sendto_realops("[TimeShift] Resetting a few timers to prevent IRCd freeze!");
+ unreal_log(ULOG_WARNING, "system", "SYSTEM_CLOCK_JUMP_BACKWARDS", NULL,
+ "System clock jumped back in time ~$time_delta seconds ($time_from -> $time_to)\n"
+ "Incorrect time for IRC servers is a serious problem. "
+ "Time being set backwards (system clock changed) is "
+ "even more serious and can cause clients to freeze, channels to be "
+ "taken over, and other issues.\n"
+ "Please be sure your clock is always synchronized before the IRCd is started!",
+ log_data_integer("time_delta", tdiff),
+ log_data_timestamp("time_from", oldtimeofday),
+ log_data_timestamp("time_to", timeofday));
fix_timers();
} else
if (mytdiff(timeofday, oldtimeofday) > POSITIVE_SHIFT_WARN) /* do not set too low or you get false positives */
{
/* tdiff = # of seconds of time set forward (eg: 60) */
time_t tdiff = timeofday - oldtimeofday;
- ircd_log(LOG_ERROR, "WARNING: Time jumped ~%lld seconds ahead! (%lld -> %lld)",
- (long long)tdiff, (long long)oldtimeofday, (long long)timeofday);
- ircd_log(LOG_ERROR, "[TimeShift] Resetting some timers!");
- sendto_realops("WARNING: Time jumped ~%lld seconds ahead! (%lld -> %lld)",
- (long long)tdiff, (long long)oldtimeofday, (long long)timeofday);
- sendto_realops("Incorrect time for IRC servers is a serious problem. "
- "Time being adjusted (by changing the system clock) "
- "more than a few seconds forward/backward can lead to serious issues.");
- sendto_realops("Please be sure your clock is always synchronized before "
- "the IRCd is started!");
- sendto_realops("[TimeShift] Resetting some timers!");
+ unreal_log(ULOG_WARNING, "system", "SYSTEM_CLOCK_JUMP_FORWARDS", NULL,
+ "System clock jumped ~$time_delta seconds forward ($time_from -> $time_to)\n"
+ "Incorrect time for IRC servers is a serious problem. "
+ "Time being adjusted (by changing the system clock) "
+ "more than a few seconds forward/backward can lead to serious issues.\n"
+ "Please be sure your clock is always synchronized before the IRCd is started!",
+ log_data_integer("time_delta", tdiff),
+ log_data_timestamp("time_from", oldtimeofday),
+ log_data_timestamp("time_to", timeofday));
fix_timers();
}
@@ -784,13 +663,11 @@ void detect_timeshift_and_warn(void)
lasthighwarn = timeofday;
if (timeofday - lasthighwarn > 300)
{
- ircd_log(LOG_ERROR, "[TimeShift] The (IRCd) clock was set backwards. "
- "Waiting for time to be OK again. This will be in %lld seconds",
- (long long)(highesttimeofday - timeofday));
- sendto_realops("[TimeShift] The (IRCd) clock was set backwards. Timers, nick- "
- "and channel-timestamps are possibly incorrect. This message will "
- "repeat itself until we catch up with the original time, which will be "
- "in %lld seconds", (long long)(highesttimeofday - timeofday));
+ unreal_log(ULOG_WARNING, "system", "SYSTEM_CLOCK_JUMP_BACKWARDS_PREVIOUSLY", NULL,
+ "The system clock previously went backwards. Waiting for time to be OK again. This will be in $time_delta seconds.",
+ log_data_integer("time_delta", highesttimeofday - timeofday),
+ log_data_timestamp("time_from", highesttimeofday),
+ log_data_timestamp("time_to", timeofday));
lasthighwarn = timeofday;
}
} else {
@@ -909,7 +786,6 @@ int InitUnrealIRCd(int argc, char *argv[])
#else
WSAStartup(wVersionRequested, &wsaData);
#endif
- memset(&StatsZ, 0, sizeof(StatsZ));
setup_signals();
memset(&irccounts, '\0', sizeof(irccounts));
@@ -918,10 +794,10 @@ int InitUnrealIRCd(int argc, char *argv[])
mp_pool_init();
dbuf_init();
initlists();
+ initlist_channels();
-#ifdef USE_LIBCURL
+ early_init_tls();
url_init();
-#endif
tkl_init();
umode_init();
extcmode_init();
@@ -967,7 +843,7 @@ int InitUnrealIRCd(int argc, char *argv[])
#ifndef _WIN32
case 'P':{
short type;
- char *result;
+ const char *result;
srandom(TStime());
type = Auth_FindType(NULL, p);
if (type == -1)
@@ -1001,11 +877,10 @@ int InitUnrealIRCd(int argc, char *argv[])
exit(0);
}
#endif
-#if 1
+#if 0
case 'S':
- //charsys_dump_table(p ? p : "*");
- unrealdb_test();
- exit(0);
+ charsys_dump_table(p ? p : "*");
+ //unrealdb_test();
#endif
#ifndef _WIN32
case 't':
@@ -1065,14 +940,6 @@ int InitUnrealIRCd(int argc, char *argv[])
fprintf(stderr, "It is impossible to get here\n");
exit(0);
}
- case 'U':
- if (chdir(CONFDIR) < 0)
- {
- fprintf(stderr, "Unable to change to '%s' directory\n", CONFDIR);
- exit(1);
- }
- update_conf();
- exit(0);
case 'R':
report_crash();
exit(0);
@@ -1142,7 +1009,8 @@ int InitUnrealIRCd(int argc, char *argv[])
#ifndef _WIN32
fprintf(stderr, "%s", unreallogo);
fprintf(stderr, " v%s\n\n", VERSIONONLY);
- fprintf(stderr, "UnrealIRCd is brought to you by Bram Matthys (Syzop), Gottem and i\n\n");
+ fprintf(stderr, "UnrealIRCd is brought to you by Bram Matthys (Syzop),\n"
+ "Krzysztof Beresztant (k4be), Gottem and i\n\n");
fprintf(stderr, "Using the following libraries:\n");
fprintf(stderr, "* %s\n", SSLeay_version(SSLEAY_VERSION));
@@ -1170,7 +1038,7 @@ int InitUnrealIRCd(int argc, char *argv[])
(void)chmod(CPATH, DEFAULT_PERMISSIONS);
#endif
init_dynconf();
- early_init_ssl();
+ init_sys();
/*
* Add default class
*/
@@ -1181,10 +1049,17 @@ int InitUnrealIRCd(int argc, char *argv[])
default_class->sendq = DEFAULT_RECVQ;
default_class->name = "default";
AddListItem(default_class, conf_class);
- if (init_conf(configfile, 0) < 0)
- {
+ if (config_read_start() < 0)
exit(-1);
+ while (!is_config_read_finished())
+ {
+ gettimeofday(&timeofday_tv, NULL);
+ timeofday = timeofday_tv.tv_sec;
+ url_socket_timeout(NULL);
+ fd_select(500);
}
+ if (config_test() < 0)
+ exit(-1);
booted = TRUE;
load_tunefile();
make_umodestr();
@@ -1192,7 +1067,6 @@ int InitUnrealIRCd(int argc, char *argv[])
me.local->fd = -1;
SetMe(&me);
make_server(&me);
- extcmodes_check_for_changes();
umodes_check_for_changes();
charsys_check_for_changes();
clicap_init();
@@ -1202,37 +1076,30 @@ int InitUnrealIRCd(int argc, char *argv[])
exit(-4);
}
-#ifndef _WIN32
- fprintf(stderr, "Initializing TLS..\n");
-#endif
- if (!init_ssl())
+ if (!init_tls())
{
- config_error("Failed to load SSL/TLS (see errors above). UnrealIRCd can not start.");
+ config_error("Failed to load TLS (see errors above). UnrealIRCd can not start.");
#ifdef _WIN32
win_error(); /* display error dialog box */
#endif
exit(9);
}
+ unreal_log(ULOG_INFO, "config", "CONFIG_PASSED", NULL, "Configuration test passed OK");
if (loop.config_test)
{
- ircd_log(LOG_ERROR, "Configuration test passed OK");
fflush(stderr);
exit(0);
}
if (loop.boot_function)
loop.boot_function();
-#ifndef _WIN32
- fprintf(stderr, "Dynamic configuration initialized.. booting IRCd.\n");
-#endif
open_debugfile();
me.local->port = 6667; /* pointless? */
- init_sys();
applymeblock();
#ifdef HAVE_SYSLOG
openlog("ircd", LOG_PID | LOG_NDELAY, LOG_DAEMON);
#endif
- run_configuration();
- ircd_log(LOG_ERROR, "UnrealIRCd started.");
+ config_run();
+ unreal_log(ULOG_INFO, "main", "UNREALIRCD_START", NULL, "UnrealIRCd started.");
read_motd(conf_files->botmotd_file, &botmotd);
read_motd(conf_files->rules_file, &rules);
@@ -1250,11 +1117,10 @@ int InitUnrealIRCd(int argc, char *argv[])
* This listener will never go away
*/
me_hash = find_or_add(me.name);
- me.serv->up = me_hash;
timeofday = time(NULL);
- me.local->lasttime = me.local->since = me.local->firsttime = me.serv->boottime = TStime();
- me.serv->features.protocol = UnrealProtocol;
- safe_strdup(me.serv->features.software, version);
+ me.local->last_msg_received = me.local->fake_lag = me.local->creationtime = me.server->boottime = TStime();
+ me.server->features.protocol = UnrealProtocol;
+ safe_strdup(me.server->features.software, version);
add_to_client_hash_table(me.name, &me);
add_to_id_hash_table(me.id, &me);
list_add(&me.client_node, &global_server_list);
@@ -1277,18 +1143,16 @@ int InitUnrealIRCd(int argc, char *argv[])
/* Background process (child) continues below... */
close_std_descriptors();
fd_fork();
- loop.ircd_forked = 1;
+ loop.forked = 1;
}
#endif
#ifdef _WIN32
- loop.ircd_forked = 1;
+ loop.forked = 1;
#endif
fix_timers();
write_pidfile();
- Debug((DEBUG_NOTICE, "Server ready..."));
- init_throttling();
- loop.ircd_booted = 1;
+ loop.booted = 1;
#if defined(HAVE_SETPROCTITLE)
setproctitle("%s", me.name);
#elif defined(HAVE_PSTAT)
@@ -1346,7 +1210,7 @@ void SocketLoop(void *dummy)
*/
if (dorehash)
{
- (void)rehash(&me, 1);
+ request_rehash(NULL);
dorehash = 0;
}
if (dorestart)
@@ -1355,7 +1219,8 @@ void SocketLoop(void *dummy)
}
if (doreloadcert)
{
- reinit_ssl(NULL);
+ unreal_log(ULOG_INFO, "config", "CONFIG_RELOAD_TLS", NULL, "Reloading all TLS related data (./unrealircd reloadtls)");
+ reinit_tls();
doreloadcert = 0;
}
}
@@ -1408,9 +1273,6 @@ static void open_debugfile(void)
else
# endif
strlcpy(client->name, "FD2-Pipe", sizeof(client->name));
- Debug((DEBUG_FATAL,
- "Debug: File <%s> Level: %d at %s", client->name,
- client->local->port, myctime(time(NULL))));
}
#endif
}
diff --git a/src/list.c b/src/list.c
index 7007378..d752fb8 100644
--- a/src/list.c
+++ b/src/list.c
@@ -104,14 +104,14 @@ Client *make_client(Client *from, Client *servr)
/* Note: all fields are already NULL/0, no need to set here */
client->direction = from ? from : client; /* 'from' of local client is self! */
- client->srvptr = servr;
+ client->uplink = servr;
client->status = CLIENT_STATUS_UNKNOWN;
INIT_LIST_HEAD(&client->client_node);
INIT_LIST_HEAD(&client->client_hash);
INIT_LIST_HEAD(&client->id_hash);
- strcpy(client->ident, "unknown");
+ strlcpy(client->ident, "unknown", sizeof(client->ident));
if (!from)
{
/* Local client */
@@ -123,9 +123,9 @@ Client *make_client(Client *from, Client *servr)
INIT_LIST_HEAD(&client->lclient_node);
INIT_LIST_HEAD(&client->special_node);
- client->local->since = client->local->lasttime =
- client->lastnick = client->local->firsttime =
- client->local->last = TStime();
+ client->local->fake_lag = client->local->last_msg_received =
+ client->lastnick = client->local->creationtime =
+ client->local->idle_since = TStime();
client->local->class = NULL;
client->local->passwd = NULL;
client->local->sockhost[0] = '\0';
@@ -197,7 +197,7 @@ User *make_user(Client *client)
#ifdef DEBUGMODE
users.inuse++;
#endif
- strlcpy(user->svid, "0", sizeof(user->svid));
+ strlcpy(user->account, "0", sizeof(user->account));
if (client->ip)
{
/* initially set client->user->realhost to IP */
@@ -213,7 +213,7 @@ User *make_user(Client *client)
Server *make_server(Client *client)
{
- Server *serv = client->serv;
+ Server *serv = client->server;
if (!serv)
{
@@ -223,8 +223,7 @@ Server *make_server(Client *client)
#endif
*serv->by = '\0';
serv->users = 0;
- serv->up = NULL;
- client->serv = serv;
+ client->server = serv;
}
if (strlen(client->id) > 3)
{
@@ -234,7 +233,7 @@ Server *make_server(Client *client)
del_from_id_hash_table(client->id, client);
*client->id = '\0';
}
- return client->serv;
+ return client->server;
}
/*
@@ -260,6 +259,7 @@ void free_user(Client *client)
}
safe_free(client->user->virthost);
safe_free(client->user->operlogin);
+ safe_free(client->user->snomask);
mp_pool_release(client->user);
#ifdef DEBUGMODE
users.inuse--;
@@ -297,8 +297,8 @@ void remove_client_from_list(Client *client)
VERIFY_OPERCOUNT(client, "rmvlist");
}
irccounts.clients--;
- if (client->srvptr && client->srvptr->serv)
- client->srvptr->serv->users--;
+ if (client->uplink && client->uplink->server)
+ client->uplink->server->users--;
}
if (IsUnknown(client) || IsConnecting(client) || IsHandshake(client)
|| IsTLSHandshake(client)
@@ -313,16 +313,16 @@ void remove_client_from_list(Client *client)
if (client->user)
free_user(client);
- if (client->serv)
+ if (client->server)
{
- safe_free(client->serv->features.usermodes);
- safe_free(client->serv->features.chanmodes[0]);
- safe_free(client->serv->features.chanmodes[1]);
- safe_free(client->serv->features.chanmodes[2]);
- safe_free(client->serv->features.chanmodes[3]);
- safe_free(client->serv->features.software);
- safe_free(client->serv->features.nickchars);
- safe_free(client->serv);
+ safe_free(client->server->features.usermodes);
+ safe_free(client->server->features.chanmodes[0]);
+ safe_free(client->server->features.chanmodes[1]);
+ safe_free(client->server->features.chanmodes[2]);
+ safe_free(client->server->features.chanmodes[3]);
+ safe_free(client->server->features.software);
+ safe_free(client->server->features.nickchars);
+ safe_free(client->server);
#ifdef DEBUGMODE
servs.inuse--;
#endif
@@ -383,6 +383,16 @@ void free_link(Link *lp)
#endif
}
+/** Returns the length (entry count) of a +beI list */
+int link_list_length(Link *lp)
+{
+ int count = 0;
+
+ for (; lp; lp = lp->next)
+ count++;
+ return count;
+}
+
Ban *make_ban(void)
{
Ban *lp;
@@ -491,7 +501,7 @@ void add_ListItemPrio(ListStructPrio *new, ListStructPrio **list, int priority)
/* NameList functions */
-void _add_name_list(NameList **list, char *name)
+void _add_name_list(NameList **list, const char *name)
{
NameList *e = safe_alloc(sizeof(NameList)+strlen(name));
strcpy(e->name, name); /* safe, allocated above */
@@ -509,7 +519,7 @@ void _free_entire_name_list(NameList *n)
}
}
-void _del_name_list(NameList **list, char *name)
+void _del_name_list(NameList **list, const char *name)
{
NameList *e = find_name_list(*list, name);
if (e)
@@ -523,7 +533,7 @@ void _del_name_list(NameList **list, char *name)
/** Find an entry in a NameList - case insensitive comparisson.
* @ingroup ListFunctions
*/
-NameList *find_name_list(NameList *list, char *name)
+NameList *find_name_list(NameList *list, const char *name)
{
NameList *e;
@@ -540,7 +550,7 @@ NameList *find_name_list(NameList *list, char *name)
/** Find an entry in a NameList by running match_simple() on it.
* @ingroup ListFunctions
*/
-NameList *find_name_list_match(NameList *list, char *name)
+NameList *find_name_list_match(NameList *list, const char *name)
{
NameList *e;
@@ -554,7 +564,7 @@ NameList *find_name_list_match(NameList *list, char *name)
return NULL;
}
-void add_nvplist(NameValuePrioList **lst, int priority, char *name, char *value)
+void add_nvplist(NameValuePrioList **lst, int priority, const char *name, const char *value)
{
va_list vl;
NameValuePrioList *e = safe_alloc(sizeof(NameValuePrioList));
@@ -564,7 +574,7 @@ void add_nvplist(NameValuePrioList **lst, int priority, char *name, char *value)
AddListItemPrio(e, *lst, priority);
}
-NameValuePrioList *find_nvplist(NameValuePrioList *list, char *name)
+NameValuePrioList *find_nvplist(NameValuePrioList *list, const char *name)
{
NameValuePrioList *e;
@@ -578,7 +588,7 @@ NameValuePrioList *find_nvplist(NameValuePrioList *list, char *name)
return NULL;
}
-void add_fmt_nvplist(NameValuePrioList **lst, int priority, char *name, FORMAT_STRING(const char *format), ...)
+void add_fmt_nvplist(NameValuePrioList **lst, int priority, const char *name, FORMAT_STRING(const char *format), ...)
{
char value[512];
va_list vl;
@@ -603,3 +613,37 @@ void free_nvplist(NameValuePrioList *lst)
safe_free(e);
}
}
+
+#define nv_find_by_name(stru, name) do_nv_find_by_name(stru, name, ARRAY_SIZEOF((stru)))
+
+long do_nv_find_by_name(NameValue *table, const char *cmd, int numelements)
+{
+ int start = 0;
+ int stop = numelements-1;
+ int mid;
+ while (start <= stop) {
+ mid = (start+stop)/2;
+
+ if (smycmp(cmd,table[mid].name) < 0) {
+ stop = mid-1;
+ }
+ else if (strcmp(cmd,table[mid].name) == 0) {
+ return table[mid].value;
+ }
+ else
+ start = mid+1;
+ }
+ return 0;
+}
+
+#define nv_find_by_value(stru, value) do_nv_find_by_value(stru, value, ARRAY_SIZEOF((stru)))
+const char *do_nv_find_by_value(NameValue *table, long value, int numelements)
+{
+ int i;
+
+ for (i=0; i < numelements; i++)
+ if (table[i].value == value)
+ return table[i].name;
+
+ return NULL;
+}
diff --git a/src/log.c b/src/log.c
new file mode 100644
index 0000000..d21dabb
--- /dev/null
+++ b/src/log.c
@@ -0,0 +1,1871 @@
+/************************************************************************
+ * IRC - Internet Relay Chat, src/api-channelmode.c
+ * (C) 2021 Bram Matthys (Syzop) 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 The logging API
+ */
+
+#define UNREAL_LOGGER_CODE
+#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
+
+/* Variables */
+Log *logs[NUM_LOG_DESTINATIONS] = { NULL, NULL, NULL, NULL, NULL };
+Log *temp_logs[NUM_LOG_DESTINATIONS] = { NULL, NULL, NULL, NULL, NULL };
+static int snomask_num_destinations = 0;
+
+static char snomasks_in_use[257] = { '\0' };
+static char snomasks_in_use_testing[257] = { '\0' };
+
+/* Forward declarations */
+int log_sources_match(LogSource *logsource, LogLevel loglevel, const char *subsystem, const char *event_id, int matched_already);
+void do_unreal_log_internal(LogLevel loglevel, const char *subsystem, const char *event_id, Client *client, int expand_msg, const char *msg, va_list vl);
+void log_blocks_switchover(void);
+
+/** Convert a regular string value to a JSON string.
+ * In UnrealIRCd, this must be used instead of json_string()
+ * as we may use non-UTF8 sequences. Also, this takes care
+ * of using json_null() if the string was NULL, which is
+ * usually what we want as well.
+ * @param s Input string
+ * @returns a json string value or json null value.
+ */
+json_t *json_string_unreal(const char *s)
+{
+ static char buf[8192];
+ char *verified_s;
+
+ if (s == NULL)
+ return json_null();
+
+ verified_s = unrl_utf8_make_valid(s, buf, sizeof(buf), 0);
+ return json_string(verified_s);
+}
+
+#define json_string __BAD___DO__NOT__USE__JSON__STRING__PLZ
+
+json_t *json_timestamp(time_t v)
+{
+ const char *ts = timestamp_iso8601(v);
+ if (ts)
+ return json_string_unreal(ts);
+ return json_null();
+}
+
+LogType log_type_stringtoval(const char *str)
+{
+ if (!strcmp(str, "json"))
+ return LOG_TYPE_JSON;
+ if (!strcmp(str, "text"))
+ return LOG_TYPE_TEXT;
+ return LOG_TYPE_INVALID;
+}
+
+const char *log_type_valtostring(LogType v)
+{
+ switch(v)
+ {
+ case LOG_TYPE_TEXT:
+ return "text";
+ case LOG_TYPE_JSON:
+ return "json";
+ default:
+ return NULL;
+ }
+}
+
+/***** CONFIGURATION ******/
+
+LogSource *add_log_source(const char *str)
+{
+ LogSource *ls;
+ char buf[256];
+ char *p;
+ LogLevel loglevel = ULOG_INVALID;
+ char *subsystem = NULL;
+ char *event_id = NULL;
+ int negative = 0;
+
+ if (*str == '!')
+ {
+ negative = 1;
+ strlcpy(buf, str+1, sizeof(buf));
+ } else
+ {
+ strlcpy(buf, str, sizeof(buf));
+ }
+
+ p = strchr(buf, '.');
+ if (p)
+ *p++ = '\0';
+
+ loglevel = log_level_stringtoval(buf);
+ if (loglevel == ULOG_INVALID)
+ {
+ if (isupper(*buf))
+ event_id = buf;
+ else
+ subsystem = buf;
+ }
+ if (p)
+ {
+ if (isupper(*p))
+ {
+ event_id = p;
+ } else
+ if (loglevel == ULOG_INVALID)
+ {
+ loglevel = log_level_stringtoval(p);
+ if ((loglevel == ULOG_INVALID) && !subsystem)
+ subsystem = p;
+ } else if (!subsystem)
+ {
+ subsystem = p;
+ }
+ }
+ ls = safe_alloc(sizeof(LogSource));
+ ls->loglevel = loglevel;
+ ls->negative = negative;
+ if (!BadPtr(subsystem))
+ strlcpy(ls->subsystem, subsystem, sizeof(ls->subsystem));
+ if (!BadPtr(event_id))
+ strlcpy(ls->event_id, event_id, sizeof(ls->event_id));
+
+ return ls;
+}
+
+void free_log_source(LogSource *l)
+{
+ safe_free(l);
+}
+
+void free_log_sources(LogSource *l)
+{
+ LogSource *l_next;
+ for (; l; l = l_next)
+ {
+ l_next = l->next;
+ free_log_source(l);
+ }
+}
+
+int config_test_log(ConfigFile *conf, ConfigEntry *block)
+{
+ int errors = 0;
+ int any_sources = 0;
+ ConfigEntry *ce, *cep, *cepp;
+ int destinations = 0;
+
+ for (ce = block->items; ce; ce = ce->next)
+ {
+ if (!strcmp(ce->name, "source"))
+ {
+ for (cep = ce->items; cep; cep = cep->next)
+ {
+ /* TODO: Validate the sources lightly for formatting issues */
+ any_sources = 1;
+ }
+ }
+ if (!strcmp(ce->name, "destination"))
+ {
+ for (cep = ce->items; cep; cep = cep->next)
+ {
+ if (!strcmp(cep->name, "snomask"))
+ {
+ destinations++;
+ snomask_num_destinations++;
+ /* We need to validate the parameter here as well */
+ if (!cep->value)
+ {
+ config_error_blank(cep->file->filename, cep->line_number, "set::logging::snomask");
+ errors++;
+ } else
+ if ((strlen(cep->value) != 1) || !(islower(cep->value[0]) || isupper(cep->value[0])))
+ {
+ config_error("%s:%d: snomask must be a single letter",
+ cep->file->filename, cep->line_number);
+ errors++;
+ } else {
+ strlcat(snomasks_in_use_testing, cep->value, sizeof(snomasks_in_use_testing));
+ }
+ } else
+ if (!strcmp(cep->name, "channel"))
+ {
+ destinations++;
+ /* We need to validate the parameter here as well */
+ if (!cep->value)
+ {
+ config_error_blank(cep->file->filename, cep->line_number, "set::logging::channel");
+ errors++;
+ } else
+ if (!valid_channelname(cep->value))
+ {
+ config_error("%s:%d: Invalid channel name '%s'",
+ cep->file->filename, cep->line_number, cep->value);
+ errors++;
+ }
+ } else
+ if (!strcmp(cep->name, "file"))
+ {
+ destinations++;
+ if (!cep->value)
+ {
+ config_error_blank(cep->file->filename, cep->line_number, "set::logging::file");
+ errors++;
+ continue;
+ }
+ convert_to_absolute_path(&cep->value, LOGDIR);
+ for (cepp = cep->items; cepp; cepp = cepp->next)
+ {
+ if (!strcmp(cepp->name, "type"))
+ {
+ if (!cepp->value)
+ {
+ config_error_empty(cepp->file->filename,
+ cepp->line_number, "log", cepp->name);
+ errors++;
+ continue;
+ }
+ if (!log_type_stringtoval(cepp->value))
+ {
+ config_error("%s:%i: unknown log type '%s'",
+ cepp->file->filename, cepp->line_number,
+ cepp->value);
+ errors++;
+ }
+ } else
+ if (!strcmp(cepp->name, "maxsize"))
+ {
+ if (!cepp->value)
+ {
+ config_error_empty(cepp->file->filename,
+ cepp->line_number, "log", cepp->name);
+ errors++;
+ }
+ } else
+ {
+ config_error_unknown(cepp->file->filename, cepp->line_number, "log::destination::file", cepp->name);
+ errors++;
+ }
+ }
+ } else
+ if (!strcmp(cep->name, "remote"))
+ {
+ destinations++;
+ } else
+ if (!strcmp(cep->name, "syslog"))
+ {
+ destinations++;
+ for (cepp = cep->items; cepp; cepp = cepp->next)
+ {
+ if (!strcmp(cepp->name, "type"))
+ {
+ if (!cepp->value)
+ {
+ config_error_empty(cepp->file->filename,
+ cepp->line_number, "log", cepp->name);
+ errors++;
+ continue;
+ }
+ if (!log_type_stringtoval(cepp->value))
+ {
+ config_error("%s:%i: unknown log type '%s'",
+ cepp->file->filename, cepp->line_number,
+ cepp->value);
+ errors++;
+ }
+ } else
+ {
+ config_error_unknown(cepp->file->filename, cepp->line_number, "log::destination::syslog", cepp->name);
+ errors++;
+ }
+ }
+ } else
+ {
+ config_error_unknownopt(cep->file->filename, cep->line_number, "log::destination", cep->name);
+ errors++;
+ continue;
+ }
+ }
+ }
+ }
+
+ if (!any_sources && !destinations)
+ {
+ unreal_log(ULOG_ERROR, "config", "CONFIG_OLD_LOG_BLOCK", NULL,
+ "$config_file:$line_number: Your log block contains no sources and no destinations.\n"
+ "The log block changed between UnrealIRCd 5 and UnrealIRCd 6, "
+ "see https://www.unrealircd.org/docs/FAQ#old-log-block on how "
+ "to convert it to the new syntax.",
+ log_data_string("config_file", block->file->filename),
+ log_data_integer("line_number", block->line_number));
+ errors++;
+ return errors;
+ }
+
+ if (!any_sources)
+ {
+ config_error("%s:%d: log block contains no sources. Old log block perhaps?",
+ block->file->filename, block->line_number);
+ errors++;
+ }
+ if (destinations == 0)
+ {
+ config_error("%s:%d: log block contains no destinations. Old log block perhaps?",
+ block->file->filename, block->line_number);
+ errors++;
+ }
+ if (destinations > 1)
+ {
+ config_error("%s:%d: log block contains multiple destinations. This is not support... YET!",
+ block->file->filename, block->line_number);
+ errors++;
+ }
+ return errors;
+}
+
+int config_run_log(ConfigFile *conf, ConfigEntry *block)
+{
+ ConfigEntry *ce, *cep, *cepp;
+ LogSource *sources = NULL;
+ int type;
+
+ /* If we later allow multiple destination entries later,
+ * then we need to 'clone' sources or work with reference counts.
+ */
+
+ /* First, gather the source... */
+ for (ce = block->items; ce; ce = ce->next)
+ {
+ if (!strcmp(ce->name, "source"))
+ {
+ LogSource *s;
+ for (cep = ce->items; cep; cep = cep->next)
+ {
+ s = add_log_source(cep->name);
+ AddListItem(s, sources);
+ }
+ }
+ }
+
+ /* Now deal with destinations... */
+ for (ce = block->items; ce; ce = ce->next)
+ {
+ if (!strcmp(ce->name, "destination"))
+ {
+ for (cep = ce->items; cep; cep = cep->next)
+ {
+ if (!strcmp(cep->name, "snomask"))
+ {
+ Log *log = safe_alloc(sizeof(Log));
+ strlcpy(log->destination, cep->value, sizeof(log->destination)); /* destination is the snomask */
+ strlcat(snomasks_in_use, cep->value, sizeof(snomasks_in_use));
+ log->sources = sources;
+ if (!strcmp(cep->value, "s"))
+ AddListItem(log, temp_logs[LOG_DEST_OPER]);
+ else
+ AddListItem(log, temp_logs[LOG_DEST_SNOMASK]);
+ } else
+ if (!strcmp(cep->name, "channel"))
+ {
+ Log *log = safe_alloc(sizeof(Log));
+ strlcpy(log->destination, cep->value, sizeof(log->destination)); /* destination is the channel */
+ log->sources = sources;
+ AddListItem(log, temp_logs[LOG_DEST_CHANNEL]);
+ } else
+ if (!strcmp(cep->name, "remote"))
+ {
+ Log *log = safe_alloc(sizeof(Log));
+ /* destination stays empty */
+ log->sources = sources;
+ AddListItem(log, temp_logs[LOG_DEST_REMOTE]);
+ } else
+ if (!strcmp(cep->name, "file") || !strcmp(cep->name, "syslog"))
+ {
+ Log *log;
+ /* First check if already exists... yeah this is a bit late
+ * and ideally would have been done in config_test but...
+ * that would have been lots of work for a (hopefully) rare case.
+ */
+ for (log = temp_logs[LOG_DEST_DISK]; log; log = log->next)
+ {
+ if ((log->file && !strcmp(log->file, cep->value)) ||
+ (log->filefmt && !strcmp(log->filefmt, cep->value)))
+ {
+ config_warn("%s:%d: Ignoring duplicate log block for file '%s'. "
+ "You cannot have multiple log blocks logging to the same file.",
+ cep->file->filename, cep->line_number,
+ cep->value);
+ free_log_sources(sources);
+ return 0;
+ }
+ }
+ log = safe_alloc(sizeof(Log));
+ log->sources = sources;
+ log->logfd = -1;
+ log->type = LOG_TYPE_TEXT; /* default */
+ if (!strcmp(cep->name, "syslog"))
+ safe_strdup(log->file, "syslog");
+ else if (strchr(cep->value, '%'))
+ safe_strdup(log->filefmt, cep->value);
+ else
+ safe_strdup(log->file, cep->value);
+ for (cepp = cep->items; cepp; cepp = cepp->next)
+ {
+ if (!strcmp(cepp->name, "maxsize"))
+ {
+ log->maxsize = config_checkval(cepp->value,CFG_SIZE);
+ }
+ else if (!strcmp(cepp->name, "type"))
+ {
+ log->type = log_type_stringtoval(cepp->value);
+ }
+ }
+ AddListItem(log, temp_logs[LOG_DEST_DISK]);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+
+
+/***** RUNTIME *****/
+
+void json_expand_client_security_groups(json_t *parent, Client *client)
+{
+ SecurityGroup *s;
+ json_t *child = json_array();
+ json_object_set_new(parent, "security-groups", child);
+
+ /* We put known-users or unknown-users at the beginning.
+ * The latter is special and doesn't actually exist
+ * in the linked list, hence the special code here,
+ * and again later in the for loop to skip it.
+ */
+ if (user_allowed_by_security_group_name(client, "known-users"))
+ json_array_append_new(child, json_string_unreal("known-users"));
+ else
+ json_array_append_new(child, json_string_unreal("unknown-users"));
+
+ for (s = securitygroups; s; s = s->next)
+ if (strcmp(s->name, "known-users") && user_allowed_by_security_group(client, s))
+ json_array_append_new(child, json_string_unreal(s->name));
+}
+
+void json_expand_client(json_t *j, const char *key, Client *client, int detail)
+{
+ char buf[BUFSIZE+1];
+ json_t *child = json_object();
+ json_t *user = NULL;
+ json_object_set_new(j, key, child);
+
+ /* First the information that is available for ALL client types: */
+
+ json_object_set_new(child, "name", json_string_unreal(client->name));
+ json_object_set_new(child, "id", json_string_unreal(client->id));
+
+ /* hostname is available for all, it just depends a bit on whether it is DNS or IP */
+ if (client->user && *client->user->realhost)
+ json_object_set_new(child, "hostname", json_string_unreal(client->user->realhost));
+ else if (client->local && *client->local->sockhost)
+ json_object_set_new(child, "hostname", json_string_unreal(client->local->sockhost));
+ else
+ json_object_set_new(child, "hostname", json_string_unreal(GetIP(client)));
+
+ /* 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));
+
+ /* client.details is always available: it is nick!user@host, nick@host, server@host
+ * server@ip, or just server.
+ */
+ if (client->user)
+ {
+ snprintf(buf, sizeof(buf), "%s!%s@%s", client->name, client->user->username, client->user->realhost);
+ json_object_set_new(child, "details", json_string_unreal(buf));
+ } else if (client->ip) {
+ if (*client->name)
+ snprintf(buf, sizeof(buf), "%s@%s", client->name, client->ip);
+ else
+ snprintf(buf, sizeof(buf), "[%s]", client->ip);
+ json_object_set_new(child, "details", json_string_unreal(buf));
+ } else {
+ json_object_set_new(child, "details", json_string_unreal(client->name));
+ }
+
+ if (client->local && client->local->creationtime)
+ json_object_set_new(child, "connected_since", json_timestamp(client->local->creationtime));
+
+ if (client->user)
+ {
+ char buf[512];
+ const char *str;
+ /* client.user */
+ user = json_object();
+ json_object_set_new(child, "user", user);
+
+ json_object_set_new(user, "username", json_string_unreal(client->user->username));
+ if (!BadPtr(client->info))
+ json_object_set_new(user, "realname", json_string_unreal(client->info));
+ if (client->uplink)
+ json_object_set_new(user, "servername", json_string_unreal(client->uplink->name));
+ if (IsLoggedIn(client))
+ json_object_set_new(user, "account", json_string_unreal(client->user->account));
+ json_object_set_new(user, "reputation", json_integer(GetReputation(client)));
+ json_expand_client_security_groups(user, client);
+
+ /* user modes and snomasks */
+ get_usermode_string_r(client, buf, sizeof(buf));
+ json_object_set_new(user, "modes", json_string_unreal(buf+1));
+ if (client->user->snomask)
+ json_object_set_new(user, "snomasks", json_string_unreal(client->user->snomask));
+
+ /* if oper then we can possibly expand a bit more */
+ str = get_operlogin(client);
+ if (str)
+ json_object_set_new(user, "operlogin", json_string_unreal(str));
+ str = get_operclass(client);
+ if (str)
+ json_object_set_new(user, "operclass", json_string_unreal(str));
+ } else
+ if (IsMe(client))
+ {
+ json_t *server = json_object();
+ json_t *features;
+
+ /* client.server */
+ json_object_set_new(child, "server", server);
+
+ if (!BadPtr(client->info))
+ json_object_set_new(server, "info", json_string_unreal(client->info));
+ json_object_set_new(server, "num_users", json_integer(client->server->users));
+ json_object_set_new(server, "boot_time", json_timestamp(client->server->boottime));
+ } else
+ if (IsServer(client) && client->server)
+ {
+ /* client.server */
+
+ /* Whenever a server is expanded, which is rare,
+ * we should probably expand as much as info as possible:
+ */
+ json_t *server = json_object();
+ json_t *features;
+
+ /* client.server */
+ json_object_set_new(child, "server", server);
+ if (!BadPtr(client->info))
+ json_object_set_new(server, "info", json_string_unreal(client->info));
+ if (client->uplink)
+ json_object_set_new(server, "uplink", json_string_unreal(client->uplink->name));
+ json_object_set_new(server, "num_users", json_integer(client->server->users));
+ json_object_set_new(server, "boot_time", json_timestamp(client->server->boottime));
+ json_object_set_new(server, "synced", json_boolean(client->server->flags.synced));
+
+ /* client.server.features */
+ features = json_object();
+ json_object_set_new(server, "features", features);
+ if (!BadPtr(client->server->features.software))
+ json_object_set_new(features, "software", json_string_unreal(client->server->features.software));
+ json_object_set_new(features, "protocol", json_integer(client->server->features.protocol));
+ if (!BadPtr(client->server->features.usermodes))
+ json_object_set_new(features, "usermodes", json_string_unreal(client->server->features.usermodes));
+ if (!BadPtr(client->server->features.chanmodes[0]))
+ {
+ /* client.server.features.chanmodes (array) */
+ int i;
+ json_t *chanmodes = json_array();
+ json_object_set_new(features, "chanmodes", chanmodes);
+ for (i=0; i < 4; i++)
+ json_array_append_new(chanmodes, json_string_unreal(client->server->features.chanmodes[i]));
+ }
+ if (!BadPtr(client->server->features.nickchars))
+ json_object_set_new(features, "nick_character_sets", json_string_unreal(client->server->features.nickchars));
+ }
+}
+
+void json_expand_channel(json_t *j, const char *key, Channel *channel, int detail)
+{
+ char mode1[512], mode2[512], modes[512];
+
+ json_t *child = json_object();
+ json_object_set_new(j, key, child);
+ json_object_set_new(child, "name", json_string_unreal(channel->name));
+ json_object_set_new(child, "creation_time", json_timestamp(channel->creationtime));
+ json_object_set_new(child, "num_users", json_integer(channel->users));
+ if (channel->topic)
+ {
+ json_object_set_new(child, "topic", json_string_unreal(channel->topic));
+ json_object_set_new(child, "topic_set_by", json_string_unreal(channel->topic_nick));
+ json_object_set_new(child, "topic_set_at", json_timestamp(channel->topic_time));
+ }
+
+ /* Add "mode" too */
+ channel_modes(NULL, mode1, mode2, sizeof(mode1), sizeof(mode2), channel, 0);
+ if (*mode2)
+ {
+ snprintf(modes, sizeof(modes), "%s %s", mode1+1, mode2);
+ json_object_set_new(child, "modes", json_string_unreal(modes));
+ } else {
+ json_object_set_new(child, "modes", json_string_unreal(mode1+1));
+ }
+
+ // Possibly later: If detail is set to 1 then expand more...
+}
+
+const char *timestamp_iso8601_now(void)
+{
+ struct timeval t;
+ struct tm *tm;
+ time_t sec;
+ static char buf[64];
+
+ gettimeofday(&t, NULL);
+ sec = t.tv_sec;
+ tm = gmtime(&sec);
+
+ snprintf(buf, sizeof(buf), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ",
+ tm->tm_year + 1900,
+ tm->tm_mon + 1,
+ tm->tm_mday,
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec,
+ (int)(t.tv_usec / 1000));
+
+ return buf;
+}
+
+const char *timestamp_iso8601(time_t v)
+{
+ struct tm *tm;
+ static char buf[64];
+
+ if (v == 0)
+ return NULL;
+
+ tm = gmtime(&v);
+
+ if (tm == NULL)
+ return NULL;
+
+ snprintf(buf, sizeof(buf), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ",
+ tm->tm_year + 1900,
+ tm->tm_mon + 1,
+ tm->tm_mday,
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec,
+ 0);
+
+ return buf;
+}
+
+LogData *log_data_string(const char *key, const char *str)
+{
+ LogData *d = safe_alloc(sizeof(LogData));
+ d->type = LOG_FIELD_STRING;
+ safe_strdup(d->key, key);
+ safe_strdup(d->value.string, str);
+ return d;
+}
+
+LogData *log_data_char(const char *key, const char c)
+{
+ LogData *d = safe_alloc(sizeof(LogData));
+ d->type = LOG_FIELD_STRING;
+ safe_strdup(d->key, key);
+ d->value.string = safe_alloc(2);
+ d->value.string[0] = c;
+ d->value.string[1] = '\0';
+ return d;
+}
+
+LogData *log_data_integer(const char *key, int64_t integer)
+{
+ LogData *d = safe_alloc(sizeof(LogData));
+ d->type = LOG_FIELD_INTEGER;
+ safe_strdup(d->key, key);
+ d->value.integer = integer;
+ return d;
+}
+
+LogData *log_data_timestamp(const char *key, time_t ts)
+{
+ LogData *d = safe_alloc(sizeof(LogData));
+ d->type = LOG_FIELD_STRING;
+ safe_strdup(d->key, key);
+ safe_strdup(d->value.string, timestamp_iso8601(ts));
+ return d;
+}
+
+LogData *log_data_client(const char *key, Client *client)
+{
+ LogData *d = safe_alloc(sizeof(LogData));
+ d->type = LOG_FIELD_CLIENT;
+ safe_strdup(d->key, key);
+ d->value.client = client;
+ return d;
+}
+
+LogData *log_data_channel(const char *key, Channel *channel)
+{
+ LogData *d = safe_alloc(sizeof(LogData));
+ d->type = LOG_FIELD_CHANNEL;
+ safe_strdup(d->key, key);
+ d->value.channel = channel;
+ return d;
+}
+
+LogData *log_data_source(const char *file, int line, const char *function)
+{
+ LogData *d = safe_alloc(sizeof(LogData));
+ json_t *j;
+
+ d->type = LOG_FIELD_OBJECT;
+ safe_strdup(d->key, "source");
+ d->value.object = j = json_object();
+ json_object_set_new(j, "file", json_string_unreal(file));
+ json_object_set_new(j, "line", json_integer(line));
+ json_object_set_new(j, "function", json_string_unreal(function));
+ return d;
+}
+
+LogData *log_data_socket_error(int fd)
+{
+ /* First, grab the error number very early here: */
+#ifndef _WIN32
+ int sockerr = errno;
+#else
+ int sockerr = WSAGetLastError();
+#endif
+ int v;
+ int len = sizeof(v);
+ LogData *d;
+ json_t *j;
+
+#ifdef SO_ERROR
+ /* Try to get the "real" error from the underlying socket.
+ * If we succeed then we will override "sockerr" with it.
+ */
+ if ((fd >= 0) && !getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&v, &len) && v)
+ sockerr = v;
+#endif
+
+ d = safe_alloc(sizeof(LogData));
+ d->type = LOG_FIELD_OBJECT;
+ safe_strdup(d->key, "socket_error");
+ d->value.object = j = json_object();
+ json_object_set_new(j, "error_code", json_integer(sockerr));
+ json_object_set_new(j, "error_string", json_string_unreal(STRERROR(sockerr)));
+ return d;
+}
+
+/** Populate log with the TLS error(s) stack */
+LogData *log_data_tls_error(void)
+{
+ LogData *d;
+ json_t *j;
+ json_t *error_stack;
+ json_t *name = NULL;
+ json_t *jt;
+ unsigned long e;
+ char buf[512];
+ static char all_errors[8192];
+
+ d = safe_alloc(sizeof(LogData));
+ d->type = LOG_FIELD_OBJECT;
+ safe_strdup(d->key, "tls_error");
+ d->value.object = j = json_object();
+
+ error_stack = json_array();
+ json_object_set_new(j, "error_stack", error_stack);
+ *all_errors = '\0';
+
+ do {
+ json_t *obj;
+
+ e = ERR_get_error();
+ if (e == 0)
+ break;
+ ERR_error_string_n(e, buf, sizeof(buf));
+
+ obj = json_object();
+ json_object_set_new(obj, "code", json_integer(e));
+ json_object_set_new(obj, "string", json_string_unreal(buf));
+ json_array_append_new(error_stack, obj);
+
+ if (name == NULL)
+ {
+ /* Set tls_error.name to the first error that was encountered */
+ json_object_set_new(j, "name", json_string_unreal(buf));
+ }
+ strlcat(all_errors, buf, sizeof(all_errors));
+ strlcat(all_errors, "\n", sizeof(all_errors));
+ } while(e);
+
+ json_object_set_new(j, "all", json_string_unreal(all_errors));
+
+ return d;
+}
+
+LogData *log_data_link_block(ConfigItem_link *link)
+{
+ LogData *d = safe_alloc(sizeof(LogData));
+ json_t *j;
+ char *bind_ip;
+
+ d->type = LOG_FIELD_OBJECT;
+ safe_strdup(d->key, "link_block");
+ d->value.object = j = json_object();
+ json_object_set_new(j, "name", json_string_unreal(link->servername));
+ json_object_set_new(j, "hostname", json_string_unreal(link->outgoing.hostname));
+ json_object_set_new(j, "ip", json_string_unreal(link->connect_ip));
+ json_object_set_new(j, "port", json_integer(link->outgoing.port));
+
+ if (!link->outgoing.bind_ip && iConf.link_bindip)
+ bind_ip = iConf.link_bindip;
+ else
+ bind_ip = link->outgoing.bind_ip;
+ if (!bind_ip)
+ bind_ip = "*";
+ json_object_set_new(j, "bind_ip", json_string_unreal(bind_ip));
+
+ return d;
+}
+
+LogData *log_data_tkl(const char *key, TKL *tkl)
+{
+ char buf[BUFSIZE];
+ LogData *d = safe_alloc(sizeof(LogData));
+ json_t *j;
+
+ d->type = LOG_FIELD_OBJECT;
+ safe_strdup(d->key, key);
+ d->value.object = j = json_object();
+
+ json_object_set_new(j, "type", json_string_unreal(tkl_type_config_string(tkl))); // Eg 'kline'
+ json_object_set_new(j, "type_string", json_string_unreal(tkl_type_string(tkl))); // Eg 'Soft K-Line'
+ json_object_set_new(j, "set_by", json_string_unreal(tkl->set_by));
+ json_object_set_new(j, "set_at", json_timestamp(tkl->set_at));
+ json_object_set_new(j, "expire_at", json_timestamp(tkl->expire_at));
+ *buf = '\0';
+ short_date(tkl->set_at, buf);
+ strlcat(buf, " GMT", sizeof(buf));
+ json_object_set_new(j, "set_at_string", json_string_unreal(buf));
+ if (tkl->expire_at <= 0)
+ {
+ json_object_set_new(j, "expire_at_string", json_string_unreal("Never"));
+ json_object_set_new(j, "duration_string", json_string_unreal("permanent"));
+ } else {
+ *buf = '\0';
+ short_date(tkl->expire_at, buf);
+ strlcat(buf, " GMT", sizeof(buf));
+ json_object_set_new(j, "expire_at_string", json_string_unreal(buf));
+ json_object_set_new(j, "duration_string", json_string_unreal(pretty_time_val_r(buf, sizeof(buf), tkl->expire_at - tkl->set_at)));
+ }
+ json_object_set_new(j, "set_at_delta", json_integer(TStime() - tkl->set_at));
+ if (TKLIsServerBan(tkl))
+ {
+ json_object_set_new(j, "name", json_string_unreal(tkl_uhost(tkl, buf, sizeof(buf), 0)));
+ json_object_set_new(j, "reason", json_string_unreal(tkl->ptr.serverban->reason));
+ } else
+ if (TKLIsNameBan(tkl))
+ {
+ json_object_set_new(j, "name", json_string_unreal(tkl->ptr.nameban->name));
+ json_object_set_new(j, "reason", json_string_unreal(tkl->ptr.nameban->reason));
+ } else
+ if (TKLIsBanException(tkl))
+ {
+ json_object_set_new(j, "name", json_string_unreal(tkl_uhost(tkl, buf, sizeof(buf), 0)));
+ json_object_set_new(j, "reason", json_string_unreal(tkl->ptr.banexception->reason));
+ json_object_set_new(j, "exception_types", json_string_unreal(tkl->ptr.banexception->bantypes));
+ } else
+ if (TKLIsSpamfilter(tkl))
+ {
+ json_object_set_new(j, "name", json_string_unreal(tkl->ptr.spamfilter->match->str));
+ json_object_set_new(j, "match_type", json_string_unreal(unreal_match_method_valtostr(tkl->ptr.spamfilter->match->type)));
+ json_object_set_new(j, "ban_action", json_string_unreal(banact_valtostring(tkl->ptr.spamfilter->action)));
+ json_object_set_new(j, "spamfilter_targets", json_string_unreal(spamfilter_target_inttostring(tkl->ptr.spamfilter->target)));
+ json_object_set_new(j, "reason", json_string_unreal(unreal_decodespace(tkl->ptr.spamfilter->tkl_reason)));
+ }
+
+ return d;
+}
+
+void log_data_free(LogData *d)
+{
+ if (d->type == LOG_FIELD_STRING)
+ safe_free(d->value.string);
+ else if ((d->type == LOG_FIELD_OBJECT) && d->value.object)
+ json_decref(d->value.object);
+
+ safe_free(d->key);
+ safe_free(d);
+}
+
+const char *log_level_valtostring(LogLevel loglevel)
+{
+ switch(loglevel)
+ {
+ case ULOG_DEBUG:
+ return "debug";
+ case ULOG_INFO:
+ return "info";
+ case ULOG_WARNING:
+ return "warn";
+ case ULOG_ERROR:
+ return "error";
+ case ULOG_FATAL:
+ return "fatal";
+ default:
+ return NULL;
+ }
+}
+
+static NameValue log_colors_irc[] = {
+ { ULOG_INVALID, "\0030,01" },
+ { ULOG_DEBUG, "\0030,01" },
+ { ULOG_INFO, "\00303" },
+ { ULOG_WARNING, "\00307" },
+ { ULOG_ERROR, "\00304" },
+ { ULOG_FATAL, "\00313" },
+};
+
+static NameValue log_colors_terminal[] = {
+ { ULOG_INVALID, "\033[90m" },
+ { ULOG_DEBUG, "\033[37m" },
+ { ULOG_INFO, "\033[92m" },
+ { ULOG_WARNING, "\033[93m" },
+ { ULOG_ERROR, "\033[91m" },
+ { ULOG_FATAL, "\033[95m" },
+};
+#define TERMINAL_COLOR_RESET "\033[0m"
+
+const char *log_level_irc_color(LogLevel loglevel)
+{
+ return nv_find_by_value(log_colors_irc, loglevel);
+}
+
+const char *log_level_terminal_color(LogLevel loglevel)
+{
+ return nv_find_by_value(log_colors_terminal, loglevel);
+}
+
+LogLevel log_level_stringtoval(const char *str)
+{
+ if (!strcmp(str, "info"))
+ return ULOG_INFO;
+ if (!strcmp(str, "warn"))
+ return ULOG_WARNING;
+ if (!strcmp(str, "error"))
+ return ULOG_ERROR;
+ if (!strcmp(str, "fatal"))
+ return ULOG_FATAL;
+ if (!strcmp(str, "debug"))
+ return ULOG_DEBUG;
+ return ULOG_INVALID;
+}
+
+#define validvarcharacter(x) (isalnum((x)) || ((x) == '_'))
+#define valideventidcharacter(x) (isupper((x)) || isdigit((x)) || ((x) == '_'))
+#define validsubsystemcharacter(x) (islower((x)) || isdigit((x)) || ((x) == '_') || ((x) == '-'))
+
+int valid_event_id(const char *s)
+{
+ if (!*s)
+ return 0;
+ for (; *s; s++)
+ if (!valideventidcharacter(*s))
+ return 0;
+ return 1;
+}
+
+int valid_subsystem(const char *s)
+{
+ if (!*s)
+ return 0;
+ if (log_level_stringtoval(s) != ULOG_INVALID)
+ return 0;
+ for (; *s; s++)
+ if (!validsubsystemcharacter(*s))
+ return 0;
+ return 1;
+}
+
+const char *json_get_value(json_t *t)
+{
+ static char buf[32];
+
+ if (json_is_string(t))
+ return json_string_value(t);
+
+ if (json_is_integer(t))
+ {
+ snprintf(buf, sizeof(buf), "%lld", (long long)json_integer_value(t));
+ return buf;
+ }
+
+ return NULL;
+}
+
+// TODO: if in the function below we keep adding auto expanshion shit,
+// like we currently have $client automatically expanding to $client.name
+// and $socket_error to $socket_error.error_string,
+// if this gets more than we should use some kind of array for it,
+// especially for the hardcoded name shit like $socket_error.
+
+/** Build a string and replace $variables where needed.
+ * See src/modules/blacklist.c for an example.
+ * @param inbuf The input string
+ * @param outbuf The output string
+ * @param len The maximum size of the output string (including NUL)
+ * @param name Array of variables names
+ * @param value Array of variable values
+ */
+void buildlogstring(const char *inbuf, char *outbuf, size_t len, json_t *details)
+{
+ const char *i, *p;
+ char *o;
+ int left = len - 1;
+ int cnt, found;
+ char varname[256], *varp, *varpp;
+ json_t *t;
+
+#ifdef DEBUGMODE
+ if (len <= 0)
+ abort();
+#endif
+
+ for (i = inbuf, o = outbuf; *i; i++)
+ {
+ if (*i == '$')
+ {
+ i++;
+
+ /* $$ = literal $ */
+ if (*i == '$')
+ goto literal;
+
+ if (!validvarcharacter(*i))
+ {
+ /* What do we do with things like '$/' ? -- treat literal */
+ i--;
+ goto literal;
+ }
+
+ /* find termination */
+ for (p=i; validvarcharacter(*p) || ((*p == '.') && validvarcharacter(p[1])); p++);
+
+ /* find variable name in list */
+ strlncpy(varname, i, sizeof(varname), p - i);
+ varp = strchr(varname, '.');
+ if (varp)
+ *varp = '\0';
+ t = json_object_get(details, varname);
+ if (t)
+ {
+ const char *output = NULL;
+ if (varp)
+ {
+ char *varpp;
+ do {
+ varpp = strchr(varp+1, '.');
+ if (varpp)
+ *varpp = '\0';
+ /* Fetch explicit object.key */
+ t = json_object_get(t, varp+1);
+ varp = varpp;
+ } while(t && varpp);
+ if (t)
+ output = json_get_value(t);
+ } else
+ if (!strcmp(varname, "socket_error"))
+ {
+ /* Fetch socket_error.error_string */
+ t = json_object_get(t, "error_string");
+ if (t)
+ output = json_get_value(t);
+ } else
+ if (json_is_object(t))
+ {
+ /* Fetch object.name */
+ t = json_object_get(t, "name");
+ if (t)
+ output = json_get_value(t);
+ } else
+ {
+ output = json_get_value(t);
+ }
+ if (output)
+ {
+ strlcpy(o, output, left);
+ left -= strlen(output); /* may become <0 */
+ if (left <= 0)
+ return; /* return - don't write \0 to 'o'. ensured by strlcpy already */
+ o += strlen(output); /* value entirely written */
+ }
+ } else
+ {
+ /* variable name does not exist -- treat as literal string */
+ i--;
+ goto literal;
+ }
+
+ /* value written. we're done. */
+ i = p - 1;
+ continue;
+ }
+literal:
+ if (!left)
+ break;
+ *o++ = *i;
+ left--;
+ if (!left)
+ break;
+ }
+ *o = '\0';
+}
+
+/** 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)
+{
+ static int last_log_file_warning = 0;
+ Log *l;
+ char timebuf[128];
+ struct stat fstats;
+ int n;
+ int write_error;
+ long snomask;
+ MultiLine *m;
+
+ snprintf(timebuf, sizeof(timebuf), "[%s] ", myctime(TStime()));
+
+ RunHook(HOOKTYPE_LOG, loglevel, subsystem, event_id, msg, json_serialized, timebuf);
+
+ if (!loop.forked && (loglevel > ULOG_DEBUG))
+ {
+ for (m = msg; m; m = m->next)
+ {
+#ifdef _WIN32
+ if (show_event_id_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)
+ {
+ fprintf(stderr, "%s%s.%s%s %s[%s]%s %s\n",
+ log_level_terminal_color(ULOG_INVALID), subsystem, event_id, TERMINAL_COLOR_RESET,
+ log_level_terminal_color(loglevel), log_level_valtostring(loglevel), TERMINAL_COLOR_RESET,
+ m->line);
+ } else {
+ fprintf(stderr, "%s[%s]%s %s\n",
+ log_level_terminal_color(loglevel), log_level_valtostring(loglevel), TERMINAL_COLOR_RESET,
+ m->line);
+ }
+ } else {
+ if (show_event_id_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);
+ }
+#endif
+ }
+ }
+
+ /* In case of './unrealircd configtest': don't write to log file, only to stderr */
+ if (loop.config_test)
+ return;
+
+ for (l = logs[LOG_DEST_DISK]; l; l = l->next)
+ {
+ if (!log_sources_match(l->sources, loglevel, subsystem, event_id, 0))
+ continue;
+
+#ifdef HAVE_SYSLOG
+ if (l->file && !strcasecmp(l->file, "syslog"))
+ {
+ if (l->type == LOG_TYPE_JSON)
+ {
+ syslog(LOG_INFO, "%s", json_serialized);
+ } else
+ if (l->type == LOG_TYPE_TEXT)
+ {
+ for (m = msg; m; m = m->next)
+ syslog(LOG_INFO, "%s.%s%s %s: %s", subsystem, event_id, m->next?"+":"", log_level_valtostring(loglevel), m->line);
+ }
+ continue;
+ }
+#endif
+
+ /* This deals with dynamic log file names, such as ircd.%Y-%m-%d.log */
+ if (l->filefmt)
+ {
+ char *fname = unreal_strftime(l->filefmt);
+ if (l->file && (l->logfd != -1) && strcmp(l->file, fname))
+ {
+ /* We are logging already and need to switch over */
+ fd_close(l->logfd);
+ l->logfd = -1;
+ }
+ safe_strdup(l->file, fname);
+ }
+
+ /* log::maxsize code */
+ if (l->maxsize && (stat(l->file, &fstats) != -1) && fstats.st_size >= l->maxsize)
+ {
+ char oldlog[512];
+ if (l->logfd == -1)
+ {
+ /* Try to open, so we can write the 'Max file size reached' message. */
+ l->logfd = fd_fileopen(l->file, O_CREAT|O_APPEND|O_WRONLY);
+ }
+ if (l->logfd != -1)
+ {
+ if (write(l->logfd, "Max file size reached, starting new log file\n", 45) < 0)
+ {
+ /* We already handle the unable to write to log file case for normal data.
+ * I think we can get away with not handling this one.
+ */
+ ;
+ }
+ fd_close(l->logfd);
+ }
+ l->logfd = -1;
+
+ /* Rename log file to xxxxxx.old */
+ snprintf(oldlog, sizeof(oldlog), "%s.old", l->file);
+ unlink(oldlog); /* windows rename cannot overwrite, so unlink here.. ;) */
+ rename(l->file, oldlog);
+ }
+
+ /* generic code for opening log if not open yet.. */
+ if (l->logfd == -1)
+ {
+ l->logfd = fd_fileopen(l->file, O_CREAT|O_APPEND|O_WRONLY);
+ if (l->logfd == -1)
+ {
+ if (!loop.booted)
+ {
+ config_status("WARNING: Unable to write to '%s': %s", l->file, strerror(errno));
+ } else {
+ if (last_log_file_warning + 300 < TStime())
+ {
+ config_status("WARNING: Unable to write to '%s': %s. This warning will not re-appear for at least 5 minutes.", l->file, strerror(errno));
+ last_log_file_warning = TStime();
+ }
+ }
+ continue;
+ }
+ }
+
+ /* Now actually WRITE to the log... */
+ write_error = 0;
+ if ((l->type == LOG_TYPE_JSON) && strcmp(subsystem, "rawtraffic"))
+ {
+ n = write(l->logfd, json_serialized, strlen(json_serialized));
+ if (n < strlen(json_serialized))
+ {
+ write_error = 1;
+ } else {
+ if (write(l->logfd, "\n", 1) < 1) // FIXME: no.. we should do it this way..... and why do we use direct I/O at all?
+ write_error = 1;
+ }
+ } else
+ if (l->type == LOG_TYPE_TEXT)
+ {
+ 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... */
+ ;
+ }
+ n = write(l->logfd, text_buf, strlen(text_buf));
+ if (n < strlen(text_buf))
+ {
+ write_error = 1;
+ break;
+ }
+ }
+ }
+
+ if (write_error)
+ {
+ if (!loop.booted)
+ {
+ config_status("WARNING: Unable to write to '%s': %s", l->file, strerror(errno));
+ } else {
+ if (last_log_file_warning + 300 < TStime())
+ {
+ config_status("WARNING: Unable to write to '%s': %s. This warning will not re-appear for at least 5 minutes.", l->file, strerror(errno));
+ last_log_file_warning = TStime();
+ }
+ }
+ }
+ }
+}
+
+int log_sources_match(LogSource *logsource, LogLevel loglevel, const char *subsystem, const char *event_id, int matched_already)
+{
+ int retval = 0;
+ LogSource *ls;
+
+ // NOTE: This routine works by exclusion, so a bad struct would
+ // cause everything to match!!
+
+ for (ls = logsource; ls; ls = ls->next)
+ {
+ /* First deal with all positive matchers.. */
+ if (ls->negative)
+ continue;
+ if (!strcmp(ls->subsystem, "all"))
+ {
+ retval = 1;
+ break;
+ }
+ if (!strcmp(ls->subsystem, "nomatch") && !matched_already)
+ {
+ /* catch-all */
+ retval = 1;
+ break;
+ }
+ if (*ls->event_id && strcmp(ls->event_id, event_id))
+ continue;
+ if (*ls->subsystem && strcmp(ls->subsystem, subsystem))
+ continue;
+ if ((ls->loglevel != ULOG_INVALID) && (ls->loglevel != loglevel))
+ continue;
+ /* MATCH */
+ retval = 1;
+ break;
+ }
+
+ /* No matches? Then we can stop here */
+ if (retval == 0)
+ return 0;
+
+ /* There was a match, now check for exemptions, eg !operoverride */
+ for (ls = logsource; ls; ls = ls->next)
+ {
+ /* Only deal with negative matches... */
+ if (!ls->negative)
+ continue;
+ if (!strcmp(ls->subsystem, "nomatch") || !strcmp(ls->subsystem, "all"))
+ continue; /* !nomatch and !all make no sense, so just ignore it */
+ if (*ls->event_id && strcmp(ls->event_id, event_id))
+ continue;
+ if (*ls->subsystem && strcmp(ls->subsystem, subsystem))
+ continue;
+ if ((ls->loglevel != ULOG_INVALID) && (ls->loglevel != loglevel))
+ continue;
+ /* NEGATIVE MATCH */
+ return 0;
+ }
+
+ return 1;
+}
+
+/** Convert loglevel/subsystem/event_id to a snomask.
+ * @returns The snomask letters (may be more than one),
+ * an asterisk (for all ircops), or NULL (no delivery)
+ */
+const char *log_to_snomask(LogLevel loglevel, const char *subsystem, const char *event_id)
+{
+ Log *ld;
+ static char snomasks[64];
+ int matched = 0;
+
+ *snomasks = '\0';
+ for (ld = logs[LOG_DEST_SNOMASK]; ld; ld = ld->next)
+ {
+ if (log_sources_match(ld->sources, loglevel, subsystem, event_id, 0))
+ {
+ strlcat(snomasks, ld->destination, sizeof(snomasks));
+ matched = 1;
+ }
+ }
+
+ if (logs[LOG_DEST_OPER] && log_sources_match(logs[LOG_DEST_OPER]->sources, loglevel, subsystem, event_id, matched))
+ strlcat(snomasks, "s", sizeof(snomasks));
+
+ return *snomasks ? snomasks : NULL;
+}
+
+#define COLOR_NONE "\xf"
+#define COLOR_DARKGREY "\00314"
+/** Do the actual writing to log files */
+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)
+ return;
+
+ /* Never send these */
+ if (!strcmp(subsystem, "rawtraffic"))
+ return;
+
+ snomask_destinations = log_to_snomask(loglevel, subsystem, event_id);
+ 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;
+
+ if (snomask_destinations)
+ {
+ char found = 0;
+ if (!client->user->snomask)
+ continue; /* None set, so will never match */
+ for (p = snomask_destinations; *p; p++)
+ {
+ if (strchr(client->user->snomask, *p))
+ {
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ continue;
+ }
+
+ 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 */
+ }
+ }
+
+ 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)
+{
+ Log *l;
+ int found = 0;
+
+ for (l = logs[LOG_DEST_REMOTE]; l; l = l->next)
+ {
+ if (log_sources_match(l->sources, loglevel, subsystem, event_id, 0))
+ {
+ found = 1;
+ break;
+ }
+ }
+ if (found == 0)
+ return;
+
+ do_unreal_log_remote_deliver(loglevel, subsystem, event_id, msg, json_serialized);
+}
+
+void do_unreal_log_free_args(va_list vl)
+{
+ LogData *d;
+
+ while ((d = va_arg(vl, LogData *)))
+ {
+ log_data_free(d);
+ }
+}
+
+static int unreal_log_recursion_trap = 0;
+
+/* Logging function, called by the unreal_log() macro. */
+void do_unreal_log(LogLevel loglevel, const char *subsystem, const char *event_id,
+ Client *client, const char *msg, ...)
+{
+ va_list vl;
+
+ if (unreal_log_recursion_trap)
+ {
+ va_start(vl, msg);
+ do_unreal_log_free_args(vl);
+ va_end(vl);
+ return;
+ }
+
+ unreal_log_recursion_trap = 1;
+ va_start(vl, msg);
+ do_unreal_log_internal(loglevel, subsystem, event_id, client, 1, msg, vl);
+ va_end(vl);
+ unreal_log_recursion_trap = 0;
+}
+
+/* Logging function, called by the unreal_log_raw() macro. */
+void do_unreal_log_raw(LogLevel loglevel, const char *subsystem, const char *event_id,
+ Client *client, const char *msg, ...)
+{
+ va_list vl;
+
+ if (unreal_log_recursion_trap)
+ {
+ va_start(vl, msg);
+ do_unreal_log_free_args(vl);
+ va_end(vl);
+ return;
+ }
+
+ unreal_log_recursion_trap = 1;
+ va_start(vl, msg);
+ do_unreal_log_internal(loglevel, subsystem, event_id, client, 0, msg, vl);
+ va_end(vl);
+ unreal_log_recursion_trap = 0;
+}
+
+void do_unreal_log_norecursioncheck(LogLevel loglevel, const char *subsystem, const char *event_id,
+ Client *client, const char *msg, ...)
+{
+ va_list vl;
+
+ va_start(vl, msg);
+ do_unreal_log_internal(loglevel, subsystem, event_id, client, 1, msg, vl);
+ va_end(vl);
+}
+
+void do_unreal_log_internal(LogLevel loglevel, const char *subsystem, const char *event_id,
+ Client *client, int expand_msg, const char *msg, va_list vl)
+{
+ LogData *d;
+ char *json_serialized;
+ const char *str;
+ json_t *j = NULL;
+ json_t *j_details = NULL;
+ json_t *t;
+ char msgbuf[8192];
+ const char *loglevel_string = log_level_valtostring(loglevel);
+ MultiLine *mmsg;
+ Client *from_server = NULL;
+
+ if (loglevel_string == NULL)
+ {
+ do_unreal_log_norecursioncheck(ULOG_ERROR, "log", "BUG_LOG_LOGLEVEL", NULL,
+ "[BUG] Next log message had an invalid log level -- corrected to ULOG_ERROR",
+ NULL);
+ loglevel = ULOG_ERROR;
+ loglevel_string = log_level_valtostring(loglevel);
+ }
+ if (!valid_subsystem(subsystem))
+ {
+ do_unreal_log_norecursioncheck(ULOG_ERROR, "log", "BUG_LOG_SUBSYSTEM", NULL,
+ "[BUG] Next log message had an invalid subsystem -- changed to 'unknown'",
+ NULL);
+ subsystem = "unknown";
+ }
+ if (!valid_event_id(event_id))
+ {
+ do_unreal_log_norecursioncheck(ULOG_ERROR, "log", "BUG_LOG_EVENT_ID", NULL,
+ "[BUG] Next log message had an invalid event id -- changed to 'unknown'",
+ NULL);
+ event_id = "unknown";
+ }
+ /* This one is probably temporary since it should not be a real error, actually (but often is) */
+ if (expand_msg && strchr(msg, '%'))
+ {
+ do_unreal_log_norecursioncheck(ULOG_ERROR, "log", "BUG_LOG_MESSAGE_PERCENT", NULL,
+ "[BUG] Next log message contains a percent sign -- possibly accidental format string!",
+ NULL);
+ }
+
+ j = json_object();
+ j_details = json_object();
+
+ json_object_set_new(j, "timestamp", json_string_unreal(timestamp_iso8601_now()));
+ json_object_set_new(j, "level", json_string_unreal(loglevel_string));
+ json_object_set_new(j, "subsystem", json_string_unreal(subsystem));
+ json_object_set_new(j, "event_id", json_string_unreal(event_id));
+ json_object_set_new(j, "log_source", json_string_unreal(*me.name ? me.name : "local"));
+
+ /* We put all the rest in j_details because we want to enforce
+ * a certain ordering of the JSON output. We will merge these
+ * details later on.
+ */
+ if (client)
+ json_expand_client(j_details, "client", client, 0);
+ /* Additional details (if any) */
+ while ((d = va_arg(vl, LogData *)))
+ {
+ switch(d->type)
+ {
+ case LOG_FIELD_INTEGER:
+ json_object_set_new(j_details, d->key, json_integer(d->value.integer));
+ break;
+ case LOG_FIELD_STRING:
+ if (d->value.string)
+ json_object_set_new(j_details, d->key, json_string_unreal(d->value.string));
+ else
+ json_object_set_new(j_details, d->key, json_null());
+ break;
+ case LOG_FIELD_CLIENT:
+ json_expand_client(j_details, d->key, d->value.client, 0);
+ break;
+ case LOG_FIELD_CHANNEL:
+ json_expand_channel(j_details, d->key, d->value.channel, 0);
+ break;
+ case LOG_FIELD_OBJECT:
+ json_object_set_new(j_details, d->key, d->value.object);
+ d->value.object = NULL; /* don't let log_data_free() free it */
+ break;
+ default:
+#ifdef DEBUGMODE
+ abort();
+#endif
+ break;
+ }
+ log_data_free(d);
+ }
+
+ if (expand_msg)
+ buildlogstring(msg, msgbuf, sizeof(msgbuf), j_details);
+ else
+ strlcpy(msgbuf, msg, sizeof(msgbuf));
+
+ json_object_set_new(j, "msg", json_string_unreal(msgbuf));
+
+ /* Now merge the details into root object 'j': */
+ json_object_update_missing(j, j_details);
+ /* Generate the JSON */
+ json_serialized = json_dumps(j, JSON_COMPACT);
+
+ /* 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 */
+ 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;
+ do_unreal_log_opers(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!
+
+ /* Free everything */
+ safe_free(json_serialized);
+ safe_free_multiline(mmsg);
+ json_decref(j_details);
+ json_decref(j);
+}
+
+void do_unreal_log_internal_from_remote(LogLevel loglevel, const char *subsystem, const char *event_id,
+ MultiLine *msg, const char *json_serialized, Client *from_server)
+{
+ if (unreal_log_recursion_trap)
+ return;
+ unreal_log_recursion_trap = 1;
+
+ /* Call the disk loggers */
+ do_unreal_log_disk(loglevel, subsystem, event_id, msg, json_serialized);
+
+ /* And the ircops stuff */
+ do_unreal_log_opers(loglevel, subsystem, event_id, msg, json_serialized, from_server);
+
+ unreal_log_recursion_trap = 0;
+}
+
+
+void free_log_block(Log *l)
+{
+ Log *l_next;
+ LogSource *src, *src_next;
+ for (; l; l = l_next)
+ {
+ l_next = l->next;
+ if (l->logfd > 0)
+ {
+ fd_close(l->logfd);
+ l->logfd = -1;
+ }
+ free_log_sources(l->sources);
+ safe_free(l->file);
+ safe_free(l->filefmt);
+ safe_free(l);
+ }
+}
+
+int log_tests(void)
+{
+ if (snomask_num_destinations <= 1)
+ {
+ unreal_log(ULOG_ERROR, "config", "LOG_SNOMASK_BLOCK_MISSING", NULL,
+ "Missing snomask logging configuration:\n"
+ "Please add the following line to your unrealircd.conf: "
+ "include \"snomasks.default.conf\";");
+ return 0;
+ }
+ snomask_num_destinations = 0;
+ return 1;
+}
+
+void postconf_defaults_log_block(void)
+{
+ Log *l;
+ LogSource *ls;
+
+ /* Is there any log block to disk? Then nothing to do. */
+ if (logs[LOG_DEST_DISK])
+ return;
+
+ unreal_log(ULOG_WARNING, "log", "NO_DISK_LOG_BLOCK", NULL,
+ "No log { } block found that logs to disk -- "
+ "logging everything in text format to 'ircd.log'");
+
+ /* Create a default log block */
+ l = safe_alloc(sizeof(Log));
+ l->logfd = -1;
+ l->type = LOG_TYPE_TEXT; /* text */
+ l->maxsize = 100000000; /* maxsize 100M */
+ safe_strdup(l->file, "ircd.log");
+ convert_to_absolute_path(&l->file, LOGDIR);
+ AddListItem(l, logs[LOG_DEST_DISK]);
+
+ /* And the source filter */
+ ls = add_log_source("all");
+ AppendListItem(ls, l->sources);
+ ls = add_log_source("!debug");
+ AppendListItem(ls, l->sources);
+ ls = add_log_source("!join.LOCAL_CLIENT_JOIN");
+ AppendListItem(ls, l->sources);
+ ls = add_log_source("!join.REMOTE_CLIENT_JOIN");
+ AppendListItem(ls, l->sources);
+ ls = add_log_source("!part.LOCAL_CLIENT_PART");
+ AppendListItem(ls, l->sources);
+ ls = add_log_source("!part.REMOTE_CLIENT_PART");
+ AppendListItem(ls, l->sources);
+ ls = add_log_source("!kick.LOCAL_CLIENT_KICK");
+ AppendListItem(ls, l->sources);
+ ls = add_log_source("!kick.REMOTE_CLIENT_KICK");
+ AppendListItem(ls, l->sources);
+}
+
+/* Called before CONFIG_TEST */
+void log_pre_rehash(void)
+{
+ *snomasks_in_use_testing = '\0';
+}
+
+/* Called after CONFIG_TEST right before CONFIG_RUN */
+void config_pre_run_log(void)
+{
+ *snomasks_in_use = '\0';
+}
+
+/* Called after CONFIG_RUN is complete */
+void log_blocks_switchover(void)
+{
+ int i;
+ for (i=0; i < NUM_LOG_DESTINATIONS; i++)
+ free_log_block(logs[i]);
+ memcpy(logs, temp_logs, sizeof(logs));
+ memset(temp_logs, 0, sizeof(temp_logs));
+}
+
+/** Check if a letter is a valid snomask (that is:
+ * one that exists in the log block configuration).
+ * @param c the snomask letter to check
+ * @returns 1 if exists, 0 if not.
+ */
+int is_valid_snomask(char c)
+{
+ return strchr(snomasks_in_use, c) ? 1 : 0;
+}
+
+/** Check if a letter is a valid snomask during or after CONFIG_TEST
+ * (the snomasks exist in the log block configuration read during config_test).
+ * @param c the snomask letter to check
+ * @returns 1 if exists, 0 if not.
+ */
+int is_valid_snomask_testing(char c)
+{
+ return strchr(snomasks_in_use_testing, c) ? 1 : 0;
+}
+
+/** Check if a string all consists of valid snomasks during or after CONFIG_TEST
+ * (the snomasks exist in the log block configuration read during config_test).
+ * @param str the snomask string to check
+ * @param invalid_snomasks list of unknown snomask letters
+ * @returns 1 if exists, 0 if not.
+ */
+int is_valid_snomask_string_testing(const char *str, char **invalid_snomasks)
+{
+ static char invalid_snomasks_buf[256];
+
+ *invalid_snomasks_buf = '\0';
+ for (; *str; str++)
+ {
+ if ((*str == '+') || (*str == '-'))
+ continue;
+ if (!strchr(snomasks_in_use_testing, *str))
+ strlcat_letter(invalid_snomasks_buf, *str, sizeof(invalid_snomasks_buf));
+ }
+ *invalid_snomasks = invalid_snomasks_buf;
+ return *invalid_snomasks_buf ? 0 : 1;
+}
diff --git a/src/macosx/UnrealIRCd/AppModel.swift b/src/macosx/UnrealIRCd/AppModel.swift
index 7cb4570..5fff8ba 100644
--- a/src/macosx/UnrealIRCd/AppModel.swift
+++ b/src/macosx/UnrealIRCd/AppModel.swift
@@ -13,7 +13,7 @@ class AppModel : ChangeNotifierDelegate
{
var menuItem : NSStatusItem
static let logoName = "logo.png"
- static let helpURL = "https://www.unrealircd.org/docs/UnrealIRCd_5_documentation"
+ static let helpURL = "https://www.unrealircd.org/docs/UnrealIRCd_6_documentation"
var daemonModel : DaemonModel
var configurationModel : ConfigurationModel
var windowController : NSWindowController?
diff --git a/src/match.c b/src/match.c
index ccc1c39..ca361b0 100644
--- a/src/match.c
+++ b/src/match.c
@@ -384,7 +384,7 @@ void unreal_delete_match(Match *m)
safe_free(m);
}
-Match *unreal_create_match(MatchType type, char *str, char **error)
+Match *unreal_create_match(MatchType type, const char *str, char **error)
{
Match *m = safe_alloc(sizeof(Match));
static char errorbuf[512];
@@ -438,7 +438,7 @@ Match *unreal_create_match(MatchType type, char *str, char **error)
* @returns 1 if matched, 0 if not.
* @note These (more logical) return values are opposite to the match_simple() function.
*/
-int unreal_match(Match *m, char *str)
+int unreal_match(Match *m, const char *str)
{
if (m->type == MATCH_SIMPLE)
{
@@ -463,7 +463,7 @@ int unreal_match(Match *m, char *str)
return 0;
}
-int unreal_match_method_strtoval(char *str)
+int unreal_match_method_strtoval(const char *str)
{
if (!strcmp(str, "regex") || !strcmp(str, "pcre"))
return MATCH_PCRE_REGEX;
@@ -489,10 +489,11 @@ char *unreal_match_method_valtostr(int val)
* Moved here from the censor channel and user mode module
* (previously was present in both modules, code duplication)
*/
-int fast_badword_match(ConfigItem_badword *badword, char *line)
+int fast_badword_match(ConfigItem_badword *badword, const char *line)
{
- char *p;
+ const char *p;
int bwlen = strlen(badword->word);
+
if ((badword->type & BADW_TYPE_FAST_L) && (badword->type & BADW_TYPE_FAST_R))
return (our_strcasestr(line, badword->word) ? 1 : 0);
@@ -523,21 +524,20 @@ next:
* buf is used for the result and max is sizeof(buf).
* Assumptions[!]: max > 0 AND max > strlen(line)+1
*/
-int fast_badword_replace(ConfigItem_badword *badword, char *line, char *buf, int max)
+int fast_badword_replace(ConfigItem_badword *badword, const char *line, char *buf, int max)
{
/* Some aliases ;P */
char *replacew = badword->replace ? badword->replace : REPLACEWORD;
- char *pold = line, *pnew = buf; /* Pointers to old string and new string */
- char *poldx = line;
+ const char *pold = line; /* pointer to the old string */
+ const char *poldx = line;
+ char *pnew = buf; /* pointer to the new string */
int replacen = -1; /* Only calculated if needed. w00t! saves us a few nanosecs? lol */
int searchn = -1;
- char *startw, *endw;
+ const char *startw, *endw; /* start and end of the word */
char *c_eol = buf + max - 1; /* Cached end of (new) line */
int run = 1;
int cleaned = 0;
- Debug((DEBUG_NOTICE, "replacing %s -> %s in '%s'", badword->word, replacew, line));
-
while(run) {
pold = our_strcasestr(pold, badword->word);
if (!pold)
@@ -617,7 +617,7 @@ int fast_badword_replace(ConfigItem_badword *badword, char *line, char *buf, int
* the loadbadwords() function. It's primary use is to filter swearing
* in both private and public messages
*/
-char *stripbadwords(char *str, ConfigItem_badword *start_bw, int *blocked)
+const char *stripbadwords(const char *str, ConfigItem_badword *start_bw, int *blocked)
{
static char cleanstr[4096];
char buf[4096];
@@ -692,14 +692,17 @@ char *stripbadwords(char *str, ConfigItem_badword *start_bw, int *blocked)
ret = pcre2_match(this_word->pcre2_expr, ptr, PCRE2_ZERO_TERMINATED, 0, 0, md, NULL); /* run the regex */
if (ret > 0)
{
- ircd_log(LOG_ERROR, "pcre2_get_ovector_count: %d", pcre2_get_ovector_count(md));
dd = pcre2_get_ovector_pointer(md);
start = (int)dd[0];
end = (int)dd[1];
if ((start < 0) || (end < 0) || (start > strlen(ptr)) || (end > strlen(ptr)+1))
{
- ircd_log(LOG_ERROR, "pcre2_match() returned an ovector with OOB start/end: %d/%d, str (%d): '%s'",
- (int)start, (int)end, (int)strlen(ptr), ptr);
+ unreal_log(ULOG_FATAL, "main", "BUG_STRIPBADWORDS_PCRE2_MATCH_OOB", NULL,
+ "[BUG] pcre2_match() returned an ovector with OOB start/end: $start/$end, len $length: '$buf'",
+ log_data_integer("start", start),
+ log_data_integer("end", end),
+ log_data_integer("length", strlen(ptr)),
+ log_data_string("buf", ptr));
abort();
}
m = end - start;
@@ -743,10 +746,10 @@ char *stripbadwords(char *str, ConfigItem_badword *start_bw, int *blocked)
* if check_broadness is 1, the function will attempt to determine
* if the given regex string is too broad (i.e. matches everything)
*/
-char *badword_config_check_regex(char *str, int fastsupport, int check_broadness)
+const char *badword_config_check_regex(const char *str, int fastsupport, int check_broadness)
{
int regex=0;
- char *tmp;
+ const char *tmp;
static char errorbuf[512];
if (fastsupport)
@@ -787,9 +790,9 @@ char *badword_config_check_regex(char *str, int fastsupport, int check_broadness
return NULL;
}
-int badword_config_process(ConfigItem_badword *ca, char *str)
+int badword_config_process(ConfigItem_badword *ca, const char *str)
{
- char *tmp;
+ const char *tmp;
short regex = 0;
int ast_l = 0, ast_r = 0;
diff --git a/src/misc.c b/src/misc.c
index e8a1ee5..27c4f36 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -32,17 +32,26 @@
static void exit_one_client(Client *, MessageTag *mtags_i, const char *);
-static char *months[] = {
+static const char *months[] = {
"January", "February", "March", "April",
"May", "June", "July", "August",
"September", "October", "November", "December"
};
-static char *weekdays[] = {
+static const char *weekdays[] = {
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"
};
+static const char *short_months[12] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+};
+
+static const char *short_weekdays[7] = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+};
+
typedef struct {
int value; /** Unique integer value of item */
char character; /** Unique character assigned to item */
@@ -98,167 +107,8 @@ SpamfilterTargetTable spamfiltertargettable[] = {
/** IRC Statistics (quite useless?) */
struct IRCStatistics ircstats;
-/** Main IRCd logging function.
- * @param flags One of LOG_* (eg: LOG_ERROR)
- * @param format Format string
- * @param ... Arguments
- * @note This function is safe to call at all times. It provides
- * protection against recursion.
- */
-void ircd_log(int flags, FORMAT_STRING(const char *format), ...)
-{
- static int last_log_file_warning = 0;
- static char recursion_trap=0;
-
- va_list ap;
- ConfigItem_log *logs;
- char buf[2048], timebuf[128];
- struct stat fstats;
- int written = 0;
- int n;
-
- /* Trap infinite recursions to avoid crash if log file is unavailable,
- * this will also avoid calling ircd_log from anything else called
- */
- if (recursion_trap == 1)
- return;
-
- recursion_trap = 1;
-
- /* NOTE: past this point you CANNOT just 'return'.
- * You must set 'recursion_trap = 0;' before 'return'!
- */
-
- va_start(ap, format);
- ircvsnprintf(buf, sizeof(buf), format, ap);
- va_end(ap);
- snprintf(timebuf, sizeof(timebuf), "[%s] - ", myctime(TStime()));
-
- RunHook3(HOOKTYPE_LOG, flags, timebuf, buf);
- strlcat(buf, "\n", sizeof(buf));
-
- if (!loop.ircd_forked && (flags & LOG_ERROR))
- {
-#ifdef _WIN32
- win_log("* %s", buf);
-#else
- fprintf(stderr, "%s", buf);
-#endif
- }
-
- /* In case of './unrealircd configtest': don't write to log file, only to stderr */
- if (loop.config_test)
- {
- recursion_trap = 0;
- return;
- }
-
- for (logs = conf_log; logs; logs = logs->next)
- {
- if (!(logs->flags & flags))
- continue;
-
-#ifdef HAVE_SYSLOG
- if (logs->file && !strcasecmp(logs->file, "syslog"))
- {
- syslog(LOG_INFO, "%s", buf);
- written++;
- continue;
- }
-#endif
-
- /* This deals with dynamic log file names, such as ircd.%Y-%m-%d.log */
- if (logs->filefmt)
- {
- char *fname = unreal_strftime(logs->filefmt);
- if (logs->file && (logs->logfd != -1) && strcmp(logs->file, fname))
- {
- /* We are logging already and need to switch over */
- fd_close(logs->logfd);
- logs->logfd = -1;
- }
- safe_strdup(logs->file, fname);
- }
-
- /* log::maxsize code */
- if (logs->maxsize && (stat(logs->file, &fstats) != -1) && fstats.st_size >= logs->maxsize)
- {
- char oldlog[512];
- if (logs->logfd == -1)
- {
- /* Try to open, so we can write the 'Max file size reached' message. */
- logs->logfd = fd_fileopen(logs->file, O_CREAT|O_APPEND|O_WRONLY);
- }
- if (logs->logfd != -1)
- {
- if (write(logs->logfd, "Max file size reached, starting new log file\n", 45) < 0)
- {
- /* We already handle the unable to write to log file case for normal data.
- * I think we can get away with not handling this one.
- */
- ;
- }
- fd_close(logs->logfd);
- }
- logs->logfd = -1;
-
- /* Rename log file to xxxxxx.old */
- snprintf(oldlog, sizeof(oldlog), "%s.old", logs->file);
- unlink(oldlog); /* windows rename cannot overwrite, so unlink here.. ;) */
- rename(logs->file, oldlog);
- }
-
- /* generic code for opening log if not open yet.. */
- if (logs->logfd == -1)
- {
- logs->logfd = fd_fileopen(logs->file, O_CREAT|O_APPEND|O_WRONLY);
- if (logs->logfd == -1)
- {
- if (!loop.ircd_booted)
- {
- config_status("WARNING: Unable to write to '%s': %s", logs->file, strerror(ERRNO));
- } else {
- if (last_log_file_warning + 300 < TStime())
- {
- config_status("WARNING: Unable to write to '%s': %s. This warning will not re-appear for at least 5 minutes.", logs->file, strerror(ERRNO));
- last_log_file_warning = TStime();
- }
- }
- continue;
- }
- }
-
- /* Now actually WRITE to the log... */
- if (write(logs->logfd, timebuf, strlen(timebuf)) < 0)
- {
- /* Let's ignore any write errors for this one. Next write() will catch it... */
- ;
- }
- n = write(logs->logfd, buf, strlen(buf));
- if (n == strlen(buf))
- {
- written++;
- }
- else
- {
- if (!loop.ircd_booted)
- {
- config_status("WARNING: Unable to write to '%s': %s", logs->file, strerror(ERRNO));
- } else {
- if (last_log_file_warning + 300 < TStime())
- {
- config_status("WARNING: Unable to write to '%s': %s. This warning will not re-appear for at least 5 minutes.", logs->file, strerror(ERRNO));
- last_log_file_warning = TStime();
- }
- }
- }
- }
-
- recursion_trap = 0;
-}
-
/** Returns the date in rather long string */
-char *long_date(time_t clock)
+const char *long_date(time_t clock)
{
static char buf[80], plus;
struct tm *lt, *gm;
@@ -300,10 +150,9 @@ char *long_date(time_t clock)
* @param buf The buffer to store the string (minimum size: 128 bytes),
* or NULL to use temporary static storage.
*/
-char *short_date(time_t ts, char *buf)
+const char *short_date(time_t ts, char *buf)
{
struct tm *t = gmtime(&ts);
- char *timestr;
static char retbuf[128];
if (!buf)
@@ -313,17 +162,14 @@ char *short_date(time_t ts, char *buf)
if (!t)
return NULL;
- timestr = asctime(t);
- if (!timestr)
+ if (!strftime(buf, 128, "%a %b %d %H:%M:%S %Y", t))
return NULL;
- strlcpy(buf, timestr, 128);
- stripcrlf(buf);
return buf;
}
/** Return a string with the "pretty date" - yeah, another variant */
-char *pretty_date(time_t t)
+const char *pretty_date(time_t t)
{
static char buf[128];
struct tm *tm;
@@ -347,62 +193,53 @@ char *pretty_date(time_t t)
* string marker (`\-`). returns the 'fixed' string or "*" if the string
* was NULL length or a NULL pointer.
*/
-char *check_string(char *s)
+const char *check_string(const char *s)
{
+ static char buf[512];
static char star[2] = "*";
- char *str = s;
+ const char *str = s;
if (BadPtr(s))
return star;
for (; *s; s++)
+ {
if (isspace(*s))
{
- *s = '\0';
+ /* Because this is an unlikely scenario, we have
+ * delayed the copy until here:
+ */
+ strlncpy(buf, s, sizeof(buf), s - str);
+ str = buf;
break;
}
+ }
return (BadPtr(str)) ? star : str;
}
/** Create a user@host based on the provided name and host */
-char *make_user_host(char *name, char *host)
+char *make_user_host(const char *name, const char *host)
{
static char namebuf[USERLEN + HOSTLEN + 6];
- char *s = namebuf;
- memset(namebuf, 0, sizeof(namebuf));
- name = check_string(name);
- strlcpy(s, name, USERLEN + 1);
- s += strlen(s);
- *s++ = '@';
- host = check_string(host);
- strlcpy(s, host, HOSTLEN + 1);
- s += strlen(s);
- *s = '\0';
- return (namebuf);
+ strlncpy(namebuf, check_string(name), sizeof(namebuf), USERLEN+1);
+ strlcat(namebuf, "@", sizeof(namebuf));
+ strlncat(namebuf, check_string(host), sizeof(namebuf), HOSTLEN+1);
+ return namebuf;
}
/** Create a nick!user@host string based on the provided variables.
* If any of the variables are NULL, it becomes * (asterisk)
* This is the reentrant safe version.
*/
-char *make_nick_user_host_r(char *namebuf, char *nick, char *name, char *host)
+char *make_nick_user_host_r(char *namebuf, size_t namebuflen, const char *nick, const char *name, const char *host)
{
- char *s = namebuf;
-
- nick = check_string(nick);
- strlcpy(namebuf, nick, NICKLEN + 1);
- s += strlen(s);
- *s++ = '!';
- name = check_string(name);
- strlcpy(s, name, USERLEN + 1);
- s += strlen(s);
- *s++ = '@';
- host = check_string(host);
- strlcpy(s, host, HOSTLEN + 1);
- s += strlen(s);
- *s = '\0';
+ strlncpy(namebuf, check_string(nick), namebuflen, NICKLEN+1);
+ strlcat(namebuf, "!", namebuflen);
+ strlncat(namebuf, check_string(name), namebuflen, USERLEN+1);
+ strlcat(namebuf, "@", namebuflen);
+ strlncat(namebuf, check_string(host), namebuflen, HOSTLEN+1);
return namebuf;
}
@@ -410,18 +247,18 @@ char *make_nick_user_host_r(char *namebuf, char *nick, char *name, char *host)
* If any of the variables are NULL, it becomes * (asterisk)
* This version uses static storage.
*/
-char *make_nick_user_host(char *nick, char *name, char *host)
+char *make_nick_user_host(const char *nick, const char *name, const char *host)
{
static char namebuf[NICKLEN + USERLEN + HOSTLEN + 24];
- return make_nick_user_host_r(namebuf, nick, name, host);
+ return make_nick_user_host_r(namebuf, sizeof(namebuf), nick, name, host);
}
/** Similar to ctime() but without a potential newline and
* also takes a time_t value rather than a pointer.
*/
-char *myctime(time_t value)
+const char *myctime(time_t value)
{
static char buf[28];
char *p;
@@ -457,7 +294,7 @@ char *myctime(time_t value)
** to internal buffer (nbuf). *NEVER* use the returned pointer
** to modify what it points!!!
*/
-char *get_client_name(Client *client, int showip)
+const char *get_client_name(Client *client, int showip)
{
static char nbuf[HOSTLEN * 2 + USERLEN + 5];
@@ -482,7 +319,7 @@ char *get_client_name(Client *client, int showip)
return client->name;
}
-char *get_client_host(Client *client)
+const char *get_client_host(Client *client)
{
static char nbuf[HOSTLEN * 2 + USERLEN + 5];
@@ -500,9 +337,9 @@ char *get_client_host(Client *client)
/*
* Set sockhost to 'host'. Skip the user@ part of 'host' if necessary.
*/
-void set_sockhost(Client *client, char *host)
+void set_sockhost(Client *client, const char *host)
{
- char *s;
+ const char *s;
if ((s = strchr(host, '@')))
s++;
else
@@ -516,7 +353,7 @@ int on_dccallow_list(Client *to, Client *from)
Link *lp;
for(lp = to->user->dccallow; lp; lp = lp->next)
- if(lp->flags == DCC_LINK_ME && lp->value.client == from)
+ if (lp->flags == DCC_LINK_ME && lp->value.client == from)
return 1;
return 0;
}
@@ -538,11 +375,11 @@ void remove_dcc_references(Client *client)
acptr = lp->value.client;
for(found = 0, lpp = &(acptr->user->dccallow); *lpp; lpp=&((*lpp)->next))
{
- if(lp->flags == (*lpp)->flags)
+ if (lp->flags == (*lpp)->flags)
continue; /* match only opposite types for sanity */
- if((*lpp)->value.client == client)
+ if ((*lpp)->value.client == client)
{
- if((*lpp)->flags == DCC_LINK_ME)
+ if ((*lpp)->flags == DCC_LINK_ME)
{
sendto_one(acptr, NULL, ":%s %d %s :%s has been removed from "
"your DCC allow list for signing off",
@@ -556,38 +393,19 @@ void remove_dcc_references(Client *client)
}
}
- if(!found)
- sendto_realops("[BUG] remove_dcc_references: %s was in dccallowme "
- "list[%d] of %s but not in dccallowrem list!",
- acptr->name, lp->flags, client->name);
+ if (!found)
+ {
+ unreal_log(ULOG_WARNING, "main", "BUG_REMOVE_DCC_REFERENCES", acptr,
+ "[BUG] remove_dcc_references: $client was in dccallowme "
+ "list of $existing_client but not in dccallowrem list!",
+ log_data_client("existing_client", client));
+ }
free_link(lp);
lp = nextlp;
}
}
-/*
- * Recursively send QUITs and SQUITs for cptr and all of it's dependent
- * clients. A server needs the client QUITs if it does not support NOQUIT.
- * - kaniini
- */
-static void recurse_send_quits(Client *cptr, Client *client, Client *from, Client *to,
- MessageTag *mtags, const char *comment, const char *splitstr)
-{
- Client *acptr, *next;
-
- list_for_each_entry_safe(acptr, next, &global_server_list, client_node)
- {
- if (acptr->srvptr != client)
- continue;
-
- recurse_send_quits(cptr, acptr, from, to, mtags, comment, splitstr);
- }
-
- if (cptr == client && to != from && !(to->direction && (to->direction == from)))
- sendto_one(to, mtags, "SQUIT %s :%s", client->name, comment);
-}
-
/*
* Remove all clients that depend on source_p; assumes all (S)QUITs have
* already been sent. we make sure to exit a server's dependent clients
@@ -600,7 +418,7 @@ static void recurse_remove_clients(Client *client, MessageTag *mtags, const char
list_for_each_entry_safe(acptr, next, &client_list, client_node)
{
- if (acptr->srvptr != client)
+ if (acptr->uplink != client)
continue;
exit_one_client(acptr, mtags, comment);
@@ -608,7 +426,7 @@ static void recurse_remove_clients(Client *client, MessageTag *mtags, const char
list_for_each_entry_safe(acptr, next, &global_server_list, client_node)
{
- if (acptr->srvptr != client)
+ if (acptr->uplink != client)
continue;
recurse_remove_clients(acptr, mtags, comment);
@@ -626,7 +444,10 @@ static void remove_dependents(Client *client, Client *from, MessageTag *mtags, c
Client *acptr;
list_for_each_entry(acptr, &global_server_list, client_node)
- recurse_send_quits(client, client, from, acptr, mtags, comment, splitstr);
+ {
+ if (acptr != from && !(acptr->direction && (acptr->direction == from)))
+ sendto_one(acptr, mtags, "SQUIT %s :%s", client->name, comment);
+ }
recurse_remove_clients(client, mtags, splitstr);
}
@@ -647,18 +468,14 @@ static void exit_one_client(Client *client, MessageTag *mtags_i, const char *com
MessageTag *mtags_o = NULL;
if (!MyUser(client))
- RunHook3(HOOKTYPE_REMOTE_QUIT, client, mtags_i, comment);
+ RunHook(HOOKTYPE_REMOTE_QUIT, client, mtags_i, comment);
new_message_special(client, mtags_i, &mtags_o, ":%s QUIT", client->name);
sendto_local_common_channels(client, NULL, 0, mtags_o, ":%s QUIT :%s", client->name, comment);
free_message_tags(mtags_o);
while ((mp = client->user->channel))
- remove_user_from_channel(client, mp->channel);
-
- /* Clean up invitefield */
- while ((lp = client->user->invited))
- del_invite(client, lp->value.channel);
+ remove_user_from_channel(client, mp->channel, 1);
/* again, this is all that is needed */
/* Clean up dccallow list and (if needed) notify other clients
@@ -687,8 +504,6 @@ static void exit_one_client(Client *client, MessageTag *mtags_i, const char *com
}
if (*client->name)
del_from_client_hash_table(client->name, client);
- if (IsUser(client))
- hash_check_watch(client, RPL_LOGOFF);
if (remote_rehash_client == client)
remote_rehash_client = NULL; /* client did a /REHASH and QUIT before rehash was complete */
remove_client_from_list(client);
@@ -699,7 +514,7 @@ static void exit_one_client(Client *client, MessageTag *mtags_i, const char *com
* @param recv_mtags Message tags to use as a base (if any).
* @param comment The (s)quit message
*/
-void exit_client(Client *client, MessageTag *recv_mtags, char *comment)
+void exit_client(Client *client, MessageTag *recv_mtags, const char *comment)
{
exit_client_ex(client, client->direction, recv_mtags, comment);
}
@@ -709,7 +524,24 @@ void exit_client(Client *client, MessageTag *recv_mtags, char *comment)
* @param recv_mtags Message tags to use as a base (if any).
* @param comment The (s)quit message
*/
-void exit_client_ex(Client *client, Client *origin, MessageTag *recv_mtags, char *comment)
+void exit_client_fmt(Client *client, MessageTag *recv_mtags, FORMAT_STRING(const char *pattern), ...)
+{
+ char comment[512];
+
+ va_list vl;
+ va_start(vl, pattern);
+ vsnprintf(comment, sizeof(comment), pattern, vl);
+ va_end(vl);
+
+ exit_client_ex(client, client->direction, recv_mtags, comment);
+}
+
+/** Exit this IRC client, and all the dependents (users, servers) if this is a server.
+ * @param client The client to exit.
+ * @param recv_mtags Message tags to use as a base (if any).
+ * @param comment The (s)quit message
+ */
+void exit_client_ex(Client *client, Client *origin, MessageTag *recv_mtags, const char *comment)
{
long long on_for;
ConfigItem_listen *listen_conf;
@@ -741,23 +573,25 @@ void exit_client_ex(Client *client, Client *origin, MessageTag *recv_mtags, char
}
if (IsUser(client))
irccounts.me_clients--;
- if (client->serv && client->serv->conf)
+ if (client->server && client->server->conf)
{
- client->serv->conf->refcount--;
- Debug((DEBUG_ERROR, "reference count for %s (%s) is now %d",
- client->name, client->serv->conf->servername, client->serv->conf->refcount));
- if (!client->serv->conf->refcount
- && client->serv->conf->flag.temporary)
+ client->server->conf->refcount--;
+ if (!client->server->conf->refcount
+ && client->server->conf->flag.temporary)
{
- Debug((DEBUG_ERROR, "deleting temporary block %s", client->serv->conf->servername));
- delete_linkblock(client->serv->conf);
- client->serv->conf = NULL;
+ delete_linkblock(client->server->conf);
+ client->server->conf = NULL;
}
}
if (IsServer(client))
{
irccounts.me_servers--;
- ircd_log(LOG_SERVER, "SQUIT %s (%s)", client->name, comment);
+ if (!IsServerDisconnectLogged(client))
+ {
+ unreal_log(ULOG_ERROR, "link", "LINK_DISCONNECTED", client,
+ "Lost server link to $client [$client.ip]: $reason",
+ log_data_string("reason", comment));
+ }
}
free_pending_net(client);
if (client->local->listener)
@@ -774,24 +608,17 @@ void exit_client_ex(Client *client, Client *origin, MessageTag *recv_mtags, char
SetClosing(client);
if (IsUser(client))
{
- RunHook3(HOOKTYPE_LOCAL_QUIT, client, recv_mtags, comment);
- sendto_connectnotice(client, 1, comment);
- /* Clean out list and watch structures -Donwulff */
- hash_del_watch_list(client);
- on_for = TStime() - client->local->firsttime;
- if (IsHidden(client))
- ircd_log(LOG_CLIENT, "Disconnect - (%lld:%lld:%lld) %s!%s@%s [%s] [vhost: %s] (%s)",
- on_for / 3600, (on_for % 3600) / 60, on_for % 60,
- client->name, client->user->username,
- client->user->realhost, GetIP(client), client->user->virthost, comment);
- else
- ircd_log(LOG_CLIENT, "Disconnect - (%lld:%lld:%lld) %s!%s@%s [%s] (%s)",
- on_for / 3600, (on_for % 3600) / 60, on_for % 60,
- client->name, client->user->username, client->user->realhost, GetIP(client), comment);
+ long connected_time = TStime() - client->local->creationtime;
+ RunHook(HOOKTYPE_LOCAL_QUIT, client, recv_mtags, comment);
+ unreal_log(ULOG_INFO, "connect", "LOCAL_CLIENT_DISCONNECT", client,
+ "Client exiting: $client ($client.user.username@$client.hostname) [$client.ip] ($reason)",
+ log_data_string("extended_client_info", get_connect_extinfo(client)),
+ log_data_string("reason", comment),
+ log_data_integer("connected_time", connected_time));
} else
if (IsUnknown(client))
{
- RunHook3(HOOKTYPE_UNKUSER_QUIT, client, recv_mtags, comment);
+ RunHook(HOOKTYPE_UNKUSER_QUIT, client, recv_mtags, comment);
}
if (client->local->fd >= 0 && !IsConnecting(client))
@@ -803,8 +630,14 @@ void exit_client_ex(Client *client, Client *origin, MessageTag *recv_mtags, char
}
else if (IsUser(client) && !IsULine(client))
{
- if (client->srvptr != &me)
- sendto_fconnectnotice(client, 1, comment);
+ if (client->uplink != &me)
+ {
+ unreal_log(ULOG_INFO, "connect", "REMOTE_CLIENT_DISCONNECT", client,
+ "Client exiting: $client ($client.user.username@$client.hostname) [$client.ip] ($reason)",
+ log_data_string("extended_client_info", get_connect_extinfo(client)),
+ log_data_string("reason", comment),
+ log_data_string("from_server_name", client->user->server));
+ }
}
/*
@@ -816,16 +649,16 @@ void exit_client_ex(Client *client, Client *origin, MessageTag *recv_mtags, char
{
char splitstr[HOSTLEN + HOSTLEN + 2];
- assert(client->serv != NULL && client->srvptr != NULL);
+ assert(client->server != NULL && client->uplink != NULL);
if (FLAT_MAP)
strlcpy(splitstr, "*.net *.split", sizeof splitstr);
else
- ircsnprintf(splitstr, sizeof splitstr, "%s %s", client->srvptr->name, client->name);
+ ircsnprintf(splitstr, sizeof splitstr, "%s %s", client->uplink->name, client->name);
remove_dependents(client, origin, recv_mtags, comment, splitstr);
- RunHook2(HOOKTYPE_SERVER_QUIT, client, recv_mtags);
+ RunHook(HOOKTYPE_SERVER_QUIT, client, recv_mtags);
}
else if (IsUser(client) && !IsKilled(client))
{
@@ -845,7 +678,7 @@ void initstats(void)
}
/** Verify operator count, to catch bugs introduced by flawed services */
-void verify_opercount(Client *orig, char *tag)
+void verify_opercount(Client *orig, const char *tag)
{
int counted = 0;
Client *client;
@@ -858,31 +691,44 @@ void verify_opercount(Client *orig, char *tag)
}
if (counted == irccounts.operators)
return;
- snprintf(text, sizeof(text), "[BUG] operator count bug! value in /lusers is '%d', we counted '%d', "
- "user='%s', userserver='%s', tag=%s. Corrected. ",
- irccounts.operators, counted, orig->name,
- orig->srvptr ? orig->srvptr->name : "", tag ? tag : "");
-#ifdef DEBUGMODE
- sendto_realops("%s", text);
-#endif
- ircd_log(LOG_ERROR, "%s", text);
+ unreal_log(ULOG_WARNING, "main", "BUG_LUSERS_OPERS", orig,
+ "[BUG] Operator count bug at $where! Value in /LUSERS is $opers, "
+ "we counted $counted_opers, "
+ "triggered by $client.details on $client.user.servername",
+ log_data_integer("opers", irccounts.operators),
+ log_data_integer("counted_opers", counted),
+ log_data_string("where", tag));
irccounts.operators = counted;
}
/** Check if the specified hostname does not contain forbidden characters.
- * RETURNS:
- * 1 if ok, 0 if rejected.
+ * @param host The host name to check
+ * @param strict If set to 1 then we also check if the hostname
+ * resembles an IP address (eg contains ':') and
+ * some other stuff that we don't consider valid
+ * in actual DNS names (eg '/').
+ * @returns 1 if valid, 0 if not.
*/
-int valid_host(char *host)
+int valid_host(const char *host, int strict)
{
- char *p;
+ const char *p;
+
+ if (!*host)
+ return 0; /* must at least contain something */
if (strlen(host) > HOSTLEN)
return 0; /* too long hosts are invalid too */
- for (p=host; *p; p++)
- if (!isalnum(*p) && (*p != '_') && (*p != '-') && (*p != '.') && (*p != ':') && (*p != '/'))
- return 0;
+ if (strict)
+ {
+ for (p=host; *p; p++)
+ if (!isalnum(*p) && !strchr("_-.", *p))
+ return 0;
+ } else {
+ for (p=host; *p; p++)
+ if (!isalnum(*p) && !strchr("_-.:/", *p))
+ return 0;
+ }
return 1;
}
@@ -890,7 +736,7 @@ int valid_host(char *host)
/*|| BAN ACTION ROUTINES FOLLOW ||*/
/** Converts a banaction string (eg: "kill") to an integer value (eg: BAN_ACT_KILL) */
-BanAction banact_stringtoval(char *s)
+BanAction banact_stringtoval(const char *s)
{
BanActTable *b;
@@ -923,7 +769,7 @@ char banact_valtochar(BanAction val)
}
/** Converts a banaction value (eg: BAN_ACT_KLINE) to a string (eg: "kline") */
-char *banact_valtostring(BanAction val)
+const char *banact_valtostring(BanAction val)
{
BanActTable *b;
@@ -936,7 +782,7 @@ char *banact_valtostring(BanAction val)
/*|| BAN TARGET ROUTINES FOLLOW ||*/
/** Extract target flags from string 's'. */
-int spamfilter_gettargets(char *s, Client *client)
+int spamfilter_gettargets(const char *s, Client *client)
{
SpamfilterTargetTable *e;
int flags = 0;
@@ -959,7 +805,7 @@ int flags = 0;
}
/** Convert a string with a targetname to an integer value */
-int spamfilter_getconftargets(char *s)
+int spamfilter_getconftargets(const char *s)
{
SpamfilterTargetTable *e;
@@ -972,9 +818,9 @@ SpamfilterTargetTable *e;
/** Create a string with (multiple) targets from an integer mask */
char *spamfilter_target_inttostring(int v)
{
-static char buf[128];
-SpamfilterTargetTable *e;
-char *p = buf;
+ static char buf[128];
+ SpamfilterTargetTable *e;
+ char *p = buf;
for (e = &spamfiltertargettable[0]; e->value; e++)
if (v & e->value)
@@ -1033,7 +879,7 @@ char *unreal_encodespace(char *s)
}
/** This is basically only used internally by match_spamfilter()... */
-char *cmdname_by_spamftarget(int target)
+const char *cmdname_by_spamftarget(int target)
{
SpamfilterTargetTable *e;
@@ -1044,7 +890,7 @@ char *cmdname_by_spamftarget(int target)
}
/** Returns 1 if this is a channel from set::auto-join or set::oper-auto-join */
-int is_autojoin_chan(char *chname)
+int is_autojoin_chan(const char *chname)
{
char buf[512];
char *p, *name;
@@ -1070,40 +916,6 @@ int is_autojoin_chan(char *chname)
return 0;
}
-/** Convert a character like 'o' to the corresponding channel flag
- * like CHFL_CHANOP.
- * @param c The mode character. The only valid values are: vhoaq
- * @returns One of CHFL_* or 0 if an invalid mode character is specified.
- */
-int char_to_channelflag(char c)
-{
- if (c == 'v')
- return CHFL_VOICE;
- else if (c == 'h')
- return CHFL_HALFOP;
- else if (c == 'o')
- return CHFL_CHANOP;
- else if (c == 'a')
- return CHFL_CHANADMIN;
- else if (c == 'q')
- return CHFL_CHANOWNER;
- return 0;
-}
-
-// FIXME: should detect ce_vardata)
- safe_strdup(m->mask, ce->ce_vardata);
+ if (ce->value)
+ safe_strdup(m->mask, ce->value);
else
- safe_strdup(m->mask, ce->ce_varname);
+ safe_strdup(m->mask, ce->name);
add_ListItem((ListStruct *)m, (ListStruct **)head);
}
@@ -1136,10 +948,10 @@ static void unreal_add_mask(ConfigItem_mask **head, ConfigEntry *ce)
/** Add mask entries from config */
void unreal_add_masks(ConfigItem_mask **head, ConfigEntry *ce)
{
- if (ce->ce_entries)
+ if (ce->items)
{
ConfigEntry *cep;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
unreal_add_mask(head, cep);
} else
{
@@ -1147,29 +959,108 @@ void unreal_add_masks(ConfigItem_mask **head, ConfigEntry *ce)
}
}
-/** Check if a client matches any of the masks in the mask list */
-int unreal_mask_match(Client *client, ConfigItem_mask *m)
+/** Check if a client matches any of the masks in the mask list.
+ * The following rules apply:
+ * - If you have only negating entries, like '!abc' and '!def', then
+ * we assume an implicit * rule first, since that is clearly what
+ * the user wants.
+ * - If you have a mix, like '*.com', '!irc1*', '!irc2*' then the
+ * implicit * is dropped and we assume you only want to match *.com,
+ * with the exception of irc1*.com and irc2*.com.
+ * - If you only have normal entries without ! then things are
+ * as they always are.
+ * @param client The client to run the mask match against
+ * @param mask The mask entry from the config file
+ * @returns 1 on match, 0 on non-match.
+ */
+int unreal_mask_match(Client *client, ConfigItem_mask *mask)
{
- for (; m; m = m->next)
+ int retval = 1;
+ ConfigItem_mask *m;
+
+ if (!mask)
+ return 0; /* Empty mask block is no match */
+
+ /* First check normal matches (without ! prefix) */
+ for (m = mask; m; m = m->next)
{
- /* With special support for '!' prefix (negative matching like "!192.168.*") */
- if (m->mask[0] == '!')
+ if (m->mask[0] != '!')
{
- if (!match_user(m->mask+1, client, MATCH_CHECK_REAL))
- return 1;
- } else {
- if (match_user(m->mask, client, MATCH_CHECK_REAL))
- return 1;
+ retval = 0; /* no implicit * */
+ if (match_user(m->mask, client, MATCH_CHECK_REAL|MATCH_CHECK_EXTENDED))
+ {
+ retval = 1;
+ break;
+ }
}
}
- return 0;
+ if (retval)
+ {
+ /* We matched. Check for exceptions (with ! prefix) */
+ for (m = mask; m; m = m->next)
+ {
+ if ((m->mask[0] == '!') && match_user(m->mask+1, client, MATCH_CHECK_REAL|MATCH_CHECK_EXTENDED))
+ return 0;
+ }
+ }
+
+ return retval;
+}
+
+/** Check if a string matches any of the masks in the mask list.
+ * The following rules apply:
+ * - If you have only negating entries, like '!abc' and '!def', then
+ * we assume an implicit * rule first, since that is clearly what
+ * the user wants.
+ * - If you have a mix, like '*.com', '!irc1*', '!irc2*' then the
+ * implicit * is dropped and we assume you only want to match *.com,
+ * with the exception of irc1*.com and irc2*.com.
+ * - If you only have normal entries without ! then things are
+ * as they always are.
+ * @param name The name to run the mask matching on
+ * @param mask The mask entry from the config file
+ * @returns 1 on match, 0 on non-match.
+ */
+int unreal_mask_match_string(const char *name, ConfigItem_mask *mask)
+{
+ int retval = 1;
+ ConfigItem_mask *m;
+
+ if (!mask)
+ return 0; /* Empty mask block is no match */
+
+ /* First check normal matches (without ! prefix) */
+ for (m = mask; m; m = m->next)
+ {
+ if (m->mask[0] != '!')
+ {
+ retval = 0; /* no implicit * */
+ if (match_simple(m->mask, name))
+ {
+ retval = 1;
+ break;
+ }
+ }
+ }
+
+ if (retval)
+ {
+ /* We matched. Check for exceptions (with ! prefix) */
+ for (m = mask; m; m = m->next)
+ {
+ if ((m->mask[0] == '!') && match_simple(m->mask+1, name))
+ return 0;
+ }
+ }
+
+ return retval;
}
/** Our own strcasestr implementation because strcasestr is
* often not available or is not working correctly.
*/
-char *our_strcasestr(char *haystack, char *needle)
+char *our_strcasestr(const char *haystack, const char *needle)
{
int i;
int nlength = strlen(needle);
@@ -1182,12 +1073,12 @@ char *our_strcasestr(char *haystack, char *needle)
return NULL;
if (nlength <= 0)
- return haystack;
+ return (char *)haystack;
for (i = 0; i <= (hlength - nlength); i++)
{
if (strncasecmp (haystack + i, needle, nlength) == 0)
- return haystack + i;
+ return (char *)(haystack + i);
}
return NULL; /* not found */
@@ -1203,7 +1094,7 @@ char *our_strcasestr(char *haystack, char *needle)
* @param from Who added this entry
* @param skip Which server(-side) to skip broadcasting this entry to.
*/
-int swhois_add(Client *client, char *tag, int priority, char *swhois, Client *from, Client *skip)
+int swhois_add(Client *client, const char *tag, int priority, const char *swhois, Client *from, Client *skip)
{
SWhois *s;
@@ -1237,7 +1128,7 @@ int swhois_add(Client *client, char *tag, int priority, char *swhois, Client *fr
* @param skip Which server(-side) to skip broadcasting this entry to.
* @note If you use swhois "*" then it will remove all swhois titles for that tag
*/
-int swhois_delete(Client *client, char *tag, char *swhois, Client *from, Client *skip)
+int swhois_delete(Client *client, const char *tag, const char *swhois, Client *from, Client *skip)
{
SWhois *s, *s_next;
int ret = -1; /* default to 'not found' */
@@ -1277,8 +1168,6 @@ int IsWebsocket(Client *client)
return (MyConnect(client) && moddata_client(client, md).ptr) ? 1 : 0;
}
-extern void send_raw_direct(Client *user, FORMAT_STRING(const char *pattern), ...);
-
/** Generic function to inform the user he/she has been banned.
* @param client The affected client.
* @param bantype The ban type, such as: "K-Lined", "G-Lined" or "realname".
@@ -1290,7 +1179,7 @@ extern void send_raw_direct(Client *user, FORMAT_STRING(const char *pattern), ..
*
* @note This function will call exit_client() appropriately.
*/
-void banned_client(Client *client, char *bantype, char *reason, int global, int noexit)
+void banned_client(Client *client, const char *bantype, const char *reason, int global, int noexit)
{
char buf[512];
char *fmt = global ? iConf.reject_message_gline : iConf.reject_message_kline;
@@ -1369,7 +1258,7 @@ char *mystpcpy(char *dst, const char *src)
* so similar to what strlen() would have returned.
* @note Caller must ensure that the buffer 'buf' is of sufficient size.
*/
-size_t add_sjsby(char *buf, char *setby, time_t seton)
+size_t add_sjsby(char *buf, const char *setby, time_t seton)
{
char tbuf[32];
char *p = buf;
@@ -1399,14 +1288,14 @@ size_t add_sjsby(char *buf, char *setby, time_t seton)
* sendto_server(client, 0, 0, recv_mtags, ":%s SOMECOMMAND %s", client->name, buf);
* @endcode
*/
-void concat_params(char *buf, int len, int parc, char *parv[])
+void concat_params(char *buf, int len, int parc, const char *parv[])
{
int i;
*buf = '\0';
for (i = 1; i < parc; i++)
{
- char *param = parv[i];
+ const char *param = parv[i];
if (!param)
break;
@@ -1476,7 +1365,6 @@ void new_message(Client *sender, MessageTag *recv_mtags, MessageTag **mtag_list)
* This function calls modules so they can add tags, such as:
* msgid, time and account.
* This special version deals in a special way with msgid in particular.
- * TODO: document
* The pattern and vararg create a 'signature', this is normally
* identical to the message that is sent to clients (end-users).
* For example ":xyz JOIN #chan".
@@ -1509,7 +1397,7 @@ void parse_message_tags_default_handler(Client *client, char **str, MessageTag *
* This is only used if the 'mtags' module is NOT loaded,
* which would be quite unusual, but possible.
*/
-char *mtags_to_string_default_handler(MessageTag *m, Client *client)
+const char *mtags_to_string_default_handler(MessageTag *m, Client *client)
{
return NULL;
}
@@ -1568,6 +1456,11 @@ void labeled_response_force_end_default_handler(void)
{
}
+/** Ad default handler for if the slog module is not loaded */
+void do_unreal_log_remote_deliver_default_handler(LogLevel loglevel, const char *subsystem, const char *event_id, MultiLine *msg, const char *json_serialized)
+{
+}
+
/** my_timegm: mktime()-like function which will use GMT/UTC.
* Strangely enough there is no standard function for this.
* On some *NIX OS's timegm() may be available, sometimes only
@@ -1612,16 +1505,10 @@ time_t server_time_to_unix_time(const char *tbuf)
time_t ret;
if (!tbuf)
- {
- ircd_log(LOG_ERROR, "[BUG] server_time_to_unix_time() failed for NULL item. Incorrect S2S traffic?");
return 0;
- }
if (strlen(tbuf) < 20)
- {
- ircd_log(LOG_ERROR, "[BUG] server_time_to_unix_time() failed for short item '%s'", tbuf);
return 0;
- }
memset(&tm, 0, sizeof(tm));
ret = sscanf(tbuf, "%d-%d-%dT%d:%d:%d.%dZ",
@@ -1634,10 +1521,7 @@ time_t server_time_to_unix_time(const char *tbuf)
&dontcare);
if (ret != 7)
- {
- ircd_log(LOG_ERROR, "[BUG] server_time_to_unix_time() failed for '%s'", tbuf);
return 0;
- }
tm.tm_year -= 1900;
tm.tm_mon -= 1;
@@ -1646,6 +1530,68 @@ time_t server_time_to_unix_time(const char *tbuf)
return ret;
}
+/** Convert an RFC 2616 timestamp (used in HTTP headers) to UNIX time */
+time_t rfc2616_time_to_unix_time(const char *tbuf)
+{
+ struct tm tm;
+ int dontcare = 0;
+ time_t ret;
+ char month[8];
+ int i;
+
+ if (!tbuf)
+ return 0;
+
+ if (strlen(tbuf) < 20)
+ return 0;
+
+ memset(&tm, 0, sizeof(tm));
+ *month = '\0';
+ ret = sscanf(tbuf, "%*[a-zA-Z,] %d %3s %d %d:%d:%d",
+ &tm.tm_mday, month, &tm.tm_year,
+ &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
+
+ if (ret < 6)
+ return 0;
+
+ for (i=0; i < 12; i++)
+ {
+ if (!strcmp(short_months[i], month))
+ {
+ tm.tm_mon = i;
+ break;
+ }
+ }
+ if (i == 12)
+ return 0; /* Month not found */
+ if (tm.tm_year < 1900)
+ return 0;
+
+ tm.tm_year -= 1900;
+ ret = my_timegm(&tm);
+ return ret; /* can still be 0 */
+}
+
+/** Returns an RFC 2616 timestamp (used in HTTP headers) */
+const char *rfc2616_time(time_t clock)
+{
+ static char buf[80], plus;
+ struct tm *lt, *gm;
+ struct tm gmbuf;
+ int minswest;
+
+ if (!clock)
+ time(&clock);
+ gm = gmtime(&clock);
+
+ snprintf(buf, sizeof(buf),
+ "%s, %02d %.3s %4d %02d:%02d:%02d GMT",
+ short_weekdays[gm->tm_wday], gm->tm_mday, short_months[gm->tm_mon],
+ gm->tm_year + 1900, gm->tm_hour, gm->tm_min, gm->tm_sec);
+
+ return buf;
+}
+
/** Write a 64 bit integer to a file.
* @param fd File descriptor
* @param t The value to write
@@ -1735,7 +1681,7 @@ int write_data(FILE *fd, const void *buf, size_t len)
* Note that 'x' can safely be NULL.
* @returns 1 on success, 0 on failure.
*/
-int write_str(FILE *fd, char *x)
+int write_str(FILE *fd, const char *x)
{
uint16_t len;
@@ -1814,19 +1760,31 @@ void binarytohex(void *data, size_t len, char *str)
str[n] = '\0';
}
-/** Generates an MD5 checksum.
+/** Generates an MD5 checksum - binary version.
* @param mdout[out] Buffer to store result in, the result will be 16 bytes in binary
* (not ascii printable!).
* @param src[in] The input data used to generate the checksum.
* @param n[in] Length of data.
+ * @deprecated The MD5 algorithm is deprecated and insecure,
+ * so only use this if absolutely needed.
*/
void DoMD5(char *mdout, const char *src, unsigned long n)
{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ unsigned int md_len;
+ EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
+ if (EVP_DigestInit_ex(mdctx, md5_function, NULL) != 1)
+ abort();
+ EVP_DigestUpdate(mdctx, src, n);
+ EVP_DigestFinal_ex(mdctx, mdout, &md_len);
+ EVP_MD_CTX_free(mdctx);
+#else
MD5_CTX hash;
MD5_Init(&hash);
MD5_Update(&hash, src, n);
MD5_Final(mdout, &hash);
+#endif
}
/** Generates an MD5 checksum - ASCII printable string (0011223344..etc..).
@@ -1834,6 +1792,8 @@ void DoMD5(char *mdout, const char *src, unsigned long n)
* 32 characters + nul terminator, so needs to be at least 33 characters.
* @param src[in] The input data used to generate the checksum.
* @param n[in] Length of data.
+ * @deprecated The MD5 algorithm is deprecated and insecure,
+ * so only use this if absolutely needed.
*/
char *md5hash(char *dst, const char *src, unsigned long n)
{
@@ -1844,6 +1804,32 @@ char *md5hash(char *dst, const char *src, unsigned long n)
return dst;
}
+/** Generates a SHA256 checksum - binary version.
+ * Most people will want to use sha256hash() instead which outputs hex.
+ * @param dst[out] Buffer to store result in, which needs to be 32 bytes in length
+ * (SHA256_DIGEST_LENGTH).
+ * @param src[in] The input data used to generate the checksum.
+ * @param n[in] Length of data.
+ */
+void sha256hash_binary(char *dst, const char *src, unsigned long n)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ unsigned int md_len;
+ EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
+ if (EVP_DigestInit_ex(mdctx, sha256_function, NULL) != 1)
+ abort();
+ EVP_DigestUpdate(mdctx, src, n);
+ EVP_DigestFinal_ex(mdctx, dst, &md_len);
+ EVP_MD_CTX_free(mdctx);
+#else
+ SHA256_CTX hash;
+
+ SHA256_Init(&hash);
+ SHA256_Update(&hash, src, n);
+ SHA256_Final(dst, &hash);
+#endif
+}
+
/** Generates a SHA256 checksum - ASCII printable string (0011223344..etc..).
* @param dst[out] Buffer to store result in, which needs to be 65 bytes minimum.
* @param src[in] The input data used to generate the checksum.
@@ -1851,18 +1837,15 @@ char *md5hash(char *dst, const char *src, unsigned long n)
*/
char *sha256hash(char *dst, const char *src, unsigned long n)
{
- SHA256_CTX hash;
char binaryhash[SHA256_DIGEST_LENGTH];
- SHA256_Init(&hash);
- SHA256_Update(&hash, src, n);
- SHA256_Final(binaryhash, &hash);
+ sha256hash_binary(binaryhash, src, n);
binarytohex(binaryhash, sizeof(binaryhash), dst);
return dst;
}
/** Calculate the SHA256 checksum of a file */
-char *sha256sum_file(const char *fname)
+const char *sha256sum_file(const char *fname)
{
FILE *fd;
char buf[2048];
@@ -1870,22 +1853,68 @@ char *sha256sum_file(const char *fname)
char binaryhash[SHA256_DIGEST_LENGTH];
static char hexhash[SHA256_DIGEST_LENGTH*2+1];
int n;
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ unsigned int md_len;
+ EVP_MD_CTX *mdctx;
+
+ mdctx = EVP_MD_CTX_new();
+ if (EVP_DigestInit_ex(mdctx, sha256_function, NULL) != 1)
+ abort();
+#else
+ SHA256_Init(&hash);
+#endif
fd = fopen(fname, "rb");
if (!fd)
return NULL;
- SHA256_Init(&hash);
while ((n = fread(buf, 1, sizeof(buf), fd)) > 0)
{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ EVP_DigestUpdate(mdctx, buf, n);
+#else
SHA256_Update(&hash, buf, n);
+#endif
}
fclose(fd);
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ EVP_DigestFinal_ex(mdctx, binaryhash, &md_len);
+ EVP_MD_CTX_free(mdctx);
+#else
SHA256_Final(binaryhash, &hash);
+#endif
binarytohex(binaryhash, sizeof(binaryhash), hexhash);
return hexhash;
}
+/** Generates a SHA1 checksum - binary version.
+ * @param dst[out] Buffer to store result in, which needs to be 32 bytes in length
+ * (SHA1_DIGEST_LENGTH).
+ * @param src[in] The input data used to generate the checksum.
+ * @param n[in] Length of data.
+ * @deprecated The SHA1 algorithm is deprecated and insecure,
+ * so only use this if absolutely needed.
+ */
+void sha1hash_binary(char *dst, const char *src, unsigned long n)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ unsigned int md_len;
+ EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
+ if (EVP_DigestInit_ex(mdctx, sha1_function, NULL) != 1)
+ abort();
+ EVP_DigestUpdate(mdctx, src, n);
+ EVP_DigestFinal_ex(mdctx, dst, &md_len);
+ EVP_MD_CTX_free(mdctx);
+#else
+ SHA_CTX hash;
+
+ SHA1_Init(&hash);
+ SHA1_Update(&hash, src, n);
+ SHA1_Final(dst, &hash);
+#endif
+}
+
/** Remove a suffix from a filename, eg ".c" (if it is present) */
char *filename_strip_suffix(const char *fname, const char *suffix)
{
@@ -1932,21 +1961,20 @@ int filename_has_suffix(const char *fname, const char *suffix)
return 0;
}
-/** Check if the specified file exists */
-int file_exists(char *file)
+/** Check if the specified file or directory exists */
+int file_exists(const char *file)
{
- FILE *fd;
-
- fd = fopen(file, "r");
- if (!fd)
- return 0;
-
- fclose(fd);
- return 1;
+#ifdef _WIN32
+ if (_access(file, 0) == 0)
+#else
+ if (access(file, 0) == 0)
+#endif
+ return 1;
+ return 0;
}
/** Get the file creation time */
-time_t get_file_time(char *fname)
+time_t get_file_time(const char *fname)
{
struct stat st;
@@ -1957,7 +1985,7 @@ time_t get_file_time(char *fname)
}
/** Get the size of a file */
-long get_file_size(char *fname)
+long get_file_size(const char *fname)
{
struct stat st;
@@ -1968,7 +1996,7 @@ long get_file_size(char *fname)
}
/** Add a line to a MultiLine list */
-void addmultiline(MultiLine **l, char *line)
+void addmultiline(MultiLine **l, const char *line)
{
MultiLine *m = safe_alloc(sizeof(MultiLine));
safe_strdup(m->line, line);
@@ -1987,8 +2015,27 @@ void freemultiline(MultiLine *l)
}
}
+/** Convert a line regular string containing \n's to a MultiLine linked list */
+MultiLine *line2multiline(const char *str)
+{
+ static char buf[8192];
+ char *p, *p2;
+ MultiLine *ml = NULL;
+
+ strlcpy(buf, str, sizeof(buf));
+ p = buf;
+ do {
+ p2 = strchr(p, '\n');
+ if (p2)
+ *p2++ = '\0';
+ addmultiline(&ml, p);
+ p = p2;
+ } while(p2 && *p2);
+ return ml;
+}
+
/** Convert a sendtype to a command string */
-char *sendtype_to_cmd(SendType sendtype)
+const char *sendtype_to_cmd(SendType sendtype)
{
if (sendtype == SEND_TYPE_PRIVMSG)
return "PRIVMSG";
@@ -2005,11 +2052,11 @@ char *sendtype_to_cmd(SendType sendtype)
* @param strict Whether to require UPPER+lower+digits
* @returns 1 if good, 0 if not.
*/
-int check_password_strength(char *pass, int min_length, int strict, char **err)
+int check_password_strength(const char *pass, int min_length, int strict, char **err)
{
- char has_lowercase=0, has_uppercase=0, has_digit=0;
- char *p;
static char buf[256];
+ char has_lowercase=0, has_uppercase=0, has_digit=0;
+ const char *p;
if (err)
*err = NULL;
@@ -2059,7 +2106,7 @@ int check_password_strength(char *pass, int min_length, int strict, char **err)
return 1;
}
-int valid_secret_password(char *pass, char **err)
+int valid_secret_password(const char *pass, char **err)
{
return check_password_strength(pass, 10, 1, err);
}
@@ -2082,6 +2129,34 @@ int running_interactively(void)
#endif
}
+int terminal_supports_color(void)
+{
+#ifndef _WIN32
+ char *s;
+
+ /* Yeah we check all of stdin, stdout, stderr, because
+ * or more may be redirected (bin/unrealircd >log 2>&1),
+ * and then we want to say no to color support.
+ */
+ if (!isatty(0) || !isatty(1) || !isatty(2))
+ return 0;
+
+ s = getenv("TERM");
+ /* Yeah this is a lazy way to detect color-capable terminals
+ * but it is good enough for me.
+ */
+ if (s)
+ {
+ if (strstr(s, "color") || strstr(s, "ansi"))
+ return 1;
+ }
+
+ return 0;
+#else
+ return 0;
+#endif
+}
+
/** Skip whitespace (if any) */
void skip_whitespace(char **p)
{
@@ -2096,3 +2171,201 @@ void read_until(char **p, char *stopchars)
{
for (; **p && !strchr(stopchars, **p); *p = *p + 1);
}
+
+void write_pidfile_failed(void)
+{
+ char *errstr = strerror(errno);
+ unreal_log(ULOG_WARNING, "config", "WRITE_PID_FILE_FAILED", NULL,
+ "Unable to write to pid file '$filename': $system_error",
+ log_data_string("filename", conf_files->pid_file),
+ log_data_string("system_error", errstr));
+}
+
+/** Write PID file */
+void write_pidfile(void)
+{
+#ifdef IRCD_PIDFILE
+ int fd;
+ char buff[20];
+ if ((fd = open(conf_files->pid_file, O_CREAT | O_WRONLY, 0600)) < 0)
+ {
+ write_pidfile_failed();
+ return;
+ }
+ ircsnprintf(buff, sizeof(buff), "%5d\n", (int)getpid());
+ if (write(fd, buff, strlen(buff)) < 0)
+ write_pidfile_failed();
+ if (close(fd) < 0)
+ write_pidfile_failed();
+#endif
+}
+
+/*
+ * Determines if the given string is a valid URL. Since libcurl
+ * supports telnet, ldap, and dict such strings are treated as
+ * invalid URLs here since we don't want them supported in
+ * unreal.
+ */
+int url_is_valid(const char *string)
+{
+ if (strstr(string, " ") || strstr(string, "\t"))
+ return 0;
+
+ if (strstr(string, "telnet://") == string ||
+ strstr(string, "ldap://") == string ||
+ strstr(string, "dict://") == string)
+ {
+ return 0;
+ }
+ return (strstr(string, "://") != NULL);
+}
+
+/** A displayable URL for in error messages and such.
+ * This leaves out any authentication information (user:pass)
+ * the URL may contain.
+ */
+const char *displayurl(const char *url)
+{
+ static char buf[512];
+ char *proto, *rest;
+
+ /* protocol://user:pass@host/etc.. */
+ rest = strchr(url, '@');
+
+ if (!rest)
+ return url; /* contains no auth information */
+
+ rest++; /* now points to the rest (remainder) of the URL */
+
+ proto = strstr(url, "://");
+ if (!proto || (proto > rest) || (proto == url))
+ return url; /* incorrectly formatted, just show entire URL. */
+
+ strlncpy(buf, url, sizeof(buf), proto - url);
+ strlcat(buf, "://***:***@", sizeof(buf));
+ strlcat(buf, rest, sizeof(buf));
+
+ return buf;
+}
+
+/*
+ * Returns the filename portion of the URL. The returned string
+ * is malloc()'ed and must be freed by the caller. If the specified
+ * URL does not contain a filename, a '-' is allocated and returned.
+ */
+char *url_getfilename(const char *url)
+{
+ const char *c, *start;
+
+ if ((c = strstr(url, "://")))
+ c += 3;
+ else
+ c = url;
+
+ while (*c && *c != '/')
+ c++;
+
+ if (*c == '/')
+ {
+ c++;
+ if (!*c || *c == '?')
+ return raw_strdup("-");
+ start = c;
+ while (*c && *c != '?')
+ c++;
+ if (!*c)
+ return raw_strdup(start);
+ else
+ return raw_strldup(start, c-start+1);
+
+ }
+ return raw_strdup("-");
+}
+
+#ifdef _WIN32
+ // https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/access-waccess
+ // mode value Checks file for
+ // 04 Read-only
+ #define R_OK 04
+#endif
+
+/*
+ * Checks whether a file can be opened for reading.
+ */
+int is_file_readable(const char *file, const char *dir)
+{
+ char *filename = strdup(file);
+ convert_to_absolute_path(&filename, dir);
+ if (access(filename, R_OK)){
+ safe_free(filename);
+ return 0;
+ }
+ safe_free(filename);
+ return 1;
+}
+
+void delletterfromstring(char *s, char letter)
+{
+ if (s == NULL)
+ return;
+ for (; *s; s++)
+ {
+ if (*s == letter)
+ {
+ for (; *s; s++)
+ *s = s[1];
+ break;
+ }
+ }
+}
+
+int sort_character_lowercase_before_uppercase(char x, char y)
+{
+ /* Lower before upper */
+ if (islower(x) && isupper(y))
+ return 1;
+ if (isupper(x) && islower(y))
+ return 0;
+ /* Other than that, easy */
+ return x < y ? 1 : 0;
+}
+
+/* Helper function, mainly used by snomask code */
+void addlettertodynamicstringsorted(char **str, char letter)
+{
+ char *i, *o;
+ char *newbuf;
+ size_t newbuflen;
+
+ /* NULL string? Easy! */
+ if (*str == NULL)
+ {
+ *str = safe_alloc(2);
+ **str = letter;
+ return;
+ }
+
+ /* Exists? Then nothing to do */
+ if (strchr(*str, letter))
+ return;
+
+ /* Ok, we really need to add it */
+ newbuflen = strlen(*str) + 2;
+ newbuf = safe_alloc(newbuflen);
+ for (i = *str, o = newbuf; *i; i++)
+ {
+ /* Insert before a higher letter */
+ if (letter && sort_character_lowercase_before_uppercase(letter, *i))
+ {
+ *o++ = letter;
+ letter = '\0';
+ }
+ *o++ = *i;
+ }
+ /* Or maybe we should be at the final spot? */
+ if (letter)
+ *o++ = letter;
+ *o = '\0';
+ safe_free_raw(*str);
+ *str = newbuf;
+}
diff --git a/src/modulemanager.c b/src/modulemanager.c
index 1165df0..680a888 100644
--- a/src/modulemanager.c
+++ b/src/modulemanager.c
@@ -44,7 +44,7 @@ int mm_valid_module_name(char *name);
void free_managed_module(ManagedModule *m);
-SSL_CTX *mm_init_ssl(void)
+SSL_CTX *mm_init_tls(void)
{
SSL_CTX *ctx_client;
char buf1[512], buf2[512];
@@ -101,8 +101,7 @@ int parse_url(const char *url, char **host, int *port, char **document)
if (!p)
return 0;
- *hostbuf = '\0';
- strlncat(hostbuf, url, sizeof(hostbuf), p - url);
+ strlncpy(hostbuf, url, sizeof(hostbuf), p - url);
strlcpy(documentbuf, p, sizeof(documentbuf));
@@ -134,7 +133,7 @@ int mm_http_request(char *url, char *fname, int follow_redirects)
snprintf(hostandport, sizeof(hostandport), "%s:%d", host, port);
- ctx_client = mm_init_ssl();
+ ctx_client = mm_init_tls();
if (!ctx_client)
{
fprintf(stderr, "ERROR: TLS initalization failure (I)\n");
@@ -163,14 +162,14 @@ int mm_http_request(char *url, char *fname, int follow_redirects)
if (BIO_do_connect(socket) != 1)
{
fprintf(stderr, "ERROR: Could not connect to %s\n", hostandport);
- config_report_ssl_error();
+ //config_report_ssl_error(); FIXME?
goto out2;
}
if (BIO_do_handshake(socket) != 1)
{
fprintf(stderr, "ERROR: Could not connect to %s (TLS handshake failed)\n", hostandport);
- config_report_ssl_error();
+ //config_report_ssl_error(); FIXME?
goto out2;
}
@@ -339,63 +338,64 @@ int parse_quoted_string(char *buf, char *dest, size_t destlen)
return 1;
}
-#define CheckNull(x) if ((!(x)->ce_vardata) || (!(*((x)->ce_vardata)))) { config_error("%s:%i: missing parameter", m->name, (x)->ce_varlinenum); return 0; }
+#undef CheckNull
+#define CheckNull(x) if ((!(x)->value) || (!(*((x)->value)))) { config_error("%s:%i: missing parameter", m->name, (x)->line_number); return 0; }
/** Parse a module { } line from a module (not repo!!) */
int mm_module_file_config(ManagedModule *m, ConfigEntry *ce)
{
ConfigEntry *cep;
- if (ce->ce_vardata)
+ if (ce->value)
{
config_error("%s:%d: module { } block should not have a name.",
- m->name, ce->ce_varlinenum);
+ m->name, ce->line_number);
return 0;
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "source") ||
- !strcmp(cep->ce_varname, "version") ||
- !strcmp(cep->ce_varname, "author") ||
- !strcmp(cep->ce_varname, "sha256sum") ||
- !strcmp(cep->ce_varname, "description")
+ if (!strcmp(cep->name, "source") ||
+ !strcmp(cep->name, "version") ||
+ !strcmp(cep->name, "author") ||
+ !strcmp(cep->name, "sha256sum") ||
+ !strcmp(cep->name, "description")
)
{
config_error("%s:%d: module::%s should not be in here (it only exists in repository entries)",
- m->name, cep->ce_varlinenum, cep->ce_varname);
+ m->name, cep->line_number, cep->name);
return 0;
}
- else if (!strcmp(cep->ce_varname, "troubleshooting"))
+ else if (!strcmp(cep->name, "troubleshooting"))
{
CheckNull(cep);
- safe_strdup(m->troubleshooting, cep->ce_vardata);
+ safe_strdup(m->troubleshooting, cep->value);
}
- else if (!strcmp(cep->ce_varname, "documentation"))
+ else if (!strcmp(cep->name, "documentation"))
{
CheckNull(cep);
- safe_strdup(m->documentation, cep->ce_vardata);
+ safe_strdup(m->documentation, cep->value);
}
- else if (!strcmp(cep->ce_varname, "min-unrealircd-version"))
+ else if (!strcmp(cep->name, "min-unrealircd-version"))
{
CheckNull(cep);
- safe_strdup(m->min_unrealircd_version, cep->ce_vardata);
+ safe_strdup(m->min_unrealircd_version, cep->value);
}
- else if (!strcmp(cep->ce_varname, "max-unrealircd-version"))
+ else if (!strcmp(cep->name, "max-unrealircd-version"))
{
CheckNull(cep);
- safe_strdup(m->max_unrealircd_version, cep->ce_vardata);
+ safe_strdup(m->max_unrealircd_version, cep->value);
}
- else if (!strcmp(cep->ce_varname, "post-install-text"))
+ else if (!strcmp(cep->name, "post-install-text"))
{
- if (cep->ce_entries)
+ if (cep->items)
{
ConfigEntry *cepp;
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
- addmultiline(&m->post_install_text, cepp->ce_varname);
+ for (cepp = cep->items; cepp; cepp = cepp->next)
+ addmultiline(&m->post_install_text, cepp->name);
} else {
CheckNull(cep);
- addmultiline(&m->post_install_text, cep->ce_vardata);
+ addmultiline(&m->post_install_text, cep->value);
}
}
/* unknown items are silently ignored for future compatibility */
@@ -403,19 +403,19 @@ int mm_module_file_config(ManagedModule *m, ConfigEntry *ce)
if (!m->documentation)
{
- config_error("%s:%d: module::documentation missing", m->name, ce->ce_varlinenum);
+ config_error("%s:%d: module::documentation missing", m->name, ce->line_number);
return 0;
}
if (!m->troubleshooting)
{
- config_error("%s:%d: module::troubleshooting missing", m->name, ce->ce_varlinenum);
+ config_error("%s:%d: module::troubleshooting missing", m->name, ce->line_number);
return 0;
}
if (!m->min_unrealircd_version)
{
- config_error("%s:%d: module::min-unrealircd-version missing", m->name, ce->ce_varlinenum);
+ config_error("%s:%d: module::min-unrealircd-version missing", m->name, ce->line_number);
return 0;
}
@@ -438,9 +438,9 @@ int mm_parse_module_file(ManagedModule *m, char *buf, unsigned int line_offset)
return 0; /* eg: parse errors */
/* Parse the module { } block (only one!) */
- for (ce = cf->cf_entries; ce; ce = ce->ce_next)
+ for (ce = cf->items; ce; ce = ce->next)
{
- if (!strcmp(ce->ce_varname, "module"))
+ if (!strcmp(ce->name, "module"))
{
int n = mm_module_file_config(m, ce);
config_free(cf);
@@ -652,7 +652,8 @@ int mm_valid_module_name(char *name)
return 1;
}
-#define CheckNull(x) if ((!(x)->ce_vardata) || (!(*((x)->ce_vardata)))) { config_error("%s:%i: missing parameter", repo_url, (x)->ce_varlinenum); goto fail_mm_repo_module_config; }
+#undef CheckNull
+#define CheckNull(x) if ((!(x)->value) || (!(*((x)->value)))) { config_error("%s:%i: missing parameter", repo_url, (x)->line_number); goto fail_mm_repo_module_config; }
/** Parse a module { } line from a repository */
ManagedModule *mm_repo_module_config(char *repo_url, ConfigEntry *ce)
@@ -660,84 +661,84 @@ ManagedModule *mm_repo_module_config(char *repo_url, ConfigEntry *ce)
ConfigEntry *cep;
ManagedModule *m = safe_alloc(sizeof(ManagedModule));
- if (!ce->ce_vardata)
+ if (!ce->value)
{
config_error("%s:%d: module { } with no name",
- repo_url, ce->ce_varlinenum);
+ repo_url, ce->line_number);
goto fail_mm_repo_module_config;
}
- if (strncmp(ce->ce_vardata, "third/", 6))
+ if (strncmp(ce->value, "third/", 6))
{
config_error("%s:%d: module { } name must start with: third/",
- repo_url, ce->ce_varlinenum);
+ repo_url, ce->line_number);
goto fail_mm_repo_module_config;
}
- if (!mm_valid_module_name(ce->ce_vardata))
+ if (!mm_valid_module_name(ce->value))
{
config_error("%s:%d: module { } with illegal name: %s",
- repo_url, ce->ce_varlinenum, ce->ce_vardata);
+ repo_url, ce->line_number, ce->value);
goto fail_mm_repo_module_config;
}
- safe_strdup(m->name, ce->ce_vardata);
+ safe_strdup(m->name, ce->value);
safe_strdup(m->repo_url, repo_url);
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "source"))
+ if (!strcmp(cep->name, "source"))
{
CheckNull(cep);
- safe_strdup(m->source, cep->ce_vardata);
+ safe_strdup(m->source, cep->value);
}
- else if (!strcmp(cep->ce_varname, "sha256sum"))
+ else if (!strcmp(cep->name, "sha256sum"))
{
CheckNull(cep);
- safe_strdup(m->sha256sum, cep->ce_vardata);
+ safe_strdup(m->sha256sum, cep->value);
}
- else if (!strcmp(cep->ce_varname, "version"))
+ else if (!strcmp(cep->name, "version"))
{
CheckNull(cep);
- safe_strdup(m->version, cep->ce_vardata);
+ safe_strdup(m->version, cep->value);
}
- else if (!strcmp(cep->ce_varname, "author"))
+ else if (!strcmp(cep->name, "author"))
{
CheckNull(cep);
- safe_strdup(m->author, cep->ce_vardata);
+ safe_strdup(m->author, cep->value);
}
- else if (!strcmp(cep->ce_varname, "troubleshooting"))
+ else if (!strcmp(cep->name, "troubleshooting"))
{
CheckNull(cep);
- safe_strdup(m->troubleshooting, cep->ce_vardata);
+ safe_strdup(m->troubleshooting, cep->value);
}
- else if (!strcmp(cep->ce_varname, "documentation"))
+ else if (!strcmp(cep->name, "documentation"))
{
CheckNull(cep);
- safe_strdup(m->documentation, cep->ce_vardata);
+ safe_strdup(m->documentation, cep->value);
}
- else if (!strcmp(cep->ce_varname, "min-unrealircd-version"))
+ else if (!strcmp(cep->name, "min-unrealircd-version"))
{
CheckNull(cep);
- safe_strdup(m->min_unrealircd_version, cep->ce_vardata);
+ safe_strdup(m->min_unrealircd_version, cep->value);
}
- else if (!strcmp(cep->ce_varname, "max-unrealircd-version"))
+ else if (!strcmp(cep->name, "max-unrealircd-version"))
{
CheckNull(cep);
- safe_strdup(m->max_unrealircd_version, cep->ce_vardata);
+ safe_strdup(m->max_unrealircd_version, cep->value);
}
- else if (!strcmp(cep->ce_varname, "description"))
+ else if (!strcmp(cep->name, "description"))
{
CheckNull(cep);
- safe_strdup(m->description, cep->ce_vardata);
+ safe_strdup(m->description, cep->value);
}
- else if (!strcmp(cep->ce_varname, "post-install-text"))
+ else if (!strcmp(cep->name, "post-install-text"))
{
- if (cep->ce_entries)
+ if (cep->items)
{
ConfigEntry *cepp;
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
- addmultiline(&m->post_install_text, cepp->ce_varname);
+ for (cepp = cep->items; cepp; cepp = cepp->next)
+ addmultiline(&m->post_install_text, cepp->name);
} else {
CheckNull(cep);
- addmultiline(&m->post_install_text, cep->ce_vardata);
+ addmultiline(&m->post_install_text, cep->value);
}
}
/* unknown items are silently ignored for future compatibility */
@@ -745,43 +746,43 @@ ManagedModule *mm_repo_module_config(char *repo_url, ConfigEntry *ce)
if (!m->source)
{
- config_error("%s:%d: module::source missing", repo_url, ce->ce_varlinenum);
+ config_error("%s:%d: module::source missing", repo_url, ce->line_number);
goto fail_mm_repo_module_config;
}
if (!m->sha256sum)
{
- config_error("%s:%d: module::sha256sum missing", repo_url, ce->ce_varlinenum);
+ config_error("%s:%d: module::sha256sum missing", repo_url, ce->line_number);
goto fail_mm_repo_module_config;
}
if (!m->version)
{
- config_error("%s:%d: module::version missing", repo_url, ce->ce_varlinenum);
+ config_error("%s:%d: module::version missing", repo_url, ce->line_number);
goto fail_mm_repo_module_config;
}
if (!m->author)
{
- config_error("%s:%d: module::author missing", repo_url, ce->ce_varlinenum);
+ config_error("%s:%d: module::author missing", repo_url, ce->line_number);
goto fail_mm_repo_module_config;
}
if (!m->documentation)
{
- config_error("%s:%d: module::documentation missing", repo_url, ce->ce_varlinenum);
+ config_error("%s:%d: module::documentation missing", repo_url, ce->line_number);
goto fail_mm_repo_module_config;
}
if (!m->troubleshooting)
{
- config_error("%s:%d: module::troubleshooting missing", repo_url, ce->ce_varlinenum);
+ config_error("%s:%d: module::troubleshooting missing", repo_url, ce->line_number);
goto fail_mm_repo_module_config;
}
if (!m->min_unrealircd_version)
{
- config_error("%s:%d: module::min-unrealircd-version missing", repo_url, ce->ce_varlinenum);
+ config_error("%s:%d: module::min-unrealircd-version missing", repo_url, ce->line_number);
goto fail_mm_repo_module_config;
}
/* max_unrealircd_version is optional */
if (!m->description)
{
- config_error("%s:%d: module::description missing", repo_url, ce->ce_varlinenum);
+ config_error("%s:%d: module::description missing", repo_url, ce->line_number);
goto fail_mm_repo_module_config;
}
/* post_install_text is optional */
@@ -805,9 +806,9 @@ int mm_parse_repo_db(char *url, char *filename)
if (!cf)
return 0; /* eg: parse errors */
- for (ce = cf->cf_entries; ce; ce = ce->ce_next)
+ for (ce = cf->items; ce; ce = ce->next)
{
- if (!strcmp(ce->ce_varname, "module"))
+ if (!strcmp(ce->name, "module"))
{
m = mm_repo_module_config(url, ce);
if (!m)
@@ -957,7 +958,7 @@ int mm_get_module_status(ManagedModule *m)
{
FILE *fd;
char fname[512];
- char *our_sha256sum;
+ const char *our_sha256sum;
snprintf(fname, sizeof(fname), "%s/src/modules/%s.c", BUILDDIR, m->name);
if (!file_exists(fname))
@@ -1142,7 +1143,7 @@ int mm_compile(ManagedModule *m, char *tmpfile, int test)
{
char newpath[512];
char cmd[512];
- char *basename;
+ const char *basename;
char *p;
FILE *fd;
char buf[512];
@@ -1213,15 +1214,15 @@ int mm_compile(ManagedModule *m, char *tmpfile, int test)
*/
void mm_install_module(ManagedModule *m)
{
- char *basename = unreal_getfilename(m->source);
+ const char *basename = unreal_getfilename(m->source);
char *tmpfile;
- char *sha256;
+ const char *sha256;
if (!basename)
basename = "mod.c";
tmpfile = unreal_mktemp(TMPDIR, basename);
- printf("Downloading %s from %s...\n", m->name, m->source);
+ printf("ConfigResourceing %s from %s...\n", m->name, m->source);
if (!mm_http_request(m->source, tmpfile, 1))
{
fprintf(stderr, "Repository %s seems to list a module file that cannot be retrieved (%s).\n", m->repo_url, m->source);
@@ -1535,7 +1536,7 @@ void print_md_block(FILE *fdo, ManagedModule *m)
void mm_generate_repository_usage(void)
{
- fprintf(stderr, "Usage: ./unrealircd module generate-repository \n");
+ fprintf(stderr, "Usage: ./unrealircd module generate-repository [optional-minimum-version-filter]\n");
fprintf(stderr, "For example: ./unrealircd module generate-repository https://www.unrealircd.org/modules/ src/modules/third modules.lst\n");
}
@@ -1547,6 +1548,7 @@ void mm_generate_repository(int argc, char *args[])
char *urlbasepath;
char *dirname;
char *outputfile;
+ char *minversion;
char modname[128];
char fullname[512];
ManagedModule *m;
@@ -1555,6 +1557,8 @@ void mm_generate_repository(int argc, char *args[])
urlbasepath = args[1];
dirname = args[2];
outputfile = args[3];
+ minversion = args[4];
+
if (!urlbasepath || !dirname || !outputfile)
{
mm_generate_repository_usage();
@@ -1587,6 +1591,7 @@ void mm_generate_repository(int argc, char *args[])
char *fname = dir->d_name;
if (filename_has_suffix(fname, ".c"))
{
+ int hide = 0;
snprintf(fullname, sizeof(fullname), "%s/%s", dirname, fname);
snprintf(modname, sizeof(modname), "third/%s", filename_strip_suffix(fname, ".c"));
printf("Processing: %s\n", modname);
@@ -1599,7 +1604,12 @@ void mm_generate_repository(int argc, char *args[])
m->sha256sum = strdup(sha256sum_file(fullname));
m->source = safe_alloc(512);
snprintf(m->source, 512, "%s%s.c", urlbasepath, modname + 6);
- print_md_block(fdo, m);
+ /* filter */
+ if (minversion && m->min_unrealircd_version && strncmp(minversion, m->min_unrealircd_version, strlen(minversion)))
+ hide = 1;
+ /* /filter */
+ if (!hide)
+ print_md_block(fdo, m);
free_managed_module(m);
m = NULL;
}
@@ -1611,7 +1621,7 @@ void mm_generate_repository(int argc, char *args[])
void mm_parse_c_file(int argc, char *args[])
{
char *fullname = args[1];
- char *basename;
+ const char *basename;
char modname[256];
ManagedModule *m;
diff --git a/src/modules.c b/src/modules.c
index d7de75c..208c6b5 100644
--- a/src/modules.c
+++ b/src/modules.c
@@ -52,7 +52,7 @@ Module *Module_make(ModuleHeader *header,
#ifdef UNDERSCORE
/* dlsym for OpenBSD */
-void *obsd_dlsym(void *handle, char *symbol)
+void *obsd_dlsym(void *handle, const char *symbol)
{
size_t buflen = strlen(symbol) + 2;
char *obsdsymbol = safe_alloc(buflen);
@@ -69,7 +69,7 @@ void *obsd_dlsym(void *handle, char *symbol)
}
#endif
-void deletetmp(char *path)
+void deletetmp(const char *path)
{
#ifndef NOREMOVETMP
if (!loop.config_test)
@@ -88,7 +88,7 @@ void DeleteTempModules(void)
{
config_error("Unable to open temp directory %s: %s, please create one with the appropriate permissions",
TMPDIR, strerror(errno));
- if (!loop.ircd_booted)
+ if (!loop.booted)
exit(7);
return;
}
@@ -131,7 +131,7 @@ void DeleteTempModules(void)
#endif
}
-Module *Module_Find(char *name)
+Module *Module_Find(const char *name)
{
Module *p;
@@ -149,16 +149,16 @@ Module *Module_Find(char *name)
}
-int parse_modsys_version(char *version)
+int parse_modsys_version(const char *version)
{
- if (!strcmp(version, "unrealircd-5"))
- return 0x500000;
+ if (!strcmp(version, "unrealircd-6"))
+ return 0x600000;
return 0;
}
void make_compiler_string(char *buf, size_t buflen, unsigned int ver)
{
-unsigned int maj, min, plevel;
+ unsigned int maj, min, plevel;
if (ver == 0)
{
@@ -180,7 +180,7 @@ unsigned int maj, min, plevel;
* something like "/home/xyz/unrealircd/modules/third/la.so
* (and other tricks)
*/
-char *Module_TransformPath(char *path_)
+const char *Module_TransformPath(const char *path_)
{
static char path[1024];
@@ -202,17 +202,18 @@ char *Module_TransformPath(char *path_)
}
/** This function is the inverse of Module_TransformPath() */
-char *Module_GetRelPath(char *fullpath)
+const char *Module_GetRelPath(const char *fullpath)
{
static char buf[512];
char prefix[512];
- char *s = fullpath;
+ const char *without_prefix = fullpath;
+ char *s;
/* Strip the prefix */
snprintf(prefix, sizeof(prefix), "%s/", MODULESDIR);
if (!strncasecmp(fullpath, prefix, strlen(prefix)))
- s += strlen(prefix);
- strlcpy(buf, s, sizeof(buf));
+ without_prefix += strlen(prefix);
+ strlcpy(buf, without_prefix, sizeof(buf));
/* Strip the suffix */
s = strstr(buf, MODULE_SUFFIX);
@@ -225,7 +226,7 @@ char *Module_GetRelPath(char *fullpath)
/** Validate a modules' ModuleHeader.
* @returns Error message is returned, or NULL if everything is OK.
*/
-static char *validate_mod_header(char *relpath, ModuleHeader *mod_header)
+static const char *validate_mod_header(const char *relpath, ModuleHeader *mod_header)
{
char *p;
static char buf[256];
@@ -260,7 +261,7 @@ static char *validate_mod_header(char *relpath, ModuleHeader *mod_header)
return NULL; /* SUCCESS */
}
-int module_already_in_testing(char *relpath)
+int module_already_in_testing(const char *relpath)
{
Module *m;
for (m = Modules; m; m = m->next)
@@ -277,7 +278,7 @@ int module_already_in_testing(char *relpath)
/*
* Returns an error if insucessful .. yes NULL is OK!
*/
-char *Module_Create(char *path_)
+const char *Module_Create(const char *path_)
{
#ifdef _WIN32
HMODULE Mod;
@@ -291,15 +292,14 @@ char *Module_Create(char *path_)
char *Mod_Version;
unsigned int *compiler_version;
static char errorbuf[1024];
- char *path, *relpath, *tmppath;
+ const char *path, *relpath, *tmppath;
ModuleHeader *mod_header = NULL;
int ret = 0;
- char *reterr;
+ const char *reterr;
Module *mod = NULL, **Mod_Handle = NULL;
char *expectedmodversion = our_mod_version;
unsigned int expectedcompilerversion = our_compiler_version;
long modsys_ver = 0;
- Debug((DEBUG_DEBUG, "Attempting to load module from %s", path_));
path = Module_TransformPath(path_);
@@ -447,7 +447,7 @@ char *Module_Create(char *path_)
else
{
/* Return the error .. */
- return ((char *)irc_dlerror());
+ return irc_dlerror();
}
}
@@ -524,9 +524,6 @@ void FreeModObj(ModuleObject *obj, Module *m)
else if (obj->type == MOBJ_VERSIONFLAG) {
VersionflagDel(obj->object.versionflag, m);
}
- else if (obj->type == MOBJ_SNOMASK) {
- SnomaskDel(obj->object.snomask);
- }
else if (obj->type == MOBJ_UMODE) {
UmodeDel(obj->object.umode);
}
@@ -565,7 +562,9 @@ void FreeModObj(ModuleObject *obj, Module *m)
}
else
{
- ircd_log(LOG_ERROR, "FreeModObj() called for unknown object");
+ unreal_log(ULOG_FATAL, "module", "FREEMODOBJ_UNKNOWN_TYPE", NULL,
+ "[BUG] FreeModObj() called for unknown object (type $type)",
+ log_data_integer("type", obj->type));
abort();
}
}
@@ -655,8 +654,6 @@ int Module_free(Module *mod)
for (cp = mod->children; cp; cp = cp->next)
{
- sendto_realops("Unloading child module %s",
- cp->child->header->name);
Module_Unload(cp->child->header->name);
}
for (objs = mod->objects; objs; objs = next) {
@@ -693,7 +690,7 @@ int Module_free(Module *mod)
* 1 Module unloaded
* 2 Module wishes delayed unloading, has placed event
*/
-int Module_Unload(char *name)
+int Module_Unload(const char *name)
{
Module *m;
int (*Mod_Unload)();
@@ -734,11 +731,6 @@ void module_loadall(void)
iFP fp;
Module *mi, *next;
- if (!loop.ircd_booted)
- {
- sendto_realops("Ehh, !loop.ircd_booted in module_loadall()");
- return ;
- }
/* Run through all modules and check for module load */
for (mi = Modules; mi; mi = next)
{
@@ -799,12 +791,12 @@ CMD_FUNC(cmd_module)
all = 1;
if (MyUser(client) && !IsOper(client) && all)
- client->local->since += 7; /* Lag them up. Big list. */
+ add_fake_lag(client, 7000); /* Lag them up. Big list. */
- if ((parc > 2) && (hunt_server(client, recv_mtags, ":%s MODULE %s :%s", 2, parc, parv) != HUNTED_ISME))
+ if ((parc > 2) && (hunt_server(client, recv_mtags, "MODULE", 2, parc, parv) != HUNTED_ISME))
return;
- if ((parc == 2) && (parv[1][0] != '-') && (hunt_server(client, recv_mtags, ":%s MODULE :%s", 1, parc, parv) != HUNTED_ISME))
+ if ((parc == 2) && (parv[1][0] != '-') && (hunt_server(client, recv_mtags, "MODULE", 1, parc, parv) != HUNTED_ISME))
return;
if (all)
@@ -884,7 +876,7 @@ CMD_FUNC(cmd_module)
sendtxtnumeric(client, "Override: %s", tmp);
}
-Hooktype *HooktypeFind(char *string) {
+Hooktype *HooktypeFind(const char *string) {
Hooktype *hooktype;
for (hooktype = Hooktypes; hooktype->string ;hooktype++) {
if (!strcasecmp(hooktype->string, string))
@@ -984,7 +976,7 @@ void VersionflagDel(Versionflag *vflag, Module *module)
}
}
-Hook *HookAddMain(Module *module, int hooktype, int priority, int (*func)(), void (*vfunc)(), char *(*cfunc)())
+Hook *HookAddMain(Module *module, int hooktype, int priority, int (*func)(), void (*vfunc)(), char *(*stringfunc)(), const char *(*conststringfunc)())
{
Hook *p;
@@ -993,8 +985,10 @@ Hook *HookAddMain(Module *module, int hooktype, int priority, int (*func)(), voi
p->func.intfunc = func;
if (vfunc)
p->func.voidfunc = vfunc;
- if (cfunc)
- p->func.pcharfunc = cfunc;
+ if (stringfunc)
+ p->func.stringfunc = stringfunc;
+ if (conststringfunc)
+ p->func.conststringfunc = conststringfunc;
p->type = hooktype;
p->owner = module;
p->priority = priority;
@@ -1036,17 +1030,40 @@ Hook *HookDel(Hook *hook)
return NULL;
}
-Callback *CallbackAddMain(Module *module, int cbtype, int (*func)(), void (*vfunc)(), char *(*cfunc)())
+static int num_callbacks(int cbtype)
+{
+Callback *e;
+int cnt = 0;
+
+ for (e = Callbacks[cbtype]; e; e = e->next)
+ if (!e->willberemoved)
+ cnt++;
+
+ return cnt;
+}
+
+Callback *CallbackAddMain(Module *module, int cbtype, int (*func)(), void (*vfunc)(), void *(*pvfunc)(), char *(*stringfunc)(), const char *(*conststringfunc)())
{
Callback *p;
+ if (num_callbacks(cbtype) > 0)
+ {
+ if (module)
+ module->errorcode = MODERR_EXISTS;
+ return NULL;
+ }
+
p = safe_alloc(sizeof(Callback));
if (func)
p->func.intfunc = func;
if (vfunc)
p->func.voidfunc = vfunc;
- if (cfunc)
- p->func.pcharfunc = cfunc;
+ if (pvfunc)
+ p->func.pvoidfunc = pvfunc;
+ if (stringfunc)
+ p->func.stringfunc = stringfunc;
+ if (conststringfunc)
+ p->func.conststringfunc = conststringfunc;
p->type = cbtype;
p->owner = module;
AddListItem(p, Callbacks[cbtype]);
@@ -1086,7 +1103,7 @@ Callback *CallbackDel(Callback *cb)
return NULL;
}
-CommandOverride *CommandOverrideAddEx(Module *module, char *name, int priority, OverrideCmdFunc function)
+CommandOverride *CommandOverrideAdd(Module *module, const char *name, int priority, OverrideCmdFunc function)
{
RealCommand *p;
CommandOverride *ovr;
@@ -1108,7 +1125,7 @@ CommandOverride *CommandOverrideAddEx(Module *module, char *name, int priority,
}
ovr = safe_alloc(sizeof(CommandOverride));
ovr->func = function;
- ovr->owner = module; /* TODO: module objects */
+ ovr->owner = module;
ovr->priority = priority;
if (module)
{
@@ -1127,11 +1144,6 @@ CommandOverride *CommandOverrideAddEx(Module *module, char *name, int priority,
return ovr;
}
-CommandOverride *CommandOverrideAdd(Module *module, char *name, OverrideCmdFunc function)
-{
- return CommandOverrideAddEx(module, name, 0, function);
-}
-
void CommandOverrideDel(CommandOverride *cmd)
{
DelListItem(cmd, cmd->command->overriders);
@@ -1157,7 +1169,7 @@ void CommandOverrideDel(CommandOverride *cmd)
safe_free(cmd);
}
-void CallCommandOverride(CommandOverride *ovr, Client *client, MessageTag *mtags, int parc, char *parv[])
+void CallCommandOverride(CommandOverride *ovr, Client *client, MessageTag *mtags, int parc, const char *parv[])
{
if (ovr->next)
ovr->next->func(ovr->next, client, mtags, parc, parv);
@@ -1171,21 +1183,27 @@ EVENT(e_unload_module_delayed)
int i;
i = Module_Unload(name);
if (i == 1)
- sendto_realops("Unloaded module %s", name);
+ {
+ unreal_log(ULOG_INFO, "module", "MODULE_UNLOADING_DELAYED", NULL,
+ "Unloading module $module_name (was delayed earlier)",
+ log_data_string("module_name", name));
+ }
safe_free(name);
extcmodes_check_for_changes();
umodes_check_for_changes();
return;
}
-void unload_all_modules(void)
+void unload_all_modules(void)
{
Module *m;
int (*Mod_Unload)();
for (m = Modules; m; m = m->next)
{
#ifdef DEBUGMODE
- ircd_log(LOG_ERROR, "Unloading %s...", m->header->name);
+ unreal_log(ULOG_DEBUG, "module", "MODULE_UNLOADING", NULL,
+ "Unloading module $module_name",
+ log_data_string("module_name", m->header->name));
#endif
irc_dlsym(m->dll, "Mod_Unload", Mod_Unload);
if (Mod_Unload)
@@ -1237,18 +1255,6 @@ const char *ModuleGetErrorStr(Module *module)
return module_error_str[module->errorcode];
}
-static int num_callbacks(int cbtype)
-{
-Callback *e;
-int cnt = 0;
-
- for (e = Callbacks[cbtype]; e; e = e->next)
- if (!e->willberemoved)
- cnt++;
-
- return cnt;
-}
-
/** Ensure that all required callbacks are in place and meet
* all specified requirements
*/
@@ -1262,11 +1268,21 @@ int i;
{
config_error("ERROR: Multiple callbacks loaded for type %d. "
"Make sure you only load 1 module of 1 type (eg: only 1 cloaking module)",
- i); /* TODO: make more clear? */
+ i);
return -1;
}
}
-
+
+ if (!Callbacks[CALLBACKTYPE_CLOAK_KEY_CHECKSUM])
+ {
+ unreal_log(ULOG_ERROR, "config", "NO_CLOAKING_MODULE", NULL,
+ "No cloaking module loaded, you must load 1 of these modulese:\n"
+ "1) cloak_sha256 - if you are a new network starting with UnrealIRCd 6\n"
+ "2) cloak_md5 - the old one if migrating an existing network from UnrealIRCd 3.2/4/5\n"
+ "3) cloak_none - if you don't want to use cloaking at all\n"
+ "See also https://www.unrealircd.org/docs/FAQ#choose-a-cloaking-module");
+ return -1;
+ }
return 0;
}
@@ -1311,7 +1327,7 @@ const char *our_dlerror(void)
* @note The name is checked against the module name,
* this can be a problem if two modules have the same name.
*/
-int is_module_loaded(char *name)
+int is_module_loaded(const char *name)
{
Module *mi;
for (mi = Modules; mi; mi = mi->next)
@@ -1325,17 +1341,17 @@ int is_module_loaded(char *name)
return 0;
}
-static char *mod_var_name(ModuleInfo *modinfo, char *varshortname)
+static const char *mod_var_name(ModuleInfo *modinfo, const char *varshortname)
{
static char fullname[512];
snprintf(fullname, sizeof(fullname), "%s:%s", modinfo->handle->header->name, varshortname);
return fullname;
}
-int LoadPersistentPointerX(ModuleInfo *modinfo, char *varshortname, void **var, void (*free_variable)(ModData *m))
+int LoadPersistentPointerX(ModuleInfo *modinfo, const char *varshortname, void **var, void (*free_variable)(ModData *m))
{
ModDataInfo *m;
- char *fullname = mod_var_name(modinfo, varshortname);
+ const char *fullname = mod_var_name(modinfo, varshortname);
m = findmoddata_byname(fullname, MODDATATYPE_LOCAL_VARIABLE);
if (m)
@@ -1346,27 +1362,28 @@ int LoadPersistentPointerX(ModuleInfo *modinfo, char *varshortname, void **var,
ModDataInfo mreq;
memset(&mreq, 0, sizeof(mreq));
mreq.type = MODDATATYPE_LOCAL_VARIABLE;
- mreq.name = fullname;
+ mreq.name = strdup(fullname);
mreq.free = free_variable;
m = ModDataAdd(modinfo->handle, mreq);
moddata_local_variable(m).ptr = NULL;
+ safe_free(mreq.name);
return 0;
}
}
-void SavePersistentPointerX(ModuleInfo *modinfo, char *varshortname, void *var)
+void SavePersistentPointerX(ModuleInfo *modinfo, const char *varshortname, void *var)
{
ModDataInfo *m;
- char *fullname = mod_var_name(modinfo, varshortname);
+ const char *fullname = mod_var_name(modinfo, varshortname);
m = findmoddata_byname(fullname, MODDATATYPE_LOCAL_VARIABLE);
moddata_local_variable(m).ptr = var;
}
-int LoadPersistentIntX(ModuleInfo *modinfo, char *varshortname, int *var)
+int LoadPersistentIntX(ModuleInfo *modinfo, const char *varshortname, int *var)
{
ModDataInfo *m;
- char *fullname = mod_var_name(modinfo, varshortname);
+ const char *fullname = mod_var_name(modinfo, varshortname);
m = findmoddata_byname(fullname, MODDATATYPE_LOCAL_VARIABLE);
if (m)
@@ -1377,27 +1394,28 @@ int LoadPersistentIntX(ModuleInfo *modinfo, char *varshortname, int *var)
ModDataInfo mreq;
memset(&mreq, 0, sizeof(mreq));
mreq.type = MODDATATYPE_LOCAL_VARIABLE;
- mreq.name = fullname;
+ mreq.name = strdup(fullname);
mreq.free = NULL;
m = ModDataAdd(modinfo->handle, mreq);
moddata_local_variable(m).i = 0;
+ safe_free(mreq.name);
return 0;
}
}
-void SavePersistentIntX(ModuleInfo *modinfo, char *varshortname, int var)
+void SavePersistentIntX(ModuleInfo *modinfo, const char *varshortname, int var)
{
ModDataInfo *m;
- char *fullname = mod_var_name(modinfo, varshortname);
+ const char *fullname = mod_var_name(modinfo, varshortname);
m = findmoddata_byname(fullname, MODDATATYPE_LOCAL_VARIABLE);
moddata_local_variable(m).i = var;
}
-int LoadPersistentLongX(ModuleInfo *modinfo, char *varshortname, long *var)
+int LoadPersistentLongX(ModuleInfo *modinfo, const char *varshortname, long *var)
{
ModDataInfo *m;
- char *fullname = mod_var_name(modinfo, varshortname);
+ const char *fullname = mod_var_name(modinfo, varshortname);
m = findmoddata_byname(fullname, MODDATATYPE_LOCAL_VARIABLE);
if (m)
@@ -1408,18 +1426,19 @@ int LoadPersistentLongX(ModuleInfo *modinfo, char *varshortname, long *var)
ModDataInfo mreq;
memset(&mreq, 0, sizeof(mreq));
mreq.type = MODDATATYPE_LOCAL_VARIABLE;
- mreq.name = fullname;
+ mreq.name = strdup(fullname);
mreq.free = NULL;
m = ModDataAdd(modinfo->handle, mreq);
moddata_local_variable(m).l = 0;
+ safe_free(mreq.name);
return 0;
}
}
-void SavePersistentLongX(ModuleInfo *modinfo, char *varshortname, long var)
+void SavePersistentLongX(ModuleInfo *modinfo, const char *varshortname, long var)
{
ModDataInfo *m;
- char *fullname = mod_var_name(modinfo, varshortname);
+ const char *fullname = mod_var_name(modinfo, varshortname);
m = findmoddata_byname(fullname, MODDATATYPE_LOCAL_VARIABLE);
moddata_local_variable(m).l = var;
diff --git a/src/modules/Makefile.in b/src/modules/Makefile.in
index cdc560f..62ee898 100644
--- a/src/modules/Makefile.in
+++ b/src/modules/Makefile.in
@@ -28,13 +28,14 @@ INCLUDES = ../include/channel.h \
../include/ircsprintf.h \
../include/license.h \
../include/modules.h ../include/modversion.h ../include/msg.h \
- ../include/numeric.h ../include/proto.h ../include/dns.h \
+ ../include/numeric.h ../include/dns.h \
../include/resource.h ../include/setup.h \
../include/struct.h ../include/sys.h \
- ../include/types.h ../include/url.h \
+ ../include/types.h \
../include/version.h ../include/whowas.h
-R_MODULES= \
+MODULES= \
+ cloak_md5.so cloak_sha256.so cloak_none.so \
sethost.so chghost.so chgident.so setname.so \
setident.so sdesc.so svsmode.so swhois.so\
svsmotd.so svsnline.so who_old.so whox.so mkpasswd.so \
@@ -49,7 +50,7 @@ R_MODULES= \
invite.so list.so time.so svskill.so sjoin.so \
pass.so userhost.so ison.so silence.so knock.so \
umode2.so squit.so protoctl.so addomotd.so \
- wallops.so admin.so globops.so locops.so \
+ admin.so globops.so locops.so \
trace.so netinfo.so links.so help.so rules.so \
close.so map.so eos.so server.so stats.so \
dccdeny.so whowas.so \
@@ -71,604 +72,48 @@ R_MODULES= \
account-tag.so labeled-response.so link-security.so \
message-ids.so plaintext-policy.so server-time.so sts.so \
echo-message.so userip-tag.so userhost-tag.so \
- bot-tag.so \
- reply-tag.so typing-indicator.so \
+ bot-tag.so reply-tag.so json-log-tag.so \
+ typing-indicator.so \
ident_lookup.so history.so chathistory.so \
- targetfloodprot.so clienttagdeny.so
+ targetfloodprot.so clienttagdeny.so watch-backend.so \
+ monitor.so slog.so tls_cipher.so operinfo.so \
+ unreal_server_compat.so \
+ extended-monitor.so geoip_csv.so \
+ geoip_base.so extjwt.so \
+ $(GEOIP_CLASSIC_OBJECTS) $(GEOIP_MAXMIND_OBJECTS)
-MODULES=cloak.so $(R_MODULES)
MODULEFLAGS=@MODULEFLAGS@
RM=@RM@
+.SUFFIXES:
+.SUFFIXES: .c .h .so
+
all: build
build: $(MODULES)
cd chanmodes; $(MAKE) all
cd usermodes; $(MAKE) all
- cd snomasks; $(MAKE) all
cd extbans; $(MAKE) all
cd third; $(MAKE) all
-#############################################################################
-# .so's section
-#############################################################################
-
-chgname.so: chgname.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o chgname.so chgname.c
-
-kill.so: kill.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o kill.so kill.c
-
-lag.so: lag.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o lag.so lag.c
-
-message.so: message.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o message.so message.c
-
-oper.so: oper.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o oper.so oper.c
-
-pingpong.so: pingpong.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o pingpong.so pingpong.c
-
-quit.so: quit.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o quit.so quit.c
-
-sendumode.so: sendumode.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o sendumode.so sendumode.c
-
-sqline.so: sqline.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o sqline.so sqline.c
-
-tsctl.so: tsctl.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o tsctl.so tsctl.c
-
-unsqline.so: unsqline.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o unsqline.so unsqline.c
-
-whois.so: whois.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o whois.so whois.c
-
-sethost.so: sethost.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o sethost.so sethost.c
-
-chghost.so: chghost.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o chghost.so chghost.c
-
-chgident.so: chgident.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o chgident.so chgident.c
-
-setident.so: setident.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o setident.so setident.c
-
-setname.so: setname.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o setname.so setname.c
-
-sdesc.so: sdesc.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o sdesc.so sdesc.c
-
-svsmode.so: svsmode.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o svsmode.so svsmode.c
-
-swhois.so: swhois.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o swhois.so swhois.c
-
-svsmotd.so: svsmotd.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o svsmotd.so svsmotd.c
-
-svsnline.so: svsnline.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o svsnline.so svsnline.c
-
-who_old.so: who_old.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o who_old.so who_old.c
-
-whox.so: whox.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o whox.so whox.c
-
-mkpasswd.so: mkpasswd.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o mkpasswd.so mkpasswd.c
-
-away.so: away.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o away.so away.c
-
-svsnoop.so: svsnoop.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o svsnoop.so svsnoop.c
-
-svsnick.so: svsnick.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o svsnick.so svsnick.c
-
-tkl.so: tkl.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o tkl.so tkl.c
-
-vhost.so: vhost.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o vhost.so vhost.c
-
-cycle.so: cycle.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o cycle.so cycle.c
-
-svsjoin.so: svsjoin.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o svsjoin.so svsjoin.c
-
-svspart.so: svspart.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o svspart.so svspart.c
-
-svslusers.so: svslusers.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o svslusers.so svslusers.c
-
-svswatch.so: svswatch.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o svswatch.so svswatch.c
-
-svssilence.so: svssilence.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o svssilence.so svssilence.c
-
-sendsno.so: sendsno.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o sendsno.so sendsno.c
-
-svssno.so: svssno.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o svssno.so svssno.c
-
-sajoin.so: sajoin.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o sajoin.so sajoin.c
-
-sapart.so: sapart.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o sapart.so sapart.c
-
-samode.so: samode.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o samode.so samode.c
-
-kick.so: kick.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o kick.so kick.c
-
-topic.so: topic.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o topic.so topic.c
-
-invite.so: invite.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o invite.so invite.c
-
-list.so: list.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o list.so list.c
-
-time.so: time.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o time.so time.c
-
-svskill.so: svskill.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o svskill.so svskill.c
-
-sjoin.so: sjoin.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o sjoin.so sjoin.c
-
-pass.so: pass.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o pass.so pass.c
-
-userhost.so: userhost.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o userhost.so userhost.c
-
-ison.so: ison.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o ison.so ison.c
-
-silence.so: silence.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o silence.so silence.c
-
-knock.so: knock.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o knock.so knock.c
-
-umode2.so: umode2.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o umode2.so umode2.c
-
-squit.so: squit.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o squit.so squit.c
-
-protoctl.so: protoctl.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o protoctl.so protoctl.c
-
-addmotd.so: addmotd.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o addmotd.so addmotd.c
-
-addomotd.so: addomotd.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o addomotd.so addomotd.c
-
-wallops.so: wallops.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o wallops.so wallops.c
-
-admin.so: admin.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o admin.so admin.c
-
-globops.so: globops.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o globops.so globops.c
-
-locops.so: locops.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o locops.so locops.c
-
-trace.so: trace.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o trace.so trace.c
-
-netinfo.so: netinfo.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o netinfo.so netinfo.c
-
-links.so: links.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o links.so links.c
-
-help.so: help.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o help.so help.c
-
-rules.so: rules.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o rules.so rules.c
-
-close.so: close.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o close.so close.c
-
-map.so: map.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o map.so map.c
-
-eos.so: eos.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o eos.so eos.c
-
-server.so: server.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o server.so server.c
-
-stats.so: stats.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o stats.so stats.c
-
-dccdeny.so: dccdeny.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o dccdeny.so dccdeny.c
-
-whowas.so: whowas.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o whowas.so whowas.c
-
-connect.so: connect.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o connect.so connect.c
-
-dccallow.so: dccallow.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o dccallow.so dccallow.c
-
-userip.so: userip.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o userip.so userip.c
-
-nick.so: nick.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o nick.so nick.c
-
-user.so: user.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o user.so user.c
-
-mode.so: mode.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o mode.so mode.c
-
-watch.so: watch.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o watch.so watch.c
-
-part.so: part.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o part.so part.c
-
-join.so: join.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o join.so join.c
-
-motd.so: motd.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o motd.so motd.c
-
-opermotd.so: opermotd.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o opermotd.so opermotd.c
-
-botmotd.so: botmotd.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o botmotd.so botmotd.c
-
-lusers.so: lusers.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o lusers.so lusers.c
-
-names.so: names.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o names.so names.c
-
-svsnolag.so: svsnolag.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o svsnolag.so svsnolag.c
-
-starttls.so: starttls.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o starttls.so starttls.c
-
-webredir.so: webredir.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o webredir.so webredir.c
-
-cap.so: cap.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o cap.so cap.c
-
-sasl.so: sasl.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o sasl.so sasl.c
-
-md.so: md.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o md.so md.c
-
-certfp.so: certfp.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o certfp.so certfp.c
-
-tls_antidos.so: tls_antidos.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o tls_antidos.so tls_antidos.c
-
-webirc.so: webirc.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o webirc.so webirc.c
-
-websocket.so: websocket.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o websocket.so websocket.c
-
-blacklist.so: blacklist.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o blacklist.so blacklist.c
-
-jointhrottle.so: jointhrottle.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o jointhrottle.so jointhrottle.c
-
-antirandom.so: antirandom.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o antirandom.so antirandom.c
-
-hideserver.so: hideserver.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o hideserver.so hideserver.c
-
-jumpserver.so: jumpserver.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o jumpserver.so jumpserver.c
-
-ircops.so: ircops.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o ircops.so ircops.c
-
-staff.so: staff.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o staff.so staff.c
-
-nocodes.so: nocodes.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o nocodes.so nocodes.c
-
-charsys.so: charsys.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o charsys.so charsys.c
-
-antimixedutf8.so: antimixedutf8.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o antimixedutf8.so antimixedutf8.c
-
-authprompt.so: authprompt.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o authprompt.so authprompt.c
-
-sinfo.so: sinfo.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o sinfo.so sinfo.c
-
-reputation.so: reputation.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o reputation.so reputation.c
-
-connthrottle.so: connthrottle.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o connthrottle.so connthrottle.c
-
-history_backend_mem.so: history_backend_mem.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o history_backend_mem.so history_backend_mem.c
-
-history_backend_null.so: history_backend_null.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o history_backend_null.so history_backend_null.c
-
-tkldb.so: tkldb.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o tkldb.so tkldb.c
-
-channeldb.so: channeldb.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o channeldb.so channeldb.c
-
-restrict-commands.so: restrict-commands.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o restrict-commands.so restrict-commands.c
-
-rmtkl.so: rmtkl.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o rmtkl.so rmtkl.c
-
-message-tags.so: message-tags.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o message-tags.so message-tags.c
-
-batch.so: batch.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o batch.so batch.c
-
-account-tag.so: account-tag.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o account-tag.so account-tag.c
-
-labeled-response.so: labeled-response.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o labeled-response.so labeled-response.c
-
-link-security.so: link-security.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o link-security.so link-security.c
-
-message-ids.so: message-ids.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o message-ids.so message-ids.c
-
-plaintext-policy.so: plaintext-policy.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o plaintext-policy.so plaintext-policy.c
-
-server-time.so: server-time.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o server-time.so server-time.c
-
-sts.so: sts.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o sts.so sts.c
-
-echo-message.so: echo-message.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o echo-message.so echo-message.c
-
-userip-tag.so: userip-tag.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o userip-tag.so userip-tag.c
-
-userhost-tag.so: userhost-tag.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o userhost-tag.so userhost-tag.c
-
-bot-tag.so: bot-tag.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o bot-tag.so bot-tag.c
-
-reply-tag.so: reply-tag.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o reply-tag.so reply-tag.c
-
-typing-indicator.so: typing-indicator.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o typing-indicator.so typing-indicator.c
-
-require-module.so: require-module.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o require-module.so require-module.c
-
-account-notify.so: account-notify.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o account-notify.so account-notify.c
-
-ident_lookup.so: ident_lookup.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o ident_lookup.so ident_lookup.c
-
-history.so: history.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o history.so history.c
-
-chathistory.so: chathistory.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o chathistory.so chathistory.c
-
-targetfloodprot.so: targetfloodprot.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o targetfloodprot.so targetfloodprot.c
-
-clienttagdeny.so: clienttagdeny.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o clienttagdeny.so clienttagdeny.c
-
-#############################################################################
-# capabilities
-#############################################################################
-
-#############################################################################
-# and now the remaining modules...
-#############################################################################
-
-cloak.so: cloak.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o cloak.so cloak.c
-
clean:
$(RM) -f *.o *.so *~ core
cd chanmodes; $(MAKE) clean
cd usermodes; $(MAKE) clean
- cd snomasks; $(MAKE) clean
cd extbans; $(MAKE) clean
cd third; $(MAKE) clean
+
+# Generic *.so rule:
+%.so: %.c $(INCLUDES)
+ $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
+ -o $@ $<
+
+# geoip_classic requires extra library
+geoip_classic.so: geoip_classic.c $(INCLUDES)
+ $(CC) $(CFLAGS) $(MODULEFLAGS) $(GEOIP_CLASSIC_CFLAGS) -DDYNAMIC_LINKING \
+ -o geoip_classic.so geoip_classic.c @LDFLAGS_PRIVATELIBS@ $(GEOIP_CLASSIC_LIBS)
+
+# geoip_maxmind requires another extra library
+geoip_maxmind.so: geoip_maxmind.c $(INCLUDES)
+ $(CC) $(CFLAGS) $(MODULEFLAGS) $(LIBMAXMINDDB_CFLAGS) -DDYNAMIC_LINKING \
+ -o geoip_maxmind.so geoip_maxmind.c @LDFLAGS_PRIVATELIBS@ $(LIBMAXMINDDB_LIBS)
diff --git a/src/modules/account-notify.c b/src/modules/account-notify.c
index b2e9c3b..9bd4100 100644
--- a/src/modules/account-notify.c
+++ b/src/modules/account-notify.c
@@ -28,7 +28,7 @@ ModuleHeader MOD_HEADER
"5.0", /* Version */
"account-notify CAP", /* Short description of module */
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Variables */
@@ -70,7 +70,7 @@ int account_notify_account_login(Client *client, MessageTag *recv_mtags)
CAP_ACCOUNT_NOTIFY, mtags,
":%s ACCOUNT %s",
client->name,
- !isdigit(*client->user->svid) ? client->user->svid : "*");
+ IsLoggedIn(client) ? client->user->account : "*");
free_message_tags(mtags);
return 0;
}
diff --git a/src/modules/account-tag.c b/src/modules/account-tag.c
index 523da07..b23578a 100644
--- a/src/modules/account-tag.c
+++ b/src/modules/account-tag.c
@@ -28,14 +28,14 @@ ModuleHeader MOD_HEADER
"5.0",
"account-tag CAP",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Variables */
long CAP_ACCOUNT_TAG = 0L;
-int account_tag_mtag_is_ok(Client *client, char *name, char *value);
-void mtag_add_account(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, char *signature);
+int account_tag_mtag_is_ok(Client *client, const char *name, const char *value);
+void mtag_add_account(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, const char *signature);
MOD_INIT()
{
@@ -75,7 +75,7 @@ MOD_UNLOAD()
* syntax.
* We simply allow account-tag ONLY from servers and with any syntax.
*/
-int account_tag_mtag_is_ok(Client *client, char *name, char *value)
+int account_tag_mtag_is_ok(Client *client, const char *name, const char *value)
{
if (IsServer(client))
return 1;
@@ -83,15 +83,15 @@ int account_tag_mtag_is_ok(Client *client, char *name, char *value)
return 0;
}
-void mtag_add_account(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, char *signature)
+void mtag_add_account(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, const char *signature)
{
MessageTag *m;
- if (client && client->user && (*client->user->svid != '*') && !isdigit(*client->user->svid))
+ if (IsLoggedIn(client))
{
m = safe_alloc(sizeof(MessageTag));
safe_strdup(m->name, "account");
- safe_strdup(m->value, client->user->svid);
+ safe_strdup(m->value, client->user->account);
AddListItem(m, *mtag_list);
}
diff --git a/src/modules/addmotd.c b/src/modules/addmotd.c
index 51d5b6f..6ba7f95 100644
--- a/src/modules/addmotd.c
+++ b/src/modules/addmotd.c
@@ -32,7 +32,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /addmotd",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
@@ -60,7 +60,7 @@ MOD_UNLOAD()
CMD_FUNC(cmd_addmotd)
{
FILE *conf;
- char *text;
+ const char *text;
text = parc > 1 ? parv[1] : NULL;
diff --git a/src/modules/addomotd.c b/src/modules/addomotd.c
index ea0f1e8..140d044 100644
--- a/src/modules/addomotd.c
+++ b/src/modules/addomotd.c
@@ -32,7 +32,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /addomotd",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
@@ -60,7 +60,7 @@ MOD_UNLOAD()
CMD_FUNC(cmd_addomotd)
{
FILE *conf;
- char *text;
+ const char *text;
text = parc > 1 ? parv[1] : NULL;
diff --git a/src/modules/admin.c b/src/modules/admin.c
index 6b79c39..064dd9b 100644
--- a/src/modules/admin.c
+++ b/src/modules/admin.c
@@ -32,7 +32,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /admin",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
@@ -61,7 +61,7 @@ CMD_FUNC(cmd_admin)
if (IsUser(client))
{
- if (hunt_server(client, recv_mtags, ":%s ADMIN :%s", 1, parc, parv) != HUNTED_ISME)
+ if (hunt_server(client, recv_mtags, "ADMIN", 1, parc, parv) != HUNTED_ISME)
return;
}
diff --git a/src/modules/antimixedutf8.c b/src/modules/antimixedutf8.c
index 731ef4b..8d7eabb 100644
--- a/src/modules/antimixedutf8.c
+++ b/src/modules/antimixedutf8.c
@@ -48,7 +48,7 @@ ModuleHeader MOD_HEADER
"1.0",
"Mixed UTF8 character filter (look-alike character spam) - by Syzop",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
struct {
@@ -99,22 +99,22 @@ int detect_script(const char *t)
else if ((t[0] == 0xd3) && (t[1] >= 0x80) && (t[1] <= 0xbf))
return SCRIPT_CYRILLIC;
- if((t[0] == 0xe4) && (t[1] >= 0xb8) && (t[1] <= 0xbf))
+ if ((t[0] == 0xe4) && (t[1] >= 0xb8) && (t[1] <= 0xbf))
return SCRIPT_CJK;
else if ((t[0] >= 0xe5) && (t[0] <= 0xe9) && (t[1] >= 0x80) && (t[1] <= 0xbf))
return SCRIPT_CJK;
- if((t[0] == 0xea) && (t[1] >= 0xb0) && (t[1] <= 0xbf))
+ if ((t[0] == 0xea) && (t[1] >= 0xb0) && (t[1] <= 0xbf))
return SCRIPT_HANGUL;
else if ((t[0] >= 0xeb) && (t[0] <= 0xec) && (t[1] >= 0x80) && (t[1] <= 0xbf))
return SCRIPT_HANGUL;
else if ((t[0] == 0xed) && (t[1] >= 0x80) && (t[1] <= 0x9f))
return SCRIPT_HANGUL;
- if((t[0] == 0xe1) && (t[1] >= 0x90) && (t[1] <= 0x99))
+ if ((t[0] == 0xe1) && (t[1] >= 0x90) && (t[1] <= 0x99))
return SCRIPT_CANADIAN;
- if((t[0] == 0xe0) && (t[1] >= 0xb0) && (t[1] <= 0xb1))
+ if ((t[0] == 0xe0) && (t[1] >= 0xb0) && (t[1] <= 0xb1))
return SCRIPT_TELUGU;
if ((t[0] >= 'a') && (t[0] <= 'z'))
@@ -206,12 +206,9 @@ CMD_OVERRIDE_FUNC(override_msg)
score = lookalikespam_score(StripControlCodes(parv[2]));
if ((score >= cfg.score) && !find_tkl_exception(TKL_ANTIMIXEDUTF8, client))
{
- if (cfg.ban_action == BAN_ACT_KILL)
- {
- sendto_realops("[antimixedutf8] Killed connection from %s (score %d)",
- GetIP(client), score);
- } /* no else here!! */
-
+ unreal_log(ULOG_INFO, "antimixedutf8", "ANTIMIXEDUTF8_HIT", client,
+ "[antimixedutf8] Client $client.details hit score $score -- taking action",
+ log_data_integer("score", score));
if ((cfg.ban_action == BAN_ACT_BLOCK) ||
((cfg.ban_action == BAN_ACT_SOFT_BLOCK) && !IsLoggedIn(client)))
{
@@ -246,10 +243,10 @@ MOD_INIT()
MOD_LOAD()
{
- if (!CommandOverrideAdd(modinfo->handle, "PRIVMSG", override_msg))
+ if (!CommandOverrideAdd(modinfo->handle, "PRIVMSG", 0, override_msg))
return MOD_FAILED;
- if (!CommandOverrideAdd(modinfo->handle, "NOTICE", override_msg))
+ if (!CommandOverrideAdd(modinfo->handle, "NOTICE", 0, override_msg))
return MOD_FAILED;
return MOD_SUCCESS;
@@ -286,45 +283,45 @@ int antimixedutf8_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *er
return 0;
/* We are only interrested in set::antimixedutf8... */
- if (!ce || !ce->ce_varname || strcmp(ce->ce_varname, "antimixedutf8"))
+ if (!ce || !ce->name || strcmp(ce->name, "antimixedutf8"))
return 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!cep->ce_vardata)
+ if (!cep->value)
{
config_error("%s:%i: set::antimixedutf8::%s with no value",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname);
+ cep->file->filename, cep->line_number, cep->name);
errors++;
} else
- if (!strcmp(cep->ce_varname, "score"))
+ if (!strcmp(cep->name, "score"))
{
- int v = atoi(cep->ce_vardata);
+ int v = atoi(cep->value);
if ((v < 1) || (v > 99))
{
config_error("%s:%i: set::antimixedutf8::score: must be between 1 - 99 (got: %d)",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, v);
+ cep->file->filename, cep->line_number, v);
errors++;
}
} else
- if (!strcmp(cep->ce_varname, "ban-action"))
+ if (!strcmp(cep->name, "ban-action"))
{
- if (!banact_stringtoval(cep->ce_vardata))
+ if (!banact_stringtoval(cep->value))
{
config_error("%s:%i: set::antimixedutf8::ban-action: unknown action '%s'",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_vardata);
+ cep->file->filename, cep->line_number, cep->value);
errors++;
}
} else
- if (!strcmp(cep->ce_varname, "ban-reason"))
+ if (!strcmp(cep->name, "ban-reason"))
{
} else
- if (!strcmp(cep->ce_varname, "ban-time"))
+ if (!strcmp(cep->name, "ban-time"))
{
} else
{
config_error("%s:%i: unknown directive set::antimixedutf8::%s",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname);
+ cep->file->filename, cep->line_number, cep->name);
errors++;
}
}
@@ -340,26 +337,26 @@ int antimixedutf8_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
return 0;
/* We are only interrested in set::antimixedutf8... */
- if (!ce || !ce->ce_varname || strcmp(ce->ce_varname, "antimixedutf8"))
+ if (!ce || !ce->name || strcmp(ce->name, "antimixedutf8"))
return 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "score"))
+ if (!strcmp(cep->name, "score"))
{
- cfg.score = atoi(cep->ce_vardata);
+ cfg.score = atoi(cep->value);
} else
- if (!strcmp(cep->ce_varname, "ban-action"))
+ if (!strcmp(cep->name, "ban-action"))
{
- cfg.ban_action = banact_stringtoval(cep->ce_vardata);
+ cfg.ban_action = banact_stringtoval(cep->value);
} else
- if (!strcmp(cep->ce_varname, "ban-reason"))
+ if (!strcmp(cep->name, "ban-reason"))
{
- safe_strdup(cfg.ban_reason, cep->ce_vardata);
+ safe_strdup(cfg.ban_reason, cep->value);
} else
- if (!strcmp(cep->ce_varname, "ban-time"))
+ if (!strcmp(cep->name, "ban-time"))
{
- cfg.ban_time = config_checkval(cep->ce_vardata, CFG_TIME);
+ cfg.ban_time = config_checkval(cep->value, CFG_TIME);
}
}
return 1;
diff --git a/src/modules/antirandom.c b/src/modules/antirandom.c
index 8522f36..9c30703 100644
--- a/src/modules/antirandom.c
+++ b/src/modules/antirandom.c
@@ -22,24 +22,13 @@
#include "unrealircd.h"
-/* You can change this '//#undef' into '#define' if you want to see quite
- * a flood for every user that connects (and on-load if cfg.fullstatus_on_load).
- * Obviously only recommended for testing, use with care!
- */
-#undef DEBUGMODE
-
-/** Change this 'undef' to 'define' to get performance information.
- * This really only meant for debugging purposes.
- */
-#undef TIMING
-
ModuleHeader MOD_HEADER
= {
"antirandom",
"1.4",
"Detect and ban users with random names",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
#ifndef MAX
@@ -515,7 +504,6 @@ struct {
long ban_time;
int convert_to_lowercase;
int show_failedconnects;
- int fullstatus_on_load;
ConfigItem_mask *except_hosts;
int except_webirc;
} cfg;
@@ -553,19 +541,14 @@ MOD_INIT()
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, antirandom_config_run);
/* Some default values: */
- cfg.fullstatus_on_load = 1;
cfg.convert_to_lowercase = 1;
cfg.except_webirc = 1;
return MOD_SUCCESS;
}
-void check_all_users(void);
-
MOD_LOAD()
{
- if (cfg.fullstatus_on_load)
- check_all_users();
return MOD_SUCCESS;
}
@@ -592,67 +575,64 @@ int antirandom_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
return 0;
/* We are only interrested in set::antirandom... */
- if (!ce || !ce->ce_varname || strcmp(ce->ce_varname, "antirandom"))
+ if (!ce || !ce->name || strcmp(ce->name, "antirandom"))
return 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "except-hosts"))
+ if (!strcmp(cep->name, "except-hosts"))
{
} else
- if (!strcmp(cep->ce_varname, "except-webirc"))
+ if (!strcmp(cep->name, "except-webirc"))
{
/* This should normally be UNDER the generic 'set::antirandom::%s with no value'
* stuff but I put it here because people may think it's a hostlist and then
* the error can be a tad confusing. -- Syzop
*/
- if (!cep->ce_vardata)
+ if (!cep->value)
{
config_error("%s:%i: set::antirandom::except-webirc should be 'yes' or 'no'",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+ cep->file->filename, cep->line_number);
errors++;
}
} else
- if (!cep->ce_vardata)
+ if (!cep->value)
{
config_error("%s:%i: set::antirandom::%s with no value",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname);
+ cep->file->filename, cep->line_number, cep->name);
errors++;
} else
- if (!strcmp(cep->ce_varname, "threshold"))
+ if (!strcmp(cep->name, "threshold"))
{
req.threshold = 1;
} else
- if (!strcmp(cep->ce_varname, "ban-action"))
+ if (!strcmp(cep->name, "ban-action"))
{
- if (!banact_stringtoval(cep->ce_vardata))
+ if (!banact_stringtoval(cep->value))
{
config_error("%s:%i: set::antirandom::ban-action: unknown action '%s'",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_vardata);
+ cep->file->filename, cep->line_number, cep->value);
errors++;
} else
req.ban_action = 1;
} else
- if (!strcmp(cep->ce_varname, "ban-reason"))
+ if (!strcmp(cep->name, "ban-reason"))
{
req.ban_reason = 1;
} else
- if (!strcmp(cep->ce_varname, "ban-time"))
+ if (!strcmp(cep->name, "ban-time"))
{
req.ban_time = 1;
} else
- if (!strcmp(cep->ce_varname, "convert-to-lowercase"))
+ if (!strcmp(cep->name, "convert-to-lowercase"))
{
} else
- if (!strcmp(cep->ce_varname, "fullstatus-on-load"))
- {
- } else
- if (!strcmp(cep->ce_varname, "show-failedconnects"))
+ if (!strcmp(cep->name, "show-failedconnects"))
{
} else
{
config_error("%s:%i: unknown directive set::antirandom::%s",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname);
+ cep->file->filename, cep->line_number, cep->name);
errors++;
}
}
@@ -668,47 +648,43 @@ int antirandom_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
return 0;
/* We are only interrested in set::antirandom... */
- if (!ce || !ce->ce_varname || strcmp(ce->ce_varname, "antirandom"))
+ if (!ce || !ce->name || strcmp(ce->name, "antirandom"))
return 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "except-hosts"))
+ if (!strcmp(cep->name, "except-hosts"))
{
- for (cep2 = cep->ce_entries; cep2; cep2 = cep2->ce_next)
+ for (cep2 = cep->items; cep2; cep2 = cep2->next)
unreal_add_masks(&cfg.except_hosts, cep2);
} else
- if (!strcmp(cep->ce_varname, "except-webirc"))
+ if (!strcmp(cep->name, "except-webirc"))
{
- cfg.except_webirc = config_checkval(cep->ce_vardata, CFG_YESNO);
+ cfg.except_webirc = config_checkval(cep->value, CFG_YESNO);
} else
- if (!strcmp(cep->ce_varname, "threshold"))
+ if (!strcmp(cep->name, "threshold"))
{
- cfg.threshold = atoi(cep->ce_vardata);
+ cfg.threshold = atoi(cep->value);
} else
- if (!strcmp(cep->ce_varname, "ban-action"))
+ if (!strcmp(cep->name, "ban-action"))
{
- cfg.ban_action = banact_stringtoval(cep->ce_vardata);
+ cfg.ban_action = banact_stringtoval(cep->value);
} else
- if (!strcmp(cep->ce_varname, "ban-reason"))
+ if (!strcmp(cep->name, "ban-reason"))
{
- safe_strdup(cfg.ban_reason, cep->ce_vardata);
+ safe_strdup(cfg.ban_reason, cep->value);
} else
- if (!strcmp(cep->ce_varname, "ban-time"))
+ if (!strcmp(cep->name, "ban-time"))
{
- cfg.ban_time = config_checkval(cep->ce_vardata, CFG_TIME);
+ cfg.ban_time = config_checkval(cep->value, CFG_TIME);
} else
- if (!strcmp(cep->ce_varname, "convert-to-lowercase"))
+ if (!strcmp(cep->name, "convert-to-lowercase"))
{
- cfg.convert_to_lowercase = config_checkval(cep->ce_vardata, CFG_YESNO);
+ cfg.convert_to_lowercase = config_checkval(cep->value, CFG_YESNO);
}
- if (!strcmp(cep->ce_varname, "show-failedconnects"))
+ if (!strcmp(cep->name, "show-failedconnects"))
{
- cfg.show_failedconnects = config_checkval(cep->ce_vardata, CFG_YESNO);
- } else
- if (!strcmp(cep->ce_varname, "fullstatus-on-load"))
- {
- cfg.fullstatus_on_load = config_checkval(cep->ce_vardata, CFG_YESNO);
+ cfg.show_failedconnects = config_checkval(cep->value, CFG_YESNO);
}
}
return 1;
@@ -820,24 +796,15 @@ static int internal_getscore(char *str)
if (digits >= 5)
{
- score += 5 + (digits - 5);
-#ifdef DEBUGMODE
- sendto_ops_and_log("score@'%s': MATCH for digits check", str);
-#endif
+ score += digits;
}
if (vowels >= 4)
{
- score += 4 + (vowels - 4);
-#ifdef DEBUGMODE
- sendto_ops_and_log("score@'%s': MATCH for vowels check", str);
-#endif
+ score += vowels;
}
if (consonants >= 4)
{
- score += 4 + (consonants - 4);
-#ifdef DEBUGMODE
- sendto_ops_and_log("score@'%s': MATCH for consonants check", str);
-#endif
+ score += consonants;
}
for (t=triples; t; t=t->next)
@@ -846,10 +813,6 @@ static int internal_getscore(char *str)
if ((t->two[0] == s[0]) && (t->two[1] == s[1]) && s[2] && strchr(t->rest, s[2]))
{
score++; /* OK */
-#ifdef DEBUGMODE
- sendto_ops_and_log("score@'%s': MATCH for '%s[%s]' %c/%c/%c", str, t->two, t->rest,
- s[0], s[1], s[2]);
-#endif
}
}
@@ -868,11 +831,6 @@ static int get_spam_score(Client *client)
char *gecos = client->info;
char nbuf[NICKLEN+1], ubuf[USERLEN+1], rbuf[REALLEN+1];
int nscore, uscore, gscore, score;
-#ifdef TIMING
- struct timeval tv_alpha, tv_beta;
-
- gettimeofday(&tv_alpha, NULL);
-#endif
if (cfg.convert_to_lowercase)
{
@@ -889,46 +847,9 @@ static int get_spam_score(Client *client)
gscore = internal_getscore(gecos);
score = nscore + uscore + gscore;
-#ifdef TIMING
- gettimeofday(&tv_beta, NULL);
- ircd_log(LOG_ERROR, "AntiRandom Timing: %ld microseconds",
- ((tv_beta.tv_sec - tv_alpha.tv_sec) * 1000000) + (tv_beta.tv_usec - tv_alpha.tv_usec));
-#endif
-#ifdef DEBUGMODE
- sendto_ops_and_log("got score: %d/%d/%d = %d",
- nscore, uscore, gscore, score);
-#endif
-
return score;
}
-void check_all_users(void)
-{
- Client *client;
- int matches=0, score;
-
- list_for_each_entry(client, &lclient_list, lclient_node)
- {
- if (IsUser(client))
- {
- if (is_exempt(client))
- continue;
-
- score = get_spam_score(client);
- if (score > cfg.threshold)
- {
- if (!matches)
- sendto_realops("[antirandom] Full status report follows:");
- sendto_realops("%d points: %s!%s@%s:%s",
- score, client->name, client->user->username, client->user->realhost, client->info);
- matches++;
- }
- }
- }
- if (matches)
- sendto_realops("[antirandom] %d match%s", matches, matches == 1 ? "" : "es");
-}
-
int antirandom_preconnect(Client *client)
{
int score;
@@ -941,13 +862,17 @@ int antirandom_preconnect(Client *client)
{
if (cfg.ban_action == BAN_ACT_WARN)
{
- sendto_ops_and_log("[antirandom] would have denied access to user with score %d: %s!%s@%s:%s",
- score, client->name, client->user->username, client->user->realhost, client->info);
+ unreal_log(ULOG_INFO, "antirandom", "ANTIRANDOM_DENIED_USER", client,
+ "[antirandom] would have denied access to user with score $score: $client:$client.info",
+ log_data_integer("score", score));
return HOOK_CONTINUE;
}
if (cfg.show_failedconnects)
- sendto_ops_and_log("[antirandom] denied access to user with score %d: %s!%s@%s:%s",
- score, client->name, client->user->username, client->user->realhost, client->info);
+ {
+ unreal_log(ULOG_INFO, "antirandom", "ANTIRANDOM_DENIED_USER", client,
+ "[antirandom] denied access to user with score $score: $client:$client.info",
+ log_data_integer("score", score));
+ }
place_host_ban(client, cfg.ban_action, cfg.ban_reason, cfg.ban_time);
return HOOK_DENY;
}
@@ -972,7 +897,7 @@ static int is_exempt(Client *client)
/* WEBIRC gateway and exempt? */
if (cfg.except_webirc)
{
- char *val = moddata_client_get(client, "webirc");
+ const char *val = moddata_client_get(client, "webirc");
if (val && (atoi(val)>0))
return 1;
}
diff --git a/src/modules/authprompt.c b/src/modules/authprompt.c
index 3a46d96..da0d496 100644
--- a/src/modules/authprompt.c
+++ b/src/modules/authprompt.c
@@ -25,7 +25,7 @@ ModuleHeader MOD_HEADER
"1.0",
"SASL authentication for clients that don't support SASL",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/** Configuration settings */
@@ -33,6 +33,7 @@ struct {
int enabled;
MultiLine *message;
MultiLine *fail_message;
+ MultiLine *unconfirmed_message;
} cfg;
/** User struct */
@@ -50,10 +51,9 @@ static void init_config(void);
static void config_postdefaults(void);
int authprompt_config_test(ConfigFile *, ConfigEntry *, int, int *);
int authprompt_config_run(ConfigFile *, ConfigEntry *, int);
-int authprompt_require_sasl(Client *client, char *reason);
-int authprompt_sasl_continuation(Client *client, char *buf);
+int authprompt_sasl_continuation(Client *client, const char *buf);
int authprompt_sasl_result(Client *client, int success);
-int authprompt_place_host_ban(Client *client, int action, char *reason, long duration);
+int authprompt_place_host_ban(Client *client, int action, const char *reason, long duration);
int authprompt_find_tkline_match(Client *client, TKL *tk);
int authprompt_pre_connect(Client *client);
CMD_FUNC(cmd_auth);
@@ -89,7 +89,6 @@ MOD_INIT()
init_config();
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, authprompt_config_run);
- HookAdd(modinfo->handle, HOOKTYPE_REQUIRE_SASL, 0, authprompt_require_sasl);
HookAdd(modinfo->handle, HOOKTYPE_SASL_CONTINUATION, 0, authprompt_sasl_continuation);
HookAdd(modinfo->handle, HOOKTYPE_SASL_RESULT, 0, authprompt_sasl_result);
HookAdd(modinfo->handle, HOOKTYPE_PLACE_HOST_BAN, 0, authprompt_place_host_ban);
@@ -133,12 +132,18 @@ static void config_postdefaults(void)
{
addmultiline(&cfg.fail_message, "Authentication failed.");
}
+ if (!cfg.unconfirmed_message)
+ {
+ addmultiline(&cfg.unconfirmed_message, "You are trying to use an unconfirmed services account.");
+ addmultiline(&cfg.unconfirmed_message, "This services account can only be used after it has been activated/confirmed.");
+ }
}
static void free_config(void)
{
freemultiline(cfg.message);
freemultiline(cfg.fail_message);
+ freemultiline(cfg.unconfirmed_message);
memset(&cfg, 0, sizeof(cfg)); /* needed! */
}
@@ -151,29 +156,32 @@ int authprompt_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
return 0;
/* We are only interrested in set::authentication-prompt... */
- if (!ce || !ce->ce_varname || strcmp(ce->ce_varname, "authentication-prompt"))
+ if (!ce || !ce->name || strcmp(ce->name, "authentication-prompt"))
return 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!cep->ce_vardata)
+ if (!cep->value)
{
config_error("%s:%i: set::authentication-prompt::%s with no value",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname);
+ cep->file->filename, cep->line_number, cep->name);
errors++;
} else
- if (!strcmp(cep->ce_varname, "enabled"))
+ if (!strcmp(cep->name, "enabled"))
{
} else
- if (!strcmp(cep->ce_varname, "message"))
+ if (!strcmp(cep->name, "message"))
{
} else
- if (!strcmp(cep->ce_varname, "fail-message"))
+ if (!strcmp(cep->name, "fail-message"))
+ {
+ } else
+ if (!strcmp(cep->name, "unconfirmed-message"))
{
} else
{
config_error("%s:%i: unknown directive set::authentication-prompt::%s",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname);
+ cep->file->filename, cep->line_number, cep->name);
errors++;
}
}
@@ -189,22 +197,26 @@ int authprompt_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
return 0;
/* We are only interrested in set::authentication-prompt... */
- if (!ce || !ce->ce_varname || strcmp(ce->ce_varname, "authentication-prompt"))
+ if (!ce || !ce->name || strcmp(ce->name, "authentication-prompt"))
return 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "enabled"))
+ if (!strcmp(cep->name, "enabled"))
{
- cfg.enabled = config_checkval(cep->ce_vardata, CFG_YESNO);
+ cfg.enabled = config_checkval(cep->value, CFG_YESNO);
} else
- if (!strcmp(cep->ce_varname, "message"))
+ if (!strcmp(cep->name, "message"))
{
- addmultiline(&cfg.message, cep->ce_vardata);
+ addmultiline(&cfg.message, cep->value);
} else
- if (!strcmp(cep->ce_varname, "fail-message"))
+ if (!strcmp(cep->name, "fail-message"))
{
- addmultiline(&cfg.fail_message, cep->ce_vardata);
+ addmultiline(&cfg.fail_message, cep->value);
+ } else
+ if (!strcmp(cep->name, "unconfirmed-message"))
+ {
+ addmultiline(&cfg.unconfirmed_message, cep->value);
}
}
return 1;
@@ -257,7 +269,7 @@ char *make_authbuf(const char *username, const char *password)
int size;
size = strlen(username) + 1 + strlen(username) + 1 + strlen(password);
- if (size >= sizeof(inbuf))
+ if (size >= sizeof(inbuf)-1)
return NULL; /* too long */
/* Because size limits are already checked above, we can cut some corners here: */
@@ -281,7 +293,7 @@ void send_first_auth(Client *client)
{
Client *sasl_server;
char *addr = BadPtr(client->ip) ? "0" : client->ip;
- char *certfp = moddata_client_get(client, "certfp");
+ const char *certfp = moddata_client_get(client, "certfp");
sasl_server = find_client(SASL_SERVER, NULL);
if (!sasl_server)
{
@@ -365,25 +377,8 @@ void authprompt_send_auth_required_message(Client *client)
sendnotice_multiline(client, cfg.message);
}
-int authprompt_require_sasl(Client *client, char *reason)
-{
- /* If the client did SASL then we (authprompt) will not kick in */
- if (HasCapability(client, "sasl"))
- return 0;
-
- authprompt_tag_as_auth_required(client);
-
- /* Display the require authentication::reason */
- if (reason && strcmp(reason, "-") && strcmp(reason, "*"))
- sendnotice(client, "%s", reason);
-
- authprompt_send_auth_required_message(client);
-
- return 1;
-}
-
/* Called upon "place a host ban on this user" (eg: spamfilter, blacklist, ..) */
-int authprompt_place_host_ban(Client *client, int action, char *reason, long duration)
+int authprompt_place_host_ban(Client *client, int action, const char *reason, long duration)
{
/* If it's a soft-xx action and the user is not logged in
* and the user is not yet online, then we will handle this user.
@@ -437,7 +432,7 @@ int authprompt_pre_connect(Client *client)
return HOOK_CONTINUE; /* no action taken, proceed normally */
}
-int authprompt_sasl_continuation(Client *client, char *buf)
+int authprompt_sasl_continuation(Client *client, const char *buf)
{
/* If it's not for us (eg: user is doing real SASL) then return 0. */
if (!SEUSER(client) || !SEUSER(client)->authmsg)
@@ -468,10 +463,16 @@ int authprompt_sasl_result(Client *client, int success)
return 1;
}
+ if (client->user && !IsLoggedIn(client))
+ {
+ sendnotice_multiline(client, cfg.unconfirmed_message);
+ return 1;
+ }
+
/* Authentication was a success */
if (*client->name && client->user && *client->user->username && IsNotSpoof(client))
{
- register_user(client, client->name, client->user->username, NULL, NULL, NULL);
+ register_user(client);
/* User MAY be killed now. But since we 'return 1' below, it's safe */
}
diff --git a/src/modules/away.c b/src/modules/away.c
index a760c83..2d02a48 100644
--- a/src/modules/away.c
+++ b/src/modules/away.c
@@ -25,6 +25,9 @@
#include "unrealircd.h"
CMD_FUNC(cmd_away);
+int away_join(Client *client, Channel *channel, MessageTag *mtags);
+
+long CAP_AWAY_NOTIFY = 0L;
#define MSG_AWAY "AWAY"
@@ -34,12 +37,19 @@ ModuleHeader MOD_HEADER
"5.0",
"command /away",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
{
+ ClientCapabilityInfo c;
+ memset(&c, 0, sizeof(c));
+ c.name = "away-notify";
+ ClientCapabilityAdd(modinfo->handle, &c, &CAP_AWAY_NOTIFY);
CommandAdd(modinfo->handle, MSG_AWAY, cmd_away, 1, CMD_USER);
+ HookAdd(modinfo->handle, HOOKTYPE_LOCAL_JOIN, 0, away_join);
+ HookAdd(modinfo->handle, HOOKTYPE_REMOTE_JOIN, 0, away_join);
+
MARK_AS_OFFICIAL_MODULE(modinfo);
return MOD_SUCCESS;
}
@@ -54,17 +64,44 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
+int away_join(Client *client, Channel *channel, MessageTag *mtags)
+{
+ Member *lp;
+ Client *acptr;
+ int invisible = invisible_user_in_channel(client, channel);
+ for (lp = channel->members; lp; lp = lp->next)
+ {
+ acptr = lp->client;
+
+ if (!MyConnect(acptr))
+ continue; /* only locally connected clients */
+
+ if (invisible && !check_channel_access_member(lp, "hoaq") && (client != acptr))
+ continue; /* skip non-ops if requested to (used for mode +D), but always send to 'client' */
+
+ if (client->user->away && HasCapabilityFast(acptr, CAP_AWAY_NOTIFY))
+ {
+ MessageTag *mtags_away = NULL;
+ new_message(client, NULL, &mtags_away);
+ sendto_one(acptr, mtags_away, ":%s!%s@%s AWAY :%s",
+ client->name, client->user->username, GetHost(client), client->user->away);
+ free_message_tags(mtags_away);
+ }
+ }
+ return 0;
+}
+
/** Mark client as AWAY or mark them as back (in case of empty reason) */
CMD_FUNC(cmd_away)
{
- char *new_reason = parv[1];
+ char reason[512];
int n, already_as_away = 0;
MessageTag *mtags = NULL;
if (IsServer(client))
return;
- if (parc < 2 || !*new_reason)
+ if (parc < 2 || BadPtr(parv[1]))
{
/* Marking as not away */
if (client->user->away)
@@ -73,10 +110,9 @@ CMD_FUNC(cmd_away)
new_message(client, recv_mtags, &mtags);
sendto_server(client, 0, 0, mtags, ":%s AWAY", client->name);
- hash_check_watch(client, RPL_NOTAWAY);
- sendto_local_common_channels(client, client, ClientCapabilityBit("away-notify"), mtags,
+ sendto_local_common_channels(client, client, CAP_AWAY_NOTIFY, mtags,
":%s AWAY", client->name);
- RunHook3(HOOKTYPE_AWAY, client, mtags, NULL);
+ RunHook(HOOKTYPE_AWAY, client, mtags, NULL, 0);
free_message_tags(mtags);
}
@@ -85,8 +121,11 @@ CMD_FUNC(cmd_away)
return;
}
+ /* Obey set::away-length */
+ strlncpy(reason, parv[1], sizeof(reason), iConf.away_length);
+
/* Check spamfilters */
- if (MyUser(client) && match_spamfilter(client, new_reason, SPAMF_AWAY, "AWAY", NULL, 0, NULL))
+ if (MyUser(client) && match_spamfilter(client, reason, SPAMF_AWAY, "AWAY", NULL, 0, NULL))
return;
/* Check away-flood */
@@ -98,21 +137,17 @@ CMD_FUNC(cmd_away)
return;
}
- /* Obey set::away-length */
- if (strlen(new_reason) > iConf.away_length)
- new_reason[iConf.away_length] = '\0';
-
/* Check if the new away reason is the same as the current reason - if so then return (no change) */
- if ((client->user->away) && !strcmp(client->user->away, new_reason))
+ if ((client->user->away) && !strcmp(client->user->away, reason))
return;
/* All tests passed. Now marking as away (or still away but changing the away reason) */
- client->user->lastaway = TStime();
+ client->user->away_since = TStime();
new_message(client, recv_mtags, &mtags);
- sendto_server(client, 0, 0, mtags, ":%s AWAY :%s", client->id, new_reason);
+ sendto_server(client, 0, 0, mtags, ":%s AWAY :%s", client->id, reason);
if (client->user->away)
{
@@ -120,18 +155,16 @@ CMD_FUNC(cmd_away)
already_as_away = 1;
}
- safe_strdup(client->user->away, new_reason);
+ safe_strdup(client->user->away, reason);
if (MyConnect(client))
sendnumeric(client, RPL_NOWAWAY);
- hash_check_watch(client, already_as_away ? RPL_REAWAY : RPL_GONEAWAY);
-
sendto_local_common_channels(client, client,
- ClientCapabilityBit("away-notify"), mtags,
+ CAP_AWAY_NOTIFY, mtags,
":%s AWAY :%s", client->name, client->user->away);
- RunHook3(HOOKTYPE_AWAY, client, mtags, client->user->away);
+ RunHook(HOOKTYPE_AWAY, client, mtags, client->user->away, already_as_away);
free_message_tags(mtags);
diff --git a/src/modules/batch.c b/src/modules/batch.c
index e1ca1a8..692680c 100644
--- a/src/modules/batch.c
+++ b/src/modules/batch.c
@@ -28,7 +28,7 @@ ModuleHeader MOD_HEADER
"5.0",
"Batch CAP",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Forward declarations */
@@ -37,7 +37,7 @@ CMD_FUNC(cmd_batch);
/* Variables */
long CAP_BATCH = 0L;
-int batch_mtag_is_ok(Client *client, char *name, char *value);
+int batch_mtag_is_ok(Client *client, const char *name, const char *value);
MOD_INIT()
{
@@ -111,7 +111,7 @@ CMD_FUNC(cmd_batch)
* syntax.
* We simply allow batch ONLY from servers and with any syntax.
*/
-int batch_mtag_is_ok(Client *client, char *name, char *value)
+int batch_mtag_is_ok(Client *client, const char *name, const char *value)
{
if (IsServer(client))
return 1;
diff --git a/src/modules/blacklist.c b/src/modules/blacklist.c
index 7cc99cd..696b8fa 100644
--- a/src/modules/blacklist.c
+++ b/src/modules/blacklist.c
@@ -26,7 +26,7 @@ ModuleHeader MOD_HEADER
"5.0",
"Check connecting users against DNS Blacklists",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* In this module and the config syntax I tried to 'abstract' things
@@ -83,6 +83,9 @@ struct BLUser {
long save_tkltime;
char *save_opernotice;
char *save_reason;
+ char *save_blacklist;
+ char *save_blacklist_dns_name;
+ int save_blacklist_dns_reply;
};
/* Global variables */
@@ -96,7 +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_quit(Client *client, MessageTag *mtags, char *comment);
+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);
int blacklist_start_check(Client *client);
@@ -109,13 +112,11 @@ void blacklist_free_bluser_if_able(BLUser *bl);
#define SetBLUser(x, y) do { moddata_client(x, blacklist_md).ptr = y; } while(0)
#define BLUSER(x) ((BLUser *)moddata_client(x, blacklist_md).ptr)
-long SNO_BLACKLIST = 0L;
-
MOD_TEST()
{
HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, blacklist_config_test);
- CallbackAddEx(modinfo->handle, CALLBACKTYPE_BLACKLIST_CHECK, blacklist_start_check);
+ CallbackAdd(modinfo->handle, CALLBACKTYPE_BLACKLIST_CHECK, blacklist_start_check);
return MOD_SUCCESS;
}
@@ -150,8 +151,6 @@ MOD_INIT()
HookAdd(modinfo->handle, HOOKTYPE_REHASH_COMPLETE, 0, blacklist_rehash_complete);
HookAdd(modinfo->handle, HOOKTYPE_LOCAL_QUIT, 0, blacklist_quit);
- SnomaskAdd(modinfo->handle, 'b', umode_allow_opers, &SNO_BLACKLIST);
-
return MOD_SUCCESS;
}
@@ -251,192 +250,192 @@ int blacklist_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
if (!ce)
return 0;
- if (strcmp(ce->ce_varname, "blacklist"))
+ if (strcmp(ce->name, "blacklist"))
return 0; /* not interested in non-blacklist stuff.. */
- if (!ce->ce_vardata)
+ if (!ce->value)
{
config_error("%s:%i: blacklist block without name (use: blacklist somename { })",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
*errs = 1;
return -1;
}
/* Now actually go parse the blacklist { } block */
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "dns"))
+ if (!strcmp(cep->name, "dns"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "reply"))
+ if (!strcmp(cepp->name, "reply"))
{
if (has_dns_reply)
{
/* this is an error (not a warning) */
config_error("%s:%i: blacklist block may contain only one blacklist::dns::reply item. "
"You can specify multiple replies by using: reply { 1; 2; 4; };",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum);
+ cepp->file->filename, cepp->line_number);
errors++;
continue;
}
- if (!cepp->ce_vardata && !cepp->ce_entries)
+ if (!cepp->value && !cepp->items)
{
- config_error_blank(cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum, "blacklist::dns::reply");
+ config_error_blank(cepp->file->filename, cepp->line_number, "blacklist::dns::reply");
errors++;
continue;
}
has_dns_reply = 1; /* we have a reply. now whether it's actually valid is another story.. */
- if (cepp->ce_vardata && cepp->ce_entries)
+ if (cepp->value && cepp->items)
{
config_error("%s:%i: blacklist::dns::reply must be either using format 'reply 1;' or "
"'reply { 1; 2; 4; }; but not both formats at the same time.",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum);
+ cepp->file->filename, cepp->line_number);
errors++;
continue;
}
- if (cepp->ce_vardata)
+ if (cepp->value)
{
- if (atoi(cepp->ce_vardata) <= 0)
+ if (atoi(cepp->value) <= 0)
{
config_error("%s:%i: blacklist::dns::reply must be >0",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum);
+ cepp->file->filename, cepp->line_number);
errors++;
continue;
}
}
- if (cepp->ce_entries)
+ if (cepp->items)
{
- for (ceppp = cepp->ce_entries; ceppp; ceppp=ceppp->ce_next)
+ for (ceppp = cepp->items; ceppp; ceppp=ceppp->next)
{
- if (atoi(ceppp->ce_varname) <= 0)
+ if (atoi(ceppp->name) <= 0)
{
config_error("%s:%i: all items in blacklist::dns::reply must be >0",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum);
+ cepp->file->filename, cepp->line_number);
errors++;
}
}
}
} else
- if (!cepp->ce_vardata)
+ if (!cepp->value)
{
- config_error_empty(cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum,
- "blacklist::dns", cepp->ce_varname);
+ config_error_empty(cepp->file->filename, cepp->line_number,
+ "blacklist::dns", cepp->name);
errors++;
continue;
} else
- if (!strcmp(cepp->ce_varname, "name"))
+ if (!strcmp(cepp->name, "name"))
{
if (has_dns_name)
{
- config_warn_duplicate(cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum, "blacklist::dns::name");
+ config_warn_duplicate(cepp->file->filename,
+ cepp->line_number, "blacklist::dns::name");
}
has_dns_name = 1;
} else
- if (!strcmp(cepp->ce_varname, "type"))
+ if (!strcmp(cepp->name, "type"))
{
if (has_dns_type)
{
- config_warn_duplicate(cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum, "blacklist::dns::type");
+ config_warn_duplicate(cepp->file->filename,
+ cepp->line_number, "blacklist::dns::type");
}
has_dns_type = 1;
- if (!strcmp(cepp->ce_vardata, "record"))
+ if (!strcmp(cepp->value, "record"))
;
- else if (!strcmp(cepp->ce_vardata, "bitmask"))
+ else if (!strcmp(cepp->value, "bitmask"))
;
else
{
config_error("%s:%i: unknown blacklist::dns::type '%s', must be either 'record' or 'bitmask'",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum, cepp->ce_vardata);
+ cepp->file->filename, cepp->line_number, cepp->value);
errors++;
}
}
}
} else
- if (!cep->ce_vardata)
+ if (!cep->value)
{
- config_error_empty(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- "blacklist", cep->ce_varname);
+ config_error_empty(cep->file->filename, cep->line_number,
+ "blacklist", cep->name);
errors++;
continue;
}
- else if (!strcmp(cep->ce_varname, "action"))
+ else if (!strcmp(cep->name, "action"))
{
if (has_action)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "blacklist::action");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "blacklist::action");
continue;
}
has_action = 1;
- if (!banact_stringtoval(cep->ce_vardata))
+ if (!banact_stringtoval(cep->value))
{
config_error("%s:%i: blacklist::action has unknown action type '%s'",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_vardata);
+ cep->file->filename, cep->line_number, cep->value);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "ban-time"))
+ else if (!strcmp(cep->name, "ban-time"))
{
if (has_ban_time)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "blacklist::ban-time");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "blacklist::ban-time");
continue;
}
has_ban_time = 1;
} else
- if (!strcmp(cep->ce_varname, "reason"))
+ if (!strcmp(cep->name, "reason"))
{
if (has_reason)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "blacklist::reason");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "blacklist::reason");
continue;
}
has_reason = 1;
}
else
{
- config_error_unknown(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- "blacklist", cep->ce_varname);
+ config_error_unknown(cep->file->filename, cep->line_number,
+ "blacklist", cep->name);
errors++;
}
}
if (!has_action)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"blacklist::action");
errors++;
}
if (!has_reason)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"blacklist::reason");
errors++;
}
if (!has_dns_name)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"blacklist::dns::name");
errors++;
}
if (!has_dns_type)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"blacklist::dns::type");
errors++;
}
if (!has_dns_reply)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"blacklist::dns::reply");
errors++;
}
@@ -453,12 +452,12 @@ int blacklist_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
if (type != CONFIG_MAIN)
return 0;
- if (!ce || !ce->ce_varname || strcmp(ce->ce_varname, "blacklist"))
+ if (!ce || !ce->name || strcmp(ce->name, "blacklist"))
return 0; /* not interested */
d = safe_alloc(sizeof(Blacklist));
- safe_strdup(d->name, ce->ce_vardata);
- /* set some defaults. TODO: use set::blacklist or something ? */
+ safe_strdup(d->name, ce->value);
+ /* set some defaults */
d->action = BAN_ACT_KILL;
safe_strdup(d->reason, "Your IP is on a DNS Blacklist");
d->ban_time = 3600;
@@ -468,28 +467,28 @@ int blacklist_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
d->backend = safe_alloc(sizeof(BlacklistBackend));
d->backend->dns = safe_alloc(sizeof(DNSBL));
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "dns"))
+ if (!strcmp(cep->name, "dns"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "reply"))
+ if (!strcmp(cepp->name, "reply"))
{
- if (cepp->ce_vardata)
+ if (cepp->value)
{
/* single reply */
d->backend->dns->reply = safe_alloc(sizeof(int)*2);
- d->backend->dns->reply[0] = atoi(cepp->ce_vardata);
+ d->backend->dns->reply[0] = atoi(cepp->value);
d->backend->dns->reply[1] = 0;
} else
- if (cepp->ce_entries)
+ if (cepp->items)
{
/* (potentially) multiple reply values */
int cnt = 0;
- for (ceppp = cepp->ce_entries; ceppp; ceppp = ceppp->ce_next)
+ for (ceppp = cepp->items; ceppp; ceppp = ceppp->next)
{
- if (ceppp->ce_varname)
+ if (ceppp->name)
cnt++;
}
@@ -499,37 +498,37 @@ int blacklist_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
d->backend->dns->reply = safe_alloc(sizeof(int)*(cnt+1));
cnt = 0;
- for (ceppp = cepp->ce_entries; ceppp; ceppp = ceppp->ce_next)
+ for (ceppp = cepp->items; ceppp; ceppp = ceppp->next)
{
- d->backend->dns->reply[cnt++] = atoi(ceppp->ce_varname);
+ d->backend->dns->reply[cnt++] = atoi(ceppp->name);
}
d->backend->dns->reply[cnt] = 0;
}
} else
- if (!strcmp(cepp->ce_varname, "type"))
+ if (!strcmp(cepp->name, "type"))
{
- if (!strcmp(cepp->ce_vardata, "record"))
+ if (!strcmp(cepp->value, "record"))
d->backend->dns->type = DNSBL_RECORD;
- else if (!strcmp(cepp->ce_vardata, "bitmask"))
+ else if (!strcmp(cepp->value, "bitmask"))
d->backend->dns->type = DNSBL_BITMASK;
} else
- if (!strcmp(cepp->ce_varname, "name"))
+ if (!strcmp(cepp->name, "name"))
{
- safe_strdup(d->backend->dns->name, cepp->ce_vardata);
+ safe_strdup(d->backend->dns->name, cepp->value);
}
}
}
- else if (!strcmp(cep->ce_varname, "action"))
+ else if (!strcmp(cep->name, "action"))
{
- d->action = banact_stringtoval(cep->ce_vardata);
+ d->action = banact_stringtoval(cep->value);
}
- else if (!strcmp(cep->ce_varname, "reason"))
+ else if (!strcmp(cep->name, "reason"))
{
- safe_strdup(d->reason, cep->ce_vardata);
+ safe_strdup(d->reason, cep->value);
}
- else if (!strcmp(cep->ce_varname, "ban-time"))
+ else if (!strcmp(cep->name, "ban-time"))
{
- d->ban_time = config_checkval(cep->ce_vardata, CFG_TIME);
+ d->ban_time = config_checkval(cep->value, CFG_TIME);
}
}
@@ -644,7 +643,7 @@ void blacklist_cancel(BLUser *bl)
bl->client = NULL;
}
-int blacklist_quit(Client *client, MessageTag *mtags, char *comment)
+int blacklist_quit(Client *client, MessageTag *mtags, const char *comment)
{
if (BLUSER(client))
blacklist_cancel(BLUSER(client));
@@ -725,10 +724,17 @@ int blacklist_parse_reply(struct hostent *he, int entry)
* from blacklist_preconnect() for softbans that need to be delayed
* as to give the user the opportunity to do SASL Authentication.
*/
-int blacklist_action(Client *client, char *opernotice, BanAction ban_action, char *ban_reason, long ban_time)
+int blacklist_action(Client *client, char *opernotice, BanAction ban_action, char *ban_reason, long ban_time,
+ char *blacklist, char *blacklist_dns_name, int blacklist_dns_reply)
{
- sendto_snomask(SNO_BLACKLIST, "%s", opernotice);
- ircd_log(LOG_KILL, "%s", opernotice);
+ unreal_log_raw(ULOG_INFO, "blacklist", "BLACKLIST_HIT", client,
+ opernotice,
+ log_data_string("blacklist_name", blacklist),
+ log_data_string("blacklist_dns_name", blacklist_dns_name),
+ log_data_integer("blacklist_dns_reply", blacklist_dns_reply),
+ log_data_string("ban_action", banact_valtostring(ban_action)),
+ log_data_string("ban_reason", ban_reason),
+ log_data_integer("ban_time", ban_time));
if (ban_action == BAN_ACT_WARN)
return 0;
return place_host_ban(client, ban_action, ban_reason, ban_time);
@@ -766,9 +772,12 @@ void blacklist_hit(Client *client, Blacklist *bl, int reply)
blu->save_tkltime = bl->ban_time;
safe_strdup(blu->save_opernotice, opernotice);
safe_strdup(blu->save_reason, banbuf);
+ safe_strdup(blu->save_blacklist, bl->name);
+ safe_strdup(blu->save_blacklist_dns_name, bl->backend->dns->name);
+ blu->save_blacklist_dns_reply = reply;
} else {
/* Otherwise, execute the action immediately */
- blacklist_action(client, opernotice, bl->action, banbuf, bl->ban_time);
+ blacklist_action(client, opernotice, bl->action, banbuf, bl->ban_time, bl->name, bl->backend->dns->name, reply);
}
}
@@ -841,7 +850,10 @@ int blacklist_preconnect(Client *client)
if (IsLoggedIn(client))
return HOOK_CONTINUE; /* yup, so the softban does not apply. */
- if (blacklist_action(client, blu->save_opernotice, blu->save_action, blu->save_reason, blu->save_tkltime))
+ if (blacklist_action(client, blu->save_opernotice, blu->save_action, blu->save_reason, blu->save_tkltime,
+ blu->save_blacklist, blu->save_blacklist_dns_name, blu->save_blacklist_dns_reply))
+ {
return HOOK_DENY;
+ }
return HOOK_CONTINUE; /* exempt */
}
diff --git a/src/modules/bot-tag.c b/src/modules/bot-tag.c
index ed566ef..2a300c3 100644
--- a/src/modules/bot-tag.c
+++ b/src/modules/bot-tag.c
@@ -33,11 +33,11 @@ ModuleHeader MOD_HEADER
"5.0",
"bot message tag",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
-int bottag_mtag_is_ok(Client *client, char *name, char *value);
-void mtag_add_bottag(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, char *signature);
+int bottag_mtag_is_ok(Client *client, const char *name, const char *value);
+void mtag_add_bottag(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, const char *signature);
MOD_INIT()
{
@@ -68,7 +68,7 @@ MOD_UNLOAD()
/** This function verifies if the client sending the mtag is permitted to do so.
*/
-int bottag_mtag_is_ok(Client *client, char *name, char *value)
+int bottag_mtag_is_ok(Client *client, const char *name, const char *value)
{
if (IsServer(client) && (value == NULL))
return 1; /* OK */
@@ -76,7 +76,7 @@ int bottag_mtag_is_ok(Client *client, char *name, char *value)
return 0;
}
-void mtag_add_bottag(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, char *signature)
+void mtag_add_bottag(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, const char *signature)
{
MessageTag *m;
diff --git a/src/modules/botmotd.c b/src/modules/botmotd.c
index a36248b..b5dcde2 100644
--- a/src/modules/botmotd.c
+++ b/src/modules/botmotd.c
@@ -32,7 +32,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /botmotd",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
@@ -60,7 +60,7 @@ CMD_FUNC(cmd_botmotd)
MOTDLine *motdline;
ConfigItem_tld *tld;
- if (hunt_server(client, recv_mtags, ":%s BOTMOTD :%s", 1, parc, parv) != HUNTED_ISME)
+ if (hunt_server(client, recv_mtags, "BOTMOTD", 1, parc, parv) != HUNTED_ISME)
return;
if (!IsUser(client))
diff --git a/src/modules/cap.c b/src/modules/cap.c
index 7b886a3..08ffe5e 100644
--- a/src/modules/cap.c
+++ b/src/modules/cap.c
@@ -34,7 +34,7 @@ ModuleHeader MOD_HEADER
"5.0", /* Version */
"command /cap", /* Short description of module */
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Forward declarations */
@@ -43,13 +43,7 @@ int cap_never_visible(Client *client);
/* Variables */
long CAP_IN_PROGRESS = 0L;
-long CAP_ACCOUNT_NOTIFY = 0L;
-long CAP_AWAY_NOTIFY = 0L;
-long CAP_MULTI_PREFIX = 0L;
-long CAP_USERHOST_IN_NAMES = 0L;
long CAP_NOTIFY = 0L;
-long CAP_CHGHOST = 0L;
-long CAP_EXTENDED_JOIN = 0L;
MOD_INIT()
{
@@ -66,34 +60,10 @@ MOD_INIT()
c.visible = cap_never_visible;
ClientCapabilityAdd(modinfo->handle, &c, &CAP_IN_PROGRESS);
- memset(&c, 0, sizeof(c));
- c.name = "account-notify";
- ClientCapabilityAdd(modinfo->handle, &c, &CAP_ACCOUNT_NOTIFY);
-
- memset(&c, 0, sizeof(c));
- c.name = "away-notify";
- ClientCapabilityAdd(modinfo->handle, &c, &CAP_AWAY_NOTIFY);
-
- memset(&c, 0, sizeof(c));
- c.name = "multi-prefix";
- ClientCapabilityAdd(modinfo->handle, &c, &CAP_MULTI_PREFIX);
-
- memset(&c, 0, sizeof(c));
- c.name = "userhost-in-names";
- ClientCapabilityAdd(modinfo->handle, &c, &CAP_USERHOST_IN_NAMES);
-
memset(&c, 0, sizeof(c));
c.name = "cap-notify";
ClientCapabilityAdd(modinfo->handle, &c, &CAP_NOTIFY);
- memset(&c, 0, sizeof(c));
- c.name = "chghost";
- ClientCapabilityAdd(modinfo->handle, &c, &CAP_CHGHOST);
-
- memset(&c, 0, sizeof(c));
- c.name = "extended-join";
- ClientCapabilityAdd(modinfo->handle, &c, &CAP_EXTENDED_JOIN);
-
HookAdd(modinfo->handle, HOOKTYPE_IS_HANDSHAKE_FINISHED, 0, cap_is_handshake_finished);
return MOD_SUCCESS;
@@ -139,17 +109,17 @@ static ClientCapability *clicap_find(Client *client, const char *data, int *nega
return NULL;
}
- if(*p == '-')
+ if (*p == '-')
{
*negate = 1;
p++;
/* someone sent a '-' without a parameter.. */
- if(*p == '\0')
+ if (*p == '\0')
return NULL;
}
- if((s = strchr(p, ' ')))
+ if ((s = strchr(p, ' ')))
*s++ = '\0';
cap = ClientCapabilityFind(p, client);
@@ -190,7 +160,7 @@ static void clicap_generate(Client *client, const char *subcmd, int flags)
for (cap = clicaps; cap; cap = cap->next)
{
char name[256];
- char *param;
+ const char *param;
if (cap->visible && !cap->visible(client))
continue; /* hidden */
@@ -240,7 +210,7 @@ static void cap_end(Client *client, const char *arg)
ClearCapabilityFast(client, CAP_IN_PROGRESS);
if (*client->name && client->user && *client->user->username && IsNotSpoof(client))
- register_user(client, client->name, client->user->username, NULL, NULL, NULL);
+ register_user(client);
}
static void cap_list(Client *client, const char *arg)
@@ -386,8 +356,8 @@ CMD_FUNC(cmd_cap)
* Only add a 1 second fake lag penalty if this is the XXth command.
* This will speed up connections considerably.
*/
- if (client->local->receiveM > 15)
- client->local->since++;
+ if (client->local->traffic.messages_received > 15)
+ add_fake_lag(client, 1000);
if (DISABLE_CAP)
{
@@ -406,7 +376,7 @@ CMD_FUNC(cmd_cap)
return;
}
- if(!(cmd = bsearch(parv[1], clicap_cmdtable,
+ if (!(cmd = bsearch(parv[1], clicap_cmdtable,
sizeof(clicap_cmdtable) / sizeof(struct clicap_cmd),
sizeof(struct clicap_cmd), (bqcmp) clicap_cmd_search)))
{
diff --git a/src/modules/certfp.c b/src/modules/certfp.c
index 1ec8b9a..c389b9e 100644
--- a/src/modules/certfp.c
+++ b/src/modules/certfp.c
@@ -1,6 +1,6 @@
/*
* Certificate Fingerprint Module
- * This grabs the SHA256 fingerprint of the SSL/TLS client certificate
+ * This grabs the SHA256 fingerprint of the TLS client certificate
* the user is using, shares it with the other servers (and rest of
* UnrealIRCd) and shows it in /WHOIS etc.
*
@@ -17,24 +17,22 @@ ModuleHeader MOD_HEADER
"5.0",
"Certificate fingerprint",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Forward declarations */
void certfp_free(ModData *m);
-char *certfp_serialize(ModData *m);
-void certfp_unserialize(char *str, ModData *m);
+const char *certfp_serialize(ModData *m);
+void certfp_unserialize(const char *str, ModData *m);
int certfp_handshake(Client *client);
int certfp_connect(Client *client);
-int certfp_whois(Client *client, Client *target);
+int certfp_whois(Client *client, Client *target, NameValuePrioList **list);
ModDataInfo *certfp_md; /* Module Data structure which we acquire */
-#define WHOISCERTFP_STRING ":%s 276 %s %s :has client certificate fingerprint %s"
-
MOD_INIT()
{
-ModDataInfo mreq;
+ ModDataInfo mreq;
MARK_AS_OFFICIAL_MODULE(modinfo);
@@ -43,7 +41,7 @@ ModDataInfo mreq;
mreq.free = certfp_free;
mreq.serialize = certfp_serialize;
mreq.unserialize = certfp_unserialize;
- mreq.sync = 1;
+ mreq.sync = MODDATA_SYNC_EARLY;
mreq.type = MODDATATYPE_CLIENT;
certfp_md = ModDataAdd(modinfo->handle, mreq);
if (!certfp_md)
@@ -121,7 +119,7 @@ int certfp_connect(Client *client)
{
if (IsSecure(client))
{
- char *fp = moddata_client_get(client, "certfp");
+ const char *fp = moddata_client_get(client, "certfp");
if (fp && !iConf.no_connect_tls_info)
sendnotice(client, "*** Your TLS certificate fingerprint is %s", fp);
@@ -130,12 +128,17 @@ int certfp_connect(Client *client)
return 0;
}
-int certfp_whois(Client *client, Client *target)
+int certfp_whois(Client *client, Client *target, NameValuePrioList **list)
{
- char *fp = moddata_client_get(target, "certfp");
-
- if (fp)
- sendnumeric(client, RPL_WHOISCERTFP, target->name, fp);
+ const char *fp = moddata_client_get(target, "certfp");
+ char buf[512];
+
+ if (!fp)
+ return 0;
+
+ if (whois_get_policy(client, target, "certfp") == WHOIS_CONFIG_DETAILS_FULL)
+ add_nvplist_numeric(list, 0, "certfp", client, RPL_WHOISCERTFP, target->name, fp);
+
return 0;
}
@@ -144,14 +147,14 @@ void certfp_free(ModData *m)
safe_free(m->str);
}
-char *certfp_serialize(ModData *m)
+const char *certfp_serialize(ModData *m)
{
if (!m->str)
return NULL;
return m->str;
}
-void certfp_unserialize(char *str, ModData *m)
+void certfp_unserialize(const char *str, ModData *m)
{
safe_strdup(m->str, str);
}
diff --git a/src/modules/chanmodes/Makefile.in b/src/modules/chanmodes/Makefile.in
index a493260..0544b9c 100644
--- a/src/modules/chanmodes/Makefile.in
+++ b/src/modules/chanmodes/Makefile.in
@@ -25,14 +25,17 @@ INCLUDES = ../../include/channel.h \
../../include/ircsprintf.h \
../../include/license.h \
../../include/modules.h ../../include/modversion.h ../../include/msg.h \
- ../../include/numeric.h ../../include/proto.h ../../include/dns.h \
+ ../../include/numeric.h ../../include/dns.h \
../../include/resource.h ../../include/setup.h \
../../include/struct.h ../../include/sys.h \
- ../../include/types.h ../../include/url.h \
+ ../../include/types.h \
../../include/version.h ../../include/whowas.h
R_MODULES= \
- nocolor.so stripcolor.so issecure.so permanent.so floodprot.so \
+ chanowner.so chanadmin.so chanop.so halfop.so voice.so \
+ key.so limit.so inviteonly.so secret.so private.so \
+ moderated.so noexternalmsgs.so topiclimit.so \
+ nocolor.so stripcolor.so isregistered.so issecure.so permanent.so floodprot.so \
noctcp.so link.so censor.so delayjoin.so noknock.so noinvite.so operonly.so \
nonotice.so regonly.so nonickchange.so nokick.so regonlyspeak.so \
secureonly.so history.so
@@ -41,6 +44,9 @@ MODULES=$(R_MODULES)
MODULEFLAGS=@MODULEFLAGS@
RM=@RM@
+.SUFFIXES:
+.SUFFIXES: .c .h .so
+
all: build
build: $(MODULES)
@@ -48,82 +54,6 @@ build: $(MODULES)
clean:
$(RM) -f *.o *.so *~ core
-#############################################################################
-# .so's section
-#############################################################################
-
-issecure.so: issecure.c $(INCLUDES)
+%.so: %.c $(INCLUDES)
$(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o issecure.so issecure.c
-
-nocolor.so: nocolor.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o nocolor.so nocolor.c
-
-stripcolor.so: stripcolor.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o stripcolor.so stripcolor.c
-
-permanent.so: permanent.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o permanent.so permanent.c
-
-floodprot.so: floodprot.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o floodprot.so floodprot.c
-
-noctcp.so: noctcp.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o noctcp.so noctcp.c
-
-link.so: link.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o link.so link.c
-
-censor.so: censor.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o censor.so censor.c
-
-delayjoin.so: delayjoin.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o delayjoin.so delayjoin.c
-
-noknock.so: noknock.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o noknock.so noknock.c
-
-noinvite.so: noinvite.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o noinvite.so noinvite.c
-
-operonly.so: operonly.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o operonly.so operonly.c
-
-nonotice.so: nonotice.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o nonotice.so nonotice.c
-
-regonly.so: regonly.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o regonly.so regonly.c
-
-nonickchange.so: nonickchange.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o nonickchange.so nonickchange.c
-
-nokick.so: nokick.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o nokick.so nokick.c
-
-regonlyspeak.so: regonlyspeak.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o regonlyspeak.so regonlyspeak.c
-
-secureonly.so: secureonly.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o secureonly.so secureonly.c
-
-history.so: history.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o history.so history.c
+ -o $@ $<
diff --git a/src/modules/chanmodes/censor.c b/src/modules/chanmodes/censor.c
index 767d21f..5ae21a8 100644
--- a/src/modules/chanmodes/censor.c
+++ b/src/modules/chanmodes/censor.c
@@ -12,18 +12,18 @@ ModuleHeader MOD_HEADER
"4.2",
"Channel Mode +G",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
Cmode_t EXTMODE_CENSOR = 0L;
-#define IsCensored(x) ((x)->mode.extmode & EXTMODE_CENSOR)
+#define IsCensored(x) ((x)->mode.mode & EXTMODE_CENSOR)
-int censor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
-char *censor_pre_local_part(Client *client, Channel *channel, char *text);
-char *censor_pre_local_quit(Client *client, char *text);
-int censor_stats_badwords_channel(Client *client, char *para);
+int censor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype);
+const char *censor_pre_local_part(Client *client, Channel *channel, const char *text);
+const char *censor_pre_local_quit(Client *client, const char *text);
+int censor_stats_badwords_channel(Client *client, const char *para);
int censor_config_test(ConfigFile *, ConfigEntry *, int, int *);
int censor_config_run(ConfigFile *, ConfigEntry *, int);
@@ -49,12 +49,12 @@ MOD_INIT()
memset(&req, 0, sizeof(req));
req.paracount = 0;
req.is_ok = extcmode_default_requirechop;
- req.flag = 'G';
+ req.letter = 'G';
CmodeAdd(modinfo->handle, req, &EXTMODE_CENSOR);
HookAdd(modinfo->handle, HOOKTYPE_CAN_SEND_TO_CHANNEL, 0, censor_can_send_to_channel);
- HookAddPChar(modinfo->handle, HOOKTYPE_PRE_LOCAL_PART, 0, censor_pre_local_part);
- HookAddPChar(modinfo->handle, HOOKTYPE_PRE_LOCAL_QUIT, 0, censor_pre_local_quit);
+ HookAddConstString(modinfo->handle, HOOKTYPE_PRE_LOCAL_PART, 0, censor_pre_local_part);
+ HookAddConstString(modinfo->handle, HOOKTYPE_PRE_LOCAL_QUIT, 0, censor_pre_local_quit);
HookAdd(modinfo->handle, HOOKTYPE_STATS, 0, censor_stats_badwords_channel);
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, censor_config_run);
return MOD_SUCCESS;
@@ -88,99 +88,99 @@ int censor_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
if (type != CONFIG_MAIN)
return 0;
- if (!ce || !ce->ce_varname || strcmp(ce->ce_varname, "badword"))
+ if (!ce || !ce->name || strcmp(ce->name, "badword"))
return 0; /* not interested */
- if (!ce->ce_vardata)
+ if (!ce->value)
{
config_error("%s:%i: badword without type",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
return 1;
}
- else if (strcmp(ce->ce_vardata, "channel") &&
- strcmp(ce->ce_vardata, "quit") && strcmp(ce->ce_vardata, "all")) {
+ else if (strcmp(ce->value, "channel") &&
+ strcmp(ce->value, "quit") && strcmp(ce->value, "all")) {
/* config_error("%s:%i: badword with unknown type",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum); -- can't do that.. */
+ ce->file->filename, ce->line_number); -- can't do that.. */
return 0; /* unhandled */
}
- if (!strcmp(ce->ce_vardata, "quit"))
+ if (!strcmp(ce->value, "quit"))
{
config_error("%s:%i: badword quit has been removed. We just use the bad words from "
"badword channel { } instead.",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
return 0; /* pretend unhandled.. ok not just pretend.. ;) */
}
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
if (config_is_blankorempty(cep, "badword"))
{
errors++;
continue;
}
- if (!strcmp(cep->ce_varname, "word"))
+ if (!strcmp(cep->name, "word"))
{
- char *errbuf;
+ const char *errbuf;
if (has_word)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "badword::word");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "badword::word");
continue;
}
has_word = 1;
- if ((errbuf = badword_config_check_regex(cep->ce_vardata,1,1)))
+ if ((errbuf = badword_config_check_regex(cep->value,1,1)))
{
config_error("%s:%i: badword::%s contains an invalid regex: %s",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum,
- cep->ce_varname, errbuf);
+ cep->file->filename,
+ cep->line_number,
+ cep->name, errbuf);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "replace"))
+ else if (!strcmp(cep->name, "replace"))
{
if (has_replace)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "badword::replace");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "badword::replace");
continue;
}
has_replace = 1;
}
- else if (!strcmp(cep->ce_varname, "action"))
+ else if (!strcmp(cep->name, "action"))
{
if (has_action)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "badword::action");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "badword::action");
continue;
}
has_action = 1;
- if (!strcmp(cep->ce_vardata, "replace"))
+ if (!strcmp(cep->value, "replace"))
action = 'r';
- else if (!strcmp(cep->ce_vardata, "block"))
+ else if (!strcmp(cep->value, "block"))
action = 'b';
else
{
config_error("%s:%d: Unknown badword::action '%s'",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- cep->ce_vardata);
+ cep->file->filename, cep->line_number,
+ cep->value);
errors++;
}
}
else
{
- config_error_unknown(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- "badword", cep->ce_varname);
+ config_error_unknown(cep->file->filename, cep->line_number,
+ "badword", cep->name);
errors++;
}
}
if (!has_word)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"badword::word");
errors++;
}
@@ -189,7 +189,7 @@ int censor_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
if (has_replace && action == 'b')
{
config_error("%s:%i: badword::action is block but badword::replace exists",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
}
}
@@ -207,39 +207,39 @@ int censor_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
if (type != CONFIG_MAIN)
return 0;
- if (!ce || !ce->ce_varname || strcmp(ce->ce_varname, "badword"))
+ if (!ce || !ce->name || strcmp(ce->name, "badword"))
return 0; /* not interested */
- if (strcmp(ce->ce_vardata, "channel") && strcmp(ce->ce_vardata, "all"))
+ if (strcmp(ce->value, "channel") && strcmp(ce->value, "all"))
return 0; /* not for us */
ca = safe_alloc(sizeof(ConfigItem_badword));
ca->action = BADWORD_REPLACE;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "action"))
+ if (!strcmp(cep->name, "action"))
{
- if (!strcmp(cep->ce_vardata, "block"))
+ if (!strcmp(cep->value, "block"))
{
ca->action = BADWORD_BLOCK;
}
}
- else if (!strcmp(cep->ce_varname, "replace"))
+ else if (!strcmp(cep->name, "replace"))
{
- safe_strdup(ca->replace, cep->ce_vardata);
+ safe_strdup(ca->replace, cep->value);
} else
- if (!strcmp(cep->ce_varname, "word"))
+ if (!strcmp(cep->name, "word"))
{
word = cep;
}
}
- badword_config_process(ca, word->ce_vardata);
+ badword_config_process(ca, word->value);
- if (!strcmp(ce->ce_vardata, "channel"))
+ if (!strcmp(ce->value, "channel"))
AddListItem(ca, conf_badword_channel);
- else if (!strcmp(ce->ce_vardata, "all"))
+ else if (!strcmp(ce->value, "all"))
{
AddListItem(ca, conf_badword_channel);
return 0; /* pretend we didn't see it, so other modules can handle 'all' as well */
@@ -248,12 +248,12 @@ int censor_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
return 1;
}
-char *stripbadwords_channel(char *str, int *blocked)
+const char *stripbadwords_channel(const char *str, int *blocked)
{
return stripbadwords(str, conf_badword_channel, blocked);
}
-int censor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
+int censor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype)
{
int blocked;
Hook *h;
@@ -281,7 +281,7 @@ int censor_can_send_to_channel(Client *client, Channel *channel, Membership *lp,
return HOOK_CONTINUE;
}
-char *censor_pre_local_part(Client *client, Channel *channel, char *text)
+const char *censor_pre_local_part(Client *client, Channel *channel, const char *text)
{
int blocked;
@@ -306,7 +306,7 @@ static int IsAnyChannelCensored(Client *client)
return 0;
}
-char *censor_pre_local_quit(Client *client, char *text)
+const char *censor_pre_local_quit(Client *client, const char *text)
{
int blocked = 0;
@@ -319,7 +319,7 @@ char *censor_pre_local_quit(Client *client, char *text)
return blocked ? NULL : text;
}
-int censor_stats_badwords_channel(Client *client, char *para)
+int censor_stats_badwords_channel(Client *client, const char *para)
{
ConfigItem_badword *words;
diff --git a/src/modules/chanmodes/chanadmin.c b/src/modules/chanmodes/chanadmin.c
new file mode 100644
index 0000000..358557d
--- /dev/null
+++ b/src/modules/chanmodes/chanadmin.c
@@ -0,0 +1,88 @@
+/*
+ * Channel Mode +a
+ * (C) Copyright 2021 Syzop and the UnrealIRCd team
+ *
+ * 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.
+ */
+
+#include "unrealircd.h"
+
+ModuleHeader MOD_HEADER
+ = {
+ "chanmodes/chanadmin",
+ "6.0",
+ "Channel Mode +a",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+ };
+
+/* Forward declarations */
+int cmode_chanadmin_is_ok(Client *client, Channel *channel, char mode, const char *para, int type, int what);
+
+MOD_INIT()
+{
+ CmodeInfo creq;
+ ModDataInfo mreq;
+
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ memset(&creq, 0, sizeof(creq));
+ creq.paracount = 1;
+ creq.is_ok = cmode_chanadmin_is_ok;
+ creq.letter = 'a';
+ creq.prefix = '&';
+ creq.sjoin_prefix = '~'; /* yeah i know, totally not confusing! */
+ creq.rank = RANK_CHANADMIN;
+ creq.unset_with_param = 1;
+ creq.type = CMODE_MEMBER;
+ CmodeAdd(modinfo->handle, creq, NULL);
+
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ return MOD_SUCCESS;
+}
+
+int cmode_chanadmin_is_ok(Client *client, Channel *channel, char mode, const char *param, int type, int what)
+{
+ if ((type == EXCHK_ACCESS) || (type == EXCHK_ACCESS_ERR))
+ {
+ Client *target = find_user(param, NULL);
+
+ if ((what == MODE_DEL) && (client == target))
+ {
+ /* User may always remove their own modes */
+ return EX_ALLOW;
+ }
+ if (check_channel_access(client, channel, "q"))
+ {
+ /* only +q people may do +a/-a */
+ return EX_ALLOW;
+ }
+ if (type == EXCHK_ACCESS_ERR)
+ sendnumeric(client, ERR_CHANOWNPRIVNEEDED, channel->name);
+ return EX_DENY;
+ }
+
+ /* fallthrough -- should not be used */
+ return EX_DENY;
+}
diff --git a/src/modules/chanmodes/chanop.c b/src/modules/chanmodes/chanop.c
new file mode 100644
index 0000000..3a08f32
--- /dev/null
+++ b/src/modules/chanmodes/chanop.c
@@ -0,0 +1,78 @@
+/*
+ * Channel Mode +o
+ * (C) Copyright 2021 Syzop and the UnrealIRCd team
+ *
+ * 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.
+ */
+
+#include "unrealircd.h"
+
+ModuleHeader MOD_HEADER
+ = {
+ "chanmodes/chanop",
+ "6.0",
+ "Channel Mode +o",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+ };
+
+/* Forward declarations */
+int cmode_chanop_is_ok(Client *client, Channel *channel, char mode, const char *para, int type, int what);
+
+MOD_INIT()
+{
+ CmodeInfo creq;
+ ModDataInfo mreq;
+
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ memset(&creq, 0, sizeof(creq));
+ creq.paracount = 1;
+ creq.is_ok = cmode_chanop_is_ok;
+ creq.letter = 'o';
+ creq.prefix = '@';
+ creq.sjoin_prefix = '@';
+ creq.rank = RANK_CHANOP;
+ creq.unset_with_param = 1;
+ creq.type = CMODE_MEMBER;
+ CmodeAdd(modinfo->handle, creq, NULL);
+
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ return MOD_SUCCESS;
+}
+
+int cmode_chanop_is_ok(Client *client, Channel *channel, char mode, const char *param, int type, int what)
+{
+ if ((type == EXCHK_ACCESS) || (type == EXCHK_ACCESS_ERR))
+ {
+ if (check_channel_access(client, channel, "oaq"))
+ return EX_ALLOW;
+ if (type == EXCHK_ACCESS_ERR)
+ sendnumeric(client, ERR_CHANOPRIVSNEEDED, channel->name);
+ return EX_DENY;
+ }
+
+ /* fallthrough -- should not be used */
+ return EX_DENY;
+}
diff --git a/src/modules/chanmodes/chanowner.c b/src/modules/chanmodes/chanowner.c
new file mode 100644
index 0000000..f449d99
--- /dev/null
+++ b/src/modules/chanmodes/chanowner.c
@@ -0,0 +1,88 @@
+/*
+ * Channel Mode +q
+ * (C) Copyright 2021 Syzop and the UnrealIRCd team
+ *
+ * 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.
+ */
+
+#include "unrealircd.h"
+
+ModuleHeader MOD_HEADER
+ = {
+ "chanmodes/chanowner",
+ "6.0",
+ "Channel Mode +q",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+ };
+
+/* Forward declarations */
+int cmode_chanowner_is_ok(Client *client, Channel *channel, char mode, const char *para, int type, int what);
+
+MOD_INIT()
+{
+ CmodeInfo creq;
+ ModDataInfo mreq;
+
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ memset(&creq, 0, sizeof(creq));
+ creq.paracount = 1;
+ creq.is_ok = cmode_chanowner_is_ok;
+ creq.letter = 'q';
+ creq.prefix = '~';
+ creq.sjoin_prefix = '*';
+ creq.rank = RANK_CHANOWNER;
+ creq.unset_with_param = 1;
+ creq.type = CMODE_MEMBER;
+ CmodeAdd(modinfo->handle, creq, NULL);
+
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ return MOD_SUCCESS;
+}
+
+int cmode_chanowner_is_ok(Client *client, Channel *channel, char mode, const char *param, int type, int what)
+{
+ if ((type == EXCHK_ACCESS) || (type == EXCHK_ACCESS_ERR))
+ {
+ Client *target = find_user(param, NULL);
+
+ if ((what == MODE_DEL) && (client == target))
+ {
+ /* User may always remove their own modes */
+ return EX_ALLOW;
+ }
+ if (check_channel_access(client, channel, "q"))
+ {
+ /* only +q people may do +q/-q */
+ return EX_ALLOW;
+ }
+ if (type == EXCHK_ACCESS_ERR)
+ sendnumeric(client, ERR_CHANOWNPRIVNEEDED, channel->name);
+ return EX_DENY;
+ }
+
+ /* fallthrough -- should not be used */
+ return EX_DENY;
+}
diff --git a/src/modules/chanmodes/delayjoin.c b/src/modules/chanmodes/delayjoin.c
index 0eedb31..95fc07b 100644
--- a/src/modules/chanmodes/delayjoin.c
+++ b/src/modules/chanmodes/delayjoin.c
@@ -11,7 +11,7 @@ ModuleHeader MOD_HEADER
"5.0", /* Version */
"delayed join (+D,+d)", /* Short description of module */
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
#define MOD_DATA_STR "delayjoin"
@@ -26,13 +26,14 @@ static Cmode_t EXTMODE_POST_DELAYED;
int visible_in_channel(Client *client, Channel *channel);
int moded_check_part(Client *client, Channel *channel);
int moded_join(Client *client, Channel *channel);
-int moded_part(Client *client, Channel *channel, MessageTag *mtags, char *comment);
-int deny_all(Client *client, Channel *channel, char mode, char *para, int checkt, int what);
+int moded_part(Client *client, Channel *channel, MessageTag *mtags, const char *comment);
+int moded_quit(Client *client, MessageTag *mtags, const char *comment);
+int delayjoin_is_ok(Client *client, Channel *channel, char mode, const char *para, int checkt, int what);
int moded_chanmode(Client *client, Channel *channel,
- MessageTag *mtags, char *modebuf, char *parabuf, time_t sendts, int samode);
-int moded_prechanmsg(Client *client, Channel *channel, MessageTag *mtags, char *text, SendType sendtype);
-char *moded_serialize(ModData *m);
-void moded_unserialize(char *str, ModData *m);
+ MessageTag *mtags, const char *modebuf, const char *parabuf, time_t sendts, int samode);
+int moded_prechanmsg(Client *client, Channel *channel, MessageTag *mtags, const char *text, SendType sendtype);
+const char *moded_serialize(ModData *m);
+void moded_unserialize(const char *str, ModData *m);
MOD_INIT()
{
@@ -45,13 +46,14 @@ MOD_INIT()
memset(&req, 0, sizeof(req));
req.paracount = 0;
req.is_ok = extcmode_default_requirechop;
- req.flag = 'D';
+ req.letter = 'D';
CmodeDelayed = CmodeAdd(modinfo->handle, req, &EXTMODE_DELAYED);
memset(&req, 0, sizeof(req));
req.paracount = 0;
- req.is_ok = deny_all;
- req.flag = 'd';
+ req.is_ok = delayjoin_is_ok;
+ req.letter = 'd';
+ req.local = 1;
CmodePostDelayed = CmodeAdd(modinfo->handle, req, &EXTMODE_POST_DELAYED);
memset(&mreq, 0, sizeof(mreq));
@@ -76,6 +78,8 @@ MOD_INIT()
HookAdd(modinfo->handle, HOOKTYPE_JOIN_DATA, 0, moded_join);
HookAdd(modinfo->handle, HOOKTYPE_LOCAL_PART, 0, moded_part);
HookAdd(modinfo->handle, HOOKTYPE_REMOTE_PART, 0, moded_part);
+ HookAdd(modinfo->handle, HOOKTYPE_LOCAL_QUIT, 0, moded_quit);
+ HookAdd(modinfo->handle, HOOKTYPE_REMOTE_QUIT, 0, moded_quit);
HookAdd(modinfo->handle, HOOKTYPE_PRE_LOCAL_CHANMODE, 0, moded_chanmode);
HookAdd(modinfo->handle, HOOKTYPE_PRE_REMOTE_CHANMODE, 0, moded_chanmode);
HookAdd(modinfo->handle, HOOKTYPE_PRE_CHANMSG, 0, moded_prechanmsg);
@@ -97,10 +101,10 @@ void set_post_delayed(Channel *channel)
{
MessageTag *mtags = NULL;
- channel->mode.extmode |= EXTMODE_POST_DELAYED;
+ channel->mode.mode |= EXTMODE_POST_DELAYED;
new_message(&me, NULL, &mtags);
- sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags, ":%s MODE %s +d", me.name, channel->chname);
+ sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags, ":%s MODE %s +d", me.name, channel->name);
free_message_tags(mtags);
}
@@ -108,10 +112,10 @@ void clear_post_delayed(Channel *channel)
{
MessageTag *mtags = NULL;
- channel->mode.extmode &= ~EXTMODE_POST_DELAYED;
+ channel->mode.mode &= ~EXTMODE_POST_DELAYED;
new_message(&me, NULL, &mtags);
- sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags, ":%s MODE %s -d", me.name, channel->chname);
+ sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags, ":%s MODE %s -d", me.name, channel->name);
free_message_tags(mtags);
}
@@ -153,14 +157,14 @@ bool channel_has_invisible_users(Channel *channel)
bool channel_is_post_delayed(Channel *channel)
{
- if (channel->mode.extmode & EXTMODE_POST_DELAYED)
+ if (channel->mode.mode & EXTMODE_POST_DELAYED)
return true;
return false;
}
bool channel_is_delayed(Channel *channel)
{
- if (channel->mode.extmode & EXTMODE_DELAYED)
+ if (channel->mode.mode & EXTMODE_DELAYED)
return true;
return false;
}
@@ -196,7 +200,7 @@ void clear_user_invisible(Channel *channel, Client *client)
}
}
- if (should_clear && (channel->mode.extmode & EXTMODE_POST_DELAYED))
+ if (should_clear && (channel->mode.mode & EXTMODE_POST_DELAYED))
{
clear_post_delayed(channel);
}
@@ -213,18 +217,18 @@ void clear_user_invisible_announce(Channel *channel, Client *client, MessageTag
clear_user_invisible(channel, client);
ircsnprintf(joinbuf, sizeof(joinbuf), ":%s!%s@%s JOIN %s",
- client->name, client->user->username, GetHost(client), channel->chname);
+ client->name, client->user->username, GetHost(client), channel->name);
ircsnprintf(exjoinbuf, sizeof(exjoinbuf), ":%s!%s@%s JOIN %s %s :%s",
- client->name, client->user->username, GetHost(client), channel->chname,
- !isdigit(*client->user->svid) ? client->user->svid : "*",
+ client->name, client->user->username, GetHost(client), channel->name,
+ IsLoggedIn(client) ? client->user->account : "*",
client->info);
- new_message_special(client, recv_mtags, &mtags, ":%s JOIN %s", client->name, channel->chname);
+ new_message_special(client, recv_mtags, &mtags, ":%s JOIN %s", client->name, channel->name);
for (i = channel->members; i; i = i->next)
{
Client *acptr = i->client;
- if (!is_skochanop(acptr, channel) && acptr != client && MyConnect(acptr))
+ if (!check_channel_access(acptr, channel, "hoaq") && acptr != client && MyConnect(acptr))
{
if (HasCapabilityFast(acptr, CAP_EXTENDED_JOIN))
sendto_one(acptr, mtags, "%s", exjoinbuf);
@@ -252,7 +256,7 @@ void set_user_invisible(Channel *channel, Client *client)
}
-int deny_all(Client *client, Channel *channel, char mode, char *para, int checkt, int what)
+int delayjoin_is_ok(Client *client, Channel *channel, char mode, const char *para, int checkt, int what)
{
return EX_ALWAYS_DENY;
}
@@ -272,7 +276,7 @@ int moded_join(Client *client, Channel *channel)
return 0;
}
-int moded_part(Client *client, Channel *channel, MessageTag *mtags, char *comment)
+int moded_part(Client *client, Channel *channel, MessageTag *mtags, const char *comment)
{
if (channel_is_delayed(channel) || channel_is_post_delayed(channel))
clear_user_invisible(channel, client);
@@ -280,7 +284,23 @@ int moded_part(Client *client, Channel *channel, MessageTag *mtags, char *commen
return 0;
}
-int moded_chanmode(Client *client, Channel *channel, MessageTag *recv_mtags, char *modebuf, char *parabuf, time_t sendts, int samode)
+int moded_quit(Client *client, MessageTag *mtags, const char *comment)
+{
+ Membership *membership;
+ Channel *channel;
+
+ for (membership = client->user->channel; membership; membership=membership->next)
+ {
+ channel = membership->channel;
+ /* Identical to moded_part() */
+ if (channel_is_delayed(channel) || channel_is_post_delayed(channel))
+ clear_user_invisible(channel, client);
+ }
+
+ return 0;
+}
+
+int moded_chanmode(Client *client, Channel *channel, MessageTag *recv_mtags, const char *modebuf, const char *parabuf, time_t sendts, int samode)
{
long CAP_EXTENDED_JOIN = ClientCapabilityBit("extended-join");
@@ -317,16 +337,16 @@ int moded_chanmode(Client *client, Channel *channel, MessageTag *recv_mtags, cha
if (moded_user_invisible(i->client, channel))
{
MessageTag *mtags = NULL;
- new_message_special(i->client, recv_mtags, &mtags, ":%s JOIN %s", i->client->name, channel->chname);
+ new_message_special(i->client, recv_mtags, &mtags, ":%s JOIN %s", i->client->name, channel->name);
if (HasCapabilityFast(user, CAP_EXTENDED_JOIN))
{
sendto_one(user, mtags, ":%s!%s@%s JOIN %s %s :%s",
i->client->name, i->client->user->username, GetHost(i->client),
- channel->chname,
- !isdigit(*i->client->user->svid) ? i->client->user->svid : "*",
+ channel->name,
+ IsLoggedIn(i->client) ? i->client->user->account : "*",
i->client->info);
} else {
- sendto_one(user, mtags, ":%s!%s@%s JOIN :%s", i->client->name, i->client->user->username, GetHost(i->client), channel->chname);
+ sendto_one(user, mtags, ":%s!%s@%s JOIN :%s", i->client->name, i->client->user->username, GetHost(i->client), channel->name);
}
free_message_tags(mtags);
}
@@ -354,8 +374,8 @@ int moded_chanmode(Client *client, Channel *channel, MessageTag *recv_mtags, cha
if (moded_user_invisible(i->client, channel))
{
MessageTag *mtags = NULL;
- new_message_special(i->client, recv_mtags, &mtags, ":%s PART %s", i->client->name, channel->chname);
- sendto_one(user, mtags, ":%s!%s@%s PART :%s", i->client->name, i->client->user->username, GetHost(i->client), channel->chname);
+ new_message_special(i->client, recv_mtags, &mtags, ":%s PART %s", i->client->name, channel->name);
+ sendto_one(user, mtags, ":%s!%s@%s PART :%s", i->client->name, i->client->user->username, GetHost(i->client), channel->name);
free_message_tags(mtags);
}
}
@@ -367,7 +387,7 @@ int moded_chanmode(Client *client, Channel *channel, MessageTag *recv_mtags, cha
return 0;
}
-int moded_prechanmsg(Client *client, Channel *channel, MessageTag *mtags, char *text, SendType sendtype)
+int moded_prechanmsg(Client *client, Channel *channel, MessageTag *mtags, const char *text, SendType sendtype)
{
if ((channel_is_delayed(channel) || channel_is_post_delayed(channel)) && (moded_user_invisible(client, channel)))
clear_user_invisible_announce(channel, client, mtags);
@@ -375,12 +395,12 @@ int moded_prechanmsg(Client *client, Channel *channel, MessageTag *mtags, char *
return 0;
}
-char *moded_serialize(ModData *m)
+const char *moded_serialize(ModData *m)
{
return m->i ? "1" : "0";
}
-void moded_unserialize(char *str, ModData *m)
+void moded_unserialize(const char *str, ModData *m)
{
m->i = atoi(str);
}
diff --git a/src/modules/chanmodes/floodprot.c b/src/modules/chanmodes/floodprot.c
index a3aa3ef..148a652 100644
--- a/src/modules/chanmodes/floodprot.c
+++ b/src/modules/chanmodes/floodprot.c
@@ -25,17 +25,18 @@ ModuleHeader MOD_HEADER
"5.0",
"Channel Mode +f",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
-#define CHFLD_CTCP 0 /* c */
-#define CHFLD_JOIN 1 /* j */
-#define CHFLD_KNOCK 2 /* k */
-#define CHFLD_MSG 3 /* m */
-#define CHFLD_NICK 4 /* n */
-#define CHFLD_TEXT 5 /* t */
-#define CHFLD_REPEAT 6 /* r */
-
+typedef enum Flood {
+ CHFLD_CTCP = 0,
+ CHFLD_JOIN = 1,
+ CHFLD_KNOCK = 2,
+ CHFLD_MSG = 3,
+ CHFLD_NICK = 4,
+ CHFLD_TEXT = 5,
+ CHFLD_REPEAT = 6,
+} Flood;
#define NUMFLD 7 /* 7 flood types */
/** Configuration settings */
@@ -47,7 +48,7 @@ struct {
typedef struct FloodType {
char letter;
- int index;
+ Flood index;
char *description;
char default_action;
char *actions;
@@ -61,7 +62,7 @@ FloodType floodtypes[] = {
{ 'c', CHFLD_CTCP, "CTCPflood", 'C', "mM", 0, },
{ 'j', CHFLD_JOIN, "joinflood", 'i', "R", 0, },
{ 'k', CHFLD_KNOCK, "knockflood", 'K', "", 0, },
- { 'm', CHFLD_MSG, "msg/noticeflood", 'm', "M", 0, },
+ { 'm', CHFLD_MSG, "msg/noticeflood", 'm', "M", 0, },
{ 'n', CHFLD_NICK, "nickflood", 'N', "", 0, },
{ 't', CHFLD_TEXT, "msg/noticeflood", '\0', "bd", 1, },
{ 'r', CHFLD_REPEAT, "repeating", '\0', "bd", 1, },
@@ -113,7 +114,7 @@ static int timedban_available = 0; /**< Set to 1 if extbans/timedban module is l
RemoveChannelModeTimer *removechannelmodetimer_list = NULL;
char *floodprot_msghash_key = NULL;
-#define IsFloodLimit(x) ((x)->mode.extmode & EXTMODE_FLOODLIMIT)
+#define IsFloodLimit(x) ((x)->mode.mode & EXTMODE_FLOODLIMIT)
/* Forward declarations */
static void init_config(void);
@@ -128,24 +129,24 @@ static int do_floodprot(Channel *channel, Client *client, int what);
char *channel_modef_string(ChannelFloodProtection *x, char *str);
void do_floodprot_action(Channel *channel, int what);
void floodprottimer_add(Channel *channel, char mflag, time_t when);
-uint64_t gen_floodprot_msghash(char *text);
-int cmodef_is_ok(Client *client, Channel *channel, char mode, char *para, int type, int what);
-void *cmodef_put_param(void *r_in, char *param);
-char *cmodef_get_param(void *r_in);
-char *cmodef_conv_param(char *param_in, Client *client, Channel *channel);
+uint64_t gen_floodprot_msghash(const char *text);
+int cmodef_is_ok(Client *client, Channel *channel, char mode, const char *para, int type, int what);
+void *cmodef_put_param(void *r_in, const char *param);
+const char *cmodef_get_param(void *r_in);
+const char *cmodef_conv_param(const char *param_in, Client *client, Channel *channel);
void cmodef_free_param(void *r);
void *cmodef_dup_struct(void *r_in);
int cmodef_sjoin_check(Channel *channel, void *ourx, void *theirx);
-int floodprot_join(Client *client, Channel *channel, MessageTag *mtags, char *parv[]);
+int floodprot_join(Client *client, Channel *channel, MessageTag *mtags);
EVENT(modef_event);
int cmodef_channel_destroy(Channel *channel, int *should_destroy);
-int floodprot_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
-int floodprot_post_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, SendType sendtype);
-int floodprot_knock(Client *client, Channel *channel, MessageTag *mtags, char *comment);
-int floodprot_nickchange(Client *client, MessageTag *mtags, char *oldnick);
+int floodprot_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype);
+int floodprot_post_chanmsg(Client *client, Channel *channel, int sendflags, const char *prefix, const char *target, MessageTag *mtags, const char *text, SendType sendtype);
+int floodprot_knock(Client *client, Channel *channel, MessageTag *mtags, const char *comment);
+int floodprot_nickchange(Client *client, MessageTag *mtags, const char *oldnick);
int floodprot_chanmode_del(Channel *channel, int m);
void memberflood_free(ModData *md);
-int floodprot_stats(Client *client, char *flag);
+int floodprot_stats(Client *client, const char *flag);
void floodprot_free_removechannelmodetimer_list(ModData *m);
void floodprot_free_msghash_key(ModData *m);
@@ -165,7 +166,7 @@ MOD_INIT()
memset(&creq, 0, sizeof(creq));
creq.paracount = 1;
creq.is_ok = cmodef_is_ok;
- creq.flag = 'f';
+ creq.letter = 'f';
creq.unset_with_param = 1; /* ah yeah, +f is special! */
creq.put_param = cmodef_put_param;
creq.get_param = cmodef_get_param;
@@ -244,53 +245,53 @@ int floodprot_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
if (type != CONFIG_SET)
return 0;
- if (!strcmp(ce->ce_varname, "modef-default-unsettime"))
+ if (!strcmp(ce->name, "modef-default-unsettime"))
{
- if (!ce->ce_vardata)
+ if (!ce->value)
{
- config_error_empty(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- "set", ce->ce_varname);
+ config_error_empty(ce->file->filename, ce->line_number,
+ "set", ce->name);
errors++;
} else {
- int v = atoi(ce->ce_vardata);
+ int v = atoi(ce->value);
if ((v <= 0) || (v > 255))
{
config_error("%s:%i: set::modef-default-unsettime: value '%d' out of range (should be 1-255)",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum, v);
+ ce->file->filename, ce->line_number, v);
errors++;
}
}
} else
- if (!strcmp(ce->ce_varname, "modef-max-unsettime"))
+ if (!strcmp(ce->name, "modef-max-unsettime"))
{
- if (!ce->ce_vardata)
+ if (!ce->value)
{
- config_error_empty(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- "set", ce->ce_varname);
+ config_error_empty(ce->file->filename, ce->line_number,
+ "set", ce->name);
errors++;
} else {
- int v = atoi(ce->ce_vardata);
+ int v = atoi(ce->value);
if ((v <= 0) || (v > 255))
{
config_error("%s:%i: set::modef-max-unsettime: value '%d' out of range (should be 1-255)",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum, v);
+ ce->file->filename, ce->line_number, v);
errors++;
}
}
} else
- if (!strcmp(ce->ce_varname, "modef-boot-delay"))
+ if (!strcmp(ce->name, "modef-boot-delay"))
{
- if (!ce->ce_vardata)
+ if (!ce->value)
{
- config_error_empty(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
- "set", ce->ce_varname);
+ config_error_empty(ce->file->filename, ce->line_number,
+ "set", ce->name);
errors++;
} else {
- long v = config_checkval(ce->ce_vardata, CFG_TIME);
+ long v = config_checkval(ce->value, CFG_TIME);
if ((v < 0) || (v > 600))
{
config_error("%s:%i: set::modef-boot-delay: value '%ld' out of range (should be 0-600)",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum, v);
+ ce->file->filename, ce->line_number, v);
errors++;
}
}
@@ -309,12 +310,12 @@ int floodprot_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
if (type != CONFIG_SET)
return 0;
- if (!strcmp(ce->ce_varname, "modef-default-unsettime"))
- cfg.modef_default_unsettime = (unsigned char)atoi(ce->ce_vardata);
- else if (!strcmp(ce->ce_varname, "modef-max-unsettime"))
- cfg.modef_max_unsettime = (unsigned char)atoi(ce->ce_vardata);
- else if (!strcmp(ce->ce_varname, "modef-boot-delay"))
- cfg.modef_boot_delay = config_checkval(ce->ce_vardata, CFG_TIME);
+ if (!strcmp(ce->name, "modef-default-unsettime"))
+ cfg.modef_default_unsettime = (unsigned char)atoi(ce->value);
+ else if (!strcmp(ce->name, "modef-max-unsettime"))
+ cfg.modef_max_unsettime = (unsigned char)atoi(ce->value);
+ else if (!strcmp(ce->name, "modef-boot-delay"))
+ cfg.modef_boot_delay = config_checkval(ce->value, CFG_TIME);
else
return 0; /* not handled by us */
@@ -331,7 +332,7 @@ FloodType *find_floodprot_by_letter(char c)
return NULL;
}
-FloodType *find_floodprot_by_index(int index)
+FloodType *find_floodprot_by_index(Flood index)
{
int i;
for (i=0; i < ARRAY_SIZEOF(floodtypes); i++)
@@ -341,11 +342,11 @@ FloodType *find_floodprot_by_index(int index)
return NULL;
}
-int cmodef_is_ok(Client *client, Channel *channel, char mode, char *param, int type, int what)
+int cmodef_is_ok(Client *client, Channel *channel, char mode, const char *param, int type, int what)
{
if ((type == EXCHK_ACCESS) || (type == EXCHK_ACCESS_ERR))
{
- if (IsUser(client) && is_chan_op(client, channel))
+ if (IsUser(client) && check_channel_access(client, channel, "oaq"))
return EX_ALLOW;
if (type == EXCHK_ACCESS_ERR) /* can only be due to being halfop */
sendnumeric(client, ERR_NOTFORHALFOPS, 'f');
@@ -359,7 +360,7 @@ int cmodef_is_ok(Client *client, Channel *channel, char mode, char *param, int t
unsigned short warnings = 0, breakit;
unsigned char r;
FloodType *floodtype;
- int index;
+ Flood index;
memset(&newf, 0, sizeof(newf));
@@ -467,7 +468,7 @@ invalidsyntax:
return EX_DENY;
}
-void *cmodef_put_param(void *fld_in, char *param)
+void *cmodef_put_param(void *fld_in, const char *param)
{
ChannelFloodProtection *fld = (ChannelFloodProtection *)fld_in;
char xbuf[256], c, a, *p, *p2, *x = xbuf+1;
@@ -475,7 +476,7 @@ void *cmodef_put_param(void *fld_in, char *param)
unsigned short breakit;
unsigned char r;
FloodType *floodtype;
- int index;
+ Flood index;
strlcpy(xbuf, param, sizeof(xbuf));
@@ -581,7 +582,7 @@ fail_cmodef_put_param:
return fld; /* FAIL */
}
-char *cmodef_get_param(void *r_in)
+const char *cmodef_get_param(void *r_in)
{
ChannelFloodProtection *r = (ChannelFloodProtection *)r_in;
static char retbuf[512];
@@ -596,7 +597,7 @@ char *cmodef_get_param(void *r_in)
/** Convert parameter to something proper.
* NOTE: client may be NULL if called for e.g. set::modes-on-join
*/
-char *cmodef_conv_param(char *param_in, Client *client, Channel *channel)
+const char *cmodef_conv_param(const char *param_in, Client *client, Channel *channel)
{
static char retbuf[256];
char param[256];
@@ -607,7 +608,7 @@ char *cmodef_conv_param(char *param_in, Client *client, Channel *channel)
unsigned short breakit;
unsigned char r;
FloodType *floodtype;
- int index;
+ Flood index;
memset(&newf, 0, sizeof(newf));
@@ -736,7 +737,7 @@ int cmodef_sjoin_check(Channel *channel, void *ourx, void *theirx)
return EXSJ_MERGE;
}
-int floodprot_join(Client *client, Channel *channel, MessageTag *mtags, char *parv[])
+int floodprot_join(Client *client, Channel *channel, MessageTag *mtags)
{
/* I'll explain this only once:
* 1. if channel is +f
@@ -749,8 +750,8 @@ int floodprot_join(Client *client, Channel *channel, MessageTag *mtags, char *pa
* from all servers.
*/
if (IsFloodLimit(channel) &&
- (MyUser(client) || client->srvptr->serv->flags.synced) &&
- (client->srvptr->serv->boottime && (TStime() - client->srvptr->serv->boottime >= MODEF_BOOT_DELAY)) &&
+ (MyUser(client) || client->uplink->server->flags.synced) &&
+ (client->uplink->server->boottime && (TStime() - client->uplink->server->boottime >= MODEF_BOOT_DELAY)) &&
!IsULine(client))
{
do_floodprot(channel, client, CHFLD_JOIN);
@@ -818,7 +819,7 @@ char *channel_modef_string(ChannelFloodProtection *x, char *retbuf)
return retbuf;
}
-int floodprot_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
+int floodprot_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype)
{
Membership *mb;
ChannelFloodProtection *chp;
@@ -834,7 +835,7 @@ int floodprot_can_send_to_channel(Client *client, Channel *channel, Membership *
if (sendtype == SEND_TYPE_TAGMSG)
return 0; // TODO: some TAGMSG specific limit? (1 of 2)
- if (ValidatePermissionsForPath("channel:override:flood",client,NULL,channel,NULL) || !IsFloodLimit(channel) || is_skochanop(client, channel))
+ if (ValidatePermissionsForPath("channel:override:flood",client,NULL,channel,NULL) || !IsFloodLimit(channel) || check_channel_access(client, channel, "hoaq"))
return HOOK_CONTINUE;
if (!(mb = find_membership_link(client->user->channel, channel)))
@@ -921,16 +922,21 @@ int floodprot_can_send_to_channel(Client *client, Channel *channel, Membership *
{
/* Ban the user */
if (timedban_available && (chp->remove_after[flood_type] > 0))
- snprintf(mask, sizeof(mask), "~t:%d:*!*@%s", chp->remove_after[flood_type], GetHost(client));
- else
+ {
+ if (iConf.named_extended_bans)
+ snprintf(mask, sizeof(mask), "~time:%d:*!*@%s", chp->remove_after[flood_type], GetHost(client));
+ else
+ snprintf(mask, sizeof(mask), "~t:%d:*!*@%s", chp->remove_after[flood_type], GetHost(client));
+ } else {
snprintf(mask, sizeof(mask), "*!*@%s", GetHost(client));
+ }
if (add_listmode(&channel->banlist, &me, channel, mask) == 0)
{
mtags = NULL;
new_message(&me, NULL, &mtags);
- sendto_server(NULL, 0, 0, mtags, ":%s MODE %s +b %s 0", me.id, channel->chname, mask);
+ sendto_server(NULL, 0, 0, mtags, ":%s MODE %s +b %s 0", me.id, channel->name, mask);
sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags,
- ":%s MODE %s +b %s", me.name, channel->chname, mask);
+ ":%s MODE %s +b %s", me.name, channel->name, mask);
free_message_tags(mtags);
} /* else.. ban list is full */
}
@@ -942,9 +948,9 @@ int floodprot_can_send_to_channel(Client *client, Channel *channel, Membership *
return HOOK_CONTINUE;
}
-int floodprot_post_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, SendType sendtype)
+int floodprot_post_chanmsg(Client *client, Channel *channel, int sendflags, const char *prefix, const char *target, MessageTag *mtags, const char *text, SendType sendtype)
{
- if (!IsFloodLimit(channel) || is_skochanop(client, channel) || IsULine(client))
+ if (!IsFloodLimit(channel) || check_channel_access(client, channel, "hoaq") || IsULine(client))
return 0;
if (sendtype == SEND_TYPE_TAGMSG)
@@ -960,14 +966,14 @@ int floodprot_post_chanmsg(Client *client, Channel *channel, int sendflags, int
return 0;
}
-int floodprot_knock(Client *client, Channel *channel, MessageTag *mtags, char *comment)
+int floodprot_knock(Client *client, Channel *channel, MessageTag *mtags, const char *comment)
{
if (IsFloodLimit(channel) && !IsULine(client))
do_floodprot(channel, client, CHFLD_KNOCK);
return 0;
}
-int floodprot_nickchange(Client *client, MessageTag *mtags, char *oldnick)
+int floodprot_nickchange(Client *client, MessageTag *mtags, const char *oldnick)
{
Membership *mp;
@@ -977,8 +983,7 @@ int floodprot_nickchange(Client *client, MessageTag *mtags, char *oldnick)
for (mp = client->user->channel; mp; mp = mp->next)
{
Channel *channel = mp->channel;
- if (channel && IsFloodLimit(channel) &&
- !(mp->flags & (CHFL_CHANOP|CHFL_VOICE|CHFL_CHANOWNER|CHFL_HALFOP|CHFL_CHANADMIN)))
+ if (channel && IsFloodLimit(channel) && !check_channel_access_membership(mp, "vhoaq"))
{
do_floodprot(channel, client, CHFLD_NICK);
}
@@ -1080,8 +1085,10 @@ void floodprottimer_add(Channel *channel, char mflag, time_t when)
{
if (strlen(chp->timers_running)+1 >= sizeof(chp->timers_running))
{
- sendto_realops_and_log("floodprottimer_add: too many timers running for %s (%s)!!!",
- channel->chname, chp->timers_running);
+ unreal_log(ULOG_WARNING, "flood", "BUG_FLOODPROTTIMER_ADD", NULL,
+ "[BUG] floodprottimer_add: too many timers running for $channel ($timers_running)",
+ log_data_channel("channel", channel),
+ log_data_string("timers_running", chp->timers_running));
return;
}
strccat(chp->timers_running, mflag); /* bounds already checked ^^ */
@@ -1137,39 +1144,24 @@ EVENT(modef_event)
if (e->when <= now)
{
/* Remove chanmode... */
- long mode = 0;
- Cmode_t extmode = 0;
-#ifdef NEWFLDDBG
- sendto_realops("modef_event: chan %s mode -%c EXPIRED", e->channel->chname, e->m);
-#endif
- mode = get_mode_bitbychar(e->m);
- if (mode == 0)
- extmode = get_extmode_bitbychar(e->m);
+ Cmode_t extmode = get_extmode_bitbychar(e->m);
- if ((mode && (e->channel->mode.mode & mode)) ||
- (extmode && (e->channel->mode.extmode & extmode)))
+ if (extmode && (e->channel->mode.mode & extmode))
{
MessageTag *mtags = NULL;
new_message(&me, NULL, &mtags);
- sendto_server(NULL, 0, 0, mtags, ":%s MODE %s -%c 0", me.id, e->channel->chname, e->m);
+ sendto_server(NULL, 0, 0, mtags, ":%s MODE %s -%c 0", me.id, e->channel->name, e->m);
sendto_channel(e->channel, &me, NULL, 0, 0, SEND_LOCAL, mtags,
":%s MODE %s -%c",
- me.name, e->channel->chname, e->m);
+ me.name, e->channel->name, e->m);
free_message_tags(mtags);
-
- e->channel->mode.mode &= ~mode;
- e->channel->mode.extmode &= ~extmode;
+ e->channel->mode.mode &= ~extmode;
}
/* And delete... */
DelListItem(e, removechannelmodetimer_list);
safe_free(e);
- } else {
-#ifdef NEWFLDDBG
- sendto_realops("modef_event: chan %s mode -%c about %d seconds",
- e->channel->chname, e->m, e->when - now);
-#endif
}
}
}
@@ -1220,7 +1212,6 @@ int do_floodprot(Channel *channel, Client *client, int what)
void do_floodprot_action(Channel *channel, int what)
{
char m;
- int mode = 0;
Cmode_t extmode = 0;
ChannelFloodProtection *chp = (ChannelFloodProtection *)GETPARASTRUCT(channel, 'f');
FloodType *floodtype = find_floodprot_by_index(what);
@@ -1240,15 +1231,11 @@ void do_floodprot_action(Channel *channel, int what)
if (chp->action[what] == 'd')
return;
- mode = get_mode_bitbychar(m);
- if (mode == 0)
- extmode = get_extmode_bitbychar(m);
-
- if (!mode && !extmode)
+ extmode = get_extmode_bitbychar(m);
+ if (!extmode)
return;
- if (!(mode && (channel->mode.mode & mode)) &&
- !(extmode && (channel->mode.extmode & extmode)))
+ if (!(extmode && (channel->mode.mode & extmode)))
{
char comment[512], target[CHANNELLEN + 8];
MessageTag *mtags;
@@ -1258,8 +1245,8 @@ void do_floodprot_action(Channel *channel, int what)
new_message(&me, NULL, &mtags);
ircsnprintf(comment, sizeof(comment), "*** Channel %s detected (limit is %d per %d seconds), setting mode +%c",
text, chp->limit[what], chp->per, m);
- ircsnprintf(target, sizeof(target), "%%%s", channel->chname);
- sendto_channel(channel, &me, NULL, PREFIX_HALFOP|PREFIX_OP|PREFIX_ADMIN|PREFIX_OWNER,
+ ircsnprintf(target, sizeof(target), "%%%s", channel->name);
+ sendto_channel(channel, &me, NULL, "ho",
0, SEND_ALL, mtags,
":%s NOTICE %s :%s", me.name, target, comment);
free_message_tags(mtags);
@@ -1267,13 +1254,12 @@ void do_floodprot_action(Channel *channel, int what)
/* Then the MODE broadcast */
mtags = NULL;
new_message(&me, NULL, &mtags);
- sendto_server(NULL, 0, 0, mtags, ":%s MODE %s +%c 0", me.id, channel->chname, m);
- sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags, ":%s MODE %s +%c", me.name, channel->chname, m);
+ sendto_server(NULL, 0, 0, mtags, ":%s MODE %s +%c 0", me.id, channel->name, m);
+ sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags, ":%s MODE %s +%c", me.name, channel->name, m);
free_message_tags(mtags);
/* Actually set the mode internally */
- channel->mode.mode |= mode;
- channel->mode.extmode |= extmode;
+ channel->mode.mode |= extmode;
/* Add remove-chanmode timer */
if (chp->remove_after[what])
@@ -1286,7 +1272,7 @@ void do_floodprot_action(Channel *channel, int what)
}
}
-uint64_t gen_floodprot_msghash(char *text)
+uint64_t gen_floodprot_msghash(const char *text)
{
int i;
int is_ctcp, is_action;
@@ -1312,10 +1298,10 @@ uint64_t gen_floodprot_msghash(char *text)
if (is_ctcp || is_action)
{
// Remove the \001 chars around the message
- if((len = strlen(plaintext)) && plaintext[len - 1] == '\001')
+ if ((len = strlen(plaintext)) && plaintext[len - 1] == '\001')
plaintext[len - 1] = '\0';
plaintext++;
- if(is_action)
+ if (is_action)
plaintext += 7;
}
@@ -1345,7 +1331,7 @@ void memberflood_free(ModData *md)
safe_free(md->ptr);
}
-int floodprot_stats(Client *client, char *flag)
+int floodprot_stats(Client *client, const char *flag)
{
if (*flag != 'S')
return 0;
diff --git a/src/modules/chanmodes/halfop.c b/src/modules/chanmodes/halfop.c
new file mode 100644
index 0000000..2e2a6ba
--- /dev/null
+++ b/src/modules/chanmodes/halfop.c
@@ -0,0 +1,88 @@
+/*
+ * Channel Mode +h
+ * (C) Copyright 2021 Syzop and the UnrealIRCd team
+ *
+ * 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.
+ */
+
+#include "unrealircd.h"
+
+ModuleHeader MOD_HEADER
+ = {
+ "chanmodes/halfop",
+ "6.0",
+ "Channel Mode +h",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+ };
+
+/* Forward declarations */
+int cmode_halfop_is_ok(Client *client, Channel *channel, char mode, const char *para, int type, int what);
+
+MOD_INIT()
+{
+ CmodeInfo creq;
+ ModDataInfo mreq;
+
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ memset(&creq, 0, sizeof(creq));
+ creq.paracount = 1;
+ creq.is_ok = cmode_halfop_is_ok;
+ creq.letter = 'h';
+ creq.prefix = '%';
+ creq.sjoin_prefix = '%';
+ creq.rank = RANK_HALFOP;
+ creq.unset_with_param = 1;
+ creq.type = CMODE_MEMBER;
+ CmodeAdd(modinfo->handle, creq, NULL);
+
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ return MOD_SUCCESS;
+}
+
+int cmode_halfop_is_ok(Client *client, Channel *channel, char mode, const char *param, int type, int what)
+{
+ if ((type == EXCHK_ACCESS) || (type == EXCHK_ACCESS_ERR))
+ {
+ Client *target = find_user(param, NULL);
+
+ if ((what == MODE_DEL) && (target == client))
+ {
+ /* User may always remove their own modes */
+ return EX_ALLOW;
+ }
+ if ((what == MODE_ADD) && check_channel_access(client, channel, "hoaq"))
+ {
+ /* Permitted for +hoaq */
+ return EX_ALLOW;
+ }
+ if (type == EXCHK_ACCESS_ERR)
+ sendnumeric(client, ERR_CHANOPRIVSNEEDED, channel->name);
+ return EX_DENY;
+ }
+
+ /* fallthrough -- should not be used */
+ return EX_DENY;
+}
diff --git a/src/modules/chanmodes/history.c b/src/modules/chanmodes/history.c
index 124a25e..9cdc73e 100644
--- a/src/modules/chanmodes/history.c
+++ b/src/modules/chanmodes/history.c
@@ -11,7 +11,7 @@ ModuleHeader MOD_HEADER
"1.0",
"Channel Mode +H",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
typedef struct ConfigHistoryExt ConfigHistoryExt;
@@ -37,25 +37,25 @@ Cmode_t EXTMODE_HISTORY = 0L;
static cfgstruct cfg;
static cfgstruct test;
-#define HistoryEnabled(channel) (channel->mode.extmode & EXTMODE_HISTORY)
+#define HistoryEnabled(channel) (channel->mode.mode & EXTMODE_HISTORY)
/* Forward declarations */
static void init_config(cfgstruct *cfg);
int history_config_test(ConfigFile *, ConfigEntry *, int, int *);
int history_config_posttest(int *);
int history_config_run(ConfigFile *, ConfigEntry *, int);
-int history_chanmode_change(Client *client, Channel *channel, MessageTag *mtags, char *modebuf, char *parabuf, time_t sendts, int samode);
+int history_chanmode_change(Client *client, Channel *channel, MessageTag *mtags, const char *modebuf, const char *parabuf, time_t sendts, int samode, int *destroy_channel);
static int compare_history_modes(HistoryChanMode *a, HistoryChanMode *b);
-int history_chanmode_is_ok(Client *client, Channel *channel, char mode, char *para, int type, int what);
-void *history_chanmode_put_param(void *r_in, char *param);
-char *history_chanmode_get_param(void *r_in);
-char *history_chanmode_conv_param(char *param, Client *client, Channel *channel);
+int history_chanmode_is_ok(Client *client, Channel *channel, char mode, const char *para, int type, int what);
+void *history_chanmode_put_param(void *r_in, const char *param);
+const char *history_chanmode_get_param(void *r_in);
+const char *history_chanmode_conv_param(const char *param, Client *client, Channel *channel);
void history_chanmode_free_param(void *r);
void *history_chanmode_dup_struct(void *r_in);
int history_chanmode_sjoin_check(Channel *channel, void *ourx, void *theirx);
int history_channel_destroy(Channel *channel, int *should_destroy);
-int history_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, SendType sendtype);
-int history_join(Client *client, Channel *channel, MessageTag *mtags, char *parv[]);
+int history_chanmsg(Client *client, Channel *channel, int sendflags, const char *prefix, const char *target, MessageTag *mtags, const char *text, SendType sendtype);
+int history_join(Client *client, Channel *channel, MessageTag *mtags);
CMD_OVERRIDE_FUNC(override_mode);
MOD_TEST()
@@ -77,7 +77,7 @@ MOD_INIT()
memset(&creq, 0, sizeof(creq));
creq.paracount = 1;
creq.is_ok = history_chanmode_is_ok;
- creq.flag = 'H';
+ creq.letter = 'H';
creq.put_param = history_chanmode_put_param;
creq.get_param = history_chanmode_get_param;
creq.conv_param = history_chanmode_conv_param;
@@ -99,11 +99,11 @@ MOD_INIT()
MOD_LOAD()
{
- CommandOverrideAdd(modinfo->handle, "MODE", override_mode);
- CommandOverrideAdd(modinfo->handle, "SVSMODE", override_mode);
- CommandOverrideAdd(modinfo->handle, "SVS2MODE", override_mode);
- CommandOverrideAdd(modinfo->handle, "SAMODE", override_mode);
- CommandOverrideAdd(modinfo->handle, "SJOIN", override_mode);
+ CommandOverrideAdd(modinfo->handle, "MODE", 0, override_mode);
+ CommandOverrideAdd(modinfo->handle, "SVSMODE", 0, override_mode);
+ CommandOverrideAdd(modinfo->handle, "SVS2MODE", 0, override_mode);
+ CommandOverrideAdd(modinfo->handle, "SAMODE", 0, override_mode);
+ CommandOverrideAdd(modinfo->handle, "SJOIN", 0, override_mode);
return MOD_SUCCESS;
}
@@ -124,8 +124,6 @@ static void init_config(cfgstruct *cfg)
cfg->max_storage_per_channel_registered.time = 86400*31;
}
-#define CheckNull(x) if ((!(x)->ce_vardata) || (!(*((x)->ce_vardata)))) { config_error("%s:%i: missing parameter", (x)->ce_fileptr->cf_filename, (x)->ce_varlinenum); errors++; continue; }
-
int history_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
{
int errors = 0;
@@ -134,140 +132,140 @@ int history_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
long on_join_time=0L, maximum_storage_time_registered=0L, maximum_storage_time_unregistered=0L;
/* We only care about set::history */
- if ((type != CONFIG_SET) || strcmp(ce->ce_varname, "history"))
+ if ((type != CONFIG_SET) || strcmp(ce->name, "history"))
return 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "channel"))
+ if (!strcmp(cep->name, "channel"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "playback-on-join"))
+ if (!strcmp(cepp->name, "playback-on-join"))
{
- for (cep4 = cepp->ce_entries; cep4; cep4 = cep4->ce_next)
+ for (cep4 = cepp->items; cep4; cep4 = cep4->next)
{
- if (!strcmp(cep4->ce_varname, "lines"))
+ if (!strcmp(cep4->name, "lines"))
{
int v;
CheckNull(cep4);
- v = atoi(cep4->ce_vardata);
+ v = atoi(cep4->value);
if ((v < 0) || (v > 1000))
{
config_error("%s:%i: set::history::channel::playback-on-join::lines must be between 0 and 1000. "
"Recommended values are 10-50. Got: %d.",
- cep4->ce_fileptr->cf_filename, cep4->ce_varlinenum, v);
+ cep4->file->filename, cep4->line_number, v);
errors++;
continue;
}
test.playback_on_join.lines = v;
} else
- if (!strcmp(cep4->ce_varname, "time"))
+ if (!strcmp(cep4->name, "time"))
{
long v;
CheckNull(cep4);
- v = config_checkval(cep4->ce_vardata, CFG_TIME);
+ v = config_checkval(cep4->value, CFG_TIME);
if (v < 0)
{
config_error("%s:%i: set::history::channel::playback-on-join::time must be zero or more.",
- cep4->ce_fileptr->cf_filename, cep4->ce_varlinenum);
+ cep4->file->filename, cep4->line_number);
errors++;
continue;
}
test.playback_on_join.time = v;
} else
{
- config_error_unknown(cep4->ce_fileptr->cf_filename,
- cep4->ce_varlinenum, "set::history::channel::playback-on-join", cep4->ce_varname);
+ config_error_unknown(cep4->file->filename,
+ cep4->line_number, "set::history::channel::playback-on-join", cep4->name);
errors++;
}
}
} else
- if (!strcmp(cepp->ce_varname, "max-storage-per-channel"))
+ if (!strcmp(cepp->name, "max-storage-per-channel"))
{
- for (cep4 = cepp->ce_entries; cep4; cep4 = cep4->ce_next)
+ for (cep4 = cepp->items; cep4; cep4 = cep4->next)
{
- if (!strcmp(cep4->ce_varname, "registered"))
+ if (!strcmp(cep4->name, "registered"))
{
- for (cep5 = cep4->ce_entries; cep5; cep5 = cep5->ce_next)
+ for (cep5 = cep4->items; cep5; cep5 = cep5->next)
{
- if (!strcmp(cep5->ce_varname, "lines"))
+ if (!strcmp(cep5->name, "lines"))
{
int v;
CheckNull(cep5);
- v = atoi(cep5->ce_vardata);
+ v = atoi(cep5->value);
if (v < 1)
{
config_error("%s:%i: set::history::channel::max-storage-per-channel::registered::lines must be a positive number.",
- cep5->ce_fileptr->cf_filename, cep5->ce_varlinenum);
+ cep5->file->filename, cep5->line_number);
errors++;
continue;
}
test.max_storage_per_channel_registered.lines = v;
} else
- if (!strcmp(cep5->ce_varname, "time"))
+ if (!strcmp(cep5->name, "time"))
{
long v;
CheckNull(cep5);
- v = config_checkval(cep5->ce_vardata, CFG_TIME);
+ v = config_checkval(cep5->value, CFG_TIME);
if (v < 1)
{
config_error("%s:%i: set::history::channel::max-storage-per-channel::registered::time must be a positive number.",
- cep5->ce_fileptr->cf_filename, cep5->ce_varlinenum);
+ cep5->file->filename, cep5->line_number);
errors++;
continue;
}
test.max_storage_per_channel_registered.time = v;
} else
{
- config_error_unknown(cep5->ce_fileptr->cf_filename,
- cep5->ce_varlinenum, "set::history::channel::max-storage-per-channel::registered", cep5->ce_varname);
+ config_error_unknown(cep5->file->filename,
+ cep5->line_number, "set::history::channel::max-storage-per-channel::registered", cep5->name);
errors++;
}
}
} else
- if (!strcmp(cep4->ce_varname, "unregistered"))
+ if (!strcmp(cep4->name, "unregistered"))
{
- for (cep5 = cep4->ce_entries; cep5; cep5 = cep5->ce_next)
+ for (cep5 = cep4->items; cep5; cep5 = cep5->next)
{
- if (!strcmp(cep5->ce_varname, "lines"))
+ if (!strcmp(cep5->name, "lines"))
{
int v;
CheckNull(cep5);
- v = atoi(cep5->ce_vardata);
+ v = atoi(cep5->value);
if (v < 1)
{
config_error("%s:%i: set::history::channel::max-storage-per-channel::unregistered::lines must be a positive number.",
- cep5->ce_fileptr->cf_filename, cep5->ce_varlinenum);
+ cep5->file->filename, cep5->line_number);
errors++;
continue;
}
test.max_storage_per_channel_unregistered.lines = v;
} else
- if (!strcmp(cep5->ce_varname, "time"))
+ if (!strcmp(cep5->name, "time"))
{
long v;
CheckNull(cep5);
- v = config_checkval(cep5->ce_vardata, CFG_TIME);
+ v = config_checkval(cep5->value, CFG_TIME);
if (v < 1)
{
config_error("%s:%i: set::history::channel::max-storage-per-channel::unregistered::time must be a positive number.",
- cep5->ce_fileptr->cf_filename, cep5->ce_varlinenum);
+ cep5->file->filename, cep5->line_number);
errors++;
continue;
}
test.max_storage_per_channel_unregistered.time = v;
} else
{
- config_error_unknown(cep5->ce_fileptr->cf_filename,
- cep5->ce_varlinenum, "set::history::channel::max-storage-per-channel::unregistered", cep5->ce_varname);
+ config_error_unknown(cep5->file->filename,
+ cep5->line_number, "set::history::channel::max-storage-per-channel::unregistered", cep5->name);
errors++;
}
}
} else
{
- config_error_unknown(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "set::history::max-storage-per-channel", cep->ce_varname);
+ config_error_unknown(cep->file->filename,
+ cep->line_number, "set::history::max-storage-per-channel", cep->name);
errors++;
}
}
@@ -304,15 +302,15 @@ int history_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
}
if (!used)
{
- config_error_unknown(cepp->ce_fileptr->cf_filename,
- cepp->ce_varlinenum, "set::history::channel", cepp->ce_varname);
+ config_error_unknown(cepp->file->filename,
+ cepp->line_number, "set::history::channel", cepp->name);
errors++;
}
}
}
} else {
- config_error_unknown(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "set::history", cep->ce_varname);
+ config_error_unknown(cep->file->filename,
+ cep->line_number, "set::history", cep->name);
errors++;
}
}
@@ -337,58 +335,58 @@ int history_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
{
ConfigEntry *cep, *cepp, *cep4, *cep5;
- if ((type != CONFIG_SET) || strcmp(ce->ce_varname, "history"))
+ if ((type != CONFIG_SET) || strcmp(ce->name, "history"))
return 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "channel"))
+ if (!strcmp(cep->name, "channel"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "playback-on-join"))
+ if (!strcmp(cepp->name, "playback-on-join"))
{
- for (cep4 = cepp->ce_entries; cep4; cep4 = cep4->ce_next)
+ for (cep4 = cepp->items; cep4; cep4 = cep4->next)
{
- if (!strcmp(cep4->ce_varname, "lines"))
+ if (!strcmp(cep4->name, "lines"))
{
- cfg.playback_on_join.lines = atoi(cep4->ce_vardata);
+ cfg.playback_on_join.lines = atoi(cep4->value);
} else
- if (!strcmp(cep4->ce_varname, "time"))
+ if (!strcmp(cep4->name, "time"))
{
- cfg.playback_on_join.time = config_checkval(cep4->ce_vardata, CFG_TIME);
+ cfg.playback_on_join.time = config_checkval(cep4->value, CFG_TIME);
}
}
} else
- if (!strcmp(cepp->ce_varname, "max-storage-per-channel"))
+ if (!strcmp(cepp->name, "max-storage-per-channel"))
{
- for (cep4 = cepp->ce_entries; cep4; cep4 = cep4->ce_next)
+ for (cep4 = cepp->items; cep4; cep4 = cep4->next)
{
- if (!strcmp(cep4->ce_varname, "registered"))
+ if (!strcmp(cep4->name, "registered"))
{
- for (cep5 = cep4->ce_entries; cep5; cep5 = cep5->ce_next)
+ for (cep5 = cep4->items; cep5; cep5 = cep5->next)
{
- if (!strcmp(cep5->ce_varname, "lines"))
+ if (!strcmp(cep5->name, "lines"))
{
- cfg.max_storage_per_channel_registered.lines = atoi(cep5->ce_vardata);
+ cfg.max_storage_per_channel_registered.lines = atoi(cep5->value);
} else
- if (!strcmp(cep5->ce_varname, "time"))
+ if (!strcmp(cep5->name, "time"))
{
- cfg.max_storage_per_channel_registered.time = config_checkval(cep5->ce_vardata, CFG_TIME);
+ cfg.max_storage_per_channel_registered.time = config_checkval(cep5->value, CFG_TIME);
}
}
} else
- if (!strcmp(cep4->ce_varname, "unregistered"))
+ if (!strcmp(cep4->name, "unregistered"))
{
- for (cep5 = cep4->ce_entries; cep5; cep5 = cep5->ce_next)
+ for (cep5 = cep4->items; cep5; cep5 = cep5->next)
{
- if (!strcmp(cep5->ce_varname, "lines"))
+ if (!strcmp(cep5->name, "lines"))
{
- cfg.max_storage_per_channel_unregistered.lines = atoi(cep5->ce_vardata);
+ cfg.max_storage_per_channel_unregistered.lines = atoi(cep5->value);
} else
- if (!strcmp(cep5->ce_varname, "time"))
+ if (!strcmp(cep5->name, "time"))
{
- cfg.max_storage_per_channel_unregistered.time = config_checkval(cep5->ce_vardata, CFG_TIME);
+ cfg.max_storage_per_channel_unregistered.time = config_checkval(cep5->value, CFG_TIME);
}
}
}
@@ -415,7 +413,7 @@ int history_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
* @param lines: The number of lines (the X in +H X:Y)
* @param t: The time value (the Y in +H X:Y)
*/
-int history_parse_chanmode(Channel *channel, char *param, int *lines, long *t)
+int history_parse_chanmode(Channel *channel, const char *param, int *lines, long *t)
{
char buf[64], *p, *q;
char contains_non_digit = 0;
@@ -479,11 +477,11 @@ int history_parse_chanmode(Channel *channel, char *param, int *lines, long *t)
* Does the user have rights to add/remove this channel mode?
* Is the supplied mode parameter ok?
*/
-int history_chanmode_is_ok(Client *client, Channel *channel, char mode, char *param, int type, int what)
+int history_chanmode_is_ok(Client *client, Channel *channel, char mode, const char *param, int type, int what)
{
if ((type == EXCHK_ACCESS) || (type == EXCHK_ACCESS_ERR))
{
- if (IsUser(client) && is_chan_op(client, channel))
+ if (IsUser(client) && check_channel_access(client, channel, "oaq"))
return EX_ALLOW;
if (type == EXCHK_ACCESS_ERR) /* can only be due to being halfop */
sendnumeric(client, ERR_NOTFORHALFOPS, 'H');
@@ -529,7 +527,7 @@ static void history_chanmode_helper(char *buf, size_t bufsize, int lines, long t
/** Convert channel parameter to something proper.
* NOTE: client may be NULL if called for e.g. set::modes-playback-on-join
*/
-char *history_chanmode_conv_param(char *param, Client *client, Channel *channel)
+const char *history_chanmode_conv_param(const char *param, Client *client, Channel *channel)
{
static char buf[64];
int lines = 0;
@@ -543,7 +541,7 @@ char *history_chanmode_conv_param(char *param, Client *client, Channel *channel)
}
/** Store the +H x:y channel mode */
-void *history_chanmode_put_param(void *mode_in, char *param)
+void *history_chanmode_put_param(void *mode_in, const char *param)
{
HistoryChanMode *h = (HistoryChanMode *)mode_in;
int lines = 0;
@@ -565,7 +563,7 @@ void *history_chanmode_put_param(void *mode_in, char *param)
}
/** Retrieve the +H settings (the X:Y string) */
-char *history_chanmode_get_param(void *h_in)
+const char *history_chanmode_get_param(void *h_in)
{
HistoryChanMode *h = (HistoryChanMode *)h_in;
static char buf[64];
@@ -612,7 +610,7 @@ int history_chanmode_sjoin_check(Channel *channel, void *ourx, void *theirx)
}
/** On channel mode change, communicate the +H limits to the history backend layer */
-int history_chanmode_change(Client *client, Channel *channel, MessageTag *mtags, char *modebuf, char *parabuf, time_t sendts, int samode)
+int history_chanmode_change(Client *client, Channel *channel, MessageTag *mtags, const char *modebuf, const char *parabuf, time_t sendts, int samode, int *destroy_channel)
{
HistoryChanMode *settings;
@@ -623,9 +621,9 @@ int history_chanmode_change(Client *client, Channel *channel, MessageTag *mtags,
/* If so, grab the settings, and communicate them */
settings = (HistoryChanMode *)GETPARASTRUCT(channel, 'H');
if (settings)
- history_set_limit(channel->chname, settings->max_lines, settings->max_time);
+ history_set_limit(channel->name, settings->max_lines, settings->max_time);
else
- history_destroy(channel->chname);
+ history_destroy(channel->name);
return 0;
}
@@ -636,12 +634,12 @@ int history_channel_destroy(Channel *channel, int *should_destroy)
if (*should_destroy == 0)
return 0; /* channel will not be destroyed */
- history_destroy(channel->chname);
+ history_destroy(channel->name);
return 0;
}
-int history_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, SendType sendtype)
+int history_chanmsg(Client *client, Channel *channel, int sendflags, const char *prefix, const char *target, MessageTag *mtags, const char *text, SendType sendtype)
{
char buf[512];
char source[64];
@@ -672,15 +670,15 @@ int history_chanmsg(Client *client, Channel *channel, int sendflags, int prefix,
snprintf(buf, sizeof(buf), ":%s %s %s :%s",
source,
sendtype_to_cmd(sendtype),
- channel->chname,
+ channel->name,
text);
- history_add(channel->chname, mtags, buf);
+ history_add(channel->name, mtags, buf);
return 0;
}
-int history_join(Client *client, Channel *channel, MessageTag *mtags, char *parv[])
+int history_join(Client *client, Channel *channel, MessageTag *mtags)
{
/* Only for +H channels */
if (!HistoryEnabled(channel) || !cfg.playback_on_join.lines || !cfg.playback_on_join.time)
@@ -689,7 +687,7 @@ int history_join(Client *client, Channel *channel, MessageTag *mtags, char *parv
/* No history-on-join for clients that implement CHATHISTORY,
* they will pull history themselves if they need it.
*/
- if (HasCapability(client, "draft/chathistory") || HasCapability(client, "chathistory"))
+ if (HasCapability(client, "draft/chathistory") /*|| HasCapability(client, "chathistory")*/)
return 0;
if (MyUser(client) && can_receive_history(client))
@@ -700,7 +698,7 @@ int history_join(Client *client, Channel *channel, MessageTag *mtags, char *parv
filter.cmd = HFC_SIMPLE;
filter.last_lines = cfg.playback_on_join.lines;
filter.last_seconds = cfg.playback_on_join.time;
- r = history_request(channel->chname, &filter);
+ r = history_request(channel->name, &filter);
if (r)
{
history_send_result(client, r);
@@ -724,10 +722,10 @@ CMD_OVERRIDE_FUNC(override_mode)
* means: we are the server that services are linked to.
*/
if ((IsServer(client) && client->local) ||
- (IsUser(client) && client->srvptr && client->srvptr->local))
+ (IsUser(client) && client->uplink && client->uplink->local))
{
/* Now check if the channel is currently +r */
- if ((parc >= 2) && !BadPtr(parv[1]) && ((channel = find_channel(parv[1], NULL))) &&
+ if ((parc >= 2) && !BadPtr(parv[1]) && ((channel = find_channel(parv[1]))) &&
has_channel_mode(channel, 'r'))
{
had_r = 1;
@@ -744,7 +742,7 @@ CMD_OVERRIDE_FUNC(override_mode)
* then...
*/
if (had_r &&
- ((channel = find_channel(parv[1], NULL))) &&
+ ((channel = find_channel(parv[1]))) &&
!has_channel_mode(channel, 'r') &&
HistoryEnabled(channel))
{
@@ -770,7 +768,9 @@ CMD_OVERRIDE_FUNC(override_mode)
if (changed)
{
MessageTag *mtags = NULL;
- char *params = history_chanmode_get_param(settings);
+ const char *params = history_chanmode_get_param(settings);
+ char modebuf[BUFSIZE], parabuf[BUFSIZE];
+ int destroy_channel = 0;
if (!params)
return; /* Weird */
@@ -782,13 +782,13 @@ CMD_OVERRIDE_FUNC(override_mode)
sendto_channel(channel, &me, &me, 0, 0, SEND_LOCAL, mtags,
":%s MODE %s %s %s",
- me.name, channel->chname, modebuf, parabuf);
+ me.name, channel->name, modebuf, parabuf);
sendto_server(NULL, 0, 0, mtags, ":%s MODE %s %s %s %lld",
- me.id, channel->chname, modebuf, parabuf,
+ me.id, channel->name, modebuf, parabuf,
(long long)channel->creationtime);
/* Activate this hook just like cmd_mode.c */
- RunHook7(HOOKTYPE_REMOTE_CHANMODE, &me, channel, mtags, modebuf, parabuf, 0, 0);
+ RunHook(HOOKTYPE_REMOTE_CHANMODE, &me, channel, mtags, modebuf, parabuf, 0, 0, &destroy_channel);
free_message_tags(mtags);
diff --git a/src/modules/chanmodes/inviteonly.c b/src/modules/chanmodes/inviteonly.c
new file mode 100644
index 0000000..d7548f9
--- /dev/null
+++ b/src/modules/chanmodes/inviteonly.c
@@ -0,0 +1,77 @@
+/*
+ * Channel Mode +i
+ * (C) Copyright 2021 Syzop and the UnrealIRCd team
+ *
+ * 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.
+ */
+
+#include "unrealircd.h"
+
+
+ModuleHeader MOD_HEADER
+ = {
+ "chanmodes/inviteonly",
+ "6.0",
+ "Channel Mode +i",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+ };
+
+Cmode_t EXTCMODE_INVITE_ONLY;
+
+#define IsInviteOnly(channel) (channel->mode.mode & EXTCMODE_INVITE_ONLY)
+
+int inviteonly_can_join(Client *client, Channel *channel, const char *key, char **errmsg);
+
+MOD_INIT()
+{
+ CmodeInfo req;
+
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ memset(&req, 0, sizeof(req));
+ req.paracount = 0;
+ req.letter = 'i';
+ req.is_ok = extcmode_default_requirehalfop;
+ CmodeAdd(modinfo->handle, req, &EXTCMODE_INVITE_ONLY);
+
+ HookAdd(modinfo->handle, HOOKTYPE_CAN_JOIN, 0, inviteonly_can_join);
+
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ return MOD_SUCCESS;
+}
+
+int inviteonly_can_join (Client *client, Channel *channel, const char *key, char **errmsg)
+{
+ if (IsInviteOnly(channel))
+ {
+ if (is_invited(client, channel))
+ return 0;
+ if (find_invex(channel, client))
+ return 0;
+ *errmsg = STR_ERR_INVITEONLYCHAN;
+ return ERR_INVITEONLYCHAN;
+ }
+ return 0;
+}
diff --git a/src/modules/chanmodes/isregistered.c b/src/modules/chanmodes/isregistered.c
new file mode 100644
index 0000000..4d8675f
--- /dev/null
+++ b/src/modules/chanmodes/isregistered.c
@@ -0,0 +1,72 @@
+/*
+ * Channel Mode +r
+ * (C) Copyright 2021 Syzop and the UnrealIRCd team
+ *
+ * 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.
+ */
+
+#include "unrealircd.h"
+
+
+ModuleHeader MOD_HEADER
+ = {
+ "chanmodes/isregistered",
+ "6.0",
+ "Channel Mode +r",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+ };
+
+Cmode_t EXTCMODE_REGISTERED;
+
+#define IsRegisteredChannel(channel) (channel->mode.mode & EXTCMODE_REGISTERED)
+
+int isregistered_chanmode_is_ok(Client *client, Channel *channel, char mode, const char *param, int type, int what);
+
+MOD_INIT()
+{
+ CmodeInfo req;
+
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ memset(&req, 0, sizeof(req));
+ req.paracount = 0;
+ req.letter = 'r';
+ req.is_ok = isregistered_chanmode_is_ok;
+ CmodeAdd(modinfo->handle, req, &EXTCMODE_REGISTERED);
+
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ return MOD_SUCCESS;
+}
+
+int isregistered_chanmode_is_ok(Client *client, Channel *channel, char mode, const char *param, int type, int what)
+{
+ if (!IsServer(client) && !IsULine(client))
+ {
+ if (type == EXCHK_ACCESS_ERR)
+ sendnumeric(client, ERR_ONLYSERVERSCANCHANGE, channel->name);
+ return EX_ALWAYS_DENY;
+ }
+ return EX_ALLOW;
+}
diff --git a/src/modules/chanmodes/issecure.c b/src/modules/chanmodes/issecure.c
index 56320ab..07839a8 100644
--- a/src/modules/chanmodes/issecure.c
+++ b/src/modules/chanmodes/issecure.c
@@ -3,7 +3,7 @@
* (C) Copyright 2010-.. Bram Matthys (Syzop) and the UnrealIRCd team
*
* This module will indicate if a channel is secure, and if so will set +Z.
- * Secure is defined as: all users on the channel are connected through SSL/TLS
+ * Secure is defined as: all users on the channel are connected through TLS
* Additionally, the channel has to be +z (only allow secure users to join).
* Suggested on http://bugs.unrealircd.org/view.php?id=3720
* Thanks go to fez for pushing us for some kind of method to indicate
@@ -34,21 +34,21 @@ ModuleHeader MOD_HEADER
"4.2",
"Channel Mode +Z",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
Cmode_t EXTCMODE_ISSECURE;
-#define IsSecureChanIndicated(channel) (channel->mode.extmode & EXTCMODE_ISSECURE)
+#define IsSecureChanIndicated(channel) (channel->mode.mode & EXTCMODE_ISSECURE)
int IsSecureJoin(Channel *channel);
-int modeZ_is_ok(Client *client, Channel *channel, char mode, char *para, int checkt, int what);
-int issecure_join(Client *client, Channel *channel, MessageTag *mtags, char *parv[]);
-int issecure_part(Client *client, Channel *channel, MessageTag *mtags, char *comment);
-int issecure_quit(Client *client, MessageTag *mtags, char *comment);
-int issecure_kick(Client *client, Client *victim, Channel *channel, MessageTag *mtags, char *comment);
+int modeZ_is_ok(Client *client, Channel *channel, char mode, const char *para, int checkt, int what);
+int issecure_join(Client *client, Channel *channel, MessageTag *mtags);
+int issecure_part(Client *client, Channel *channel, MessageTag *mtags, const char *comment);
+int issecure_quit(Client *client, MessageTag *mtags, const char *comment);
+int issecure_kick(Client *client, Client *victim, Channel *channel, MessageTag *mtags, const char *comment);
int issecure_chanmode(Client *client, Channel *channel, MessageTag *mtags,
- char *modebuf, char *parabuf, time_t sendts, int samode);
+ const char *modebuf, const char *parabuf, time_t sendts, int samode, int *destroy_channel);
MOD_TEST()
@@ -64,7 +64,7 @@ CmodeInfo req;
memset(&req, 0, sizeof(req));
req.paracount = 0;
req.is_ok = modeZ_is_ok;
- req.flag = 'Z';
+ req.letter = 'Z';
req.local = 1; /* local channel mode */
CmodeAdd(modinfo->handle, req, &EXTCMODE_ISSECURE);
@@ -108,7 +108,7 @@ int IsSecureJoin(Channel *channel)
return i;
}
-int modeZ_is_ok(Client *client, Channel *channel, char mode, char *para, int checkt, int what)
+int modeZ_is_ok(Client *client, Channel *channel, char mode, const char *para, int checkt, int what)
{
/* Reject any attempt to set or unset our mode. Even to IRCOps */
return EX_ALWAYS_DENY;
@@ -143,17 +143,17 @@ void issecure_unset(Channel *channel, Client *client, MessageTag *recv_mtags, in
if (notice)
{
mtags = NULL;
- new_message_special(&me, recv_mtags, &mtags, "NOTICE %s :setting -Z", channel->chname);
+ new_message_special(&me, recv_mtags, &mtags, "NOTICE %s :setting -Z", channel->name);
sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags,
- ":%s NOTICE %s :User '%s' joined and is not connected through SSL/TLS, setting channel -Z (insecure)",
- me.id, channel->chname, client->name);
+ ":%s NOTICE %s :User '%s' joined and is not connected through TLS, setting channel -Z (insecure)",
+ me.id, channel->name, client->name);
free_message_tags(mtags);
}
- channel->mode.extmode &= ~EXTCMODE_ISSECURE;
+ channel->mode.mode &= ~EXTCMODE_ISSECURE;
mtags = NULL;
- new_message_special(&me, recv_mtags, &mtags, "MODE %s -Z", channel->chname);
- sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags, ":%s MODE %s -Z", me.name, channel->chname);
+ new_message_special(&me, recv_mtags, &mtags, "MODE %s -Z", channel->name);
+ sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags, ":%s MODE %s -Z", me.name, channel->name);
free_message_tags(mtags);
}
@@ -168,31 +168,31 @@ void issecure_set(Channel *channel, Client *client, MessageTag *recv_mtags, int
MessageTag *mtags;
mtags = NULL;
- new_message_special(&me, recv_mtags, &mtags, "NOTICE %s :setting +Z", channel->chname);
+ new_message_special(&me, recv_mtags, &mtags, "NOTICE %s :setting +Z", channel->name);
if (notice && client)
{
/* note that we have to skip 'client', since when this call is being made
* he is still considered a member of this channel.
*/
sendto_channel(channel, &me, client, 0, 0, SEND_LOCAL, NULL,
- ":%s NOTICE %s :Now all users in the channel are connected through SSL/TLS, setting channel +Z (secure)",
- me.name, channel->chname);
+ ":%s NOTICE %s :Now all users in the channel are connected through TLS, setting channel +Z (secure)",
+ me.name, channel->name);
} else if (notice)
{
/* note the missing word 'now' in next line */
sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, NULL,
- ":%s NOTICE %s :All users in the channel are connected through SSL/TLS, setting channel +Z (secure)",
- me.name, channel->chname);
+ ":%s NOTICE %s :All users in the channel are connected through TLS, setting channel +Z (secure)",
+ me.name, channel->name);
}
free_message_tags(mtags);
- channel->mode.extmode |= EXTCMODE_ISSECURE;
+ channel->mode.mode |= EXTCMODE_ISSECURE;
mtags = NULL;
- new_message_special(&me, recv_mtags, &mtags, "MODE %s +Z", channel->chname);
+ new_message_special(&me, recv_mtags, &mtags, "MODE %s +Z", channel->name);
sendto_channel(channel, &me, client, 0, 0, SEND_LOCAL, mtags,
":%s MODE %s +Z",
- me.name, channel->chname);
+ me.name, channel->name);
free_message_tags(mtags);
}
@@ -200,7 +200,7 @@ void issecure_set(Channel *channel, Client *client, MessageTag *recv_mtags, int
* so while they can be written shorter, they would only take longer to execute!
*/
-int issecure_join(Client *client, Channel *channel, MessageTag *mtags, char *parv[])
+int issecure_join(Client *client, Channel *channel, MessageTag *mtags)
{
/* Check only if chan already +zZ and the user joining is insecure (no need to count) */
if (IsSecureJoin(channel) && IsSecureChanIndicated(channel) && !IsSecureConnect(client) && !IsULine(client))
@@ -213,7 +213,7 @@ int issecure_join(Client *client, Channel *channel, MessageTag *mtags, char *par
return 0;
}
-int issecure_part(Client *client, Channel *channel, MessageTag *mtags, char *comment)
+int issecure_part(Client *client, Channel *channel, MessageTag *mtags, const char *comment)
{
/* Only care if chan is +z-Z and the user leaving is insecure, then count */
if (IsSecureJoin(channel) && !IsSecureChanIndicated(channel) && !IsSecureConnect(client) &&
@@ -222,7 +222,7 @@ int issecure_part(Client *client, Channel *channel, MessageTag *mtags, char *com
return 0;
}
-int issecure_quit(Client *client, MessageTag *mtags, char *comment)
+int issecure_quit(Client *client, MessageTag *mtags, const char *comment)
{
Membership *membership;
Channel *channel;
@@ -238,7 +238,7 @@ Channel *channel;
return 0;
}
-int issecure_kick(Client *client, Client *victim, Channel *channel, MessageTag *mtags, char *comment)
+int issecure_kick(Client *client, Client *victim, Channel *channel, MessageTag *mtags, const char *comment)
{
/* Identical to part&quit, except we care about 'victim' and not 'client' */
if (IsSecureJoin(channel) && !IsSecureChanIndicated(channel) &&
@@ -248,7 +248,7 @@ int issecure_kick(Client *client, Client *victim, Channel *channel, MessageTag *
}
int issecure_chanmode(Client *client, Channel *channel, MessageTag *mtags,
- char *modebuf, char *parabuf, time_t sendts, int samode)
+ const char *modebuf, const char *parabuf, time_t sendts, int samode, int *destroy_channel)
{
if (!strchr(modebuf, 'z'))
return 0; /* don't care */
diff --git a/src/modules/chanmodes/key.c b/src/modules/chanmodes/key.c
new file mode 100644
index 0000000..e0753cc
--- /dev/null
+++ b/src/modules/chanmodes/key.c
@@ -0,0 +1,232 @@
+/*
+ * Channel Mode +k
+ * (C) Copyright 2021 Syzop and the UnrealIRCd team
+ *
+ * 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.
+ */
+
+#include "unrealircd.h"
+
+ModuleHeader MOD_HEADER
+ = {
+ "chanmodes/key",
+ "6.0",
+ "Channel Mode +k",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+ };
+
+typedef struct ChannelKey ChannelKey;
+struct ChannelKey {
+ char key[KEYLEN+1];
+};
+
+/* Global variables */
+ModDataInfo *mdkey = NULL;
+Cmode_t EXTMODE_KEY = 0L;
+
+#define IsKey(x) ((x)->mode.mode & EXTMODE_KEY)
+
+/* Forward declarations */
+int key_can_join(Client *client, Channel *channel, const char *key, char **errmsg);
+int cmode_key_is_ok(Client *client, Channel *channel, char mode, const char *para, int type, int what);
+void *cmode_key_put_param(void *r_in, const char *param);
+const char *cmode_key_get_param(void *r_in);
+const char *cmode_key_conv_param(const char *param_in, Client *client, Channel *channel);
+void cmode_key_free_param(void *r);
+void *cmode_key_dup_struct(void *r_in);
+int cmode_key_sjoin_check(Channel *channel, void *ourx, void *theirx);
+int is_valid_key(const char *key);
+void transform_channel_key(const char *i, char *o, int n);
+
+MOD_INIT()
+{
+ CmodeInfo creq;
+ ModDataInfo mreq;
+
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ memset(&creq, 0, sizeof(creq));
+ creq.paracount = 1;
+ creq.is_ok = cmode_key_is_ok;
+ creq.letter = 'k';
+ creq.unset_with_param = 1; /* yeah... +k is like this */
+ creq.put_param = cmode_key_put_param;
+ creq.get_param = cmode_key_get_param;
+ creq.conv_param = cmode_key_conv_param;
+ creq.free_param = cmode_key_free_param;
+ creq.dup_struct = cmode_key_dup_struct;
+ creq.sjoin_check = cmode_key_sjoin_check;
+ CmodeAdd(modinfo->handle, creq, &EXTMODE_KEY);
+
+ HookAdd(modinfo->handle, HOOKTYPE_CAN_JOIN, 0, key_can_join);
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ return MOD_SUCCESS;
+}
+
+/** Can the user join the channel? */
+int key_can_join(Client *client, Channel *channel, const char *key, char **errmsg)
+{
+ ChannelKey *r = (ChannelKey *)GETPARASTRUCT(channel, 'k');
+
+ /* Is the channel +k? */
+ if (r && *r->key)
+ {
+ if (key && !strcmp(r->key, key))
+ return 0;
+ *errmsg = STR_ERR_BADCHANNELKEY;
+ return ERR_BADCHANNELKEY;
+ }
+
+ return 0;
+}
+
+int cmode_key_is_ok(Client *client, Channel *channel, char mode, const char *param, int type, int what)
+{
+ if ((type == EXCHK_ACCESS) || (type == EXCHK_ACCESS_ERR))
+ {
+ /* Permitted for +hoaq */
+ if (IsUser(client) && check_channel_access(client, channel, "hoaq"))
+ return EX_ALLOW;
+ return EX_DENY;
+ } else
+ if (type == EXCHK_PARAM)
+ {
+ if (!is_valid_key(param))
+ {
+ sendnumeric(client, ERR_INVALIDMODEPARAM,
+ channel->name, 'k', "*", "Channel key contains forbidden characters or is too long");
+ return EX_DENY;
+ }
+ return EX_ALLOW;
+ }
+
+ /* fallthrough -- should not be used */
+ return EX_DENY;
+}
+
+void *cmode_key_put_param(void *k_in, const char *param)
+{
+ ChannelKey *fld = (ChannelKey *)k_in;
+
+ if (!fld)
+ fld = safe_alloc(sizeof(ChannelKey));
+
+ transform_channel_key(param, fld->key, sizeof(fld->key));
+
+ return fld;
+}
+
+const char *cmode_key_get_param(void *r_in)
+{
+ ChannelKey *r = (ChannelKey *)r_in;
+ static char retbuf[KEYLEN+1];
+
+ if (!r)
+ return NULL;
+
+ strlcpy(retbuf, r->key, sizeof(retbuf));
+ return retbuf;
+}
+
+const char *cmode_key_conv_param(const char *param, Client *client, Channel *channel)
+{
+ static char retbuf[KEYLEN+1];
+
+ transform_channel_key(param, retbuf, sizeof(retbuf));
+
+ if (!*retbuf)
+ return NULL; /* entire key was invalid */
+
+ return retbuf;
+}
+
+void cmode_key_free_param(void *r)
+{
+ safe_free(r);
+}
+
+void *cmode_key_dup_struct(void *r_in)
+{
+ ChannelKey *r = (ChannelKey *)r_in;
+ ChannelKey *w = safe_alloc(sizeof(ChannelKey));
+
+ memcpy(w, r, sizeof(ChannelKey));
+
+ return (void *)w;
+}
+
+int cmode_key_sjoin_check(Channel *channel, void *ourx, void *theirx)
+{
+ ChannelKey *our = (ChannelKey *)ourx;
+ ChannelKey *their = (ChannelKey *)theirx;
+ int i;
+ int r;
+
+ r = strcmp(our->key, their->key);
+ if (r == 0)
+ return EXSJ_SAME;
+ else if (r > 0)
+ return EXSJ_WEWON;
+ else
+ return EXSJ_THEYWON;
+}
+
+int valid_key_char(char c)
+{
+ if (strchr(" :,", c))
+ return 0;
+ if (c <= 32)
+ return 0;
+ return 1;
+}
+
+#define BADKEYCHARS " :,"
+int is_valid_key(const char *key)
+{
+ const char *p;
+
+ if (strlen(key) > KEYLEN)
+ return 0;
+ for (p = key; *p; p++)
+ if (!valid_key_char(*p))
+ return 0;
+ return 1;
+}
+
+void transform_channel_key(const char *i, char *o, int n)
+{
+ n--; /* reserve one for final nul byte */
+
+ for (; *i; i++)
+ {
+ if (!valid_key_char(*i))
+ break;
+ if (n <= 0)
+ break;
+ *o++ = *i;
+ n--;
+ }
+ *o = '\0';
+}
diff --git a/src/modules/chanmodes/limit.c b/src/modules/chanmodes/limit.c
new file mode 100644
index 0000000..761d1ea
--- /dev/null
+++ b/src/modules/chanmodes/limit.c
@@ -0,0 +1,198 @@
+/*
+ * Channel Mode +l
+ * (C) Copyright 2021 Syzop and the UnrealIRCd team
+ *
+ * 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.
+ */
+
+#include "unrealircd.h"
+
+ModuleHeader MOD_HEADER
+ = {
+ "chanmodes/limit",
+ "6.0",
+ "Channel Mode +l",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+ };
+
+typedef struct ChannelLimit ChannelLimit;
+struct ChannelLimit {
+ int limit;
+};
+
+/* Global variables */
+ModDataInfo *mdlimit = NULL;
+Cmode_t EXTMODE_LIMIT = 0L;
+
+#define IsLimit(x) ((x)->mode.mode & EXTMODE_LIMIT)
+
+/* Just for buffers, nothing else */
+#define LIMITLEN 32
+
+/* Forward declarations */
+int limit_can_join(Client *client, Channel *channel, const char *key, char **errmsg);
+int cmode_limit_is_ok(Client *client, Channel *channel, char mode, const char *para, int type, int what);
+void *cmode_limit_put_param(void *r_in, const char *param);
+const char *cmode_limit_get_param(void *r_in);
+const char *cmode_limit_conv_param(const char *param_in, Client *client, Channel *channel);
+void cmode_limit_free_param(void *r);
+void *cmode_limit_dup_struct(void *r_in);
+int cmode_limit_sjoin_check(Channel *channel, void *ourx, void *theirx);
+int transform_channel_limit(const char *param);
+
+MOD_INIT()
+{
+ CmodeInfo creq;
+ ModDataInfo mreq;
+
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ memset(&creq, 0, sizeof(creq));
+ creq.paracount = 1;
+ creq.is_ok = cmode_limit_is_ok;
+ creq.letter = 'l';
+ creq.put_param = cmode_limit_put_param;
+ creq.get_param = cmode_limit_get_param;
+ creq.conv_param = cmode_limit_conv_param;
+ creq.free_param = cmode_limit_free_param;
+ creq.dup_struct = cmode_limit_dup_struct;
+ creq.sjoin_check = cmode_limit_sjoin_check;
+ CmodeAdd(modinfo->handle, creq, &EXTMODE_LIMIT);
+
+ HookAdd(modinfo->handle, HOOKTYPE_CAN_JOIN, 0, limit_can_join);
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ return MOD_SUCCESS;
+}
+
+/** Can the user join the channel? */
+int limit_can_join(Client *client, Channel *channel, const char *key, char **errmsg)
+{
+ ChannelLimit *r = (ChannelLimit *)GETPARASTRUCT(channel, 'l');
+
+ /* Is the channel +l? */
+ if (r && r->limit && (channel->users >= r->limit))
+ {
+ Hook *h;
+ for (h = Hooks[HOOKTYPE_CAN_JOIN_LIMITEXCEEDED]; h; h = h->next)
+ {
+ int i = (*(h->func.intfunc))(client,channel,key,errmsg);
+ if (i != 0)
+ return i;
+ }
+ *errmsg = STR_ERR_CHANNELISFULL;
+ return ERR_CHANNELISFULL;
+ }
+
+ return 0;
+}
+
+int cmode_limit_is_ok(Client *client, Channel *channel, char mode, const char *param, int type, int what)
+{
+ if ((type == EXCHK_ACCESS) || (type == EXCHK_ACCESS_ERR))
+ {
+ /* Permitted for +hoaq */
+ if (IsUser(client) && check_channel_access(client, channel, "hoaq"))
+ return EX_ALLOW;
+ return EX_DENY;
+ } else
+ if (type == EXCHK_PARAM)
+ {
+ /* Actually any value is valid, we just morph it */
+ return EX_ALLOW;
+ }
+
+ /* fallthrough -- should not be used */
+ return EX_DENY;
+}
+
+void *cmode_limit_put_param(void *k_in, const char *param)
+{
+ ChannelLimit *fld = (ChannelLimit *)k_in;
+
+ if (!fld)
+ fld = safe_alloc(sizeof(ChannelLimit));
+
+ fld->limit = transform_channel_limit(param);
+
+ return fld;
+}
+
+const char *cmode_limit_get_param(void *r_in)
+{
+ ChannelLimit *r = (ChannelLimit *)r_in;
+ static char retbuf[32];
+
+ if (!r)
+ return NULL;
+
+ snprintf(retbuf, sizeof(retbuf), "%d", r->limit);
+ return retbuf;
+}
+
+const char *cmode_limit_conv_param(const char *param, Client *client, Channel *channel)
+{
+ static char retbuf[32];
+ int v = transform_channel_limit(param);
+ snprintf(retbuf, sizeof(retbuf), "%d", v);
+ return retbuf;
+}
+
+void cmode_limit_free_param(void *r)
+{
+ safe_free(r);
+}
+
+void *cmode_limit_dup_struct(void *r_in)
+{
+ ChannelLimit *r = (ChannelLimit *)r_in;
+ ChannelLimit *w = safe_alloc(sizeof(ChannelLimit));
+
+ memcpy(w, r, sizeof(ChannelLimit));
+
+ return (void *)w;
+}
+
+int cmode_limit_sjoin_check(Channel *channel, void *ourx, void *theirx)
+{
+ ChannelLimit *our = (ChannelLimit *)ourx;
+ ChannelLimit *their = (ChannelLimit *)theirx;
+
+ if (our->limit == their->limit)
+ return EXSJ_SAME;
+ else if (our->limit > their->limit)
+ return EXSJ_WEWON;
+ else
+ return EXSJ_THEYWON;
+}
+
+int transform_channel_limit(const char *param)
+{
+ int v = atoi(param);
+ if (v <= 0)
+ v = 1; /* setting +l with a negative number makes no sense */
+ if (v > 1000000)
+ v = 1000000; /* some kind of limit, 1 million (mrah...) */
+ return v;
+}
diff --git a/src/modules/chanmodes/link.c b/src/modules/chanmodes/link.c
index 3be4a43..9a5b5b8 100644
--- a/src/modules/chanmodes/link.c
+++ b/src/modules/chanmodes/link.c
@@ -26,7 +26,7 @@ ModuleHeader MOD_HEADER = {
"5.0",
"Channel Mode +L",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
Cmode_t EXTMODE_LINK = 0L;
@@ -39,26 +39,25 @@ typedef enum {
LINKTYPE_BAN = 1, // +b
LINKTYPE_INVITE = 2, // +i
LINKTYPE_OPER = 3, // +O
- LINKTYPE_SSL = 4, // +z
+ LINKTYPE_SECURE = 4, // +z
LINKTYPE_REG = 5, // +R
LINKTYPE_LIMIT = 6, // +l
LINKTYPE_BADKEY = 7, // +k
} linkType;
-int cmodeL_is_ok(Client *client, Channel *channel, char mode, char *para, int type, int what);
-void *cmodeL_put_param(void *r_in, char *param);
-char *cmodeL_get_param(void *r_in);
-char *cmodeL_conv_param(char *param_in, Client *client, Channel *channel);
+int cmodeL_is_ok(Client *client, Channel *channel, char mode, const char *para, int type, int what);
+void *cmodeL_put_param(void *r_in, const char *param);
+const char *cmodeL_get_param(void *r_in);
+const char *cmodeL_conv_param(const char *param_in, Client *client, Channel *channel);
void cmodeL_free_param(void *r);
void *cmodeL_dup_struct(void *r_in);
int cmodeL_sjoin_check(Channel *channel, void *ourx, void *theirx);
-int extban_link_syntax(Client *client, int checkt, char *reason);
-int extban_link_is_ok(Client *client, Channel *channel, char *param, int checkt, int what, int what2);
-char *extban_link_conv_param(char *param);
-int extban_link_is_banned(Client *client, Channel *channel, char *ban, int type, char **msg, char **errmsg);
-int link_doforward(Client *client, Channel *channel, char *linked, linkType linktype);
-int link_pre_localjoin_cb(Client *client, Channel *channel, char *parv[]);
+int extban_link_syntax(Client *client, int checkt, const char *reason);
+int extban_link_is_ok(BanContext *b);
+const char *extban_link_conv_param(BanContext *b, Extban *extban);
+int link_doforward(Client *client, Channel *channel, const char *linked, linkType linktype);
+int link_pre_localjoin_cb(Client *client, Channel *channel, const char *key);
MOD_INIT()
{
@@ -70,7 +69,7 @@ MOD_INIT()
memset(&req, 0, sizeof(req));
req.paracount = 1;
req.is_ok = cmodeL_is_ok;
- req.flag = 'L';
+ req.letter = 'L';
req.unset_with_param = 1; /* Oh yeah, we are special! */
req.put_param = cmodeL_put_param;
req.get_param = cmodeL_get_param;
@@ -81,10 +80,10 @@ MOD_INIT()
CmodeAdd(modinfo->handle, req, &EXTMODE_LINK);
memset(&req_extban, 0, sizeof(ExtbanInfo));
- req_extban.flag = 'f';
+ req_extban.letter = 'f';
+ req_extban.name = "forward";
req_extban.is_ok = extban_link_is_ok;
req_extban.conv_param = extban_link_conv_param;
- req_extban.is_banned = extban_link_is_banned;
req_extban.options = EXTBOPT_ACTMODIFIER;
if (!ExtbanAdd(modinfo->handle, req_extban))
{
@@ -107,14 +106,14 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
-int cmodeL_is_ok(Client *client, Channel *channel, char mode, char *para, int type, int what)
+int cmodeL_is_ok(Client *client, Channel *channel, char mode, const char *para, int type, int what)
{
if ((type == EXCHK_ACCESS) || (type == EXCHK_ACCESS_ERR))
{
- if (IsUser(client) && is_chan_op(client, channel))
+ if (IsUser(client) && check_channel_access(client, channel, "oaq"))
return EX_ALLOW;
if (type == EXCHK_ACCESS_ERR) /* can only be due to being halfop */
- sendnumeric(client, ERR_NOTFORHALFOPS, 'H');
+ sendnumeric(client, ERR_NOTFORHALFOPS, 'L');
return EX_DENY;
} else
if (type == EXCHK_PARAM)
@@ -129,7 +128,7 @@ int cmodeL_is_ok(Client *client, Channel *channel, char mode, char *para, int ty
return EX_DENY;
}
- if (find_channel(para, NULL) == channel)
+ if (find_channel(para) == channel)
{
if (MyUser(client))
sendnumeric(client, ERR_CANNOTCHANGECHANMODE, 'L',
@@ -143,7 +142,7 @@ int cmodeL_is_ok(Client *client, Channel *channel, char mode, char *para, int ty
return EX_DENY;
}
-void *cmodeL_put_param(void *r_in, char *param)
+void *cmodeL_put_param(void *r_in, const char *param)
{
aModeLEntry *r = (aModeLEntry *)r_in;
@@ -156,7 +155,7 @@ void *cmodeL_put_param(void *r_in, char *param)
return (void *)r;
}
-char *cmodeL_get_param(void *r_in)
+const char *cmodeL_get_param(void *r_in)
{
aModeLEntry *r = (aModeLEntry *)r_in;
static char retbuf[CHANNELLEN+1];
@@ -171,10 +170,8 @@ char *cmodeL_get_param(void *r_in)
/** Convert parameter to something proper.
* NOTE: client may be NULL
*/
-char *cmodeL_conv_param(char *param, Client *client, Channel *channel)
+const char *cmodeL_conv_param(const char *param, Client *client, Channel *channel)
{
- char *p;
-
if (!valid_channelname(param))
return NULL;
@@ -207,7 +204,7 @@ int cmodeL_sjoin_check(Channel *channel, void *ourx, void *theirx)
return EXSJ_THEYWON;
}
-int extban_link_syntax(Client *client, int checkt, char *reason)
+int extban_link_syntax(Client *client, int checkt, const char *reason)
{
if (MyUser(client) && (checkt == EXBCHK_PARAM))
{
@@ -222,52 +219,50 @@ int extban_link_syntax(Client *client, int checkt, char *reason)
return 0; // Reject ban
}
-int extban_link_is_ok(Client *client, Channel *channel, char *param, int checkt, int what, int what2)
+int extban_link_is_ok(BanContext *b)
{
- char paramtmp[MAX_EB_LEN + 1];
- char tmpmask[MAX_EB_LEN + 1];
+ static char paramtmp[MAX_EB_LEN + 1];
char *matchby; // Matching method, such as 'n!u@h'
char *chan;
// Always permit deletion
- if (what == MODE_DEL)
+ if (b->what == MODE_DEL)
return 1;
- if (what2 != EXBTYPE_BAN)
+ if (b->ban_type != EXBTYPE_BAN)
{
- if (checkt == EXBCHK_PARAM)
- sendnotice(client, "Ban type ~f only works with bans (+b) and not with exceptions or invex (+e/+I)");
+ if (b->is_ok_check == EXBCHK_PARAM)
+ sendnotice(b->client, "Ban type ~f only works with bans (+b) and not with exceptions or invex (+e/+I)");
return 0; // Reject
}
- strlcpy(paramtmp, param + 3, sizeof(paramtmp)); // Work on a size-truncated copy
+ strlcpy(paramtmp, b->banstr, sizeof(paramtmp)); // Work on a size-truncated copy
chan = paramtmp;
matchby = strchr(paramtmp, ':');
if (!matchby || !matchby[1])
- return extban_link_syntax(client, checkt, "Invalid syntax");
+ return extban_link_syntax(b->client, b->is_ok_check, "Invalid syntax");
*matchby++ = '\0';
- if (*chan != '#' || strchr(param, ','))
- return extban_link_syntax(client, checkt, "Invalid channel");
+ if (*chan != '#' || strchr(b->banstr, ','))
+ return extban_link_syntax(b->client, b->is_ok_check, "Invalid channel");
- // Possibly stack multiple extbans, this is a little convoluted due to extban API limitations
- snprintf(tmpmask, sizeof(tmpmask), "~?:%s", matchby);
- if (extban_is_ok_nuh_extban(client, channel, tmpmask, checkt, what, what2) == 0)
- return extban_link_syntax(client, checkt, "Invalid matcher");
+ b->banstr = matchby;
+ if (extban_is_ok_nuh_extban(b) == 0)
+ return extban_link_syntax(b->client, b->is_ok_check, "Invalid matcher");
return 1; // Is ok
}
-char *extban_link_conv_param(char *param)
+const char *extban_link_conv_param(BanContext *b, Extban *extban)
{
static char retbuf[MAX_EB_LEN + 1];
char paramtmp[MAX_EB_LEN + 1];
char tmpmask[MAX_EB_LEN + 1];
char *matchby; // Matching method, such as 'n!u@h'
- char *newmask; // Cleaned matching method, such as 'n!u@h'
+ const char *newmask; // Cleaned matching method, such as 'n!u@h'
char *chan;
- strlcpy(paramtmp, param + 3, sizeof(paramtmp)); // Work on a size-truncated copy
+ strlcpy(paramtmp, b->banstr, sizeof(paramtmp)); // Work on a size-truncated copy
chan = paramtmp;
matchby = strchr(paramtmp, ':');
if (!matchby || !matchby[1])
@@ -277,26 +272,20 @@ char *extban_link_conv_param(char *param)
if (!valid_channelname(chan))
return NULL;
- // Possibly stack multiple extbans, this is a little convoluted due to extban API limitations
- snprintf(tmpmask, sizeof(tmpmask), "~?:%s", matchby);
- newmask = extban_conv_param_nuh_or_extban(tmpmask);
- if (!newmask || (strlen(newmask) <= 3))
+ b->banstr = matchby;
+ newmask = extban_conv_param_nuh_or_extban(b, extban);
+ if (BadPtr(newmask))
return NULL;
- snprintf(retbuf, sizeof(retbuf), "~f:%s:%s", chan, newmask + 3);
+ snprintf(retbuf, sizeof(retbuf), "%s:%s", chan, newmask);
return retbuf;
}
-int extban_link_is_banned(Client *client, Channel *channel, char *ban, int type, char **msg, char **errmsg)
-{
- // We don't actually ban here because we have to extract the channel name in PRE_LOCAL_JOIN anyways
- return 0;
-}
-
-int link_doforward(Client *client, Channel *channel, char *linked, linkType type)
+int link_doforward(Client *client, Channel *channel, const char *linked, linkType type)
{
+ char linked_channel_buffer[CHANNELLEN+1];
char desc[64];
- char *parv[3];
+ const char *parv[3];
switch (type)
{
@@ -312,8 +301,8 @@ int link_doforward(Client *client, Channel *channel, char *linked, linkType type
strncpy(desc, "channel is oper only", sizeof(desc));
break;
- case LINKTYPE_SSL:
- strncpy(desc, "channel requires SSL", sizeof(desc));
+ case LINKTYPE_SECURE:
+ strncpy(desc, "channel requires a secure connection", sizeof(desc));
break;
case LINKTYPE_REG:
@@ -335,23 +324,24 @@ int link_doforward(Client *client, Channel *channel, char *linked, linkType type
sendto_one(client, NULL,
":%s %d %s %s %s :[Link] Cannot join channel %s (%s) -- transferring you to %s",
- me.name, ERR_LINKCHANNEL, client->name, channel->chname, linked,
- channel->chname, desc, linked);
+ me.name, ERR_LINKCHANNEL, client->name, channel->name, linked,
+ channel->name, desc, linked);
+
+ strlcpy(linked_channel_buffer, linked, sizeof(linked_channel_buffer));
parv[0] = client->name;
- parv[1] = linked;
+ parv[1] = linked_channel_buffer;
parv[2] = NULL;
+
do_join(client, 2, parv);
+
return HOOK_DENY; // Original channel join = ignored
}
-int link_pre_localjoin_cb(Client *client, Channel *channel, char *parv[])
+int link_pre_localjoin_cb(Client *client, Channel *channel, const char *key)
{
- char *linked;
+ const char *linked;
int canjoin;
- Ban *ban;
- char bantmp[MAX_EB_LEN + 1];
- char *banchan;
- char *banmask;
+ char *error = NULL;
// User might already be on this channel, let's also exclude any possible services bots early
if (IsULine(client) || find_membership_link(client->user->channel, channel))
@@ -361,12 +351,26 @@ int link_pre_localjoin_cb(Client *client, Channel *channel, char *parv[])
// only /INVITE from chanop bypasses:
if (!is_invited(client, channel))
{
- for(ban = channel->banlist; ban; ban = ban->next)
+ Ban *ban;
+ BanContext *b = safe_alloc(sizeof(BanContext));
+ char bantmp[MAX_EB_LEN + 1];
+ char *banchan;
+ char *banmask;
+
+ b->client = client;
+ b->channel = channel;
+ b->ban_check_types = BANCHK_JOIN;
+
+ for (ban = channel->banlist; ban; ban = ban->next)
{
if (!strncmp(ban->banstr, "~f:", 3))
{
strlcpy(bantmp, ban->banstr + 3, sizeof(bantmp));
} else
+ if (!strncmp(ban->banstr, "~forward:", 9))
+ {
+ strlcpy(bantmp, ban->banstr + 9, sizeof(bantmp));
+ } else
if (!strncmp(ban->banstr, "~t:", 3))
{
/* A timed ban, but is it for us? Need to parse a little:
@@ -376,6 +380,28 @@ int link_pre_localjoin_cb(Client *client, Channel *channel, char *parv[])
if (p && !strncmp(p, ":~f:", 4))
{
strlcpy(bantmp, p + 4, sizeof(bantmp));
+ } else
+ if (p && !strncmp(p, ":~forward:", 10))
+ {
+ strlcpy(bantmp, p + 10, sizeof(bantmp));
+ } else {
+ /* Not for us - some other ~t ban */
+ continue;
+ }
+ } else
+ if (!strncmp(ban->banstr, "~time:", 6))
+ {
+ /* A timed ban, but is it for us? Need to parse a little:
+ * ~t:dddd:~f:...
+ */
+ char *p = strchr(ban->banstr + 6, ':');
+ if (p && !strncmp(p, ":~f:", 4))
+ {
+ strlcpy(bantmp, p + 4, sizeof(bantmp));
+ } else
+ if (p && !strncmp(p, ":~forward:", 10))
+ {
+ strlcpy(bantmp, p + 10, sizeof(bantmp));
} else {
/* Not for us - some other ~t ban */
continue;
@@ -391,26 +417,32 @@ int link_pre_localjoin_cb(Client *client, Channel *channel, char *parv[])
continue;
*banmask++ = '\0';
- if (ban_check_mask(client, channel, banmask, BANCHK_JOIN, NULL, NULL, 0))
+ b->banstr = banmask;
+ if (ban_check_mask(b))
+ {
+ safe_free(b);
return link_doforward(client, channel, banchan, LINKTYPE_BAN);
+ }
}
+
+ safe_free(b);
}
// Either +L is not set, or it is set but the parameter isn't stored somehow
- if (!(channel->mode.extmode & EXTMODE_LINK) || !(linked = cm_getparameter(channel, 'L')))
+ if (!(channel->mode.mode & EXTMODE_LINK) || !(linked = cm_getparameter(channel, 'L')))
return HOOK_CONTINUE;
// can_join() actually returns 0 if we *can* join a channel, so we don't need to bother checking any further conditions
- if (!(canjoin = can_join(client, channel, parv[2], parv)))
+ if (!(canjoin = can_join(client, channel, key, &error)))
return HOOK_CONTINUE;
// Oper only channel
if (has_channel_mode(channel, 'O') && !IsOper(client))
return link_doforward(client, channel, linked, LINKTYPE_OPER);
- // SSL/TLS connected users only
+ // TLS connected users only
if (has_channel_mode(channel, 'z') && !IsSecureConnect(client))
- return link_doforward(client, channel, linked, LINKTYPE_SSL);
+ return link_doforward(client, channel, linked, LINKTYPE_SECURE);
// Registered/identified users only
if (has_channel_mode(channel, 'R') && !IsRegNick(client))
diff --git a/src/modules/chanmodes/moderated.c b/src/modules/chanmodes/moderated.c
new file mode 100644
index 0000000..6a00d4a
--- /dev/null
+++ b/src/modules/chanmodes/moderated.c
@@ -0,0 +1,117 @@
+/*
+ * Channel Mode +m
+ * (C) Copyright 2021 Syzop and the UnrealIRCd team
+ *
+ * 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.
+ */
+
+#include "unrealircd.h"
+
+
+ModuleHeader MOD_HEADER
+ = {
+ "chanmodes/moderated",
+ "6.0",
+ "Channel Mode +m",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+ };
+
+/* Global variables */
+Cmode_t EXTCMODE_MODERATED;
+
+/* Forward declarations */
+int moderated_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype);
+const char *moderated_pre_local_part(Client *client, Channel *channel, const char *text);
+int moderated_can_set_topic(Client *client, Channel *channel, const char *topic, const char **errmsg);
+
+/* Macros */
+#define IsModerated(channel) (channel->mode.mode & EXTCMODE_MODERATED)
+
+MOD_INIT()
+{
+ CmodeInfo req;
+
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ memset(&req, 0, sizeof(req));
+ req.paracount = 0;
+ req.letter = 'm';
+ req.is_ok = extcmode_default_requirehalfop;
+ CmodeAdd(modinfo->handle, req, &EXTCMODE_MODERATED);
+
+ HookAdd(modinfo->handle, HOOKTYPE_CAN_SEND_TO_CHANNEL, 0, moderated_can_send_to_channel);
+ HookAddConstString(modinfo->handle, HOOKTYPE_PRE_LOCAL_PART, 0, moderated_pre_local_part);
+ HookAdd(modinfo->handle, HOOKTYPE_CAN_SET_TOPIC, 0, moderated_can_set_topic);
+
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ return MOD_SUCCESS;
+}
+
+int moderated_can_send_to_channel(Client *client, Channel *channel, Membership *m, const char **msg, const char **errmsg, SendType sendtype)
+{
+ if (IsModerated(channel) && (!m || !check_channel_access_membership(m, "vhoaq")) &&
+ !op_can_override("channel:override:message:moderated",client,channel,NULL))
+ {
+ Hook *h;
+ for (h = Hooks[HOOKTYPE_CAN_BYPASS_CHANNEL_MESSAGE_RESTRICTION]; h; h = h->next)
+ {
+ int i = (*(h->func.intfunc))(client, channel, BYPASS_CHANMSG_MODERATED);
+ if (i == HOOK_ALLOW)
+ return HOOK_CONTINUE; /* bypass +m restriction */
+ if (i != HOOK_CONTINUE)
+ break;
+ }
+
+ *errmsg = "You need voice (+v)";
+ return HOOK_DENY; /* BLOCK message */
+ }
+
+ return HOOK_CONTINUE;
+}
+
+/** Remove PART reason too if the channel is +m, -t, and user not +vhoaq */
+const char *moderated_pre_local_part(Client *client, Channel *channel, const char *text)
+{
+ if (IsModerated(channel) && !check_channel_access(client, channel, "v") && !check_channel_access(client, channel, "h"))
+ return NULL;
+ return text;
+}
+
+int moderated_can_set_topic(Client *client, Channel *channel, const char *topic, const char **errmsg)
+{
+ static char errmsg_buf[NICKLEN+256];
+
+ /* Channel is +m but user is not +vhoaq: reject the topic change */
+ if (has_channel_mode(channel, 'm') && !check_channel_access(client, channel, "vhoaq"))
+ {
+ char buf[512];
+ snprintf(buf, sizeof(buf), "Voice (+v) or higher is required in order to change the topic on %s (channel is +m)", channel->name);
+ buildnumeric(errmsg_buf, sizeof(errmsg_buf), client, ERR_CANNOTDOCOMMAND, "TOPIC", buf);
+ *errmsg = errmsg_buf;
+ return EX_DENY;
+ }
+
+ return EX_ALLOW;
+}
diff --git a/src/modules/chanmodes/nocolor.c b/src/modules/chanmodes/nocolor.c
index 6f2dab5..9544368 100644
--- a/src/modules/chanmodes/nocolor.c
+++ b/src/modules/chanmodes/nocolor.c
@@ -27,16 +27,16 @@ ModuleHeader MOD_HEADER
"4.2",
"Channel Mode +c",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
Cmode_t EXTCMODE_NOCOLOR;
-#define IsNoColor(channel) (channel->mode.extmode & EXTCMODE_NOCOLOR)
+#define IsNoColor(channel) (channel->mode.mode & EXTCMODE_NOCOLOR)
-int nocolor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
-char *nocolor_prelocalpart(Client *client, Channel *channel, char *comment);
-char *nocolor_prelocalquit(Client *client, char *comment);
+int nocolor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype);
+const char *nocolor_prelocalpart(Client *client, Channel *channel, const char *comment);
+const char *nocolor_prelocalquit(Client *client, const char *comment);
MOD_TEST()
{
@@ -50,14 +50,14 @@ CmodeInfo req;
/* Channel mode */
memset(&req, 0, sizeof(req));
req.paracount = 0;
- req.flag = 'c';
+ req.letter = 'c';
req.is_ok = extcmode_default_requirechop;
CmodeAdd(modinfo->handle, req, &EXTCMODE_NOCOLOR);
HookAdd(modinfo->handle, HOOKTYPE_CAN_SEND_TO_CHANNEL, 0, nocolor_can_send_to_channel);
- HookAddPChar(modinfo->handle, HOOKTYPE_PRE_LOCAL_PART, 0, nocolor_prelocalpart);
- HookAddPChar(modinfo->handle, HOOKTYPE_PRE_LOCAL_QUIT_CHAN, 0, nocolor_prelocalpart);
- HookAddPChar(modinfo->handle, HOOKTYPE_PRE_LOCAL_QUIT, 0, nocolor_prelocalquit);
+ HookAddConstString(modinfo->handle, HOOKTYPE_PRE_LOCAL_PART, 0, nocolor_prelocalpart);
+ HookAddConstString(modinfo->handle, HOOKTYPE_PRE_LOCAL_QUIT_CHAN, 0, nocolor_prelocalpart);
+ HookAddConstString(modinfo->handle, HOOKTYPE_PRE_LOCAL_QUIT, 0, nocolor_prelocalquit);
MARK_AS_OFFICIAL_MODULE(modinfo);
return MOD_SUCCESS;
@@ -73,7 +73,7 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
-static int IsUsingColor(char *s)
+static int IsUsingColor(const char *s)
{
if (!s)
return 0;
@@ -85,7 +85,7 @@ static int IsUsingColor(char *s)
return 0;
}
-int nocolor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
+int nocolor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype)
{
Hook *h;
int i;
@@ -108,7 +108,7 @@ int nocolor_can_send_to_channel(Client *client, Channel *channel, Membership *lp
return HOOK_CONTINUE;
}
-char *nocolor_prelocalpart(Client *client, Channel *channel, char *comment)
+const char *nocolor_prelocalpart(Client *client, Channel *channel, const char *comment)
{
if (!comment)
return NULL;
@@ -130,7 +130,7 @@ static int IsAnyChannelNoColor(Client *client)
return 0;
}
-char *nocolor_prelocalquit(Client *client, char *comment)
+const char *nocolor_prelocalquit(Client *client, const char *comment)
{
if (!comment)
return NULL;
diff --git a/src/modules/chanmodes/noctcp.c b/src/modules/chanmodes/noctcp.c
index 058f20a..3ce69db 100644
--- a/src/modules/chanmodes/noctcp.c
+++ b/src/modules/chanmodes/noctcp.c
@@ -27,14 +27,14 @@ ModuleHeader MOD_HEADER
"4.2",
"Channel Mode +C",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
Cmode_t EXTCMODE_NOCTCP;
-#define IsNoCTCP(channel) (channel->mode.extmode & EXTCMODE_NOCTCP)
+#define IsNoCTCP(channel) (channel->mode.mode & EXTCMODE_NOCTCP)
-int noctcp_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
+int noctcp_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype);
MOD_TEST()
{
@@ -47,7 +47,7 @@ CmodeInfo req;
memset(&req, 0, sizeof(req));
req.paracount = 0;
- req.flag = 'C';
+ req.letter = 'C';
req.is_ok = extcmode_default_requirehalfop;
CmodeAdd(modinfo->handle, req, &EXTCMODE_NOCTCP);
@@ -67,7 +67,7 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
-static int IsACTCP(char *s)
+static int IsACTCP(const char *s)
{
if (!s)
return 0;
@@ -78,7 +78,7 @@ static int IsACTCP(char *s)
return 0;
}
-int noctcp_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
+int noctcp_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype)
{
if (IsNoCTCP(channel) && IsACTCP(*msg))
{
diff --git a/src/modules/chanmodes/noexternalmsgs.c b/src/modules/chanmodes/noexternalmsgs.c
new file mode 100644
index 0000000..1de63ad
--- /dev/null
+++ b/src/modules/chanmodes/noexternalmsgs.c
@@ -0,0 +1,89 @@
+/*
+ * Channel Mode +n
+ * (C) Copyright 2021 Syzop and the UnrealIRCd team
+ *
+ * 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.
+ */
+
+#include "unrealircd.h"
+
+
+ModuleHeader MOD_HEADER
+ = {
+ "chanmodes/noexternalmsgs",
+ "6.0",
+ "Channel Mode +n",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+ };
+
+Cmode_t EXTCMODE_NO_EXTERNAL_MESSAGES;
+
+#define IsNoExternalMessages(channel) (channel->mode.mode & EXTCMODE_NO_EXTERNAL_MESSAGES)
+
+int noexternalmsgs_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype);
+
+MOD_INIT()
+{
+ CmodeInfo req;
+
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ memset(&req, 0, sizeof(req));
+ req.paracount = 0;
+ req.letter = 'n';
+ req.is_ok = extcmode_default_requirehalfop;
+ CmodeAdd(modinfo->handle, req, &EXTCMODE_NO_EXTERNAL_MESSAGES);
+
+ HookAdd(modinfo->handle, HOOKTYPE_CAN_SEND_TO_CHANNEL, 0, noexternalmsgs_can_send_to_channel);
+
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ return MOD_SUCCESS;
+}
+
+int noexternalmsgs_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype)
+{
+ if (IsNoExternalMessages(channel) && !IsMember(client,channel))
+ {
+ /* Channel does not accept external messages (+n).
+ * Reject, unless HOOKTYPE_CAN_BYPASS_NO_EXTERNAL_MSGS tells otherwise.
+ */
+ Hook *h;
+ int i;
+
+ for (h = Hooks[HOOKTYPE_CAN_BYPASS_CHANNEL_MESSAGE_RESTRICTION]; h; h = h->next)
+ {
+ i = (*(h->func.intfunc))(client, channel, BYPASS_CHANMSG_EXTERNAL);
+ if (i == HOOK_ALLOW)
+ return HOOK_CONTINUE; /* bypass +n restriction */
+ if (i != HOOK_CONTINUE)
+ break;
+ }
+
+ *errmsg = "No external channel messages";
+ return HOOK_DENY; /* BLOCK message */
+ }
+
+ return HOOK_CONTINUE;
+}
diff --git a/src/modules/chanmodes/noinvite.c b/src/modules/chanmodes/noinvite.c
index d6874aa..2d81825 100644
--- a/src/modules/chanmodes/noinvite.c
+++ b/src/modules/chanmodes/noinvite.c
@@ -27,14 +27,14 @@ ModuleHeader MOD_HEADER
"4.2",
"Channel Mode +V",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
Cmode_t EXTCMODE_NOINVITE;
-#define IsNoInvite(channel) (channel->mode.extmode & EXTCMODE_NOINVITE)
+#define IsNoInvite(channel) (channel->mode.mode & EXTCMODE_NOINVITE)
-int noinvite_pre_knock(Client *client, Channel *channel);
+int noinvite_pre_knock(Client *client, Channel *channel, const char **reason);
int noinvite_pre_invite(Client *client, Client *target, Channel *channel, int *override);
MOD_TEST()
@@ -48,7 +48,7 @@ MOD_INIT()
memset(&req, 0, sizeof(req));
req.paracount = 0;
- req.flag = 'V';
+ req.letter = 'V';
req.is_ok = extcmode_default_requirechop;
CmodeAdd(modinfo->handle, req, &EXTCMODE_NOINVITE);
@@ -70,12 +70,12 @@ MOD_UNLOAD()
}
-int noinvite_pre_knock(Client *client, Channel *channel)
+int noinvite_pre_knock(Client *client, Channel *channel, const char **reason)
{
if (MyUser(client) && IsNoInvite(channel))
{
- sendnumeric(client, ERR_CANNOTKNOCK,
- channel->chname, "The channel does not allow invites (+V)");
+ sendnumeric(client, ERR_CANNOTKNOCK, channel->name,
+ "The channel does not allow invites (+V)");
return HOOK_DENY;
}
@@ -90,7 +90,7 @@ int noinvite_pre_invite(Client *client, Client *target, Channel *channel, int *o
{
*override = 1;
} else {
- sendnumeric(client, ERR_NOINVITE, channel->chname);
+ sendnumeric(client, ERR_NOINVITE, channel->name);
return HOOK_DENY;
}
}
diff --git a/src/modules/chanmodes/nokick.c b/src/modules/chanmodes/nokick.c
index 899d7c9..56cb115 100644
--- a/src/modules/chanmodes/nokick.c
+++ b/src/modules/chanmodes/nokick.c
@@ -26,14 +26,14 @@ ModuleHeader MOD_HEADER
"4.2",
"Channel Mode +Q",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
Cmode_t EXTCMODE_NOKICK;
-#define IsNoKick(channel) (channel->mode.extmode & EXTCMODE_NOKICK)
+#define IsNoKick(channel) (channel->mode.mode & EXTCMODE_NOKICK)
-int nokick_check (Client *client, Client *who, Channel *channel, char *comment, long client_flags, long who_flags, char **reject_reason);
+int nokick_check (Client *client, Client *target, Channel *channel, const char *comment, const char *client_member_modes, const char *target_member_modes, const char **reject_reason);
MOD_TEST()
{
@@ -46,7 +46,7 @@ MOD_INIT()
memset(&req, 0, sizeof(req));
req.paracount = 0;
- req.flag = 'Q';
+ req.letter = 'Q';
req.is_ok = extcmode_default_requirechop;
CmodeAdd(modinfo->handle, req, &EXTCMODE_NOKICK);
@@ -67,7 +67,7 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
-int nokick_check (Client *client, Client *who, Channel *channel, char *comment, long client_flags, long who_flags, char **reject_reason)
+int nokick_check (Client *client, Client *target, Channel *channel, const char *comment, const char *client_member_modes, const char *target_member_modes, const char **reject_reason)
{
static char errmsg[256];
diff --git a/src/modules/chanmodes/noknock.c b/src/modules/chanmodes/noknock.c
index d5b36a4..ac5f1f6 100644
--- a/src/modules/chanmodes/noknock.c
+++ b/src/modules/chanmodes/noknock.c
@@ -25,15 +25,15 @@ ModuleHeader MOD_HEADER
"4.2",
"Channel Mode +K",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
Cmode_t EXTCMODE_NOKNOCK;
-#define IsNoKnock(channel) (channel->mode.extmode & EXTCMODE_NOKNOCK)
+#define IsNoKnock(channel) (channel->mode.mode & EXTCMODE_NOKNOCK)
-int noknock_check (Client *client, Channel *channel);
-int noknock_mode_allow(Client *client, Channel *channel, char mode, char *para, int checkt, int what);
+int noknock_check_knock(Client *client, Channel *channel, const char **reason);
+int noknock_mode_allow(Client *client, Channel *channel, char mode, const char *para, int checkt, int what);
int noknock_mode_del (Channel *channel, int modeChar);
MOD_TEST()
@@ -47,11 +47,11 @@ CmodeInfo req;
memset(&req, 0, sizeof(req));
req.paracount = 0;
- req.flag = 'K';
+ req.letter = 'K';
req.is_ok = noknock_mode_allow;
CmodeAdd(modinfo->handle, req, &EXTCMODE_NOKNOCK);
- HookAdd(modinfo->handle, HOOKTYPE_PRE_KNOCK, 0, noknock_check);
+ HookAdd(modinfo->handle, HOOKTYPE_PRE_KNOCK, 0, noknock_check_knock);
HookAdd(modinfo->handle, HOOKTYPE_MODECHAR_DEL, 0, noknock_mode_del);
@@ -70,11 +70,11 @@ MOD_UNLOAD()
}
-int noknock_check (Client *client, Channel *channel)
+int noknock_check_knock (Client *client, Channel *channel, const char **reason)
{
if (MyUser(client) && IsNoKnock(channel))
{
- sendnumeric(client, ERR_CANNOTKNOCK, channel->chname, "No knocks are allowed! (+K)");
+ sendnumeric(client, ERR_CANNOTKNOCK, channel->name, "No knocks are allowed! (+K)");
return HOOK_DENY;
}
@@ -85,14 +85,14 @@ int noknock_mode_del (Channel *channel, int modeChar)
{
// Remove noknock when we're removing invite only
if (modeChar == 'i')
- channel->mode.extmode &= ~EXTCMODE_NOKNOCK;
+ channel->mode.mode &= ~EXTCMODE_NOKNOCK;
return 0;
}
-int noknock_mode_allow(Client *client, Channel *channel, char mode, char *para, int checkt, int what)
+int noknock_mode_allow(Client *client, Channel *channel, char mode, const char *para, int checkt, int what)
{
- if (!(channel->mode.mode & MODE_INVITEONLY))
+ if (!has_channel_mode(channel, 'i'))
{
if (checkt == EXCHK_ACCESS_ERR)
{
diff --git a/src/modules/chanmodes/nonickchange.c b/src/modules/chanmodes/nonickchange.c
index 1d28e38..88a411c 100644
--- a/src/modules/chanmodes/nonickchange.c
+++ b/src/modules/chanmodes/nonickchange.c
@@ -26,12 +26,12 @@ ModuleHeader MOD_HEADER
"4.2",
"Channel Mode +N",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
Cmode_t EXTCMODE_NONICKCHANGE;
-#define IsNoNickChange(channel) (channel->mode.extmode & EXTCMODE_NONICKCHANGE)
+#define IsNoNickChange(channel) (channel->mode.mode & EXTCMODE_NONICKCHANGE)
int nonickchange_check (Client *client, Channel *channel);
@@ -46,7 +46,7 @@ CmodeInfo req;
memset(&req, 0, sizeof(req));
req.paracount = 0;
- req.flag = 'N';
+ req.letter = 'N';
req.is_ok = extcmode_default_requirehalfop;
CmodeAdd(modinfo->handle, req, &EXTCMODE_NONICKCHANGE);
@@ -71,7 +71,7 @@ int nonickchange_check (Client *client, Channel *channel)
{
if (!IsOper(client) && !IsULine(client)
&& IsNoNickChange(channel)
- && !is_chan_op(client, channel))
+ && !check_channel_access(client, channel, "oaq"))
{
return HOOK_DENY;
}
diff --git a/src/modules/chanmodes/nonotice.c b/src/modules/chanmodes/nonotice.c
index 0d60023..7c63b35 100644
--- a/src/modules/chanmodes/nonotice.c
+++ b/src/modules/chanmodes/nonotice.c
@@ -25,14 +25,14 @@ ModuleHeader MOD_HEADER
"4.2",
"Channel Mode +T",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
Cmode_t EXTCMODE_NONOTICE;
-#define IsNoNotice(channel) (channel->mode.extmode & EXTCMODE_NONOTICE)
+#define IsNoNotice(channel) (channel->mode.mode & EXTCMODE_NONOTICE)
-int nonotice_check_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
+int nonotice_check_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype);
MOD_TEST()
{
@@ -45,7 +45,7 @@ MOD_INIT()
memset(&req, 0, sizeof(req));
req.paracount = 0;
- req.flag = 'T';
+ req.letter = 'T';
req.is_ok = extcmode_default_requirechop;
CmodeAdd(modinfo->handle, req, &EXTCMODE_NONOTICE);
@@ -65,14 +65,14 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
-int nonotice_check_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
+int nonotice_check_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype)
{
Hook *h;
int i;
if ((sendtype == SEND_TYPE_NOTICE) &&
IsNoNotice(channel) &&
- (!lp || !(lp->flags & (CHFL_CHANOP | CHFL_CHANOWNER | CHFL_CHANADMIN))))
+ !check_channel_access_membership(lp, "oaq"))
{
for (h = Hooks[HOOKTYPE_CAN_BYPASS_CHANNEL_MESSAGE_RESTRICTION]; h; h = h->next)
{
diff --git a/src/modules/chanmodes/operonly.c b/src/modules/chanmodes/operonly.c
index 4b959c0..3c4b4f7 100644
--- a/src/modules/chanmodes/operonly.c
+++ b/src/modules/chanmodes/operonly.c
@@ -27,15 +27,15 @@ ModuleHeader MOD_HEADER
"4.2",
"Channel Mode +O",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
Cmode_t EXTCMODE_OPERONLY;
-int operonly_require_oper(Client *client, Channel *channel, char mode, char *para, int checkt, int what);
-int operonly_check (Client *client, Channel *channel, char *key, char *parv[]);
-int operonly_topic_allow (Client *client, Channel *channel);
-int operonly_check_ban(Client *client, Channel *channel);
+int operonly_require_oper(Client *client, Channel *channel, char mode, const char *para, int checkt, int what);
+int operonly_can_join(Client *client, Channel *channel, const char *key, char **errmsg);
+int operonly_view_topic_outside_channel(Client *client, Channel *channel);
+int operonly_oper_invite_ban(Client *client, Channel *channel);
MOD_TEST()
{
@@ -48,13 +48,13 @@ CmodeInfo req;
memset(&req, 0, sizeof(req));
req.paracount = 0;
- req.flag = 'O';
+ req.letter = 'O';
req.is_ok = operonly_require_oper;
CmodeAdd(modinfo->handle, req, &EXTCMODE_OPERONLY);
- HookAdd(modinfo->handle, HOOKTYPE_CAN_JOIN, 0, operonly_check);
- HookAdd(modinfo->handle, HOOKTYPE_OPER_INVITE_BAN, 0, operonly_check_ban);
- HookAdd(modinfo->handle, HOOKTYPE_VIEW_TOPIC_OUTSIDE_CHANNEL, 0, operonly_topic_allow);
+ HookAdd(modinfo->handle, HOOKTYPE_CAN_JOIN, 0, operonly_can_join);
+ HookAdd(modinfo->handle, HOOKTYPE_OPER_INVITE_BAN, 0, operonly_oper_invite_ban);
+ HookAdd(modinfo->handle, HOOKTYPE_VIEW_TOPIC_OUTSIDE_CHANNEL, 0, operonly_view_topic_outside_channel);
MARK_AS_OFFICIAL_MODULE(modinfo);
@@ -71,31 +71,34 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
-int operonly_check (Client *client, Channel *channel, char *key, char *parv[])
+int operonly_can_join(Client *client, Channel *channel, const char *key, char **errmsg)
{
- if ((channel->mode.extmode & EXTCMODE_OPERONLY) && !ValidatePermissionsForPath("channel:operonly:join",client,NULL,channel,NULL))
+ if ((channel->mode.mode & EXTCMODE_OPERONLY) && !ValidatePermissionsForPath("channel:operonly:join",client,NULL,channel,NULL))
+ {
+ *errmsg = STR_ERR_OPERONLY;
return ERR_OPERONLY;
+ }
return 0;
}
-int operonly_check_ban(Client *client, Channel *channel)
+int operonly_oper_invite_ban(Client *client, Channel *channel)
{
- if ((channel->mode.extmode & EXTCMODE_OPERONLY) &&
+ if ((channel->mode.mode & EXTCMODE_OPERONLY) &&
!ValidatePermissionsForPath("channel:operonly:ban",client,NULL,NULL,NULL))
return HOOK_DENY;
return HOOK_CONTINUE;
}
-int operonly_topic_allow (Client *client, Channel *channel)
+int operonly_view_topic_outside_channel(Client *client, Channel *channel)
{
- if (channel->mode.extmode & EXTCMODE_OPERONLY && !ValidatePermissionsForPath("channel:operonly:topic",client,NULL,channel,NULL))
+ if (channel->mode.mode & EXTCMODE_OPERONLY && !ValidatePermissionsForPath("channel:operonly:topic",client,NULL,channel,NULL))
return HOOK_DENY;
return HOOK_CONTINUE;
}
-int operonly_require_oper(Client *client, Channel *channel, char mode, char *para, int checkt, int what)
+int operonly_require_oper(Client *client, Channel *channel, char mode, const char *para, int checkt, int what)
{
if (!MyUser(client) || ValidatePermissionsForPath("channel:operonly:set",client,NULL,channel,NULL))
return EX_ALLOW;
diff --git a/src/modules/chanmodes/permanent.c b/src/modules/chanmodes/permanent.c
index bccc443..e52c9f7 100644
--- a/src/modules/chanmodes/permanent.c
+++ b/src/modules/chanmodes/permanent.c
@@ -25,20 +25,20 @@ ModuleHeader MOD_HEADER
"4.2",
"Permanent channel mode (+P)",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
static Cmode_t EXTMODE_PERMANENT = 0L;
static int permanent_channel_destroy(Channel *channel, int *should_destroy)
{
- if (channel->mode.extmode & EXTMODE_PERMANENT)
+ if (channel->mode.mode & EXTMODE_PERMANENT)
*should_destroy = 0;
return 0;
}
-static int permanent_is_ok(Client *client, Channel *channel, char mode, char *para, int checkt, int what)
+static int permanent_is_ok(Client *client, Channel *channel, char mode, const char *para, int checkt, int what)
{
if (!IsOper(client))
{
@@ -51,14 +51,17 @@ static int permanent_is_ok(Client *client, Channel *channel, char mode, char *pa
return EX_ALLOW;
}
-int permanent_chanmode(Client *client, Channel *channel, MessageTag *mtags, char *modebuf, char *parabuf, time_t sendts, int samode)
+int permanent_chanmode(Client *client, Channel *channel, MessageTag *mtags, const char *modebuf, const char *parabuf, time_t sendts, int samode, int *destroy_channel)
{
if (samode == -1)
return 0; /* SJOIN server-sync, already has its own way of destroying the channel */
/* Destroy the channel if it was set '(SA)MODE #chan -P' with nobody in it (#4442) */
- if (!(channel->mode.extmode & EXTMODE_PERMANENT) && (channel->users <= 0))
+ if (!(channel->mode.mode & EXTMODE_PERMANENT) && (channel->users <= 0))
+ {
sub1_from_channel(channel);
+ *destroy_channel = 1;
+ }
return 0;
}
@@ -72,7 +75,7 @@ CmodeInfo req;
memset(&req, 0, sizeof(req));
req.paracount = 0;
- req.flag = 'P';
+ req.letter = 'P';
req.is_ok = permanent_is_ok;
CmodeAdd(modinfo->handle, req, &EXTMODE_PERMANENT);
diff --git a/src/modules/snomasks/dccreject.c b/src/modules/chanmodes/private.c
similarity index 52%
rename from src/modules/snomasks/dccreject.c
rename to src/modules/chanmodes/private.c
index 50bccdd..d292050 100644
--- a/src/modules/snomasks/dccreject.c
+++ b/src/modules/chanmodes/private.c
@@ -1,6 +1,6 @@
/*
- * Show DCC SEND rejection notices (Snomask +D)
- * (C) Copyright 2000-.. Bram Matthys (Syzop) and the UnrealIRCd team
+ * Channel Mode +p
+ * (C) Copyright 2021 Syzop and the UnrealIRCd team
*
* 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
@@ -19,34 +19,36 @@
#include "unrealircd.h"
-/* Module header */
+
ModuleHeader MOD_HEADER
= {
- "snomasks/dccreject",
- "4.2",
- "Snomask +D",
+ "chanmodes/private",
+ "6.0",
+ "Channel Mode +p",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
-/* Global variables */
-long SNO_DCCREJECT = 0L;
+Cmode_t EXTCMODE_PRIVATE;
-/* Forward declarations */
-int dccreject_dcc_denied(Client *client, char *target, char *realfile, char *displayfile, ConfigItem_deny_dcc *dccdeny);
+#define IsPrivate(channel) (channel->mode.mode & EXTCMODE_PRIVATE)
-MOD_TEST()
-{
- return MOD_SUCCESS;
-}
+int private_modechar_add(Channel *channel, int modechar);
MOD_INIT()
{
- SnomaskAdd(modinfo->handle, 'D', umode_allow_opers, &SNO_DCCREJECT);
-
- HookAdd(modinfo->handle, HOOKTYPE_DCC_DENIED, 0, dccreject_dcc_denied);
-
+ CmodeInfo req;
+
MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ memset(&req, 0, sizeof(req));
+ req.paracount = 0;
+ req.letter = 'p';
+ req.is_ok = extcmode_default_requirehalfop;
+ CmodeAdd(modinfo->handle, req, &EXTCMODE_PRIVATE);
+
+ HookAdd(modinfo->handle, HOOKTYPE_MODECHAR_ADD, 0, private_modechar_add);
+
return MOD_SUCCESS;
}
@@ -60,11 +62,12 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
-int dccreject_dcc_denied(Client *client, char *target, char *realfile, char *displayfile, ConfigItem_deny_dcc *dccdeny)
+/** This clears channel mode +p when +s gets set */
+int private_modechar_add(Channel *channel, int modechar)
{
- sendto_snomask_global(SNO_DCCREJECT,
- "%s tried to send forbidden file %s (%s) to %s (is blocked now)",
- client->name, displayfile, dccdeny->reason, target);
-
+ if (modechar == 's')
+ {
+ channel->mode.mode &= ~EXTCMODE_PRIVATE;
+ }
return 0;
}
diff --git a/src/modules/chanmodes/regonly.c b/src/modules/chanmodes/regonly.c
index 8b1b559..b35100c 100644
--- a/src/modules/chanmodes/regonly.c
+++ b/src/modules/chanmodes/regonly.c
@@ -26,14 +26,14 @@ ModuleHeader MOD_HEADER
"4.2",
"Channel Mode +R",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
Cmode_t EXTCMODE_REGONLY;
-#define IsRegOnly(channel) (channel->mode.extmode & EXTCMODE_REGONLY)
+#define IsRegOnly(channel) (channel->mode.mode & EXTCMODE_REGONLY)
-int regonly_check (Client *client, Channel *channel, char *key, char *parv[]);
+int regonly_check(Client *client, Channel *channel, const char *key, char **errmsg);
MOD_TEST()
@@ -47,7 +47,7 @@ CmodeInfo req;
memset(&req, 0, sizeof(req));
req.paracount = 0;
- req.flag = 'R';
+ req.letter = 'R';
req.is_ok = extcmode_default_requirehalfop;
CmodeAdd(modinfo->handle, req, &EXTCMODE_REGONLY);
@@ -68,10 +68,13 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
-int regonly_check (Client *client, Channel *channel, char *key, char *parv[])
+int regonly_check (Client *client, Channel *channel, const char *key, char **errmsg)
{
if (IsRegOnly(channel) && !IsLoggedIn(client))
+ {
+ *errmsg = STR_ERR_NEEDREGGEDNICK;
return ERR_NEEDREGGEDNICK;
+ }
return 0;
}
diff --git a/src/modules/chanmodes/regonlyspeak.c b/src/modules/chanmodes/regonlyspeak.c
index 33e2c5b..656dd06 100644
--- a/src/modules/chanmodes/regonlyspeak.c
+++ b/src/modules/chanmodes/regonlyspeak.c
@@ -26,16 +26,16 @@ ModuleHeader MOD_HEADER
"4.2",
"Channel Mode +M",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
Cmode_t EXTCMODE_REGONLYSPEAK;
static char errMsg[2048];
-#define IsRegOnlySpeak(channel) (channel->mode.extmode & EXTCMODE_REGONLYSPEAK)
+#define IsRegOnlySpeak(channel) (channel->mode.mode & EXTCMODE_REGONLYSPEAK)
-int regonlyspeak_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
-char *regonlyspeak_part_message (Client *client, Channel *channel, char *comment);
+int regonlyspeak_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype);
+const char *regonlyspeak_part_message (Client *client, Channel *channel, const char *comment);
MOD_TEST()
{
@@ -48,12 +48,12 @@ MOD_INIT()
memset(&req, 0, sizeof(req));
req.paracount = 0;
- req.flag = 'M';
+ req.letter = 'M';
req.is_ok = extcmode_default_requirehalfop;
CmodeAdd(modinfo->handle, req, &EXTCMODE_REGONLYSPEAK);
HookAdd(modinfo->handle, HOOKTYPE_CAN_SEND_TO_CHANNEL, 0, regonlyspeak_can_send_to_channel);
- HookAddPChar(modinfo->handle, HOOKTYPE_PRE_LOCAL_PART, 0, regonlyspeak_part_message);
+ HookAddConstString(modinfo->handle, HOOKTYPE_PRE_LOCAL_PART, 0, regonlyspeak_part_message);
MARK_AS_OFFICIAL_MODULE(modinfo);
@@ -70,7 +70,7 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
-char *regonlyspeak_part_message (Client *client, Channel *channel, char *comment)
+const char *regonlyspeak_part_message (Client *client, Channel *channel, const char *comment)
{
if (!comment)
return NULL;
@@ -81,15 +81,15 @@ char *regonlyspeak_part_message (Client *client, Channel *channel, char *comment
return comment;
}
-int regonlyspeak_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
+int regonlyspeak_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype)
{
Hook *h;
int i;
- if (IsRegOnlySpeak(channel) && !op_can_override("channel:override:message:regonlyspeak",client,channel,NULL) && !IsLoggedIn(client) &&
- (!lp
- || !(lp->flags & (CHFL_CHANOP | CHFL_VOICE | CHFL_CHANOWNER |
- CHFL_HALFOP | CHFL_CHANADMIN))))
+ if (IsRegOnlySpeak(channel) &&
+ !op_can_override("channel:override:message:regonlyspeak",client,channel,NULL) &&
+ !IsLoggedIn(client) &&
+ !check_channel_access_membership(lp, "vhoaq"))
{
for (h = Hooks[HOOKTYPE_CAN_BYPASS_CHANNEL_MESSAGE_RESTRICTION]; h; h = h->next)
{
diff --git a/src/modules/chanmodes/secret.c b/src/modules/chanmodes/secret.c
new file mode 100644
index 0000000..0487a29
--- /dev/null
+++ b/src/modules/chanmodes/secret.c
@@ -0,0 +1,73 @@
+/*
+ * Channel Mode +s
+ * (C) Copyright 2021 Syzop and the UnrealIRCd team
+ *
+ * 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.
+ */
+
+#include "unrealircd.h"
+
+
+ModuleHeader MOD_HEADER
+ = {
+ "chanmodes/secret",
+ "6.0",
+ "Channel Mode +s",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+ };
+
+Cmode_t EXTCMODE_SECRET;
+
+#define IsSecret(channel) (channel->mode.mode & EXTCMODE_SECRET)
+
+int secret_modechar_add(Channel *channel, int modechar);
+
+MOD_INIT()
+{
+ CmodeInfo req;
+
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ memset(&req, 0, sizeof(req));
+ req.paracount = 0;
+ req.letter = 's';
+ req.is_ok = extcmode_default_requirehalfop;
+ CmodeAdd(modinfo->handle, req, &EXTCMODE_SECRET);
+
+ HookAdd(modinfo->handle, HOOKTYPE_MODECHAR_ADD, 0, secret_modechar_add);
+
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ return MOD_SUCCESS;
+}
+
+/** This clears channel mode +s when +p gets set */
+int secret_modechar_add(Channel *channel, int modechar)
+{
+ if (modechar == 'p')
+ {
+ channel->mode.mode &= ~EXTCMODE_SECRET;
+ }
+ return 0;
+}
diff --git a/src/modules/chanmodes/secureonly.c b/src/modules/chanmodes/secureonly.c
index 4bd3dcb..084997b 100644
--- a/src/modules/chanmodes/secureonly.c
+++ b/src/modules/chanmodes/secureonly.c
@@ -25,18 +25,18 @@ ModuleHeader MOD_HEADER
"4.2",
"Channel Mode +z",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
Cmode_t EXTCMODE_SECUREONLY;
-#define IsSecureOnly(channel) (channel->mode.extmode & EXTCMODE_SECUREONLY)
+#define IsSecureOnly(channel) (channel->mode.mode & EXTCMODE_SECUREONLY)
-int secureonly_check_join(Client *client, Channel *channel, char *key, char *parv[]);
+int secureonly_check_join(Client *client, Channel *channel, const char *key, char **errmsg);
int secureonly_channel_sync (Channel *channel, int merge, int removetheirs, int nomode);
int secureonly_check_secure(Channel *channel);
int secureonly_check_sajoin(Client *target, Channel *channel, Client *requester);
-int secureonly_specialcheck(Client *client, Channel *channel, char *parv[]);
+int secureonly_pre_local_join(Client *client, Channel *channel, const char *key);
MOD_TEST()
{
@@ -49,11 +49,11 @@ MOD_INIT()
memset(&req, 0, sizeof(req));
req.paracount = 0;
- req.flag = 'z';
+ req.letter = 'z';
req.is_ok = extcmode_default_requirechop;
CmodeAdd(modinfo->handle, req, &EXTCMODE_SECUREONLY);
- HookAdd(modinfo->handle, HOOKTYPE_PRE_LOCAL_JOIN, 0, secureonly_specialcheck);
+ HookAdd(modinfo->handle, HOOKTYPE_PRE_LOCAL_JOIN, 0, secureonly_pre_local_join);
HookAdd(modinfo->handle, HOOKTYPE_CAN_JOIN, 0, secureonly_check_join);
HookAdd(modinfo->handle, HOOKTYPE_CHANNEL_SYNCED, 0, secureonly_channel_sync);
HookAdd(modinfo->handle, HOOKTYPE_IS_CHANNEL_SECURE, 0, secureonly_check_secure);
@@ -95,39 +95,39 @@ static int secureonly_kick_insecure_users(Channel *channel)
client = member->client;
if (MyUser(client) && !IsSecureConnect(client) && !IsULine(client))
{
- int prefix = 0;
+ char *prefix = NULL;
MessageTag *mtags = NULL;
if (invisible_user_in_channel(client, channel))
{
/* Send only to chanops */
- prefix = CHFL_HALFOP|CHFL_CHANOP|CHFL_CHANOWNER|CHFL_CHANADMIN;
+ prefix = "ho";
}
new_message(&me, NULL, &mtags);
- RunHook6(HOOKTYPE_LOCAL_KICK, &me, &me, client, channel, mtags, comment);
+ RunHook(HOOKTYPE_LOCAL_KICK, &me, &me, client, channel, mtags, comment);
sendto_channel(channel, &me, client,
prefix, 0,
SEND_LOCAL, mtags,
":%s KICK %s %s :%s",
- me.name, channel->chname, client->name, comment);
+ me.name, channel->name, client->name, comment);
- sendto_prefix_one(client, &me, mtags, ":%s KICK %s %s :%s", me.name, channel->chname, client->name, comment);
+ sendto_prefix_one(client, &me, mtags, ":%s KICK %s %s :%s", me.name, channel->name, client->name, comment);
- sendto_server(NULL, 0, 0, mtags, ":%s KICK %s %s :%s", me.id, channel->chname, client->id, comment);
+ sendto_server(NULL, 0, 0, mtags, ":%s KICK %s %s :%s", me.id, channel->name, client->id, comment);
free_message_tags(mtags);
- if (remove_user_from_channel(client, channel) == 1)
+ if (remove_user_from_channel(client, channel, 0) == 1)
return 1; /* channel was destroyed */
}
}
return 0;
}
-int secureonly_check_join(Client *client, Channel *channel, char *key, char *parv[])
+int secureonly_check_join(Client *client, Channel *channel, const char *key, char **errmsg)
{
Link *lp;
@@ -141,6 +141,7 @@ int secureonly_check_join(Client *client, Channel *channel, char *key, char *par
if (is_invited(client, channel))
return HOOK_CONTINUE;
}
+ *errmsg = STR_ERR_SECUREONLYCHAN;
return ERR_SECUREONLYCHAN;
}
return 0;
@@ -167,8 +168,8 @@ int secureonly_check_sajoin(Client *target, Channel *channel, Client *requester)
{
if (IsSecureOnly(channel) && !IsSecure(target))
{
- sendnotice(requester, "You cannot SAJOIN %s to %s because the channel is +z and the user is not connected via SSL/TLS",
- target->name, channel->chname);
+ sendnotice(requester, "You cannot SAJOIN %s to %s because the channel is +z and the user is not connected via TLS",
+ target->name, channel->name);
return HOOK_DENY;
}
@@ -178,11 +179,11 @@ int secureonly_check_sajoin(Client *target, Channel *channel, Client *requester)
/* Special check for +z in set::modes-on-join. Needs to be done early.
* Perhaps one day this will be properly handled in the core so this can be removed.
*/
-int secureonly_specialcheck(Client *client, Channel *channel, char *parv[])
+int secureonly_pre_local_join(Client *client, Channel *channel, const char *key)
{
- if ((channel->users == 0) && (iConf.modes_on_join.extmodes & EXTCMODE_SECUREONLY) && !IsSecure(client) && !IsOper(client))
+ if ((channel->users == 0) && (MODES_ON_JOIN & EXTCMODE_SECUREONLY) && !IsSecure(client) && !IsOper(client))
{
- sendnumeric(client, ERR_SECUREONLYCHAN, channel->chname);
+ sendnumeric(client, ERR_SECUREONLYCHAN, channel->name);
return HOOK_DENY;
}
return HOOK_CONTINUE;
diff --git a/src/modules/chanmodes/stripcolor.c b/src/modules/chanmodes/stripcolor.c
index 11f9f31..c172381 100644
--- a/src/modules/chanmodes/stripcolor.c
+++ b/src/modules/chanmodes/stripcolor.c
@@ -27,16 +27,16 @@ ModuleHeader MOD_HEADER
"4.2",
"Channel Mode +S",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
Cmode_t EXTCMODE_STRIPCOLOR;
-#define IsStripColor(channel) (channel->mode.extmode & EXTCMODE_STRIPCOLOR)
+#define IsStripColor(channel) (channel->mode.mode & EXTCMODE_STRIPCOLOR)
-int stripcolor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
-char *stripcolor_prelocalpart(Client *client, Channel *channel, char *comment);
-char *stripcolor_prelocalquit(Client *client, char *comment);
+int stripcolor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype);
+const char *stripcolor_prelocalpart(Client *client, Channel *channel, const char *comment);
+const char *stripcolor_prelocalquit(Client *client, const char *comment);
MOD_TEST()
{
@@ -50,14 +50,14 @@ CmodeInfo req;
/* Channel mode */
memset(&req, 0, sizeof(req));
req.paracount = 0;
- req.flag = 'S';
+ req.letter = 'S';
req.is_ok = extcmode_default_requirechop;
CmodeAdd(modinfo->handle, req, &EXTCMODE_STRIPCOLOR);
HookAdd(modinfo->handle, HOOKTYPE_CAN_SEND_TO_CHANNEL, 0, stripcolor_can_send_to_channel);
- HookAddPChar(modinfo->handle, HOOKTYPE_PRE_LOCAL_PART, 0, stripcolor_prelocalpart);
- HookAddPChar(modinfo->handle, HOOKTYPE_PRE_LOCAL_QUIT_CHAN, 0, stripcolor_prelocalpart);
- HookAddPChar(modinfo->handle, HOOKTYPE_PRE_LOCAL_QUIT, 0, stripcolor_prelocalquit);
+ HookAddConstString(modinfo->handle, HOOKTYPE_PRE_LOCAL_PART, 0, stripcolor_prelocalpart);
+ HookAddConstString(modinfo->handle, HOOKTYPE_PRE_LOCAL_QUIT_CHAN, 0, stripcolor_prelocalpart);
+ HookAddConstString(modinfo->handle, HOOKTYPE_PRE_LOCAL_QUIT, 0, stripcolor_prelocalquit);
MARK_AS_OFFICIAL_MODULE(modinfo);
return MOD_SUCCESS;
@@ -73,7 +73,7 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
-int stripcolor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
+int stripcolor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype)
{
Hook *h;
int i;
@@ -95,7 +95,7 @@ int stripcolor_can_send_to_channel(Client *client, Channel *channel, Membership
return HOOK_CONTINUE;
}
-char *stripcolor_prelocalpart(Client *client, Channel *channel, char *comment)
+const char *stripcolor_prelocalpart(Client *client, Channel *channel, const char *comment)
{
if (!comment)
return NULL;
@@ -118,7 +118,7 @@ static int IsAnyChannelStripColor(Client *client)
}
-char *stripcolor_prelocalquit(Client *client, char *comment)
+const char *stripcolor_prelocalquit(Client *client, const char *comment)
{
if (!comment)
return NULL;
diff --git a/src/modules/chanmodes/topiclimit.c b/src/modules/chanmodes/topiclimit.c
new file mode 100644
index 0000000..f16583a
--- /dev/null
+++ b/src/modules/chanmodes/topiclimit.c
@@ -0,0 +1,82 @@
+/*
+ * Channel Mode +t
+ * (C) Copyright 2021 Syzop and the UnrealIRCd team
+ *
+ * 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.
+ */
+
+#include "unrealircd.h"
+
+
+ModuleHeader MOD_HEADER
+ = {
+ "chanmodes/topiclimit",
+ "6.0",
+ "Channel Mode +t",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+ };
+
+/* Global variables */
+Cmode_t EXTCMODE_TOPIC_LIMIT;
+
+/* Forward declarations */
+int topiclimit_can_set_topic(Client *client, Channel *channel, const char *topic, const char **errmsg);
+
+/* Macros */
+#define IsTopicLimit(channel) (channel->mode.mode & EXTCMODE_TOPIC_LIMIT)
+
+MOD_INIT()
+{
+ CmodeInfo req;
+
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ memset(&req, 0, sizeof(req));
+ req.paracount = 0;
+ req.letter = 't';
+ req.is_ok = extcmode_default_requirehalfop;
+ CmodeAdd(modinfo->handle, req, &EXTCMODE_TOPIC_LIMIT);
+
+ HookAdd(modinfo->handle, HOOKTYPE_CAN_SET_TOPIC, 0, topiclimit_can_set_topic);
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ return MOD_SUCCESS;
+}
+
+int topiclimit_can_set_topic(Client *client, Channel *channel, const char *topic, const char **errmsg)
+{
+ static char errmsg_buf[NICKLEN+256];
+
+ if (has_channel_mode(channel, 't') &&
+ !check_channel_access(client, channel, "hoaq") &&
+ !IsULine(client) &&
+ !IsServer(client))
+ {
+ buildnumeric(errmsg_buf, sizeof(errmsg_buf), client, ERR_CHANOPRIVSNEEDED, channel->name);
+ *errmsg = errmsg_buf;
+ return EX_DENY;
+ }
+
+ return EX_ALLOW;
+}
diff --git a/src/modules/chanmodes/voice.c b/src/modules/chanmodes/voice.c
new file mode 100644
index 0000000..7233c53
--- /dev/null
+++ b/src/modules/chanmodes/voice.c
@@ -0,0 +1,88 @@
+/*
+ * Channel Mode +v
+ * (C) Copyright 2021 Syzop and the UnrealIRCd team
+ *
+ * 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.
+ */
+
+#include "unrealircd.h"
+
+ModuleHeader MOD_HEADER
+ = {
+ "chanmodes/voice",
+ "6.0",
+ "Channel Mode +v",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+ };
+
+/* Forward declarations */
+int cmode_voice_is_ok(Client *client, Channel *channel, char mode, const char *para, int type, int what);
+
+MOD_INIT()
+{
+ CmodeInfo creq;
+ ModDataInfo mreq;
+
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ memset(&creq, 0, sizeof(creq));
+ creq.paracount = 1;
+ creq.is_ok = cmode_voice_is_ok;
+ creq.letter = 'v';
+ creq.prefix = '+';
+ creq.sjoin_prefix = '+';
+ creq.rank = RANK_VOICE;
+ creq.unset_with_param = 1;
+ creq.type = CMODE_MEMBER;
+ CmodeAdd(modinfo->handle, creq, NULL);
+
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ return MOD_SUCCESS;
+}
+
+int cmode_voice_is_ok(Client *client, Channel *channel, char mode, const char *param, int type, int what)
+{
+ if ((type == EXCHK_ACCESS) || (type == EXCHK_ACCESS_ERR))
+ {
+ Client *target = find_user(param, NULL);
+
+ if ((what == MODE_DEL) && (target == client))
+ {
+ /* User may always remove their own modes */
+ return EX_ALLOW;
+ }
+ if (check_channel_access(client, channel, "hoaq"))
+ {
+ /* Permitted for +hoaq */
+ return EX_ALLOW;
+ }
+ if (type == EXCHK_ACCESS_ERR)
+ sendnumeric(client, ERR_CHANOPRIVSNEEDED, channel->name);
+ return EX_DENY;
+ }
+
+ /* fallthrough -- should not be used */
+ return EX_DENY;
+}
diff --git a/src/modules/channeldb.c b/src/modules/channeldb.c
index 7df6ddf..9c4f0c2 100644
--- a/src/modules/channeldb.c
+++ b/src/modules/channeldb.c
@@ -11,7 +11,7 @@ ModuleHeader MOD_HEADER = {
"1.0",
"Stores and retrieves channel settings for persistent (+P) channels",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Database version */
@@ -27,15 +27,14 @@ ModuleHeader MOD_HEADER = {
#define MAGIC_CHANNEL_START 0x11111111
#define MAGIC_CHANNEL_END 0x22222222
-#ifdef DEBUGMODE
- #define BENCHMARK
-#endif
+// #undef BENCHMARK
#define WARN_WRITE_ERROR(fname) \
do { \
- sendto_realops_and_log("[channeldb] Error writing to temporary database file " \
- "'%s': %s (DATABASE NOT SAVED)", \
- fname, unrealdb_get_error_string()); \
+ unreal_log(ULOG_ERROR, "channeldb", "CHANNELDB_FILE_WRITE_ERROR", NULL, \
+ "[channeldb] Error writing to temporary database file $filename: $system_error", \
+ log_data_string("filename", fname), \
+ log_data_string("system_error", unrealdb_get_error_string())); \
} while(0)
#define W_SAFE(x) \
@@ -72,7 +71,6 @@ EVENT(write_channeldb_evt);
int write_channeldb(void);
int write_channel_entry(UnrealDB *db, const char *tmpfname, Channel *channel);
int read_channeldb(void);
-static void set_channel_mode(Channel *channel, char *modes, char *parameters);
/* Global variables */
static uint32_t channeldb_version = CHANNELDB_VERSION;
@@ -132,7 +130,7 @@ MOD_LOAD()
MOD_UNLOAD()
{
- if (loop.ircd_terminating)
+ if (loop.terminating)
write_channeldb();
freecfg(&test);
freecfg(&cfg);
@@ -168,34 +166,34 @@ int channeldb_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
if (type != CONFIG_SET)
return 0;
- if (!ce || strcmp(ce->ce_varname, "channeldb"))
+ if (!ce || strcmp(ce->name, "channeldb"))
return 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!cep->ce_vardata)
+ if (!cep->value)
{
- config_error("%s:%i: blank set::channeldb::%s without value", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname);
+ config_error("%s:%i: blank set::channeldb::%s without value", cep->file->filename, cep->line_number, cep->name);
errors++;
} else
- if (!strcmp(cep->ce_varname, "database"))
+ if (!strcmp(cep->name, "database"))
{
- convert_to_absolute_path(&cep->ce_vardata, PERMDATADIR);
- safe_strdup(test.database, cep->ce_vardata);
+ convert_to_absolute_path(&cep->value, PERMDATADIR);
+ safe_strdup(test.database, cep->value);
} else
- if (!strcmp(cep->ce_varname, "db-secret"))
+ if (!strcmp(cep->name, "db-secret"))
{
- char *err;
- if ((err = unrealdb_test_secret(cep->ce_vardata)))
+ const char *err;
+ if ((err = unrealdb_test_secret(cep->value)))
{
- config_error("%s:%i: set::channeldb::db-secret: %s", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, err);
+ config_error("%s:%i: set::channeldb::db-secret: %s", cep->file->filename, cep->line_number, err);
errors++;
continue;
}
- safe_strdup(test.db_secret, cep->ce_vardata);
+ safe_strdup(test.db_secret, cep->value);
} else
{
- config_error("%s:%i: unknown directive set::channeldb::%s", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname);
+ config_error("%s:%i: unknown directive set::channeldb::%s", cep->file->filename, cep->line_number, cep->name);
errors++;
}
}
@@ -227,15 +225,15 @@ int channeldb_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
if (type != CONFIG_SET)
return 0;
- if (!ce || strcmp(ce->ce_varname, "channeldb"))
+ if (!ce || strcmp(ce->name, "channeldb"))
return 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "database"))
- safe_strdup(cfg.database, cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "db-secret"))
- safe_strdup(cfg.db_secret, cep->ce_vardata);
+ if (!strcmp(cep->name, "database"))
+ safe_strdup(cfg.database, cep->value);
+ else if (!strcmp(cep->name, "db-secret"))
+ safe_strdup(cfg.db_secret, cep->value);
}
return 1;
}
@@ -300,7 +298,7 @@ int write_channeldb(void)
#endif
if (rename(tmpfname, cfg.database) < 0)
{
- sendto_realops_and_log("[channeldb] Error renaming '%s' to '%s': %s (DATABASE NOT SAVED)", tmpfname, cfg.database, strerror(errno));
+ config_error("[channeldb] Error renaming '%s' to '%s': %s (DATABASE NOT SAVED)", tmpfname, cfg.database, strerror(errno));
return 0;
}
#ifdef BENCHMARK
@@ -333,9 +331,11 @@ int write_listmode(UnrealDB *db, const char *tmpfname, Ban *lst)
int write_channel_entry(UnrealDB *db, const char *tmpfname, Channel *channel)
{
+ char modebuf[BUFSIZE], parabuf[BUFSIZE];
+
W_SAFE(unrealdb_write_int32(db, MAGIC_CHANNEL_START));
/* Channel name */
- W_SAFE(unrealdb_write_str(db, channel->chname));
+ W_SAFE(unrealdb_write_str(db, channel->name));
/* Channel creation time */
W_SAFE(unrealdb_write_int64(db, channel->creationtime));
/* Topic (topic, setby, seton) */
@@ -343,7 +343,7 @@ int write_channel_entry(UnrealDB *db, const char *tmpfname, Channel *channel)
W_SAFE(unrealdb_write_str(db, channel->topic_nick));
W_SAFE(unrealdb_write_int64(db, channel->topic_time));
/* Basic channel modes (eg: +sntkl key 55) */
- channel_modes(&me, modebuf, parabuf, sizeof(modebuf), sizeof(parabuf), channel);
+ channel_modes(&me, modebuf, parabuf, sizeof(modebuf), sizeof(parabuf), channel, 1);
W_SAFE(unrealdb_write_str(db, modebuf));
W_SAFE(unrealdb_write_str(db, parabuf));
/* Mode lock */
@@ -506,8 +506,11 @@ int read_channeldb(void)
R_SAFE(unrealdb_read_str(db, &modes2));
R_SAFE(unrealdb_read_str(db, &mode_lock));
/* If we got this far, we can create/initialize the channel with the above */
- channel = get_channel(&me, chname, CREATE);
- channel->creationtime = creationtime;
+ channel = make_channel(chname);
+ if (IsInvalidChannelTS(creationtime))
+ channel->creationtime = TStime();
+ else
+ channel->creationtime = creationtime;
safe_strdup(channel->topic, topic);
safe_strdup(channel->topic_nick, topic_nick);
channel->topic_time = topic_time;
@@ -529,37 +532,14 @@ int read_channeldb(void)
unrealdb_close(db);
if (added)
- sendto_realops_and_log("[channeldb] Added %d persistent channels (+P)", added);
+ config_status("[channeldb] Added %d persistent channels (+P)", added);
#ifdef BENCHMARK
gettimeofday(&tv_beta, NULL);
- ircd_log(LOG_ERROR, "[channeldb] Benchmark: LOAD DB: %ld microseconds",
- ((tv_beta.tv_sec - tv_alpha.tv_sec) * 1000000) + (tv_beta.tv_usec - tv_alpha.tv_usec));
+ unreal_log(ULOG_DEBUG, "channeldb", "CHANNELDB_BENCHMARK", NULL,
+ "[channeldb] Benchmark: LOAD DB: $time_msec microseconds",
+ log_data_integer("time_msec", ((tv_beta.tv_sec - tv_alpha.tv_sec) * 1000000) + (tv_beta.tv_usec - tv_alpha.tv_usec)));
#endif
return 1;
}
#undef FreeChannelEntry
#undef R_SAFE
-
-static void set_channel_mode(Channel *channel, char *modes, char *parameters)
-{
- char buf[512];
- char *p, *param;
- int myparc = 1, i;
- char *myparv[64];
-
- memset(&myparv, 0, sizeof(myparv));
- myparv[0] = raw_strdup(modes);
-
- strlcpy(buf, parameters, sizeof(buf));
- for (param = strtoken(&p, buf, " "); param; param = strtoken(&p, NULL, " "))
- myparv[myparc++] = raw_strdup(param);
- myparv[myparc] = NULL;
-
- SetULine(&me); // hack for crash.. set ulined so no access checks.
- do_mode(channel, &me, NULL, myparc, myparv, 0, 0);
- ClearULine(&me); // and clear it again..
-
- for (i = 0; i < myparc; i++)
- safe_free(myparv[i]);
-}
-// FIXME: move above function to m_mode and make efunc, available for all modules anyway
diff --git a/src/modules/charsys.c b/src/modules/charsys.c
index f0b1430..e20e13c 100644
--- a/src/modules/charsys.c
+++ b/src/modules/charsys.c
@@ -32,7 +32,7 @@ ModuleHeader MOD_HEADER
"5.0", /* Version */
"Character System (set::allowed-nickchars)", /* Short description of module */
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* NOTE: it is guaranteed that char is unsigned by compiling options
@@ -73,6 +73,7 @@ char langsinuse[4096];
#define LANGAV_CYRILLIC_UTF8 0x008000 /* UTF8: cyrillic script */
#define LANGAV_GREEK_UTF8 0x010000 /* UTF8: greek script */
#define LANGAV_HEBREW_UTF8 0x020000 /* UTF8: hebrew script */
+#define LANGAV_ARABIC_UTF8 0x040000 /* UTF8: arabic script */
typedef struct LangList LangList;
struct LangList
{
@@ -83,7 +84,7 @@ struct LangList
/* MUST be alphabetized (first column) */
static LangList langlist[] = {
-/* { "arabic", "ara", LANGAV_ASCII|LANGAV_ISO8859_6 }, -- TODO: check if this has issues first! */
+ { "arabic-utf8", "ara-utf8", LANGAV_ASCII|LANGAV_UTF8|LANGAV_ARABIC_UTF8 },
{ "belarussian-utf8", "blr-utf8", LANGAV_ASCII|LANGAV_UTF8|LANGAV_CYRILLIC_UTF8 },
{ "belarussian-w1251", "blr", LANGAV_ASCII|LANGAV_W1251 },
{ "catalan", "cat", LANGAV_ASCII|LANGAV_LATIN1 },
@@ -189,7 +190,7 @@ MOD_TEST()
MARK_AS_OFFICIAL_MODULE(modinfo);
EfunctionAdd(modinfo->handle, EFUNC_DO_NICK_NAME, _do_nick_name);
EfunctionAdd(modinfo->handle, EFUNC_DO_REMOTE_NICK_NAME, _do_remote_nick_name);
- EfunctionAddPChar(modinfo->handle, EFUNC_CHARSYS_GET_CURRENT_LANGUAGES, _charsys_get_current_languages);
+ EfunctionAddString(modinfo->handle, EFUNC_CHARSYS_GET_CURRENT_LANGUAGES, _charsys_get_current_languages);
charsys_reset();
charsys_reset_pretest();
HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, charsys_config_test);
@@ -226,26 +227,26 @@ int charsys_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
return 0;
/* We are only interrested in set::allowed-nickchars... */
- if (!ce || !ce->ce_varname || strcmp(ce->ce_varname, "allowed-nickchars"))
+ if (!ce || !ce->name || strcmp(ce->name, "allowed-nickchars"))
return 0;
- if (ce->ce_vardata)
+ if (ce->value)
{
config_error("%s:%i: set::allowed-nickchars: please use 'allowed-nickchars { name; };' "
"and not 'allowed-nickchars name;'",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
/* Give up immediately. Don't bother the user with any other errors. */
errors++;
*errs = errors;
return -1;
}
- for (cep = ce->ce_entries; cep; cep=cep->ce_next)
+ for (cep = ce->items; cep; cep=cep->next)
{
- if (!charsys_test_language(cep->ce_varname))
+ if (!charsys_test_language(cep->name))
{
config_error("%s:%i: set::allowed-nickchars: Unknown (sub)language '%s'",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum, cep->ce_varname);
+ ce->file->filename, ce->line_number, cep->name);
errors++;
}
}
@@ -262,11 +263,11 @@ int charsys_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
return 0;
/* We are only interrested in set::allowed-nickchars... */
- if (!ce || !ce->ce_varname || strcmp(ce->ce_varname, "allowed-nickchars"))
+ if (!ce || !ce->name || strcmp(ce->name, "allowed-nickchars"))
return 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
- charsys_add_language(cep->ce_varname);
+ for (cep = ce->items; cep; cep = cep->next)
+ charsys_add_language(cep->name);
return 1;
}
@@ -313,6 +314,8 @@ int charsys_config_posttest(int *errs)
x++;
if (x > 1)
{
+#if 0
+// I don't think this should be hard error, right? Some combinations may be problematic, but not all.
if (langav & LANGAV_LATIN_UTF8)
{
config_error("ERROR: set::allowed-nickchars: you cannot combine 'latin-utf8' with any other character set");
@@ -333,8 +336,13 @@ int charsys_config_posttest(int *errs)
config_error("ERROR: set::allowed-nickchars: you cannot combine 'hebrew-utf8' with any other character set");
errors++;
}
- config_status("WARNING: set::allowed-nickchars: "
- "Mixing of charsets (eg: latin1+latin2) can cause display problems");
+ if (langav & LANGAV_ARABIC_UTF8)
+ {
+ config_error("ERROR: set::allowed-nickchars: you cannot combine 'arabic-utf8' with any other character set");
+ errors++;
+ }
+#endif
+ config_status("WARNING: set::allowed-nickchars: Mixing of charsets (eg: latin1+latin2) may cause display problems");
}
*errs = errors;
@@ -877,13 +885,6 @@ void charsys_add_language(char *name)
charsys_addmultibyterange(0xc3, 0xc3, 0xba, 0xba);
charsys_addmultibyterange(0xc3, 0xc3, 0xbd, 0xbe);
}
-/* if (latin1 || !strcmp(name, "arabic")) -- Since when is arabic considered latin(1)??? oh man...
- {
- char bytes[] = { 0xa0, 0xa4, 0xac, 0xad, 0xbb, 0xbf, 0x00 };
- charsys_addallowed(bytes);
- charsys_addallowed_range(0xc1, 0xda);
- charsys_addallowed_range(0xe0, 0xf2);
- } */
/* [LATIN2] and rest of [LATIN-UTF8] */
/* actually hungarian is a special case, include it in both w1250 and latin2 ;p */
@@ -1181,6 +1182,19 @@ void charsys_add_language(char *name)
charsys_addmultibyterange(0xc5, 0xc5, 0xaa, 0xab);
charsys_addmultibyterange(0xc5, 0xc5, 0xbd, 0xbe);
}
+
+ /* [ARABIC] */
+ if (latin_utf8 || !strcmp(name, "arabic-utf8"))
+ {
+ /* Supplied by Sensiva */
+ /*charsys_addallowed("اأإآءبتثجحخدذرزسشصضطظعغفقكلمنهؤةويىئ");*/
+ /*- From U+0621 to U+063A (Regex: [\u0621-\u063A])*/
+ /* 0xd8a1 - 0xd8ba */
+ charsys_addmultibyterange(0xd8, 0xd8, 0xa1, 0xba);
+ /*- From U+0641 to U+064A (Regex: [\u0641-\u064A])*/
+ /* 0xd981 - 0xd98a */
+ charsys_addmultibyterange(0xd9, 0xd9, 0x81, 0x8a);
+ }
}
/** This displays all the nick characters that are permitted */
@@ -1250,6 +1264,8 @@ char *charsys_group(int v)
return "Greek script";
if (v & LANGAV_HEBREW_UTF8)
return "Hebrew script";
+ if (v & LANGAV_ARABIC_UTF8)
+ return "Arabic script";
return "Other";
}
diff --git a/src/modules/chathistory.c b/src/modules/chathistory.c
index dba2d5f..d13c32d 100644
--- a/src/modules/chathistory.c
+++ b/src/modules/chathistory.c
@@ -13,7 +13,15 @@ ModuleHeader MOD_HEADER
"1.0",
"IRCv3 CHATHISTORY command",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
+};
+
+/* Structs */
+typedef struct ChatHistoryTarget ChatHistoryTarget;
+struct ChatHistoryTarget {
+ ChatHistoryTarget *prev, *next;
+ char *datetime;
+ char *object;
};
/* Forward declarations */
@@ -22,7 +30,6 @@ CMD_FUNC(cmd_chathistory);
/* Global variables */
long CAP_CHATHISTORY = 0L;
-/* TODO: consider moving to config file */
#define CHATHISTORY_LIMIT 50
MOD_INIT()
@@ -49,13 +56,18 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
-int chathistory_token(char *str, char *token, char **store)
+int chathistory_token(const char *str, char *token, char **store)
{
- char *p = strchr(str, '=');
+ char request[BUFSIZE];
+ char *p;
+
+ strlcpy(request, str, sizeof(request));
+
+ p = strchr(request, '=');
if (!p)
return 0;
*p = '\0'; // frag
- if (!strcmp(str, token))
+ if (!strcmp(request, token))
{
*p = '='; // restore
*store = strdup(p + 1); // can be \0
@@ -65,15 +77,68 @@ int chathistory_token(char *str, char *token, char **store)
return 0;
}
-static int chathistory_targets_send_line(Client *client, HistoryResult *r, char *batchid)
+static void add_chathistory_target_list(ChatHistoryTarget *new, ChatHistoryTarget **list)
+{
+ ChatHistoryTarget *x, *last = NULL;
+
+ if (!*list)
+ {
+ /* We are the only item. Easy. */
+ *list = new;
+ return;
+ }
+
+ for (x = *list; x; x = x->next)
+ {
+ last = x;
+ if (strcmp(new->datetime, x->datetime) >= 0)
+ break;
+ }
+
+ if (x)
+ {
+ if (x->prev)
+ {
+ /* We will insert ourselves just before this item */
+ new->prev = x->prev;
+ new->next = x;
+ x->prev->next = new;
+ x->prev = new;
+ } else {
+ /* We are the new head */
+ *list = new;
+ new->next = x;
+ x->prev = new;
+ }
+ } else
+ {
+ /* We are the last item */
+ last->next = new;
+ new->prev = last;
+ }
+}
+
+static void add_chathistory_target(ChatHistoryTarget **list, HistoryResult *r)
+{
+ MessageTag *m;
+ time_t ts;
+ char *datetime;
+ ChatHistoryTarget *e;
+
+ if (!r->log || !((m = find_mtag(r->log->mtags, "time"))) || !m->value)
+ return;
+ datetime = m->value;
+
+ e = safe_alloc(sizeof(ChatHistoryTarget));
+ safe_strdup(e->datetime, datetime);
+ safe_strdup(e->object, r->object);
+ add_chathistory_target_list(e, list);
+}
+
+static void chathistory_targets_send_line(Client *client, ChatHistoryTarget *r, char *batchid)
{
MessageTag *mtags = NULL;
MessageTag *m;
- char *ts;
-
- if (!r->log || !((m = find_mtag(r->log->mtags, "time"))) || !m->value)
- return 0;
- ts = m->value;
if (!BadPtr(batchid))
{
@@ -83,12 +148,10 @@ static int chathistory_targets_send_line(Client *client, HistoryResult *r, char
}
sendto_one(client, mtags, ":%s CHATHISTORY TARGETS %s %s",
- me.name, r->object, ts);
+ me.name, r->object, r->datetime);
if (mtags)
free_message_tags(mtags);
-
- return 1;
}
void chathistory_targets(Client *client, HistoryFilter *filter, int limit)
@@ -97,14 +160,9 @@ void chathistory_targets(Client *client, HistoryFilter *filter, int limit)
HistoryResult *r;
char batch[BATCHLEN+1];
int sent = 0;
+ ChatHistoryTarget *targets = NULL, *targets_next;
- batch[0] = '\0';
- if (HasCapability(client, "batch"))
- {
- /* Start a new batch */
- generate_batch_id(batch);
- sendto_one(client, NULL, ":%s BATCH +%s draft/chathistory-targets", me.name, batch);
- }
+ /* 1. Grab all information we need */
filter->cmd = HFC_BEFORE;
if (strcmp(filter->timestamp_a, filter->timestamp_b) < 0)
@@ -119,14 +177,32 @@ void chathistory_targets(Client *client, HistoryFilter *filter, int limit)
for (mp = client->user->channel; mp; mp = mp->next)
{
Channel *channel = mp->channel;
- r = history_request(channel->chname, filter);
- if (r->log && chathistory_targets_send_line(client, r, batch))
+ r = history_request(channel->name, filter);
+ if (r)
{
- if (++sent >= limit)
- break; /* We are done */
+ add_chathistory_target(&targets, r);
+ free_history_result(r);
}
- free_history_result(r);
- r = NULL;
+ }
+
+ /* 2. Now send it to the client */
+
+ batch[0] = '\0';
+ if (HasCapability(client, "batch"))
+ {
+ /* Start a new batch */
+ generate_batch_id(batch);
+ sendto_one(client, NULL, ":%s BATCH +%s draft/chathistory-targets", me.name, batch);
+ }
+
+ for (; targets; targets = targets_next)
+ {
+ targets_next = targets->next;
+ if (++sent < limit)
+ chathistory_targets_send_line(client, targets, batch);
+ safe_free(targets->datetime);
+ safe_free(targets->object);
+ safe_free(targets);
}
/* End of batch */
@@ -160,7 +236,7 @@ CMD_FUNC(cmd_chathistory)
return;
}
- if (!strcmp(parv[1], "TARGETS"))
+ if (!strcasecmp(parv[1], "TARGETS"))
{
Membership *mp;
int limit;
@@ -185,18 +261,39 @@ CMD_FUNC(cmd_chathistory)
goto end;
}
- channel = find_channel(parv[2], NULL);
- if (!channel || !IsMember(client, channel) || !has_channel_mode(channel, 'H'))
+ channel = find_channel(parv[2]);
+ if (!channel)
{
- sendto_one(client, NULL, ":%s FAIL CHATHISTORY INVALID_TARGET %s %s :Messages could not be retrieved",
+ sendto_one(client, NULL, ":%s FAIL CHATHISTORY INVALID_TARGET %s %s :Messages could not be retrieved, not an existing channel",
me.name, parv[1], parv[2]);
return;
}
+ if (!IsMember(client, channel))
+ {
+ sendto_one(client, NULL, ":%s FAIL CHATHISTORY INVALID_TARGET %s %s :Messages could not be retrieved, you are not a member",
+ me.name, parv[1], parv[2]);
+ return;
+ }
+
+ /* Channel is not +H? Send empty response/batch (as per IRCv3 discussion) */
+ if (!has_channel_mode(channel, 'H'))
+ {
+ if (HasCapability(client, "batch"))
+ {
+ char batch[BATCHLEN+1];
+
+ generate_batch_id(batch);
+ sendto_one(client, NULL, ":%s BATCH +%s chathistory %s", me.name, batch, channel->name);
+ sendto_one(client, NULL, ":%s BATCH -%s", me.name, batch);
+ }
+ return;
+ }
+
filter = safe_alloc(sizeof(HistoryFilter));
/* Below this point, instead of 'return', use 'goto end', which takes care of the freeing of 'filter' and 'history' */
- if (!strcmp(parv[1], "BEFORE"))
+ if (!strcasecmp(parv[1], "BEFORE"))
{
filter->cmd = HFC_BEFORE;
if (!chathistory_token(parv[3], "timestamp", &filter->timestamp_a) &&
@@ -208,7 +305,7 @@ CMD_FUNC(cmd_chathistory)
}
filter->limit = atoi(parv[4]);
} else
- if (!strcmp(parv[1], "AFTER"))
+ if (!strcasecmp(parv[1], "AFTER"))
{
filter->cmd = HFC_AFTER;
if (!chathistory_token(parv[3], "timestamp", &filter->timestamp_a) &&
@@ -220,7 +317,7 @@ CMD_FUNC(cmd_chathistory)
}
filter->limit = atoi(parv[4]);
} else
- if (!strcmp(parv[1], "LATEST"))
+ if (!strcasecmp(parv[1], "LATEST"))
{
filter->cmd = HFC_LATEST;
if (!chathistory_token(parv[3], "timestamp", &filter->timestamp_a) &&
@@ -233,7 +330,7 @@ CMD_FUNC(cmd_chathistory)
}
filter->limit = atoi(parv[4]);
} else
- if (!strcmp(parv[1], "AROUND"))
+ if (!strcasecmp(parv[1], "AROUND"))
{
filter->cmd = HFC_AROUND;
if (!chathistory_token(parv[3], "timestamp", &filter->timestamp_a) &&
@@ -245,7 +342,7 @@ CMD_FUNC(cmd_chathistory)
}
filter->limit = atoi(parv[4]);
} else
- if (!strcmp(parv[1], "BETWEEN"))
+ if (!strcasecmp(parv[1], "BETWEEN"))
{
filter->cmd = HFC_BETWEEN;
if (BadPtr(parv[5]))
@@ -283,7 +380,7 @@ CMD_FUNC(cmd_chathistory)
if (filter->limit > CHATHISTORY_LIMIT)
filter->limit = CHATHISTORY_LIMIT;
- if ((r = history_request(channel->chname, filter)))
+ if ((r = history_request(channel->name, filter)))
history_send_result(client, r);
end:
diff --git a/src/modules/chghost.c b/src/modules/chghost.c
index 8d3e3f0..a52c883 100644
--- a/src/modules/chghost.c
+++ b/src/modules/chghost.c
@@ -25,6 +25,10 @@
#define MSG_CHGHOST "CHGHOST"
CMD_FUNC(cmd_chghost);
+void _userhost_save_current(Client *client);
+void _userhost_changed(Client *client);
+
+long CAP_CHGHOST = 0L;
ModuleHeader MOD_HEADER
= {
@@ -32,13 +36,28 @@ ModuleHeader MOD_HEADER
"5.0", /* Version */
"/chghost", /* Short description of module */
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
+MOD_TEST()
+{
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+ EfunctionAddVoid(modinfo->handle, EFUNC_USERHOST_SAVE_CURRENT, _userhost_save_current);
+ EfunctionAddVoid(modinfo->handle, EFUNC_USERHOST_CHANGED, _userhost_changed);
+ return MOD_SUCCESS;
+}
+
MOD_INIT()
{
+ ClientCapabilityInfo c;
+
CommandAdd(modinfo->handle, MSG_CHGHOST, cmd_chghost, MAXPARA, CMD_USER|CMD_SERVER);
MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ memset(&c, 0, sizeof(c));
+ c.name = "chghost";
+ ClientCapabilityAdd(modinfo->handle, &c, &CAP_CHGHOST);
+
return MOD_SUCCESS;
}
@@ -53,6 +72,177 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
+
+static char remember_nick[NICKLEN+1];
+static char remember_user[USERLEN+1];
+static char remember_host[HOSTLEN+1];
+
+/** Save current nick/user/host. Used later by userhost_changed(). */
+void _userhost_save_current(Client *client)
+{
+ strlcpy(remember_nick, client->name, sizeof(remember_nick));
+ strlcpy(remember_user, client->user->username, sizeof(remember_user));
+ strlcpy(remember_host, GetHost(client), sizeof(remember_host));
+}
+
+/** User/Host changed for user.
+ * Note that userhost_save_current() needs to be called before this
+ * to save the old username/hostname.
+ * This userhost_changed() function deals with notifying local clients
+ * about the user/host change by sending PART+JOIN+MODE if
+ * set::allow-userhost-change force-rejoin is in use,
+ * and it wills end "CAP chghost" to such capable clients.
+ * It will also deal with bumping fakelag for the user since a user/host
+ * change is costly, doesn't matter if it was self-induced or not.
+ *
+ * Please call this function for any user/host change by doing:
+ * userhost_save_current(client);
+ * << change username or hostname here >>
+ * userhost_changed(client);
+ */
+void _userhost_changed(Client *client)
+{
+ Membership *channels;
+ Member *lp;
+ Client *acptr;
+ int impact = 0;
+ char buf[512];
+ long CAP_EXTENDED_JOIN = ClientCapabilityBit("extended-join");
+
+ if (strcmp(remember_nick, client->name))
+ {
+ unreal_log(ULOG_ERROR, "main", "BUG_USERHOST_CHANGED", client,
+ "[BUG] userhost_changed() was called but without calling userhost_save_current() first! Affected user: $client\n"
+ "Please report above bug on https://bugs.unrealircd.org/");
+ return; /* We cannot safely process this request anymore */
+ }
+
+ /* It's perfectly acceptable to call us even if the userhost didn't change. */
+ if (!strcmp(remember_user, client->user->username) && !strcmp(remember_host, GetHost(client)))
+ return; /* Nothing to do */
+
+ /* Most of the work is only necessary for set::allow-userhost-change force-rejoin */
+ if (UHOST_ALLOWED == UHALLOW_REJOIN)
+ {
+ /* Walk through all channels of this user.. */
+ for (channels = client->user->channel; channels; channels = channels->next)
+ {
+ Channel *channel = channels->channel;
+ char *modes;
+ char partbuf[512]; /* PART */
+ char joinbuf[512]; /* JOIN */
+ char exjoinbuf[512]; /* JOIN (for CAP extended-join) */
+ char modebuf[512]; /* MODE (if any) */
+ int chanops_only = invisible_user_in_channel(client, channel);
+
+ modebuf[0] = '\0';
+
+ /* If the user is banned, don't send any rejoins, it would only be annoying */
+ if (is_banned(client, channel, BANCHK_JOIN, NULL, NULL))
+ continue;
+
+ /* Prepare buffers for PART, JOIN, MODE */
+ ircsnprintf(partbuf, sizeof(partbuf), ":%s!%s@%s PART %s :%s",
+ remember_nick, remember_user, remember_host,
+ channel->name,
+ "Changing host");
+
+ ircsnprintf(joinbuf, sizeof(joinbuf), ":%s!%s@%s JOIN %s",
+ client->name, client->user->username, GetHost(client), channel->name);
+
+ ircsnprintf(exjoinbuf, sizeof(exjoinbuf), ":%s!%s@%s JOIN %s %s :%s",
+ client->name, client->user->username, GetHost(client), channel->name,
+ IsLoggedIn(client) ? client->user->account : "*",
+ client->info);
+
+ modes = get_chmodes_for_user(client, channels->member_modes);
+ if (!BadPtr(modes))
+ ircsnprintf(modebuf, sizeof(modebuf), ":%s MODE %s %s", me.name, channel->name, modes);
+
+ for (lp = channel->members; lp; lp = lp->next)
+ {
+ acptr = lp->client;
+
+ if (acptr == client)
+ continue; /* skip self */
+
+ if (!MyConnect(acptr))
+ continue; /* only locally connected clients */
+
+ if (chanops_only && !check_channel_access_member(lp, "hoaq"))
+ continue; /* skip non-ops if requested to (used for mode +D) */
+
+ if (HasCapabilityFast(acptr, CAP_CHGHOST))
+ continue; /* we notify 'CAP chghost' users in a different way, so don't send it here. */
+
+ impact++;
+
+ /* FIXME: if a client does not have the "chghost" cap then
+ * here we will not generate a proper new message, probably
+ * needs to be fixed... I skipped doing it for now.
+ */
+ sendto_one(acptr, NULL, "%s", partbuf);
+
+ if (HasCapabilityFast(acptr, CAP_EXTENDED_JOIN))
+ sendto_one(acptr, NULL, "%s", exjoinbuf);
+ else
+ sendto_one(acptr, NULL, "%s", joinbuf);
+
+ if (*modebuf)
+ sendto_one(acptr, NULL, "%s", modebuf);
+ }
+ }
+ }
+
+ /* Now deal with "CAP chghost" clients.
+ * This only needs to be sent one per "common channel".
+ * This would normally call sendto_common_channels_local_butone() but the user already
+ * has the new user/host.. so we do it here..
+ */
+ ircsnprintf(buf, sizeof(buf), ":%s!%s@%s CHGHOST %s %s",
+ remember_nick, remember_user, remember_host,
+ client->user->username,
+ GetHost(client));
+ current_serial++;
+ for (channels = client->user->channel; channels; channels = channels->next)
+ {
+ for (lp = channels->channel->members; lp; lp = lp->next)
+ {
+ acptr = lp->client;
+ if (MyUser(acptr) && HasCapabilityFast(acptr, CAP_CHGHOST) &&
+ (acptr->local->serial != current_serial) && (client != acptr))
+ {
+ /* FIXME: send mtag */
+ sendto_one(acptr, NULL, "%s", buf);
+ acptr->local->serial = current_serial;
+ }
+ }
+ }
+
+ RunHook(HOOKTYPE_USERHOST_CHANGED, client, remember_user, remember_host);
+
+ if (MyUser(client))
+ {
+ /* We take the liberty of sending the CHGHOST to the impacted user as
+ * well. This makes things easy for client coders.
+ * (Note that this cannot be merged with the for loop from 15 lines up
+ * since the user may not be in any channels)
+ */
+ if (HasCapabilityFast(client, CAP_CHGHOST))
+ sendto_one(client, NULL, "%s", buf);
+
+ /* A userhost change always generates the following network traffic:
+ * server to server traffic, CAP "chghost" notifications, and
+ * possibly PART+JOIN+MODE if force-rejoin had work to do.
+ * We give the user a penalty so they don't flood...
+ */
+ if (impact)
+ add_fake_lag(client, 7000); /* Resulted in rejoins and such. */
+ else
+ add_fake_lag(client, 4000); /* No rejoins */
+ }
+}
+
/*
* cmd_chghost - 12/07/1999 (two months after I made SETIDENT) - Stskeeps
* :prefix CHGHOST
@@ -83,7 +273,7 @@ CMD_FUNC(cmd_chghost)
return;
}
- if (!valid_host(parv[2]))
+ if (!valid_host(parv[2], 0))
{
sendnotice(client, "*** /ChgHost Error: A hostname may contain a-z, A-Z, 0-9, '-' & '.' - Please only use them");
return;
@@ -95,7 +285,7 @@ CMD_FUNC(cmd_chghost)
return;
}
- if (!(target = find_person(parv[1], NULL)))
+ if (!(target = find_user(parv[1], NULL)))
{
sendnumeric(client, ERR_NOSUCHNICK, parv[1]);
return;
@@ -135,14 +325,11 @@ CMD_FUNC(cmd_chghost)
if (!IsULine(client))
{
- sendto_snomask(SNO_EYES,
- "%s changed the virtual hostname of %s (%s@%s) to be %s",
- client->name, target->name, target->user->username,
- target->user->realhost, parv[2]);
- /* Logging added by XeRXeS */
- ircd_log(LOG_CHGCMDS,
- "CHGHOST: %s changed the virtual hostname of %s (%s@%s) to be %s",
- client->name, target->name, target->user->username, target->user->realhost, parv[2]);
+ unreal_log(ULOG_INFO, "chgcmds", "CHGHOST_COMMAND", client,
+ "CHGHOST: $client changed the virtual hostname of $target.details to be $new_hostname",
+ log_data_string("change_type", "hostname"),
+ log_data_client("target", target),
+ log_data_string("new_hostname", parv[2]));
}
target->umodes |= UMODE_HIDE;
diff --git a/src/modules/chgident.c b/src/modules/chgident.c
index 923ec39..155c894 100644
--- a/src/modules/chgident.c
+++ b/src/modules/chgident.c
@@ -32,7 +32,7 @@ ModuleHeader MOD_HEADER
"5.0", /* Version */
"/chgident", /* Short description of module */
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
@@ -63,7 +63,7 @@ MOD_UNLOAD()
CMD_FUNC(cmd_chgident)
{
Client *target;
- char *s;
+ const char *s;
int legalident = 1;
if (!ValidatePermissionsForPath("client:set:ident",client,NULL,NULL,NULL))
@@ -102,7 +102,7 @@ CMD_FUNC(cmd_chgident)
return;
}
- if (!(target = find_person(parv[1], NULL)))
+ if (!(target = find_user(parv[1], NULL)))
{
sendnumeric(client, ERR_NOSUCHNICK, parv[1]);
return;
@@ -134,15 +134,11 @@ CMD_FUNC(cmd_chgident)
}
if (!IsULine(client))
{
- sendto_snomask(SNO_EYES,
- "%s changed the virtual ident of %s (%s@%s) to be %s",
- client->name, target->name, target->user->username,
- GetHost(target), parv[2]);
- /* Logging ability added by XeRXeS */
- ircd_log(LOG_CHGCMDS,
- "CHGIDENT: %s changed the virtual ident of %s (%s@%s) to be %s",
- client->name, target->name, target->user->username,
- GetHost(target), parv[2]);
+ unreal_log(ULOG_INFO, "chgcmds", "CHGIDENT_COMMAND", client,
+ "CHGIDENT: $client changed the username of $target.details to be $new_username",
+ log_data_string("change_type", "username"),
+ log_data_client("target", target),
+ log_data_string("new_username", parv[2]));
}
sendto_server(client, 0, 0, NULL, ":%s CHGIDENT %s %s",
diff --git a/src/modules/chgname.c b/src/modules/chgname.c
index 2866117..ed6b089 100644
--- a/src/modules/chgname.c
+++ b/src/modules/chgname.c
@@ -31,7 +31,7 @@ ModuleHeader MOD_HEADER
"5.0", /* Version */
"command /chgname", /* Short description of module */
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
@@ -88,7 +88,7 @@ CMD_FUNC(cmd_chgname)
return;
}
- if (!(target = find_person(parv[1], NULL)))
+ if (!(target = find_user(parv[1], NULL)))
{
sendnumeric(client, ERR_NOSUCHNICK, parv[1]);
return;
@@ -97,15 +97,11 @@ CMD_FUNC(cmd_chgname)
/* Let's log this first */
if (!IsULine(client))
{
- sendto_snomask(SNO_EYES,
- "%s changed the GECOS of %s (%s@%s) to be %s",
- client->name, target->name, target->user->username,
- GetHost(target), parv[2]);
- /* Logging ability added by XeRXeS */
- ircd_log(LOG_CHGCMDS,
- "CHGNAME: %s changed the GECOS of %s (%s@%s) to be %s",
- client->name, target->name, target->user->username,
- GetHost(target), parv[2]);
+ unreal_log(ULOG_INFO, "chgcmds", "CHGNAME_COMMAND", client,
+ "CHGNAME: $client changed the realname of $target.details to be $new_realname",
+ log_data_string("change_type", "realname"),
+ log_data_client("target", target),
+ log_data_string("new_realname", parv[2]));
}
/* set the realname to make ban checking work */
diff --git a/src/modules/clienttagdeny.c b/src/modules/clienttagdeny.c
index 2552d49..4add58a 100644
--- a/src/modules/clienttagdeny.c
+++ b/src/modules/clienttagdeny.c
@@ -32,7 +32,7 @@ ModuleHeader MOD_HEADER = {
"5.0",
"Informs clients about supported client tags",
"k4be",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT(){
@@ -62,7 +62,7 @@ char *ct_isupport_param(void){
strlcpy(buf, "*", sizeof(buf));
for (m = mtaghandlers; m; m = m->next) {
- if(!m->unloaded && m->name[0] == '+'){
+ if (!m->unloaded && m->name[0] == '+'){
strlcat(buf, ",-", sizeof(buf));
strlcat(buf, m->name+1, sizeof(buf));
}
diff --git a/src/modules/cloak.c b/src/modules/cloak_md5.c
similarity index 84%
rename from src/modules/cloak.c
rename to src/modules/cloak_md5.c
index a28a53b..74df253 100644
--- a/src/modules/cloak.c
+++ b/src/modules/cloak_md5.c
@@ -1,6 +1,6 @@
/*
- * IRC - Internet Relay Chat, src/modules/cloak.c
- * (C) 2004 The UnrealIRCd Team
+ * IRC - Internet Relay Chat, src/modules/cloak_md5.c
+ * (C) 2004-2017 Bram Matthys and The UnrealIRCd Team
*
* See file AUTHORS in IRC package for additional names of
* the programmers.
@@ -46,28 +46,26 @@ static char *hidehost_ipv6(char *host);
static char *hidehost_normalhost(char *host);
static inline unsigned int downsample(char *i);
-Callback *cloak = NULL, *cloak_csum = NULL;
-
ModuleHeader MOD_HEADER = {
- "cloak",
+ "cloak_md5",
"1.0",
- "Official cloaking module (md5)",
+ "Old cloaking module (MD5)",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_TEST()
{
- cloak = CallbackAddPCharEx(modinfo->handle, CALLBACKTYPE_CLOAK_EX, hidehost);
- if (!cloak)
+ if (!CallbackAddString(modinfo->handle, CALLBACKTYPE_CLOAK_KEY_CHECKSUM, cloakcsum))
{
- config_error("cloak: Error while trying to install cloaking callback!");
+ unreal_log(ULOG_ERROR, "config", "CLOAK_MODULE_DUPLICATE", NULL,
+ "cloak_md5: Error while trying to install callback.\n"
+ "Maybe you have multiple cloaking modules loaded? You can only load one!");
return MOD_FAILED;
}
- cloak_csum = CallbackAddPCharEx(modinfo->handle, CALLBACKTYPE_CLOAKKEYCSUM, cloakcsum);
- if (!cloak_csum)
+ if (!CallbackAddString(modinfo->handle, CALLBACKTYPE_CLOAK_EX, hidehost))
{
- config_error("cloak: Error while trying to install cloaking checksum callback!");
+ config_error("cloak_md5: Error while trying to install cloaking callback!");
return MOD_FAILED;
}
HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, cloak_config_test);
@@ -125,19 +123,19 @@ int cloak_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
if (type == CONFIG_SET)
{
/* set::cloak-method */
- if (!ce || !ce->ce_varname || strcmp(ce->ce_varname, "cloak-method"))
+ if (!ce || !ce->name || strcmp(ce->name, "cloak-method"))
return 0;
- if (!ce->ce_vardata)
+ if (!ce->value)
{
config_error("%s:%i: set::cloak-method: no method specified. The only supported methods are: 'ip' and 'host'",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
} else
- if (strcmp(ce->ce_vardata, "ip") && strcmp(ce->ce_vardata, "host"))
+ if (strcmp(ce->value, "ip") && strcmp(ce->value, "host"))
{
config_error("%s:%i: set::cloak-method: unknown method '%s'. The only supported methods are: 'ip' and 'host'",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_vardata);
+ ce->file->filename, ce->line_number, ce->value);
errors++;
}
@@ -149,41 +147,40 @@ int cloak_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
return 0;
nokeys = 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
keycnt++;
- /* TODO: check randomness */
- if (check_badrandomness(cep->ce_varname))
+ if (check_badrandomness(cep->name))
{
config_error("%s:%i: set::cloak-keys: (key %d) Keys should be mixed a-zA-Z0-9, "
- "like \"a2JO6fh3Q6w4oN3s7\"", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, keycnt);
+ "like \"a2JO6fh3Q6w4oN3s7\"", cep->file->filename, cep->line_number, keycnt);
errors++;
}
- if (strlen(cep->ce_varname) < 5)
+ if (strlen(cep->name) < 5)
{
config_error("%s:%i: set::cloak-keys: (key %d) Each key should be at least 5 characters",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, keycnt);
+ cep->file->filename, cep->line_number, keycnt);
errors++;
}
- if (strlen(cep->ce_varname) > 100)
+ if (strlen(cep->name) > 100)
{
config_error("%s:%i: set::cloak-keys: (key %d) Each key should be less than 100 characters",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, keycnt);
+ cep->file->filename, cep->line_number, keycnt);
errors++;
}
if (keycnt < 4)
- keys[keycnt-1] = cep->ce_varname;
+ keys[keycnt-1] = cep->name;
}
if (keycnt != 3)
{
config_error("%s:%i: set::cloak-keys: we want 3 values, not %i!",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum, keycnt);
+ ce->file->filename, ce->line_number, keycnt);
errors++;
}
if ((keycnt == 3) && (!strcmp(keys[0], keys[1]) || !strcmp(keys[1], keys[2])))
{
config_error("%s:%i: set::cloak-keys: All your 3 keys should be RANDOM, they should not be equal",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
}
*errs = errors;
@@ -212,10 +209,10 @@ char buf[512], result[16];
if (type == CONFIG_SET)
{
/* set::cloak-method */
- if (!ce || !ce->ce_varname || strcmp(ce->ce_varname, "cloak-method"))
+ if (!ce || !ce->name || strcmp(ce->name, "cloak-method"))
return 0;
- if (!strcmp(ce->ce_vardata, "ip"))
+ if (!strcmp(ce->value, "ip"))
CLOAK_IP_ONLY = 1;
return 0;
@@ -225,12 +222,12 @@ char buf[512], result[16];
return 0;
/* config test should ensure this goes fine... */
- cep = ce->ce_entries;
- safe_strdup(cloak_key1, cep->ce_varname);
- cep = cep->ce_next;
- safe_strdup(cloak_key2, cep->ce_varname);
- cep = cep->ce_next;
- safe_strdup(cloak_key3, cep->ce_varname);
+ cep = ce->items;
+ safe_strdup(cloak_key1, cep->name);
+ cep = cep->next;
+ safe_strdup(cloak_key2, cep->name);
+ cep = cep->next;
+ safe_strdup(cloak_key3, cep->name);
/* Calculate checksum */
ircsnprintf(buf, sizeof(buf), "%s:%s:%s", KEY1, KEY2, KEY3);
@@ -412,14 +409,14 @@ unsigned int alpha, n;
{
unsigned int len;
p++;
- ircsnprintf(result, sizeof(result), "%s-%X.", hidden_host, alpha);
+ ircsnprintf(result, sizeof(result), "%s-%X.", CLOAK_PREFIX, alpha);
len = strlen(result) + strlen(p);
if (len <= HOSTLEN)
strlcat(result, p, sizeof(result));
else
strlcat(result, p + (len - HOSTLEN), sizeof(result));
} else
- ircsnprintf(result, sizeof(result), "%s-%X", hidden_host, alpha);
+ ircsnprintf(result, sizeof(result), "%s-%X", CLOAK_PREFIX, alpha);
return result;
}
diff --git a/src/modules/cloak_none.c b/src/modules/cloak_none.c
new file mode 100644
index 0000000..4cb627d
--- /dev/null
+++ b/src/modules/cloak_none.c
@@ -0,0 +1,87 @@
+/*
+ * IRC - Internet Relay Chat, src/modules/cloak_none.c
+ * (C) 2021 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.
+ */
+
+#include "unrealircd.h"
+
+char *cloakcsum();
+int cloak_config_test(ConfigFile *, ConfigEntry *, int, int *);
+
+ModuleHeader MOD_HEADER = {
+ "cloak_none",
+ "1.0",
+ "Cloaking module that does nothing",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+};
+
+MOD_TEST()
+{
+ if (!CallbackAddString(modinfo->handle, CALLBACKTYPE_CLOAK_KEY_CHECKSUM, cloakcsum))
+ {
+ unreal_log(ULOG_ERROR, "config", "CLOAK_MODULE_DUPLICATE", NULL,
+ "cloak_none: Error while trying to install callback.\n"
+ "Maybe you have multiple cloaking modules loaded? You can only load one!");
+ return MOD_FAILED;
+ }
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, cloak_config_test);
+ return MOD_SUCCESS;
+}
+
+MOD_INIT()
+{
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ return MOD_SUCCESS;
+}
+
+int cloak_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
+{
+ int errors = 0;
+
+ if (type != CONFIG_CLOAKKEYS)
+ return 0;
+
+ if (ce->items)
+ {
+ config_error("%s:%i: The cloaking module 'cloak_none' is loaded (no cloaking) but "
+ "you also have set::cloak-keys set. Either delete your cloak keys, "
+ "or switch to a real cloaking module.",
+ ce->file->filename, ce->line_number);
+ errors++;
+ }
+ *errs = errors;
+ return errors ? -1 : 1;
+}
+
+char *cloakcsum()
+{
+ return "NONE";
+}
diff --git a/src/modules/cloak_sha256.c b/src/modules/cloak_sha256.c
new file mode 100644
index 0000000..3200a86
--- /dev/null
+++ b/src/modules/cloak_sha256.c
@@ -0,0 +1,411 @@
+/*
+ * IRC - Internet Relay Chat, src/modules/cloak_sha256.c
+ * (C) 2004-2021 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.
+ */
+
+#include "unrealircd.h"
+
+static char *cloak_key1 = NULL, *cloak_key2 = NULL, *cloak_key3 = NULL;
+static char cloak_checksum[64];
+static int nokeys = 1;
+
+int CLOAK_IP_ONLY = 0;
+
+#undef KEY1
+#undef KEY2
+#undef KEY3
+#define KEY1 cloak_key1
+#define KEY2 cloak_key2
+#define KEY3 cloak_key3
+
+#define SHA256_HASH_SIZE (256/8)
+
+char *hidehost(Client *client, char *host);
+char *cloakcsum();
+int cloak_config_test(ConfigFile *, ConfigEntry *, int, int *);
+int cloak_config_run(ConfigFile *, ConfigEntry *, int);
+int cloak_config_posttest(int *);
+
+static char *hidehost_ipv4(char *host);
+static char *hidehost_ipv6(char *host);
+static char *hidehost_normalhost(char *host);
+static inline unsigned int downsample(char *i);
+
+ModuleHeader MOD_HEADER = {
+ "cloak_sha256",
+ "1.0",
+ "Cloaking module (SHA256)",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+};
+
+MOD_TEST()
+{
+ if (!CallbackAddString(modinfo->handle, CALLBACKTYPE_CLOAK_KEY_CHECKSUM, cloakcsum))
+ {
+ unreal_log(ULOG_ERROR, "config", "CLOAK_MODULE_DUPLICATE", NULL,
+ "cloak_sha256: Error while trying to install callback.\n"
+ "Maybe you have multiple cloaking modules loaded? You can only load one!");
+ return MOD_FAILED;
+ }
+ if (!CallbackAddString(modinfo->handle, CALLBACKTYPE_CLOAK_EX, hidehost))
+ {
+ config_error("cloak_sha256: Error while trying to install cloaking callback!");
+ return MOD_FAILED;
+ }
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, cloak_config_test);
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGPOSTTEST, 0, cloak_config_posttest);
+ return MOD_SUCCESS;
+}
+
+MOD_INIT()
+{
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, cloak_config_run);
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ if (cloak_key1)
+ {
+ safe_free(cloak_key1);
+ safe_free(cloak_key2);
+ safe_free(cloak_key3);
+ }
+ return MOD_SUCCESS;
+}
+
+static int check_badrandomness(char *key)
+{
+ char gotlowcase=0, gotupcase=0, gotdigit=0;
+ char *p;
+
+ for (p=key; *p; p++)
+ {
+ if (islower(*p))
+ gotlowcase = 1;
+ else if (isupper(*p))
+ gotupcase = 1;
+ else if (isdigit(*p))
+ gotdigit = 1;
+ }
+
+ if (gotlowcase && gotupcase && gotdigit)
+ return 0;
+
+ return 1;
+}
+
+
+int cloak_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
+{
+ ConfigEntry *cep;
+ int keycnt = 0, errors = 0;
+ char *keys[3];
+
+ if (type == CONFIG_SET)
+ {
+ /* set::cloak-method */
+ if (!ce || !ce->name || strcmp(ce->name, "cloak-method"))
+ return 0;
+
+ if (!ce->value)
+ {
+ config_error("%s:%i: set::cloak-method: no method specified. The only supported methods are: 'ip' and 'host'",
+ ce->file->filename, ce->line_number);
+ errors++;
+ } else
+ if (strcmp(ce->value, "ip") && strcmp(ce->value, "host"))
+ {
+ config_error("%s:%i: set::cloak-method: unknown method '%s'. The only supported methods are: 'ip' and 'host'",
+ ce->file->filename, ce->line_number, ce->value);
+ errors++;
+ }
+
+ *errs = errors;
+ return errors ? -1 : 1;
+ }
+
+ if (type != CONFIG_CLOAKKEYS)
+ return 0;
+
+ nokeys = 0;
+ for (cep = ce->items; cep; cep = cep->next)
+ {
+ keycnt++;
+ if (check_badrandomness(cep->name))
+ {
+ config_error("%s:%i: set::cloak-keys: (key %d) Keys should be mixed a-zA-Z0-9, "
+ "like \"a2JO6fh3Q6w4oN3s7\"", cep->file->filename, cep->line_number, keycnt);
+ errors++;
+ }
+ if (strlen(cep->name) < 80)
+ {
+ config_error("%s:%i: set::cloak-keys: (key %d) Each key should be at least 80 characters",
+ cep->file->filename, cep->line_number, keycnt);
+ errors++;
+ }
+ if (strlen(cep->name) > 1000)
+ {
+ config_error("%s:%i: set::cloak-keys: (key %d) Each key should be less than 1000 characters",
+ cep->file->filename, cep->line_number, keycnt);
+ errors++;
+ }
+ if (keycnt < 4)
+ keys[keycnt-1] = cep->name;
+ }
+ if (keycnt != 3)
+ {
+ config_error("%s:%i: set::cloak-keys: we want 3 values, not %i!",
+ ce->file->filename, ce->line_number, keycnt);
+ errors++;
+ }
+ if ((keycnt == 3) && (!strcmp(keys[0], keys[1]) || !strcmp(keys[1], keys[2])))
+ {
+ config_error("%s:%i: set::cloak-keys: All your 3 keys should be RANDOM, they should not be equal",
+ ce->file->filename, ce->line_number);
+ errors++;
+ }
+ *errs = errors;
+ return errors ? -1 : 1;
+}
+
+int cloak_config_posttest(int *errs)
+{
+ int errors = 0;
+
+ if (nokeys)
+ {
+ config_error("set::cloak-keys missing!");
+ errors++;
+ }
+
+ *errs = errors;
+ return errors ? -1 : 1;
+}
+
+int cloak_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
+{
+ ConfigEntry *cep;
+ char buf[4096];
+ char result[128];
+
+ if (type == CONFIG_SET)
+ {
+ /* set::cloak-method */
+ if (!ce || !ce->name || strcmp(ce->name, "cloak-method"))
+ return 0;
+
+ if (!strcmp(ce->value, "ip"))
+ CLOAK_IP_ONLY = 1;
+
+ return 0;
+ }
+
+ if (type != CONFIG_CLOAKKEYS)
+ return 0;
+
+ /* config test should ensure this goes fine... */
+ cep = ce->items;
+ safe_strdup(cloak_key1, cep->name);
+ cep = cep->next;
+ safe_strdup(cloak_key2, cep->name);
+ cep = cep->next;
+ safe_strdup(cloak_key3, cep->name);
+
+ /* Calculate checksum */
+ ircsnprintf(buf, sizeof(buf), "%s:%s:%s", KEY1, KEY2, KEY3);
+ ircsnprintf(cloak_checksum, sizeof(cloak_checksum), "SHA256:%s", sha256hash(result, buf, strlen(buf)));
+ return 1;
+}
+
+char *hidehost(Client *client, char *host)
+{
+ char *p;
+ int host_type;
+
+ if (CLOAK_IP_ONLY)
+ host = GetIP(client);
+
+ host_type = is_valid_ip(host);
+
+ if (host_type == 4)
+ return hidehost_ipv4(host);
+ else if (host_type == 6)
+ return hidehost_ipv6(host);
+ else
+ return hidehost_normalhost(host);
+}
+
+char *cloakcsum()
+{
+ return cloak_checksum;
+}
+
+/** Downsamples a 256 bit result to 32 bits (SHA256 -> unsigned int) */
+static inline unsigned int downsample(char *i)
+{
+ char r[4];
+
+ r[0] = i[0] ^ i[1] ^ i[2] ^ i[3] ^ i[4] ^ i[5] ^ i[6] ^ i[7];
+ r[1] = i[8] ^ i[9] ^ i[10] ^ i[11] ^ i[12] ^ i[13] ^ i[14] ^ i[15];
+ r[2] = i[16] ^ i[17] ^ i[18] ^ i[19] ^ i[20] ^ i[21] ^ i[22] ^ i[23];
+ r[3] = i[24] ^ i[25] ^ i[26] ^ i[27] ^ i[28] ^ i[29] ^ i[30] ^ i[31];
+
+ return ( ((unsigned int)r[0] << 24) +
+ ((unsigned int)r[1] << 16) +
+ ((unsigned int)r[2] << 8) +
+ (unsigned int)r[3]);
+}
+
+static char *hidehost_ipv4(char *host)
+{
+ unsigned int a, b, c, d;
+ static char buf[512], res[512], res2[512], result[128];
+ unsigned long n;
+ unsigned int alpha, beta, gamma;
+
+ /*
+ * Output: ALPHA.BETA.GAMMA.IP
+ * ALPHA is unique for a.b.c.d
+ * BETA is unique for a.b.c.*
+ * GAMMA is unique for a.b.*
+ * We cloak like this:
+ * ALPHA = downsample(sha256(sha256("KEY2:A.B.C.D:KEY3")+"KEY1"));
+ * BETA = downsample(sha256(sha256("KEY3:A.B.C:KEY1")+"KEY2"));
+ * GAMMA = downsample(sha256(sha256("KEY1:A.B:KEY2")+"KEY3"));
+ */
+ sscanf(host, "%u.%u.%u.%u", &a, &b, &c, &d);
+
+ /* ALPHA... */
+ ircsnprintf(buf, sizeof(buf), "%s:%s:%s", KEY2, host, KEY3);
+ sha256hash_binary(res, buf, strlen(buf));
+ strlcpy(res+SHA256_HASH_SIZE, KEY1, sizeof(res)-SHA256_HASH_SIZE); /* first bytes are filled, append our key.. */
+ n = strlen(res+SHA256_HASH_SIZE) + SHA256_HASH_SIZE;
+ sha256hash_binary(res2, res, n);
+ alpha = downsample(res2);
+
+ /* BETA... */
+ ircsnprintf(buf, sizeof(buf), "%s:%d.%d.%d:%s", KEY3, a, b, c, KEY1);
+ sha256hash_binary(res, buf, strlen(buf));
+ strlcpy(res+SHA256_HASH_SIZE, KEY2, sizeof(res)-SHA256_HASH_SIZE); /* first bytes are filled, append our key.. */
+ n = strlen(res+SHA256_HASH_SIZE) + SHA256_HASH_SIZE;
+ sha256hash_binary(res2, res, n);
+ beta = downsample(res2);
+
+ /* GAMMA... */
+ ircsnprintf(buf, sizeof(buf), "%s:%d.%d:%s", KEY1, a, b, KEY2);
+ sha256hash_binary(res, buf, strlen(buf));
+ strlcpy(res+SHA256_HASH_SIZE, KEY3, sizeof(res)-SHA256_HASH_SIZE); /* first bytes are filled, append our key.. */
+ n = strlen(res+SHA256_HASH_SIZE) + SHA256_HASH_SIZE;
+ sha256hash_binary(res2, res, n);
+ gamma = downsample(res2);
+
+ ircsnprintf(result, sizeof(result), "%X.%X.%X.IP", alpha, beta, gamma);
+ return result;
+}
+
+static char *hidehost_ipv6(char *host)
+{
+ unsigned int a, b, c, d, e, f, g, h;
+ static char buf[512], res[512], res2[512], result[128];
+ unsigned long n;
+ unsigned int alpha, beta, gamma;
+
+ /*
+ * Output: ALPHA:BETA:GAMMA:IP
+ * ALPHA is unique for a:b:c:d:e:f:g:h
+ * BETA is unique for a:b:c:d:e:f:g
+ * GAMMA is unique for a:b:c:d
+ * We cloak like this:
+ * ALPHA = downsample(sha256(sha256("KEY2:a:b:c:d:e:f:g:h:KEY3")+"KEY1"));
+ * BETA = downsample(sha256(sha256("KEY3:a:b:c:d:e:f:g:KEY1")+"KEY2"));
+ * GAMMA = downsample(sha256(sha256("KEY1:a:b:c:d:KEY2")+"KEY3"));
+ */
+ sscanf(host, "%x:%x:%x:%x:%x:%x:%x:%x",
+ &a, &b, &c, &d, &e, &f, &g, &h);
+
+ /* ALPHA... */
+ ircsnprintf(buf, sizeof(buf), "%s:%s:%s", KEY2, host, KEY3);
+ sha256hash_binary(res, buf, strlen(buf));
+ strlcpy(res+SHA256_HASH_SIZE, KEY1, sizeof(res)-SHA256_HASH_SIZE); /* first bytes are filled, append our key.. */
+ n = strlen(res+SHA256_HASH_SIZE) + SHA256_HASH_SIZE;
+ sha256hash_binary(res2, res, n);
+ alpha = downsample(res2);
+
+ /* BETA... */
+ ircsnprintf(buf, sizeof(buf), "%s:%x:%x:%x:%x:%x:%x:%x:%s", KEY3, a, b, c, d, e, f, g, KEY1);
+ sha256hash_binary(res, buf, strlen(buf));
+ strlcpy(res+SHA256_HASH_SIZE, KEY2, sizeof(res)-SHA256_HASH_SIZE); /* first bytes are filled, append our key.. */
+ n = strlen(res+SHA256_HASH_SIZE) + SHA256_HASH_SIZE;
+ sha256hash_binary(res2, res, n);
+ beta = downsample(res2);
+
+ /* GAMMA... */
+ ircsnprintf(buf, sizeof(buf), "%s:%x:%x:%x:%x:%s", KEY1, a, b, c, d, KEY2);
+ sha256hash_binary(res, buf, strlen(buf));
+ strlcpy(res+SHA256_HASH_SIZE, KEY3, sizeof(res)-SHA256_HASH_SIZE); /* first bytes are filled, append our key.. */
+ n = strlen(res+SHA256_HASH_SIZE) + SHA256_HASH_SIZE;
+ sha256hash_binary(res2, res, n);
+ gamma = downsample(res2);
+
+ ircsnprintf(result, sizeof(result), "%X:%X:%X:IP", alpha, beta, gamma);
+ return result;
+}
+
+static char *hidehost_normalhost(char *host)
+{
+ char *p;
+ static char buf[512], res[512], res2[512], result[HOSTLEN+1];
+ unsigned int alpha, n;
+
+ ircsnprintf(buf, sizeof(buf), "%s:%s:%s", KEY1, host, KEY2);
+ sha256hash_binary(res, buf, strlen(buf));
+ strlcpy(res+SHA256_HASH_SIZE, KEY3, sizeof(res)-SHA256_HASH_SIZE); /* first bytes are filled, append our key.. */
+ n = strlen(res+SHA256_HASH_SIZE) + SHA256_HASH_SIZE;
+ sha256hash_binary(res2, res, n);
+ alpha = downsample(res2);
+
+ for (p = host; *p; p++)
+ if (*p == '.')
+ if (isalpha(*(p + 1)))
+ break;
+
+ if (*p)
+ {
+ unsigned int len;
+ p++;
+ ircsnprintf(result, sizeof(result), "%s-%X.", CLOAK_PREFIX, alpha);
+ len = strlen(result) + strlen(p);
+ if (len <= HOSTLEN)
+ strlcat(result, p, sizeof(result));
+ else
+ strlcat(result, p + (len - HOSTLEN), sizeof(result));
+ } else
+ ircsnprintf(result, sizeof(result), "%s-%X", CLOAK_PREFIX, alpha);
+
+ return result;
+}
diff --git a/src/modules/close.c b/src/modules/close.c
index e9f988e..a732990 100644
--- a/src/modules/close.c
+++ b/src/modules/close.c
@@ -32,7 +32,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /close",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
@@ -75,7 +75,8 @@ CMD_FUNC(cmd_close)
}
sendnumeric(client, RPL_CLOSEEND, closed);
- sendto_realops("%s!%s@%s closed %d unknown connections", client->name,
- client->user->username, GetHost(client), closed);
+ unreal_log(ULOG_INFO, "close", "CLOSED_CONNECTIONS", client,
+ "$client.details closed $num_closed unknown connections",
+ log_data_integer("num_closed", closed));
irccounts.unknown = 0;
}
diff --git a/src/modules/connect.c b/src/modules/connect.c
index e5c47bd..59cff3c 100644
--- a/src/modules/connect.c
+++ b/src/modules/connect.c
@@ -32,7 +32,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /connect",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
@@ -76,7 +76,7 @@ CMD_FUNC(cmd_connect)
sendnumeric(client, ERR_NOPRIVILEGES);
return;
}
- if (hunt_server(client, recv_mtags, ":%s CONNECT %s %s :%s", 3, parc, parv) != HUNTED_ISME)
+ if (hunt_server(client, recv_mtags, "CONNECT", 3, parc, parv) != HUNTED_ISME)
return;
if (parc < 2 || *parv[1] == '\0')
@@ -117,7 +117,7 @@ CMD_FUNC(cmd_connect)
/* Evaluate deny link */
for (deny = conf_deny_link; deny; deny = deny->next)
{
- if (deny->flag.type == CRULE_ALL && match_simple(deny->mask, aconf->servername)
+ if (deny->flag.type == CRULE_ALL && unreal_mask_match_string(aconf->servername, deny->mask)
&& crule_eval(deny->rule))
{
sendnotice(client, "*** Connect: Disallowed by connection rule");
@@ -134,22 +134,5 @@ CMD_FUNC(cmd_connect)
get_client_name(client, FALSE));
}
- switch (retval = connect_server(aconf, client, NULL))
- {
- case 0:
- sendnotice(client, "*** Trying to activate link with server %s[%s]...",
- aconf->servername, aconf->outgoing.hostname);
- break;
- case -1:
- sendnotice(client, "*** Couldn't connect to %s[%s]",
- aconf->servername, aconf->outgoing.hostname);
- break;
- case -2:
- sendnotice(client, "*** Resolving hostname '%s'...",
- aconf->outgoing.hostname);
- break;
- default:
- sendnotice(client, "*** Connection to %s[%s] failed: %s",
- aconf->servername, aconf->outgoing.hostname, STRERROR(retval));
- }
+ connect_server(aconf, client, NULL);
}
diff --git a/src/modules/connthrottle.c b/src/modules/connthrottle.c
index 608e07c..5b35e2a 100644
--- a/src/modules/connthrottle.c
+++ b/src/modules/connthrottle.c
@@ -19,7 +19,7 @@ ModuleHeader MOD_HEADER
CONNTHROTTLE_VERSION,
"Connection throttler - by Syzop",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
typedef struct {
@@ -146,9 +146,6 @@ int ct_config_posttest(int *errs)
return errors ? -1 : 1;
}
-#ifndef CheckNull
- #define CheckNull(x) if ((!(x)->ce_vardata) || (!(*((x)->ce_vardata)))) { config_error("%s:%i: missing parameter", (x)->ce_fileptr->cf_filename, (x)->ce_varlinenum); errors++; continue; }
-#endif
/** Test the set::connthrottle configuration */
int ct_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
{
@@ -159,113 +156,113 @@ int ct_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
return 0;
/* We are only interrested in set::connthrottle.. */
- if (!ce || !ce->ce_varname || strcmp(ce->ce_varname, "connthrottle"))
+ if (!ce || !ce->name || strcmp(ce->name, "connthrottle"))
return 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "known-users"))
+ if (!strcmp(cep->name, "known-users"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
CheckNull(cepp);
- if (!strcmp(cepp->ce_varname, "minimum-reputation-score"))
+ if (!strcmp(cepp->name, "minimum-reputation-score"))
{
- int cnt = atoi(cepp->ce_vardata);
+ int cnt = atoi(cepp->value);
if (cnt < 1)
{
config_error("%s:%i: set::connthrottle::known-users::minimum-reputation-score should be at least 1",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum);
+ cepp->file->filename, cepp->line_number);
errors++;
continue;
}
} else
- if (!strcmp(cepp->ce_varname, "sasl-bypass"))
+ if (!strcmp(cepp->name, "sasl-bypass"))
{
} else
- if (!strcmp(cepp->ce_varname, "webirc-bypass"))
+ if (!strcmp(cepp->name, "webirc-bypass"))
{
} else
{
- config_error_unknown(cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum,
- "set::connthrottle::known-users", cepp->ce_varname);
+ config_error_unknown(cepp->file->filename, cepp->line_number,
+ "set::connthrottle::known-users", cepp->name);
errors++;
}
}
} else
- if (!strcmp(cep->ce_varname, "new-users"))
+ if (!strcmp(cep->name, "new-users"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
CheckNull(cepp);
- if (!strcmp(cepp->ce_varname, "local-throttle"))
+ if (!strcmp(cepp->name, "local-throttle"))
{
int cnt, period;
- if (!config_parse_flood(cepp->ce_vardata, &cnt, &period) ||
+ if (!config_parse_flood(cepp->value, &cnt, &period) ||
(cnt < 1) || (cnt > 2000000000) || (period > 2000000000))
{
config_error("%s:%i: set::connthrottle::new-users::local-throttle error. "
"Syntax is : (eg 6:60), "
"and count and period should be non-zero.",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum);
+ cepp->file->filename, cepp->line_number);
errors++;
continue;
}
} else
- if (!strcmp(cepp->ce_varname, "global-throttle"))
+ if (!strcmp(cepp->name, "global-throttle"))
{
int cnt, period;
- if (!config_parse_flood(cepp->ce_vardata, &cnt, &period) ||
+ if (!config_parse_flood(cepp->value, &cnt, &period) ||
(cnt < 1) || (cnt > 2000000000) || (period > 2000000000))
{
config_error("%s:%i: set::connthrottle::new-users::global-throttle error. "
"Syntax is : (eg 6:60), "
"and count and period should be non-zero.",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum);
+ cepp->file->filename, cepp->line_number);
errors++;
continue;
}
} else
{
- config_error_unknown(cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum,
- "set::connthrottle::new-users", cepp->ce_varname);
+ config_error_unknown(cepp->file->filename, cepp->line_number,
+ "set::connthrottle::new-users", cepp->name);
errors++;
}
}
} else
- if (!strcmp(cep->ce_varname, "disabled-when"))
+ if (!strcmp(cep->name, "disabled-when"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
CheckNull(cepp);
- if (!strcmp(cepp->ce_varname, "start-delay"))
+ if (!strcmp(cepp->name, "start-delay"))
{
- int cnt = config_checkval(cepp->ce_vardata, CFG_TIME);
+ int cnt = config_checkval(cepp->value, CFG_TIME);
if ((cnt < 0) || (cnt > 3600))
{
config_error("%s:%i: set::connthrottle::disabled-when::start-delay should be in range 0-3600",
- cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum);
+ cepp->file->filename, cepp->line_number);
errors++;
continue;
}
} else
- if (!strcmp(cepp->ce_varname, "reputation-gathering"))
+ if (!strcmp(cepp->name, "reputation-gathering"))
{
} else
{
- config_error_unknown(cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum,
- "set::connthrottle::disabled-when", cepp->ce_varname);
+ config_error_unknown(cepp->file->filename, cepp->line_number,
+ "set::connthrottle::disabled-when", cepp->name);
errors++;
}
}
} else
- if (!strcmp(cep->ce_varname, "reason"))
+ if (!strcmp(cep->name, "reason"))
{
CheckNull(cep);
} else
{
config_error("%s:%i: unknown directive set::connthrottle::%s",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname);
+ cep->file->filename, cep->line_number, cep->name);
errors++;
continue;
}
@@ -284,48 +281,48 @@ int ct_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
return 0;
/* We are only interrested in set::connthrottle.. */
- if (!ce || !ce->ce_varname || strcmp(ce->ce_varname, "connthrottle"))
+ if (!ce || !ce->name || strcmp(ce->name, "connthrottle"))
return 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "known-users"))
+ if (!strcmp(cep->name, "known-users"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "minimum-reputation-score"))
- cfg.minimum_reputation_score = atoi(cepp->ce_vardata);
- else if (!strcmp(cepp->ce_varname, "sasl-bypass"))
- cfg.sasl_bypass = config_checkval(cepp->ce_vardata, CFG_YESNO);
- else if (!strcmp(cepp->ce_varname, "webirc-bypass"))
- cfg.webirc_bypass = config_checkval(cepp->ce_vardata, CFG_YESNO);
+ if (!strcmp(cepp->name, "minimum-reputation-score"))
+ cfg.minimum_reputation_score = atoi(cepp->value);
+ else if (!strcmp(cepp->name, "sasl-bypass"))
+ cfg.sasl_bypass = config_checkval(cepp->value, CFG_YESNO);
+ else if (!strcmp(cepp->name, "webirc-bypass"))
+ cfg.webirc_bypass = config_checkval(cepp->value, CFG_YESNO);
}
} else
- if (!strcmp(cep->ce_varname, "new-users"))
+ if (!strcmp(cep->name, "new-users"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "local-throttle"))
- config_parse_flood(cepp->ce_vardata, &cfg.local.count, &cfg.local.period);
- else if (!strcmp(cepp->ce_varname, "global-throttle"))
- config_parse_flood(cepp->ce_vardata, &cfg.global.count, &cfg.global.period);
+ if (!strcmp(cepp->name, "local-throttle"))
+ config_parse_flood(cepp->value, &cfg.local.count, &cfg.local.period);
+ else if (!strcmp(cepp->name, "global-throttle"))
+ config_parse_flood(cepp->value, &cfg.global.count, &cfg.global.period);
}
} else
- if (!strcmp(cep->ce_varname, "disabled-when"))
+ if (!strcmp(cep->name, "disabled-when"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcmp(cepp->ce_varname, "start-delay"))
- cfg.start_delay = config_checkval(cepp->ce_vardata, CFG_TIME);
- else if (!strcmp(cepp->ce_varname, "reputation-gathering"))
- cfg.reputation_gathering = config_checkval(cepp->ce_vardata, CFG_TIME);
+ if (!strcmp(cepp->name, "start-delay"))
+ cfg.start_delay = config_checkval(cepp->value, CFG_TIME);
+ else if (!strcmp(cepp->name, "reputation-gathering"))
+ cfg.reputation_gathering = config_checkval(cepp->value, CFG_TIME);
}
} else
- if (!strcmp(cep->ce_varname, "reason"))
+ if (!strcmp(cep->name, "reason"))
{
safe_free(cfg.reason);
- cfg.reason = safe_alloc(strlen(cep->ce_vardata)+16);
- sprintf(cfg.reason, "Throttled: %s", cep->ce_vardata);
+ cfg.reason = safe_alloc(strlen(cep->value)+16);
+ sprintf(cfg.reason, "Throttled: %s", cep->value);
}
}
return 1;
@@ -360,16 +357,18 @@ EVENT(connthrottle_evt)
if (ucounter->rejected_clients)
{
- snprintf(buf, sizeof(buf),
- "[ConnThrottle] Stats for this server past 60 secs: Connections rejected: %d. Accepted: %d known user(s), %d SASL, %d WEBIRC and %d new user(s).",
- ucounter->rejected_clients,
- ucounter->allowed_score,
- ucounter->allowed_sasl,
- ucounter->allowed_webirc,
- ucounter->allowed_other);
-
- sendto_realops("%s", buf);
- ircd_log(LOG_ERROR, "%s", buf);
+ unreal_log(ULOG_INFO, "connthrottle", "CONNTHROTLE_REPORT", NULL,
+ "ConnThrottle] Stats for this server past 60 secs: "
+ "Connections rejected: $num_rejected. "
+ "Accepted: $num_accepted_known_users known user(s), "
+ "$num_accepted_sasl SASL, "
+ "$num_accepted_webirc WEBIRC and "
+ "$num_accepted_unknown_users new user(s).",
+ log_data_integer("num_rejected", ucounter->rejected_clients),
+ log_data_integer("num_accepted_known_users", ucounter->allowed_score),
+ log_data_integer("num_accepted_sasl", ucounter->allowed_sasl),
+ log_data_integer("num_accepted_webirc", ucounter->allowed_webirc),
+ log_data_integer("num_accepted_unknown_users", ucounter->allowed_other));
}
/* Reset stats for next message */
@@ -391,7 +390,7 @@ int ct_pre_lconnect(Client *client)
int throttle=0;
int score;
- if (me.local->firsttime + cfg.start_delay > TStime())
+ if (me.local->creationtime + cfg.start_delay > TStime())
return HOOK_CONTINUE; /* no throttle: start delay */
if (ucounter->disabled)
@@ -436,10 +435,10 @@ int ct_pre_lconnect(Client *client)
/* We send the LARGE banner if throttling was activated */
if (!ucounter->throttling_previous_minute && !ucounter->throttling_banner_displayed)
{
- ircd_log(LOG_ERROR, "[ConnThrottle] Connection throttling has been ACTIVATED due to a HIGH CONNECTION RATE.");
- sendto_realops("[ConnThrottle] Connection throttling has been ACTIVATED due to a HIGH CONNECTION RATE.");
- sendto_realops("[ConnThrottle] Users with IP addresses that have not been seen before will be rejected above the set connection rate. Known users can still get in.");
- sendto_realops("[ConnThrottle] For more information see https://www.unrealircd.org/docs/ConnThrottle");
+ unreal_log(ULOG_WARNING, "connthrottle", "CONNTHROTLE_ACTIVATED", NULL,
+ "[ConnThrottle] Connection throttling has been ACTIVATED due to a HIGH CONNECTION RATE.\n"
+ "Users with IP addresses that have not been seen before will be rejected above the set connection rate. Known users can still get in.\n"
+ "or more information see https://www.unrealircd.org/docs/ConnThrottle");
ucounter->throttling_banner_displayed = 1;
}
exit_client(client, NULL, cfg.reason);
@@ -478,7 +477,7 @@ int ct_lconnect(Client *client)
{
int score;
- if (me.local->firsttime + cfg.start_delay > TStime())
+ if (me.local->creationtime + cfg.start_delay > TStime())
return 0; /* no throttle: start delay */
if (ucounter->disabled)
@@ -521,7 +520,7 @@ int ct_rconnect(Client *client)
{
int score;
- if (client->srvptr && !IsSynched(client->srvptr))
+ if (client->uplink && !IsSynched(client->uplink))
return 0; /* Netmerge: skip */
if (IsULine(client))
@@ -533,8 +532,8 @@ int ct_rconnect(Client *client)
* set::disabled-when::start-delay restriction on remote
* servers as well.
*/
- if (client->srvptr && client->srvptr->serv && client->srvptr->serv->boottime &&
- (TStime() - client->srvptr->serv->boottime < cfg.start_delay))
+ if (client->uplink && client->uplink->server && client->uplink->server->boottime &&
+ (TStime() - client->uplink->server->boottime < cfg.start_delay))
{
return 0;
}
@@ -584,10 +583,10 @@ CMD_FUNC(ct_throttle)
{
sendnotice(client, "Module DISABLED because the 'reputation' module has not gathered enough data yet (set::connthrottle::disabled-when::reputation-gathering).");
} else
- if (me.local->firsttime + cfg.start_delay > TStime())
+ if (me.local->creationtime + cfg.start_delay > TStime())
{
sendnotice(client, "Module DISABLED due to start-delay (set::connthrottle::disabled-when::start-delay), will be enabled in %lld second(s).",
- (long long)((me.local->firsttime + cfg.start_delay) - TStime()));
+ (long long)((me.local->creationtime + cfg.start_delay) - TStime()));
} else
{
sendnotice(client, "Module ENABLED");
@@ -602,8 +601,8 @@ CMD_FUNC(ct_throttle)
return;
}
ucounter->disabled = 1;
- sendto_realops("[connthrottle] %s (%s@%s) DISABLED the connthrottle module.",
- client->name, client->user->username, client->user->realhost);
+ unreal_log(ULOG_WARNING, "connthrottle", "CONNTHROTLE_MODULE_DISABLED", client,
+ "[ConnThrottle] $client.details DISABLED the connthrottle module.");
} else
if (!strcasecmp(parv[1], "ON"))
{
@@ -612,15 +611,15 @@ CMD_FUNC(ct_throttle)
sendnotice(client, "Already ON");
return;
}
- sendto_realops("[connthrottle] %s (%s@%s) ENABLED the connthrottle module.",
- client->name, client->user->username, client->user->realhost);
+ unreal_log(ULOG_WARNING, "connthrottle", "CONNTHROTLE_MODULE_ENABLED", client,
+ "[ConnThrottle] $client.details ENABLED the connthrottle module.");
ucounter->disabled = 0;
} else
if (!strcasecmp(parv[1], "RESET"))
{
memset(ucounter, 0, sizeof(UCounter));
- sendto_realops("[connthrottle] %s (%s@%s) did a RESET on the stats/counters!!",
- client->name, client->user->username, client->user->realhost);
+ unreal_log(ULOG_WARNING, "connthrottle", "CONNTHROTLE_RESET", client,
+ "[ConnThrottle] $client.details did a RESET on the statistics/counters.");
} else
{
sendnotice(client, "Unknown option '%s'", parv[1]);
diff --git a/src/modules/cycle.c b/src/modules/cycle.c
index 8953609..f1af457 100644
--- a/src/modules/cycle.c
+++ b/src/modules/cycle.c
@@ -30,7 +30,7 @@ ModuleHeader MOD_HEADER
"5.0", /* Version */
"command /cycle", /* Short description of module */
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* This is called on module init, before Server Ready */
@@ -62,6 +62,7 @@ MOD_UNLOAD()
CMD_FUNC(cmd_cycle)
{
char channels[BUFSIZE];
+ const char *parx[3];
int n;
if (parc < 2)
@@ -75,7 +76,8 @@ CMD_FUNC(cmd_cycle)
return;
/* Then JOIN the user again... */
- parv[1] = channels;
- parv[2] = NULL;
- do_cmd(client, recv_mtags, "JOIN", 2, parv);
+ parx[0] = NULL;
+ parx[1] = channels;
+ parx[2] = NULL;
+ do_cmd(client, recv_mtags, "JOIN", 2, parx);
}
diff --git a/src/modules/dccallow.c b/src/modules/dccallow.c
index ffeffd4..ce1ad49 100644
--- a/src/modules/dccallow.c
+++ b/src/modules/dccallow.c
@@ -32,7 +32,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /dccallow",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
@@ -59,6 +59,7 @@ MOD_UNLOAD()
*/
CMD_FUNC(cmd_dccallow)
{
+ char request[BUFSIZE];
Link *lp;
char *p, *s;
Client *friend;
@@ -92,7 +93,8 @@ CMD_FUNC(cmd_dccallow)
return;
}
- for (p = NULL, s = strtoken(&p, parv[1], ", "); s; s = strtoken(&p, NULL, ", "))
+ strlcpy(request, parv[1], sizeof(request));
+ for (p = NULL, s = strtoken(&p, request, ", "); s; s = strtoken(&p, NULL, ", "))
{
if (MyUser(client) && (++ntargets > maxtargets))
{
@@ -105,7 +107,7 @@ CMD_FUNC(cmd_dccallow)
if (!*++s)
continue;
- friend = find_person(s, NULL);
+ friend = find_user(s, NULL);
if (friend == client)
continue;
@@ -123,7 +125,7 @@ CMD_FUNC(cmd_dccallow)
if (!*++s)
continue;
- friend = find_person(s, NULL);
+ friend = find_user(s, NULL);
if (friend == client)
continue;
if (!friend)
@@ -243,8 +245,11 @@ int del_dccallow(Client *client, Client *optr)
}
}
if (!found)
- sendto_realops("[BUG!] %s was in dccallowme list of %s but not in dccallowrem list!",
- optr->name, client->name);
+ {
+ unreal_log(ULOG_WARNING, "dccallow", "BUG_DCCALLOW", client,
+ "[BUG] DCCALLOW list for $client did not contain $target",
+ log_data_client("target", optr));
+ }
sendnumeric(client, RPL_DCCSTATUS, optr->name, "removed from");
diff --git a/src/modules/dccdeny.c b/src/modules/dccdeny.c
index d27a9f7..0fda03f 100644
--- a/src/modules/dccdeny.c
+++ b/src/modules/dccdeny.c
@@ -28,7 +28,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /dccdeny",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Variables */
@@ -40,24 +40,26 @@ int dccdeny_configtest_deny_dcc(ConfigFile *cf, ConfigEntry *ce, int type, int *
int dccdeny_configtest_allow_dcc(ConfigFile *cf, ConfigEntry *ce, int type, int *errs);
int dccdeny_configrun_deny_dcc(ConfigFile *cf, ConfigEntry *ce, int type);
int dccdeny_configrun_allow_dcc(ConfigFile *cf, ConfigEntry *ce, int type);
-int dccdeny_stats(Client *client, char *para);
+int dccdeny_stats(Client *client, const char *para);
+int dccdeny_dcc_denied(Client *client, const char *target, const char *realfile, const char *displayfile, ConfigItem_deny_dcc *dccdeny);
CMD_FUNC(cmd_dccdeny);
CMD_FUNC(cmd_undccdeny);
CMD_FUNC(cmd_svsfline);
-int dccdeny_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype);
-int dccdeny_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
+int dccdeny_can_send_to_user(Client *client, Client *target, const char **text, const char **errmsg, SendType sendtype);
+int dccdeny_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype);
int dccdeny_server_sync(Client *client);
-static ConfigItem_deny_dcc *dcc_isforbidden(Client *client, char *filename);
-static ConfigItem_deny_dcc *dcc_isdiscouraged(Client *client, char *filename);
-static void DCCdeny_add(char *filename, char *reason, int type, int type2);
+static ConfigItem_deny_dcc *dcc_isforbidden(Client *client, const char *filename);
+static ConfigItem_deny_dcc *dcc_isdiscouraged(Client *client, const char *filename);
+static void DCCdeny_add(const char *filename, const char *reason, int type, int type2);
static void DCCdeny_del(ConfigItem_deny_dcc *deny);
static void dcc_wipe_services(void);
-static char *get_dcc_filename(const char *text);
-static int can_dcc(Client *client, char *target, Client *targetcli, char *filename, char **errmsg);
-static int can_dcc_soft(Client *from, Client *to, char *filename, char **errmsg);
+static const char *get_dcc_filename(const char *text);
+static int can_dcc(Client *client, const char *target, Client *targetcli, const char *filename, const char **errmsg);
+static int can_dcc_soft(Client *from, Client *to, const char *filename, const char **errmsg);
static void free_dcc_config_blocks(void);
void dccdeny_unload_free_all_conf_deny_dcc(ModData *m);
void dccdeny_unload_free_all_conf_allow_dcc(ModData *m);
+ConfigItem_deny_dcc *find_deny_dcc(const char *name);
MOD_TEST()
{
@@ -80,6 +82,7 @@ MOD_INIT()
HookAdd(modinfo->handle, HOOKTYPE_CAN_SEND_TO_USER, 0, dccdeny_can_send_to_user);
HookAdd(modinfo->handle, HOOKTYPE_CAN_SEND_TO_CHANNEL, 0, dccdeny_can_send_to_channel);
HookAdd(modinfo->handle, HOOKTYPE_SERVER_SYNC, 0, dccdeny_server_sync);
+ HookAdd(modinfo->handle, HOOKTYPE_DCC_DENIED, 0, dccdeny_dcc_denied);
return MOD_SUCCESS;
}
@@ -104,62 +107,62 @@ int dccdeny_configtest_deny_dcc(ConfigFile *cf, ConfigEntry *ce, int type, int *
char has_filename = 0, has_reason = 0, has_soft = 0;
/* We are only interested in deny dcc { } */
- if ((type != CONFIG_DENY) || strcmp(ce->ce_vardata, "dcc"))
+ if ((type != CONFIG_DENY) || strcmp(ce->value, "dcc"))
return 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
if (config_is_blankorempty(cep, "deny dcc"))
{
errors++;
continue;
}
- if (!strcmp(cep->ce_varname, "filename"))
+ if (!strcmp(cep->name, "filename"))
{
if (has_filename)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny dcc::filename");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "deny dcc::filename");
continue;
}
has_filename = 1;
}
- else if (!strcmp(cep->ce_varname, "reason"))
+ else if (!strcmp(cep->name, "reason"))
{
if (has_reason)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny dcc::reason");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "deny dcc::reason");
continue;
}
has_reason = 1;
}
- else if (!strcmp(cep->ce_varname, "soft"))
+ else if (!strcmp(cep->name, "soft"))
{
if (has_soft)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny dcc::soft");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "deny dcc::soft");
continue;
}
has_soft = 1;
}
else
{
- config_error_unknown(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny dcc", cep->ce_varname);
+ config_error_unknown(cep->file->filename,
+ cep->line_number, "deny dcc", cep->name);
errors++;
}
}
if (!has_filename)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"deny dcc::filename");
errors++;
}
if (!has_reason)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"deny dcc::reason");
errors++;
}
@@ -174,46 +177,46 @@ int dccdeny_configtest_allow_dcc(ConfigFile *cf, ConfigEntry *ce, int type, int
int errors = 0, has_filename = 0, has_soft = 0;
/* We are only interested in allow dcc { } */
- if ((type != CONFIG_ALLOW) || strcmp(ce->ce_vardata, "dcc"))
+ if ((type != CONFIG_ALLOW) || strcmp(ce->value, "dcc"))
return 0;
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
if (config_is_blankorempty(cep, "allow dcc"))
{
errors++;
continue;
}
- if (!strcmp(cep->ce_varname, "filename"))
+ if (!strcmp(cep->name, "filename"))
{
if (has_filename)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "allow dcc::filename");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "allow dcc::filename");
continue;
}
has_filename = 1;
}
- else if (!strcmp(cep->ce_varname, "soft"))
+ else if (!strcmp(cep->name, "soft"))
{
if (has_soft)
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "allow dcc::soft");
+ config_warn_duplicate(cep->file->filename,
+ cep->line_number, "allow dcc::soft");
continue;
}
has_soft = 1;
}
else
{
- config_error_unknown(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
- "allow dcc", cep->ce_varname);
+ config_error_unknown(cep->file->filename, cep->line_number,
+ "allow dcc", cep->name);
errors++;
}
}
if (!has_filename)
{
- config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
+ config_error_missing(ce->file->filename, ce->line_number,
"allow dcc::filename");
errors++;
}
@@ -228,23 +231,23 @@ int dccdeny_configrun_deny_dcc(ConfigFile *cf, ConfigEntry *ce, int type)
ConfigEntry *cep;
/* We are only interested in deny dcc { } */
- if ((type != CONFIG_DENY) || strcmp(ce->ce_vardata, "dcc"))
+ if ((type != CONFIG_DENY) || strcmp(ce->value, "dcc"))
return 0;
deny = safe_alloc(sizeof(ConfigItem_deny_dcc));
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "filename"))
+ if (!strcmp(cep->name, "filename"))
{
- safe_strdup(deny->filename, cep->ce_vardata);
+ safe_strdup(deny->filename, cep->value);
}
- else if (!strcmp(cep->ce_varname, "reason"))
+ else if (!strcmp(cep->name, "reason"))
{
- safe_strdup(deny->reason, cep->ce_vardata);
+ safe_strdup(deny->reason, cep->value);
}
- else if (!strcmp(cep->ce_varname, "soft"))
+ else if (!strcmp(cep->name, "soft"))
{
- int x = config_checkval(cep->ce_vardata,CFG_YESNO);
+ int x = config_checkval(cep->value,CFG_YESNO);
if (x == 1)
deny->flag.type = DCCDENY_SOFT;
}
@@ -266,18 +269,18 @@ int dccdeny_configrun_allow_dcc(ConfigFile *cf, ConfigEntry *ce, int type)
ConfigEntry *cep;
/* We are only interested in allow dcc { } */
- if ((type != CONFIG_ALLOW) || strcmp(ce->ce_vardata, "dcc"))
+ if ((type != CONFIG_ALLOW) || strcmp(ce->value, "dcc"))
return 0;
allow = safe_alloc(sizeof(ConfigItem_allow_dcc));
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "filename"))
- safe_strdup(allow->filename, cep->ce_vardata);
- else if (!strcmp(cep->ce_varname, "soft"))
+ if (!strcmp(cep->name, "filename"))
+ safe_strdup(allow->filename, cep->value);
+ else if (!strcmp(cep->name, "soft"))
{
- int x = config_checkval(cep->ce_vardata,CFG_YESNO);
+ int x = config_checkval(cep->value,CFG_YESNO);
if (x)
allow->flag.type = DCCDENY_SOFT;
}
@@ -371,8 +374,10 @@ CMD_FUNC(cmd_dccdeny)
if (!find_deny_dcc(parv[1]))
{
- sendto_ops("%s added a temp dccdeny for %s (%s)", client->name,
- parv[1], parv[2]);
+ unreal_log(ULOG_INFO, "dccdeny", "DCCDENY_ADD", client,
+ "[dccdeny] $client added a temporary DCCDENY for $file ($reason)",
+ log_data_string("file", parv[1]),
+ log_data_string("reason", parv[2]));
DCCdeny_add(parv[1], parv[2], DCCDENY_HARD, CONF_BAN_TYPE_TEMPORARY);
return;
} else
@@ -405,7 +410,10 @@ CMD_FUNC(cmd_undccdeny)
if ((d = find_deny_dcc(parv[1])) && d->flag.type2 == CONF_BAN_TYPE_TEMPORARY)
{
- sendto_ops("%s removed a temp dccdeny for %s", client->name, parv[1]);
+ unreal_log(ULOG_INFO, "dccdeny", "DCCDENY_DEL", client,
+ "[dccdeny] $client removed a temporary DCCDENY for $file ($reason)",
+ log_data_string("file", d->filename),
+ log_data_string("reason", d->reason));
DCCdeny_del(d);
return;
} else
@@ -489,11 +497,11 @@ int dccdeny_server_sync(Client *client)
}
/** Check if a DCC should be blocked (user-to-user) */
-int dccdeny_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype)
+int dccdeny_can_send_to_user(Client *client, Client *target, const char **text, const char **errmsg, SendType sendtype)
{
if (**text == '\001')
{
- char *filename = get_dcc_filename(*text);
+ const char *filename = get_dcc_filename(*text);
if (filename)
{
if (MyUser(client) && !can_dcc(client, target->name, target, filename, errmsg))
@@ -507,15 +515,15 @@ int dccdeny_can_send_to_user(Client *client, Client *target, char **text, char *
}
/** Check if a DCC should be blocked (user-to-channel, unusual) */
-int dccdeny_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
+int dccdeny_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype)
{
static char errbuf[512];
if (MyUser(client) && (**msg == '\001'))
{
- char *err = NULL;
- char *filename = get_dcc_filename(*msg);
- if (filename && !can_dcc(client, channel->chname, NULL, filename, &err))
+ const char *err = NULL;
+ const char *filename = get_dcc_filename(*msg);
+ if (filename && !can_dcc(client, channel->name, NULL, filename, &err))
{
if (!IsDead(client) && (sendtype != SEND_TYPE_NOTICE))
{
@@ -541,10 +549,11 @@ int dccdeny_can_send_to_channel(Client *client, Channel *channel, Membership *lp
* This is to protect a bit against tricks like 'flood-it-off-the-buffer'
* and color 1,1 etc...
*/
-static char *dcc_displayfile(char *f)
+static const char *dcc_displayfile(const char *f)
{
static char buf[512];
- char *i, *o = buf;
+ const char *i;
+ char *o = buf;
size_t n = strlen(f);
if (n < 300)
@@ -575,7 +584,7 @@ static char *dcc_displayfile(char *f)
return buf;
}
-static char *get_dcc_filename(const char *text)
+static const char *get_dcc_filename(const char *text)
{
static char filename[BUFSIZE+1];
char *end;
@@ -617,7 +626,7 @@ static char *get_dcc_filename(const char *text)
* @param text The entire message
* @returns 1 if DCC SEND allowed, 0 if rejected
*/
-static int can_dcc(Client *client, char *target, Client *targetcli, char *filename, char **errmsg)
+static int can_dcc(Client *client, const char *target, Client *targetcli, const char *filename, const char **errmsg)
{
ConfigItem_deny_dcc *fl;
static char errbuf[256];
@@ -644,9 +653,9 @@ static int can_dcc(Client *client, char *target, Client *targetcli, char *filena
if ((fl = dcc_isforbidden(client, filename)))
{
- char *displayfile = dcc_displayfile(filename);
+ const char *displayfile = dcc_displayfile(filename);
- RunHook5(HOOKTYPE_DCC_DENIED, client, target, filename, displayfile, fl);
+ RunHook(HOOKTYPE_DCC_DENIED, client, target, filename, displayfile, fl);
ircsnprintf(errbuf, sizeof(errbuf), "Cannot DCC SEND file: %s", fl->reason);
*errmsg = errbuf;
@@ -675,10 +684,10 @@ static int can_dcc(Client *client, char *target, Client *targetcli, char *filena
* 1: allowed
* 0: block
*/
-static int can_dcc_soft(Client *from, Client *to, char *filename, char **errmsg)
+static int can_dcc_soft(Client *from, Client *to, const char *filename, const char **errmsg)
{
ConfigItem_deny_dcc *fl;
- char *displayfile;
+ const char *displayfile;
static char errbuf[256];
/* User (IRCOp) may bypass send restrictions */
@@ -718,7 +727,7 @@ static int can_dcc_soft(Client *from, Client *to, char *filename, char **errmsg)
}
/** Checks if the dcc is blacklisted. */
-static ConfigItem_deny_dcc *dcc_isforbidden(Client *client, char *filename)
+static ConfigItem_deny_dcc *dcc_isforbidden(Client *client, const char *filename)
{
ConfigItem_deny_dcc *d;
ConfigItem_allow_dcc *a;
@@ -743,7 +752,7 @@ static ConfigItem_deny_dcc *dcc_isforbidden(Client *client, char *filename)
}
/** checks if the dcc is discouraged ('soft bans'). */
-static ConfigItem_deny_dcc *dcc_isdiscouraged(Client *client, char *filename)
+static ConfigItem_deny_dcc *dcc_isdiscouraged(Client *client, const char *filename)
{
ConfigItem_deny_dcc *d;
ConfigItem_allow_dcc *a;
@@ -767,7 +776,7 @@ static ConfigItem_deny_dcc *dcc_isdiscouraged(Client *client, char *filename)
return NULL;
}
-static void DCCdeny_add(char *filename, char *reason, int type, int type2)
+static void DCCdeny_add(const char *filename, const char *reason, int type, int type2)
{
ConfigItem_deny_dcc *deny = NULL;
@@ -787,7 +796,7 @@ static void DCCdeny_del(ConfigItem_deny_dcc *deny)
safe_free(deny);
}
-ConfigItem_deny_dcc *find_deny_dcc(char *name)
+ConfigItem_deny_dcc *find_deny_dcc(const char *name)
{
ConfigItem_deny_dcc *e;
@@ -820,7 +829,7 @@ static void dcc_wipe_services(void)
}
-int dccdeny_stats(Client *client, char *para)
+int dccdeny_stats(Client *client, const char *para)
{
ConfigItem_deny_dcc *denytmp;
ConfigItem_allow_dcc *allowtmp;
@@ -860,3 +869,13 @@ int dccdeny_stats(Client *client, char *para)
}
return 1;
}
+
+int dccdeny_dcc_denied(Client *client, const char *target, const char *realfile, const char *displayfile, ConfigItem_deny_dcc *dccdeny)
+{
+ unreal_log(ULOG_INFO, "dcc", "DCC_REJECTED", client,
+ "$client.details tried to send forbidden file $filename ($ban_reason) to $target (is blocked now)",
+ log_data_string("filename", displayfile),
+ log_data_string("ban_reason", dccdeny->reason),
+ log_data_string("target", target));
+ return 0;
+}
diff --git a/src/modules/echo-message.c b/src/modules/echo-message.c
index 90f83b5..97a5997 100644
--- a/src/modules/echo-message.c
+++ b/src/modules/echo-message.c
@@ -28,15 +28,15 @@ ModuleHeader MOD_HEADER
"5.0",
"Batch CAP",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Variables */
long CAP_ECHO_MESSAGE = 0L;
/* Forward declarations */
-int em_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, SendType sendtype);
-int em_usermsg(Client *client, Client *to, MessageTag *mtags, char *text, SendType sendtype);
+int em_chanmsg(Client *client, Channel *channel, int sendflags, const char *prefix, const char *target, MessageTag *mtags, const char *text, SendType sendtype);
+int em_usermsg(Client *client, Client *to, MessageTag *mtags, const char *text, SendType sendtype);
MOD_INIT()
{
@@ -64,7 +64,7 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
-int em_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, SendType sendtype)
+int em_chanmsg(Client *client, Channel *channel, int sendflags, const char *prefix, const char *target, MessageTag *mtags, const char *text, SendType sendtype)
{
if (MyUser(client) && HasCapabilityFast(client, CAP_ECHO_MESSAGE))
{
@@ -85,7 +85,7 @@ int em_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char
return 0;
}
-int em_usermsg(Client *client, Client *to, MessageTag *mtags, char *text, SendType sendtype)
+int em_usermsg(Client *client, Client *to, MessageTag *mtags, const char *text, SendType sendtype)
{
if (MyUser(client) && HasCapabilityFast(client, CAP_ECHO_MESSAGE))
{
diff --git a/src/modules/eos.c b/src/modules/eos.c
index 157c9f0..c3e0707 100644
--- a/src/modules/eos.c
+++ b/src/modules/eos.c
@@ -32,7 +32,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /eos",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
@@ -63,12 +63,8 @@ CMD_FUNC(cmd_eos)
{
if (!IsServer(client))
return;
- client->serv->flags.synced = 1;
+ client->server->flags.synced = 1;
/* pass it on ^_- */
-#ifdef DEBUGMODE
- ircd_log(LOG_ERROR, "[EOSDBG] cmd_eos: got sync from %s (path:%s)", client->name, client->direction->name);
- ircd_log(LOG_ERROR, "[EOSDBG] cmd_eos: broadcasting it back to everyone except route from %s", client->direction->name);
-#endif
sendto_server(client, 0, 0, NULL, ":%s EOS", client->id);
RunHook(HOOKTYPE_SERVER_SYNCED, client);
diff --git a/src/modules/extbans/Makefile.in b/src/modules/extbans/Makefile.in
index b286cc3..26ea7cf 100644
--- a/src/modules/extbans/Makefile.in
+++ b/src/modules/extbans/Makefile.in
@@ -25,21 +25,25 @@ INCLUDES = ../../include/channel.h \
../../include/ircsprintf.h \
../../include/license.h \
../../include/modules.h ../../include/modversion.h ../../include/msg.h \
- ../../include/numeric.h ../../include/proto.h ../../include/dns.h \
+ ../../include/numeric.h ../../include/dns.h \
../../include/resource.h ../../include/setup.h \
../../include/struct.h ../../include/sys.h \
- ../../include/types.h ../../include/url.h \
+ ../../include/types.h \
../../include/version.h ../../include/whowas.h
R_MODULES= \
join.so quiet.so nickchange.so inchannel.so realname.so \
account.so operclass.so certfp.so textban.so msgbypass.so \
- timedban.so partmsg.so securitygroup.so
+ timedban.so partmsg.so securitygroup.so \
+ country.so
MODULES=$(R_MODULES)
MODULEFLAGS=@MODULEFLAGS@
RM=@RM@
+.SUFFIXES:
+.SUFFIXES: .c .h .so
+
all: build
build: $(MODULES)
@@ -47,62 +51,6 @@ build: $(MODULES)
clean:
$(RM) -f *.o *.so *~ core
-#############################################################################
-# .so's section
-#############################################################################
-
-skel.so: skel.c $(INCLUDES)
+%.so: %.c $(INCLUDES)
$(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o skel.so skel.c
-
-join.so: join.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o join.so join.c
-
-quiet.so: quiet.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o quiet.so quiet.c
-
-nickchange.so: nickchange.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o nickchange.so nickchange.c
-
-inchannel.so: inchannel.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o inchannel.so inchannel.c
-
-realname.so: realname.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o realname.so realname.c
-
-account.so: account.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o account.so account.c
-
-operclass.so: operclass.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o operclass.so operclass.c
-
-certfp.so: certfp.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o certfp.so certfp.c
-
-textban.so: textban.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o textban.so textban.c
-
-msgbypass.so: msgbypass.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o msgbypass.so msgbypass.c
-
-timedban.so: timedban.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o timedban.so timedban.c
-
-partmsg.so: partmsg.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o partmsg.so partmsg.c
-
-securitygroup.so: securitygroup.c $(INCLUDES)
- $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
- -o securitygroup.so securitygroup.c
+ -o $@ $<
diff --git a/src/modules/extbans/account.c b/src/modules/extbans/account.c
index 3e4877d..d28b0e8 100644
--- a/src/modules/extbans/account.c
+++ b/src/modules/extbans/account.c
@@ -24,22 +24,25 @@ ModuleHeader MOD_HEADER
"4.2",
"ExtBan ~a - Ban/exempt by services account name",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Forward declarations */
-char *extban_account_conv_param(char *para);
-int extban_account_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg);
+const char *extban_account_conv_param(BanContext *b, Extban *extban);
+int extban_account_is_banned(BanContext *b);
/** Called upon module init */
MOD_INIT()
{
ExtbanInfo req;
- req.flag = 'a';
+ memset(&req, 0, sizeof(req));
+ req.letter = 'a';
+ req.name = "account";
req.is_ok = NULL;
req.conv_param = extban_account_conv_param;
req.is_banned = extban_account_is_banned;
+ req.is_banned_events = BANCHK_ALL|BANCHK_TKL;
req.options = EXTBOPT_INVEX|EXTBOPT_TKL;
if (!ExtbanAdd(modinfo->handle, req))
{
@@ -65,27 +68,34 @@ MOD_UNLOAD()
}
/** Account bans */
-char *extban_account_conv_param(char *para)
+const char *extban_account_conv_param(BanContext *b, Extban *extban)
{
char *mask, *acc;
static char retbuf[NICKLEN + 4];
- strlcpy(retbuf, para, sizeof(retbuf)); /* truncate */
+ strlcpy(retbuf, b->banstr, sizeof(retbuf)); /* truncate */
- acc = retbuf+3;
+ acc = retbuf;
if (!*acc)
return NULL; /* don't allow "~a:" */
- if (!strcmp(acc, "0"))
- return NULL; /* ~a:0 would mean ban all non-regged, but we already have +R for that. */
return retbuf;
}
-int extban_account_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg)
+int extban_account_is_banned(BanContext *b)
{
- char *ban = banin+3;
+ /* ~a:0 is special and matches all unauthenticated users */
+ if (!strcmp(b->banstr, "0") && !IsLoggedIn(b->client))
+ return 1;
- if (!strcasecmp(ban, client->user->svid))
+ /* ~a:* matches all authenticated users
+ * (Yes this special code is needed because account
+ * is 0 or * for unauthenticated users)
+ */
+ if (!strcmp(b->banstr, "*") && IsLoggedIn(b->client))
+ return 1;
+
+ if (match_simple(b->banstr, b->client->user->account))
return 1;
return 0;
diff --git a/src/modules/extbans/certfp.c b/src/modules/extbans/certfp.c
index c3f4103..8bb1102 100644
--- a/src/modules/extbans/certfp.c
+++ b/src/modules/extbans/certfp.c
@@ -24,23 +24,26 @@ ModuleHeader MOD_HEADER
"4.2",
"ExtBan ~S - Ban/exempt by SHA256 TLS certificate fingerprint",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Forward declarations */
-int extban_certfp_is_ok(Client *client, Channel *channel, char *para, int checkt, int what, int what2);
-char *extban_certfp_conv_param(char *para);
-int extban_certfp_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg);
+int extban_certfp_is_ok(BanContext *b);
+const char *extban_certfp_conv_param(BanContext *b, Extban *extban);
+int extban_certfp_is_banned(BanContext *b);
/* Called upon module init */
MOD_INIT()
{
ExtbanInfo req;
- req.flag = 'S';
+ memset(&req, 0, sizeof(req));
+ req.letter = 'S';
+ req.name = "certfp";
req.is_ok = extban_certfp_is_ok;
req.conv_param = extban_certfp_conv_param;
req.is_banned = extban_certfp_is_banned;
+ req.is_banned_events = BANCHK_ALL|BANCHK_TKL;
req.options = EXTBOPT_INVEX|EXTBOPT_TKL;
if (!ExtbanAdd(modinfo->handle, req))
{
@@ -74,18 +77,18 @@ int extban_certfp_usage(Client *client)
return EX_DENY;
}
-int extban_certfp_is_ok(Client *client, Channel *channel, char *para, int checkt, int what, int what2)
+int extban_certfp_is_ok(BanContext *b)
{
- if (checkt == EXCHK_PARAM)
+ if (b->is_ok_check == EXCHK_PARAM)
{
- char *p;
+ const char *p;
- if (strlen(para) != 3 + CERT_FP_LEN)
- return extban_certfp_usage(client);
+ if (strlen(b->banstr) != CERT_FP_LEN)
+ return extban_certfp_usage(b->client);
- for (p = para + 3; *p; p++)
+ for (p = b->banstr; *p; p++)
if (!isxdigit(*p))
- return extban_certfp_usage(client);
+ return extban_certfp_usage(b->client);
return EX_ALLOW;
}
@@ -93,14 +96,14 @@ int extban_certfp_is_ok(Client *client, Channel *channel, char *para, int checkt
}
/* Obtain targeted certfp from the ban string */
-char *extban_certfp_conv_param(char *para)
+const char *extban_certfp_conv_param(BanContext *b, Extban *extban)
{
static char retbuf[EVP_MAX_MD_SIZE * 2 + 1];
char *p;
- strlcpy(retbuf, para, sizeof(retbuf));
+ strlcpy(retbuf, b->banstr, sizeof(retbuf));
- for (p = retbuf+3; *p; p++)
+ for (p = retbuf; *p; p++)
{
*p = tolower(*p);
}
@@ -108,17 +111,14 @@ char *extban_certfp_conv_param(char *para)
return retbuf;
}
-int extban_certfp_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg)
+int extban_certfp_is_banned(BanContext *b)
{
- char *ban = banin+3;
- char *fp;
-
- fp = moddata_client_get(client, "certfp");
+ const char *fp = moddata_client_get(b->client, "certfp");
if (!fp)
return 0; /* not using TLS */
- if (!strcmp(ban, fp))
+ if (!strcmp(b->banstr, fp))
return 1;
return 0;
diff --git a/src/modules/extbans/country.c b/src/modules/extbans/country.c
new file mode 100644
index 0000000..012bfe9
--- /dev/null
+++ b/src/modules/extbans/country.c
@@ -0,0 +1,124 @@
+/*
+ * Extended ban to ban/exempt by country/geoip info (+b ~country:UK)
+ * (C) Copyright 2021 The UnrealIRCd Team
+ *
+ * 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.
+ */
+#include "unrealircd.h"
+
+ModuleHeader MOD_HEADER
+= {
+ "extbans/country",
+ "6.0",
+ "ExtBan ~country - Ban/exempt by country (geoip)",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+};
+
+/* Forward declarations */
+int extban_country_is_ok(BanContext *b);
+const char *extban_country_conv_param(BanContext *b, Extban *extban);
+int extban_country_is_banned(BanContext *b);
+
+/* Called upon module init */
+MOD_INIT()
+{
+ ExtbanInfo req;
+
+ memset(&req, 0, sizeof(req));
+ req.letter = 'C';
+ req.name = "country";
+ req.is_ok = extban_country_is_ok;
+ req.conv_param = extban_country_conv_param;
+ req.is_banned = extban_country_is_banned;
+ req.is_banned_events = BANCHK_ALL|BANCHK_TKL;
+ req.options = EXTBOPT_INVEX|EXTBOPT_TKL;
+ if (!ExtbanAdd(modinfo->handle, req))
+ {
+ config_error("could not register extended ban type");
+ return MOD_FAILED;
+ }
+
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ return MOD_SUCCESS;
+}
+
+/* Called upon module load */
+MOD_LOAD()
+{
+ return MOD_SUCCESS;
+}
+
+/* Called upon unload */
+MOD_UNLOAD()
+{
+ return MOD_SUCCESS;
+}
+
+int extban_country_usage(Client *client)
+{
+ sendnotice(client, "ERROR: ExtBan ~country expects a two letter country code, or * to ban unknown countries. "
+ "For example: +b ~country:UK");
+ return EX_DENY;
+}
+
+int extban_country_is_ok(BanContext *b)
+{
+ if (b->is_ok_check == EXCHK_PARAM)
+ {
+ const char *p;
+
+ if (!strcmp(b->banstr, "*"))
+ return EX_ALLOW;
+
+ if ((strlen(b->banstr) != 2))
+ return extban_country_usage(b->client);
+
+ for (p = b->banstr; *p; p++)
+ if (!isalpha(*p))
+ return extban_country_usage(b->client);
+
+ return EX_ALLOW;
+ }
+ return EX_ALLOW;
+}
+
+/* Obtain targeted country from the ban string */
+const char *extban_country_conv_param(BanContext *b, Extban *extban)
+{
+ static char retbuf[EVP_MAX_MD_SIZE * 2 + 1];
+ char *p;
+
+ strlcpy(retbuf, b->banstr, sizeof(retbuf));
+
+ for (p = retbuf; *p; p++)
+ *p = toupper(*p);
+
+ return retbuf;
+}
+
+int extban_country_is_banned(BanContext *b)
+{
+ GeoIPResult *geo = geoip_client(b->client);
+ char *country;
+
+ country = geo ? geo->country_code : "*";
+
+ if (!strcmp(b->banstr, country))
+ return 1;
+
+ return 0;
+}
diff --git a/src/modules/extbans/inchannel.c b/src/modules/extbans/inchannel.c
index e8755f4..5d5a3ac 100644
--- a/src/modules/extbans/inchannel.c
+++ b/src/modules/extbans/inchannel.c
@@ -24,23 +24,26 @@ ModuleHeader MOD_HEADER
"4.2",
"ExtBan ~c - banned when in specified channel",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Forward declarations */
-int extban_inchannel_is_ok(Client *client, Channel *channel, char *para, int checkt, int what, int what2);
-char *extban_inchannel_conv_param(char *para);
-int extban_inchannel_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg);
+int extban_inchannel_is_ok(BanContext *b);
+const char *extban_inchannel_conv_param(BanContext *b, Extban *extban);
+int extban_inchannel_is_banned(BanContext *b);
/** Called upon module init */
MOD_INIT()
{
ExtbanInfo req;
- req.flag = 'c';
+ memset(&req, 0, sizeof(req));
+ req.letter = 'c';
+ req.name = "channel";
req.is_ok = extban_inchannel_is_ok;
req.conv_param = extban_inchannel_conv_param;
req.is_banned = extban_inchannel_is_banned;
+ req.is_banned_events = BANCHK_ALL|BANCHK_TKL;
req.options = EXTBOPT_INVEX; /* for +I too */
if (!ExtbanAdd(modinfo->handle, req))
{
@@ -65,13 +68,13 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
-char *extban_inchannel_conv_param(char *para)
+const char *extban_inchannel_conv_param(BanContext *b, Extban *extban)
{
static char retbuf[CHANNELLEN+6];
char *chan, *p, symbol='\0';
- strlcpy(retbuf, para, sizeof(retbuf));
- chan = retbuf+3;
+ strlcpy(retbuf, b->banstr, sizeof(retbuf));
+ chan = retbuf;
if ((*chan == '+') || (*chan == '%') || (*chan == '%') ||
(*chan == '@') || (*chan == '&') || (*chan == '~'))
@@ -92,51 +95,53 @@ char *extban_inchannel_conv_param(char *para)
}
/* The only purpose of this function is a temporary workaround to prevent a desync.. pfff */
-int extban_inchannel_is_ok(Client *client, Channel *channel, char *para, int checkt, int what, int what2)
+int extban_inchannel_is_ok(BanContext *b)
{
- char *p;
+ const char *p = b->banstr;
- if ((checkt == EXBCHK_PARAM) && MyUser(client) && (what == MODE_ADD) && (strlen(para) > 3))
+ if ((b->is_ok_check == EXBCHK_PARAM) && MyUser(b->client) && (b->what == MODE_ADD) && (strlen(b->banstr) > 3))
{
- p = para + 3;
if ((*p == '+') || (*p == '%') || (*p == '%') ||
(*p == '@') || (*p == '&') || (*p == '~'))
p++;
if (*p != '#')
{
- sendnotice(client, "Please use a # in the channelname (eg: ~c:#*blah*)");
+ sendnotice(b->client, "Please use a # in the channelname (eg: ~c:#*blah*)");
return 0;
}
}
return 1;
}
-static int extban_inchannel_compareflags(char symbol, int flags)
+static int extban_inchannel_compareflags(char symbol, const char *member_modes)
{
- int require=0;
+ const char *required_modes = NULL;
if (symbol == '+')
- require = CHFL_VOICE|CHFL_HALFOP|CHFL_CHANOP|CHFL_CHANADMIN|CHFL_CHANOWNER;
+ required_modes = "vhoaq";
else if (symbol == '%')
- require = CHFL_HALFOP|CHFL_CHANOP|CHFL_CHANADMIN|CHFL_CHANOWNER;
+ required_modes = "hoaq";
else if (symbol == '@')
- require = CHFL_CHANOP|CHFL_CHANADMIN|CHFL_CHANOWNER;
+ required_modes = "oaq";
else if (symbol == '&')
- require = CHFL_CHANADMIN|CHFL_CHANOWNER;
+ required_modes = "aq";
else if (symbol == '~')
- require = CHFL_CHANOWNER;
+ required_modes = "q";
+ else
+ return 0; /* unknown prefix character */
- if (flags & require)
+ if (check_channel_access_string(member_modes, required_modes))
return 1;
return 0;
}
-int extban_inchannel_is_banned(Client *client, Channel *channel, char *ban, int type, char **msg, char **errmsg)
+int extban_inchannel_is_banned(BanContext *b)
{
Membership *lp;
- char *p = ban+3, symbol = '\0';
+ const char *p = b->banstr;
+ char symbol = '\0';
if (*p != '#')
{
@@ -144,14 +149,14 @@ int extban_inchannel_is_banned(Client *client, Channel *channel, char *ban, int
p++;
}
- for (lp = client->user->channel; lp; lp = lp->next)
+ for (lp = b->client->user->channel; lp; lp = lp->next)
{
- if (match_esc(p, lp->channel->chname))
+ if (match_esc(p, lp->channel->name))
{
/* Channel matched, check symbol if needed (+/%/@/etc) */
if (symbol)
{
- if (extban_inchannel_compareflags(symbol, lp->flags))
+ if (extban_inchannel_compareflags(symbol, lp->member_modes))
return 1;
} else
return 1;
diff --git a/src/modules/extbans/join.c b/src/modules/extbans/join.c
index 050b43e..d2ca1ce 100644
--- a/src/modules/extbans/join.c
+++ b/src/modules/extbans/join.c
@@ -24,21 +24,24 @@ ModuleHeader MOD_HEADER
"4.2",
"Extban ~j - prevent join only",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Forward declarations */
-int extban_modej_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg);
+int extban_modej_is_banned(BanContext *b);
/** Called upon module init */
MOD_INIT()
{
ExtbanInfo req;
- req.flag = 'j';
+ memset(&req, 0, sizeof(req));
+ req.letter = 'j';
+ req.name = "join";
req.is_ok = extban_is_ok_nuh_extban;
req.conv_param = extban_conv_param_nuh_or_extban;
req.is_banned = extban_modej_is_banned;
+ req.is_banned_events = BANCHK_JOIN;
req.options = EXTBOPT_ACTMODIFIER;
if (!ExtbanAdd(modinfo->handle, req))
{
@@ -64,15 +67,7 @@ MOD_UNLOAD()
}
/** This ban that affects JOINs only */
-int extban_modej_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg)
+int extban_modej_is_banned(BanContext *b)
{
- char *sub_ban;
-
- if (type != BANCHK_JOIN)
- return 0;
-
- sub_ban = banin + 3;
-
- return ban_check_mask(client, channel, sub_ban, type, msg, errmsg, 0);
+ return ban_check_mask(b);
}
-
diff --git a/src/modules/extbans/msgbypass.c b/src/modules/extbans/msgbypass.c
index 167bf64..ef0b6fc 100644
--- a/src/modules/extbans/msgbypass.c
+++ b/src/modules/extbans/msgbypass.c
@@ -24,24 +24,24 @@ ModuleHeader MOD_HEADER
"4.2",
"ExtBan ~m - bypass +m/+n/+c/+S/+T (msgbypass)",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Forward declarations */
-int extban_msgbypass_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg);
int msgbypass_can_bypass(Client *client, Channel *channel, BypassChannelMessageRestrictionType bypass_type);
-int msgbypass_extban_is_ok(Client *client, Channel* channel, char *para, int checkt, int what, int what2);
-char *msgbypass_extban_conv_param(char *para);
+int msgbypass_extban_is_ok(BanContext *b);
+const char *msgbypass_extban_conv_param(BanContext *b, Extban *extban);
/** Called upon module init */
MOD_INIT()
{
ExtbanInfo req;
- req.flag = 'm';
+ memset(&req, 0, sizeof(req));
+ req.letter = 'm';
+ req.name = "msgbypass";
req.is_ok = msgbypass_extban_is_ok;
req.conv_param = msgbypass_extban_conv_param;
- req.is_banned = extban_msgbypass_is_banned;
req.options = EXTBOPT_ACTMODIFIER;
if (!ExtbanAdd(modinfo->handle, req))
{
@@ -67,42 +67,50 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
-/** Is the user banned? No, never by us anyway. */
-int extban_msgbypass_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg)
-{
- return 0; /* not banned by us */
-}
-
/** Can the user bypass restrictions? */
int msgbypass_can_bypass(Client *client, Channel *channel, BypassChannelMessageRestrictionType bypass_type)
{
Ban *ban;
char *p;
-
+ BanContext *b = safe_alloc(sizeof(BanContext));
+
+ b->client = client;
+ b->channel = channel;
+ b->ban_check_types = BANCHK_MSG;
+
for (ban = channel->exlist; ban; ban=ban->next)
{
+ char *type;
+ char *matchby;
+
if (!strncmp(ban->banstr, "~m:", 3))
+ type = ban->banstr + 3;
+ else if (!strncmp(ban->banstr, "~msgbypass:", 11))
+ type = ban->banstr + 11;
+ else
+ continue;
+
+ if (((bypass_type == BYPASS_CHANMSG_EXTERNAL) && !strncmp(type, "external:", 9)) ||
+ ((bypass_type == BYPASS_CHANMSG_MODERATED) && !strncmp(type, "moderated:", 10)) ||
+ ((bypass_type == BYPASS_CHANMSG_COLOR) && !strncmp(type, "color:", 6)) ||
+ ((bypass_type == BYPASS_CHANMSG_CENSOR) && !strncmp(type, "censor:", 7)) ||
+ ((bypass_type == BYPASS_CHANMSG_NOTICE) && !strncmp(type, "notice:", 7)))
{
- char *type = ban->banstr + 3;
- char *matchby;
+ matchby = strchr(type, ':');
+ if (!matchby)
+ continue;
+ matchby++;
- if (((bypass_type == BYPASS_CHANMSG_EXTERNAL) && !strncmp(type, "external:", 9)) ||
- ((bypass_type == BYPASS_CHANMSG_MODERATED) && !strncmp(type, "moderated:", 10)) ||
- ((bypass_type == BYPASS_CHANMSG_COLOR) && !strncmp(type, "color:", 6)) ||
- ((bypass_type == BYPASS_CHANMSG_CENSOR) && !strncmp(type, "censor:", 7)) ||
- ((bypass_type == BYPASS_CHANMSG_NOTICE) && !strncmp(type, "notice:", 7)))
+ b->banstr = matchby;
+ if (ban_check_mask(b))
{
- matchby = strchr(type, ':');
- if (!matchby)
- continue;
- matchby++;
-
- if (ban_check_mask(client, channel, matchby, BANCHK_MSG, NULL, NULL, 0))
- return HOOK_ALLOW; /* Yes, user may bypass */
+ safe_free(b);
+ return HOOK_ALLOW; /* Yes, user may bypass */
}
}
}
+ safe_free(b);
return HOOK_CONTINUE; /* No, may NOT bypass. */
}
@@ -121,16 +129,16 @@ int msgbypass_extban_type_ok(char *type)
}
#define MAX_LENGTH 128
-char *msgbypass_extban_conv_param(char *para_in)
+const char *msgbypass_extban_conv_param(BanContext *b, Extban *extban)
{
static char retbuf[MAX_LENGTH+1];
char para[MAX_LENGTH+1];
char tmpmask[MAX_LENGTH+1];
char *type; /**< Type, such as 'external' */
char *matchby; /**< Matching method, such as 'n!u@h' */
- char *newmask; /**< Cleaned matching method, such as 'n!u@h' */
+ const char *newmask; /**< Cleaned matching method, such as 'n!u@h' */
- strlcpy(para, para_in+3, sizeof(para)); /* work on a copy (and truncate it) */
+ strlcpy(para, b->banstr, sizeof(para)); /* work on a copy (and truncate it) */
/* ~m:type:n!u@h for direct matching
* ~m:type:~x:.... when calling another bantype
@@ -145,16 +153,13 @@ char *msgbypass_extban_conv_param(char *para_in)
if (!msgbypass_extban_type_ok(type))
return NULL;
- /* This is quite silly, we have to create a fake extban here due to
- * the current API of extban_conv_param_nuh and extban_conv_param_nuh_or_extban
- * expecting the full banmask rather than the portion that actually matters.
- */
- snprintf(tmpmask, sizeof(tmpmask), "~?:%s", matchby);
- newmask = extban_conv_param_nuh_or_extban(tmpmask);
- if (!newmask || (strlen(newmask) <= 3))
+ b->banstr = matchby;
+ newmask = extban_conv_param_nuh_or_extban(b, extban);
+ if (BadPtr(newmask))
return NULL;
- snprintf(retbuf, sizeof(retbuf), "~m:%s:%s", type, newmask+3);
+ //snprintf(retbuf, sizeof(retbuf), "~m:%s:%s", type, newmask);
+ snprintf(retbuf, sizeof(retbuf), "%s:%s", type, newmask);
return retbuf;
}
@@ -171,26 +176,25 @@ int msgbypass_extban_syntax(Client *client, int checkt, char *reason)
return 0; /* FAIL: ban rejected */
}
-int msgbypass_extban_is_ok(Client *client, Channel* channel, char *para_in, int checkt, int what, int what2)
+int msgbypass_extban_is_ok(BanContext *b)
{
- char para[MAX_LENGTH+1];
- char tmpmask[MAX_LENGTH+1];
+ static char para[MAX_LENGTH+1];
char *type; /**< Type, such as 'external' */
char *matchby; /**< Matching method, such as 'n!u@h' */
char *newmask; /**< Cleaned matching method, such as 'n!u@h' */
/* Always permit deletion */
- if (what == MODE_DEL)
+ if (b->what == MODE_DEL)
return 1;
- if (what2 != EXBTYPE_EXCEPT)
+ if (b->ban_type != EXBTYPE_EXCEPT)
{
- if (checkt == EXBCHK_PARAM)
- sendnotice(client, "Ban type ~m only works with exceptions (+e) and not with bans or invex (+b/+I)");
+ if (b->is_ok_check == EXBCHK_PARAM)
+ sendnotice(b->client, "Ban type ~m only works with exceptions (+e) and not with bans or invex (+b/+I)");
return 0; /* reject */
}
- strlcpy(para, para_in+3, sizeof(para)); /* work on a copy (and truncate it) */
+ strlcpy(para, b->banstr, sizeof(para)); /* work on a copy (and truncate it) */
/* ~m:type:n!u@h for direct matching
* ~m:type:~x:.... when calling another bantype
@@ -199,24 +203,20 @@ int msgbypass_extban_is_ok(Client *client, Channel* channel, char *para_in, int
type = para;
matchby = strchr(para, ':');
if (!matchby || !matchby[1])
- return msgbypass_extban_syntax(client, checkt, "Invalid syntax");
+ return msgbypass_extban_syntax(b->client, b->is_ok_check, "Invalid syntax");
*matchby++ = '\0';
if (!msgbypass_extban_type_ok(type))
- return msgbypass_extban_syntax(client, checkt, "Unknown type");
+ return msgbypass_extban_syntax(b->client, b->is_ok_check, "Unknown type");
- /* This is quite silly, we have to create a fake extban here due to
- * the current API of extban_conv_param_nuh and extban_conv_param_nuh_or_extban
- * expecting the full banmask rather than the portion that actually matters.
- */
- snprintf(tmpmask, sizeof(tmpmask), "~?:%s", matchby);
- if (extban_is_ok_nuh_extban(client, channel, tmpmask, checkt, what, what2) == 0)
+ b->banstr = matchby;
+ if (extban_is_ok_nuh_extban(b) == 0)
{
/* This could be anything ranging from:
* invalid n!u@h syntax, unknown (sub)extbantype,
* disabled extban type in conf, too much recursion, etc.
*/
- return msgbypass_extban_syntax(client, checkt, "Invalid matcher");
+ return msgbypass_extban_syntax(b->client, b->is_ok_check, "Invalid matcher");
}
return 1; /* OK */
diff --git a/src/modules/extbans/nickchange.c b/src/modules/extbans/nickchange.c
index 164fbc0..bc8769f 100644
--- a/src/modules/extbans/nickchange.c
+++ b/src/modules/extbans/nickchange.c
@@ -24,21 +24,24 @@ ModuleHeader MOD_HEADER
"4.2",
"ExtBan ~n - prevent nick-changes only",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Forward declarations */
-int extban_nickchange_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg);
+int extban_nickchange_is_banned(BanContext *b);
/** Called upon module init */
MOD_INIT()
{
ExtbanInfo req;
- req.flag = 'n';
+ memset(&req, 0, sizeof(req));
+ req.letter = 'n';
+ req.name = "nickchange";
req.is_ok = extban_is_ok_nuh_extban;
req.conv_param = extban_conv_param_nuh_or_extban;
req.is_banned = extban_nickchange_is_banned;
+ req.is_banned_events = BANCHK_NICK;
req.options = EXTBOPT_ACTMODIFIER;
if (!ExtbanAdd(modinfo->handle, req))
{
@@ -64,18 +67,10 @@ MOD_UNLOAD()
}
/** This ban that affects nick-changes only */
-int extban_nickchange_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg)
+int extban_nickchange_is_banned(BanContext *b)
{
- char *sub_ban;
-
- if (type != BANCHK_NICK)
+ if (check_channel_access(b->client, b->channel, "v"))
return 0;
- if (has_voice(client, channel))
- return 0;
-
- sub_ban = banin + 3;
-
- return ban_check_mask(client, channel, sub_ban, type, msg, errmsg, 0);
+ return ban_check_mask(b);
}
-
diff --git a/src/modules/extbans/operclass.c b/src/modules/extbans/operclass.c
index b5469cc..5b6bc2a 100644
--- a/src/modules/extbans/operclass.c
+++ b/src/modules/extbans/operclass.c
@@ -24,22 +24,25 @@ ModuleHeader MOD_HEADER
"4.2",
"ExtBan ~O - Ban/exempt operclass",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Forward declarations */
-char *extban_operclass_conv_param(char *para);
-int extban_operclass_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg);
+const char *extban_operclass_conv_param(BanContext *b, Extban *extban);
+int extban_operclass_is_banned(BanContext *b);
/** Called upon module init */
MOD_INIT()
{
ExtbanInfo req;
- req.flag = 'O';
+ memset(&req, 0, sizeof(req));
+ req.letter = 'O';
+ req.name = "operclass";
req.is_ok = NULL;
req.conv_param = extban_operclass_conv_param;
req.is_banned = extban_operclass_is_banned;
+ req.is_banned_events = BANCHK_ALL;
req.options = EXTBOPT_INVEX;
if (!ExtbanAdd(modinfo->handle, req))
{
@@ -67,15 +70,15 @@ MOD_UNLOAD()
#define OPERCLASSLEN 64
-char *extban_operclass_conv_param(char *para)
+const char *extban_operclass_conv_param(BanContext *b, Extban *extban)
{
static char retbuf[OPERCLASSLEN + 4];
char *p;
- strlcpy(retbuf, para, sizeof(retbuf));
+ strlcpy(retbuf, b->banstr, sizeof(retbuf));
/* allow alpha, numeric, -, _, * and ? wildcards */
- for (p = retbuf+3; *p; p++)
+ for (p = retbuf; *p; p++)
if (!strchr("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_?*", *p))
*p = '\0';
@@ -85,18 +88,12 @@ char *extban_operclass_conv_param(char *para)
return retbuf;
}
-int extban_operclass_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg)
+int extban_operclass_is_banned(BanContext *b)
{
- char *ban = banin+3;
-
- if (MyUser(client) && IsOper(client))
+ if (MyUser(b->client) && IsOper(b->client))
{
- char *operclass = NULL;
- ConfigItem_oper *oper = find_oper(client->user->operlogin);
- if (oper && oper->operclass)
- operclass = oper->operclass;
-
- if (operclass && match_simple(ban, operclass))
+ const char *operclass = get_operclass(b->client);
+ if (operclass && match_simple(b->banstr, operclass))
return 1;
}
diff --git a/src/modules/extbans/partmsg.c b/src/modules/extbans/partmsg.c
index 10c3651..a6402d5 100644
--- a/src/modules/extbans/partmsg.c
+++ b/src/modules/extbans/partmsg.c
@@ -25,20 +25,23 @@ ModuleHeader MOD_HEADER
"4.2",
"ExtBan ~p - Ban/exempt Part/Quit message",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
-int extban_partmsg_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg);
+int extban_partmsg_is_banned(BanContext *b);
MOD_INIT()
{
ExtbanInfo req;
- req.flag = 'p';
+ memset(&req, 0, sizeof(req));
+ req.letter = 'p';
+ req.name = "partmsg";
req.is_ok = extban_is_ok_nuh_extban;
req.conv_param = extban_conv_param_nuh_or_extban;
req.options = EXTBOPT_ACTMODIFIER;
req.is_banned = extban_partmsg_is_banned;
+ req.is_banned_events = BANCHK_LEAVE_MSG;
if (!ExtbanAdd(modinfo->handle, req))
{
config_error("could not register extended ban type");
@@ -62,10 +65,10 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
-int extban_partmsg_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg)
+int extban_partmsg_is_banned(BanContext *b)
{
- if (type == BANCHK_LEAVE_MSG)
- *msg = NULL;
+ b->msg = NULL;
+ // Uh.. there is no attempt to match.... anything.......?
return 0;
}
diff --git a/src/modules/extbans/quiet.c b/src/modules/extbans/quiet.c
index 2f7d787..5d3dfdf 100644
--- a/src/modules/extbans/quiet.c
+++ b/src/modules/extbans/quiet.c
@@ -24,21 +24,24 @@ ModuleHeader MOD_HEADER
"4.2",
"ExtBan ~q - prevent messages only (quiet)",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Forward declarations */
-int extban_quiet_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg);
+int extban_quiet_is_banned(BanContext *b);
/** Called upon module init */
MOD_INIT()
{
ExtbanInfo req;
- req.flag = 'q';
+ memset(&req, 0, sizeof(req));
+ req.letter = 'q';
+ req.name = "quiet";
req.is_ok = extban_is_ok_nuh_extban;
req.conv_param = extban_conv_param_nuh_or_extban;
req.is_banned = extban_quiet_is_banned;
+ req.is_banned_events = BANCHK_MSG;
req.options = EXTBOPT_ACTMODIFIER;
if (!ExtbanAdd(modinfo->handle, req))
{
@@ -64,14 +67,7 @@ MOD_UNLOAD()
}
/** This ban that affects messages/notices only */
-int extban_quiet_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg)
+int extban_quiet_is_banned(BanContext *b)
{
- char *sub_ban;
-
- if (type != BANCHK_MSG)
- return 0;
-
- sub_ban = banin + 3;
-
- return ban_check_mask(client, channel, sub_ban, type, msg, errmsg, 0);
+ return ban_check_mask(b);
}
diff --git a/src/modules/extbans/realname.c b/src/modules/extbans/realname.c
index 8181716..074948e 100644
--- a/src/modules/extbans/realname.c
+++ b/src/modules/extbans/realname.c
@@ -24,22 +24,25 @@ ModuleHeader MOD_HEADER
"4.2",
"ExtBan ~r - Ban based on realname/gecos field",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Forward declarations */
-char *extban_realname_conv_param(char *para);
-int extban_realname_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg);
+const char *extban_realname_conv_param(BanContext *b, Extban *extban);
+int extban_realname_is_banned(BanContext *b);
/** Called upon module init */
MOD_INIT()
{
ExtbanInfo req;
- req.flag = 'r';
+ memset(&req, 0, sizeof(req));
+ req.letter = 'r';
+ req.name = "realname";
req.is_ok = NULL;
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;
if (!ExtbanAdd(modinfo->handle, req))
{
@@ -65,32 +68,31 @@ MOD_UNLOAD()
}
/** Realname bans - conv_param */
-char *extban_realname_conv_param(char *para)
+const char *extban_realname_conv_param(BanContext *b, Extban *extban)
{
static char retbuf[REALLEN + 8];
char *mask;
- strlcpy(retbuf, para, sizeof(retbuf));
+ strlcpy(retbuf, b->banstr, sizeof(retbuf));
- mask = retbuf+3;
+ mask = retbuf;
if (!*mask)
return NULL; /* don't allow "~r:" */
- if (strlen(mask) > REALLEN + 3)
- mask[REALLEN + 3] = '\0';
+ if (strlen(mask) > REALLEN)
+ mask[REALLEN] = '\0';
+ /* Prevent otherwise confusing extban relationship */
if (*mask == '~')
- *mask = '?'; /* Is this good? No ;) */
+ *mask = '?';
return retbuf;
}
-int extban_realname_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg)
+int extban_realname_is_banned(BanContext *b)
{
- char *ban = banin+3;
-
- if (match_esc(ban, client->info))
+ if (match_esc(b->banstr, b->client->info))
return 1;
return 0;
diff --git a/src/modules/extbans/securitygroup.c b/src/modules/extbans/securitygroup.c
index e45782e..ac412f2 100644
--- a/src/modules/extbans/securitygroup.c
+++ b/src/modules/extbans/securitygroup.c
@@ -24,23 +24,26 @@ ModuleHeader MOD_HEADER
"4.2",
"ExtBan ~G - Ban based on security-group",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Forward declarations */
-char *extban_securitygroup_conv_param(char *para);
-int extban_securitygroup_is_ok(Client *client, Channel *channel, char *para, int checkt, int what, int what2);
-int extban_securitygroup_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg);
+const char *extban_securitygroup_conv_param(BanContext *b, Extban *extban);
+int extban_securitygroup_is_ok(BanContext *b);
+int extban_securitygroup_is_banned(BanContext *b);
/** Called upon module init */
MOD_INIT()
{
ExtbanInfo req;
-
- req.flag = 'G';
+
+ memset(&req, 0, sizeof(req));
+ req.letter = 'G';
+ req.name = "security-group";
req.conv_param = extban_securitygroup_conv_param;
req.is_ok = extban_securitygroup_is_ok;
req.is_banned = extban_securitygroup_is_banned;
+ req.is_banned_events = BANCHK_ALL|BANCHK_TKL;
req.options = EXTBOPT_INVEX|EXTBOPT_TKL;
if (!ExtbanAdd(modinfo->handle, req))
{
@@ -68,12 +71,8 @@ MOD_UNLOAD()
/* Helper function for extban_securitygroup_is_ok() and extban_securitygroup_conv_param()
* to do ban validation.
*/
-int extban_securitygroup_generic(char *para, int strict)
+int extban_securitygroup_generic(char *mask, int strict)
{
- char *mask;
-
- mask = para+3;
-
/* ! at the start means negative match */
if (*mask == '!')
mask++;
@@ -91,27 +90,24 @@ int extban_securitygroup_generic(char *para, int strict)
if (!*mask)
return 0; /* don't allow "~G:" nor "~G:!" */
- if (strlen(mask) > SECURITYGROUPLEN + 3)
- mask[SECURITYGROUPLEN + 3] = '\0';
-
return 1;
}
-int extban_securitygroup_is_ok(Client *client, Channel *channel, char *para, int checkt, int what, int what2)
+int extban_securitygroup_is_ok(BanContext *b)
{
- if (MyUser(client) && (what == MODE_ADD) && (checkt == EXBCHK_PARAM))
+ if (MyUser(b->client) && (b->what == MODE_ADD) && (b->is_ok_check == EXBCHK_PARAM))
{
char banbuf[SECURITYGROUPLEN+8];
- strlcpy(banbuf, para, sizeof(banbuf));
+ strlcpy(banbuf, b->banstr, sizeof(banbuf));
if (!extban_securitygroup_generic(banbuf, 1))
{
SecurityGroup *s;
- sendnotice(client, "ERROR: Unknown security-group '%s'. Syntax: +b ~G:securitygroup or +b ~G:!securitygroup", para+3);
- sendnotice(client, "Available security groups:");
+ sendnotice(b->client, "ERROR: Unknown security-group '%s'. Syntax: +b ~G:securitygroup or +b ~G:!securitygroup", b->banstr);
+ sendnotice(b->client, "Available security groups:");
for (s = securitygroups; s; s = s->next)
- sendnotice(client, "%s", s->name);
- sendnotice(client, "unknown-users");
- sendnotice(client, "End of security group list.");
+ sendnotice(b->client, "%s", s->name);
+ sendnotice(b->client, "unknown-users");
+ sendnotice(b->client, "End of security group list.");
return 0;
}
}
@@ -119,11 +115,11 @@ int extban_securitygroup_is_ok(Client *client, Channel *channel, char *para, int
}
/** Security group extban - conv_param */
-char *extban_securitygroup_conv_param(char *para)
+const char *extban_securitygroup_conv_param(BanContext *b, Extban *extban)
{
static char retbuf[SECURITYGROUPLEN + 8];
- strlcpy(retbuf, para, sizeof(retbuf));
+ strlcpy(retbuf, b->banstr, sizeof(retbuf));
if (!extban_securitygroup_generic(retbuf, 0))
return NULL;
@@ -131,11 +127,9 @@ char *extban_securitygroup_conv_param(char *para)
}
/** Is the user banned by ~G:something ? */
-int extban_securitygroup_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg)
+int extban_securitygroup_is_banned(BanContext *b)
{
- char *ban = banin+3;
-
- if (*ban == '!')
- return !user_allowed_by_security_group_name(client, ban+1);
- return user_allowed_by_security_group_name(client, ban);
+ if (*b->banstr == '!')
+ return !user_allowed_by_security_group_name(b->client, b->banstr+1);
+ return user_allowed_by_security_group_name(b->client, b->banstr);
}
diff --git a/src/modules/extbans/textban.c b/src/modules/extbans/textban.c
index 297f0ca..cc241f5 100644
--- a/src/modules/extbans/textban.c
+++ b/src/modules/extbans/textban.c
@@ -61,30 +61,20 @@
/** Which censor replace word to use when CENSORFEATURE is enabled. */
#define CENSORWORD ""
-/** Benchmark mode.
- * Should never be used on production servers.
- * Mainly meant for debugging/profiling purposes for myself, but if you
- * have a test server and are curious about the speed of this module,
- * then you can enable it of course ;).
- */
-#undef BENCHMARK
-
-
ModuleHeader MOD_HEADER
= {
"extbans/textban",
"2.2",
"ExtBan ~T (textban) by Syzop",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Forward declarations */
-char *extban_modeT_conv_param(char *para_in);
-int textban_check_ban(Client *client, Channel *channel, char *ban, char **msg, char **errmsg);
-int textban_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
-int extban_modeT_is_banned(Client *client, Channel *channel, char *ban, int type, char **msg, char **errmsg);
-int extban_modeT_is_ok(Client *client, Channel *channel, char *para, int checkt, int what, int what2);
+const char *extban_modeT_conv_param(BanContext *b, Extban *extban);
+int textban_check_ban(Client *client, Channel *channel, const char *ban, const char **msg, const char **errmsg);
+int textban_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype);
+int extban_modeT_is_ok(BanContext *b);
void parse_word(const char *s, char **word, int *type);
MOD_INIT()
@@ -94,10 +84,10 @@ MOD_INIT()
MARK_AS_OFFICIAL_MODULE(modinfo);
memset(&req, 0, sizeof(ExtbanInfo));
- req.flag = 'T';
+ req.letter = 'T';
+ req.name = "text";
req.options = EXTBOPT_NOSTACKCHILD; /* disallow things like ~n:~T, as we only affect text. */
req.conv_param = extban_modeT_conv_param;
- req.is_banned = extban_modeT_is_banned;
req.is_ok = extban_modeT_is_ok;
if (!ExtbanAdd(modinfo->handle, req))
@@ -262,21 +252,21 @@ unsigned int counttextbans(Channel *channel)
}
-int extban_modeT_is_ok(Client *client, Channel *channel, char *para, int checkt, int what, int what2)
+int extban_modeT_is_ok(BanContext *b)
{
int n;
- if ((what == MODE_ADD) && (what2 == EXBTYPE_EXCEPT) && MyUser(client))
+ if ((b->what == MODE_ADD) && (b->ban_type == EXBTYPE_EXCEPT) && MyUser(b->client))
return 0; /* except is not supported */
/* We check the # of bans in the channel, may not exceed MAX_EXTBANT_PER_CHAN */
- if ((what == MODE_ADD) && (checkt == EXBCHK_PARAM) &&
- MyUser(client) && !IsOper(client) &&
- ((n = counttextbans(channel)) >= MAX_EXTBANT_PER_CHAN))
+ if ((b->what == MODE_ADD) && (b->is_ok_check == EXBCHK_PARAM) &&
+ MyUser(b->client) && !IsOper(b->client) &&
+ ((n = counttextbans(b->channel)) >= MAX_EXTBANT_PER_CHAN))
{
/* We check the # of bans in the channel, may not exceed MAX_EXTBANT_PER_CHAN */
- sendnumeric(client, ERR_BANLISTFULL, channel->chname, para);
- sendnotice(client, "Too many textbans for this channel");
+ sendnumeric(b->client, ERR_BANLISTFULL, b->channel->name, b->banstr); // FIXME: wants b->full_banstr here
+ sendnotice(b->client, "Too many textbans for this channel");
return 0;
}
return 1;
@@ -298,7 +288,7 @@ char *conv_pattern_asterisks(const char *pattern)
}
/** Ban callbacks */
-char *extban_modeT_conv_param(char *para_in)
+const char *extban_modeT_conv_param(BanContext *b, Extban *extban)
{
static char retbuf[MAX_LENGTH+1];
char para[MAX_LENGTH+1], *action, *text, *p;
@@ -307,7 +297,7 @@ char *extban_modeT_conv_param(char *para_in)
int ap = 0;
#endif
- strlcpy(para, para_in+3, sizeof(para)); /* work on a copy (and truncate it) */
+ strlcpy(para, b->banstr, sizeof(para)); /* work on a copy (and truncate it) */
/* ~T::
* ~T:user@host:: if UHOSTFEATURE is enabled
@@ -380,26 +370,20 @@ char *extban_modeT_conv_param(char *para_in)
/* Rebuild the string.. can be cut off if too long. */
#ifdef UHOSTFEATURE
- snprintf(retbuf, sizeof(retbuf), "~T:%s:%s:%s", uhost, action, text);
+ snprintf(retbuf, sizeof(retbuf), "%s:%s:%s", uhost, action, text);
#else
- snprintf(retbuf, sizeof(retbuf), "~T:%s:%s", action, text);
+ snprintf(retbuf, sizeof(retbuf), "%s:%s", action, text);
#endif
return retbuf;
}
-/** This is the regular "is banned?" routine. We can't use this as we need to be called for voiced users as well */
-int extban_modeT_is_banned(Client *client, Channel *channel, char *ban, int checktype, char **msg, char **errmsg)
-{
- return 0;
-}
-
/** Check for text bans (censor and block) */
-int textban_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
+int textban_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype)
{
Ban *ban;
/* +h/+o/+a/+q users bypass textbans */
- if (is_skochanop(client, channel))
+ if (check_channel_access(client, channel, "hoaq"))
return HOOK_CONTINUE;
/* IRCOps with these privileges bypass textbans too */
@@ -409,21 +393,29 @@ int textban_can_send_to_channel(Client *client, Channel *channel, Membership *lp
/* Now we have to manually walk the banlist and check if things match */
for (ban = channel->banlist; ban; ban=ban->next)
{
- if (!strncmp(ban->banstr, "~T:", 3))
+ char *banstr = ban->banstr;
+
+ /* Pretend time does not exist... */
+ if (!strncmp(banstr, "~t:", 3))
{
- /* ~T ban */
- if (textban_check_ban(client, channel, ban->banstr, msg, errmsg))
+ banstr = strchr(banstr+3, ':');
+ if (!banstr)
+ continue;
+ banstr++;
+ }
+ else if (!strncmp(banstr, "~time:", 6))
+ {
+ banstr = strchr(banstr+6, ':');
+ if (!banstr)
+ continue;
+ banstr++;
+ }
+
+ if (!strncmp(banstr, "~T:", 3) || !strncmp(banstr, "~text:", 6))
+ {
+ /* text ban */
+ if (textban_check_ban(client, channel, banstr, msg, errmsg))
return HOOK_DENY;
- } else
- if (!strncmp(ban->banstr, "~t:", 3))
- {
- /* Stacked ~t:xx:~T ban (timed text ban) */
- char *p = strchr(ban->banstr+3, ':');
- if (p && !strncmp(p+1, "~T:", 3))
- {
- if (textban_check_ban(client, channel, p+1, msg, errmsg))
- return HOOK_DENY;
- }
}
}
@@ -431,23 +423,18 @@ int textban_can_send_to_channel(Client *client, Channel *channel, Membership *lp
}
-int textban_check_ban(Client *client, Channel *channel, char *ban, char **msg, char **errmsg)
+int textban_check_ban(Client *client, Channel *channel, const char *ban, const char **msg, const char **errmsg)
{
static char retbuf[512];
char filtered[512]; /* temp input buffer */
long fl;
int cleaned=0;
- char *p;
+ const char *p;
#ifdef UHOSTFEATURE
char buf[512], uhost[USERLEN + HOSTLEN + 16];
#endif
char tmp[1024], *word;
int type;
-#ifdef BENCHMARK
- struct timeval tv_alpha, tv_beta;
-
- gettimeofday(&tv_alpha, NULL);
-#endif
/* We can only filter on non-NULL text of course */
if ((msg == NULL) || (*msg == NULL))
@@ -460,7 +447,10 @@ int textban_check_ban(Client *client, Channel *channel, char *ban, char **msg, c
#endif
strlcpy(filtered, StripControlCodes(*msg), sizeof(filtered));
- p = ban + 3;
+ p = strchr(ban, ':');
+ if (!p)
+ return 0; /* "impossible" */
+ p++;
#ifdef UHOSTFEATURE
/* First.. deal with userhost... */
strcpy(buf, p);
@@ -496,13 +486,6 @@ int textban_check_ban(Client *client, Channel *channel, char *ban, char **msg, c
#endif
}
-#ifdef BENCHMARK
- gettimeofday(&tv_beta, NULL);
- ircd_log(LOG_ERROR, "TextBan Timing: %ld microseconds (%s / %s / %d)",
- ((tv_beta.tv_sec - tv_alpha.tv_sec) * 1000000) + (tv_beta.tv_usec - tv_alpha.tv_usec),
- client->name, channel->chname, strlen(*msg));
-#endif
-
if (cleaned)
{
/* check for null string */
diff --git a/src/modules/extbans/timedban.c b/src/modules/extbans/timedban.c
index 1b5f130..5ec418c 100644
--- a/src/modules/extbans/timedban.c
+++ b/src/modules/extbans/timedban.c
@@ -51,13 +51,13 @@ ModuleHeader MOD_HEADER
"1.0",
"ExtBan ~t: automatically removed timed bans",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Forward declarations */
-char *timedban_extban_conv_param(char *para_in);
-int timedban_extban_is_ok(Client *client, Channel* channel, char *para_in, int checkt, int what, int what2);
-int timedban_is_banned(Client *client, Channel *channel, char *ban, int chktype, char **msg, char **errmsg);
+const char *timedban_extban_conv_param(BanContext *b, Extban *extban);
+int timedban_extban_is_ok(BanContext *b);
+int timedban_is_banned(BanContext *b);
void add_send_mode_param(Channel *channel, Client *from, char what, char mode, char *param);
char *timedban_chanmsg(Client *, Client *, Channel *, char *, int);
@@ -70,18 +70,20 @@ MOD_TEST()
MOD_INIT()
{
-ExtbanInfo extban;
+ ExtbanInfo extban;
MARK_AS_OFFICIAL_MODULE(modinfo);
memset(&extban, 0, sizeof(ExtbanInfo));
- extban.flag = 't';
+ 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;
extban.is_banned = timedban_is_banned;
+ extban.is_banned_events = BANCHK_ALL;
if (!ExtbanAdd(modinfo->handle, extban))
{
@@ -106,17 +108,18 @@ MOD_UNLOAD()
/** Generic helper for our conv_param extban function.
* Mostly copied from clean_ban_mask()
+ * FIXME: Figure out why we have this one at all and not use conv_param? ;)
*/
-char *generic_clean_ban_mask(char *mask)
+const char *generic_clean_ban_mask(BanContext *b, Extban *extban)
{
char *cp, *x;
char *user;
char *host;
- Extban *p;
static char maskbuf[512];
+ char *mask;
/* Work on a copy */
- strlcpy(maskbuf, mask, sizeof(maskbuf));
+ strlcpy(maskbuf, b->banstr, sizeof(maskbuf));
mask = maskbuf;
cp = strchr(mask, ' ');
@@ -136,11 +139,22 @@ char *generic_clean_ban_mask(char *mask)
/* Extended ban? */
if (is_extended_ban(mask))
{
- p = findmod_by_bantype(mask[1]);
- if (!p)
+ const char *nextbanstr;
+ Extban *extban = findmod_by_bantype(mask, &nextbanstr);
+ if (!extban)
return NULL; /* reject unknown extban */
- if (p->conv_param)
- return p->conv_param(mask);
+ if (extban->conv_param)
+ {
+ const char *ret;
+ static char retbuf[512];
+ BanContext *newb = safe_alloc(sizeof(BanContext));
+ newb->banstr = nextbanstr;
+ newb->conv_options = b->conv_options;
+ ret = extban->conv_param(newb, extban);
+ ret = prefix_with_extban(ret, newb, extban, retbuf, sizeof(retbuf));
+ safe_free(newb);
+ return ret;
+ }
/* else, do some basic sanity checks and cut it off at 80 bytes */
if ((mask[1] != ':') || (mask[2] == '\0'))
return NULL; /* require a ":" after extban type */
@@ -169,7 +183,7 @@ char *generic_clean_ban_mask(char *mask)
}
/** Convert ban to an acceptable format (or return NULL to fully reject it) */
-char *timedban_extban_conv_param(char *para_in)
+const char *timedban_extban_conv_param(BanContext *b, Extban *extban)
{
static char retbuf[MAX_LENGTH+1];
char para[MAX_LENGTH+1];
@@ -177,13 +191,13 @@ char *timedban_extban_conv_param(char *para_in)
char *durationstr; /**< Duration, such as '5' */
int duration;
char *matchby; /**< Matching method, such as 'n!u@h' */
- char *newmask; /**< Cleaned matching method, such as 'n!u@h' */
+ const char *newmask; /**< Cleaned matching method, such as 'n!u@h' */
static int timedban_extban_conv_param_recursion = 0;
if (timedban_extban_conv_param_recursion)
return NULL; /* reject: recursion detected! */
- strlcpy(para, para_in+3, sizeof(para)); /* work on a copy (and truncate it) */
+ strlcpy(para, b->banstr, sizeof(para)); /* work on a copy (and truncate it) */
/* ~t:duration:n!u@h for direct matching
* ~t:duration:~x:.... when calling another bantype
@@ -203,12 +217,14 @@ char *timedban_extban_conv_param(char *para_in)
strlcpy(tmpmask, matchby, sizeof(tmpmask));
timedban_extban_conv_param_recursion++;
//newmask = extban_conv_param_nuh_or_extban(tmpmask);
- newmask = generic_clean_ban_mask(tmpmask);
+ b->banstr = matchby; // this was previously 'tmpmask' but then it's a copy-copy-copy.. :D
+ newmask = generic_clean_ban_mask(b, extban);
timedban_extban_conv_param_recursion--;
if (!newmask || (strlen(newmask) <= 1))
return NULL;
- snprintf(retbuf, sizeof(retbuf), "~t:%d:%s", duration, newmask);
+ //snprintf(retbuf, sizeof(retbuf), "~t:%d:%s", duration, newmask);
+ snprintf(retbuf, sizeof(retbuf), "%d:%s", duration, newmask);
return retbuf;
}
@@ -226,54 +242,50 @@ int timedban_extban_syntax(Client *client, int checkt, char *reason)
}
/** Generic helper for sub-bans, used by our "is this ban ok?" function */
-int generic_ban_is_ok(Client *client, Channel *channel, char *mask, int checkt, int what, int what2)
+int generic_ban_is_ok(BanContext *b)
{
- if ((mask[0] == '~') && MyUser(client))
+ if ((b->banstr[0] == '~') && MyUser(b->client))
{
- Extban *p;
+ Extban *extban;
+ const char *nextbanstr;
/* This portion is copied from clean_ban_mask() */
- if (is_extended_ban(mask) && MyUser(client))
+ if (is_extended_ban(b->banstr) && MyUser(b->client))
{
- if (RESTRICT_EXTENDEDBANS && !ValidatePermissionsForPath("immune:restrict-extendedbans",client,NULL,NULL,NULL))
+ if (RESTRICT_EXTENDEDBANS && !ValidatePermissionsForPath("immune:restrict-extendedbans",b->client,NULL,NULL,NULL))
{
if (!strcmp(RESTRICT_EXTENDEDBANS, "*"))
{
- if (checkt == EXBCHK_ACCESS_ERR)
- sendnotice(client, "Setting/removing of extended bans has been disabled");
+ if (b->is_ok_check == EXBCHK_ACCESS_ERR)
+ sendnotice(b->client, "Setting/removing of extended bans has been disabled");
return 0; /* REJECT */
}
- if (strchr(RESTRICT_EXTENDEDBANS, mask[1]))
+ if (strchr(RESTRICT_EXTENDEDBANS, b->banstr[1]))
{
- if (checkt == EXBCHK_ACCESS_ERR)
- sendnotice(client, "Setting/removing of extended bantypes '%s' has been disabled", RESTRICT_EXTENDEDBANS);
+ if (b->is_ok_check == EXBCHK_ACCESS_ERR)
+ sendnotice(b->client, "Setting/removing of extended bantypes '%s' has been disabled", RESTRICT_EXTENDEDBANS);
return 0; /* REJECT */
}
}
/* And next is inspired by cmd_mode */
- p = findmod_by_bantype(mask[1]);
- if (checkt == EXBCHK_ACCESS)
+ extban = findmod_by_bantype(b->banstr, &nextbanstr);
+ if (extban && extban->is_ok)
{
- if (p && p->is_ok && !p->is_ok(client, channel, mask, EXBCHK_ACCESS, what, what2) &&
- !ValidatePermissionsForPath("channel:override:mode:extban",client,NULL,channel,NULL))
+ b->banstr = nextbanstr;
+ if ((b->is_ok_check == EXBCHK_ACCESS) || (b->is_ok_check == EXBCHK_ACCESS_ERR))
{
- return 0; /* REJECT */
- }
- } else
- if (checkt == EXBCHK_ACCESS_ERR)
- {
- if (p && p->is_ok && !p->is_ok(client, channel, mask, EXBCHK_ACCESS, what, what2) &&
- !ValidatePermissionsForPath("channel:override:mode:extban",client,NULL,channel,NULL))
+ if (!extban->is_ok(b) &&
+ !ValidatePermissionsForPath("channel:override:mode:extban",b->client,NULL,b->channel,NULL))
+ {
+ return 0; /* REJECT */
+ }
+ } else
+ if (b->is_ok_check == EXBCHK_PARAM)
{
- p->is_ok(client, channel, mask, EXBCHK_ACCESS_ERR, what, what2);
- return 0; /* REJECT */
- }
- } else
- if (checkt == EXBCHK_PARAM)
- {
- if (p && p->is_ok && !p->is_ok(client, channel, mask, EXBCHK_PARAM, what, what2))
- {
- return 0; /* REJECT */
+ if (!extban->is_ok(b))
+ {
+ return 0; /* REJECT */
+ }
}
}
}
@@ -288,7 +300,7 @@ int generic_ban_is_ok(Client *client, Channel *channel, char *mask, int checkt,
}
/** Validate ban ("is this ban ok?") */
-int timedban_extban_is_ok(Client *client, Channel* channel, char *para_in, int checkt, int what, int what2)
+int timedban_extban_is_ok(BanContext *b)
{
char para[MAX_LENGTH+1];
char tmpmask[MAX_LENGTH+1];
@@ -300,13 +312,13 @@ int timedban_extban_is_ok(Client *client, Channel* channel, char *para_in, int c
int res;
/* Always permit deletion */
- if (what == MODE_DEL)
+ if (b->what == MODE_DEL)
return 1;
if (timedban_extban_is_ok_recursion)
return 0; /* Recursion detected (~t:1:~t:....) */
- strlcpy(para, para_in+3, sizeof(para)); /* work on a copy (and truncate it) */
+ strlcpy(para, b->banstr, sizeof(para)); /* work on a copy (and truncate it) */
/* ~t:duration:n!u@h for direct matching
* ~t:duration:~x:.... when calling another bantype
@@ -315,18 +327,19 @@ int timedban_extban_is_ok(Client *client, Channel* channel, char *para_in, int c
durationstr = para;
matchby = strchr(para, ':');
if (!matchby || !matchby[1])
- return timedban_extban_syntax(client, checkt, "Invalid syntax");
+ return timedban_extban_syntax(b->client, b->is_ok_check, "Invalid syntax");
*matchby++ = '\0';
duration = atoi(durationstr);
if ((duration <= 0) || (duration > TIMEDBAN_MAX_TIME))
- return timedban_extban_syntax(client, checkt, "Invalid duration time");
+ return timedban_extban_syntax(b->client, b->is_ok_check, "Invalid duration time");
strlcpy(tmpmask, matchby, sizeof(tmpmask));
timedban_extban_is_ok_recursion++;
- //res = extban_is_ok_nuh_extban(client, channel, tmpmask, checkt, what, what2);
- res = generic_ban_is_ok(client, channel, tmpmask, checkt, what, what2);
+ //res = extban_is_ok_nuh_extban(b->client, b->channel, tmpmask, b->is_ok_check, b->what, b->ban_type);
+ b->banstr = tmpmask;
+ res = generic_ban_is_ok(b);
timedban_extban_is_ok_recursion--;
if (res == 0)
{
@@ -334,41 +347,48 @@ int timedban_extban_is_ok(Client *client, Channel* channel, char *para_in, int c
* invalid n!u@h syntax, unknown (sub)extbantype,
* disabled extban type in conf, too much recursion, etc.
*/
- return timedban_extban_syntax(client, checkt, "Invalid matcher");
+ return timedban_extban_syntax(b->client, b->is_ok_check, "Invalid matcher");
}
return 1; /* OK */
}
/** Check if the user is currently banned */
-int timedban_is_banned(Client *client, Channel *channel, char *ban, int chktype, char **msg, char **errmsg)
+int timedban_is_banned(BanContext *b)
{
- if (strncmp(ban, "~t:", 3))
- return 0; /* not for us */
- ban = strchr(ban+3, ':'); /* skip time argument */
- if (!ban)
+ b->banstr = strchr(b->banstr, ':'); /* skip time argument */
+ if (!b->banstr)
return 0; /* invalid fmt */
- ban++;
+ b->banstr++; /* skip over final semicolon */
- return ban_check_mask(client, channel, ban, chktype, msg, errmsg, 0);
+ return ban_check_mask(b);
}
-/** Helper to check if the ban has been expired */
+/** Helper to check if the ban has been expired.
+ */
int timedban_has_ban_expired(Ban *ban)
{
char *banstr = ban->banstr;
- char *p;
+ char *p1, *p2;
int t;
time_t expire_on;
- if (strncmp(banstr, "~t:", 3))
+ /* The caller has only performed a very light check (string starting
+ * with ~t, in the interest of performance), so we don't know yet if
+ * it REALLY is a timed ban. We check that first here...
+ */
+ if (!strncmp(banstr, "~t:", 3))
+ p1 = banstr + 3;
+ else if (!strncmp(banstr, "~time:", 6))
+ p1 = banstr + 6;
+ else
return 0; /* not for us */
- p = strchr(banstr+3, ':'); /* skip time argument */
- if (!p)
+ p2 = strchr(p1+1, ':'); /* skip time argument */
+ if (!p2)
return 0; /* invalid fmt */
- *p = '\0'; /* danger.. must restore!! */
- t = atoi(banstr+3);
- *p = ':'; /* restored.. */
+ *p2 = '\0'; /* danger.. must restore!! */
+ t = atoi(p1);
+ *p2 = ':'; /* restored.. */
expire_on = ban->when + (t * 60) - TIMEDBAN_TIMER_DELTA;
@@ -398,14 +418,14 @@ EVENT(timedban_timeout)
* is too costly. So we stick with this. It should be
* good enough. Alternative would be some channel->id value.
*/
- if (((unsigned int)channel->chname[1] % TIMEDBAN_TIMER_ITERATION_SPLIT) != current_iteration)
+ if (((unsigned int)channel->name[1] % TIMEDBAN_TIMER_ITERATION_SPLIT) != current_iteration)
continue; /* not this time, maybe next */
*mbuf = *pbuf = '\0';
for (ban = channel->banlist; ban; ban=nextban)
{
nextban = ban->next;
- if (!strncmp(ban->banstr, "~t:", 3) && timedban_has_ban_expired(ban))
+ if (!strncmp(ban->banstr, "~t", 2) && timedban_has_ban_expired(ban))
{
add_send_mode_param(channel, &me, '-', 'b', ban->banstr);
del_listmode(&channel->banlist, channel, ban->banstr);
@@ -414,7 +434,7 @@ EVENT(timedban_timeout)
for (ban = channel->exlist; ban; ban=nextban)
{
nextban = ban->next;
- if (!strncmp(ban->banstr, "~t:", 3) && timedban_has_ban_expired(ban))
+ if (!strncmp(ban->banstr, "~t", 2) && timedban_has_ban_expired(ban))
{
add_send_mode_param(channel, &me, '-', 'e', ban->banstr);
del_listmode(&channel->exlist, channel, ban->banstr);
@@ -423,7 +443,7 @@ EVENT(timedban_timeout)
for (ban = channel->invexlist; ban; ban=nextban)
{
nextban = ban->next;
- if (!strncmp(ban->banstr, "~t:", 3) && timedban_has_ban_expired(ban))
+ if (!strncmp(ban->banstr, "~t", 2) && timedban_has_ban_expired(ban))
{
add_send_mode_param(channel, &me, '-', 'I', ban->banstr);
del_listmode(&channel->invexlist, channel, ban->banstr);
@@ -433,8 +453,8 @@ EVENT(timedban_timeout)
{
MessageTag *mtags = NULL;
new_message(&me, NULL, &mtags);
- sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags, ":%s MODE %s %s %s", me.name, channel->chname, mbuf, pbuf);
- sendto_server(NULL, 0, 0, mtags, ":%s MODE %s %s %s 0", me.id, channel->chname, mbuf, pbuf);
+ sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags, ":%s MODE %s %s %s", me.name, channel->name, mbuf, pbuf);
+ sendto_server(NULL, 0, 0, mtags, ":%s MODE %s %s %s 0", me.id, channel->name, mbuf, pbuf);
free_message_tags(mtags);
*pbuf = 0;
}
@@ -484,8 +504,8 @@ void add_send_mode_param(Channel *channel, Client *from, char what, char mode, c
MessageTag *mtags = NULL;
new_message(&me, NULL, &mtags);
- sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags, ":%s MODE %s %s %s", me.name, channel->chname, mbuf, pbuf);
- sendto_server(NULL, 0, 0, mtags, ":%s MODE %s %s %s 0", me.id, channel->chname, mbuf, pbuf);
+ sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags, ":%s MODE %s %s %s", me.name, channel->name, mbuf, pbuf);
+ sendto_server(NULL, 0, 0, mtags, ":%s MODE %s %s %s 0", me.id, channel->name, mbuf, pbuf);
free_message_tags(mtags);
send = 0;
*pbuf = 0;
diff --git a/src/modules/extended-monitor.c b/src/modules/extended-monitor.c
new file mode 100644
index 0000000..34c9f1f
--- /dev/null
+++ b/src/modules/extended-monitor.c
@@ -0,0 +1,153 @@
+/*
+ * IRC - Internet Relay Chat, src/modules/extended-monitor.c
+ * (C) 2021 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.
+ */
+
+#include "unrealircd.h"
+
+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_notification(Client *client, Watch *watch, Link *lp, int event);
+
+ModuleHeader MOD_HEADER
+ = {
+ "extended-monitor",
+ "5.0",
+ "extended functionality for /monitor",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+ };
+
+MOD_INIT()
+{
+ ClientCapabilityInfo cap;
+ ClientCapability *c;
+
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ ModDataInfo mreq;
+
+ memset(&cap, 0, sizeof(cap));
+ cap.name = "draft/extended-monitor";
+ c = ClientCapabilityAdd(modinfo->handle, &cap, &CAP_EXTENDED_MONITOR);
+ if (!c)
+ {
+ config_error("[%s] Failed to request extended-monitor cap: %s", MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle));
+ return MOD_FAILED;
+ }
+
+ 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);
+
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ return MOD_SUCCESS;
+}
+
+int extended_monitor_away(Client *client, MessageTag *mtags, const char *reason, int already_as_away)
+{
+ if (reason)
+ watch_check(client, WATCH_EVENT_AWAY, extended_monitor_notification);
+ else
+ watch_check(client, WATCH_EVENT_NOTAWAY, extended_monitor_notification);
+
+ return 0;
+}
+
+int extended_monitor_account_login(Client *client, MessageTag *mtags)
+{
+ if (IsLoggedIn(client))
+ watch_check(client, WATCH_EVENT_LOGGEDIN, extended_monitor_notification);
+ else
+ watch_check(client, WATCH_EVENT_LOGGEDOUT, extended_monitor_notification);
+
+ return 0;
+}
+
+int extended_monitor_userhost_changed(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)
+{
+ watch_check(client, WATCH_EVENT_REALNAME, extended_monitor_notification);
+ return 0;
+}
+
+int extended_monitor_notification(Client *client, Watch *watch, Link *lp, int event)
+{
+ if (!(lp->flags & WATCH_FLAG_TYPE_MONITOR))
+ return 0;
+
+ if (!HasCapabilityFast(lp->value.client, CAP_EXTENDED_MONITOR))
+ return 0; /* this client does not support our notifications */
+
+ if (has_common_channels(client, lp->value.client))
+ return 0; /* will be notified anyway */
+
+ switch (event)
+ {
+ case WATCH_EVENT_AWAY:
+ if (HasCapability(lp->value.client, "away-notify"))
+ sendto_prefix_one(lp->value.client, client, NULL, ":%s AWAY :%s", client->name, client->user->away);
+ break;
+ case WATCH_EVENT_NOTAWAY:
+ if (HasCapability(lp->value.client, "away-notify"))
+ sendto_prefix_one(lp->value.client, client, NULL, ":%s AWAY", client->name);
+ break;
+ case WATCH_EVENT_LOGGEDIN:
+ if (HasCapability(lp->value.client, "account-notify"))
+ sendto_prefix_one(lp->value.client, client, NULL, ":%s ACCOUNT :%s", client->name, client->user->account);
+ break;
+ case WATCH_EVENT_LOGGEDOUT:
+ if (HasCapability(lp->value.client, "account-notify"))
+ sendto_prefix_one(lp->value.client, client, NULL, ":%s ACCOUNT :*", client->name);
+ break;
+ case WATCH_EVENT_USERHOST:
+ if (HasCapability(lp->value.client, "chghost"))
+ sendto_prefix_one(lp->value.client, client, NULL, ":%s CHGHOST %s %s", client->name, client->user->username, GetHost(client));
+ break;
+ case WATCH_EVENT_REALNAME:
+ if (HasCapability(lp->value.client, "setname"))
+ sendto_prefix_one(lp->value.client, client, NULL, ":%s SETNAME :%s", client->name, client->info);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
diff --git a/src/modules/extjwt.c b/src/modules/extjwt.c
new file mode 100644
index 0000000..0d9d63c
--- /dev/null
+++ b/src/modules/extjwt.c
@@ -0,0 +1,1151 @@
+/*
+ * IRC - Internet Relay Chat, src/modules/extjwt.c
+ * (C) 2021 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.
+ */
+
+#include "unrealircd.h"
+
+#if defined(__GNUC__)
+/* Temporarily ignore these for this entire file. FIXME later when updating the code for OpenSSL 3: */
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
+/* internal definitions */
+
+#define MSG_EXTJWT "EXTJWT"
+#define MYCONF "extjwt"
+
+#undef NEW_ISUPPORT /* enable this for https://github.com/ircv3/ircv3-specifications/pull/341#issuecomment-617038799 */
+
+#define EXTJWT_METHOD_NOT_SET 0
+#define EXTJWT_METHOD_HS256 1
+#define EXTJWT_METHOD_HS384 2
+#define EXTJWT_METHOD_HS512 3
+#define EXTJWT_METHOD_RS256 4
+#define EXTJWT_METHOD_RS384 5
+#define EXTJWT_METHOD_RS512 6
+#define EXTJWT_METHOD_ES256 7
+#define EXTJWT_METHOD_ES384 8
+#define EXTJWT_METHOD_ES512 9
+#define EXTJWT_METHOD_NONE 10
+
+#define NEEDS_KEY(x) (x>=EXTJWT_METHOD_RS256 && x<=EXTJWT_METHOD_ES512)
+
+#define URL_LENGTH 4096
+#define MODES_SIZE 41 /* about 10 mode chars */
+#define TS_LENGTH 19 /* 64-bit integer */
+#define MAX_TOKEN_CHUNK (510-sizeof(extjwt_message_pattern)-HOSTLEN-CHANNELLEN)
+
+/* OpenSSL 1.0.x compatibility */
+
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
+void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
+{
+ if (pr != NULL)
+ *pr = sig->r;
+ if (ps != NULL)
+ *ps = sig->s;
+}
+#endif
+
+/* struct definitions */
+
+struct extjwt_config {
+ time_t exp_delay;
+ char *secret;
+ int method;
+ char *vfy;
+};
+
+struct jwt_service {
+ char *name;
+ struct extjwt_config *cfg;
+ struct jwt_service *next;
+};
+
+/* function declarations */
+
+CMD_FUNC(cmd_extjwt);
+char *extjwt_make_payload(Client *client, Channel *channel, struct extjwt_config *config);
+char *extjwt_generate_token(const char *payload, struct extjwt_config *config);
+void b64url(char *b64);
+unsigned char *extjwt_hmac_extjwt_hash(int method, const void *key, int keylen, const unsigned char *data, int datalen, unsigned int* resultlen);
+unsigned char *extjwt_sha_pem_extjwt_hash(int method, const void *key, int keylen, const unsigned char *data, int datalen, unsigned int* resultlen);
+unsigned char *extjwt_hash(int method, const void *key, int keylen, const unsigned char *data, int datalen, unsigned int* resultlen);
+char *extjwt_gen_header(int method);
+int extjwt_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs);
+int extjwt_configrun(ConfigFile *cf, ConfigEntry *ce, int type);
+int extjwt_configposttest(int *errs);
+void extjwt_free_services(struct jwt_service **services);
+struct jwt_service *find_jwt_service(struct jwt_service *services, const char *name);
+int extjwt_valid_integer_string(const char *in, int min, int max);
+char *extjwt_test_key(const char *file, int method);
+char *extjwt_read_file_contents(const char *file, int absolute, int *size);
+int EXTJWT_METHOD_from_string(const char *in);
+#ifdef NEW_ISUPPORT
+char *extjwt_isupport_param(void);
+#endif
+
+/* string constants */
+
+const char extjwt_message_pattern[] = ":%s EXTJWT %s %s %s%s";
+
+/* global structs */
+
+ModuleHeader MOD_HEADER = {
+ "extjwt",
+ "6.0",
+ "Command /EXTJWT (web service authorization)",
+ "UnrealIRCd Team",
+ "unrealircd-6"
+};
+
+struct {
+ int have_secret;
+ int have_key;
+ int have_method;
+ int have_expire;
+ int have_vfy;
+ char *key_filename;
+} cfg_state;
+
+struct extjwt_config cfg;
+struct jwt_service *jwt_services;
+
+MOD_TEST()
+{
+ memset(&cfg_state, 0, sizeof(cfg_state));
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, extjwt_configtest);
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGPOSTTEST, 0, extjwt_configposttest);
+ return MOD_SUCCESS;
+}
+
+MOD_INIT()
+{
+ CommandAdd(modinfo->handle, MSG_EXTJWT, cmd_extjwt, 2, CMD_USER);
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, extjwt_configrun);
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ struct jwt_service *service = jwt_services;
+#ifdef NEW_ISUPPORT
+ ISupportAdd(modinfo->handle, "EXTJWT", extjwt_isupport_param());
+#else
+ ISupportAdd(modinfo->handle, "EXTJWT", "1");
+#endif
+ while (service)
+ { /* copy default exp to all services not having one specified */
+ if (service->cfg->exp_delay == 0)
+ service->cfg->exp_delay = cfg.exp_delay;
+ service = service->next;
+ }
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ extjwt_free_services(&jwt_services);
+ return MOD_SUCCESS;
+}
+
+#ifdef NEW_ISUPPORT
+char *extjwt_isupport_param(void)
+{
+ struct jwt_service *services = jwt_services;
+ int count = 0;
+ static char buf[500];
+ strlcpy(buf, "V:1", sizeof(buf));
+ while (services)
+ {
+ strlcat(buf, count?",":"&S:", sizeof(buf));
+ strlcat(buf, services->name, sizeof(buf));
+ count++;
+ services = services->next;
+ }
+ return buf;
+}
+#endif
+
+void extjwt_free_services(struct jwt_service **services){
+ struct jwt_service *ss, *next;
+ ss = *services;
+ while (ss)
+ {
+ next = ss->next;
+ safe_free(ss->name);
+ if (ss->cfg)
+ safe_free(ss->cfg->secret);
+ safe_free(ss->cfg);
+ safe_free(ss);
+ ss = next;
+ }
+ *services = NULL;
+}
+
+struct jwt_service *find_jwt_service(struct jwt_service *services, const char *name)
+{
+ if (!name)
+ return NULL;
+ while (services)
+ {
+ if (services->name && !strcmp(services->name, name))
+ return services;
+ services = services->next;
+ }
+ return NULL;
+}
+
+int extjwt_valid_integer_string(const char *in, int min, int max)
+{
+ int i, val;
+ if (BadPtr(in))
+ return 0;
+ for (i=0; in[i]; i++){
+ if (!isdigit(in[i]))
+ return 0;
+ }
+ val = atoi(in);
+ if (val < min || val > max)
+ return 0;
+ return 1;
+}
+
+int vfy_url_is_valid(const char *string)
+{
+ if (strstr(string, "http://") == string || strstr(string, "https://") == string)
+ {
+ if (strstr(string, "%s"))
+ return 1;
+ }
+ return 0;
+}
+
+char *extjwt_test_key(const char *file, int method)
+{ /* returns NULL when valid */
+ int fsize;
+ char *fcontent = NULL;
+ char *retval = NULL;
+ BIO *bufkey = NULL;
+ EVP_PKEY *pkey = NULL;
+ int type, pkey_type;
+ do {
+ switch (method)
+ {
+ case EXTJWT_METHOD_RS256: case EXTJWT_METHOD_RS384: case EXTJWT_METHOD_RS512:
+ type = EVP_PKEY_RSA;
+ break;
+ case EXTJWT_METHOD_ES256: case EXTJWT_METHOD_ES384: case EXTJWT_METHOD_ES512:
+ type = EVP_PKEY_EC;
+ break;
+ default:
+ retval = "Internal error (invalid type)";
+ return retval;
+ }
+ fcontent = extjwt_read_file_contents(file, 0, &fsize);
+ if (!fcontent)
+ {
+ retval = "Cannot open file";
+ break;
+ }
+ if (fsize == 0)
+ {
+ retval = "File is empty";
+ break;
+ }
+ if (!(bufkey = BIO_new_mem_buf(fcontent, fsize)))
+ {
+ retval = "Unknown error";
+ break;
+ }
+ if (!(pkey = PEM_read_bio_PrivateKey(bufkey, NULL, NULL, NULL)))
+ {
+ retval = "Key is invalid";
+ break;
+ }
+ pkey_type = EVP_PKEY_id(pkey);
+ if (type != pkey_type)
+ {
+ retval = "Key does not match method";
+ break;
+ }
+ } while (0);
+ safe_free(fcontent);
+ if (bufkey)
+ BIO_free(bufkey);
+ if (pkey)
+ EVP_PKEY_free(pkey);
+ return retval;
+}
+
+int EXTJWT_METHOD_from_string(const char *in)
+{
+ if (!strcmp(in, "HS256"))
+ return EXTJWT_METHOD_HS256;
+ if (!strcmp(in, "HS384"))
+ return EXTJWT_METHOD_HS384;
+ if (!strcmp(in, "HS512"))
+ return EXTJWT_METHOD_HS512;
+ if (!strcmp(in, "RS256"))
+ return EXTJWT_METHOD_RS256;
+ if (!strcmp(in, "RS384"))
+ return EXTJWT_METHOD_RS384;
+ if (!strcmp(in, "RS512"))
+ return EXTJWT_METHOD_RS512;
+ if (!strcmp(in, "ES256"))
+ return EXTJWT_METHOD_ES256;
+ if (!strcmp(in, "ES384"))
+ return EXTJWT_METHOD_ES384;
+ if (!strcmp(in, "ES512"))
+ return EXTJWT_METHOD_ES512;
+ if (!strcmp(in, "NONE"))
+ return EXTJWT_METHOD_NONE;
+ return EXTJWT_METHOD_NOT_SET;
+}
+
+/* Configuration is described in conf/modules.optional.conf */
+
+int extjwt_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
+{
+ int errors = 0;
+ ConfigEntry *cep, *cep2;
+ int i;
+ struct jwt_service *services = NULL;
+ struct jwt_service **ss = &services; /* list for checking whether service names repeat */
+ int have_ssecret, have_smethod, have_svfy, have_scert;
+ unsigned int sfilename_line_number = 0;
+ char *sfilename = NULL;
+
+ if (type != CONFIG_MAIN)
+ return 0;
+
+ if (!ce || strcmp(ce->name, MYCONF))
+ return 0;
+
+ for (cep = ce->items; cep; cep = cep->next)
+ {
+ if (!cep->value)
+ {
+ config_error("%s:%i: blank %s::%s without value", cep->file->filename, cep->line_number, MYCONF, cep->name);
+ errors++;
+ continue;
+ }
+ if (!strcmp(cep->name, "method"))
+ {
+ if (cfg_state.have_method)
+ {
+ config_error("%s:%i: duplicate %s::%s item", cep->file->filename, cep->line_number, MYCONF, cep->name);
+ errors++;
+ continue;
+ }
+ cfg_state.have_method = EXTJWT_METHOD_from_string(cep->value);
+ if (cfg_state.have_method == EXTJWT_METHOD_NOT_SET)
+ {
+ config_error("%s:%i: invalid value %s::%s \"%s\" (check docs for allowed options)", cep->file->filename, cep->line_number, MYCONF, cep->name, cep->value);
+ errors++;
+ }
+ continue;
+ }
+ if (!strcmp(cep->name, "expire-after"))
+ {
+ if (!extjwt_valid_integer_string(cep->value, 1, 9999))
+ {
+ config_error("%s:%i: %s::%s must be an integer between 1 and 9999 (seconds)", cep->file->filename, cep->line_number, MYCONF, cep->name);
+ errors++;
+ }
+ continue;
+ }
+ if (!strcmp(cep->name, "secret"))
+ {
+ if (cfg_state.have_secret)
+ {
+ config_error("%s:%i: duplicate %s::%s item", cep->file->filename, cep->line_number, MYCONF, cep->name);
+ errors++;
+ continue;
+ }
+ cfg_state.have_secret = 1;
+ if (strlen(cep->value) < 4)
+ {
+ config_error("%s:%i: Secret specified in %s::%s is too short!", cep->file->filename, cep->line_number, MYCONF, cep->name);
+ errors++;
+ }
+ continue;
+ }
+ if (!strcmp(cep->name, "key"))
+ {
+ if (cfg_state.have_key)
+ {
+ config_error("%s:%i: duplicate %s::%s item", cep->file->filename, cep->line_number, MYCONF, cep->name);
+ errors++;
+ continue;
+ }
+ if (!is_file_readable(cep->value, CONFDIR))
+ {
+ config_error("%s:%i: Cannot open file \"%s\" specified in %s::%s for reading", cep->file->filename, cep->line_number, cep->value, MYCONF, cep->name);
+ errors++;
+ }
+ safe_strdup(cfg_state.key_filename, cep->value);
+ cfg_state.have_key = 1;
+ continue;
+ }
+ if (!strcmp(cep->name, "verify-url"))
+ {
+ if (cfg_state.have_vfy)
+ {
+ config_error("%s:%i: duplicate %s:%s item", cep->file->filename, cep->line_number, MYCONF, cep->name);
+ errors++;
+ continue;
+ }
+ cfg_state.have_vfy = 1;
+ if (!vfy_url_is_valid(cep->value))
+ {
+ config_error("%s:%i: Optional URL specified in %s::%s is invalid!", cep->file->filename, cep->line_number, MYCONF, cep->name);
+ errors++;
+ continue;
+ }
+ if (strlen(cep->value) > URL_LENGTH)
+ {
+ config_error("%s:%i: Optional URL specified in %s::%s is too long!", cep->file->filename, cep->line_number, MYCONF, cep->name);
+ errors++;
+ }
+ continue;
+ }
+ if (!strcmp(cep->name, "service"))
+ {
+ have_ssecret = 0;
+ have_smethod = 0;
+ have_svfy = 0;
+ have_scert = 0;
+ if (strchr(cep->value, ' ') || strchr(cep->value, ','))
+ {
+ config_error("%s:%i: Invalid %s::%s name (contains spaces or commas)", cep->file->filename, cep->line_number, MYCONF, cep->name);
+ errors++;
+ continue;
+ }
+ if (find_jwt_service(services, cep->value))
+ {
+ config_error("%s:%i: Duplicate %s::%s name \"%s\"", cep->file->filename, cep->line_number, MYCONF, cep->name, cep->value);
+ errors++;
+ continue;
+ }
+ *ss = safe_alloc(sizeof(struct jwt_service)); /* store the new name for further checking */
+ safe_strdup((*ss)->name, cep->value);
+ ss = &(*ss)->next;
+ for (cep2 = cep->items; cep2; cep2 = cep2->next)
+ {
+ if (!cep2->name || !cep2->value || !cep2->value[0])
+ {
+ config_error("%s:%i: blank/incomplete %s::service entry", cep2->file->filename, cep2->line_number, MYCONF);
+ errors++;
+ continue;
+ }
+
+ if (!strcmp(cep2->name, "method"))
+ {
+ if (have_smethod)
+ {
+ config_error("%s:%i: duplicate %s::service::%s item", cep2->file->filename, cep2->line_number, MYCONF, cep2->name);
+ errors++;
+ continue;
+ }
+ have_smethod = EXTJWT_METHOD_from_string(cep2->value);
+ if (have_smethod == EXTJWT_METHOD_NOT_SET || have_smethod == EXTJWT_METHOD_NONE)
+ {
+ config_error("%s:%i: invalid value of optional %s::service::%s \"%s\" (check docs for allowed options)", cep2->file->filename, cep2->line_number, MYCONF, cep2->name, cep2->value);
+ errors++;
+ }
+ continue;
+ }
+
+ if (!strcmp(cep2->name, "secret"))
+ {
+ if (have_ssecret)
+ {
+ config_error("%s:%i: duplicate %s::service::%s item", cep2->file->filename, cep2->line_number, MYCONF, cep2->name);
+ errors++;
+ continue;
+ }
+ have_ssecret = 1;
+ if (strlen(cep2->value) < 4) /* TODO maybe a better check? */
+ {
+ config_error("%s:%i: Secret specified in %s::service::%s is too short!", cep2->file->filename, cep2->line_number, MYCONF, cep2->name);
+ errors++;
+ }
+ continue;
+ }
+
+ if (!strcmp(cep2->name, "key"))
+ {
+ if (have_scert)
+ {
+ config_error("%s:%i: duplicate %s::service::%s item", cep2->file->filename, cep2->line_number, MYCONF, cep2->name);
+ errors++;
+ continue;
+ }
+ if (!is_file_readable(cep2->value, CONFDIR))
+ {
+ config_error("%s:%i: Cannot open file \"%s\" specified in %s::service::%s for reading", cep2->file->filename, cep2->line_number, cep2->value, MYCONF, cep2->name);
+ errors++;
+ }
+ have_scert = 1;
+ safe_strdup(sfilename, cep2->value);
+ sfilename_line_number = cep2->line_number;
+ continue;
+ }
+
+ if (!strcmp(cep2->name, "expire-after"))
+ {
+ if (!extjwt_valid_integer_string(cep2->value, 1, 9999))
+ {
+ config_error("%s:%i: %s::%s must be an integer between 1 and 9999 (seconds)", cep2->file->filename, cep2->line_number, MYCONF, cep2->name);
+ errors++;
+ }
+ continue;
+ }
+
+ if (!strcmp(cep2->name, "verify-url"))
+ {
+ if (have_svfy)
+ {
+ config_error("%s:%i: duplicate %s::service::%s item", cep2->file->filename, cep2->line_number, MYCONF, cep2->name);
+ errors++;
+ continue;
+ }
+ have_svfy = 1;
+ if (!vfy_url_is_valid(cep2->value))
+ {
+ config_error("%s:%i: Optional URL specified in %s::service::%s is invalid!", cep2->file->filename, cep2->line_number, MYCONF, cep2->name);
+ errors++;
+ continue;
+ }
+ if (strlen(cep2->value) > URL_LENGTH)
+ {
+ config_error("%s:%i: Optional URL specified in %s::service::%s is too long!", cep2->file->filename, cep2->line_number, MYCONF, cep2->name);
+ errors++;
+ }
+ continue;
+ }
+
+ config_error("%s:%i: invalid %s::service attribute %s (must be one of: name, secret, expire-after)", cep2->file->filename, cep2->line_number, MYCONF, cep2->name);
+ errors++;
+ }
+ if (!have_smethod)
+ {
+ config_error("%s:%i: invalid %s::service entry (no %s::service::method specfied)", cep->file->filename, cep->line_number, MYCONF, MYCONF);
+ errors++;
+ continue;
+ }
+ if (have_ssecret && NEEDS_KEY(have_smethod))
+ {
+ config_error("%s:%i: invalid %s::service entry (this method needs %s::service::key and not %s::service::secret option)", cep->file->filename, cep->line_number, MYCONF, MYCONF, MYCONF);
+ errors++;
+ continue;
+ }
+ if (have_scert && !NEEDS_KEY(have_smethod))
+ {
+ config_error("%s:%i: invalid %s::service entry (this method needs %s::service::secret and not %s::service::key option)", cep->file->filename, cep->line_number, MYCONF, MYCONF, MYCONF);
+ errors++;
+ continue;
+ }
+ if (!have_ssecret && !NEEDS_KEY(have_smethod))
+ {
+ config_error("%s:%i: invalid %s::service entry (must contain %s::service::secret option)", cep->file->filename, cep->line_number, MYCONF, MYCONF);
+ errors++;
+ continue;
+ }
+ if (!have_scert && NEEDS_KEY(have_smethod)) {
+ config_error("%s:%i: invalid %s::service entry (must contain %s::service::key option)", cep->file->filename, cep->line_number, MYCONF, MYCONF);
+ errors++;
+ continue;
+ }
+ if (NEEDS_KEY(have_smethod) && have_scert)
+ {
+ char *keyerr;
+ keyerr = extjwt_test_key(sfilename, have_smethod);
+ if (keyerr)
+ {
+ config_error("%s:%i: Invalid key file specified for %s::key: %s", cep->file->filename, sfilename_line_number, MYCONF, keyerr);
+ errors++;
+ }
+ }
+ continue;
+ }
+ config_error("%s:%i: unknown directive %s::%s", cep->file->filename, cep->line_number, MYCONF, cep->name);
+ errors++;
+ }
+ *errs = errors;
+ extjwt_free_services(&services);
+ if (errors)
+ safe_free(cfg_state.key_filename);
+ safe_free(sfilename);
+ return errors ? -1 : 1;
+}
+
+int extjwt_configposttest(int *errs)
+{
+ int errors = 0;
+ if (cfg_state.have_method == EXTJWT_METHOD_NOT_SET)
+ {
+ config_error("No %s::method specfied!", MYCONF);
+ errors++;
+ } else
+ {
+ if (cfg_state.have_method != EXTJWT_METHOD_NONE && !NEEDS_KEY(cfg_state.have_method) && !cfg_state.have_secret)
+ {
+ config_error("No %s::secret specfied as required by requested method!", MYCONF);
+ errors++;
+ }
+ if ((cfg_state.have_method == EXTJWT_METHOD_NONE || NEEDS_KEY(cfg_state.have_method)) && cfg_state.have_secret)
+ {
+ config_error("A %s::secret specfied but it should not be when using requested method!", MYCONF);
+ errors++;
+ }
+ if (NEEDS_KEY(cfg_state.have_method) && !cfg_state.have_key)
+ {
+ config_error("No %s::key specfied as required by requested method!", MYCONF);
+ errors++;
+ }
+ if (!NEEDS_KEY(cfg_state.have_method) && cfg_state.have_key)
+ {
+ config_error("A %s::key specfied but it should not be when using requested method!", MYCONF);
+ errors++;
+ }
+ if (NEEDS_KEY(cfg_state.have_method) && cfg_state.have_key && cfg_state.key_filename)
+ {
+ char *keyerr;
+
+ keyerr = extjwt_test_key(cfg_state.key_filename, cfg_state.have_method);
+ if (keyerr)
+ {
+ config_error("Invalid key file specified for %s::key: %s", MYCONF, keyerr);
+ errors++;
+ }
+ }
+ }
+ safe_free(cfg_state.key_filename);
+ if (errors)
+ {
+ *errs = errors;
+ return -1;
+ }
+ /* setting defaults, FIXME this may behave incorrectly if there's another module failing POSTTEST */
+ if (!cfg_state.have_expire)
+ cfg.exp_delay = 30;
+ /* prepare service list to load new data */
+ extjwt_free_services(&jwt_services);
+ return 1;
+}
+
+int extjwt_configrun(ConfigFile *cf, ConfigEntry *ce, int type)
+{ /* actually use the new configuration data */
+ ConfigEntry *cep, *cep2;
+ struct jwt_service **ss = &jwt_services;
+ if (*ss)
+ ss = &((*ss)->next);
+
+ if (type != CONFIG_MAIN)
+ return 0;
+
+ if (!ce || strcmp(ce->name, MYCONF))
+ return 0;
+
+ for (cep = ce->items; cep; cep = cep->next)
+ {
+ if (!strcmp(cep->name, "method"))
+ {
+ cfg.method = EXTJWT_METHOD_from_string(cep->value);
+ continue;
+ }
+ if (!strcmp(cep->name, "expire-after"))
+ {
+ cfg.exp_delay = atoi(cep->value);
+ continue;
+ }
+ if (!strcmp(cep->name, "secret"))
+ {
+ cfg.secret = strdup(cep->value);
+ continue;
+ }
+ if (!strcmp(cep->name, "key"))
+ {
+ cfg.secret = extjwt_read_file_contents(cep->value, 0, NULL);
+ continue;
+ }
+ if (!strcmp(cep->name, "verify-url"))
+ {
+ cfg.vfy = strdup(cep->value);
+ continue;
+ }
+ if (!strcmp(cep->name, "service"))
+ { /* nested block */
+ *ss = safe_alloc(sizeof(struct jwt_service));
+ (*ss)->cfg = safe_alloc(sizeof(struct extjwt_config));
+ safe_strdup((*ss)->name, cep->value); /* copy the service name */
+ for (cep2 = cep->items; cep2; cep2 = cep2->next)
+ {
+ if (!strcmp(cep2->name, "method"))
+ {
+ (*ss)->cfg->method = EXTJWT_METHOD_from_string(cep2->value);
+ continue;
+ }
+ if (!strcmp(cep2->name, "expire-after"))
+ {
+ (*ss)->cfg->exp_delay = atoi(cep2->value);
+ continue;
+ }
+ if (!strcmp(cep2->name, "secret"))
+ {
+ (*ss)->cfg->secret = strdup(cep2->value);
+ continue;
+ }
+ if (!strcmp(cep2->name, "key"))
+ {
+ (*ss)->cfg->secret = extjwt_read_file_contents(cep2->value, 0, NULL);
+ continue;
+ }
+ if (!strcmp(cep2->name, "verify-url"))
+ {
+ (*ss)->cfg->vfy = strdup(cep2->value);
+ continue;
+ }
+ }
+ ss = &((*ss)->next);
+ }
+ }
+ return 1;
+}
+
+char *extjwt_read_file_contents(const char *file, int absolute, int *size)
+{
+ FILE *f = NULL;
+ int fsize;
+ char *filename = NULL;
+ char *buf = NULL;
+ do
+ {
+ safe_strdup(filename, file);
+ if (!absolute)
+ convert_to_absolute_path(&filename, CONFDIR);
+ f = fopen(filename, "rb");
+ if (!f)
+ break;
+ fseek(f, 0, SEEK_END);
+ fsize = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ buf = safe_alloc(fsize + 1);
+ fsize = fread(buf, 1, fsize, f);
+ buf[fsize] = '\0';
+ if (size)
+ *size = fsize;
+ fclose(f);
+ } while (0);
+ safe_free(filename);
+ if (!buf && size)
+ *size = 0;
+ return buf;
+}
+
+CMD_FUNC(cmd_extjwt)
+{
+ Channel *channel;
+ char *payload;
+ char *token, *full_token;
+ struct jwt_service *service = NULL;
+ struct extjwt_config *config;
+ int last = 0;
+ char message[MAX_TOKEN_CHUNK+1];
+ if (parc < 2 || BadPtr(parv[1]))
+ {
+ sendnumeric(client, ERR_NEEDMOREPARAMS, MSG_EXTJWT);
+ return;
+ }
+ if (parv[1][0] == '*' && parv[1][1] == '\0')
+ {
+ channel = NULL; /* not linked to a channel */
+ } else
+ {
+ channel = find_channel(parv[1]);
+ if (!channel)
+ {
+ sendnumeric(client, ERR_NOSUCHNICK, parv[1]);
+ return;
+ }
+ }
+ if (parc > 2 && !BadPtr(parv[2]))
+ {
+ service = find_jwt_service(jwt_services, parv[2]);
+ if (!service)
+ {
+ sendto_one(client, NULL, ":%s FAIL %s NO_SUCH_SERVICE :No such service", me.name, MSG_EXTJWT);
+ return;
+ }
+ }
+ if (service){
+ config = service->cfg; /* service config */
+ } else {
+ config = &cfg; /* default config */
+ }
+ if (!(payload = extjwt_make_payload(client, channel, config)) || !(full_token = extjwt_generate_token(payload, config)))
+ {
+ sendto_one(client, NULL, ":%s FAIL %s UNKNOWN_ERROR :Failed to generate token", me.name, MSG_EXTJWT);
+ return;
+ }
+ safe_free(payload);
+ token = full_token;
+ do
+ {
+ if (strlen(token) <= MAX_TOKEN_CHUNK)
+ { /* the remaining data (or whole token) will fit a single irc message */
+ last = 1;
+ strcpy(message, token);
+ } else
+ { /* send a chunk and shift buffer */
+ strlcpy(message, token, MAX_TOKEN_CHUNK+1);
+ token += MAX_TOKEN_CHUNK;
+ }
+ sendto_one(client, NULL, extjwt_message_pattern, me.name, parv[1], "*", last?"":"* ", message);
+ } while (!last);
+ safe_free(full_token);
+}
+
+char *extjwt_make_payload(Client *client, Channel *channel, struct extjwt_config *config)
+{
+ Membership *lp;
+ json_t *payload = NULL;
+ json_t *modes = NULL;
+ json_t *umodes = NULL;
+ char *modestring;
+ char singlemode[2] = { '\0' };
+ char *result;
+
+ if (!IsUser(client))
+ return NULL;
+
+ payload = json_object();
+ modes = json_array();
+ umodes = json_array();
+
+ json_object_set_new(payload, "exp", json_integer(TStime()+config->exp_delay));
+ json_object_set_new(payload, "iss", json_string_unreal(me.name));
+ json_object_set_new(payload, "sub", json_string_unreal(client->name));
+ json_object_set_new(payload, "account", json_string_unreal(IsLoggedIn(client)?client->user->account:""));
+
+ if (config->vfy) /* also add the URL */
+ json_object_set_new(payload, "vfy", json_string_unreal(config->vfy));
+
+ if (IsOper(client)) /* add "o" ircop flag */
+ json_array_append_new(umodes, json_string("o"));
+ json_object_set_new(payload, "umodes", umodes);
+
+ if (channel)
+ { /* fill in channel information and user flags */
+ lp = find_membership_link(client->user->channel, channel);
+ if (lp)
+ {
+ modestring = lp->member_modes;
+ while (*modestring)
+ {
+ singlemode[0] = *modestring;
+ json_array_append_new(modes, json_string(singlemode));
+ modestring++;
+ }
+ }
+ json_object_set_new(payload, "channel", json_string_unreal(channel->name));
+ json_object_set_new(payload, "joined", json_integer(lp?1:0));
+ json_object_set_new(payload, "cmodes", modes);
+ }
+ result = json_dumps(payload, JSON_COMPACT);
+ json_decref(modes);
+ json_decref(umodes);
+ json_decref(payload);
+ return result;
+}
+
+void b64url(char *b64)
+{ /* convert base64 to base64-url */
+ while (*b64)
+ {
+ if (*b64 == '+')
+ *b64 = '-';
+ if (*b64 == '/')
+ *b64 = '_';
+ if (*b64 == '=')
+ {
+ *b64 = '\0';
+ return;
+ }
+ b64++;
+ }
+}
+
+unsigned char *extjwt_hash(int method, const void *key, int keylen, const unsigned char *data, int datalen, unsigned int* resultlen)
+{
+ switch(method)
+ {
+ case EXTJWT_METHOD_HS256: case EXTJWT_METHOD_HS384: case EXTJWT_METHOD_HS512:
+ return extjwt_hmac_extjwt_hash(method, key, keylen, data, datalen, resultlen);
+ case EXTJWT_METHOD_RS256: case EXTJWT_METHOD_RS384: case EXTJWT_METHOD_RS512: case EXTJWT_METHOD_ES256: case EXTJWT_METHOD_ES384: case EXTJWT_METHOD_ES512:
+ return extjwt_sha_pem_extjwt_hash(method, key, keylen, data, datalen, resultlen);
+ }
+ return NULL;
+}
+
+unsigned char* extjwt_sha_pem_extjwt_hash(int method, const void *key, int keylen, const unsigned char *data, int datalen, unsigned int* resultlen)
+{
+ EVP_MD_CTX *mdctx = NULL;
+ ECDSA_SIG *ec_sig = NULL;
+ const BIGNUM *ec_sig_r = NULL;
+ const BIGNUM *ec_sig_s = NULL;
+ BIO *bufkey = NULL;
+ const EVP_MD *alg;
+ int type;
+ EVP_PKEY *pkey = NULL;
+ int pkey_type;
+ unsigned char *sig = NULL;
+ int ret = 0;
+ size_t slen;
+ char *retval = NULL;
+ char *output = NULL;
+ char *sig_ptr;
+
+ do
+ {
+ switch (method)
+ {
+ case EXTJWT_METHOD_RS256:
+ alg = EVP_sha256();
+ type = EVP_PKEY_RSA;
+ break;
+ case EXTJWT_METHOD_RS384:
+ alg = EVP_sha384();
+ type = EVP_PKEY_RSA;
+ break;
+ case EXTJWT_METHOD_RS512:
+ alg = EVP_sha512();
+ type = EVP_PKEY_RSA;
+ break;
+ case EXTJWT_METHOD_ES256:
+ alg = EVP_sha256();
+ type = EVP_PKEY_EC;
+ break;
+ case EXTJWT_METHOD_ES384:
+ alg = EVP_sha384();
+ type = EVP_PKEY_EC;
+ break;
+ case EXTJWT_METHOD_ES512:
+ alg = EVP_sha512();
+ type = EVP_PKEY_EC;
+ break;
+ default:
+ return NULL;
+ }
+
+#if (OPENSSL_VERSION_NUMBER < 0x10100003L) /* https://github.com/openssl/openssl/commit/8ab31975bacb9c907261088937d3aa4102e3af84 */
+ if (!(bufkey = BIO_new_mem_buf((void *)key, keylen)))
+ break; /* out of memory */
+#else
+ if (!(bufkey = BIO_new_mem_buf(key, keylen)))
+ break; /* out of memory */
+#endif
+ if (!(pkey = PEM_read_bio_PrivateKey(bufkey, NULL, NULL, NULL)))
+ break; /* invalid key? */
+ pkey_type = EVP_PKEY_id(pkey);
+ if (type != pkey_type)
+ break; /* invalid key type */
+ if (!(mdctx = EVP_MD_CTX_create()))
+ break; /* out of memory */
+ if (EVP_DigestSignInit(mdctx, NULL, alg, NULL, pkey) != 1)
+ break; /* initialize error */
+ if (EVP_DigestSignUpdate(mdctx, data, datalen) != 1)
+ break; /* signing error */
+ if (EVP_DigestSignFinal(mdctx, NULL, &slen) != 1) /* get required buffer length */
+ break;
+ sig = safe_alloc(slen);
+ if (EVP_DigestSignFinal(mdctx, sig, &slen) != 1)
+ break;
+ if (pkey_type != EVP_PKEY_EC)
+ {
+ *resultlen = slen;
+ output = safe_alloc(slen);
+ memcpy(output, sig, slen);
+ retval = output;
+ } else
+ {
+ unsigned int degree, bn_len, r_len, s_len, buf_len;
+ unsigned char *raw_buf = NULL;
+ EC_KEY *ec_key;
+ if (!(ec_key = EVP_PKEY_get1_EC_KEY(pkey)))
+ break; /* out of memory */
+ degree = EC_GROUP_get_degree(EC_KEY_get0_group(ec_key));
+ EC_KEY_free(ec_key);
+ sig_ptr = sig;
+ if (!(ec_sig = d2i_ECDSA_SIG(NULL, (const unsigned char **)&sig_ptr, slen)))
+ break; /* out of memory */
+ ECDSA_SIG_get0(ec_sig, &ec_sig_r, &ec_sig_s);
+ r_len = BN_num_bytes(ec_sig_r);
+ s_len = BN_num_bytes(ec_sig_s);
+ bn_len = (degree+7)/8;
+ if (r_len>bn_len || s_len > bn_len)
+ break;
+ buf_len = bn_len*2;
+ raw_buf = safe_alloc(buf_len);
+ BN_bn2bin(ec_sig_r, raw_buf+bn_len-r_len);
+ BN_bn2bin(ec_sig_s, raw_buf+buf_len-s_len);
+ output = safe_alloc(buf_len);
+ *resultlen = buf_len;
+ memcpy(output, raw_buf, buf_len);
+ retval = output;
+ safe_free(raw_buf);
+ }
+ } while (0);
+
+ if (bufkey)
+ BIO_free(bufkey);
+ if (pkey)
+ EVP_PKEY_free(pkey);
+ if (mdctx)
+ EVP_MD_CTX_destroy(mdctx);
+ if (ec_sig)
+ ECDSA_SIG_free(ec_sig);
+ safe_free(sig);
+ return retval;
+}
+
+unsigned char* extjwt_hmac_extjwt_hash(int method, const void *key, int keylen, const unsigned char *data, int datalen, unsigned int* resultlen)
+{
+ const EVP_MD* typ;
+ char *hmac = safe_alloc(EVP_MAX_MD_SIZE);
+ switch (method)
+ {
+ default:
+ case EXTJWT_METHOD_HS256:
+ typ = EVP_sha256();
+ break;
+ case EXTJWT_METHOD_HS384:
+ typ = EVP_sha384();
+ break;
+ case EXTJWT_METHOD_HS512:
+ typ = EVP_sha512();
+ break;
+ }
+ if (HMAC(typ, key, keylen, data, datalen, hmac, resultlen))
+ { /* openssl call */
+ return hmac;
+ } else {
+ safe_free(hmac);
+ return NULL;
+ }
+}
+
+char *extjwt_gen_header(int method)
+{ /* returns header json */
+ json_t *header = NULL;
+ json_t *alg;
+ char *result;
+
+ header = json_object();
+ json_object_set_new(header, "typ", json_string("JWT"));
+
+ switch (method)
+ {
+ default:
+ case EXTJWT_METHOD_HS256:
+ alg = json_string("HS256");
+ break;
+ case EXTJWT_METHOD_HS384:
+ alg = json_string("HS384");
+ break;
+ case EXTJWT_METHOD_HS512:
+ alg = json_string("HS512");
+ break;
+ case EXTJWT_METHOD_RS256:
+ alg = json_string("RS256");
+ break;
+ case EXTJWT_METHOD_RS384:
+ alg = json_string("RS384");
+ break;
+ case EXTJWT_METHOD_RS512:
+ alg = json_string("RS512");
+ break;
+ case EXTJWT_METHOD_ES256:
+ alg = json_string("ES256");
+ break;
+ case EXTJWT_METHOD_ES384:
+ alg = json_string("ES384");
+ break;
+ case EXTJWT_METHOD_ES512:
+ alg = json_string("ES512");
+ break;
+ case EXTJWT_METHOD_NONE:
+ alg = json_string("none");
+ break;
+ }
+ json_object_set_new(header, "alg", alg);
+ result = json_dumps(header, JSON_COMPACT);
+ json_decref(header);
+ return result;
+}
+
+char *extjwt_generate_token(const char *payload, struct extjwt_config *config)
+{
+ char *header = extjwt_gen_header(config->method);
+ size_t b64header_size = strlen(header)*4/3 + 8; // base64 has 4/3 overhead
+ size_t b64payload_size = strlen(payload)*4/3 + 8;
+ size_t b64sig_size = 4096*4/3 + 8;
+ size_t b64data_size = b64header_size + b64payload_size + b64sig_size + 4;
+ char *b64header = safe_alloc(b64header_size);
+ char *b64payload = safe_alloc(b64payload_size);
+ char *b64sig = safe_alloc(b64sig_size);
+ char *b64data = safe_alloc(b64data_size);
+ unsigned int extjwt_hashsize;
+ char *extjwt_hash_val = NULL;
+ char *retval = NULL;
+ b64_encode(header, strlen(header), b64header, b64header_size);
+ b64_encode(payload, strlen(payload), b64payload, b64payload_size);
+ b64url(b64header);
+ b64url(b64payload);
+ snprintf(b64data, b64data_size, "%s.%s", b64header, b64payload); // generate first part of the token
+ if (config->method != EXTJWT_METHOD_NONE)
+ {
+ extjwt_hash_val = extjwt_hash(config->method, config->secret, strlen(config->secret), b64data, strlen(b64data), &extjwt_hashsize); // calculate the signature extjwt_hash
+ if (extjwt_hash_val)
+ {
+ b64_encode(extjwt_hash_val, extjwt_hashsize, b64sig, b64sig_size);
+ b64url(b64sig);
+ strlcat(b64data, ".", b64data_size); // append signature extjwt_hash to token
+ strlcat(b64data, b64sig, b64data_size);
+ retval = b64data;
+ }
+ } else
+ {
+ retval = b64data;
+ }
+ safe_free(header);
+ safe_free(b64header);
+ safe_free(b64payload);
+ safe_free(b64sig);
+ safe_free(extjwt_hash_val);
+
+ if (retval != b64data)
+ safe_free(b64data);
+
+ return retval;
+}
diff --git a/src/modules/geoip_base.c b/src/modules/geoip_base.c
new file mode 100644
index 0000000..3244e1f
--- /dev/null
+++ b/src/modules/geoip_base.c
@@ -0,0 +1,326 @@
+/*
+ * GEOIP Base module, needed for all geoip functions
+ * as this stores the geo information in ModData.
+ * (C) Copyright 2021-.. Syzop and The UnrealIRCd Team
+ * License: GPLv2
+ */
+
+#include "unrealircd.h"
+
+ModuleHeader MOD_HEADER
+ = {
+ "geoip_base",
+ "5.0",
+ "Base module for geoip",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+ };
+
+struct geoip_base_config_s {
+ int check_on_load;
+};
+
+/* Forward declarations */
+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_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);
+int geoip_base_configrun(ConfigFile *cf, ConfigEntry *ce, int type);
+EVENT(geoip_base_set_existing_users_evt);
+CMD_FUNC(cmd_geoip);
+
+ModDataInfo *geoip_md; /* Module Data structure which we acquire */
+struct geoip_base_config_s geoip_base_config;
+
+/* We can use GEOIPDATA() and GEOIPDATARAW() for fast access.
+ * People wanting to get this information from outside this module
+ * should use geoip_client(client) !
+ */
+
+#define GEOIPDATARAW(x) (moddata_client((x), geoip_md).ptr)
+#define GEOIPDATA(x) ((GeoIPResult *)moddata_client((x), geoip_md).ptr)
+
+int geoip_base_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
+{
+ ConfigEntry *cep;
+ int errors = 0;
+ int i;
+
+ if (type != CONFIG_SET)
+ return 0;
+
+ if (!ce || !ce->name)
+ return 0;
+
+ if (strcmp(ce->name, "geoip"))
+ return 0;
+
+ for (cep = ce->items; cep; cep = cep->next)
+ {
+ if (!strcmp(cep->name, "check-on-load"))
+ {
+ CheckNull(cep);
+ continue;
+ }
+ config_warn("%s:%i: unknown item geoip::%s", cep->file->filename, cep->line_number, cep->name);
+ }
+
+ *errs = errors;
+ return errors ? -1 : 1;
+}
+
+int geoip_base_configrun(ConfigFile *cf, ConfigEntry *ce, int type)
+{
+ ConfigEntry *cep;
+
+ if (type != CONFIG_SET)
+ return 0;
+
+ if (!ce || !ce->name)
+ return 0;
+
+ if (strcmp(ce->name, "geoip"))
+ return 0;
+
+ for (cep = ce->items; cep; cep = cep->next)
+ {
+ if (!strcmp(cep->name, "check-on-load"))
+ geoip_base_config.check_on_load = config_checkval(cep->value, CFG_YESNO);
+ }
+ return 1;
+}
+
+MOD_TEST()
+{
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, geoip_base_configtest);
+ return MOD_SUCCESS;
+}
+
+MOD_INIT()
+{
+ ModDataInfo mreq;
+
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ memset(&mreq, 0, sizeof(mreq));
+ mreq.name = "geoip";
+ mreq.free = geoip_base_free;
+ mreq.serialize = geoip_base_serialize;
+ mreq.unserialize = geoip_base_unserialize;
+ mreq.sync = MODDATA_SYNC_EARLY;
+ mreq.type = MODDATATYPE_CLIENT;
+ geoip_md = ModDataAdd(modinfo->handle, mreq);
+ if (!geoip_md)
+ abort();
+
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, geoip_base_configrun);
+ HookAdd(modinfo->handle, HOOKTYPE_HANDSHAKE, 0, geoip_base_handshake);
+ 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);
+
+ /* set defaults */
+ geoip_base_config.check_on_load = 1;
+
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ /* add info for all users upon module loading if enabled, but delay it a bit for data provider module to load */
+ if (geoip_base_config.check_on_load)
+ {
+ EventAdd(modinfo->handle, "geoip_base_set_existing_users", geoip_base_set_existing_users_evt, NULL, 1000, 1);
+ }
+ return MOD_SUCCESS;
+}
+
+
+MOD_UNLOAD()
+{
+ return MOD_SUCCESS;
+}
+
+int geoip_base_handshake(Client *client)
+{
+ if (!client->ip)
+ return 0;
+ GeoIPResult *res = geoip_lookup(client->ip);
+
+ if (!res)
+ return 0;
+
+ if (GEOIPDATA(client))
+ {
+ free_geoip_result(GEOIPDATA(client));
+ GEOIPDATARAW(client) = NULL;
+ }
+ GEOIPDATARAW(client) = res;
+ return 0;
+}
+
+void geoip_base_free(ModData *m)
+{
+ if (m->ptr)
+ {
+ free_geoip_result((GeoIPResult *)m->ptr);
+ m->ptr = NULL;
+ }
+}
+
+const char *geoip_base_serialize(ModData *m)
+{
+ static char buf[512];
+ GeoIPResult *geo;
+
+ if (!m->ptr)
+ return NULL;
+
+ geo = m->ptr;
+ snprintf(buf, sizeof(buf), "cc=%s|cd=%s",
+ geo->country_code,
+ geo->country_name);
+
+ return buf;
+}
+
+void geoip_base_unserialize(const char *str, ModData *m)
+{
+ char buf[512], *p=NULL, *varname, *value;
+ char *country_name = NULL;
+ char *country_code = NULL;
+ GeoIPResult *res;
+
+ if (m->ptr == NULL)
+ {
+ free_geoip_result((GeoIPResult *)m->ptr);
+ m->ptr = NULL;
+ }
+ if (str == NULL)
+ return;
+
+ strlcpy(buf, str, sizeof(buf));
+ for (varname = strtoken(&p, buf, "|"); varname; varname = strtoken(&p, NULL, "|"))
+ {
+ value = strchr(varname, '=');
+ if (!value)
+ continue;
+ *value++ = '\0';
+ if (!strcmp(varname, "cc"))
+ country_code = value;
+ else if (!strcmp(varname, "cd"))
+ country_name = value;
+ }
+
+ if (!country_code || !country_name)
+ return; /* does not meet minimum criteria */
+
+ res = safe_alloc(sizeof(GeoIPResult));
+ safe_strdup(res->country_name, country_name);
+ safe_strdup(res->country_code, country_code);
+ m->ptr = res;
+}
+
+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);
+ }
+}
+
+int geoip_connect_extinfo(Client *client, NameValuePrioList **list)
+{
+ GeoIPResult *geo = GEOIPDATA(client);
+ if (geo)
+ add_nvplist(list, 0, "country", geo->country_code);
+ return 0;
+}
+
+int geoip_base_whois(Client *client, Client *target, NameValuePrioList **list)
+{
+ GeoIPResult *geo;
+ char buf[512];
+ int policy = whois_get_policy(client, target, "geo");
+
+ if (policy == WHOIS_CONFIG_DETAILS_NONE)
+ return 0;
+
+ geo = GEOIPDATA(target);
+ if (!geo)
+ return 0;
+
+ // we only have country atm, but if we add city then city goes in 'full' and
+ // country goes in 'limited'
+ // if policy == WHOIS_CONFIG_DETAILS_LIMITED ...
+ add_nvplist_numeric_fmt(list, 0, "geo", client, RPL_WHOISCOUNTRY,
+ "%s %s :is connecting from %s",
+ target->name,
+ geo->country_code,
+ geo->country_name);
+ return 0;
+}
+
+CMD_FUNC(cmd_geoip)
+{
+ const char *ip = NULL;
+ Client *target;
+ GeoIPResult *res;
+
+ if (!IsOper(client))
+ {
+ sendnumeric(client, ERR_NOPRIVILEGES);
+ return;
+ }
+
+ if ((parc < 2) || BadPtr(parv[1]))
+ {
+ /* Maybe some report */
+ return;
+ }
+
+ if (strchr(parv[1], '.') || strchr(parv[1], ':'))
+ {
+ ip = parv[1];
+ } else {
+ target = find_user(parv[1], NULL);
+ if (!target)
+ {
+ sendnumeric(client, ERR_NOSUCHNICK, parv[1]);
+ return;
+ }
+ ip = target->ip;
+ if (!ip)
+ {
+ sendnotice(client, "User %s has no known IP address", client->name); // (eg: services bot)
+ return;
+ }
+ }
+
+ res = geoip_lookup(ip);
+
+ sendnotice(client, "*** GEOIP information for IP %s ***", ip);
+ if (!res)
+ {
+ sendnotice(client, "- No information available");
+ return;
+ } else {
+ if (res->country_code)
+ sendnotice(client, "- Country code: %s", res->country_code);
+ if (res->country_name)
+ sendnotice(client, "- Country name: %s", res->country_name);
+ }
+
+ free_geoip_result(res);
+
+ sendnotice(client, "*** End of information ***");
+}
diff --git a/src/modules/geoip_classic.c b/src/modules/geoip_classic.c
new file mode 100644
index 0000000..c7299fc
--- /dev/null
+++ b/src/modules/geoip_classic.c
@@ -0,0 +1,297 @@
+/* GEOIP Classic module
+ * (C) Copyright 2021 Bram Matthys and the UnrealIRCd team
+ * License: GPLv2
+ */
+
+#include "unrealircd.h"
+#include
+
+ModuleHeader MOD_HEADER
+ = {
+ "geoip_classic",
+ "5.0",
+ "GEOIP using classic databases",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+ };
+
+struct geoip_classic_config_s {
+ char *v4_db_file;
+ char *v6_db_file;
+/* for config reading only */
+ int have_config;
+ int have_ipv4_database;
+ int have_ipv6_database;
+};
+
+/* Variables */
+
+struct geoip_classic_config_s geoip_classic_config;
+GeoIP *gi4 = NULL;
+GeoIP *gi6 = NULL;
+
+/* Forward declarations */
+int geoip_classic_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs);
+int geoip_classic_configposttest(int *errs);
+int geoip_classic_configrun(ConfigFile *cf, ConfigEntry *ce, int type);
+void geoip_classic_free(void);
+GeoIPResult *geoip_lookup_classic(char *ip);
+
+int geoip_classic_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
+{
+ ConfigEntry *cep;
+ int errors = 0;
+ int i;
+
+ if (type != CONFIG_SET)
+ return 0;
+
+ if (!ce || !ce->name)
+ return 0;
+
+ if (strcmp(ce->name, "geoip-classic"))
+ return 0;
+
+ geoip_classic_config.have_config = 1;
+
+ for (cep = ce->items; cep; cep = cep->next)
+ {
+ if (!strcmp(cep->name, "ipv4-database"))
+ {
+ if (geoip_classic_config.have_ipv4_database)
+ {
+ config_error("%s:%i: duplicate item set::geoip-classic::%s", cep->file->filename, cep->line_number, cep->name);
+ continue;
+ }
+ if (!is_file_readable(cep->value, PERMDATADIR))
+ {
+ config_error("%s:%i: set::geoip-classic::%s: cannot open file \"%s/%s\" for reading (%s)", cep->file->filename, cep->line_number, cep->name, PERMDATADIR, cep->value, strerror(errno));
+ errors++;
+ continue;
+ }
+ geoip_classic_config.have_ipv4_database = 1;
+ continue;
+ }
+ if (!strcmp(cep->name, "ipv6-database"))
+ {
+ if (geoip_classic_config.have_ipv6_database)
+ {
+ config_error("%s:%i: duplicate item set::geoip-classic::%s", cep->file->filename, cep->line_number, cep->name);
+ continue;
+ }
+ if (!is_file_readable(cep->value, PERMDATADIR))
+ {
+ config_error("%s:%i: set::geoip-classic::%s: cannot open file \"%s/%s\" for reading (%s)", cep->file->filename, cep->line_number, cep->name, PERMDATADIR, cep->value, strerror(errno));
+ errors++;
+ continue;
+ }
+ geoip_classic_config.have_ipv6_database = 1;
+ continue;
+ }
+ config_warn("%s:%i: unknown item set::geoip-classic::%s", cep->file->filename, cep->line_number, cep->name);
+ }
+
+ *errs = errors;
+ return errors ? -1 : 1;
+}
+
+int geoip_classic_configposttest(int *errs)
+{
+ int errors = 0;
+ if (geoip_classic_config.have_config)
+ {
+ if (!geoip_classic_config.have_ipv4_database && !geoip_classic_config.have_ipv6_database)
+ {
+ config_error("geoip_classic: no database files specified! Remove set::geoip-classic to use defaults");
+ errors++;
+ }
+ } else
+ {
+ safe_strdup(geoip_classic_config.v4_db_file, "GeoIP.dat");
+ safe_strdup(geoip_classic_config.v6_db_file, "GeoIPv6.dat");
+
+ if (is_file_readable(geoip_classic_config.v4_db_file, PERMDATADIR))
+ {
+ geoip_classic_config.have_ipv4_database = 1;
+ } else
+ {
+ config_warn("[geoip_classic] cannot open IPv4 database file \"%s/%s\" for reading (%s)", PERMDATADIR, geoip_classic_config.v4_db_file, strerror(errno));
+ safe_free(geoip_classic_config.v4_db_file);
+ }
+ if (is_file_readable(geoip_classic_config.v6_db_file, PERMDATADIR))
+ {
+ geoip_classic_config.have_ipv6_database = 1;
+ } else
+ {
+ config_warn("[geoip_classic] cannot open IPv6 database file \"%s/%s\" for reading (%s)", PERMDATADIR, geoip_classic_config.v6_db_file, strerror(errno));
+ safe_free(geoip_classic_config.v6_db_file);
+ }
+ if (!geoip_classic_config.have_ipv4_database && !geoip_classic_config.have_ipv6_database)
+ {
+ config_error("[geoip_classic] couldn't read any database! Either put these in %s location "
+ "or specify another in set::geoip-classic config block", PERMDATADIR);
+ errors++;
+ }
+ }
+
+ *errs = errors;
+ return errors ? -1 : 1;
+}
+
+int geoip_classic_configrun(ConfigFile *cf, ConfigEntry *ce, int type)
+{
+ ConfigEntry *cep;
+
+ if (type != CONFIG_SET)
+ return 0;
+
+ if (!ce || !ce->name)
+ return 0;
+
+ if (strcmp(ce->name, "geoip-classic"))
+ return 0;
+
+ for (cep = ce->items; cep; cep = cep->next)
+ {
+ if (!strcmp(cep->name, "ipv4-database") && geoip_classic_config.have_ipv4_database)
+ safe_strdup(geoip_classic_config.v4_db_file, cep->value);
+ if (!strcmp(cep->name, "ipv6-database") && geoip_classic_config.have_ipv6_database)
+ safe_strdup(geoip_classic_config.v6_db_file, cep->value);
+ }
+ return 1;
+}
+
+MOD_TEST()
+{
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+ if (!CallbackAddPVoid(modinfo->handle, CALLBACKTYPE_GEOIP_LOOKUP, TO_PVOIDFUNC(geoip_lookup_classic)))
+ {
+ unreal_log(ULOG_ERROR, "geoip_classic", "GEOIP_ADD_CALLBACK_FAILED", NULL,
+ "geoip_classic: Could not install GEOIP_LOOKUP callback. "
+ "Most likely another geoip module is already loaded. "
+ "You can only load one!");
+ return MOD_FAILED;
+ }
+
+ geoip_classic_config.have_config = 0;
+ geoip_classic_config.have_ipv4_database = 0;
+ geoip_classic_config.have_ipv6_database = 0;
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, geoip_classic_configtest);
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGPOSTTEST, 0, geoip_classic_configposttest);
+ return MOD_SUCCESS;
+}
+
+MOD_INIT()
+{
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+ geoip_classic_free();
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, geoip_classic_configrun);
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ int found_good_file = 0;
+
+ if (geoip_classic_config.v4_db_file)
+ {
+ convert_to_absolute_path(&geoip_classic_config.v4_db_file, PERMDATADIR);
+ gi4 = GeoIP_open(geoip_classic_config.v4_db_file, GEOIP_STANDARD | GEOIP_CHECK_CACHE | GEOIP_SILENCE);
+ if (gi4)
+ {
+ found_good_file = 1;
+ } else
+ {
+ int save_err = errno;
+ unreal_log(ULOG_WARNING, "geoip_classic", "GEOIP_CANNOT_OPEN_DB", NULL,
+ "[IPv4] Could not open '$filename': $system_error",
+ log_data_string("filename", geoip_classic_config.v4_db_file),
+ log_data_string("system_error", strerror(save_err)));
+ }
+ }
+ if (geoip_classic_config.v6_db_file)
+ {
+ convert_to_absolute_path(&geoip_classic_config.v6_db_file, PERMDATADIR);
+ gi6 = GeoIP_open(geoip_classic_config.v6_db_file, GEOIP_STANDARD | GEOIP_CHECK_CACHE | GEOIP_SILENCE);
+ if (gi6)
+ {
+ found_good_file = 1;
+ } else
+ {
+ int save_err = errno;
+ unreal_log(ULOG_WARNING, "geoip_classic", "GEOIP_CANNOT_OPEN_DB", NULL,
+ "[IPv6] Could not open '$filename': $system_error",
+ log_data_string("filename", geoip_classic_config.v6_db_file),
+ log_data_string("system_error", strerror(save_err)));
+ }
+ convert_to_absolute_path(&geoip_classic_config.v6_db_file, PERMDATADIR);
+ }
+
+ if (!found_good_file)
+ {
+ unreal_log(ULOG_ERROR, "geoip_classic", "GEOIP_CANNOT_OPEN_DB", NULL,
+ "could not open any database!");
+ return MOD_FAILED;
+ }
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ geoip_classic_free();
+ return MOD_SUCCESS;
+}
+
+void geoip_classic_free(void)
+{
+ if (gi4)
+ GeoIP_delete(gi4);
+ if (gi6)
+ GeoIP_delete(gi6);
+ gi4 = NULL;
+ gi6 = NULL;
+ safe_free(geoip_classic_config.v4_db_file);
+ safe_free(geoip_classic_config.v6_db_file);
+}
+
+GeoIPResult *geoip_lookup_classic(char *ip)
+{
+ static char buf[256];
+ const char *country_code, *country_name;
+ GeoIPLookup gl;
+ GeoIP *gi;
+ int geoid;
+ GeoIPResult *r;
+
+ if (!ip)
+ return NULL;
+
+ if (strchr(ip, ':'))
+ {
+ if (!gi6)
+ return NULL;
+ geoid = GeoIP_id_by_addr_v6_gl(gi6, ip, &gl);
+ gi = gi6;
+ } else
+ {
+ if (!gi4 || !strcmp(ip, "255.255.255.255"))
+ return NULL;
+ geoid = GeoIP_id_by_addr_gl(gi4, ip, &gl);
+ gi = gi4;
+ }
+
+ if (geoid == 0)
+ return NULL;
+
+ country_code = GeoIP_code_by_id(geoid);
+ country_name = GeoIP_country_name_by_id(gi, geoid);
+
+ if (!country_code || !country_name)
+ return NULL;
+
+ r = safe_alloc(sizeof(GeoIPResult));
+ safe_strdup(r->country_code, country_code);
+ safe_strdup(r->country_name, country_name);
+ return r;
+}
+
diff --git a/src/modules/geoip_csv.c b/src/modules/geoip_csv.c
new file mode 100644
index 0000000..19ec91e
--- /dev/null
+++ b/src/modules/geoip_csv.c
@@ -0,0 +1,838 @@
+/*
+ * IRC - Internet Relay Chat, src/modules/geoip_csv.c
+ * (C) 2021 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.
+ */
+
+#include "unrealircd.h"
+
+ModuleHeader MOD_HEADER
+ = {
+ "geoip_csv",
+ "5.0",
+ "GEOIP using csv data files",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+ };
+
+struct geoip_csv_config_s {
+ char *v4_db_file;
+ char *v6_db_file;
+ char *countries_db_file;
+/* for config reading only */
+ int have_config;
+ int have_ipv4_database;
+ int have_ipv6_database;
+ int have_countries;
+};
+
+struct geoip_csv_ip_range {
+ uint32_t addr;
+ uint32_t mask;
+ int geoid;
+ struct geoip_csv_ip_range *next;
+};
+
+struct geoip_csv_ip6_range {
+ uint16_t addr[8];
+ uint16_t mask[8];
+ int geoid;
+ struct geoip_csv_ip6_range *next;
+};
+
+struct geoip_csv_country {
+ char code[10];
+ char name[100];
+ char continent[25];
+ int id;
+ struct geoip_csv_country *next;
+};
+
+/* Variables */
+struct geoip_csv_config_s geoip_csv_config;
+struct geoip_csv_ip_range *geoip_csv_ip_range_list[256]; // we are keeping a separate list for each possible first octet to speed up searching
+struct geoip_csv_ip6_range *geoip_csv_ip6_range_list = NULL; // for ipv6 there would be too many separate lists so just use a single one
+struct geoip_csv_country *geoip_csv_country_list = NULL;
+
+/* Forward declarations */
+static void geoip_csv_free_ipv4(void);
+static void geoip_csv_free_ipv6(void);
+static void geoip_csv_free_ipv6(void);
+static void geoip_csv_free_countries(void);
+static void geoip_csv_free(void);
+static int geoip_csv_read_ipv4(char *file);
+static int geoip_csv_ip6_convert(char *ip, uint16_t out[8]);
+static int geoip_csv_read_ipv6(char *file);
+static int geoip_csv_read_countries(char *file);
+static struct geoip_csv_country *geoip_csv_get_country(int id);
+static int geoip_csv_get_v4_geoid(char *iip);
+static int geoip_csv_get_v6_geoid(char *iip);
+int geoip_csv_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs);
+int geoip_csv_configposttest(int *errs);
+int geoip_csv_configrun(ConfigFile *cf, ConfigEntry *ce, int type);
+void geoip_csv_free(void);
+GeoIPResult *geoip_lookup_csv(char *ip);
+
+int geoip_csv_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
+{
+ ConfigEntry *cep;
+ int errors = 0;
+ int i;
+
+ if (type != CONFIG_SET)
+ return 0;
+
+ if (!ce || !ce->name)
+ return 0;
+
+ if (strcmp(ce->name, "geoip-csv"))
+ return 0;
+
+ geoip_csv_config.have_config = 1;
+
+ for (cep = ce->items; cep; cep = cep->next)
+ {
+ if (!strcmp(cep->name, "ipv4-blocks-file"))
+ {
+ if (geoip_csv_config.have_ipv4_database)
+ {
+ config_error("%s:%i: duplicate item set::geoip-csv::%s", cep->file->filename, cep->line_number, cep->name);
+ continue;
+ }
+ if (!is_file_readable(cep->value, PERMDATADIR))
+ {
+ config_error("%s:%i: set::geoip-csv::%s: cannot open file \"%s/%s\" for reading (%s)", cep->file->filename, cep->line_number, cep->name, PERMDATADIR, cep->value, strerror(errno));
+ errors++;
+ continue;
+ }
+ geoip_csv_config.have_ipv4_database = 1;
+ continue;
+ }
+ if (!strcmp(cep->name, "ipv6-blocks-file"))
+ {
+ if (geoip_csv_config.have_ipv6_database)
+ {
+ config_error("%s:%i: duplicate item set::geoip-csv::%s", cep->file->filename, cep->line_number, cep->name);
+ continue;
+ }
+ if (!is_file_readable(cep->value, PERMDATADIR))
+ {
+ config_error("%s:%i: set::geoip-csv::%s: cannot open file \"%s/%s\" for reading (%s)", cep->file->filename, cep->line_number, cep->name, PERMDATADIR, cep->value, strerror(errno));
+ errors++;
+ continue;
+ }
+ geoip_csv_config.have_ipv6_database = 1;
+ continue;
+ }
+ if (!strcmp(cep->name, "countries-file"))
+ {
+ if (geoip_csv_config.have_countries)
+ {
+ config_error("%s:%i: duplicate item set::geoip-csv::%s", cep->file->filename, cep->line_number, cep->name);
+ continue;
+ }
+ if (!is_file_readable(cep->value, PERMDATADIR))
+ {
+ config_error("%s:%i: set::geoip-csv::%s: cannot open file \"%s/%s\" for reading (%s)", cep->file->filename, cep->line_number, cep->name, PERMDATADIR, cep->value, strerror(errno));
+ errors++;
+ continue;
+ }
+ geoip_csv_config.have_countries = 1;
+ continue;
+ }
+ config_warn("%s:%i: unknown item set::geoip-csv::%s", cep->file->filename, cep->line_number, cep->name);
+ }
+
+ *errs = errors;
+ return errors ? -1 : 1;
+}
+
+int geoip_csv_configposttest(int *errs)
+{
+ int errors = 0;
+ if (geoip_csv_config.have_config)
+ {
+ if (!geoip_csv_config.have_countries)
+ {
+ config_error("[geoip_csv] no countries file specified! Remove set::geoip-csv to use defaults");
+ errors++;
+ }
+ if (!geoip_csv_config.have_ipv4_database && !geoip_csv_config.have_ipv6_database)
+ {
+ config_error("[geoip_csv] no database files specified! Remove set::geoip-csv to use defaults");
+ errors++;
+ }
+ } else
+ {
+ safe_strdup(geoip_csv_config.v4_db_file, "GeoLite2-Country-Blocks-IPv4.csv");
+ safe_strdup(geoip_csv_config.v6_db_file, "GeoLite2-Country-Blocks-IPv6.csv");
+ safe_strdup(geoip_csv_config.countries_db_file, "GeoLite2-Country-Locations-en.csv");
+
+ if (is_file_readable(geoip_csv_config.v4_db_file, PERMDATADIR))
+ {
+ geoip_csv_config.have_ipv4_database = 1;
+ } else
+ {
+ config_warn("[geoip_csv] cannot open IPv4 blocks file \"%s/%s\" for reading (%s)", PERMDATADIR, geoip_csv_config.v4_db_file, strerror(errno));
+ safe_free(geoip_csv_config.v4_db_file);
+ }
+ if (is_file_readable(geoip_csv_config.v6_db_file, PERMDATADIR))
+ {
+ geoip_csv_config.have_ipv6_database = 1;
+ } else
+ {
+ config_warn("[geoip_csv] cannot open IPv6 blocks file \"%s/%s\" for reading (%s)", PERMDATADIR, geoip_csv_config.v6_db_file, strerror(errno));
+ safe_free(geoip_csv_config.v6_db_file);
+ }
+ if (!is_file_readable(geoip_csv_config.countries_db_file, PERMDATADIR))
+ {
+ config_error("[geoip_csv] cannot open countries file \"%s/%s\" for reading (%s)", PERMDATADIR, geoip_csv_config.countries_db_file, strerror(errno));
+ safe_free(geoip_csv_config.countries_db_file);
+ errors++;
+ }
+ if (!geoip_csv_config.have_ipv4_database && !geoip_csv_config.have_ipv6_database)
+ {
+ config_error("[geoip_csv] couldn't read any blocks file! Either put these in %s location "
+ "or specify another in set::geoip-csv config block", PERMDATADIR);
+ errors++;
+ }
+ }
+
+ *errs = errors;
+ return errors ? -1 : 1;
+}
+
+int geoip_csv_configrun(ConfigFile *cf, ConfigEntry *ce, int type)
+{
+ ConfigEntry *cep;
+
+ if (type != CONFIG_SET)
+ return 0;
+
+ if (!ce || !ce->name)
+ return 0;
+
+ if (strcmp(ce->name, "geoip-csv"))
+ return 0;
+
+ for (cep = ce->items; cep; cep = cep->next)
+ {
+ if (!strcmp(cep->name, "ipv4-blocks-file") && geoip_csv_config.have_ipv4_database)
+ safe_strdup(geoip_csv_config.v4_db_file, cep->value);
+ if (!strcmp(cep->name, "ipv6-blocks-file") && geoip_csv_config.have_ipv6_database)
+ safe_strdup(geoip_csv_config.v6_db_file, cep->value);
+ if (!strcmp(cep->name, "countries-file"))
+ safe_strdup(geoip_csv_config.countries_db_file, cep->value);
+ }
+ return 1;
+}
+
+MOD_TEST()
+{
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+ if (!CallbackAddPVoid(modinfo->handle, CALLBACKTYPE_GEOIP_LOOKUP, TO_PVOIDFUNC(geoip_lookup_csv)))
+ {
+ unreal_log(ULOG_ERROR, "geoip_csv", "GEOIP_ADD_CALLBACK_FAILED", NULL,
+ "geoip_csv: Could not install GEOIP_LOOKUP callback. "
+ "Most likely another geoip module is already loaded. "
+ "You can only load one!");
+ return MOD_FAILED;
+ }
+
+ geoip_csv_config.have_config = 0;
+ geoip_csv_config.have_ipv4_database = 0;
+ geoip_csv_config.have_ipv6_database = 0;
+ geoip_csv_config.have_countries = 0;
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, geoip_csv_configtest);
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGPOSTTEST, 0, geoip_csv_configposttest);
+ return MOD_SUCCESS;
+}
+
+MOD_INIT()
+{
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+ geoip_csv_free();
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, geoip_csv_configrun);
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ int found_good_file = 0;
+
+ if (geoip_csv_config.v4_db_file)
+ {
+ convert_to_absolute_path(&geoip_csv_config.v4_db_file, PERMDATADIR);
+ if (!geoip_csv_read_ipv4(geoip_csv_config.v4_db_file))
+ {
+ found_good_file = 1;
+ }
+ }
+ if (geoip_csv_config.v6_db_file)
+ {
+ convert_to_absolute_path(&geoip_csv_config.v6_db_file, PERMDATADIR);
+ if (!geoip_csv_read_ipv6(geoip_csv_config.v6_db_file))
+ {
+ found_good_file = 1;
+ }
+ }
+ if (!geoip_csv_config.countries_db_file)
+ {
+ unreal_log(ULOG_DEBUG, "geoip_csv", "GEOIP_NO_COUNTRIES", NULL,
+ "[BUG] No countries file specified");
+ geoip_csv_free();
+ return MOD_FAILED;
+ }
+ convert_to_absolute_path(&geoip_csv_config.countries_db_file, PERMDATADIR);
+ if (geoip_csv_read_countries(geoip_csv_config.countries_db_file))
+ {
+ unreal_log(ULOG_ERROR, "geoip_csv", "GEOIP_CANNOT_OPEN_DB", NULL,
+ "could not open required countries file!");
+ geoip_csv_free();
+ return MOD_FAILED;
+ }
+
+ if (!found_good_file)
+ {
+ unreal_log(ULOG_ERROR, "geoip_csv", "GEOIP_CANNOT_OPEN_DB", NULL,
+ "could not open any database!");
+ geoip_csv_free();
+ return MOD_FAILED;
+ }
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ geoip_csv_free();
+ return MOD_SUCCESS;
+}
+
+static void geoip_csv_free_ipv4(void)
+{
+ struct geoip_csv_ip_range *ptr, *oldptr;
+ int i;
+ for (i=0; i<256; i++)
+ {
+ ptr = geoip_csv_ip_range_list[i];
+ geoip_csv_ip_range_list[i] = NULL;
+ while (ptr)
+ {
+ oldptr = ptr;
+ ptr = ptr->next;
+ safe_free(oldptr);
+ }
+ }
+}
+
+static void geoip_csv_free_ipv6(void)
+{
+ struct geoip_csv_ip6_range *ptr, *oldptr;
+ ptr = geoip_csv_ip6_range_list;
+ geoip_csv_ip6_range_list = NULL;
+ while (ptr)
+ {
+ oldptr = ptr;
+ ptr = ptr->next;
+ safe_free(oldptr);
+ }
+}
+
+static void geoip_csv_free_countries(void)
+{
+ struct geoip_csv_country *ptr, *oldptr;
+ ptr = geoip_csv_country_list;
+ geoip_csv_country_list = NULL;
+ while (ptr)
+ {
+ oldptr = ptr;
+ ptr = ptr->next;
+ safe_free(oldptr);
+ }
+}
+
+static void geoip_csv_free(void)
+{
+ geoip_csv_free_ipv4();
+ geoip_csv_free_ipv6();
+ geoip_csv_free_countries();
+}
+
+/* reading data from files */
+
+#define STR_HELPER(x) #x
+#define STR(x) STR_HELPER(x)
+#define BUFLEN 8191
+
+static int geoip_csv_read_ipv4(char *file)
+{
+ FILE *u;
+ char buf[BUFLEN+1];
+ int cidr, geoid;
+ char ip[24];
+ char netmask[24];
+ uint32_t addr;
+ uint32_t mask;
+ struct geoip_csv_ip_range *curr[256];
+ struct geoip_csv_ip_range *ptr;
+ memset(curr, 0, sizeof(curr));
+ int i;
+ char *filename = NULL;
+
+ safe_strdup(filename, file);
+ convert_to_absolute_path(&filename, CONFDIR);
+ u = fopen(filename, "r");
+ safe_free(filename);
+ if (!u)
+ {
+ config_warn("[geoip_csv] Cannot open IPv4 ranges list file");
+ return 1;
+ }
+
+ if (!fgets(buf, BUFLEN, u))
+ {
+ config_warn("[geoip_csv] IPv4 list file is empty");
+ fclose(u);
+ return 1;
+ }
+ buf[BUFLEN] = '\0';
+ while (fscanf(u, "%23[^/\n]/%d,%" STR(BUFLEN) "[^\n]\n", ip, &cidr, buf) == 3)
+ {
+ if (sscanf(buf, "%d,", &geoid) != 1)
+ {
+ /* missing geoid: can happen with valid files */
+ continue;
+ }
+
+ if (cidr < 1 || cidr > 32)
+ {
+ config_warn("[geoip_csv] Invalid CIDR found! IP=%s CIDR=%d! Bad CSV file?", ip, cidr);
+ continue;
+ }
+
+ if (inet_pton(AF_INET, ip, &addr) < 1)
+ {
+ config_warn("[geoip_csv] Invalid IP found! \"%s\" Bad CSV file?", ip);
+ continue;
+ }
+ addr = htonl(addr);
+
+ mask = 0;
+ while (cidr)
+ { /* calculate netmask */
+ mask >>= 1;
+ mask |= (1<<31);
+ cidr--;
+ }
+
+ i=0;
+ do
+ { /* multiple iterations in case CIDR is <8 and we have multiple first octets matching */
+ uint8_t index = addr>>24;
+ if (!curr[index])
+ {
+ geoip_csv_ip_range_list[index] = safe_alloc(sizeof(struct geoip_csv_ip_range));
+ curr[index] = geoip_csv_ip_range_list[index];
+ } else
+ {
+ curr[index]->next = safe_alloc(sizeof(struct geoip_csv_ip_range));
+ curr[index] = curr[index]->next;
+ }
+ ptr = curr[index];
+ ptr->next = NULL;
+ ptr->addr = addr;
+ ptr->mask = mask;
+ ptr->geoid = geoid;
+ i++;
+ index++;
+ } while (i<=((~mask)>>24));
+ }
+ fclose(u);
+ return 0;
+}
+
+static int geoip_csv_ip6_convert(char *ip, uint16_t out[8])
+{ /* convert text to binary form */
+ uint16_t tmp[8];
+ int i;
+ if (inet_pton(AF_INET6, ip, out) < 1)
+ return 0;
+ for (i=0; i<8; i++)
+ {
+ out[i] = htons(out[i]);
+ }
+ return 1;
+}
+
+#define IPV6_STRING_SIZE 40
+
+static int geoip_csv_read_ipv6(char *file)
+{
+ FILE *u;
+ char buf[BUFLEN+1];
+ char *bptr, *optr;
+ int cidr, geoid;
+ char ip[IPV6_STRING_SIZE];
+ uint16_t addr[8];
+ uint16_t mask[8];
+ struct geoip_csv_ip6_range *curr = NULL;
+ struct geoip_csv_ip6_range *ptr;
+ int error;
+ int length;
+ char *filename = NULL;
+
+ safe_strdup(filename, file);
+ convert_to_absolute_path(&filename, CONFDIR);
+ u = fopen(filename, "r");
+ safe_free(filename);
+ if (!u)
+ {
+ config_warn("[geoip_csv] Cannot open IPv6 ranges list file");
+ return 1;
+ }
+ if (!fgets(buf, BUFLEN, u))
+ {
+ config_warn("[geoip_csv] IPv6 list file is empty");
+ fclose(u);
+ return 1;
+ }
+ while (fgets(buf, BUFLEN, u))
+ {
+ error = 0;
+ bptr = buf;
+ optr = ip;
+ length = 0;
+ while (*bptr != '/')
+ {
+ if (!*bptr)
+ {
+ error = 1;
+ break;
+ }
+ if (++length >= IPV6_STRING_SIZE)
+ {
+ ip[IPV6_STRING_SIZE-1] = '\0';
+ config_warn("[geoip_csv] Too long IPv6 address found, starts with %s. Bad CSV file?", ip);
+ error = 1;
+ break;
+ }
+ *optr++ = *bptr++;
+ }
+ if (error)
+ continue;
+ *optr = '\0';
+ bptr++;
+ if (!geoip_csv_ip6_convert(ip, addr))
+ {
+ config_warn("[geoip_csv] Invalid IP found! \"%s\" Bad CSV file?", ip);
+ continue;
+ }
+ sscanf(bptr, "%d,%d,", &cidr, &geoid);
+ if (cidr < 1 || cidr > 128)
+ {
+ config_warn("[geoip_csv] Invalid CIDR found! CIDR=%d Bad CSV file?", cidr);
+ continue;
+ }
+
+ memset(mask, 0, 16);
+
+ int mask_bit = 0;
+ while (cidr)
+ { /* calculate netmask */
+ mask[mask_bit/16] |= 1<<(15-(mask_bit%16));
+ mask_bit++;
+ cidr--;
+ }
+
+ if (!curr)
+ {
+ geoip_csv_ip6_range_list = safe_alloc(sizeof(struct geoip_csv_ip6_range));
+ curr = geoip_csv_ip6_range_list;
+ } else
+ {
+ curr->next = safe_alloc(sizeof(struct geoip_csv_ip6_range));
+ curr = curr->next;
+ }
+ ptr = curr;
+ ptr->next = NULL;
+ memcpy(ptr->addr, addr, 16);
+ memcpy(ptr->mask, mask, 16);
+ ptr->geoid = geoid;
+ }
+ fclose(u);
+ return 0;
+}
+
+/* CSV fields; no STATE_GEONAME_ID because of using %d in fscanf */
+#define STATE_LOCALE_CODE 0
+#define STATE_CONTINENT_CODE 1
+#define STATE_CONTINENT_NAME 2
+#define STATE_COUNTRY_ISO_CODE 3
+#define STATE_COUNTRY_NAME 4
+#define STATE_IS_IN_EU 5
+
+#define MEMBER_SIZE(type,member) sizeof(((type *)0)->member)
+
+static int geoip_csv_read_countries(char *file)
+{
+ FILE *u;
+ char code[MEMBER_SIZE(struct geoip_csv_country, code)];
+ char continent[MEMBER_SIZE(struct geoip_csv_country, continent)];
+ char name[MEMBER_SIZE(struct geoip_csv_country, name)];
+ char buf[BUFLEN+1];
+ int state;
+ int id;
+ struct geoip_csv_country *curr = NULL;
+ char *filename = NULL;
+
+ safe_strdup(filename, file);
+ convert_to_absolute_path(&filename, CONFDIR);
+ u = fopen(filename, "r");
+ safe_free(filename);
+ if (!u)
+ {
+ config_warn("[geoip_csv] Cannot open countries list file");
+ return 1;
+ }
+
+ if (!fgets(buf, BUFLEN, u))
+ {
+ config_warn("[geoip_csv] Countries list file is empty");
+ fclose(u);
+ return 1;
+ }
+ while (fscanf(u, "%d,%" STR(BUFLEN) "[^\n]", &id, buf) == 2)
+ { /* getting country ID integer and all other data in string */
+ char *ptr = buf;
+ char *codeptr = code;
+ char *contptr = continent;
+ char *nptr = name;
+ int quote_open = 0;
+ int length = 0;
+ state = STATE_LOCALE_CODE;
+ while (*ptr)
+ {
+ switch (state)
+ {
+ case STATE_CONTINENT_NAME:
+ if (*ptr == ',')
+ goto next_line; /* no continent? */
+ if (length >= MEMBER_SIZE(struct geoip_csv_country, continent))
+ {
+ *contptr = '\0';
+ config_warn("[geoip_csv] Too long continent name found: `%s`. If you are sure your countries file is correct, please file a bug report.", continent);
+ goto next_line;
+ }
+ *contptr = *ptr; /* scan for continent name */
+ contptr++;
+ length++;
+ break;
+ case STATE_COUNTRY_ISO_CODE:
+ if (*ptr == ',') /* country code is empty */
+ goto next_line; /* -- that means only the continent is specified - we ignore it completely */
+ if (length >= MEMBER_SIZE(struct geoip_csv_country, code))
+ {
+ *codeptr = '\0';
+ config_warn("[geoip_csv] Too long country code found: `%s`. If you are sure your countries file is correct, please file a bug report.", code);
+ goto next_line;
+ }
+ *codeptr = *ptr; // scan for country code (DE, PL, US etc)
+ codeptr++;
+ length++;
+ break;
+ case STATE_COUNTRY_NAME:
+ goto read_country_name;
+ default:
+ break; // ignore this field and wait for next one
+ }
+ ptr++;
+ if (*ptr == ',')
+ {
+ length = 0;
+ ptr++;
+ state++;
+ }
+ }
+ read_country_name:
+ *codeptr = '\0';
+ *contptr = '\0';
+ length = 0;
+ while (*ptr)
+ {
+ switch (*ptr)
+ {
+ case '"':
+ quote_open = !quote_open;
+ ptr++;
+ continue;
+ case ',':
+ if (!quote_open)
+ goto end_country_name; /* we reached the end of current CSV field */
+ /* fall through */
+ default:
+ *nptr++ = *ptr++;
+ if (length >= MEMBER_SIZE(struct geoip_csv_country, name))
+ {
+ *nptr = '\0';
+ config_warn("[geoip_csv] Too long country name found: `%s`. If you are sure your countries file is correct, please file a bug report.", name);
+ goto next_line;
+ }
+ break; // scan for country name
+ }
+ }
+ end_country_name:
+ *nptr = '\0';
+ if (geoip_csv_country_list)
+ {
+ curr->next = safe_alloc(sizeof(struct geoip_csv_country));
+ curr = curr->next;
+ } else
+ {
+ geoip_csv_country_list = safe_alloc(sizeof(struct geoip_csv_country));
+ curr = geoip_csv_country_list;
+ }
+ curr->next = NULL;
+ strcpy(curr->code, code);
+ strcpy(curr->name, name);
+ strcpy(curr->continent, continent);
+ curr->id = id;
+ next_line: continue;
+ }
+ fclose(u);
+ return 0;
+}
+
+static struct geoip_csv_country *geoip_csv_get_country(int id)
+{
+ struct geoip_csv_country *curr = geoip_csv_country_list;
+ if (!curr)
+ return NULL;
+ int found = 0;
+ for (;curr;curr = curr->next)
+ {
+ if (curr->id == id)
+ {
+ found = 1;
+ break;
+ }
+ }
+ if (found)
+ return curr;
+ return NULL;
+}
+
+static int geoip_csv_get_v4_geoid(char *iip)
+{
+ uint32_t addr, tmp_addr;
+ struct geoip_csv_ip_range *curr;
+ int i;
+ int found = 0;
+ if (inet_pton(AF_INET, iip, &addr) < 1)
+ {
+ unreal_log(ULOG_WARNING, "geoip_csv", "UNSUPPORTED_IP", NULL, "Invalid or unsupported client IP $ip", log_data_string("ip", iip));
+ return 0;
+ }
+ addr = htonl(addr);
+ curr = geoip_csv_ip_range_list[addr>>24];
+ if (curr)
+ {
+ i = 0;
+ for (;curr;curr = curr->next)
+ {
+ tmp_addr = addr;
+ tmp_addr &= curr->mask; /* mask the address to filter out net prefix only */
+ if (tmp_addr == curr->addr)
+ { /* ... and match it to the loaded data */
+ found = 1;
+ break;
+ }
+ i++;
+ }
+ }
+ if (found)
+ return curr->geoid;
+ return 0;
+}
+
+static int geoip_csv_get_v6_geoid(char *iip)
+{
+ uint16_t addr[8];
+ struct geoip_csv_ip6_range *curr;
+ int i;
+ int found = 0;
+
+ if (!geoip_csv_ip6_convert(iip, addr))
+ {
+ unreal_log(ULOG_WARNING, "geoip_csv", "UNSUPPORTED_IP", NULL, "Invalid or unsupported client IP $ip", log_data_string("ip", iip));
+ return 0;
+ }
+ curr = geoip_csv_ip6_range_list;
+ if (curr)
+ {
+ for (;curr;curr = curr->next)
+ {
+ found = 1;
+ for (i=0; i<8; i++)
+ {
+ if (curr->addr[i] != (addr[i] & curr->mask[i]))
+ { /* compare net address to loaded data */
+ found = 0;
+ break;
+ }
+ }
+ if(found)
+ break;
+ }
+ }
+ if (found)
+ return curr->geoid;
+ return 0;
+}
+
+GeoIPResult *geoip_lookup_csv(char *ip)
+{
+ int geoid;
+ struct geoip_csv_country *country;
+ GeoIPResult *r;
+
+ if (!ip)
+ return NULL;
+
+ if (strchr(ip, ':'))
+ {
+ geoid = geoip_csv_get_v6_geoid(ip);
+ } else
+ {
+ geoid = geoip_csv_get_v4_geoid(ip);
+ }
+
+ if (geoid == 0)
+ return NULL;
+
+ country = geoip_csv_get_country(geoid);
+
+ if (!country)
+ return NULL;
+
+ r = safe_alloc(sizeof(GeoIPResult));
+ safe_strdup(r->country_code, country->code);
+ safe_strdup(r->country_name, country->name);
+ return r;
+}
+
diff --git a/src/modules/geoip_maxmind.c b/src/modules/geoip_maxmind.c
new file mode 100644
index 0000000..06581f3
--- /dev/null
+++ b/src/modules/geoip_maxmind.c
@@ -0,0 +1,239 @@
+/* GEOIP maxmind module
+ * (C) Copyright 2021 Bram Matthys and the UnrealIRCd team
+ * License: GPLv2
+ */
+
+#include "unrealircd.h"
+#include
+
+ModuleHeader MOD_HEADER
+ = {
+ "geoip_maxmind",
+ "5.0",
+ "GEOIP using maxmind databases",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+ };
+
+struct geoip_maxmind_config_s {
+ char *db_file;
+/* for config reading only */
+ int have_config;
+ int have_database;
+};
+
+/* Variables */
+
+struct geoip_maxmind_config_s geoip_maxmind_config;
+MMDB_s mmdb;
+
+/* Forward declarations */
+int geoip_maxmind_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs);
+int geoip_maxmind_configposttest(int *errs);
+int geoip_maxmind_configrun(ConfigFile *cf, ConfigEntry *ce, int type);
+void geoip_maxmind_free(void);
+GeoIPResult *geoip_lookup_maxmind(char *ip);
+
+int geoip_maxmind_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
+{
+ ConfigEntry *cep;
+ int errors = 0;
+ int i;
+
+ if (type != CONFIG_SET)
+ return 0;
+
+ if (!ce || !ce->name)
+ return 0;
+
+ if (strcmp(ce->name, "geoip-maxmind"))
+ return 0;
+
+ geoip_maxmind_config.have_config = 1;
+
+ for (cep = ce->items; cep; cep = cep->next)
+ {
+ if (!strcmp(cep->name, "database"))
+ {
+ if (geoip_maxmind_config.have_database)
+ {
+ config_error("%s:%i: duplicate item set::geoip-maxmind::%s", cep->file->filename, cep->line_number, cep->name);
+ continue;
+ }
+ if (!is_file_readable(cep->value, PERMDATADIR))
+ {
+ config_error("%s:%i: set::geoip-maxmind::%s: cannot open file \"%s/%s\" for reading (%s)", cep->file->filename, cep->line_number, cep->name, PERMDATADIR, cep->value, strerror(errno));
+ errors++;
+ continue;
+ }
+ geoip_maxmind_config.have_database = 1;
+ continue;
+ }
+ config_warn("%s:%i: unknown item set::geoip-maxmind::%s", cep->file->filename, cep->line_number, cep->name);
+ }
+
+ *errs = errors;
+ return errors ? -1 : 1;
+}
+
+int geoip_maxmind_configposttest(int *errs)
+{
+ int errors = 0;
+ if (geoip_maxmind_config.have_config)
+ {
+ if (!geoip_maxmind_config.have_database)
+ {
+ config_error("geoip_maxmind: no database file specified! Remove set::geoip-maxmind to use defaults");
+ errors++;
+ }
+ } else
+ {
+ safe_strdup(geoip_maxmind_config.db_file, "GeoLite2-Country.mmdb");
+
+ if (is_file_readable(geoip_maxmind_config.db_file, PERMDATADIR))
+ {
+ geoip_maxmind_config.have_database = 1;
+ } else
+ {
+ config_error("[geoip_maxmind] cannot open database file \"%s/%s\" for reading (%s)", PERMDATADIR, geoip_maxmind_config.db_file, strerror(errno));
+ safe_free(geoip_maxmind_config.db_file);
+ errors++;
+ }
+ }
+
+ *errs = errors;
+ return errors ? -1 : 1;
+}
+
+int geoip_maxmind_configrun(ConfigFile *cf, ConfigEntry *ce, int type)
+{
+ ConfigEntry *cep;
+
+ if (type != CONFIG_SET)
+ return 0;
+
+ if (!ce || !ce->name)
+ return 0;
+
+ if (strcmp(ce->name, "geoip-maxmind"))
+ return 0;
+
+ for (cep = ce->items; cep; cep = cep->next)
+ {
+ if (!strcmp(cep->name, "database") && geoip_maxmind_config.have_database)
+ safe_strdup(geoip_maxmind_config.db_file, cep->value);
+ }
+ return 1;
+}
+
+MOD_TEST()
+{
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+ if (!CallbackAddPVoid(modinfo->handle, CALLBACKTYPE_GEOIP_LOOKUP, TO_PVOIDFUNC(geoip_lookup_maxmind)))
+ {
+ unreal_log(ULOG_ERROR, "geoip_maxmind", "GEOIP_ADD_CALLBACK_FAILED", NULL,
+ "geoip_maxmind: Could not install GEOIP_LOOKUP callback. "
+ "Most likely another geoip module is already loaded. "
+ "You can only load one!");
+ return MOD_FAILED;
+ }
+
+ geoip_maxmind_config.have_config = 0;
+ geoip_maxmind_config.have_database = 0;
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, geoip_maxmind_configtest);
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGPOSTTEST, 0, geoip_maxmind_configposttest);
+ return MOD_SUCCESS;
+}
+
+MOD_INIT()
+{
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, geoip_maxmind_configrun);
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ geoip_maxmind_free();
+ convert_to_absolute_path(&geoip_maxmind_config.db_file, PERMDATADIR);
+
+ int status = MMDB_open(geoip_maxmind_config.db_file, MMDB_MODE_MMAP, &mmdb);
+
+ if (status != MMDB_SUCCESS) {
+ int save_err = errno;
+ unreal_log(ULOG_WARNING, "geoip_maxmind", "GEOIP_CANNOT_OPEN_DB", NULL,
+ "Could not open '$filename' - $maxmind_error; IO error: $io_error",
+ log_data_string("filename", geoip_maxmind_config.db_file),
+ log_data_string("maxmind_error", MMDB_strerror(status)),
+ log_data_string("io_error", (status == MMDB_IO_ERROR)?strerror(save_err):"none"));
+ return MOD_FAILED;
+ }
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ geoip_maxmind_free();
+ return MOD_SUCCESS;
+}
+
+void geoip_maxmind_free(void)
+{
+ MMDB_close(&mmdb);
+}
+
+GeoIPResult *geoip_lookup_maxmind(char *ip)
+{
+ int gai_error, mmdb_error, status;
+ MMDB_lookup_result_s result;
+ MMDB_entry_data_s country_code;
+ MMDB_entry_data_s country_name;
+ char *country_code_str, *country_name_str;
+ GeoIPResult *r;
+
+ if (!ip)
+ return NULL;
+
+ result = MMDB_lookup_string(&mmdb, ip, &gai_error, &mmdb_error);
+ if (gai_error)
+ {
+ unreal_log(ULOG_DEBUG, "geoip_maxmind", "GEOIP_DB_ERROR", NULL,
+ "libmaxminddb: getaddrinfo error for $ip: $error",
+ log_data_string("ip", ip),
+ log_data_string("error", gai_strerror(gai_error)));
+ return NULL;
+ }
+
+ if (mmdb_error != MMDB_SUCCESS)
+ {
+ unreal_log(ULOG_DEBUG, "geoip_maxmind", "GEOIP_DB_ERROR", NULL,
+ "libmaxminddb: library error for $ip: $error",
+ log_data_string("ip", ip),
+ log_data_string("error", MMDB_strerror(mmdb_error)));
+ return NULL;
+ }
+
+ if (!result.found_entry) /* no result */
+ return NULL;
+
+ status = MMDB_get_value(&result.entry, &country_code, "country", "iso_code", NULL);
+ if (status != MMDB_SUCCESS || !country_code.has_data || country_code.type != MMDB_DATA_TYPE_UTF8_STRING)
+ return NULL;
+ status = MMDB_get_value(&result.entry, &country_name, "country", "names", "en", NULL);
+ if (status != MMDB_SUCCESS || !country_name.has_data || country_name.type != MMDB_DATA_TYPE_UTF8_STRING)
+ return NULL;
+
+ /* these results are not null-terminated */
+ country_code_str = safe_alloc(country_code.data_size + 1);
+ country_name_str = safe_alloc(country_name.data_size + 1);
+ memcpy(country_code_str, country_code.utf8_string, country_code.data_size);
+ country_code_str[country_code.data_size] = '\0';
+ memcpy(country_name_str, country_name.utf8_string, country_name.data_size);
+ country_name_str[country_name.data_size] = '\0';
+
+ r = safe_alloc(sizeof(GeoIPResult));
+ r->country_code = country_code_str;
+ r->country_name = country_name_str;
+ return r;
+}
+
diff --git a/src/modules/globops.c b/src/modules/globops.c
index 8afcb1f..284e62c 100644
--- a/src/modules/globops.c
+++ b/src/modules/globops.c
@@ -32,7 +32,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /globops",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
@@ -57,9 +57,7 @@ MOD_UNLOAD()
*/
CMD_FUNC(cmd_globops)
{
- char *message;
-
- message = parc > 1 ? parv[1] : NULL;
+ const char *message = parc > 1 ? parv[1] : NULL;
if (BadPtr(message))
{
diff --git a/src/modules/help.c b/src/modules/help.c
index 65f2976..7d0e496 100644
--- a/src/modules/help.c
+++ b/src/modules/help.c
@@ -33,7 +33,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /help",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
@@ -57,7 +57,7 @@ MOD_UNLOAD()
#define HDR(str) sendto_one(client, NULL, ":%s 290 %s :%s", me.name, client->name, str);
#define SND(str) sendto_one(client, NULL, ":%s 292 %s :%s", me.name, client->name, str);
-ConfigItem_help *find_Help(char *command)
+ConfigItem_help *find_Help(const char *command)
{
ConfigItem_help *help;
@@ -80,7 +80,7 @@ ConfigItem_help *find_Help(char *command)
return NULL;
}
-void parse_help(Client *client, char *name, char *help)
+void parse_help(Client *client, const char *help)
{
ConfigItem_help *helpitem;
MOTDLine *text;
@@ -109,7 +109,7 @@ void parse_help(Client *client, char *name, char *help)
SND(" We're sorry, we don't have help available for the command you requested.");
SND(" -");
sendto_one(client, NULL, ":%s 292 %s : ***** Go to %s if you have any further questions *****",
- me.name, client->name, helpchan);
+ me.name, client->name, HELP_CHANNEL);
SND(" -");
return;
}
@@ -131,7 +131,7 @@ void parse_help(Client *client, char *name, char *help)
*/
CMD_FUNC(cmd_help)
{
- char *helptopic;
+ const char *helptopic;
if (!MyUser(client))
return; /* never remote */
@@ -141,5 +141,5 @@ CMD_FUNC(cmd_help)
if (helptopic && (*helptopic == '?'))
helptopic++;
- parse_help(client, client->name, BadPtr(helptopic) ? NULL : helptopic);
+ parse_help(client, BadPtr(helptopic) ? NULL : helptopic);
}
diff --git a/src/modules/hideserver.c b/src/modules/hideserver.c
index e0231a1..4e22bca 100644
--- a/src/modules/hideserver.c
+++ b/src/modules/hideserver.c
@@ -49,7 +49,7 @@ ModuleHeader MOD_HEADER
"5.0",
"Hide servers from /MAP & /LINKS",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
static void InitConf()
@@ -95,10 +95,10 @@ MOD_INIT()
MOD_LOAD()
{
- if (!CommandOverrideAdd(MyMod, "MAP", override_map))
+ if (!CommandOverrideAdd(MyMod, "MAP", 0, override_map))
return MOD_FAILED;
- if (!CommandOverrideAdd(MyMod, "LINKS", override_links))
+ if (!CommandOverrideAdd(MyMod, "LINKS", 0, override_links))
return MOD_FAILED;
return MOD_SUCCESS;
@@ -118,35 +118,35 @@ static int cb_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
if (type == CONFIG_MAIN)
{
- if (!strcmp(ce->ce_varname, "hideserver"))
+ if (!strcmp(ce->name, "hideserver"))
{
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "hide"))
+ if (!strcmp(cep->name, "hide"))
{
/* No checking needed */
}
- else if (!cep->ce_vardata)
+ else if (!cep->value)
{
config_error("%s:%i: %s::%s without value",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum,
- ce->ce_varname, cep->ce_varname);
+ cep->file->filename,
+ cep->line_number,
+ ce->name, cep->name);
errors++;
continue;
}
- else if (!strcmp(cep->ce_varname, "disable-map"))
+ else if (!strcmp(cep->name, "disable-map"))
;
- else if (!strcmp(cep->ce_varname, "disable-links"))
+ else if (!strcmp(cep->name, "disable-links"))
;
- else if (!strcmp(cep->ce_varname, "map-deny-message"))
+ else if (!strcmp(cep->name, "map-deny-message"))
;
- else if (!strcmp(cep->ce_varname, "links-deny-message"))
+ else if (!strcmp(cep->name, "links-deny-message"))
;
else
{
config_error("%s:%i: unknown directive hideserver::%s",
- cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname);
+ cep->file->filename, cep->line_number, cep->name);
errors++;
}
}
@@ -165,31 +165,31 @@ static int cb_conf(ConfigFile *cf, ConfigEntry *ce, int type)
if (type == CONFIG_MAIN)
{
- if (!strcmp(ce->ce_varname, "hideserver"))
+ if (!strcmp(ce->name, "hideserver"))
{
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ for (cep = ce->items; cep; cep = cep->next)
{
- if (!strcmp(cep->ce_varname, "disable-map"))
- Settings.disable_map = config_checkval(cep->ce_vardata, CFG_YESNO);
- else if (!strcmp(cep->ce_varname, "disable-links"))
- Settings.disable_links = config_checkval(cep->ce_vardata, CFG_YESNO);
- else if (!strcmp(cep->ce_varname, "map-deny-message"))
+ if (!strcmp(cep->name, "disable-map"))
+ Settings.disable_map = config_checkval(cep->value, CFG_YESNO);
+ else if (!strcmp(cep->name, "disable-links"))
+ Settings.disable_links = config_checkval(cep->value, CFG_YESNO);
+ else if (!strcmp(cep->name, "map-deny-message"))
{
- safe_strdup(Settings.map_deny_message, cep->ce_vardata);
+ safe_strdup(Settings.map_deny_message, cep->value);
}
- else if (!strcmp(cep->ce_varname, "links-deny-message"))
+ else if (!strcmp(cep->name, "links-deny-message"))
{
- safe_strdup(Settings.links_deny_message, cep->ce_vardata);
+ safe_strdup(Settings.links_deny_message, cep->value);
}
- else if (!strcmp(cep->ce_varname, "hide"))
+ else if (!strcmp(cep->name, "hide"))
{
- for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+ for (cepp = cep->items; cepp; cepp = cepp->next)
{
- if (!strcasecmp(cepp->ce_varname, me.name))
+ if (!strcasecmp(cepp->name, me.name))
continue;
ca = safe_alloc(sizeof(ConfigItem_ulines));
- safe_strdup(ca->servername, cepp->ce_varname);
+ safe_strdup(ca->servername, cepp->name);
AddListItem(ca, HiddenServers);
}
}
@@ -231,7 +231,7 @@ static void dump_map(Client *client, Client *server, char *mask, int prompt_leng
else
{
sendnumeric(client, RPL_MAP, prompt,
- length, server->name, server->serv->users, IsOper(client) ? server->id : "");
+ length, server->name, server->server->users, IsOper(client) ? server->id : "");
cnt = 0;
}
@@ -248,7 +248,7 @@ static void dump_map(Client *client, Client *server, char *mask, int prompt_leng
list_for_each_entry(acptr, &global_server_list, client_node)
{
- if (acptr->srvptr != server ||
+ if (acptr->uplink != server ||
(IsULine(acptr) && HIDE_ULINES && !ValidatePermissionsForPath("server:info:map:ulines",client,NULL,NULL,NULL)))
continue;
if (FindHiddenServer(acptr->name))
@@ -263,7 +263,7 @@ static void dump_map(Client *client, Client *server, char *mask, int prompt_leng
continue;
if (FindHiddenServer(acptr->name))
break;
- if (acptr->srvptr != server)
+ if (acptr->uplink != server)
continue;
if (!IsMap(acptr))
continue;
@@ -284,7 +284,7 @@ void dump_flat_map(Client *client, Client *server, int length)
hide_ulines = (HIDE_ULINES && !ValidatePermissionsForPath("server:info:map:ulines",client,NULL,NULL,NULL)) ? 1 : 0;
- sendnumeric(client, RPL_MAP, "", length, server->name, server->serv->users, "");
+ sendnumeric(client, RPL_MAP, "", length, server->name, server->server->users, "");
list_for_each_entry(acptr, &global_server_list, client_node)
{
@@ -304,7 +304,7 @@ 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->serv->users, "");
+ sendnumeric(client, RPL_MAP, buf, length-2, acptr->name, acptr->server->users, "");
}
}
@@ -388,7 +388,7 @@ CMD_OVERRIDE_FUNC(override_links)
sendnumeric(client, RPL_LINKS, acptr->name, me.name,
1, (acptr->info[0] ? acptr->info : "(Unknown Location)"));
else
- sendnumeric(client, RPL_LINKS, acptr->name, acptr->serv->up,
+ sendnumeric(client, RPL_LINKS, acptr->name, acptr->uplink->name,
acptr->hopcount, (acptr->info[0] ? acptr->info : "(Unknown Location)"));
}
diff --git a/src/modules/history.c b/src/modules/history.c
index e8311e0..d99823e 100644
--- a/src/modules/history.c
+++ b/src/modules/history.c
@@ -34,7 +34,7 @@ ModuleHeader MOD_HEADER
"5.0",
"Simple history command for end-users",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
#define HISTORY_LINES_DEFAULT 100
@@ -76,13 +76,16 @@ CMD_FUNC(cmd_history)
Channel *channel;
int lines = HISTORY_LINES_DEFAULT;
+ if (!MyUser(client))
+ return;
+
if ((parc < 2) || BadPtr(parv[1]))
{
history_usage(client);
return;
}
- channel = find_channel(parv[1], NULL);
+ channel = find_channel(parv[1]);
if (!channel)
{
sendnumeric(client, ERR_NOSUCHCHANNEL, parv[1]);
@@ -91,13 +94,13 @@ CMD_FUNC(cmd_history)
if (!IsMember(client, channel))
{
- sendnumeric(client, ERR_NOTONCHANNEL, channel->chname);
+ sendnumeric(client, ERR_NOTONCHANNEL, channel->name);
return;
}
if (!has_channel_mode(channel, 'H'))
{
- sendnotice(client, "Channel %s does not have channel mode +H set", channel->chname);
+ sendnotice(client, "Channel %s does not have channel mode +H set", channel->name);
return;
}
@@ -125,7 +128,7 @@ CMD_FUNC(cmd_history)
filter.cmd = HFC_SIMPLE;
filter.last_lines = lines;
- if ((r = history_request(channel->chname, &filter)))
+ if ((r = history_request(channel->name, &filter)))
{
history_send_result(client, r);
free_history_result(r);
diff --git a/src/modules/history_backend_mem.c b/src/modules/history_backend_mem.c
index 897da65..9fd5117 100644
--- a/src/modules/history_backend_mem.c
+++ b/src/modules/history_backend_mem.c
@@ -17,7 +17,7 @@ ModuleHeader MOD_HEADER
"2.0",
"History backend: memory",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Defines */
@@ -97,16 +97,16 @@ static void freecfg(struct cfgstruct *cfg);
static void hbm_init_hashes(ModuleInfo *m);
static void init_history_storage(ModuleInfo *modinfo);
int hbm_modechar_del(Channel *channel, int modechar);
-int hbm_history_add(char *object, MessageTag *mtags, char *line);
+int hbm_history_add(const char *object, MessageTag *mtags, const char *line);
int hbm_history_cleanup(HistoryLogObject *h);
-HistoryResult *hbm_history_request(char *object, HistoryFilter *filter);
-int hbm_history_destroy(char *object);
-int hbm_history_set_limit(char *object, int max_lines, long max_time);
+HistoryResult *hbm_history_request(const char *object, HistoryFilter *filter);
+int hbm_history_destroy(const char *object);
+int hbm_history_set_limit(const char *object, int max_lines, long max_time);
EVENT(history_mem_clean);
EVENT(history_mem_init);
static int hbm_read_masterdb(void);
static void hbm_read_dbs(void);
-static int hbm_read_db(char *fname);
+static int hbm_read_db(const char *fname);
static int hbm_write_masterdb(void);
static int hbm_write_db(HistoryLogObject *h);
static void hbm_delete_db(HistoryLogObject *h);
@@ -200,7 +200,7 @@ EVENT(history_mem_init)
MOD_UNLOAD()
{
- if (loop.ircd_terminating)
+ if (loop.terminating)
hbm_flush();
freecfg(&test);
freecfg(&cfg);
@@ -235,6 +235,7 @@ static void setcfg(struct cfgstruct *cfg)
static void freecfg(struct cfgstruct *cfg)
{
+ safe_free(cfg->masterdb);
safe_free(cfg->directory);
safe_free(cfg->db_secret);
}
@@ -264,40 +265,40 @@ int hbm_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
{
int errors = 0;
- if ((type != CONFIG_SET_HISTORY_CHANNEL) || !ce || !ce->ce_varname)
+ if ((type != CONFIG_SET_HISTORY_CHANNEL) || !ce || !ce->name)
return 0;
- if (!strcmp(ce->ce_varname, "persist"))
+ if (!strcmp(ce->name, "persist"))
{
- if (!ce->ce_vardata)
+ if (!ce->value)
{
config_error("%s:%i: missing parameter",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
} else {
- test.persist = config_checkval(ce->ce_vardata, CFG_YESNO);
+ test.persist = config_checkval(ce->value, CFG_YESNO);
}
} else
- if (!strcmp(ce->ce_varname, "db-secret"))
+ if (!strcmp(ce->name, "db-secret"))
{
- char *err;
- if ((err = unrealdb_test_secret(ce->ce_vardata)))
+ const char *err;
+ if ((err = unrealdb_test_secret(ce->value)))
{
- config_error("%s:%i: set::history::channel::db-secret: %s", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, err);
+ config_error("%s:%i: set::history::channel::db-secret: %s", ce->file->filename, ce->line_number, err);
errors++;
}
- safe_strdup(test.db_secret, ce->ce_vardata);
+ safe_strdup(test.db_secret, ce->value);
} else
- if (!strcmp(ce->ce_varname, "directory")) // or "path" ?
+ if (!strcmp(ce->name, "directory")) // or "path" ?
{
- if (!ce->ce_vardata)
+ if (!ce->value)
{
config_error("%s:%i: missing parameter",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ ce->file->filename, ce->line_number);
errors++;
} else
{
- safe_strdup(test.directory, ce->ce_vardata);
+ safe_strdup(test.directory, ce->value);
hbm_set_masterdb_filename(&test);
}
} else
@@ -322,7 +323,7 @@ int hbm_config_posttest(int *errs)
} else
if (!test.db_secret && test.persist)
{
- config_error("set::history::channel::db-secret needs to be set."); // TODO: REFER TO FAQ OR OTHER ENTRY!!!!
+ config_error("set::history::channel::db-secret needs to be set.");
errors++;
} else
if (test.db_secret && test.persist)
@@ -367,22 +368,22 @@ hbm_config_posttest_end:
/** Configure ourselves based on the set::history::channel settings */
int hbm_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
{
- if ((type != CONFIG_SET_HISTORY_CHANNEL) || !ce || !ce->ce_varname)
+ if ((type != CONFIG_SET_HISTORY_CHANNEL) || !ce || !ce->name)
return 0;
- if (!strcmp(ce->ce_varname, "persist"))
+ if (!strcmp(ce->name, "persist"))
{
- cfg.persist = config_checkval(ce->ce_vardata, CFG_YESNO);
+ cfg.persist = config_checkval(ce->value, CFG_YESNO);
} else
- if (!strcmp(ce->ce_varname, "directory")) // or "path" ?
+ if (!strcmp(ce->name, "directory")) // or "path" ?
{
- safe_strdup(cfg.directory, ce->ce_vardata);
+ safe_strdup(cfg.directory, ce->value);
convert_to_absolute_path(&cfg.directory, PERMDATADIR);
hbm_set_masterdb_filename(&cfg);
} else
- if (!strcmp(ce->ce_varname, "db-secret"))
+ if (!strcmp(ce->name, "db-secret"))
{
- safe_strdup(cfg.db_secret, ce->ce_vardata);
+ safe_strdup(cfg.db_secret, ce->value);
} else
{
return 0; /* unknown option to us, let another module handle it */
@@ -403,7 +404,7 @@ int hbm_rehash_complete(void)
return 0;
}
-char *history_storage_capability_parameter(Client *client)
+const char *history_storage_capability_parameter(Client *client)
{
static char buf[128];
@@ -426,12 +427,12 @@ static void init_history_storage(ModuleInfo *modinfo)
ClientCapabilityAdd(modinfo->handle, &cap, NULL);
}
-uint64_t hbm_hash(char *object)
+uint64_t hbm_hash(const char *object)
{
return siphash_nocase(object, siphashkey_history_backend_mem) % HISTORY_BACKEND_MEM_HASH_TABLE_SIZE;
}
-HistoryLogObject *hbm_find_object(char *object)
+HistoryLogObject *hbm_find_object(const char *object)
{
int hashv = hbm_hash(object);
HistoryLogObject *h;
@@ -444,7 +445,7 @@ HistoryLogObject *hbm_find_object(char *object)
return NULL;
}
-HistoryLogObject *hbm_find_or_add_object(char *object)
+HistoryLogObject *hbm_find_or_add_object(const char *object)
{
int hashv = hbm_hash(object);
HistoryLogObject *h;
@@ -480,7 +481,7 @@ int hbm_modechar_del(Channel *channel, int modechar)
if (!cfg.persist)
return 0;
- if ((modechar == 'P') && ((h = hbm_find_object(channel->chname))))
+ if ((modechar == 'P') && ((h = hbm_find_object(channel->name))))
{
/* Channel went from +P to -P and also has channel history: delete the history file */
hbm_delete_db(h);
@@ -538,7 +539,7 @@ void hbm_duplicate_mtags(HistoryLogLine *l, MessageTag *m)
}
/** Add a line to a history object */
-void hbm_history_add_line(HistoryLogObject *h, MessageTag *mtags, char *line)
+void hbm_history_add_line(HistoryLogObject *h, MessageTag *mtags, const char *line)
{
HistoryLogLine *l = safe_alloc(sizeof(HistoryLogLine) + strlen(line));
strcpy(l->line, line); /* safe, see memory allocation above ^ */
@@ -589,12 +590,14 @@ void hbm_history_del_line(HistoryLogObject *h, HistoryLogLine *l)
}
/** Add history entry */
-int hbm_history_add(char *object, MessageTag *mtags, char *line)
+int hbm_history_add(const char *object, MessageTag *mtags, const char *line)
{
HistoryLogObject *h = hbm_find_or_add_object(object);
if (!h->max_lines)
{
- sendto_realops("hbm_history_add() for '%s', which has no limit", h->name);
+ unreal_log(ULOG_WARNING, "history", "BUG_HISTORY_ADD_NO_LIMIT", NULL,
+ "[BUG] hbm_history_add() called for $object, which has no limit set",
+ log_data_string("object", h->name));
#ifdef DEBUGMODE
abort();
#else
@@ -955,7 +958,7 @@ static int hbm_return_between(HistoryResult *r, HistoryLogObject *h, HistoryFilt
return 0;
}
-HistoryResult *hbm_history_request(char *object, HistoryFilter *filter)
+HistoryResult *hbm_history_request(const char *object, HistoryFilter *filter)
{
HistoryResult *r;
HistoryLogObject *h = hbm_find_object(object);
@@ -1050,7 +1053,7 @@ int hbm_history_cleanup(HistoryLogObject *h)
return 1;
}
-int hbm_history_destroy(char *object)
+int hbm_history_destroy(const char *object)
{
HistoryLogObject *h = hbm_find_object(object);
HistoryLogLine *l, *l_next;
@@ -1075,7 +1078,7 @@ int hbm_history_destroy(char *object)
}
/** Set new limit on history object */
-int hbm_history_set_limit(char *object, int max_lines, long max_time)
+int hbm_history_set_limit(const char *object, int max_lines, long max_time)
{
HistoryLogObject *h = hbm_find_or_add_object(object);
h->max_lines = max_lines;
@@ -1104,8 +1107,6 @@ static int hbm_read_masterdb(void)
{
/* Database does not exist. Could be first boot */
config_warn("[history] No database present at '%s', will start a new one", test.masterdb);
- // TODO: maybe check for condition where 'master.db' does not exist but
- // there are other .db files.
if (!hbm_write_masterdb())
return 0; /* fatal error */
return 1;
@@ -1125,10 +1126,10 @@ static int hbm_read_masterdb(void)
!unrealdb_read_str(db, &prehash) ||
!unrealdb_read_str(db, &posthash))
{
- safe_free(prehash);
- safe_free(posthash);
config_error("[history] Read error from database file '%s': %s",
test.masterdb, unrealdb_get_error_string());
+ safe_free(prehash);
+ safe_free(posthash);
unrealdb_close(db);
return 0;
}
@@ -1138,14 +1139,24 @@ static int hbm_read_masterdb(void)
{
config_error("[history] Read error from database file '%s': unexpected values encountered",
test.masterdb);
+ safe_free(prehash);
+ safe_free(posthash);
return 0;
}
/* Now, safely switch over.. */
- safe_free(hbm_prehash);
- safe_free(hbm_posthash);
- hbm_prehash = prehash;
- hbm_posthash = posthash;
+ if (hbm_prehash && !strcmp(hbm_prehash, prehash) && hbm_posthash && !strcmp(hbm_posthash, posthash))
+ {
+ /* Identical sets */
+ safe_free(prehash);
+ safe_free(posthash);
+ } else {
+ /* Diffferent */
+ safe_free(hbm_prehash);
+ safe_free(hbm_posthash);
+ hbm_prehash = prehash;
+ hbm_posthash = posthash;
+ }
return 1;
}
@@ -1275,7 +1286,7 @@ static void hbm_read_dbs(void)
/** Read a channel history db file */
-static int hbm_read_db(char *fname)
+static int hbm_read_db(const char *fname)
{
UnrealDB *db = NULL;
// header
@@ -1475,7 +1486,7 @@ EVENT(history_mem_clean)
} while(loopcnt++ < HISTORY_CLEAN_PER_LOOP);
}
-char *hbm_history_filename(HistoryLogObject *h)
+const char *hbm_history_filename(HistoryLogObject *h)
{
static char fname[512];
char oname[OBJECTLEN+1];
@@ -1495,9 +1506,10 @@ char *hbm_history_filename(HistoryLogObject *h)
#define WARN_WRITE_ERROR(fname) \
do { \
- sendto_realops_and_log("[history] Error writing to temporary database file " \
- "'%s': %s (DATABASE NOT SAVED)", \
- fname, unrealdb_get_error_string()); \
+ unreal_log(ULOG_ERROR, "history", "HISTORYDB_FILE_WRITE_ERROR", NULL, \
+ "[historydb] Error writing to temporary database file $filename: $system_error", \
+ log_data_string("filename", fname), \
+ log_data_string("system_error", unrealdb_get_error_string())); \
} while(0)
#define W_SAFE(x) \
@@ -1515,7 +1527,7 @@ char *hbm_history_filename(HistoryLogObject *h)
static int hbm_write_db(HistoryLogObject *h)
{
UnrealDB *db;
- char *realfname;
+ const char *realfname;
char tmpfname[512];
HistoryLogLine *l;
MessageTag *m;
@@ -1524,7 +1536,7 @@ static int hbm_write_db(HistoryLogObject *h)
if (!cfg.db_secret)
abort();
- channel = find_channel(h->name, NULL);
+ channel = find_channel(h->name);
if (!channel || !has_channel_mode(channel, 'P'))
return 1; /* Don't save this channel, pretend success */
@@ -1575,7 +1587,7 @@ static int hbm_write_db(HistoryLogObject *h)
#endif
if (rename(tmpfname, realfname) < 0)
{
- sendto_realops_and_log("[history] Error renaming '%s' to '%s': %s (HISTORY NOT SAVED)",
+ config_error("[history] Error renaming '%s' to '%s': %s (HISTORY NOT SAVED)",
tmpfname, realfname, strerror(errno));
return 0;
}
@@ -1588,7 +1600,7 @@ static int hbm_write_db(HistoryLogObject *h)
static void hbm_delete_db(HistoryLogObject *h)
{
UnrealDB *db;
- char *fname;
+ const char *fname;
if (!cfg.persist || !hbm_prehash || !hbm_posthash)
{
#ifdef DEBUGMODE
diff --git a/src/modules/history_backend_null.c b/src/modules/history_backend_null.c
index 2df4513..7136ce2 100644
--- a/src/modules/history_backend_null.c
+++ b/src/modules/history_backend_null.c
@@ -16,14 +16,14 @@ ModuleHeader MOD_HEADER
"2.0",
"History backend: null/none",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Forward declarations */
-int hbn_history_set_limit(char *object, int max_lines, long max_time);
-int hbn_history_add(char *object, MessageTag *mtags, char *line);
-HistoryResult *hbn_history_request(char *object, HistoryFilter *filter);
-int hbn_history_destroy(char *object);
+int hbn_history_set_limit(const char *object, int max_lines, long max_time);
+int hbn_history_add(const char *object, MessageTag *mtags, const char *line);
+HistoryResult *hbn_history_request(const char *object, HistoryFilter *filter);
+int hbn_history_destroy(const char *object);
MOD_INIT()
{
@@ -53,22 +53,22 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
-int hbn_history_add(char *object, MessageTag *mtags, char *line)
+int hbn_history_add(const char *object, MessageTag *mtags, const char *line)
{
return 1;
}
-HistoryResult *hbn_history_request(char *object, HistoryFilter *filter)
+HistoryResult *hbn_history_request(const char *object, HistoryFilter *filter)
{
return NULL;
}
-int hbn_history_set_limit(char *object, int max_lines, long max_time)
+int hbn_history_set_limit(const char *object, int max_lines, long max_time)
{
return 1;
}
-int hbn_history_destroy(char *object)
+int hbn_history_destroy(const char *object)
{
return 1;
}
diff --git a/src/modules/ident_lookup.c b/src/modules/ident_lookup.c
index 93ec0ed..c729bcc 100644
--- a/src/modules/ident_lookup.c
+++ b/src/modules/ident_lookup.c
@@ -10,7 +10,7 @@ ModuleHeader MOD_HEADER
"1.0",
"Ident lookups (RFC1413)",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Forward declarations */
@@ -43,7 +43,6 @@ MOD_UNLOAD()
static void ident_lookup_failed(Client *client)
{
- Debug((DEBUG_NOTICE, "ident_lookup_failed() for %p", client));
ircstats.is_abad++;
if (client->local->authfd != -1)
{
@@ -68,12 +67,12 @@ static EVENT(check_ident_timeout)
if (IsIdentLookupSent(client))
{
/* set::ident::connect-timeout */
- if ((TStime() - client->local->firsttime) > IDENT_CONNECT_TIMEOUT)
+ if ((TStime() - client->local->creationtime) > IDENT_CONNECT_TIMEOUT)
ident_lookup_failed(client);
} else
{
/* set::ident::read-timeout */
- if ((TStime() - client->local->firsttime) > IDENT_READ_TIMEOUT)
+ if ((TStime() - client->local->creationtime) > IDENT_READ_TIMEOUT)
ident_lookup_failed(client);
}
}
@@ -93,7 +92,8 @@ static int ident_lookup_connect(Client *client)
}
if (++OpenFiles >= maxclients+1)
{
- sendto_ops("Can't allocate fd, too many connections.");
+ unreal_log(ULOG_FATAL, "io", "IDENT_ERROR_MAXCLIENTS", client,
+ "Cannot do ident connection for $client.details: All connections in use");
fd_close(client->local->authfd);
--OpenFiles;
client->local->authfd = -1;
diff --git a/src/modules/invite.c b/src/modules/invite.c
index 906f5cc..feb99e3 100644
--- a/src/modules/invite.c
+++ b/src/modules/invite.c
@@ -22,9 +22,27 @@
#include "unrealircd.h"
+#define MSG_INVITE "INVITE"
+
+#define CLIENT_INVITES(client) (moddata_local_client(client, userInvitesMD).ptr)
+#define CHANNEL_INVITES(channel) (moddata_channel(channel, channelInvitesMD).ptr)
+
+ModDataInfo *userInvitesMD;
+ModDataInfo *channelInvitesMD;
+long CAP_INVITE_NOTIFY = 0L;
+int invite_always_notify = 0;
+
CMD_FUNC(cmd_invite);
-#define MSG_INVITE "INVITE"
+void invite_free(ModData *md);
+int invite_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs);
+int invite_config_run(ConfigFile *cf, ConfigEntry *ce, int type);
+void add_invite(Client *from, Client *to, Channel *channel, MessageTag *mtags);
+void del_invite(Client *client, Channel *channel);
+static int invite_channel_destroy(Channel *channel, int *should_destroy);
+int invite_user_quit(Client *client, MessageTag *mtags, const char *comment);
+int invite_user_join(Client *client, Channel *channel, MessageTag *mtags);
+int invite_is_invited(Client *client, Channel *channel, int *invited);
ModuleHeader MOD_HEADER
= {
@@ -32,13 +50,63 @@ ModuleHeader MOD_HEADER
"5.0",
"command /invite",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
+MOD_TEST()
+{
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, invite_config_test);
+ return MOD_SUCCESS;
+}
+
MOD_INIT()
{
- CommandAdd(modinfo->handle, MSG_INVITE, cmd_invite, MAXPARA, CMD_USER);
+ ClientCapabilityInfo cap;
+ ClientCapability *c;
+ ModDataInfo mreq;
+
MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ CommandAdd(modinfo->handle, MSG_INVITE, cmd_invite, MAXPARA, CMD_USER|CMD_SERVER);
+
+ memset(&cap, 0, sizeof(cap));
+ cap.name = "invite-notify";
+ c = ClientCapabilityAdd(modinfo->handle, &cap, &CAP_INVITE_NOTIFY);
+ if (!c)
+ {
+ config_error("[%s] Failed to request invite-notify cap: %s", MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle));
+ return MOD_FAILED;
+ }
+
+ memset(&mreq, 0 , sizeof(mreq));
+ mreq.type = MODDATATYPE_LOCAL_CLIENT;
+ mreq.name = "invite",
+ mreq.free = invite_free;
+ userInvitesMD = ModDataAdd(modinfo->handle, mreq);
+ if (!userInvitesMD)
+ {
+ config_error("[%s] Failed to request user invite moddata: %s", MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle));
+ return MOD_FAILED;
+ }
+
+ memset(&mreq, 0 , sizeof(mreq));
+ mreq.type = MODDATATYPE_CHANNEL;
+ mreq.name = "invite",
+ mreq.free = invite_free;
+ channelInvitesMD = ModDataAdd(modinfo->handle, mreq);
+ if (!channelInvitesMD)
+ {
+ config_error("[%s] Failed to request channel invite moddata: %s", MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle));
+ return MOD_FAILED;
+ }
+
+ invite_always_notify = 0; /* the default */
+ HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, invite_config_run);
+ HookAdd(modinfo->handle, HOOKTYPE_CHANNEL_DESTROY, 1000000, invite_channel_destroy);
+ HookAdd(modinfo->handle, HOOKTYPE_LOCAL_QUIT, 0, invite_user_quit);
+ HookAdd(modinfo->handle, HOOKTYPE_LOCAL_JOIN, 0, invite_user_join);
+ HookAdd(modinfo->handle, HOOKTYPE_IS_INVITED, 0, invite_is_invited);
+
return MOD_SUCCESS;
}
@@ -52,62 +120,252 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
+void invite_free(ModData *md)
+{
+ Link **inv, *tmp;
+
+ if (!md->ptr)
+ return; // was not set
+
+ for (inv = (Link **)md->ptr; (tmp = *inv); inv = &tmp->next)
+ {
+ *inv = tmp->next;
+ free_link(tmp);
+ }
+}
+
+int invite_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
+{
+ int errors = 0;
+
+ if (type != CONFIG_SET)
+ return 0;
+
+ if (!ce || !ce->name || strcmp(ce->name, "normal-user-invite-notification"))
+ return 0;
+
+ if (!ce->value)
+ {
+ config_error_empty(ce->file->filename, ce->line_number, "set", ce->name);
+ errors++;
+ }
+
+ *errs = errors;
+ return errors ? -1 : 1;
+}
+
+int invite_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
+{
+ ConfigEntry *cep;
+
+ if (type != CONFIG_SET)
+ return 0;
+
+ if (!ce || !ce->name || strcmp(ce->name, "normal-user-invite-notification"))
+ return 0;
+
+ invite_always_notify = config_checkval(ce->value, CFG_YESNO);
+
+ return 1;
+}
+
+static int invite_channel_destroy(Channel *channel, int *should_destroy)
+{
+ Link *lp;
+ while ((lp = CHANNEL_INVITES(channel)))
+ del_invite(lp->value.client, channel);
+ return 0;
+}
+
+int invite_user_quit(Client *client, MessageTag *mtags, const char *comment)
+{
+ Link *lp;
+ /* Clean up invitefield */
+ while ((lp = CLIENT_INVITES(client)))
+ del_invite(client, lp->value.channel);
+ return 0;
+}
+
+int invite_user_join(Client *client, Channel *channel, MessageTag *mtags)
+{
+ del_invite(client, channel);
+ return 0;
+}
+
/* Send the user their list of active invites */
void send_invite_list(Client *client)
{
Link *inv;
- for (inv = client->user->invited; inv; inv = inv->next)
+ for (inv = CLIENT_INVITES(client); inv; inv = inv->next)
{
sendnumeric(client, RPL_INVITELIST,
- inv->value.channel->chname);
+ inv->value.channel->name);
}
sendnumeric(client, RPL_ENDOFINVITELIST);
}
+int invite_is_invited(Client *client, Channel *channel, int *invited)
+{
+ Link *lp;
+
+ if (!MyConnect(client))
+ return 0; // not handling invite lists for remote clients
+
+ for (lp = CLIENT_INVITES(client); lp; lp = lp->next)
+ if (lp->value.channel == channel)
+ {
+ *invited = 1;
+ return 0;
+ }
+ return 0;
+}
+
+void invite_process(Client *client, Client *target, Channel *channel, MessageTag *recv_mtags, int override)
+{
+ MessageTag *mtags = NULL;
+
+ new_message(client, recv_mtags, &mtags);
+
+ /* broadcast to other servers */
+ sendto_server(client, 0, 0, mtags, ":%s INVITE %s %s %d", client->id, target->id, channel->name, override);
+
+ /* send chanops notifications */
+ if (IsUser(client) && (check_channel_access(client, channel, "oaq")
+ || IsULine(client)
+ || ValidatePermissionsForPath("channel:override:invite:self",client,NULL,channel,NULL)
+ || invite_always_notify
+ ))
+ {
+ if (override == 1)
+ {
+ sendto_channel(channel, &me, NULL, "o",
+ 0, SEND_LOCAL, mtags,
+ ":%s NOTICE @%s :OperOverride -- %s invited him/herself into the channel.",
+ me.name, channel->name, client->name);
+ }
+ if (override == 0)
+ {
+ sendto_channel(channel, &me, NULL, "o",
+ CAP_INVITE_NOTIFY | CAP_INVERT, SEND_LOCAL, mtags,
+ ":%s NOTICE @%s :%s invited %s into the channel.",
+ me.name, channel->name, client->name, target->name);
+ }
+ /* always send IRCv3 invite-notify if possible */
+ sendto_channel(channel, client, NULL, "o",
+ CAP_INVITE_NOTIFY, SEND_LOCAL, mtags,
+ ":%s INVITE %s %s",
+ client->name, target->name, channel->name);
+ }
+
+ /* add to list and notify the person who got invited */
+ if (MyConnect(target))
+ {
+ if (IsUser(client) && (check_channel_access(client, channel, "oaq")
+ || IsULine(client)
+ || ValidatePermissionsForPath("channel:override:invite:self",client,NULL,channel,NULL)
+ ))
+ {
+ add_invite(client, target, channel, mtags);
+ }
+
+ if (!is_silenced(client, target))
+ {
+ sendto_prefix_one(target, client, mtags, ":%s INVITE %s :%s", client->name,
+ target->name, channel->name);
+ }
+ }
+ free_message_tags(mtags);
+}
+
+void invite_operoverride_msg(Client *client, Channel *channel, char *override_mode, char *override_mode_text)
+{
+ unreal_log(ULOG_INFO, "operoverride", "OPEROVERRIDE_INVITE", client,
+ "OperOverride: $client.details invited him/herself into $channel (Overriding $override_mode_text)",
+ log_data_string("override_type", "join"),
+ log_data_string("override_mode", override_mode),
+ log_data_string("override_mode_text", override_mode_text),
+ log_data_channel("channel", channel));
+}
+
/*
** cmd_invite
** parv[1] - user to invite
-** parv[2] - channel number
+** parv[2] - channel name
+** parv[3] - override (S2S only)
*/
CMD_FUNC(cmd_invite)
{
- Client *target;
- Channel *channel;
+ Client *target = NULL;
+ Channel *channel = NULL;
int override = 0;
int i = 0;
+ int params_ok = 0;
Hook *h;
+ if (parc >= 3 && *parv[1] != '\0')
+ {
+ params_ok = 1;
+ target = find_user(parv[1], NULL);
+ channel = find_channel(parv[2]);
+ }
+
+ if (!MyConnect(client))
+ /*** remote invite ***/
+ {
+ if (!params_ok)
+ return;
+ /* the client or channel may be already gone */
+ if (!target)
+ {
+ sendnumeric(client, ERR_NOSUCHNICK, parv[1]);
+ return;
+ }
+ if (!channel)
+ {
+ sendnumeric(client, ERR_NOSUCHCHANNEL, parv[2]);
+ return;
+ }
+ if (parc >= 4 && !BadPtr(parv[3]))
+ {
+ override = atoi(parv[3]);
+ }
+
+ /* no further checks */
+
+ invite_process(client, target, channel, recv_mtags, override);
+ return;
+ }
+
+ /*** local invite ***/
+
+ /* the client requested own invite list */
if (parc == 1)
{
send_invite_list(client);
return;
}
-
- if (parc < 3 || *parv[1] == '\0')
+
+ /* notify user about bad parameters */
+ if (!params_ok)
{
sendnumeric(client, ERR_NEEDMOREPARAMS, "INVITE");
return;
}
- if (!(target = find_person(parv[1], NULL)))
+ if (!target)
{
sendnumeric(client, ERR_NOSUCHNICK, parv[1]);
return;
}
- if (MyConnect(client) && !valid_channelname(parv[2]))
- {
- sendnumeric(client, ERR_NOSUCHCHANNEL, parv[2]);
- return;
- }
-
- if (!(channel = find_channel(parv[2], NULL)))
+ if (!channel)
{
sendnumeric(client, ERR_NOSUCHCHANNEL, parv[2]);
return;
}
+ /* proceed with the command */
for (h = Hooks[HOOKTYPE_PRE_INVITE]; h; h = h->next)
{
i = (*(h->func.intfunc))(client,target,channel,&override);
@@ -134,15 +392,15 @@ CMD_FUNC(cmd_invite)
return;
}
- if (channel->mode.mode & MODE_INVITEONLY)
+ if (has_channel_mode(channel, 'i'))
{
- if (!is_chan_op(client, channel) && !IsULine(client))
+ if (!check_channel_access(client, channel, "oaq") && !IsULine(client))
{
if (ValidatePermissionsForPath("channel:override:invite:invite-only",client,NULL,channel,NULL) && client == target)
{
override = 1;
} else {
- sendnumeric(client, ERR_CHANOPRIVSNEEDED, channel->chname);
+ sendnumeric(client, ERR_CHANOPRIVSNEEDED, channel->name);
return;
}
}
@@ -152,100 +410,52 @@ CMD_FUNC(cmd_invite)
{
override = 1;
} else {
- sendnumeric(client, ERR_CHANOPRIVSNEEDED, channel->chname);
+ sendnumeric(client, ERR_CHANOPRIVSNEEDED, channel->name);
return;
}
}
}
if (SPAMFILTER_VIRUSCHANDENY && SPAMFILTER_VIRUSCHAN &&
- !strcasecmp(channel->chname, SPAMFILTER_VIRUSCHAN) &&
- !is_chan_op(client, channel) && !ValidatePermissionsForPath("immune:server-ban:viruschan",client,NULL,NULL,NULL))
+ !strcasecmp(channel->name, SPAMFILTER_VIRUSCHAN) &&
+ !check_channel_access(client, channel, "oaq") && !ValidatePermissionsForPath("immune:server-ban:viruschan",client,NULL,NULL,NULL))
{
- sendnumeric(client, ERR_CHANOPRIVSNEEDED, channel->chname);
+ sendnumeric(client, ERR_CHANOPRIVSNEEDED, channel->name);
return;
}
- if (MyUser(client))
+ if (target_limit_exceeded(client, target, target->name))
+ return;
+
+ if (!ValidatePermissionsForPath("immune:invite-flood",client,NULL,NULL,NULL) &&
+ flood_limit_exceeded(client, FLD_INVITE))
{
- if (target_limit_exceeded(client, target, target->name))
- return;
-
- if (!ValidatePermissionsForPath("immune:invite-flood",client,NULL,NULL,NULL) &&
- flood_limit_exceeded(client, FLD_INVITE))
- {
- sendnumeric(client, RPL_TRYAGAIN, "INVITE");
- return;
- }
-
- if (!override)
- {
- sendnumeric(client, RPL_INVITING, target->name, channel->chname);
- if (target->user->away)
- {
- sendnumeric(client, RPL_AWAY, target->name, target->user->away);
- }
- }
+ sendnumeric(client, RPL_TRYAGAIN, "INVITE");
+ return;
}
- /* Send OperOverride messages */
- if (override && MyConnect(target))
+ if (!override)
{
+ sendnumeric(client, RPL_INVITING, target->name, channel->name);
+ if (target->user->away)
+ {
+ sendnumeric(client, RPL_AWAY, target->name, target->user->away);
+ }
+ }
+ else
+ {
+ /* Send OperOverride messages */
+ char override_what = '\0';
if (is_banned(client, channel, BANCHK_JOIN, NULL, NULL))
- {
- sendto_snomask_global(SNO_EYES,
- "*** OperOverride -- %s (%s@%s) invited him/herself into %s (overriding +b).",
- client->name, client->user->username, client->user->realhost, channel->chname);
-
- /* Logging implementation added by XeRXeS */
- ircd_log(LOG_OVERRIDE,"OVERRIDE: %s (%s@%s) invited him/herself into %s (Overriding Ban).",
- client->name, client->user->username, client->user->realhost, channel->chname);
-
- }
- else if (channel->mode.mode & MODE_INVITEONLY)
- {
- sendto_snomask_global(SNO_EYES,
- "*** OperOverride -- %s (%s@%s) invited him/herself into %s (overriding +i).",
- client->name, client->user->username, client->user->realhost, channel->chname);
-
- /* Logging implementation added by XeRXeS */
- ircd_log(LOG_OVERRIDE,"OVERRIDE: %s (%s@%s) invited him/herself into %s (Overriding Invite Only)",
- client->name, client->user->username, client->user->realhost, channel->chname);
-
- }
- else if (channel->mode.limit)
- {
- sendto_snomask_global(SNO_EYES,
- "*** OperOverride -- %s (%s@%s) invited him/herself into %s (overriding +l).",
- client->name, client->user->username, client->user->realhost, channel->chname);
-
- /* Logging implementation added by XeRXeS */
- ircd_log(LOG_OVERRIDE,"OVERRIDE: %s (%s@%s) invited him/herself into %s (Overriding Limit)",
- client->name, client->user->username, client->user->realhost, channel->chname);
-
- }
-
- else if (*channel->mode.key)
- {
- sendto_snomask_global(SNO_EYES,
- "*** OperOverride -- %s (%s@%s) invited him/herself into %s (overriding +k).",
- client->name, client->user->username, client->user->realhost, channel->chname);
-
- /* Logging implementation added by XeRXeS */
- ircd_log(LOG_OVERRIDE,"OVERRIDE: %s (%s@%s) invited him/herself into %s (Overriding Key)",
- client->name, client->user->username, client->user->realhost, channel->chname);
-
- }
+ invite_operoverride_msg(client, channel, "b", "ban");
+ else if (has_channel_mode(channel, 'i'))
+ invite_operoverride_msg(client, channel, "i", "invite only");
+ else if (has_channel_mode(channel, 'l'))
+ invite_operoverride_msg(client, channel, "l", "user limit");
+ else if (has_channel_mode(channel, 'k'))
+ invite_operoverride_msg(client, channel, "k", "key");
else if (has_channel_mode(channel, 'z'))
- {
- sendto_snomask_global(SNO_EYES,
- "*** OperOverride -- %s (%s@%s) invited him/herself into %s (overriding +z).",
- client->name, client->user->username, client->user->realhost, channel->chname);
-
- /* Logging implementation added by XeRXeS */
- ircd_log(LOG_OVERRIDE,"OVERRIDE: %s (%s@%s) invited him/herself into %s (Overriding SSL/TLS-Only)",
- client->name, client->user->username, client->user->realhost, channel->chname);
- }
+ invite_operoverride_msg(client, channel, "z", "secure only");
#ifdef OPEROVERRIDE_VERIFY
else if (channel->mode.mode & MODE_SECRET || channel->mode.mode & MODE_PRIVATE)
override = -1;
@@ -254,40 +464,79 @@ CMD_FUNC(cmd_invite)
return;
}
- if (MyConnect(target))
- {
- if (IsUser(client)
- && (is_chan_op(client, channel)
- || IsULine(client)
- || ValidatePermissionsForPath("channel:override:invite:self",client,NULL,channel,NULL)
- ))
- {
- MessageTag *mtags = NULL;
-
- new_message(&me, NULL, &mtags);
- if (override == 1)
- {
- sendto_channel(channel, &me, NULL, PREFIX_OP|PREFIX_ADMIN|PREFIX_OWNER,
- 0, SEND_ALL, mtags,
- ":%s NOTICE @%s :OperOverride -- %s invited him/herself into the channel.",
- me.name, channel->chname, client->name);
- } else
- if (override == 0)
- {
- sendto_channel(channel, &me, NULL, PREFIX_OP|PREFIX_ADMIN|PREFIX_OWNER,
- 0, SEND_ALL, mtags,
- ":%s NOTICE @%s :%s invited %s into the channel.",
- me.name, channel->chname, client->name, target->name);
- }
- add_invite(client, target, channel, mtags);
- free_message_tags(mtags);
- }
- }
-
- /* Notify the person who got invited */
- if (!is_silenced(client, target))
- {
- sendto_prefix_one(target, client, NULL, ":%s INVITE %s :%s", client->name,
- target->name, channel->chname);
- }
+ /* allowed to proceed */
+ invite_process(client, target, channel, recv_mtags, override);
}
+
+/** Register an invite from someone to a channel - so they can bypass +i etc.
+ * @param from The person sending the invite
+ * @param to The person who is invited to join
+ * @param channel The channel
+ * @param mtags Message tags associated with this INVITE command
+ */
+void add_invite(Client *from, Client *to, Channel *channel, MessageTag *mtags)
+{
+ Link *inv, *tmp;
+
+ del_invite(to, channel);
+ /* If too many invite entries then delete the oldest one */
+ if (link_list_length(CLIENT_INVITES(to)) >= MAXCHANNELSPERUSER)
+ {
+ for (tmp = CLIENT_INVITES(to); tmp->next; tmp = tmp->next)
+ ;
+ del_invite(to, tmp->value.channel);
+
+ }
+ /* We get pissy over too many invites per channel as well now,
+ * since otherwise mass-inviters could take up some major
+ * resources -Donwulff
+ */
+ if (link_list_length(CHANNEL_INVITES(channel)) >= MAXCHANNELSPERUSER)
+ {
+ for (tmp = CHANNEL_INVITES(channel); tmp->next; tmp = tmp->next)
+ ;
+ del_invite(tmp->value.client, channel);
+ }
+ /*
+ * add client to the beginning of the channel invite list
+ */
+ inv = make_link();
+ inv->value.client = to;
+ inv->next = CHANNEL_INVITES(channel);
+ CHANNEL_INVITES(channel) = inv;
+ /*
+ * add channel to the beginning of the client invite list
+ */
+ inv = make_link();
+ inv->value.channel = channel;
+ inv->next = CLIENT_INVITES(to);
+ CLIENT_INVITES(to) = inv;
+
+ RunHook(HOOKTYPE_INVITE, from, to, channel, mtags);
+}
+
+/** Delete a previous invite of someone to a channel.
+ * @param client The client who was invited
+ * @param channel The channel to which the person was invited
+ */
+void del_invite(Client *client, Channel *channel)
+{
+ Link **inv, *tmp;
+
+ for (inv = (Link **)&CHANNEL_INVITES(channel); (tmp = *inv); inv = &tmp->next)
+ if (tmp->value.client == client)
+ {
+ *inv = tmp->next;
+ free_link(tmp);
+ break;
+ }
+
+ for (inv = (Link **)&CLIENT_INVITES(client); (tmp = *inv); inv = &tmp->next)
+ if (tmp->value.channel == channel)
+ {
+ *inv = tmp->next;
+ free_link(tmp);
+ break;
+ }
+}
+
diff --git a/src/modules/ircops.c b/src/modules/ircops.c
index 352208a..4b71eb0 100644
--- a/src/modules/ircops.c
+++ b/src/modules/ircops.c
@@ -31,7 +31,7 @@ ModuleHeader MOD_HEADER
"3.71",
"/IRCOPS command that lists IRC Operators",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
diff --git a/src/modules/ison.c b/src/modules/ison.c
index 69ce42d..928810c 100644
--- a/src/modules/ison.c
+++ b/src/modules/ison.c
@@ -32,7 +32,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /ison",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
@@ -66,6 +66,7 @@ static char buf[BUFSIZE];
CMD_FUNC(cmd_ison)
{
+ char request[BUFSIZE];
char namebuf[USERLEN + HOSTLEN + 4];
Client *acptr;
char *s, *user;
@@ -82,11 +83,12 @@ CMD_FUNC(cmd_ison)
ircsnprintf(buf, sizeof(buf), ":%s %d %s :", me.name, RPL_ISON, client->name);
- for (s = strtoken(&p, parv[1], " "); s; s = strtoken(&p, NULL, " "))
+ strlcpy(request, parv[1], sizeof(request));
+ for (s = strtoken(&p, request, " "); s; s = strtoken(&p, NULL, " "))
{
if ((user = strchr(s, '!')))
*user++ = '\0';
- if ((acptr = find_person(s, NULL)))
+ if ((acptr = find_user(s, NULL)))
{
if (user)
{
diff --git a/src/modules/join.c b/src/modules/join.c
index 334256e..37610b8 100644
--- a/src/modules/join.c
+++ b/src/modules/join.c
@@ -24,12 +24,12 @@
/* Forward declarations */
CMD_FUNC(cmd_join);
-void _join_channel(Channel *channel, Client *client, MessageTag *mtags, int flags);
-void _do_join(Client *client, int parc, char *parv[]);
-int _can_join(Client *client, Channel *channel, char *key, char *parv[]);
-void _userhost_save_current(Client *client);
-void _userhost_changed(Client *client);
+void _join_channel(Channel *channel, Client *client, MessageTag *mtags, const char *member_modes);
+void _do_join(Client *client, int parc, const char *parv[]);
+int _can_join(Client *client, Channel *channel, const char *key, char **errmsg);
void _send_join_to_local_users(Client *client, Channel *channel, MessageTag *mtags);
+char *_get_chmodes_for_user(Client *client, const char *flags);
+void send_cannot_join_error(Client *client, int numeric, char *fmtstr, char *channel_name);
/* Externs */
extern MODVAR int spamf_ugly_vchanoverride;
@@ -37,6 +37,7 @@ extern int find_invex(Channel *channel, Client *client);
/* Local vars */
static int bouncedtimes = 0;
+long CAP_EXTENDED_JOIN = 0L;
/* Macros */
#define MAXBOUNCE 5 /** Most sensible */
@@ -48,7 +49,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /join",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_TEST()
@@ -57,15 +58,19 @@ MOD_TEST()
EfunctionAddVoid(modinfo->handle, EFUNC_JOIN_CHANNEL, _join_channel);
EfunctionAddVoid(modinfo->handle, EFUNC_DO_JOIN, _do_join);
EfunctionAdd(modinfo->handle, EFUNC_CAN_JOIN, _can_join);
- EfunctionAddVoid(modinfo->handle, EFUNC_USERHOST_SAVE_CURRENT, _userhost_save_current);
- EfunctionAddVoid(modinfo->handle, EFUNC_USERHOST_CHANGED, _userhost_changed);
EfunctionAddVoid(modinfo->handle, EFUNC_SEND_JOIN_TO_LOCAL_USERS, _send_join_to_local_users);
+ EfunctionAddPVoid(modinfo->handle, EFUNC_GET_CHMODES_FOR_USER, TO_PVOIDFUNC(_get_chmodes_for_user));
return MOD_SUCCESS;
}
MOD_INIT()
{
+ ClientCapabilityInfo c;
+ memset(&c, 0, sizeof(c));
+ c.name = "extended-join";
+ ClientCapabilityAdd(modinfo->handle, &c, &CAP_EXTENDED_JOIN);
+
CommandAdd(modinfo->handle, MSG_JOIN, cmd_join, MAXPARA, CMD_USER);
MARK_AS_OFFICIAL_MODULE(modinfo);
return MOD_SUCCESS;
@@ -87,7 +92,7 @@ MOD_UNLOAD()
* (eg: bans at the end), so don't change it unless you have a good reason
* to do so -- Syzop.
*/
-int _can_join(Client *client, Channel *channel, char *key, char *parv[])
+int _can_join(Client *client, Channel *channel, const char *key, char **errmsg)
{
Link *lp;
Ban *banned;
@@ -96,7 +101,7 @@ int _can_join(Client *client, Channel *channel, char *key, char *parv[])
for (h = Hooks[HOOKTYPE_CAN_JOIN]; h; h = h->next)
{
- i = (*(h->func.intfunc))(client,channel,key,parv);
+ i = (*(h->func.intfunc))(client,channel,key, errmsg);
if (i != 0)
return i;
}
@@ -111,47 +116,32 @@ int _can_join(Client *client, Channel *channel, char *key, char *parv[])
/* See if we can evade this ban */
banned = is_banned(client, channel, BANCHK_JOIN, NULL, NULL);
if (banned && j == HOOK_DENY)
- return (ERR_BANNEDFROMCHAN);
+ {
+ *errmsg = STR_ERR_BANNEDFROMCHAN;
+ return ERR_BANNEDFROMCHAN;
+ }
if (is_invited(client, channel))
- return 0; /* allowed */
+ return 0; /* allowed to walk through all the other modes */
- if (channel->users >= channel->mode.limit)
- {
- /* Hmmm.. don't really like this.. and not at this place */
-
- for (h = Hooks[HOOKTYPE_CAN_JOIN_LIMITEXCEEDED]; h; h = h->next)
- {
- i = (*(h->func.intfunc))(client,channel,key,parv);
- if (i != 0)
- return i;
- }
-
- /* We later check again for this limit (in case +L was not set) */
- }
-
-
- if (*channel->mode.key && (BadPtr(key) || strcmp(channel->mode.key, key)))
- return (ERR_BADCHANNELKEY);
-
- if ((channel->mode.mode & MODE_INVITEONLY) && !find_invex(channel, client))
- return (ERR_INVITEONLYCHAN);
-
- if ((channel->mode.limit && channel->users >= channel->mode.limit))
- return (ERR_CHANNELISFULL);
-
- if (banned)
- return (ERR_BANNEDFROMCHAN);
+ if (banned)
+ {
+ *errmsg = STR_ERR_BANNEDFROMCHAN;
+ return ERR_BANNEDFROMCHAN;
+ }
#ifndef NO_OPEROVERRIDE
#ifdef OPEROVERRIDE_VERIFY
- if (ValidatePermissionsForPath("channel:override:privsecret",client,NULL,channel,NULL) && (channel->mode.mode & MODE_SECRET ||
- channel->mode.mode & MODE_PRIVATE) && !is_autojoin_chan(channel->chname))
- return (ERR_OPERSPVERIFY);
+ if (ValidatePermissionsForPath("channel:override:privsecret",client,NULL,channel,NULL) && (channel->mode.mode & MODE_SECRET ||
+ channel->mode.mode & MODE_PRIVATE) && !is_autojoin_chan(channel->name))
+ {
+ *errmsg = STR_ERR_OPERSPVERIFY;
+ return (ERR_OPERSPVERIFY);
+ }
#endif
#endif
- return 0;
+ return 0;
}
/*
@@ -170,7 +160,12 @@ CMD_FUNC(cmd_join)
int r;
if (bouncedtimes)
- sendto_realops("join: bouncedtimes=%d??? [please report at https://bugs.unrealircd.org/]", bouncedtimes);
+ {
+ unreal_log(ULOG_ERROR, "join", "BUG_JOIN_BOUNCEDTIMES", NULL,
+ "[BUG] join: bouncedtimes is not initialized to zero ($bounced_times)!! "
+ "Please report at https://bugs.unrealircd.org/",
+ log_data_integer("bounced_times", bouncedtimes));
+ }
bouncedtimes = 0;
if (IsServer(client))
@@ -190,15 +185,13 @@ void _send_join_to_local_users(Client *client, Channel *channel, MessageTag *mta
Client *acptr;
char joinbuf[512];
char exjoinbuf[512];
- long CAP_EXTENDED_JOIN = ClientCapabilityBit("extended-join");
- long CAP_AWAY_NOTIFY = ClientCapabilityBit("away-notify");
ircsnprintf(joinbuf, sizeof(joinbuf), ":%s!%s@%s JOIN :%s",
- client->name, client->user->username, GetHost(client), channel->chname);
+ client->name, client->user->username, GetHost(client), channel->name);
ircsnprintf(exjoinbuf, sizeof(exjoinbuf), ":%s!%s@%s JOIN %s %s :%s",
- client->name, client->user->username, GetHost(client), channel->chname,
- !isdigit(*client->user->svid) ? client->user->svid : "*",
+ client->name, client->user->username, GetHost(client), channel->name,
+ IsLoggedIn(client) ? client->user->account : "*",
client->info);
for (lp = channel->members; lp; lp = lp->next)
@@ -208,46 +201,37 @@ void _send_join_to_local_users(Client *client, Channel *channel, MessageTag *mta
if (!MyConnect(acptr))
continue; /* only locally connected clients */
- if (chanops_only && !(lp->flags & (CHFL_HALFOP|CHFL_CHANOP|CHFL_CHANOWNER|CHFL_CHANADMIN)) && (client != acptr))
+ if (chanops_only && !check_channel_access_member(lp, "hoaq") && (client != acptr))
continue; /* skip non-ops if requested to (used for mode +D), but always send to 'client' */
if (HasCapabilityFast(acptr, CAP_EXTENDED_JOIN))
sendto_one(acptr, mtags, "%s", exjoinbuf);
else
sendto_one(acptr, mtags, "%s", joinbuf);
-
- if (client->user->away && HasCapabilityFast(acptr, CAP_AWAY_NOTIFY))
- {
- MessageTag *mtags_away = NULL;
- new_message(client, NULL, &mtags_away);
- sendto_one(acptr, mtags_away, ":%s!%s@%s AWAY :%s",
- client->name, client->user->username, GetHost(client), client->user->away);
- free_message_tags(mtags_away);
- }
}
}
/* Routine that actually makes a user join the channel
* this does no actual checking (banned, etc.) it just adds the user
*/
-void _join_channel(Channel *channel, Client *client, MessageTag *recv_mtags, int flags)
+void _join_channel(Channel *channel, Client *client, MessageTag *recv_mtags, const char *member_modes)
{
MessageTag *mtags = NULL; /** Message tags to send to local users (sender is :user) */
MessageTag *mtags_sjoin = NULL; /* Message tags to send to remote servers for SJOIN (sender is :me.id) */
- char *parv[] = { 0, 0 };
+ const char *parv[3];
/* Same way as in SJOIN */
- new_message_special(client, recv_mtags, &mtags, ":%s JOIN %s", client->name, channel->chname);
+ new_message_special(client, recv_mtags, &mtags, ":%s JOIN %s", client->name, channel->name);
new_message(&me, recv_mtags, &mtags_sjoin);
- add_user_to_channel(channel, client, flags);
+ add_user_to_channel(channel, client, member_modes);
send_join_to_local_users(client, channel, mtags);
sendto_server(client, 0, 0, mtags_sjoin, ":%s SJOIN %lld %s :%s%s ",
me.id, (long long)channel->creationtime,
- channel->chname, chfl_to_sjoin_symbol(flags), client->id);
+ channel->name, modes_to_sjoin_prefix(member_modes), client->id);
if (MyUser(client))
{
@@ -260,56 +244,63 @@ void _join_channel(Channel *channel, Client *client, MessageTag *recv_mtags, int
{
channel->creationtime = TStime();
sendto_server(client, 0, 0, NULL, ":%s MODE %s + %lld",
- me.id, channel->chname, (long long)channel->creationtime);
+ me.id, channel->name, (long long)channel->creationtime);
}
- del_invite(client, channel);
if (channel->topic)
{
- sendnumeric(client, RPL_TOPIC, channel->chname, channel->topic);
- sendnumeric(client, RPL_TOPICWHOTIME, channel->chname, channel->topic_nick,
- channel->topic_time);
+ sendnumeric(client, RPL_TOPIC, channel->name, channel->topic);
+ sendnumeric(client, RPL_TOPICWHOTIME, channel->name, channel->topic_nick, (long long)channel->topic_time);
}
/* Set default channel modes (set::modes-on-join).
* Set only if it's the 1st user and only if no other modes have been set
* already (eg: +P, permanent).
*/
- if ((channel->users == 1) && !channel->mode.mode && !channel->mode.extmode &&
- (MODES_ON_JOIN || iConf.modes_on_join.extmodes))
+ if ((channel->users == 1) && !channel->mode.mode && MODES_ON_JOIN)
{
- int i;
MessageTag *mtags_mode = NULL;
-
- channel->mode.extmode = iConf.modes_on_join.extmodes;
- /* Param fun */
- for (i = 0; i <= Channelmode_highest; i++)
- {
- if (!Channelmode_Table[i].flag || !Channelmode_Table[i].paracount)
- continue;
- if (channel->mode.extmode & Channelmode_Table[i].mode)
- cm_putparameter(channel, Channelmode_Table[i].flag, iConf.modes_on_join.extparams[i]);
- }
+ Cmode *cm;
+ char modebuf[BUFSIZE], parabuf[BUFSIZE];
channel->mode.mode = MODES_ON_JOIN;
+ /* Param fun */
+ for (cm=channelmodes; cm; cm = cm->next)
+ {
+ if (!cm->letter || !cm->paracount)
+ continue;
+ if (channel->mode.mode & cm->mode)
+ cm_putparameter(channel, cm->letter, iConf.modes_on_join.extparams[cm->letter]);
+ }
+
*modebuf = *parabuf = 0;
- channel_modes(client, modebuf, parabuf, sizeof(modebuf), sizeof(parabuf), channel);
+ channel_modes(client, modebuf, parabuf, sizeof(modebuf), sizeof(parabuf), channel, 0);
/* This should probably be in the SJOIN stuff */
- new_message_special(&me, recv_mtags, &mtags_mode, ":%s MODE %s %s %s", me.name, channel->chname, modebuf, parabuf);
+ new_message_special(&me, recv_mtags, &mtags_mode, ":%s MODE %s %s %s", me.name, channel->name, modebuf, parabuf);
sendto_server(NULL, 0, 0, mtags_mode, ":%s MODE %s %s %s %lld",
- me.id, channel->chname, modebuf, parabuf, (long long)channel->creationtime);
- sendto_one(client, mtags_mode, ":%s MODE %s %s %s", me.name, channel->chname, modebuf, parabuf);
+ me.id, channel->name, modebuf, parabuf, (long long)channel->creationtime);
+ sendto_one(client, mtags_mode, ":%s MODE %s %s %s", me.name, channel->name, modebuf, parabuf);
free_message_tags(mtags_mode);
}
- parv[0] = client->name;
- parv[1] = channel->chname;
+ parv[0] = NULL;
+ parv[1] = channel->name;
+ parv[2] = NULL;
do_cmd(client, NULL, "NAMES", 2, parv);
- RunHook4(HOOKTYPE_LOCAL_JOIN, client, channel, mtags, parv);
+ unreal_log(ULOG_INFO, "join", "LOCAL_CLIENT_JOIN", client,
+ "User $client joined $channel",
+ log_data_channel("channel", channel),
+ log_data_string("modes", member_modes));
+
+ RunHook(HOOKTYPE_LOCAL_JOIN, client, channel, mtags);
} else {
- RunHook4(HOOKTYPE_REMOTE_JOIN, client, channel, mtags, parv);
+ unreal_log(ULOG_INFO, "join", "REMOTE_CLIENT_JOIN", client,
+ "User $client joined $channel",
+ log_data_channel("channel", channel),
+ log_data_string("modes", member_modes));
+ RunHook(HOOKTYPE_REMOTE_JOIN, client, channel, mtags);
}
free_message_tags(mtags);
@@ -323,18 +314,21 @@ void _join_channel(Channel *channel, Client *client, MessageTag *recv_mtags, int
* increased every time we enter this loop and decreased anytime we leave the
* loop. So be carefull not to use a simple 'return' after bouncedtimes++. -- Syzop
*/
-void _do_join(Client *client, int parc, char *parv[])
+void _do_join(Client *client, int parc, const char *parv[])
{
+ char request[BUFSIZE];
+ char request_key[BUFSIZE];
char jbuf[BUFSIZE], jbuf2[BUFSIZE];
- char *orig_parv1;
+ const char *orig_parv1;
Membership *lp;
Channel *channel;
char *name, *key = NULL;
- int i, flags = 0, ishold;
+ int i, ishold;
char *p = NULL, *p2 = NULL;
TKL *tklban;
int ntargets = 0;
int maxtargets = max_targets_for_command("JOIN");
+ const char *member_modes = "";
#define RET() do { bouncedtimes--; parv[1] = orig_parv1; return; } while(0)
@@ -343,6 +337,11 @@ void _do_join(Client *client, int parc, char *parv[])
sendnumeric(client, ERR_NEEDMOREPARAMS, "JOIN");
return;
}
+
+ /* For our tests we need super accurate time for JOINs or they mail fail. */
+ gettimeofday(&timeofday_tv, NULL);
+ timeofday = timeofday_tv.tv_sec;
+
bouncedtimes++;
orig_parv1 = parv[1];
/* don't use 'return;' but 'RET();' from here ;p */
@@ -359,9 +358,8 @@ void _do_join(Client *client, int parc, char *parv[])
** Rebuild list of channels joined to be the actual result of the
** JOIN. Note that "JOIN 0" is the destructive problem.
*/
- for (i = 0, name = strtoken(&p, parv[1], ",");
- name;
- i++, name = strtoken(&p, NULL, ","))
+ strlcpy(request, parv[1], sizeof(request));
+ for (i = 0, name = strtoken(&p, request, ","); name; i++, name = strtoken(&p, NULL, ","))
{
if (MyUser(client) && (++ntargets > maxtargets))
{
@@ -370,7 +368,7 @@ void _do_join(Client *client, int parc, char *parv[])
}
if (*name == '0' && !atoi(name))
{
- /* UnrealIRCd 5: we only support "JOIN 0",
+ /* UnrealIRCd 5+: we only support "JOIN 0",
* "JOIN 0,#somechan" etc... so only at the beginning.
* We do not support it half-way like "JOIN #a,0,#b"
* since that doesn't make sense, unless you are flooding...
@@ -384,7 +382,7 @@ void _do_join(Client *client, int parc, char *parv[])
if (MyConnect(client) && !valid_channelname(name))
{
send_invalid_channelname(client, name);
- if (IsOper(client) && find_channel(name, NULL))
+ if (IsOper(client) && find_channel(name))
{
/* Give IRCOps a bit more information */
sendnotice(client, "Channel '%s' is unjoinable because it contains illegal characters. "
@@ -415,7 +413,10 @@ void _do_join(Client *client, int parc, char *parv[])
p = NULL;
if (parv[2])
- key = strtoken(&p2, parv[2], ",");
+ {
+ strlcpy(request_key, parv[2], sizeof(request_key));
+ key = strtoken(&p2, request_key, ",");
+ }
parv[2] = NULL; /* for cmd_names call later, parv[parc] must == NULL */
for (name = strtoken(&p, jbuf, ",");
@@ -442,13 +443,13 @@ void _do_join(Client *client, int parc, char *parv[])
sendto_channel(channel, client, NULL, 0, 0, SEND_LOCAL, mtags,
":%s PART %s :%s",
- client->name, channel->chname, "Left all channels");
- sendto_server(client, 0, 0, mtags, ":%s PART %s :Left all channels", client->name, channel->chname);
+ client->name, channel->name, "Left all channels");
+ sendto_server(client, 0, 0, mtags, ":%s PART %s :Left all channels", client->name, channel->name);
if (MyConnect(client))
- RunHook4(HOOKTYPE_LOCAL_PART, client, channel, mtags, "Left all channels");
+ RunHook(HOOKTYPE_LOCAL_PART, client, channel, mtags, "Left all channels");
- remove_user_from_channel(client, channel);
+ remove_user_from_channel(client, channel, 0);
free_message_tags(mtags);
}
continue;
@@ -456,19 +457,7 @@ void _do_join(Client *client, int parc, char *parv[])
if (MyConnect(client))
{
- /*
- ** local client is first to enter previously nonexistant
- ** channel so make them (rightfully) the Channel
- ** Operator.
- */
- /* Where did this come from? Potvin ? --Stskeeps
- flags = (ChannelExists(name)) ? CHFL_DEOPPED :
- CHFL_CHANOWNER;
-
- */
-
- flags =
- (ChannelExists(name)) ? CHFL_DEOPPED : LEVEL_ON_JOIN;
+ member_modes = (ChannelExists(name)) ? "" : LEVEL_ON_JOIN;
if (!ValidatePermissionsForPath("immune:maxchannelsperuser",client,NULL,NULL,NULL)) /* opers can join unlimited chans */
if (client->user->joined >= MAXCHANNELSPERUSER)
@@ -486,8 +475,9 @@ void _do_join(Client *client, int parc, char *parv[])
{
if (d->warn)
{
- sendto_snomask(SNO_EYES, "*** %s tried to join forbidden channel %s",
- get_client_name(client, 1), name);
+ unreal_log(ULOG_INFO, "join", "JOIN_DENIED_FORBIDDEN_CHANNEL", client,
+ "Client $client.details tried to join forbidden channel $channel",
+ log_data_string("channel", name));
}
if (d->reason)
sendnumeric(client, ERR_FORBIDDENCHANNEL, name, d->reason);
@@ -514,7 +504,7 @@ void _do_join(Client *client, int parc, char *parv[])
!strcasecmp(name, SPAMFILTER_VIRUSCHAN) &&
!ValidatePermissionsForPath("immune:server-ban:viruschan",client,NULL,NULL,NULL) && !spamf_ugly_vchanoverride)
{
- Channel *channel = find_channel(name, NULL);
+ Channel *channel = find_channel(name);
if (!channel || !is_invited(client, channel))
{
@@ -525,7 +515,7 @@ void _do_join(Client *client, int parc, char *parv[])
}
}
- channel = get_channel(client, name, CREATE);
+ channel = make_channel(name);
if (channel && (lp = find_membership_link(client->user->channel, channel)))
continue;
@@ -534,23 +524,14 @@ void _do_join(Client *client, int parc, char *parv[])
i = HOOK_CONTINUE;
if (!MyConnect(client))
- flags = CHFL_DEOPPED;
+ member_modes = "";
else
{
Hook *h;
+ char *errmsg = NULL;
for (h = Hooks[HOOKTYPE_PRE_LOCAL_JOIN]; h; h = h->next)
{
- /* Note: this is just a hack not to break the ABI but still be
- * able to fix https://bugs.unrealircd.org/view.php?id=5644
- * In the future we should just drop the parv/parx argument
- * and use key as an argument instead.
- */
- char *parx[4];
- parx[0] = NULL;
- parx[1] = name;
- parx[2] = key;
- parx[3] = NULL;
- i = (*(h->func.intfunc))(client,channel,parx);
+ i = (*(h->func.intfunc))(client,channel,key);
if (i == HOOK_DENY || i == HOOK_ALLOW)
break;
}
@@ -564,12 +545,10 @@ void _do_join(Client *client, int parc, char *parv[])
}
/* If they are allowed, don't check can_join */
if (i != HOOK_ALLOW &&
- (i = can_join(client, channel, key, parv)))
+ (i = can_join(client, channel, key, &errmsg)))
{
if (i != -1)
- {
- sendnumeric(client, i, name);
- }
+ send_cannot_join_error(client, i, errmsg, name);
continue;
}
}
@@ -585,43 +564,42 @@ void _do_join(Client *client, int parc, char *parv[])
* and so on, each with their own unique msgid and such.
*/
new_message(client, NULL, &mtags);
- join_channel(channel, client, mtags, flags);
+ join_channel(channel, client, mtags, member_modes);
free_message_tags(mtags);
}
RET();
#undef RET
}
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+#endif
+void send_cannot_join_error(Client *client, int numeric, char *fmtstr, char *channel_name)
+{
+ // TODO: add single %s validation !
+ sendnumericfmt(client, numeric, fmtstr, channel_name);
+}
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
/* Additional channel-related functions. I've put it here instead
* of the core so it could be upgraded on the fly should it be necessary.
*/
-char *get_chmodes_for_user(Client *client, int flags)
+char *_get_chmodes_for_user(Client *client, const char *member_flags)
{
static char modebuf[512]; /* returned */
char flagbuf[8]; /* For holding "vhoaq" */
- char *p = flagbuf;
char parabuf[512];
int n, i;
- if (!flags)
+ if (BadPtr(member_flags))
return "";
- if (flags & MODE_CHANOWNER)
- *p++ = 'q';
- if (flags & MODE_CHANADMIN)
- *p++ = 'a';
- if (flags & MODE_CHANOP)
- *p++ = 'o';
- if (flags & MODE_VOICE)
- *p++ = 'v';
- if (flags & MODE_HALFOP)
- *p++ = 'h';
- *p = '\0';
-
parabuf[0] = '\0';
-
- n = strlen(flagbuf);
+ n = strlen(member_flags);
if (n)
{
for (i=0; i < n; i++)
@@ -631,182 +609,9 @@ char *get_chmodes_for_user(Client *client, int flags)
strlcat(parabuf, " ", sizeof(parabuf));
}
/* And we have our mode line! */
- snprintf(modebuf, sizeof(modebuf), "+%s %s", flagbuf, parabuf);
+ snprintf(modebuf, sizeof(modebuf), "+%s %s", member_flags, parabuf);
return modebuf;
}
return "";
}
-
-static char remember_nick[NICKLEN+1];
-static char remember_user[USERLEN+1];
-static char remember_host[HOSTLEN+1];
-
-/** Save current nick/user/host. Used later by userhost_changed(). */
-void _userhost_save_current(Client *client)
-{
- strlcpy(remember_nick, client->name, sizeof(remember_nick));
- strlcpy(remember_user, client->user->username, sizeof(remember_user));
- strlcpy(remember_host, GetHost(client), sizeof(remember_host));
-}
-
-/** User/Host changed for user.
- * Note that userhost_save_current() needs to be called before this
- * to save the old username/hostname.
- * This userhost_changed() function deals with notifying local clients
- * about the user/host change by sending PART+JOIN+MODE if
- * set::allow-userhost-change force-rejoin is in use,
- * and it wills end "CAP chghost" to such capable clients.
- * It will also deal with bumping fakelag for the user since a user/host
- * change is costly, doesn't matter if it was self-induced or not.
- *
- * Please call this function for any user/host change by doing:
- * userhost_save_current(client);
- * << change username or hostname here >>
- * userhost_changed(client);
- */
-void _userhost_changed(Client *client)
-{
- Membership *channels;
- Member *lp;
- Client *acptr;
- int impact = 0;
- char buf[512];
- long CAP_EXTENDED_JOIN = ClientCapabilityBit("extended-join");
- long CAP_CHGHOST = ClientCapabilityBit("chghost");
-
- if (strcmp(remember_nick, client->name))
- {
- ircd_log(LOG_ERROR, "[BUG] userhost_changed() was called but without calling userhost_save_current() first! Affected user: %s",
- client->name);
- ircd_log(LOG_ERROR, "Please report above bug on https://bugs.unrealircd.org/");
- sendto_realops("[BUG] userhost_changed() was called but without calling userhost_save_current() first! Affected user: %s",
- client->name);
- sendto_realops("Please report above bug on https://bugs.unrealircd.org/");
- return; /* We cannot safely process this request anymore */
- }
-
- /* It's perfectly acceptable to call us even if the userhost didn't change. */
- if (!strcmp(remember_user, client->user->username) && !strcmp(remember_host, GetHost(client)))
- return; /* Nothing to do */
-
- /* Most of the work is only necessary for set::allow-userhost-change force-rejoin */
- if (UHOST_ALLOWED == UHALLOW_REJOIN)
- {
- /* Walk through all channels of this user.. */
- for (channels = client->user->channel; channels; channels = channels->next)
- {
- Channel *channel = channels->channel;
- int flags = channels->flags;
- char *modes;
- char partbuf[512]; /* PART */
- char joinbuf[512]; /* JOIN */
- char exjoinbuf[512]; /* JOIN (for CAP extended-join) */
- char modebuf[512]; /* MODE (if any) */
- int chanops_only = invisible_user_in_channel(client, channel);
-
- modebuf[0] = '\0';
-
- /* If the user is banned, don't send any rejoins, it would only be annoying */
- if (is_banned(client, channel, BANCHK_JOIN, NULL, NULL))
- continue;
-
- /* Prepare buffers for PART, JOIN, MODE */
- ircsnprintf(partbuf, sizeof(partbuf), ":%s!%s@%s PART %s :%s",
- remember_nick, remember_user, remember_host,
- channel->chname,
- "Changing host");
-
- ircsnprintf(joinbuf, sizeof(joinbuf), ":%s!%s@%s JOIN %s",
- client->name, client->user->username, GetHost(client), channel->chname);
-
- ircsnprintf(exjoinbuf, sizeof(exjoinbuf), ":%s!%s@%s JOIN %s %s :%s",
- client->name, client->user->username, GetHost(client), channel->chname,
- !isdigit(*client->user->svid) ? client->user->svid : "*",
- client->info);
-
- modes = get_chmodes_for_user(client, flags);
- if (!BadPtr(modes))
- ircsnprintf(modebuf, sizeof(modebuf), ":%s MODE %s %s", me.name, channel->chname, modes);
-
- for (lp = channel->members; lp; lp = lp->next)
- {
- acptr = lp->client;
-
- if (acptr == client)
- continue; /* skip self */
-
- if (!MyConnect(acptr))
- continue; /* only locally connected clients */
-
- if (chanops_only && !(lp->flags & (CHFL_CHANOP|CHFL_CHANOWNER|CHFL_CHANADMIN)))
- continue; /* skip non-ops if requested to (used for mode +D) */
-
- if (HasCapabilityFast(acptr, CAP_CHGHOST))
- continue; /* we notify 'CAP chghost' users in a different way, so don't send it here. */
-
- impact++;
-
- /* FIXME: if a client does not have the "chghost" cap then
- * here we will not generate a proper new message, probably
- * needs to be fixed... I skipped doing it for now.
- */
- sendto_one(acptr, NULL, "%s", partbuf);
-
- if (HasCapabilityFast(acptr, CAP_EXTENDED_JOIN))
- sendto_one(acptr, NULL, "%s", exjoinbuf);
- else
- sendto_one(acptr, NULL, "%s", joinbuf);
-
- if (*modebuf)
- sendto_one(acptr, NULL, "%s", modebuf);
- }
- }
- }
-
- /* Now deal with "CAP chghost" clients.
- * This only needs to be sent one per "common channel".
- * This would normally call sendto_common_channels_local_butone() but the user already
- * has the new user/host.. so we do it here..
- */
- ircsnprintf(buf, sizeof(buf), ":%s!%s@%s CHGHOST %s %s",
- remember_nick, remember_user, remember_host,
- client->user->username,
- GetHost(client));
- current_serial++;
- for (channels = client->user->channel; channels; channels = channels->next)
- {
- for (lp = channels->channel->members; lp; lp = lp->next)
- {
- acptr = lp->client;
- if (MyUser(acptr) && HasCapabilityFast(acptr, CAP_CHGHOST) &&
- (acptr->local->serial != current_serial) && (client != acptr))
- {
- /* FIXME: send mtag */
- sendto_one(acptr, NULL, "%s", buf);
- acptr->local->serial = current_serial;
- }
- }
- }
-
- if (MyUser(client))
- {
- /* We take the liberty of sending the CHGHOST to the impacted user as
- * well. This makes things easy for client coders.
- * (Note that this cannot be merged with the for loop from 15 lines up
- * since the user may not be in any channels)
- */
- if (HasCapabilityFast(client, CAP_CHGHOST))
- sendto_one(client, NULL, "%s", buf);
-
- /* A userhost change always generates the following network traffic:
- * server to server traffic, CAP "chghost" notifications, and
- * possibly PART+JOIN+MODE if force-rejoin had work to do.
- * We give the user a penalty so they don't flood...
- */
- if (impact)
- client->local->since += 7; /* Resulted in rejoins and such. */
- else
- client->local->since += 4; /* No rejoins */
- }
-}
diff --git a/src/modules/jointhrottle.c b/src/modules/jointhrottle.c
index 3247406..58a2404 100644
--- a/src/modules/jointhrottle.c
+++ b/src/modules/jointhrottle.c
@@ -29,7 +29,7 @@ ModuleHeader MOD_HEADER
"5.0",
"Join flood protection (set::anti-flood::join-flood)",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
ModuleInfo *ModInfo = NULL;
@@ -40,15 +40,15 @@ typedef struct JoinFlood JoinFlood;
struct JoinFlood {
JoinFlood *prev, *next;
- char chname[CHANNELLEN+1];
+ char name[CHANNELLEN+1];
time_t firstjoin;
unsigned short numjoins;
};
/* Forward declarations */
void jointhrottle_md_free(ModData *m);
-int jointhrottle_can_join(Client *client, Channel *channel, char *key, char *parv[]);
-int jointhrottle_local_join(Client *client, Channel *channel, MessageTag *mtags, char *parv[]);
+int jointhrottle_can_join(Client *client, Channel *channel, const char *key, char **errmsg);
+int jointhrottle_local_join(Client *client, Channel *channel, MessageTag *mtags);
static int isjthrottled(Client *client, Channel *channel);
static void jointhrottle_increase_usercounter(Client *client, Channel *channel);
EVENT(jointhrottle_cleanup_structs);
@@ -104,7 +104,7 @@ static int isjthrottled(Client *client, Channel *channel)
/* Grab user<->chan entry.. */
for (e = moddata_local_client(client, jointhrottle_md).ptr; e; e=e->next)
- if (!strcasecmp(e->chname, channel->chname))
+ if (!strcasecmp(e->name, channel->name))
break;
if (!e)
@@ -129,7 +129,7 @@ static void jointhrottle_increase_usercounter(Client *client, Channel *channel)
/* Grab user<->chan entry.. */
for (e = moddata_local_client(client, jointhrottle_md).ptr; e; e=e->next)
- if (!strcasecmp(e->chname, channel->chname))
+ if (!strcasecmp(e->name, channel->name))
break;
if (!e)
@@ -149,15 +149,18 @@ static void jointhrottle_increase_usercounter(Client *client, Channel *channel)
}
}
-int jointhrottle_can_join(Client *client, Channel *channel, char *key, char *parv[])
+int jointhrottle_can_join(Client *client, Channel *channel, const char *key, char **errmsg)
{
if (!ValidatePermissionsForPath("immune:join-flood",client,NULL,channel,NULL) && isjthrottled(client, channel))
+ {
+ *errmsg = STR_ERR_TOOMANYJOINS;
return ERR_TOOMANYJOINS;
+ }
return 0;
}
-int jointhrottle_local_join(Client *client, Channel *channel, MessageTag *mtags, char *parv[])
+int jointhrottle_local_join(Client *client, Channel *channel, MessageTag *mtags)
{
jointhrottle_increase_usercounter(client, channel);
return 0;
@@ -175,12 +178,12 @@ JoinFlood *jointhrottle_addentry(Client *client, Channel *channel)
abort();
for (e=moddata_local_client(client, jointhrottle_md).ptr; e; e=e->next)
- if (!strcasecmp(e->chname, channel->chname))
+ if (!strcasecmp(e->name, channel->name))
abort(); /* already exists -- should never happen */
#endif
e = safe_alloc(sizeof(JoinFlood));
- strlcpy(e->chname, channel->chname, sizeof(e->chname));
+ strlcpy(e->name, channel->name, sizeof(e->name));
/* Insert our new entry as (new) head */
if (moddata_local_client(client, jointhrottle_md).ptr)
@@ -211,11 +214,6 @@ EVENT(jointhrottle_cleanup_structs)
if (jf->firstjoin + iConf.floodsettings->period[FLD_JOIN] > TStime())
continue; /* still valid entry */
-#ifdef DEBUGMODE
- ircd_log(LOG_ERROR, "jointhrottle_cleanup_structs(): freeing %s/%s (%ld[%ld], %ld)",
- client->name, jf->chname, jf->firstjoin, (long)(TStime() - jf->firstjoin),
- iConf.floodsettings->period[FLD_JOIN]);
-#endif
if (moddata_local_client(client, jointhrottle_md).ptr == jf)
{
/* change head */
diff --git a/src/modules/json-log-tag.c b/src/modules/json-log-tag.c
new file mode 100644
index 0000000..5354ef1
--- /dev/null
+++ b/src/modules/json-log-tag.c
@@ -0,0 +1,90 @@
+/*
+ * IRC - Internet Relay Chat, src/modules/monitor.c
+ * (C) 2021 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.
+ */
+
+#include "unrealircd.h"
+
+ModuleHeader MOD_HEADER
+ = {
+ "json-log-tag",
+ "5.0",
+ "unrealircd.org/json-log tag for S2S and ircops",
+ "UnrealIRCd Team",
+ "unrealircd-6",
+ };
+
+/* Variables */
+long CAP_JSON_LOG = 0L;
+
+/* Forward declarations */
+int json_log_mtag_is_ok(Client *client, const char *name, const char *value);
+int json_log_mtag_should_send_to_client(Client *target);
+
+MOD_INIT()
+{
+ ClientCapabilityInfo cap;
+ ClientCapability *c;
+ MessageTagHandlerInfo mtag;
+
+ MARK_AS_OFFICIAL_MODULE(modinfo);
+
+ memset(&cap, 0, sizeof(cap));
+ cap.name = "unrealircd.org/json-log";
+ c = ClientCapabilityAdd(modinfo->handle, &cap, &CAP_JSON_LOG);
+
+ memset(&mtag, 0, sizeof(mtag));
+ mtag.name = "unrealircd.org/json-log";
+ mtag.is_ok = json_log_mtag_is_ok;
+ mtag.should_send_to_client = json_log_mtag_should_send_to_client;
+ mtag.clicap_handler = c;
+ MessageTagHandlerAdd(modinfo->handle, &mtag);
+
+ return MOD_SUCCESS;
+}
+
+MOD_LOAD()
+{
+ return MOD_SUCCESS;
+}
+
+MOD_UNLOAD()
+{
+ return MOD_SUCCESS;
+}
+
+/** This function verifies if the client sending
+ * We simply allow from servers without any syntax checking.
+ */
+int json_log_mtag_is_ok(Client *client, const char *name, const char *value)
+{
+ if (IsServer(client) || IsMe(client))
+ return 1;
+
+ return 0;
+}
+
+/** Outgoing filter for this message tag */
+int json_log_mtag_should_send_to_client(Client *target)
+{
+ if (IsServer(target) || (target->local && IsOper(target) && HasCapabilityFast(target, CAP_JSON_LOG)))
+ return 1;
+ return 0;
+}
diff --git a/src/modules/jumpserver.c b/src/modules/jumpserver.c
index 8d11c53..7743624 100644
--- a/src/modules/jumpserver.c
+++ b/src/modules/jumpserver.c
@@ -25,12 +25,9 @@ ModuleHeader MOD_HEADER
"1.1",
"/jumpserver command",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
-/* Defines */
-#define MSG_JUMPSERVER "JUMPSERVER"
-
/* Forward declarations */
CMD_FUNC(cmd_jumpserver);
int jumpserver_preconnect(Client *);
@@ -43,8 +40,8 @@ struct JSS
char *reason;
char *server;
int port;
- char *ssl_server;
- int ssl_port;
+ char *tls_server;
+ int tls_port;
};
JSS *jss=NULL; /**< JumpServer Status. NULL=disabled. */
@@ -53,7 +50,7 @@ MOD_INIT()
{
MARK_AS_OFFICIAL_MODULE(modinfo);
LoadPersistentPointer(modinfo, jss, jumpserver_free_jss);
- CommandAdd(modinfo->handle, MSG_JUMPSERVER, cmd_jumpserver, 3, CMD_USER);
+ CommandAdd(modinfo->handle, "JUMPSERVER", cmd_jumpserver, 3, CMD_USER);
HookAdd(modinfo->handle, HOOKTYPE_PRE_LOCAL_CONNECT, 0, jumpserver_preconnect);
return MOD_SUCCESS;
}
@@ -71,8 +68,8 @@ MOD_UNLOAD()
static void do_jumpserver_exit_client(Client *client)
{
- if (IsSecure(client) && jss->ssl_server)
- sendnumeric(client, RPL_REDIR, jss->ssl_server, jss->ssl_port);
+ if (IsSecure(client) && jss->tls_server)
+ sendnumeric(client, RPL_REDIR, jss->tls_server, jss->tls_port);
else
sendnumeric(client, RPL_REDIR, jss->server, jss->port);
exit_client(client, NULL, jss->reason);
@@ -91,8 +88,9 @@ static void redirect_all_clients(void)
count++;
}
}
- sendto_realops("JUMPSERVER: Redirected %d client%s",
- count, count == 1 ? "" : "s"); /* Language fun... ;p */
+ unreal_log(ULOG_INFO, "jumpserver", "JUMPSERVER_REPORT", NULL,
+ "[jumpserver] Redirected $num_clients client(s)",
+ log_data_integer("num_clients", count));
}
int jumpserver_preconnect(Client *client)
@@ -111,7 +109,7 @@ void free_jss(void)
{
safe_free(jss->server);
safe_free(jss->reason);
- safe_free(jss->ssl_server);
+ safe_free(jss->tls_server);
safe_free(jss);
jss = NULL;
}
@@ -124,8 +122,10 @@ void jumpserver_free_jss(ModData *m)
CMD_FUNC(cmd_jumpserver)
{
- char *serv, *sslserv=NULL, *reason, *p;
+ char *serv, *tlsserv=NULL, *p;
+ const char *reason;
int all=0, port=6667, sslport=6697;
+ char request[BUFSIZE];
char logbuf[512];
if (!IsOper(client))
@@ -136,9 +136,9 @@ CMD_FUNC(cmd_jumpserver)
if ((parc < 2) || BadPtr(parv[1]))
{
- if (jss && jss->ssl_server)
- sendnotice(client, "JumpServer is \002ENABLED\002 to %s:%d (SSL/TLS: %s:%d) with reason '%s'",
- jss->server, jss->port, jss->ssl_server, jss->ssl_port, jss->reason);
+ if (jss && jss->tls_server)
+ sendnotice(client, "JumpServer is \002ENABLED\002 to %s:%d (TLS: %s:%d) with reason '%s'",
+ jss->server, jss->port, jss->tls_server, jss->tls_port, jss->reason);
else
if (jss)
sendnotice(client, "JumpServer is \002ENABLED\002 to %s:%d with reason '%s'",
@@ -156,10 +156,8 @@ CMD_FUNC(cmd_jumpserver)
return;
}
free_jss();
- snprintf(logbuf, sizeof(logbuf), "%s (%s@%s) turned JUMPSERVER OFF",
- client->name, client->user->username, client->user->realhost);
- sendto_realops("%s", logbuf);
- ircd_log(LOG_ERROR, "%s", logbuf);
+ unreal_log(ULOG_INFO, "jumpserver", "JUMPSERVER_DISABLED", client,
+ "[jumpserver] $client.details turned jumpserver OFF");
return;
}
@@ -167,7 +165,7 @@ CMD_FUNC(cmd_jumpserver)
{
/* Waah, pretty verbose usage info ;) */
sendnotice(client, "Use: /JUMPSERVER [:port] ");
- sendnotice(client, " Or: /JUMPSERVER [:port]/[:port] ");
+ sendnotice(client, " Or: /JUMPSERVER [:port]/[:port] ");
sendnotice(client, "if 'NEW' is chosen then only new (incoming) connections will be redirected");
sendnotice(client, "if 'ALL' is chosen then all clients except opers will be redirected immediately (+incoming connections)");
sendnotice(client, "Example: /JUMPSERVER irc2.test.net NEW This server will be upgraded, please use irc2.test.net for now");
@@ -177,19 +175,16 @@ CMD_FUNC(cmd_jumpserver)
return;
}
- /* Parsing code follows...
- * The parsing of the SSL stuff is still done even on non-SSL,
- * but it's simply not used/applied :).
- * Reason for this is to reduce non-SSL/SSL inconsistency issues.
- */
+ /* Parsing code follows... */
- serv = parv[1];
+ strlcpy(request, parv[1], sizeof(request));
+ serv = request;
p = strchr(serv, '/');
if (p)
{
*p = '\0';
- sslserv = p+1;
+ tlsserv = p+1;
}
p = strchr(serv, ':');
@@ -203,21 +198,21 @@ CMD_FUNC(cmd_jumpserver)
return;
}
}
- if (sslserv)
+ if (tlsserv)
{
- p = strchr(sslserv, ':');
+ p = strchr(tlsserv, ':');
if (p)
{
*p++ = '\0';
sslport = atoi(p);
if ((sslport < 1) || (sslport > 65535))
{
- sendnotice(client, "Invalid SSL/TLS serverport specified (%d)", sslport);
+ sendnotice(client, "Invalid TLS serverport specified (%d)", sslport);
return;
}
}
- if (!*sslserv)
- sslserv = NULL;
+ if (!*tlsserv)
+ tlsserv = NULL;
}
if (!strcasecmp(parv[2], "new"))
all = 0;
@@ -239,27 +234,37 @@ CMD_FUNC(cmd_jumpserver)
/* Set it */
safe_strdup(jss->server, serv);
jss->port = port;
- if (sslserv)
+ if (tlsserv)
{
- safe_strdup(jss->ssl_server, sslserv);
- jss->ssl_port = sslport;
+ safe_strdup(jss->tls_server, tlsserv);
+ jss->tls_port = sslport;
}
safe_strdup(jss->reason, reason);
/* Broadcast/log */
- if (sslserv)
- snprintf(logbuf, sizeof(logbuf), "%s (%s@%s) added JUMPSERVER redirect for %s to %s:%d [SSL/TLS: %s:%d] with reason '%s'",
- client->name, client->user->username, client->user->realhost,
- all ? "ALL CLIENTS" : "all new clients",
- jss->server, jss->port, jss->ssl_server, jss->ssl_port, jss->reason);
- else
- snprintf(logbuf, sizeof(logbuf), "%s (%s@%s) added JUMPSERVER redirect for %s to %s:%d with reason '%s'",
- client->name, client->user->username, client->user->realhost,
- all ? "ALL CLIENTS" : "all new clients",
- jss->server, jss->port, jss->reason);
-
- sendto_realops("%s", logbuf);
- ircd_log(LOG_ERROR, "%s", logbuf);
+ if (tlsserv)
+ {
+ unreal_log(ULOG_INFO, "jumpserver", "JUMPSERVER_ENABLED", client,
+ "[jumpserver] $client.details turned jumpserver ON for $jumpserver_who "
+ "to $jumpserver_server:$jumpserver_port "
+ "[TLS: $jumpserver_tls_server:$jumpserver_tls_port] "
+ "($reason)",
+ log_data_string("jumpserver_who", all ? "ALL CLIENTS" : "all new clients"),
+ log_data_string("jumpserver_server", jss->server),
+ log_data_integer("jumpserver_port", jss->port),
+ log_data_string("jumpserver_tls_server", jss->tls_server),
+ log_data_integer("jumpserver_tls_port", jss->tls_port),
+ log_data_string("reason", jss->reason));
+ } else {
+ unreal_log(ULOG_INFO, "jumpserver", "JUMPSERVER_ENABLED", client,
+ "[jumpserver] $client.details turned jumpserver ON for $jumpserver_who "
+ "to $jumpserver_server:$jumpserver_port "
+ "($reason)",
+ log_data_string("jumpserver_who", all ? "ALL CLIENTS" : "all new clients"),
+ log_data_string("jumpserver_server", jss->server),
+ log_data_integer("jumpserver_port", jss->port),
+ log_data_string("reason", jss->reason));
+ }
if (all)
redirect_all_clients();
diff --git a/src/modules/kick.c b/src/modules/kick.c
index 8545f9b..f5a2b09 100644
--- a/src/modules/kick.c
+++ b/src/modules/kick.c
@@ -28,7 +28,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /kick",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Forward declarations */
@@ -59,6 +59,16 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
+void kick_operoverride_msg(Client *client, Channel *channel, Client *target, char *reason)
+{
+ unreal_log(ULOG_INFO, "operoverride", "OPEROVERRIDE_KICK", client,
+ "OperOverride: $client.details kicked $target from $channel ($reason)",
+ log_data_string("override_type", "kick"),
+ log_data_string("reason", reason),
+ log_data_client("target", target),
+ log_data_channel("channel", channel));
+}
+
/** Kick a user from a channel.
* @param initial_mtags Message tags associated with this KICK (can be NULL)
* @param channel The channel where the KICK should happen
@@ -84,37 +94,37 @@ void _kick_user(MessageTag *initial_mtags, Channel *channel, Client *client, Cli
new_message(client, NULL, &initial_mtags);
}
- new_message_special(client, initial_mtags, &mtags, ":%s KICK %s %s", client->name, channel->chname, victim->name);
+ new_message_special(client, initial_mtags, &mtags, ":%s KICK %s %s", client->name, channel->name, victim->name);
/* The same message is actually sent at 5 places below (though max 4 at most) */
if (MyUser(client))
- RunHook5(HOOKTYPE_LOCAL_KICK, client, victim, channel, mtags, comment);
+ RunHook(HOOKTYPE_LOCAL_KICK, client, victim, channel, mtags, comment);
else
- RunHook5(HOOKTYPE_REMOTE_KICK, client, victim, channel, mtags, comment);
+ RunHook(HOOKTYPE_REMOTE_KICK, client, victim, channel, mtags, comment);
if (invisible_user_in_channel(victim, channel))
{
/* Send it only to chanops & victim */
sendto_channel(channel, client, victim,
- PREFIX_HALFOP|PREFIX_OP|PREFIX_OWNER|PREFIX_ADMIN, 0,
+ "h", 0,
SEND_LOCAL, mtags,
":%s KICK %s %s :%s",
- client->name, channel->chname, victim->name, comment);
+ client->name, channel->name, victim->name, comment);
if (MyUser(victim))
{
sendto_prefix_one(victim, client, mtags, ":%s KICK %s %s :%s",
- client->name, channel->chname, victim->name, comment);
+ client->name, channel->name, victim->name, comment);
}
} else {
/* NORMAL */
sendto_channel(channel, client, NULL, 0, 0, SEND_LOCAL, mtags,
":%s KICK %s %s :%s",
- client->name, channel->chname, victim->name, comment);
+ client->name, channel->name, victim->name, comment);
}
sendto_server(client, 0, 0, mtags, ":%s KICK %s %s :%s",
- client->id, channel->chname, victim->id, comment);
+ client->id, channel->name, victim->id, comment);
free_message_tags(mtags);
if (initial_mtags_generated)
@@ -123,34 +133,44 @@ void _kick_user(MessageTag *initial_mtags, Channel *channel, Client *client, Cli
initial_mtags = NULL;
}
- remove_user_from_channel(victim, channel);
+ if (MyUser(victim))
+ {
+ unreal_log(ULOG_INFO, "kick", "LOCAL_CLIENT_KICK", victim,
+ "User $client kicked from $channel",
+ log_data_channel("channel", channel));
+ } else {
+ unreal_log(ULOG_INFO, "kick", "REMOTE_CLIENT_KICK", victim,
+ "User $client kicked from $channel",
+ log_data_channel("channel", channel));
+ }
+
+ remove_user_from_channel(victim, channel, 1);
}
/*
** cmd_kick
-** parv[1] = channel
-** parv[2] = client to kick
+** parv[1] = channel (single channel)
+** parv[2] = client to kick (comma separated)
** parv[3] = kick comment
*/
-#ifdef PREFIX_AQ
-#define CHFL_ISOP (CHFL_CHANOWNER|CHFL_CHANADMIN|CHFL_CHANOP)
-#else
-#define CHFL_ISOP (CHFL_CHANOP)
-#endif
-
CMD_FUNC(cmd_kick)
{
- Client *who;
+ Client *target;
Channel *channel;
int chasing = 0;
- char *comment, *name, *p = NULL, *user, *p2 = NULL, *badkick;
+ char *p = NULL, *user, *p2 = NULL, *badkick;
+ char comment[MAXKICKLEN+1];
Membership *lp;
Hook *h;
int ret;
int ntargets = 0;
int maxtargets = max_targets_for_command("KICK");
MessageTag *mtags;
+ char request[BUFSIZE];
+ char request_chans[BUFSIZE];
+ const char *client_member_modes = NULL;
+ const char *target_member_modes;
if (parc < 3 || *parv[1] == '\0')
{
@@ -158,216 +178,192 @@ CMD_FUNC(cmd_kick)
return;
}
- comment = (BadPtr(parv[3])) ? client->name : parv[3];
+ if (BadPtr(parv[3]))
+ strlcpy(comment, client->name, sizeof(comment));
+ else
+ strlncpy(comment, parv[3], sizeof(comment), iConf.kick_length);
- if (!BadPtr(parv[3]) && (strlen(comment) > iConf.kick_length))
- comment[iConf.kick_length] = '\0';
-
- for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL)
+ strlcpy(request_chans, parv[1], sizeof(request_chans));
+ p = strchr(request_chans, ',');
+ if (p)
+ *p = '\0';
+ channel = find_channel(request_chans);
+ if (!channel)
{
- long client_flags = 0;
- channel = get_channel(client, name, !CREATE);
- if (!channel)
+ sendnumeric(client, ERR_NOSUCHCHANNEL, request_chans);
+ return;
+ }
+
+ /* Store "client" access flags */
+ if (IsUser(client))
+ client_member_modes = get_channel_access(client, channel);
+ if (MyUser(client) && !IsULine(client) &&
+ !op_can_override("channel:override:kick:no-ops",client,channel,NULL) &&
+ !check_channel_access(client, channel, "hoaq"))
+ {
+ sendnumeric(client, ERR_CHANOPRIVSNEEDED, channel->name);
+ return;
+ }
+
+ strlcpy(request, parv[2], sizeof(request));
+ for (user = strtoken(&p2, request, ","); user; user = strtoken(&p2, NULL, ","))
+ {
+ if (MyUser(client) && (++ntargets > maxtargets))
{
- sendnumeric(client, ERR_NOSUCHCHANNEL, name);
- continue;
+ sendnumeric(client, ERR_TOOMANYTARGETS, user, maxtargets, "KICK");
+ break;
}
- /* Store "client" access flags */
- if (IsUser(client))
- client_flags = get_access(client, channel);
- if (MyUser(client) && !IsULine(client) && !op_can_override("channel:override:kick:no-ops",client,channel,NULL)
- && !(client_flags & CHFL_ISOP) && !(client_flags & CHFL_HALFOP))
+
+ if (!(target = find_chasing(client, user, &chasing)))
+ continue; /* No such user left! */
+
+ if (!target->user)
+ continue; /* non-user */
+
+ lp = find_membership_link(target->user->channel, channel);
+ if (!lp)
{
- sendnumeric(client, ERR_CHANOPRIVSNEEDED, channel->chname);
+ if (MyUser(client))
+ sendnumeric(client, ERR_USERNOTINCHANNEL, user, request_chans);
continue;
}
- for (; (user = strtoken(&p2, parv[2], ",")); parv[2] = NULL)
- {
- long who_flags;
+ if (IsULine(client) || IsServer(client))
+ goto attack;
- if (MyUser(client) && (++ntargets > maxtargets))
+ /* Note for coders regarding oper override:
+ * always let a remote kick (=from a user on another server) through or
+ * else we will get desynced. In short this means all the denying should
+ * always contain a && MyUser(client) and at the end
+ * a remote kick should always be allowed (pass through). -- Syzop
+ */
+
+ /* Store "target" access flags */
+ target_member_modes = get_channel_access(target, channel);
+
+ badkick = NULL;
+ ret = EX_ALLOW;
+ for (h = Hooks[HOOKTYPE_CAN_KICK]; h; h = h->next) {
+ int n = (*(h->func.intfunc))(client, target, channel, comment, client_member_modes, target_member_modes, &badkick);
+
+ if (n == EX_DENY)
+ ret = n;
+ else if (n == EX_ALWAYS_DENY)
{
- sendnumeric(client, ERR_TOOMANYTARGETS, user, maxtargets, "KICK");
+ ret = n;
break;
}
+ }
- if (!(who = find_chasing(client, user, &chasing)))
- continue; /* No such user left! */
+ if (ret == EX_ALWAYS_DENY)
+ {
+ if (MyUser(client) && badkick)
+ sendto_one(client, NULL, "%s", badkick); /* send error, if any */
- if (!who->user)
- continue; /* non-user */
+ if (MyUser(client))
+ continue; /* reject the kick (note: we never block remote kicks) */
+ }
- lp = find_membership_link(who->user->channel, channel);
- if (!lp)
- {
- if (MyUser(client))
- sendnumeric(client, ERR_USERNOTINCHANNEL, user, name);
- continue;
- }
-
- if (IsULine(client) || IsServer(client))
- goto attack;
-
- /* Note for coders regarding oper override:
- * always let a remote kick (=from a user on another server) through or
- * else we will get desynced. In short this means all the denying should
- * always contain a && MyUser(client) and at the end
- * a remote kick should always be allowed (pass through). -- Syzop
- */
-
- /* Store "who" access flags */
- who_flags = get_access(who, channel);
-
- badkick = NULL;
- ret = EX_ALLOW;
- for (h = Hooks[HOOKTYPE_CAN_KICK]; h; h = h->next) {
- int n = (*(h->func.intfunc))(client, who, channel, comment, client_flags, who_flags, &badkick);
-
- if (n == EX_DENY)
- ret = n;
- else if (n == EX_ALWAYS_DENY)
- {
- ret = n;
- break;
- }
- }
-
- if (ret == EX_ALWAYS_DENY)
+ if (ret == EX_DENY)
+ {
+ /* If set it means 'not allowed to kick'.. now check if (s)he can override that.. */
+ if (op_can_override("channel:override:kick:no-ops",client,channel,NULL))
{
+ kick_operoverride_msg(client, channel, target, comment);
+ goto attack; /* all other checks don't matter anymore (and could cause double msgs) */
+ } else {
+ /* Not an oper overriding */
if (MyUser(client) && badkick)
sendto_one(client, NULL, "%s", badkick); /* send error, if any */
- if (MyUser(client))
- continue; /* reject the kick (note: we never block remote kicks) */
+ continue; /* reject the kick */
}
+ }
- if (ret == EX_DENY)
+ // FIXME: Most, maybe even all, of these must be moved to HOOKTYPE_CAN_KICK checks in the corresponding halfop/chanop/chanadmin/chanowner modules :)
+ // !!!! FIXME
+
+ /* we are neither +o nor +h, OR..
+ * we are +h but target is +o, OR...
+ * we are +h and target is +h
+ */
+ if (op_can_override("channel:override:kick:no-ops",client,channel,NULL))
+ {
+ if ((!check_channel_access_string(client_member_modes, "o") && !check_channel_access_string(client_member_modes, "h")) ||
+ (check_channel_access_string(client_member_modes, "h") && check_channel_access_string(target_member_modes, "h")) ||
+ (check_channel_access_string(client_member_modes, "h") && check_channel_access_string(target_member_modes, "o")))
{
- /* If set it means 'not allowed to kick'.. now check if (s)he can override that.. */
- if (op_can_override("channel:override:kick:no-ops",client,channel,NULL))
- {
- sendto_snomask(SNO_EYES,
- "*** OperOverride -- %s (%s@%s) KICK %s %s (%s)",
- client->name, client->user->username, client->user->realhost,
- channel->chname, who->name, comment);
- ircd_log(LOG_OVERRIDE,"OVERRIDE: %s (%s@%s) KICK %s %s (%s)",
- client->name, client->user->username, client->user->realhost,
- channel->chname, who->name, comment);
- goto attack; /* all other checks don't matter anymore (and could cause double msgs) */
- } else {
- /* Not an oper overriding */
- if (MyUser(client) && badkick)
- sendto_one(client, NULL, "%s", badkick); /* send error, if any */
+ kick_operoverride_msg(client, channel, target, comment);
+ goto attack;
+ } /* is_chan_op */
- continue; /* reject the kick */
- }
- }
+ }
- /* we are neither +o nor +h, OR..
- * we are +h but victim is +o, OR...
- * we are +h and victim is +h
- */
- if (op_can_override("channel:override:kick:no-ops",client,channel,NULL))
+ /* target is +a/+q, and we are not +q? */
+ if (check_channel_access_string(target_member_modes, "qa") && !check_channel_access_string(client_member_modes, "q"))
+ {
+ if (client == target)
+ goto attack; /* kicking self == ok */
+ if (op_can_override("channel:override:kick:owner",client,channel,NULL)) /* (and f*ck local ops) */
{
- if ((!(client_flags & CHFL_ISOP) && !(client_flags & CHFL_HALFOP)) ||
- ((client_flags & CHFL_HALFOP) && (who_flags & CHFL_ISOP)) ||
- ((client_flags & CHFL_HALFOP) && (who_flags & CHFL_HALFOP)))
- {
- sendto_snomask(SNO_EYES,
- "*** OperOverride -- %s (%s@%s) KICK %s %s (%s)",
- client->name, client->user->username, client->user->realhost,
- channel->chname, who->name, comment);
-
- /* Logging Implementation added by XeRXeS */
- ircd_log(LOG_OVERRIDE,"OVERRIDE: %s (%s@%s) KICK %s %s (%s)",
- client->name, client->user->username, client->user->realhost,
- channel->chname, who->name, comment);
-
- goto attack;
- } /* is_chan_op */
-
+ /* IRCop kicking owner/prot */
+ kick_operoverride_msg(client, channel, target, comment);
+ goto attack;
}
-
- /* victim is +a or +q, we are not +q */
- if ((who_flags & (CHFL_CHANOWNER|CHFL_CHANADMIN))
- && !(client_flags & CHFL_CHANOWNER)) {
- if (client == who)
- goto attack; /* kicking self == ok */
- if (op_can_override("channel:override:kick:owner",client,channel,NULL)) /* (and f*ck local ops) */
- { /* IRCop kicking owner/prot */
- sendto_snomask(SNO_EYES,
- "*** OperOverride -- %s (%s@%s) KICK %s %s (%s)",
- client->name, client->user->username, client->user->realhost,
- channel->chname, who->name, comment);
-
- /* Logging Implementation added by XeRXeS */
- ircd_log(LOG_OVERRIDE,"OVERRIDE: %s (%s@%s) KICK %s %s (%s)",
- client->name, client->user->username, client->user->realhost,
- channel->chname, who->name, comment);
-
- goto attack;
- }
- else if (!IsULine(client) && (who != client) && MyUser(client))
- {
- char errbuf[NICKLEN+25];
- if (who_flags & CHFL_CHANOWNER)
- ircsnprintf(errbuf, sizeof(errbuf), "%s is a channel owner",
- who->name);
- else
- ircsnprintf(errbuf, sizeof(errbuf), "%s is a channel admin",
- who->name);
- sendnumeric(client, ERR_CANNOTDOCOMMAND, "KICK",
- errbuf);
- goto deny;
- } /* chanadmin/chanowner */
- }
-
- /* victim is +o, we are +h [operoverride is already taken care of 2 blocks above] */
- if ((who_flags & CHFL_ISOP) && (client_flags & CHFL_HALFOP)
- && !(client_flags & CHFL_ISOP) && !IsULine(client) && MyUser(client))
+ else if (!IsULine(client) && (target != client) && MyUser(client))
{
- char errbuf[NICKLEN+30];
- ircsnprintf(errbuf, sizeof(errbuf), "%s is a channel operator", who->name);
- sendnumeric(client, ERR_CANNOTDOCOMMAND, "KICK",
- errbuf);
+ char errbuf[NICKLEN+25];
+ if (check_channel_access_string(target_member_modes, "q"))
+ ircsnprintf(errbuf, sizeof(errbuf), "%s is a channel owner", target->name);
+ else
+ ircsnprintf(errbuf, sizeof(errbuf), "%s is a channel admin", target->name);
+ sendnumeric(client, ERR_CANNOTDOCOMMAND, "KICK", errbuf);
goto deny;
}
+ }
- /* victim is +h, we are +h [operoverride is already taken care of 3 blocks above] */
- if ((who_flags & CHFL_HALFOP) && (client_flags & CHFL_HALFOP)
- && !(client_flags & CHFL_ISOP) && MyUser(client))
- {
- char errbuf[NICKLEN+15];
- ircsnprintf(errbuf, sizeof(errbuf), "%s is a halfop", who->name);
- sendnumeric(client, ERR_CANNOTDOCOMMAND, "KICK",
- errbuf);
- goto deny;
- } /* halfop */
+ /* target is +o, we are +h [operoverride is already taken care of 2 blocks above] */
+ if (check_channel_access_string(target_member_modes, "h") && check_channel_access_string(client_member_modes, "h")
+ && !check_channel_access_string(client_member_modes, "o") && !IsULine(client) && MyUser(client))
+ {
+ char errbuf[NICKLEN+30];
+ ircsnprintf(errbuf, sizeof(errbuf), "%s is a channel operator", target->name);
+ sendnumeric(client, ERR_CANNOTDOCOMMAND, "KICK",
+ errbuf);
+ goto deny;
+ }
- /* allowed (either coz access granted or a remote kick), so attack! */
- goto attack;
+ /* target is +h, we are +h [operoverride is already taken care of 3 blocks above] */
+ if (check_channel_access_string(target_member_modes, "o") && check_channel_access_string(client_member_modes, "h")
+ && !check_channel_access_string(client_member_modes, "o") && MyUser(client))
+ {
+ char errbuf[NICKLEN+15];
+ ircsnprintf(errbuf, sizeof(errbuf), "%s is a halfop", target->name);
+ sendnumeric(client, ERR_CANNOTDOCOMMAND, "KICK",
+ errbuf);
+ goto deny;
+ } /* halfop */
- deny:
- continue;
+ /* allowed (either coz access granted or a remote kick), so attack! */
+ goto attack;
- attack:
- if (MyConnect(client)) {
- int breakit = 0;
- Hook *h;
- for (h = Hooks[HOOKTYPE_PRE_LOCAL_KICK]; h; h = h->next) {
- if((*(h->func.intfunc))(client,who,channel,comment) > 0) {
- breakit = 1;
- break;
- }
+ deny:
+ continue;
+
+ attack:
+ if (MyConnect(client)) {
+ int breakit = 0;
+ Hook *h;
+ for (h = Hooks[HOOKTYPE_PRE_LOCAL_KICK]; h; h = h->next) {
+ if ((*(h->func.intfunc))(client,target,channel,comment) > 0) {
+ breakit = 1;
+ break;
}
- if (breakit)
- continue;
}
+ if (breakit)
+ continue;
+ }
- kick_user(recv_mtags, channel, client, who, comment);
- } /* loop on parv[2] */
- if (MyUser(client))
- break;
- } /* loop on parv[1] */
+ kick_user(recv_mtags, channel, client, target, comment);
+ }
}
diff --git a/src/modules/kill.c b/src/modules/kill.c
index 67c53c3..2a62a75 100644
--- a/src/modules/kill.c
+++ b/src/modules/kill.c
@@ -29,7 +29,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /kill",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
@@ -56,7 +56,9 @@ MOD_UNLOAD()
*/
CMD_FUNC(cmd_kill)
{
- char *targetlist, *reason;
+ char targetlist[BUFSIZE];
+ char reason[BUFSIZE];
+ char *str;
char *nick, *save = NULL;
Client *target;
Hook *h;
@@ -69,20 +71,18 @@ CMD_FUNC(cmd_kill)
return;
}
- targetlist = parv[1];
- reason = parv[2];
-
if (!IsServer(client->direction) && !ValidatePermissionsForPath("kill:global",client,NULL,NULL,NULL) && !ValidatePermissionsForPath("kill:local",client,NULL,NULL,NULL))
{
sendnumeric(client, ERR_NOPRIVILEGES);
return;
}
- if (strlen(reason) > iConf.quit_length)
- reason[iConf.quit_length] = '\0';
-
if (MyUser(client))
- targetlist = canonize(targetlist);
+ strlcpy(targetlist, canonize(parv[1]), sizeof(targetlist));
+ else
+ strlcpy(targetlist, parv[1], sizeof(targetlist));
+
+ strlncpy(reason, parv[2], sizeof(reason), iConf.quit_length);
for (nick = strtoken(&save, targetlist, ","); nick; nick = strtoken(&save, NULL, ","))
{
@@ -94,7 +94,7 @@ CMD_FUNC(cmd_kill)
break;
}
- target = find_person(nick, NULL);
+ target = find_user(nick, NULL);
/* If a local user issued the /KILL then we will "chase" the user.
* In other words: we'll check the history for recently changed nicks.
@@ -138,16 +138,10 @@ CMD_FUNC(cmd_kill)
/* From here on, the kill is probably going to be successful. */
- sendto_snomask(SNO_KILLS,
- "*** Received KILL message for %s (%s@%s) from %s: %s",
- target->name, target->user->username, GetHost(target),
- client->name,
- reason);
-
- ircd_log(LOG_KILL, "KILL (%s) by %s (%s)",
- make_nick_user_host(target->name, target->user->username, GetHost(target)),
- client->name,
- reason);
+ unreal_log(ULOG_INFO, "kill", "KILL_COMMAND", client,
+ "Client killed: $target.details [by: $client] ($reason)",
+ log_data_client("target", target),
+ log_data_string("reason", reason));
new_message(client, recv_mtags, &mtags);
@@ -177,7 +171,7 @@ CMD_FUNC(cmd_kill)
}
if (MyUser(client))
- RunHook3(HOOKTYPE_LOCAL_KILL, client, target, reason);
+ RunHook(HOOKTYPE_LOCAL_KILL, client, target, reason);
ircsnprintf(buf2, sizeof(buf2), "Killed by %s (%s)", client->name, reason);
exit_client(target, mtags, buf2);
diff --git a/src/modules/knock.c b/src/modules/knock.c
index d2197af..16d2a7f 100644
--- a/src/modules/knock.c
+++ b/src/modules/knock.c
@@ -32,7 +32,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /knock",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
@@ -78,7 +78,7 @@ CMD_FUNC(cmd_knock)
Hook *h;
int i = 0;
MessageTag *mtags = NULL;
- char *reason;
+ const char *reason;
if (IsServer(client))
return;
@@ -97,7 +97,7 @@ CMD_FUNC(cmd_knock)
return;
}
- if (!(channel = find_channel(parv[1], NULL)))
+ if (!(channel = find_channel(parv[1])))
{
sendnumeric(client, ERR_CANNOTKNOCK, parv[1], "Channel does not exist!");
return;
@@ -106,25 +106,25 @@ CMD_FUNC(cmd_knock)
/* IsMember bugfix by codemastr */
if (IsMember(client, channel) == 1)
{
- sendnumeric(client, ERR_CANNOTKNOCK, channel->chname, "You're already there!");
+ sendnumeric(client, ERR_CANNOTKNOCK, channel->name, "You're already there!");
return;
}
- if (!(channel->mode.mode & MODE_INVITEONLY))
+ if (!has_channel_mode(channel, 'i'))
{
- sendnumeric(client, ERR_CANNOTKNOCK, channel->chname, "Channel is not invite only!");
+ sendnumeric(client, ERR_CANNOTKNOCK, channel->name, "Channel is not invite only!");
return;
}
if (is_banned(client, channel, BANCHK_JOIN, NULL, NULL))
{
- sendnumeric(client, ERR_CANNOTKNOCK, channel->chname, "You're banned!");
+ sendnumeric(client, ERR_CANNOTKNOCK, channel->name, "You're banned!");
return;
}
for (h = Hooks[HOOKTYPE_PRE_KNOCK]; h; h = h->next)
{
- i = (*(h->func.intfunc))(client,channel);
+ i = (*(h->func.intfunc))(client, channel, &reason);
if (i == HOOK_DENY || i == HOOK_ALLOW)
break;
}
@@ -142,19 +142,19 @@ CMD_FUNC(cmd_knock)
new_message(&me, NULL, &mtags);
- sendto_channel(channel, &me, NULL, PREFIX_OP|PREFIX_ADMIN|PREFIX_OWNER,
+ sendto_channel(channel, &me, NULL, "o",
0, SEND_LOCAL, mtags,
":%s NOTICE @%s :[Knock] by %s!%s@%s (%s)",
- me.name, channel->chname,
+ me.name, channel->name,
client->name, client->user->username, GetHost(client),
reason);
- sendto_server(client, 0, 0, mtags, ":%s KNOCK %s :%s", client->id, channel->chname, reason);
+ sendto_server(client, 0, 0, mtags, ":%s KNOCK %s :%s", client->id, channel->name, reason);
if (MyUser(client))
- sendnotice(client, "Knocked on %s", channel->chname);
+ sendnotice(client, "Knocked on %s", channel->name);
- RunHook4(HOOKTYPE_KNOCK, client, channel, mtags, parv[2]);
+ RunHook(HOOKTYPE_KNOCK, client, channel, mtags, parv[2]);
free_message_tags(mtags);
}
diff --git a/src/modules/labeled-response.c b/src/modules/labeled-response.c
index 56e9183..5027fe0 100644
--- a/src/modules/labeled-response.c
+++ b/src/modules/labeled-response.c
@@ -28,7 +28,7 @@ ModuleHeader MOD_HEADER
"5.0",
"Labeled response CAP",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Data structures */
@@ -43,8 +43,8 @@ struct LabeledResponseContext {
};
/* Forward declarations */
-int lr_pre_command(Client *from, MessageTag *mtags, char *buf);
-int lr_post_command(Client *from, MessageTag *mtags, char *buf);
+int lr_pre_command(Client *from, MessageTag *mtags, const char *buf);
+int lr_post_command(Client *from, MessageTag *mtags, const char *buf);
int lr_close_connection(Client *client);
int lr_packet(Client *from, Client *to, Client *intended_to, char **msg, int *len);
void *_labeled_response_save_context(void);
@@ -61,7 +61,7 @@ static long CAP_LABELED_RESPONSE = 0L;
static char packet[8192];
-int labeled_response_mtag_is_ok(Client *client, char *name, char *value);
+int labeled_response_mtag_is_ok(Client *client, const char *name, const char *value);
MOD_TEST()
{
@@ -111,7 +111,7 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
-int lr_pre_command(Client *from, MessageTag *mtags, char *buf)
+int lr_pre_command(Client *from, MessageTag *mtags, const char *buf)
{
memset(¤tcmd, 0, sizeof(currentcmd));
labeled_response_inhibit = labeled_response_inhibit_end = labeled_response_force = 0;
@@ -156,7 +156,7 @@ char *gen_start_batch(void)
return buf;
}
-int lr_post_command(Client *from, MessageTag *mtags, char *buf)
+int lr_post_command(Client *from, MessageTag *mtags, const char *buf)
{
/* ** IMPORTANT **
* Take care NOT to return here, use 'goto done' instead
@@ -336,7 +336,7 @@ int lr_packet(Client *from, Client *to, Client *intended_to, char **msg, int *le
/** This function verifies if the client sending the
* tag is permitted to do so and uses a permitted syntax.
*/
-int labeled_response_mtag_is_ok(Client *client, char *name, char *value)
+int labeled_response_mtag_is_ok(Client *client, const char *name, const char *value)
{
if (BadPtr(value))
return 0;
diff --git a/src/modules/lag.c b/src/modules/lag.c
index b2c1b59..9018303 100644
--- a/src/modules/lag.c
+++ b/src/modules/lag.c
@@ -31,7 +31,7 @@ ModuleHeader MOD_HEADER
"5.0", /* Version */
"command /lag", /* Short description of module */
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* This is called on module init, before Server Ready */
@@ -78,7 +78,7 @@ CMD_FUNC(cmd_lag)
return;
}
- if (hunt_server(client, recv_mtags, ":%s LAG :%s", 1, parc, parv) == HUNTED_NOSUCH)
+ if (hunt_server(client, recv_mtags, "LAG", 1, parc, parv) == HUNTED_NOSUCH)
return;
sendnotice(client, "Lag reply -- %s %s %lld", me.name, parv[1], (long long)TStime());
diff --git a/src/modules/link-security.c b/src/modules/link-security.c
index d4e6341..76e8bed 100644
--- a/src/modules/link-security.c
+++ b/src/modules/link-security.c
@@ -29,14 +29,14 @@ ModuleHeader MOD_HEADER
"5.0",
"Link Security CAP",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
/* Forward declarations */
-char *link_security_md_serialize(ModData *m);
-void link_security_md_unserialize(char *str, ModData *m);
+const char *link_security_md_serialize(ModData *m);
+void link_security_md_unserialize(const char *str, ModData *m);
EVENT(checklinksec);
-char *link_security_capability_parameter(Client *client);
+const char *link_security_capability_parameter(Client *client);
CMD_FUNC(cmd_linksecurity);
/* Global variables */
@@ -59,6 +59,7 @@ MOD_INIT()
mreq.serialize = link_security_md_serialize;
mreq.unserialize = link_security_md_unserialize;
mreq.sync = 1;
+ mreq.self_write = 1;
link_security_md = ModDataAdd(modinfo->handle, mreq);
if (!link_security_md)
{
@@ -97,7 +98,7 @@ MOD_UNLOAD()
*/
#define LNKSECMAGIC 100
-char *link_security_md_serialize(ModData *m)
+const char *link_security_md_serialize(ModData *m)
{
static char buf[32];
if (m->i == 0)
@@ -106,7 +107,7 @@ char *link_security_md_serialize(ModData *m)
return buf;
}
-void link_security_md_unserialize(char *str, ModData *m)
+void link_security_md_unserialize(const char *str, ModData *m)
{
m->i = atoi(str) + LNKSECMAGIC;
}
@@ -118,9 +119,9 @@ int certificate_verification_active(Client *client)
{
ConfigItem_link *conf;
- if (!client->serv || !client->serv->conf)
+ if (!client->server || !client->server->conf)
return 0; /* wtf? */
- conf = client->serv->conf;
+ conf = client->server->conf;
if (conf->verify_certificate)
return 1; /* yes, verify-certificate is 'yes' */
@@ -140,7 +141,7 @@ int certificate_verification_active(Client *client)
/** Calculate our (local) link-security level.
* This means stepping through the list of directly linked
- * servers and determining if they are linked via SSL and
+ * servers and determining if they are linked via TLS and
* certificate verification is active.
* @returns value from 0 to 2.
*/
@@ -154,7 +155,7 @@ int our_link_security(void)
if (IsLocalhost(client))
continue; /* server connected via localhost */
if (!IsSecure(client))
- return 0; /* Any non-SSL server (which is not localhost) results in level 0. */
+ return 0; /* Any non-TLS server (which is not localhost) results in level 0. */
if (!certificate_verification_active(client))
level = 1; /* downgrade to level 1 */
}
@@ -177,7 +178,6 @@ EVENT(checklinksec)
int last_local_link_security = local_link_security;
int last_global_link_security = global_link_security;
Client *client;
- char *s;
int v;
int warning_sent = 0;
@@ -193,7 +193,7 @@ EVENT(checklinksec)
global_link_security = 2;
list_for_each_entry(client, &global_server_list, client_node)
{
- s = moddata_client_get(client, "link-security");
+ const char *s = moddata_client_get(client, "link-security");
if (s)
{
v = atoi(s);
@@ -209,15 +209,19 @@ EVENT(checklinksec)
if (local_link_security < last_local_link_security)
{
- sendto_realops("Local link-security downgraded from level %d to %d due to just linked in server(s)",
- last_local_link_security, local_link_security);
+ unreal_log(ULOG_INFO, "link-security", "LOCAL_LINK_SECURITY_DOWNGRADED", NULL,
+ "Local link-security downgraded from level $previous_level to $new_level due to just linked in server(s)",
+ log_data_integer("previous_level", last_local_link_security),
+ log_data_integer("new_level", local_link_security));
warning_sent = 1;
}
if (global_link_security < last_global_link_security)
{
- sendto_realops("Global link-security downgraded from level %d to %d due to just linked in server(s)",
- last_global_link_security, global_link_security);
+ unreal_log(ULOG_INFO, "link-security", "GLOBAL_LINK_SECURITY_DOWNGRADED", NULL,
+ "Global link-security downgraded from level $previous_level to $new_level due to just linked in server(s)",
+ log_data_integer("previous_level", last_global_link_security),
+ log_data_integer("new_level", global_link_security));
warning_sent = 1;
}
@@ -225,12 +229,14 @@ EVENT(checklinksec)
if (warning_sent)
{
- sendto_realops("Effective (network-wide) link-security is: level %d", effective_link_security);
- sendto_realops("More information about this can be found at https://www.unrealircd.org/docs/Link_security");
+ unreal_log(ULOG_INFO, "link-security", "EFFECTIVE_LINK_SECURITY_REPORT", NULL,
+ "Effective (network-wide) link-security is now: level $effective_link_security\n"
+ "More information about this can be found at https://www.unrealircd.org/docs/Link_security",
+ log_data_integer("effective_link_security", effective_link_security));
}
}
-char *link_security_capability_parameter(Client *client)
+const char *link_security_capability_parameter(Client *client)
{
return valtostr(effective_link_security);
}
@@ -239,8 +245,6 @@ char *link_security_capability_parameter(Client *client)
CMD_FUNC(cmd_linksecurity)
{
Client *acptr;
- char *s;
- int v;
if (!IsOper(client))
{
@@ -253,15 +257,11 @@ CMD_FUNC(cmd_linksecurity)
sendtxtnumeric(client, "= By server =");
list_for_each_entry(acptr, &global_server_list, client_node)
{
- v = -1;
- s = moddata_client_get(acptr, "link-security");
+ const char *s = moddata_client_get(acptr, "link-security");
if (s)
- {
- v = atoi(s);
- sendtxtnumeric(client, "%s: level %d", acptr->name, v);
- } else {
+ sendtxtnumeric(client, "%s: level %d", acptr->name, atoi(s));
+ else
sendtxtnumeric(client, "%s: level UNKNOWN", acptr->name);
- }
}
sendtxtnumeric(client, "-");
@@ -271,9 +271,9 @@ CMD_FUNC(cmd_linksecurity)
sendtxtnumeric(client, "= Legend =");
sendtxtnumeric(client, "Higher level means better link security");
sendtxtnumeric(client, "Level UNKNOWN: Not an UnrealIRCd server (eg: services) or an old version (<4.0.14)");
- sendtxtnumeric(client, "Level 0: One or more servers linked insecurely (not using SSL/TLS)");
- sendtxtnumeric(client, "Level 1: Servers are linked with SSL/TLS but at least one of them is not verifying certificates");
- sendtxtnumeric(client, "Level 2: Servers linked with SSL/TLS and certificates are properly verified");
+ sendtxtnumeric(client, "Level 0: One or more servers linked insecurely (not using TLS)");
+ sendtxtnumeric(client, "Level 1: Servers are linked with TLS but at least one of them is not verifying certificates");
+ sendtxtnumeric(client, "Level 2: Servers linked with TLS and certificates are properly verified");
sendtxtnumeric(client, "-");
sendtxtnumeric(client, "= More information =");
sendtxtnumeric(client, "To understand more about link security and how to improve your level");
diff --git a/src/modules/links.c b/src/modules/links.c
index 6036cc7..041bd97 100644
--- a/src/modules/links.c
+++ b/src/modules/links.c
@@ -32,7 +32,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /links",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
@@ -69,7 +69,7 @@ CMD_FUNC(cmd_links)
sendnumeric(client, RPL_LINKS, acptr->name, me.name,
1, (acptr->info[0] ? acptr->info : "(Unknown Location)"));
else
- sendnumeric(client, RPL_LINKS, acptr->name, acptr->serv->up,
+ sendnumeric(client, RPL_LINKS, acptr->name, acptr->uplink ? acptr->uplink->name : me.name,
acptr->hopcount, (acptr->info[0] ? acptr->info : "(Unknown Location)"));
}
diff --git a/src/modules/list.c b/src/modules/list.c
index ab4bdea..f7ece82 100644
--- a/src/modules/list.c
+++ b/src/modules/list.c
@@ -33,7 +33,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /list",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
typedef struct ChannelListOptions ChannelListOptions;
@@ -54,6 +54,7 @@ struct ChannelListOptions {
/* Global variables */
ModDataInfo *list_md = NULL;
+char modebuf[BUFSIZE], parabuf[BUFSIZE];
/* Macros */
#define CHANNELLISTOPTIONS(x) ((ChannelListOptions *)moddata_local_client(x, list_md).ptr)
@@ -125,6 +126,7 @@ CMD_FUNC(cmd_list)
NameList *nolist = NULL;
int ntargets = 0;
int maxtargets = max_targets_for_command("LIST");
+ char request[BUFSIZE];
static char *usage[] = {
" Usage: /LIST ",
@@ -187,8 +189,8 @@ CMD_FUNC(cmd_list)
usermin = 0; /* Minimum of 0 */
usermax = -1; /* No maximum */
- for (name = strtoken(&p, parv[1], ","); name && !error;
- name = strtoken(&p, NULL, ","))
+ strlcpy(request, parv[1], sizeof(request));
+ for (name = strtoken(&p, request, ","); name && !error; name = strtoken(&p, NULL, ","))
{
if (MyUser(client) && (++ntargets > maxtargets))
{
@@ -269,21 +271,17 @@ CMD_FUNC(cmd_list)
}
else /* Just a normal channel */
{
- channel = find_channel(name, NULL);
+ channel = find_channel(name);
if (channel && (ShowChannel(client, channel) || ValidatePermissionsForPath("channel:see:list:secret",client,NULL,channel,NULL))) {
-#ifdef LIST_SHOW_MODES
modebuf[0] = '[';
- channel_modes(client, modebuf+1, parabuf, sizeof(modebuf)-1, sizeof(parabuf), channel);
+ 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);
-#endif
sendnumeric(client, RPL_LIST,
name, channel->users,
-#ifdef LIST_SHOW_MODES
modebuf,
-#endif
(channel->topic ? channel->topic :
""));
}
@@ -343,13 +341,11 @@ int send_list(Client *client)
ConfigItem_offchans *x;
for (x = conf_offchans; x; x = x->next)
{
- if (find_channel(x->chname, NULL))
+ if (find_channel(x->name))
continue; /* exists, >0 users.. will be sent later */
- sendnumeric(client, RPL_LIST, x->chname,
+ sendnumeric(client, RPL_LIST, x->name,
0,
-#ifdef LIST_SHOW_MODES
"",
-#endif
x->topic ? x->topic : "");
}
}
@@ -366,11 +362,11 @@ int send_list(Client *client)
continue;
/* set::hide-list { deny-channel } */
- if (!IsOper(client) && iConf.hide_list && find_channel_allowed(client, channel->chname))
+ if (!IsOper(client) && iConf.hide_list && find_channel_allowed(client, channel->name))
continue;
/* Similarly, hide unjoinable channels for non-ircops since it would be confusing */
- if (!IsOper(client) && !valid_channelname(channel->chname))
+ if (!IsOper(client) && !valid_channelname(channel->name))
continue;
/* Much more readable like this -- codemastr */
@@ -394,39 +390,33 @@ int send_list(Client *client)
continue;
/* Must not be on nolist (if it exists) */
- if (lopt->nolist && find_name_list_match(lopt->nolist, channel->chname))
+ if (lopt->nolist && find_name_list_match(lopt->nolist, channel->name))
continue;
/* Must be on yeslist (if it exists) */
- if (lopt->yeslist && !find_name_list_match(lopt->yeslist, channel->chname))
+ if (lopt->yeslist && !find_name_list_match(lopt->yeslist, channel->name))
continue;
}
-#ifdef LIST_SHOW_MODES
modebuf[0] = '[';
- channel_modes(client, modebuf+1, parabuf, sizeof(modebuf)-1, sizeof(parabuf), channel);
+ 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);
-#endif
if (!ValidatePermissionsForPath("channel:see:list:secret",client,NULL,channel,NULL))
sendnumeric(client, RPL_LIST,
ShowChannel(client,
- channel) ? channel->chname :
+ channel) ? channel->name :
"*", channel->users,
-#ifdef LIST_SHOW_MODES
ShowChannel(client, channel) ?
modebuf : "",
-#endif
ShowChannel(client,
channel) ? (channel->topic ?
channel->topic : "") : "");
else
- sendnumeric(client, RPL_LIST, channel->chname,
+ sendnumeric(client, RPL_LIST, channel->name,
channel->users,
-#ifdef LIST_SHOW_MODES
modebuf,
-#endif
(channel->topic ? channel->topic : ""));
numsend--;
}
diff --git a/src/modules/locops.c b/src/modules/locops.c
index 5437385..1943d87 100644
--- a/src/modules/locops.c
+++ b/src/modules/locops.c
@@ -32,7 +32,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /locops",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
@@ -58,9 +58,7 @@ MOD_UNLOAD()
*/
CMD_FUNC(cmd_locops)
{
- char *message;
-
- message = parc > 1 ? parv[1] : NULL;
+ const char *message = parc > 1 ? parv[1] : NULL;
if (BadPtr(message))
{
diff --git a/src/modules/lusers.c b/src/modules/lusers.c
index 4059eb4..3f07805 100644
--- a/src/modules/lusers.c
+++ b/src/modules/lusers.c
@@ -32,7 +32,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /lusers",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
@@ -59,7 +59,7 @@ CMD_FUNC(cmd_lusers)
{
char flatmap;
- if (hunt_server(client, recv_mtags, ":%s LUSERS :%s", 1, parc, parv) != HUNTED_ISME)
+ if (hunt_server(client, recv_mtags, "LUSERS", 1, parc, parv) != HUNTED_ISME)
return;
flatmap = (FLAT_MAP && !ValidatePermissionsForPath("server:info:lusers",client,NULL,NULL,NULL)) ? 1 : 0;
@@ -83,12 +83,14 @@ char flatmap;
sendnumeric(client, RPL_LUSERME, irccounts.me_clients, flatmap ? 0 : irccounts.me_servers);
sendnumeric(client, RPL_LOCALUSERS, irccounts.me_clients, irccounts.me_max, irccounts.me_clients, irccounts.me_max);
sendnumeric(client, RPL_GLOBALUSERS, irccounts.clients, irccounts.global_max, irccounts.clients, irccounts.global_max);
- if ((irccounts.me_clients + irccounts.me_servers) > max_connection_count)
+ if (irccounts.me_clients > max_connection_count)
{
- max_connection_count =
- irccounts.me_clients + irccounts.me_servers;
+ max_connection_count = irccounts.me_clients;
if (max_connection_count % 10 == 0) /* only send on even tens */
- sendto_ops("New record on this server: %d connections (%d clients)",
- max_connection_count, irccounts.me_clients);
+ {
+ unreal_log(ULOG_INFO, "client", "NEW_USER_RECORD", NULL,
+ "New record on this server: $num_users connections",
+ log_data_integer("num_users", max_connection_count));
+ }
}
}
diff --git a/src/modules/map.c b/src/modules/map.c
index a0c8aa4..1f57e9e 100644
--- a/src/modules/map.c
+++ b/src/modules/map.c
@@ -32,7 +32,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /map",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
MOD_INIT()
@@ -71,7 +71,7 @@ static void dump_map(Client *client, Client *server, char *mask, int prompt_leng
else
{
sendnumeric(client, RPL_MAP, prompt,
- length, server->name, server->serv->users, IsOper(client) ? server->id : "");
+ length, server->name, server->server->users, IsOper(client) ? server->id : "");
cnt = 0;
}
@@ -88,7 +88,7 @@ static void dump_map(Client *client, Client *server, char *mask, int prompt_leng
list_for_each_entry(acptr, &global_server_list, client_node)
{
- if (acptr->srvptr != server ||
+ if (acptr->uplink != server ||
(IsULine(acptr) && HIDE_ULINES && !ValidatePermissionsForPath("server:info:map:ulines",client,NULL,NULL,NULL)))
continue;
SetMap(acptr);
@@ -99,7 +99,7 @@ static void dump_map(Client *client, Client *server, char *mask, int prompt_leng
{
if (IsULine(acptr) && HIDE_ULINES && !ValidatePermissionsForPath("server:info:map:ulines",client,NULL,NULL,NULL))
continue;
- if (acptr->srvptr != server)
+ if (acptr->uplink != server)
continue;
if (!IsMap(acptr))
continue;
@@ -120,7 +120,7 @@ void dump_flat_map(Client *client, Client *server, int length)
hide_ulines = (HIDE_ULINES && !ValidatePermissionsForPath("server:info:map:ulines",client,NULL,NULL,NULL)) ? 1 : 0;
- sendnumeric(client, RPL_MAP, "", length, server->name, server->serv->users, "");
+ sendnumeric(client, RPL_MAP, "", length, server->name, server->server->users, "");
list_for_each_entry(acptr, &global_server_list, client_node)
{
@@ -136,7 +136,7 @@ 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->serv->users, "");
+ sendnumeric(client, RPL_MAP, buf, length-2, acptr->name, acptr->server->users, "");
}
}
diff --git a/src/modules/md.c b/src/modules/md.c
index 485e8a4..ba735b9 100644
--- a/src/modules/md.c
+++ b/src/modules/md.c
@@ -14,7 +14,7 @@ ModuleHeader MOD_HEADER
"5.0",
"command /MD (S2S only)",
"UnrealIRCd Team",
- "unrealircd-5",
+ "unrealircd-6",
};
CMD_FUNC(cmd_md);
@@ -23,11 +23,13 @@ void _broadcast_md_channel(ModDataInfo *mdi, Channel *channel, ModData *md);
void _broadcast_md_member(ModDataInfo *mdi, Channel *channel, Member *m, ModData *md);
void _broadcast_md_membership(ModDataInfo *mdi, Client *client, Membership *m, ModData *md);
void _broadcast_md_globalvar(ModDataInfo *mdi, ModData *md);
-void _broadcast_md_client_cmd(Client *except, Client *sender, Client *client, char *varname, char *value);
-void _broadcast_md_channel_cmd(Client *except, Client *sender, Channel *channel, char *varname, char *value);
-void _broadcast_md_member_cmd(Client *except, Client *sender, Channel *channel, Client *client, char *varname, char *value);
-void _broadcast_md_membership_cmd(Client *except, Client *sender, Client *client, Channel *channel, char *varname, char *value);
-void _broadcast_md_globalvar_cmd(Client *except, Client *sender, char *varname, char *value);
+void _broadcast_md_client_cmd(Client *except, Client *sender, Client *client, const char *varname, const char *value);
+void _broadcast_md_channel_cmd(Client *except, Client *sender, Channel *channel, const char *varname, const char *value);
+void _broadcast_md_member_cmd(Client *except, Client *sender, Channel *channel, Client *client, const char *varname, const char *value);
+void _broadcast_md_membership_cmd(Client *except, Client *sender, Client *client, Channel *channel, const char *varname, const char *value);
+void _broadcast_md_globalvar_cmd(Client *except, Client *sender, const char *varname, const char *value);
+void _moddata_add_s2s_mtags(Client *client, MessageTag **mtags);
+void _moddata_extract_s2s_mtags(Client *client, MessageTag *mtags);
void _send_moddata_client(Client *srv, Client *client);
void _send_moddata_channel(Client *srv, Channel *channel);
void _send_moddata_members(Client *srv);
@@ -48,6 +50,8 @@ MOD_TEST()
EfunctionAddVoid(modinfo->handle, EFUNC_BROADCAST_MD_MEMBER_CMD, _broadcast_md_member_cmd);
EfunctionAddVoid(modinfo->handle, EFUNC_BROADCAST_MD_MEMBERSHIP_CMD, _broadcast_md_membership_cmd);
EfunctionAddVoid(modinfo->handle, EFUNC_BROADCAST_MD_GLOBALVAR_CMD, _broadcast_md_globalvar_cmd);
+ EfunctionAddVoid(modinfo->handle, EFUNC_MODDATA_ADD_S2S_MTAGS, _moddata_add_s2s_mtags);
+ EfunctionAddVoid(modinfo->handle, EFUNC_MODDATA_EXTRACT_S2S_MTAGS, _moddata_extract_s2s_mtags);
EfunctionAddVoid(modinfo->handle, EFUNC_SEND_MODDATA_CLIENT, _send_moddata_client);
EfunctionAddVoid(modinfo->handle, EFUNC_SEND_MODDATA_CHANNEL, _send_moddata_channel);
EfunctionAddVoid(modinfo->handle, EFUNC_SEND_MODDATA_MEMBERS, _send_moddata_members);
@@ -72,6 +76,25 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
+/** Check if client may write to this MD object */
+int md_access_check(Client *client, ModDataInfo *md, Client *target)
+{
+ if ((client == target) && md->self_write)
+ return 1;
+
+ if (MyConnect(target) && !md->remote_write)
+ {
+ unreal_log(ULOG_WARNING, "md", "REMOTE_MD_WRITE_DENIED", client,
+ "Remote server $client tried to write moddata $moddata_name "
+ "of a client from ours ($target.name) -- attempt BLOCKED",
+ log_data_string("moddata_name", md->name),
+ log_data_client("target", target));
+ return 0;
+ }
+
+ return 1;
+}
+
/** Set ModData command.
* Syntax: MD