diff --git 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 Now the actual build
-call extras\build-tests\windows\compilecmd\%SHORTNAME%.bat
+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 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 Now the actual build
+rem - First this, otherwise JOM will fail
+IF NOT EXIST src\version.c nmake -f Makefile.windows CONF
+rem - Then build most of UnrealIRCd.exe etc
+call extras\build-tests\windows\compilecmd\%SHORTNAME%.bat UNREALSVC.EXE UnrealIRCd.exe
+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
@@ -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
Binary files differ.
diff --git 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
@@ -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
@@ -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
Binary files differ.
diff --git a/extras/jansson.tar.gz b/extras/jansson.tar.gz
Binary files differ.
diff --git 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 {
+typedef struct Cmode Cmode;
+struct Cmode {
+ Cmode *prev, *next;
+
/** mode character (like 'Z') */
- char flag;
+ char letter;
+
+ CmodeType type;
- /** unique flag (like 0x10) */
+ /** 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 *);
-
- /** 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!!
+ const char *(*conv_param)(BanContext *b, Extban *handler);
+
+ /** 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, NULL); \
+})
+#define HookAddConstString(module, hooktype, priority, func) \
__extension__ ({ \
ValidateHooks(hooktype, func); \
- HookAddMain(module, hooktype, priority, NULL, NULL, 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) \
-{ \
- int retval; \
- Hook *h; \
- for (h = Hooks[hooktype]; h; h = h->next) \
- { \
- retval = (*(h->func.intfunc))(x); \
- if (retval retchk) return; \
- } \
-}
-#define RunHookReturn2(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; \
- } \
-}
-#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) \
+#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))(a,b,c,d); \
+ retval = (*(h->func.intfunc))(__VA_ARGS__); \
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) \
+#define RunHookReturnInt(hooktype,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(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)());
+#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)
+
+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 int LoadPersistentPointerX(ModuleInfo *modinfo, char *varshortname, void **var, void (*free_variable)(ModData *m));
+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, 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
@@ -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
@@ -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
@@ -1,68 +0,0 @@
-/************************************************************************
- * Unreal Internet Relay Chat Daemon, include/proto.h
- * (C) Dominick Meglio <codemastr@unrealircd.com> 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
@@ -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 <unistd.h> 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
@@ -39,6 +39,7 @@
#include <openssl/rand.h>
#include <openssl/md5.h>
#include <openssl/ripemd.h>
+#include <jansson.h>
#include "common.h"
#include "sys.h"
#include <stdio.h>
@@ -54,6 +55,14 @@
# ifdef SYSSYSLOGH
# include <sys/syslog.h>
# 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 <index> in logs[<index>] and temp_logs[<index>] */
+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 <sodium.h>
@@ -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 since<currenttime+10) */
- time_t firsttime; /**< Time user was created (connected on IRC) */
- time_t lasttime; /**< Last time any message was received */
+ SSL *ssl; /**< OpenSSL/LibreSSL struct for TLS connection */
+ time_t fake_lag; /**< Time when user will next be allowed to send something (actually fake_lag<currenttime+10) */
+ int fake_lag_msec; /**< Used for calculating 'fake_lag' penalty (modulo) */
+ time_t creationtime; /**< Time user was created (connected on IRC) */
+ time_t last_msg_received; /**< Last time any message was received */
dbuf sendQ; /**< Outgoing send queue (data to be sent) */
dbuf recvQ; /**< Incoming receive queue (incoming data yet to be parsed) */
ConfigItem_class *class; /**< The class { } block associated to this client */
@@ -1279,27 +1302,16 @@ struct LocalClient {
u_char targets[MAXCCUSERS]; /**< Hash values of targets for target limiting */
ConfigItem_listen *listener; /**< If this client IsListening() then this is the listener configuration attached to it */
long serial; /**< Current serial number for send.c functions (to avoid sending duplicate messages) */
- time_t nextnick; /**< Time the next nick change will be allowed */
- time_t last; /**< Last time a RESETIDLE message was received (PRIVMSG) */
- long sendM; /**< Statistics: protocol messages send */
- long sendK; /**< Statistics: total k-bytes send */
- long receiveM; /**< Statistics: protocol messages received */
- long receiveK; /**< Statistics: total k-bytes received */
- u_short sendB; /**< Statistics: counters to count upto 1-k lots of bytes */
- u_short receiveB; /**< Statistics: sent and received (???) */
- short lastsq; /**< # of 2k blocks when sendqueued called last */
- Link *watch; /**< Watch notification list (WATCH) for this user */
- u_short watches; /**< Number of entries in the watch list */
+ time_t next_nick_allowed; /**< Time the next nick change will be allowed */
+ time_t idle_since; /**< Last time a RESETIDLE message was received (PRIVMSG) */
+ TrafficStats traffic; /**< Traffic statistics */
ModData moddata[MODDATA_MAX_LOCAL_CLIENT]; /**< LocalClient attached module data, used by the ModData system */
-#ifdef DEBUGMODE
- time_t cputime; /**< Something with debugging (why is this a time_t? TODO) */
-#endif
char *error_str; /**< Quit reason set by dead_socket() in case of socket/buffer error, later used by exit_client() */
char sasl_agent[NICKLEN + 1]; /**< SASL: SASL Agent the user is interacting with */
unsigned char sasl_out; /**< SASL: Number of outgoing sasl messages */
unsigned char sasl_complete; /**< SASL: >0 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
@@ -55,9 +55,6 @@
#endif /* HAVE_INTTYPES_H */
#endif /* HAVE_STDINT_H */
-#ifdef SSL
-#include <openssl/ssl.h>
-#endif
#ifndef _WIN32
#include <netinet/in.h>
#include <sys/socket.h>
diff --git 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 <time.h>
#include <sys/stat.h>
@@ -31,7 +30,6 @@
#include <fcntl.h>
#include <signal.h>
#include "h.h"
-#include "url.h"
#include "version.h"
#ifdef USE_LIBCURL
#include <curl/curl.h>
diff --git a/include/url.h b/include/url.h
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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));
}
-/** Initialize the extended channel modes system */
-void extcmode_init(void)
+void make_prefix(char **isupport_prefix, char **isupport_statusmsg)
{
- Cmode_t val = 1;
- int i;
- Channelmode_Table = safe_alloc(sizeof(Cmode) * EXTCMODETABLESZ);
- for (i = 0; i < EXTCMODETABLESZ; i++)
+ 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)
{
- Channelmode_Table[i].mode = val;
- val *= 2;
+ 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);
}
- Channelmode_highest = 0;
+
+ *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)
+{
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)
+
+ if (!cm)
{
- Debug((DEBUG_DEBUG, "CmodeAdd failed, no space"));
- if (module)
- module->errorcode = MODERR_NOSPACE;
- return NULL;
+ 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)
+ 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;
-
- if (Channelmode_Table[i].paracount == 1)
- extcmode_para_addslot(&Channelmode_Table[i], paraslot);
-
+ 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 (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;
+ if (channel->mode.mode & cmode->mode)
+ {
+ 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->name, cmode->letter);
+ sendto_server(NULL, 0, 0, mtags,
+ ":%s MODE %s -%c 0",
+ me.id, channel->name, cmode->letter);
+ free_message_tags(mtags);
+
+ 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)
{
- /* Parameter mode, more complicated */
for (channel = channels; channel; channel = channel->nextch)
{
- if (channel->mode.extmode & cmode->mode)
+ Member *m;
+ for (m = channel->members; m; m = m->next)
{
- MessageTag *mtags = NULL;
-
- new_message(&me, NULL, &mtags);
- if (cmode->unset_with_param)
+ if (strchr(m->member_modes, cmode->letter))
{
- char *param = cmode->get_param(GETPARASTRUCT(channel, cmode->flag));
+ 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->chname, cmode->flag, param);
+ me.name, channel->name, cmode->letter, m->client->name);
sendto_server(NULL, 0, 0, mtags,
":%s MODE %s -%c %s 0",
- me.id, channel->chname, cmode->flag, param);
- } else {
- 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);
+ me.id, channel->name, cmode->letter, m->client->id);
+ free_message_tags(mtags);
+ del_member_mode(m->client, channel, cmode->letter);
}
- free_message_tags(mtags);
-
- cmode->free_param(GETPARASTRUCT(channel, cmode->flag));
- channel->mode.extmode &= ~cmode->mode;
}
}
- 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;
+
+ for (cm=channelmodes; cm; cm = cm->next)
+ if ((cm->letter) && (cm->owner == mod) && (cm->paracount))
+ return 1;
+
+ 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;
- while (i < EXTCMODETABLESZ)
+ 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++)
{
- if ((Channelmode_Table[i].flag) &&
- (Channelmode_Table[i].owner == mod) &&
- (Channelmode_Table[i].paracount))
+ cm = find_channel_mode_handler(*p);
+ if (!cm)
+ continue; /* wtf */
+ if (cm->rank < my_rank)
{
- return 1;
+ /* We need to insert us here */
+ n = strlen(p);
+ memmove(p+1, p, n+1); // +1 for NUL byte
+ *p = letter;
+ return;
}
- i++;
}
- return 0;
+ /* 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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, ':');
+
+ if (!p || !p[1])
+ {
+ if (remainder)
+ *remainder = NULL;
+ return NULL;
+ }
+ if (remainder)
+ *remainder = p+1;
- for (i=0; i <= ExtBan_highest; i++)
- if (ExtBan_Table[i].flag == c)
- return &ExtBan_Table[i];
+ 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 (!req.name)
+ {
+ 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;
+ }
- if (findmod_by_bantype(req.flag))
+ if (!req.is_banned_events && req.is_banned)
{
- if (module)
- module->errorcode = MODERR_EXISTS;
- return NULL;
+ 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;
}
- /* 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 (!isalnum(req.letter))
{
- if (module)
- module->errorcode = MODERR_NOSPACE;
+ 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;
}
- 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 (!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))
{
+ const char *nextbanstr;
+ Extban *extban = 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; /* Fail: more than one stacked extban */
+ return 0; /* Rule #1 violation (more than one stacked extban) */
- if ((checkt == EXBCHK_PARAM) && RESTRICT_EXTENDEDBANS && !ValidatePermissionsForPath("immune:restrict-extendedbans",client,NULL,channel,NULL))
+ 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. */
}
+
+ 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 (p->is_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))
+ if (!is_extended_ban(b->banstr))
+ return extban_conv_param_nuh(b, self_extban);
+
+ /* 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)
{
- /* 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;
+ /* Handling unknown bantypes in is_ok. Assume that it's ok here. */
+ return b->banstr;
+ }
- /* 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;
+ b->banstr = nextbanstr;
+
+ if ((extban->options & EXTBOPT_ACTMODIFIER) || (extban->options & EXTBOPT_NOSTACKCHILD))
+ {
+ /* Rule #2 violation */
+ return NULL;
}
- else
+
+ 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)
{
- return extban_conv_param_nuh(para);
+ 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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,203 +112,148 @@ void umodes_check_for_changes(void)
strlcpy(previous_umodestring, umodestring, sizeof(previous_umodestring));
}
-/* 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)
+void usermode_add_sorted(Umode *n)
{
- short i = 0;
- short j = 0;
- short save = -1;
- while (i < UMODETABLESZ)
+ Umode *m;
+
+ if (usermodes == NULL)
{
- if (!Usermode_Table[i].flag && save == -1)
- save = i;
- else if (Usermode_Table[i].flag == ch)
+ 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))
{
- if (Usermode_Table[i].unloaded)
- {
- save = i;
- Usermode_Table[i].unloaded = 0;
- break;
- }
+ /* Insert us before */
+ if (m->prev)
+ m->prev->next = n;
else
- {
- if (module)
- module->errorcode = MODERR_EXISTS;
- return NULL;
- }
+ usermodes = n; /* new head */
+ n->prev = m->prev;
+
+ n->next = m;
+ m->prev = n;
+ return;
}
- i++;
- }
- i = save;
- if (i != UMODETABLESZ)
- {
- 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)
+ if (!m->next)
{
- ModuleObject *umodeobj = safe_alloc(sizeof(ModuleObject));
- umodeobj->object.umode = &(Usermode_Table[i]);
- umodeobj->type = MOBJ_UMODE;
- AddListItem(umodeobj, module->objects);
- module->errorcode = MODERR_NOERROR;
+ /* Append us at end */
+ m->next = n;
+ n->prev = m;
+ return;
}
- return &(Usermode_Table[i]);
- }
- else
- {
- Debug((DEBUG_DEBUG, "UmodeAdd failed, no space"));
- if (module)
- module->errorcode = MODERR_NOSPACE;
- return NULL;
}
}
-void UmodeDel(Umode *umode)
+/* 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)
{
- if (loop.ircd_rehashing)
- umode->unloaded = 1;
- else
- {
- 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();
- }
+ Umode *um;
+ int existing = 0;
- if (umode->owner) {
- ModuleObject *umodeobj;
- 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;
- }
- }
- 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)
+ for (um=usermodes; um; um = um->next)
{
- if (!Snomask_Table[i].flag && save == -1)
- save = i;
- else if (Snomask_Table[i].flag == ch)
+ if (um->letter == ch)
{
- if (Snomask_Table[i].unloaded)
+ if (um->unloaded)
{
- save = i;
- Snomask_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)
{
- 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)
+ /* Not found, create */
+ long l, found = 0;
+ for (l = 1; l < LONG_MAX/2; l *= 2)
{
- ModuleObject *snoobj = safe_alloc(sizeof(ModuleObject));
- snoobj->object.snomask = &(Snomask_Table[i]);
- snoobj->type = MOBJ_SNOMASK;
- AddListItem(snoobj, 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;
+ }
+ /* 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;
}
- return &(Snomask_Table[i]);
+ 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, "SnomaskAdd failed, no space"));
- *mode = 0;
- 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 SnomaskDel(Snomask *sno)
+
+void UmodeDel(Umode *umode)
{
- if (loop.ircd_rehashing)
- sno->unloaded = 1;
- else
+ /* Always free the module object */
+ if (umode->owner)
{
- Client *client;
-
- list_for_each_entry(client, &lclient_list, lclient_node)
+ ModuleObject *umodeobj;
+ for (umodeobj = umode->owner->objects; umodeobj; umodeobj = umodeobj->next)
{
- 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);
+ if (umodeobj->type == MOBJ_UMODE && umodeobj->object.umode == umode)
+ {
+ DelListItem(umodeobj, umode->owner->objects);
+ safe_free(umodeobj);
break;
}
}
- sno->owner = NULL;
+ umode->owner = NULL;
}
- return;
+
+ /* Whether we can actually (already) free the Umode depends... */
+
+ if (loop.rehashing)
+ umode->unloaded = 1;
+ else
+ 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
@@ -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: $<salt>$<hash> */
@@ -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
@@ -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
@@ -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++;
-
- 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);
- }
+ if (!client->user)
+ return;
+
+ 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 1;
- tab++;
- }
+ return 0; /* Not found */
+}
- /* Special handling for +l (needed??) */
- if (channel->mode.limit && (mode == 'l'))
- return 1;
+/** 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;
- /* Special handling for +k (needed??) */
- if (channel->mode.key[0] && (mode == 'k'))
- return 1;
+ for (cm=channelmodes; cm; cm = cm->next)
+ if ((cm->letter == mode) && (m & cm->mode))
+ 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;
- }
- return 0;
-}
+ Cmode *cm;
-/** Get the extended channel mode character (eg: 'Z') by the 'bit' value (eg: 0x20) */
-long get_mode_bitbychar(char m)
-{
- CoreChannelModeTable *tab = &corechannelmodetable[0];
+ for (cm=channelmodes; cm; cm = cm->next)
+ if (cm->letter == m)
+ return cm->mode;
- while(tab->mode != 0x0)
- {
- if (tab->flag == m)
- return tab->mode;
- tab++;;
- }
- return 0;
+ 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)
- {
- if ((channel->mode.mode & tab->mode))
- if (!tab->parameters) {
- *mbuf++ = tab->flag;
- mbuf_size--;
- }
- tab++;
- }
- for (i=0; i <= Channelmode_highest; i++)
+ for (cm=channelmodes; cm; cm = cm->next)
{
- 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 ":<char>" 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,120 +894,66 @@ 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)
- {
- len = CHANNELLEN;
- *(chname + CHANNELLEN) = '\0';
- }
- if ((channel = find_channel(chname, NULL)))
- return (channel);
- if (flag == CREATE)
+ /* Copy and silently truncate */
+ strlcpy(namebuf, name, sizeof(namebuf));
+
+ /* Copied from valid_channelname(), the minimal requirements */
+ for (p = namebuf; *p; p++)
{
- 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;
+ }
}
- 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;
+ /* Exists? Return it. */
+ if ((channel = find_channel(name)))
+ return channel;
- 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);
+ channel = mp_pool_get(channel_pool);
+ memset(channel, 0, sizeof(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;
+ strlcpy(channel->name, name, sizeof(channel->name));
- RunHook4(HOOKTYPE_INVITE, from, to, channel, mtags);
-}
+ if (channels)
+ channels->prevch = channel;
-/** 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;
+ 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++;
- for (inv = &(channel->invites); (tmp = *inv); inv = &tmp->next)
- if (tmp->value.client == client)
- {
- *inv = tmp->next;
- free_link(tmp);
- break;
- }
+ RunHook(HOOKTYPE_CHANNEL_CREATE, channel);
- for (inv = &(client->user->invited); (tmp = *inv); inv = &tmp->next)
- if (tmp->value.channel == channel)
- {
- *inv = tmp->next;
- free_link(tmp);
- break;
- }
+ return channel;
}
/** Is the user 'client' invited to channel 'channel' by a chanop?
@@ -1046,12 +962,9 @@ void del_invite(Client *client, Channel *channel)
*/
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
@@ -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 },
@@ -159,22 +150,6 @@ static NameValue _LinkFlags[] = {
};
/* 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" },
{ TLSFLAG_DISABLECLIENTCERT, "no-client-certificate" },
@@ -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++)
- {
- if (tab->flag == *modes)
- {
- if (tab->parameters)
- {
- /* INCOMPATIBLE */
- break;
- }
- store->mode |= tab->mode;
- break;
- }
- }
- /* Try extcmodes */
- if (!tab->mode)
+
+ found = 0;
+ for (cm=channelmodes; cm; cm = cm->next)
{
- int i;
- for (i=0; i <= Channelmode_highest; i++)
+ if (!(cm->letter))
+ continue;
+ if (*m == cm->letter)
{
- if (!(Channelmode_Table[i].flag))
- continue;
- if (*modes == Channelmode_Table[i].flag)
+ found = 1;
+ if (cm->paracount)
{
- if (Channelmode_Table[i].paracount)
+ if (!param)
{
- 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, " ");
+ config_warn("set::modes-on-join '%s'. Parameter missing for mode %c.", modes, *m);
+ break;
}
- store->extmodes |= Channelmode_Table[i].mode;
- 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->extmodes |= cm->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++)
- {
- if (modes->mode & tab->mode)
- {
- if (!tab->parameters)
- {
- *mbuf++ = tab->flag;
- if (!--mbuf_size)
- {
- *--mbuf=0;
- break;
- }
- }
- }
- }
- for (i=0; i <= Channelmode_highest; i++)
+
+ for (cm=channelmodes; cm; cm = cm->next)
{
- 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 0; /* 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 */
-}
+ return "q";
-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 */
+ return NULL; /* unknown or unsupported */
}
-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>: 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>: 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.");
- }
-
- /* 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, "<internally added by ircd>"))
- {
- 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~");
- }
+ 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.");
}
- 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)
+{
+ 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)
{
- char *old_pid_file = NULL;
+ 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())
+
+ if (!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))
+ 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)
{
- sendto_ops("pidfile is being rewritten to %s, please delete %s",
- conf_files->pid_file,
- old_pid_file);
- write_pidfile();
+ if (!h->owner)
+ continue;
+ if (!(h->owner->options & MOD_OPT_PERM))
+ continue;
+ (*(h->func.intfunc))();
}
- safe_free(old_pid_file);
}
- else
+ config_pre_run_log();
+
+ Init_all_testing_modules();
+
+ if (config_run_blocks() < 0)
{
- config_error("IRCd configuration failed to load");
- Unload_all_testing_modules();
- unload_notloaded_includes();
- config_free(conf);
- conf = NULL;
- free_iConf(&tempiConf);
+ config_error("Bad case of config errors. Server will now die. This really shouldn't happen");
#ifdef _WIN32
- if (!rehash)
+ if (!loop.rehashing)
win_error();
#endif
- return -1;
+ 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))
+#ifndef _WIN32
+ if (rs->file && !strcmp(filename, rs->file))
+#else
+ if (rs->file && !strcasecmp(filename, rs->file))
+#endif
{
counter ++;
continue;
}
-#endif
-#ifdef USE_LIBCURL
- if (inc->url && !strcmp(original_path, inc->url))
+ if (rs->url && !strcmp(display_name, rs->url))
{
counter ++;
continue;
}
-#endif
- }
- if (counter < 1 || !my_inc)
- {
- /*
- * 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)
+ if (counter > 1)
{
- 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;
+
+ /* First, all the log { } blocks everywhere */
+ for (cfptr = conf; cfptr; cfptr = cfptr->next)
+ {
+ if (config_verbose > 1)
+ config_status("Testing %s", cfptr->filename);
+ /* First test and run the log { } blocks */
+ for (ce = cfptr->items; ce; ce = ce->next)
+ {
+ if (!strcmp(ce->name, "log"))
+ errors += config_test_log(cfptr, ce);
+ }
+ }
- for (cfptr = conf; cfptr; cfptr = cfptr->cf_next)
+ for (cfptr = conf; cfptr; cfptr = cfptr->next)
{
if (config_verbose > 1)
- config_status("Testing %s", cfptr->cf_filename);
+ config_status("Testing %s", cfptr->filename);
/* First test and run the secret { } blocks */
- for (ce = cfptr->cf_entries; ce; ce = ce->ce_next)
+ for (ce = cfptr->items; ce; ce = ce->next)
{
- if (!strcmp(ce->ce_varname, "secret"))
+ 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->ce_vardata, CONFDIR);
+ convert_to_absolute_path(&ce->value, CONFDIR);
-#ifdef USE_LIBCURL
- if (url_is_valid(ce->ce_vardata))
- return remote_include(ce);
-#else
- if (strstr(ce->ce_vardata, "://"))
- {
- 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;
+ if (url_is_valid(ce->value))
+ {
+ 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))
+ if (strlen(cep->value) > HOSTLEN)
{
- 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);
+ config_error("%s:%i: illegal me::name, must be less or equal to %i characters",
+ cep->file->filename,
+ cep->line_number, HOSTLEN);
errors++;
}
- if (strlen(cep->ce_vardata) > HOSTLEN)
+ if (!valid_server_name(cep->value))
{
- config_error("%s:%i: illegal me::name, must be less or equal to %i characters",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, HOSTLEN);
+ 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)
- {
- 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);
+ for (cep = ce->items; cep; cep = cep->next)
+ {
+ 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;
}
/* <random directive here> */
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);
+
+ oper->server_notice_colors = tempiConf.server_notice_colors; /* default */
- for (cep = ce->ce_entries; cep; cep = cep->ce_next)
+ 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)
- {
- 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"))
- {
- for (cep2 = cep->ce_entries; cep2; cep2 = cep2->ce_next)
- if (!strcmp(cep2->ce_varname, "nofakelag"))
+ for (cep = ce->items; cep; cep = cep->next)
+ {
+ 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->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);
- }
- }
- else if (!strcmp(cep->ce_varname, "hostname"))
- {
- if (has_hostname)
- {
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "allow::hostname");
- continue;
+ cep->file->filename, cep->line_number);
}
- 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: 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::ip or allow::hostname",
- ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
+ 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"))
- {
- link->class = find_class(cep->ce_vardata);
+ 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->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->name, "static-quit")) {
+ safe_strdup(tempiConf.static_quit, cep->value);
}
- else if (!strcmp(cep->ce_varname, "static-part")) {
- safe_strdup(tempiConf.static_part, cep->ce_vardata);
+ else if (!strcmp(cep->name, "static-part")) {
+ safe_strdup(tempiConf.static_part, cep->value);
}
- else if (!strcmp(cep->ce_varname, "who-limit")) {
- tempiConf.who_limit = atol(cep->ce_vardata);
+ else if (!strcmp(cep->name, "who-limit")) {
+ tempiConf.who_limit = atol(cep->value);
}
- else if (!strcmp(cep->ce_varname, "maxbans")) {
- tempiConf.maxbans = atol(cep->ce_vardata);
+ else if (!strcmp(cep->name, "maxbans")) {
+ tempiConf.maxbans = atol(cep->value);
}
- else if (!strcmp(cep->ce_varname, "maxbanlength")) {
- tempiConf.maxbanlength = atol(cep->ce_vardata);
+ else if (!strcmp(cep->name, "maxbanlength")) {
+ tempiConf.maxbanlength = atol(cep->value);
}
- else if (!strcmp(cep->ce_varname, "silence-limit")) {
- tempiConf.silence_limit = atol(cep->ce_vardata);
+ else if (!strcmp(cep->name, "silence-limit")) {
+ tempiConf.silence_limit = 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, "auto-join")) {
+ safe_strdup(tempiConf.auto_join_chans, 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, "oper-auto-join")) {
+ safe_strdup(tempiConf.oper_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, "check-target-nick-bans")) {
+ tempiConf.check_target_nick_bans = config_checkval(cep->value, CFG_YESNO);
}
- else if (!strcmp(cep->ce_varname, "ping-cookie")) {
- tempiConf.ping_cookie = 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, "watch-away-notification")) {
- tempiConf.watch_away_notification = 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, "uhnames")) {
- tempiConf.uhnames = config_checkval(cep->ce_vardata, CFG_YESNO);
+ else if (!strcmp(cep->name, "uhnames")) {
+ tempiConf.uhnames = 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, "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->name, "server-notice-colors")) {
+ CheckNull(cep);
}
- else if (!strcmp(cep->ce_varname, "level-on-join")) {
+ 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 <connections>:<period>. "
"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 '<count>:<period>' (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 '<count>:<period>' (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 '<count>:<period>' (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 '<count>:<period>' (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 '<count>:<period>' (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->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->ce_varname, "connect-flood"))
+ 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 '<count>:<period>' (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);
- 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;
+ ce->file->filename, ce->line_number);
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 : "<none>");
- ircd_log(LOG_ERROR, "IPv6: %s", *boundmsg_ipv6 ? boundmsg_ipv6 : "<none>");
+ if (!*boundmsg_ipv4)
+ strlcpy(boundmsg_ipv4, "<none>", sizeof(boundmsg_ipv4));
+ if (!*boundmsg_ipv6)
+ strlcpy(boundmsg_ipv6, "<none>", 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"))
- {
- errors++;
- continue;
- }
- if (!strcmp(cep->ce_varname, "mask"))
+ if (!cep->items)
{
- if (has_mask)
+ if (config_is_blankorempty(cep, "deny link"))
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny link::mask");
+ errors++;
continue;
}
- has_mask = 1;
- }
- else if (!strcmp(cep->ce_varname, "rule"))
- {
- int val = 0;
- if (has_rule)
+ else if (!strcmp(cep->name, "mask"))
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny link::rule");
- continue;
+ 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++;
+ }
}
- has_rule = 1;
- if ((val = crule_test(cep->ce_vardata)))
+ else
{
- config_error("%s:%i: deny link::rule contains an invalid expression: %s",
- cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum,
- crule_errstring(val));
+ config_error_unknown(cep->file->filename,
+ cep->line_number, "deny link", cep->name);
errors++;
}
}
- else if (!strcmp(cep->ce_varname, "type"))
+ else
{
- if (has_type)
+ // Sections
+ if (!strcmp(cep->name, "mask"))
{
- config_warn_duplicate(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny link::type");
- continue;
+ if (cep->value || cep->items)
+ has_mask = 1;
}
- 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
+ {
+ config_error_unknown(cep->file->filename,
+ cep->line_number, "deny link", cep->name);
errors++;
+ continue;
}
}
- else
- {
- config_error_unknown(cep->ce_fileptr->cf_filename,
- cep->ce_varlinenum, "deny link", cep->ce_varname);
- 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 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;
+ if (config_verbose)
+ config_status("resource_download_complete() for %s [%s]", url, errorbuf?errorbuf:"success");
- inc->flag.type &= ~INCLUDE_DLQUEUED;
- break;
- }
- if (!inc)
+ if (!file && !cached)
{
- ircd_log(LOG_ERROR, "Downloaded remote include which matches no include statement.");
- return;
+ /* 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.
+ */
+ }
}
-
- if (!file && !cached)
- update_remote_include(inc, file, 0, errorbuf); /* DOWNLOAD FAILED */
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);
- }
- else
- {
- /*
- 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);
+ /* 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);
}
}
- for (inc = conf_include; inc; inc = inc->next)
+
+ if (rs->file)
{
- if (inc->flag.type & INCLUDE_DLQUEUED)
- return;
+ if (rs->type & RESOURCE_INCLUDE)
+ {
+ 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!!
+ }
}
- rehash_internal(loop.rehash_save_client, loop.rehash_save_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);
}
-#endif
-int rehash(Client *client, int sig)
+/** 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;
- }
-
- /* 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);
+ return;
}
- 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);
- }
- if (!found_remote)
- return rehash_internal(client, sig);
- return 0;
-#else
- loop.ircd_rehashing = 1;
- return rehash_internal(client, sig);
-#endif
+ rehash_internal(client);
+ return;
+ }
+ /* 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)
-{
- ConfigItem_include *inc;
-
- for (inc = conf_include; inc; inc = inc->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;
- }
- }
- return NULL;
-}
-
-char *find_loaded_remote_include(char *url)
+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))
- 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;
}
-/**
- * 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().
+/* 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 remote_include(ConfigEntry *ce)
+int add_config_resource(const char *resource, int type, 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))
- {
- char *error;
- if (config_verbose > 0)
- config_status("Downloading %s", displayurl(url));
- file = download_file(url, &error);
- if (!file)
- {
- 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), 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
+ ConfigResource *rs;
+ ConfigEntryWrapper *wce;
-/**
- * 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);
-}
+ if (config_verbose)
+ config_status("add_config_resource() for '%s", resource);
-#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;
+ wce = safe_alloc(sizeof(ConfigEntryWrapper));
+ wce->ce = ce;
- /* we rely on safe_alloc() zeroing the ConfigItem_include */
- inc = safe_alloc(sizeof(ConfigItem_include));
- if (included_from)
+ rs = find_config_resource(resource);
+ if (rs)
{
- safe_strdup(inc->included_from, included_from);
- inc->included_from_line = included_from_line;
+ /* Existing entry, add us to the list of
+ * items who are interested in this resource ;)
+ */
+ AddListItem(wce, rs->wce);
+ return 0;
}
- safe_strdup(inc->url, url);
- update_remote_include(inc, file, INCLUDE_NOTLOADED|INCLUDE_REMOTE|flags, errorbuf);
- AddListItem(inc, conf_include);
-}
+ /* New entry */
+ rs = safe_alloc(sizeof(ConfigResource));
+ rs->wce = wce;
+ AddListItem(rs, config_resources);
-/**
- * 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)
+ if (!url_is_valid(resource))
{
- 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)))
- {
- remove(inc->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)
+ {
+ 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)
+ {
+ if (!strcmp(cep->name, "url-refresh"))
+ {
+ /* 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)
+ {
+ wce_next = wce->next;
+ safe_free(wce);
+ }
+ rs->wce = NULL;
+ if (rs->type & RESOURCE_REMOTE)
{
-#ifdef USE_LIBCURL
- if (inc->flag.type & INCLUDE_REMOTE)
+ /* Delete the file, but only if it's not a cached version */
+ if (rs->file && strncmp(rs->file, CACHEDIR, strlen(CACHEDIR)))
{
- /* 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);
+ remove(rs->file);
}
-#endif
- safe_free(inc->file);
- safe_free(inc->included_from);
- DelListItem(inc, conf_include);
- safe_free(inc);
+ 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -39,6 +39,11 @@
#include <sys/ioctl.h>
#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
@@ -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
@@ -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);
-
- return 1;
-}
-void fd_close(int fd)
-{
- if (!fd_unmap(fd))
- return;
+ /* 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;
+ }
- CLOSE_SOCK(fd);
+ return 1;
}
/* 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
@@ -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 : "<N/A>"),
- (IsUser(client) ?
- (IsHidden(client) ? client->user->virthost : client->
- user->realhost) : "<N/A>"), 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 : "<N/A>"),
- (IsUser(client) ?
- (IsHidden(client) ? client->user->virthost : client->
- user->realhost) : "<N/A>"), client->user->lastaway);
- else /* RPL_GONEAWAY / RPL_REAWAY */
- sendnumeric(lp->value.client, reply,
- client->name,
- (IsUser(client) ? client->user->username : "<N/A>"),
- (IsUser(client) ?
- (IsHidden(client) ? client->user->virthost : client->
- user->realhost) : "<N/A>"), 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;
}
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |