diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/chanserv.c | 34 | ||||
-rw-r--r-- | src/init.c | 28 | ||||
-rw-r--r-- | src/operserv.c | 90 | ||||
-rw-r--r-- | src/users.c | 3 |
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); |