summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/chanserv.c34
-rw-r--r--src/init.c28
-rw-r--r--src/operserv.c90
-rw-r--r--src/users.c3
4 files changed, 144 insertions, 11 deletions
diff --git a/src/chanserv.c b/src/chanserv.c
index 6add49727..ac82b8edf 100644
--- a/src/chanserv.c
+++ b/src/chanserv.c
@@ -1072,7 +1072,12 @@ void save_cs_rdb_dbase(void)
/*************************************************************************/
/* Check the current modes on a channel; if they conflict with a mode lock,
- * fix them. */
+ * fix them.
+ *
+ * Also check to make sure that every mode set or unset is allowed by the
+ * defcon mlock settings. This is more important than any normal channel
+ * mlock'd mode. --gdex (21-04-07)
+ */
void check_modes(Channel * c)
{
@@ -1109,6 +1114,7 @@ void check_modes(Channel * c)
}
c->chanserv_modecount++;
+ /* Check if the channel is registered; if not remove mode -r */
if (!(ci = c->ci)) {
if (ircd->regmode) {
if (c->mode & ircd->regmode) {
@@ -1119,8 +1125,14 @@ void check_modes(Channel * c)
return;
}
+ /* Initialize te modes-var to set all modes not set yet but which should
+ * be set as by mlock and defcon.
+ */
modes = ~c->mode & ci->mlock_on;
+ if (DefConModesSet)
+ modes |= (~c->mode & DefConModesOn);
+ /* Initialize the buffers */
*end++ = '+';
cbmi = cbmodeinfos;
@@ -1131,7 +1143,12 @@ void check_modes(Channel * c)
/* Add the eventual parameter and modify the Channel structure */
if (cbmi->getvalue && cbmi->csgetvalue) {
- char *value = cbmi->csgetvalue(ci);
+ char *value;
+ /* Check if it's a defcon or mlock mode */
+ if (DefConModesOn & cbmi->flag)
+ value = cbmi->csgetvalue(&DefConModesCI);
+ else
+ value = cbmi->csgetvalue(ci);
cbm = &cbmodes[(int) cbmi->mode];
cbm->setvalue(c, value);
@@ -1143,10 +1160,17 @@ void check_modes(Channel * c)
}
}
} else if (cbmi->getvalue && cbmi->csgetvalue
- && (ci->mlock_on & cbmi->flag)
+ && ((ci->mlock_on & cbmi->flag)
+ || (DefConModesOn & cbmi->flag))
&& (c->mode & cbmi->flag)) {
char *value = cbmi->getvalue(c);
- char *csvalue = cbmi->csgetvalue(ci);
+ char *csvalue;
+
+ /* Check if it's a defcon or mlock mode */
+ if (DefConModesOn & cbmi->flag)
+ csvalue = cbmi->csgetvalue(&DefConModesCI);
+ else
+ csvalue = cbmi->csgetvalue(ci);
/* Lock and actual values don't match, so fix the mode */
if (value && csvalue && strcmp(value, csvalue)) {
@@ -1166,6 +1190,8 @@ void check_modes(Channel * c)
end--;
modes = c->mode & ci->mlock_off;
+ if (DefConModesSet)
+ modes |= (~c->mode & DefConModesOff);
if (modes) {
*end++ = '-';
diff --git a/src/init.c b/src/init.c
index f188505b6..880264744 100644
--- a/src/init.c
+++ b/src/init.c
@@ -475,6 +475,17 @@ int init_secondary(int ac, char **av)
/* Parse all remaining command-line options. */
parse_options(ac, av);
+ /* Parse the defcon mode string if needed */
+ if (DefConLevel) {
+ int defconCount;
+ for (defconCount = 1; defconCount <= 5; defconCount++) {
+ if (!defconParseModeString(DefConChanModes)) {
+ fprintf(stderr,
+ "services.conf: The given DefConChanModes mode string was incorrect (see log for exact errors)\n");
+ return -1;
+ }
+ }
+ }
#ifndef _WIN32
if (!nofork) {
if ((i = fork()) < 0) {
@@ -503,12 +514,17 @@ int init_secondary(int ac, char **av)
}
}
if (!SupportedWindowsVersion()) {
- char *winver = GetWindowsVersion();
- alog("%s is not a supported version of Windows", winver);
- free(winver);
- return -1;
- }
- if (!nofork) {
+
+ char *winver = GetWindowsVersion();
+
+ alog("%s is not a supported version of Windows", winver);
+
+ free(winver);
+
+ return -1;
+
+ }
+ if (!nofork) {
alog("Launching Anope into the background");
FreeConsole();
}
diff --git a/src/operserv.c b/src/operserv.c
index 6f030b8cd..691b7faf2 100644
--- a/src/operserv.c
+++ b/src/operserv.c
@@ -46,6 +46,14 @@ time_t DefContimer;
int DefConModesSet = 0;
char *defconReverseModes(const char *modes);
+uint32 DefConModesOn; /* Modes to be enabled during DefCon */
+uint32 DefConModesOff; /* Modes to be disabled during DefCon */
+ChannelInfo DefConModesCI; /* ChannelInfo containg params for locked modes
+ * during DefCon; I would've done this nicer if i
+ * could, but all damn mode functions require a
+ * ChannelInfo struct! --gdex
+ */
+
#ifdef DEBUG_COMMANDS
static int do_matchwild(User * u);
@@ -1657,5 +1665,87 @@ char *defconReverseModes(const char *modes)
return newmodes;
}
+/* Parse the defcon mlock mode string and set the correct global vars.
+ *
+ * @param str mode string to parse
+ * @return 1 if accepted, 0 if failed
+ */
+int defconParseModeString(const char *str)
+{
+ int add = -1; /* 1 if adding, 0 if deleting, -1 if neither */
+ unsigned char mode;
+ CBMode *cbm;
+
+ /* Reinitialize everything */
+ DefConModesOn = 0;
+ DefConModesOff = 0;
+ DefConModesCI.mlock_limit = 0;
+ DefConModesCI.mlock_key = NULL;
+ DefConModesCI.mlock_flood = NULL;
+ DefConModesCI.mlock_redirect = NULL;
+
+ /* Loop while there are modes to set */
+ while ((mode = *str++)) {
+ switch (mode) {
+ case '+':
+ add = 1;
+ continue;
+ case '-':
+ add = 0;
+ continue;
+ default:
+ if (add < 0)
+ continue;
+ }
+
+ if ((int) mode < 128 && (cbm = &cbmodes[(int) mode])->flag != 0) {
+ if (cbm->flags & CBM_NO_MLOCK) {
+ alog("DefConChanModes mode character '%c' cannot be locked", mode);
+ return 0;
+ } else if (add) {
+ DefConModesOn |= cbm->flag;
+ DefConModesOff &= ~cbm->flag;
+ if (cbm->cssetvalue)
+ cbm->cssetvalue(&DefConModesCI, strtok(NULL, " "));
+ } else {
+ DefConModesOff |= cbm->flag;
+ if (DefConModesOn & cbm->flag) {
+ DefConModesOn &= ~cbm->flag;
+ if (cbm->cssetvalue)
+ cbm->cssetvalue(&DefConModesCI, NULL);
+ }
+ }
+ } else {
+ alog("DefConChanModes unknown mode character '%c'", mode);
+ return 0;
+ }
+ } /* while (*param) */
+
+ if (ircd->Lmode) {
+ /* We can't mlock +L if +l is not mlocked as well. */
+ if ((DefConModesOn & ircd->chan_lmode)
+ && !(DefConModesOn & anope_get_limit_mode())) {
+ DefConModesOn &= ~ircd->chan_lmode;
+ free(DefConModesCI.mlock_redirect);
+ DefConModesCI.mlock_redirect = NULL;
+ alog("DefConChanModes must lock mode +l as well to lock mode +L");
+ return 0;
+ }
+ }
+
+ /* Some ircd we can't set NOKNOCK without INVITE */
+ /* So check if we need there is a NOKNOCK MODE and that we need INVITEONLY */
+ if (ircd->noknock && ircd->knock_needs_i) {
+ if ((DefConModesOn & ircd->noknock)
+ && !(DefConModesOn & anope_get_invite_mode())) {
+ DefConModesOn &= ~ircd->noknock;
+ alog("DefConChanModes must lock mode +i as well to lock mode +K");
+ return 0;
+ }
+ }
+
+ /* Everything is set fine, return 1 */
+ return 1;
+}
/*************************************************************************/
diff --git a/src/users.c b/src/users.c
index fb586e779..fe1e41bc1 100644
--- a/src/users.c
+++ b/src/users.c
@@ -570,7 +570,8 @@ User *do_nick(const char *source, char *nick, char *username, char *host,
* then force check_akill again on them...
**/
// don't akill on netmerges -Certus
- if (is_sync(findserver(servlist, server)) && checkDefCon(DEFCON_AKILL_NEW_CLIENTS)) {
+ if (is_sync(findserver(servlist, server))
+ && checkDefCon(DEFCON_AKILL_NEW_CLIENTS)) {
strncpy(mask, "*@", 3);
strncat(mask, host, HOSTMAX);
alog("DEFCON: adding akill for %s", mask);