* 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.
- *
- * $Id$
*/
+/** @file
+ * @brief Implementation of juped server handling functions.
+ * @version $Id$
+ */
+#include "config.h"
+
#include "jupe.h"
#include "client.h"
#include "hash.h"
#include "ircd.h"
#include "ircd_alloc.h"
+#include "ircd_features.h"
+#include "ircd_log.h"
#include "ircd_reply.h"
#include "ircd_string.h"
#include "match.h"
#include "s_misc.h"
#include "send.h"
#include "struct.h"
-#include "support.h"
#include "sys.h" /* FALSE bleah */
-#include <assert.h>
+/* #include <assert.h> -- Now using assert in ircd_log.h */
+#include <string.h>
-static struct Jupe* GlobalJupeList = 0;
+/** List of jupes. */
+static struct Jupe *GlobalJupeList = 0;
+/** Allocate a new jupe with the given parameters.
+ * @param[in] server Server name to jupe.
+ * @param[in] reason Reason for jupe.
+ * @param[in] expire Expiration time for jupe.
+ * @param[in] lastmod Last modification time for jupe.
+ * @param[in] flags Flags to set for the jupe.
+ */
static struct Jupe *
make_jupe(char *server, char *reason, time_t expire, time_t lastmod,
unsigned int flags)
ajupe = (struct Jupe*) MyMalloc(sizeof(struct Jupe)); /* alloc memory */
assert(0 != ajupe);
- DupString(ajupe->ju_server, server); /* copy vital information */
+ memset(ajupe, 0, sizeof(*ajupe));
+ DupString(ajupe->ju_server, server); /* copy vital information */
DupString(ajupe->ju_reason, reason);
ajupe->ju_expire = expire;
ajupe->ju_lastmod = lastmod;
- ajupe->ju_flags = flags; /* set jupe flags */
+ ajupe->ju_flags = flags & JUPE_MASK; /* set jupe flags */
- ajupe->ju_next = GlobalJupeList; /* link it into the list */
+ ajupe->ju_next = GlobalJupeList; /* link it into the list */
ajupe->ju_prev_p = &GlobalJupeList;
if (GlobalJupeList)
GlobalJupeList->ju_prev_p = &ajupe->ju_next;
return ajupe;
}
+/** Apply a jupe.
+ * @param[in] cptr Local client that sent us the jupe.
+ * @param[in] sptr Originator of the jupe.
+ * @param[in] jupe Jupe to check.
+ */
static int
do_jupe(struct Client *cptr, struct Client *sptr, struct Jupe *jupe)
{
return exit_client_msg(cptr, acptr, &me, "Juped: %s", jupe->ju_reason);
}
+/** Forward a jupe to another server.
+ * @param[in] cptr Local client that sent us the jupe.
+ * @param[in] sptr Originator of the jupe.
+ * @param[in] jupe Jupe to forward.
+ */
static void
propagate_jupe(struct Client *cptr, struct Client *sptr, struct Jupe *jupe)
{
if (JupeIsLocal(jupe)) /* don't propagate local jupes */
return;
- sendcmdto_serv_butone(cptr, CMD_JUPE, sptr, "* %c%s %Tu %Tu :%s",
- JupeIsActive(jupe) ? '+' : '-', jupe->ju_server,
- jupe->ju_expire - TStime(), jupe->ju_lastmod,
+ sendcmdto_serv_butone(sptr, CMD_JUPE, cptr, "* %c%s %Tu %Tu :%s",
+ JupeIsRemActive(jupe) ? '+' : '-', jupe->ju_server,
+ jupe->ju_expire - CurrentTime, jupe->ju_lastmod,
jupe->ju_reason);
}
+/** Add a new server jupe.
+ * @param[in] cptr Local client that sent us the jupe.
+ * @param[in] sptr Originator of the jupe.
+ * @param[in] server Server name to jupe.
+ * @param[in] reason Reason for the jupe.
+ * @param[in] expire Jupe duration in seconds.
+ * @param[in] lastmod Last modification timestamp (or NULL).
+ * @param[in] flags Flags to set on jupe.
+ * @return Zero, unless the jupe causes \a cptr to be SQUIT, in which
+ * case CPTR_KILLED.
+ */
int
jupe_add(struct Client *cptr, struct Client *sptr, char *server, char *reason,
- time_t expire, time_t lastmod, int local, int active)
+ time_t expire, time_t lastmod, unsigned int flags)
{
struct Jupe *ajupe;
- unsigned int flags = 0;
assert(0 != server);
assert(0 != reason);
*/
if (expire <= 0 || expire > JUPE_MAX_EXPIRE) {
if (!IsServer(cptr) && MyConnect(cptr))
- send_error_to_client(cptr, ERR_BADEXPIRE, expire);
+ send_reply(cptr, ERR_BADEXPIRE, expire);
return 0;
}
- expire += TStime(); /* convert from lifetime to timestamp */
+ expire += CurrentTime; /* convert from lifetime to timestamp */
/* Inform ops and log it */
- if (IsServer(sptr)) {
- sendto_op_mask(SNO_NETWORK, "%s adding %sJUPE for %s, expiring at "
- TIME_T_FMT ": %s", sptr->name, local ? "local " : "",
- server, expire, reason);
-#ifdef JPATH
- write_log(JPATH, TIME_T_FMT " %s adding %sJUPE for %s, expiring at "
- TIME_T_FMT ": %s\n", TStime(), sptr->name,
- local ? "local " : "", server, expire, reason);
-#endif /* JPATH */
- } else {
- sendto_op_mask(SNO_NETWORK, "%s adding %sJUPE for %s, expiring at "
- TIME_T_FMT ": %s", sptr->user->server->name,
- local ? "local " : "", server, expire,
- reason);
-#ifdef JPATH
- write_log(JPATH, TIME_T_FMT, " %s!%s@%s adding %sJUPE for %s, expiring at "
- TIME_T_FMT ": %s\n", TStime(), sptr->name, sptr->user->username,
- sptr->user->host, local ? "local " : "", server, expire, reason);
-#endif /* JPATH */
- }
-
- if (active) /* compute initial flags */
- flags |= JUPE_ACTIVE;
- if (local)
- flags |= JUPE_LOCAL;
+ sendto_opmask_butone(0, SNO_NETWORK, "%s adding %sJUPE for %s, expiring at "
+ "%Tu: %s",
+ (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
+ cli_name(sptr) :
+ cli_name((cli_user(sptr))->server),
+ flags & JUPE_LOCAL ? "local " : "", server,
+ expire + TSoffset, reason);
+
+ log_write(LS_JUPE, L_INFO, LOG_NOSNOTICE,
+ "%#C adding %sJUPE for %s, expiring at %Tu: %s", sptr,
+ flags & JUPE_LOCAL ? "local " : "", server, expire + TSoffset,
+ reason);
/* make the jupe */
ajupe = make_jupe(server, reason, expire, lastmod, flags);
return do_jupe(cptr, sptr, ajupe); /* remove server if necessary */
}
+/** Activate a jupe, optionally changing its lastmod and flags.
+ * @param[in] cptr Local client that sent us the jupe.
+ * @param[in] sptr Originator of the jupe.
+ * @param[in] jupe Jupe to activate.
+ * @param[in] lastmod New timestamp for last modification of the jupe.
+ * @param[in] flags Flags to set on the jupe.
+ * @return Zero, unless the jupe causes \a cptr to be SQUIT, in which
+ * case CPTR_KILLED.
+ */
int
jupe_activate(struct Client *cptr, struct Client *sptr, struct Jupe *jupe,
- time_t lastmod)
+ time_t lastmod, unsigned int flags)
{
+ unsigned int saveflags = 0;
+
assert(0 != jupe);
- jupe->ju_flags |= JUPE_ACTIVE;
- jupe->ju_lastmod = lastmod;
+ saveflags = jupe->ju_flags;
- /* Inform ops and log it */
- if (IsServer(sptr)) {
- sendto_op_mask(SNO_NETWORK, "%s activating %sJUPE for %s, expiring at "
- TIME_T_FMT ": %s", sptr->name, JupeIsLocal(jupe) ?
- "local " : "", jupe->ju_server, jupe->ju_expire,
- jupe->ju_reason);
-#ifdef JPATH
- write_log(JPATH, TIME_T_FMT " %s activating %sJUPE for %s, expiring at "
- TIME_T_FMT ": %s\n", TStime(), sptr->name, JupeIsLocal(jupe) ?
- "local " : "", jupe->ju_server, jupe->ju_expire,
- jupe->ju_reason);
-#endif /* JPATH */
- } else {
- sendto_op_mask(SNO_NETWORK, "%s activating %sJUPE for %s, expiring at "
- TIME_T_FMT ": %s", sptr->user->server->name,
- JupeIsLocal(jupe) ? "local " : "", jupe->ju_server,
- jupe->ju_expire, jupe->ju_reason);
-#ifdef JPATH
- write_log(JPATH, TIME_T_FMT, " %s!%s@%s activating %sJUPE for %s, "
- "expiring at " TIME_T_FMT ": %s\n", TStime(), sptr->name,
- sptr->user->username, sptr->user->host, JupeIsLocal(jupe) ?
- "local " : "", jupe->ju_server, jupe->ju_expire,
- jupe->ju_reason);
-#endif /* JPATH */
+ if (flags & JUPE_LOCAL)
+ jupe->ju_flags &= ~JUPE_LDEACT;
+ else {
+ jupe->ju_flags |= JUPE_ACTIVE;
+
+ if (jupe->ju_lastmod >= lastmod) /* force lastmod to increase */
+ jupe->ju_lastmod++;
+ else
+ jupe->ju_lastmod = lastmod;
}
- propagate_jupe(cptr, sptr, jupe);
+ if ((saveflags & JUPE_ACTMASK) == JUPE_ACTIVE)
+ return 0; /* was active to begin with */
+
+ /* Inform ops and log it */
+ sendto_opmask_butone(0, SNO_NETWORK, "%s activating JUPE for %s, expiring "
+ "at %Tu: %s",
+ (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
+ cli_name(sptr) :
+ cli_name((cli_user(sptr))->server),
+ jupe->ju_server, jupe->ju_expire + TSoffset,
+ jupe->ju_reason);
+
+ log_write(LS_JUPE, L_INFO, LOG_NOSNOTICE,
+ "%#C activating JUPE for %s, expiring at %Tu: %s",sptr,
+ jupe->ju_server, jupe->ju_expire + TSoffset, jupe->ju_reason);
+
+ if (!(flags & JUPE_LOCAL)) /* don't propagate local changes */
+ propagate_jupe(cptr, sptr, jupe);
return do_jupe(cptr, sptr, jupe);
}
+/** Deactivate a jupe.
+ * @param[in] cptr Local client that sent us the jupe.
+ * @param[in] sptr Originator of the jupe.
+ * @param[in] jupe Jupe to deactivate.
+ * @param[in] lastmod New timestamp for last modification of the jupe.
+ * @param[in] flags Flags to set on the jupe.
+ * @return Zero.
+ */
int
jupe_deactivate(struct Client *cptr, struct Client *sptr, struct Jupe *jupe,
- time_t lastmod)
+ time_t lastmod, unsigned int flags)
{
+ unsigned int saveflags = 0;
+
assert(0 != jupe);
- jupe->ju_flags &= ~JUPE_ACTIVE;
- jupe->ju_lastmod = lastmod;
+ saveflags = jupe->ju_flags;
- /* Inform ops and log it */
- if (IsServer(sptr)) {
- sendto_op_mask(SNO_NETWORK, "%s deactivating %sJUPE for %s, expiring at "
- TIME_T_FMT ": %s", sptr->name, JupeIsLocal(jupe) ?
- "local " : "", jupe->ju_server, jupe->ju_expire,
- jupe->ju_reason);
-#ifdef JPATH
- write_log(JPATH, TIME_T_FMT " %s deactivating %sJUPE for %s, expiring at "
- TIME_T_FMT ": %s\n", TStime(), sptr->name, JupeIsLocal(jupe) ?
- "local " : "", jupe->ju_server, jupe->ju_expire,
- jupe->ju_reason);
-#endif /* JPATH */
- } else {
- sendto_op_mask(SNO_NETWORK, "%s deactivating %sJUPE for %s, expiring at "
- TIME_T_FMT ": %s", sptr->user->server->name,
- JupeIsLocal(jupe) ? "local " : "", jupe->ju_server,
- jupe->ju_expire, jupe->ju_reason);
-#ifdef JPATH
- write_log(JPATH, TIME_T_FMT, " %s!%s@%s deactivating %sJUPE for %s, "
- "expiring at " TIME_T_FMT ": %s\n", TStime(), sptr->name,
- sptr->user->username, sptr->user->host, JupeIsLocal(jupe) ?
- "local " : "", jupe->ju_server, jupe->ju_expire,
- jupe->ju_reason);
-#endif /* JPATH */
+ if (!JupeIsLocal(jupe)) {
+ if (flags & JUPE_LOCAL)
+ jupe->ju_flags |= JUPE_LDEACT;
+ else {
+ jupe->ju_flags &= ~JUPE_ACTIVE;
+
+ if (jupe->ju_lastmod >= lastmod) /* force lastmod to increase */
+ jupe->ju_lastmod++;
+ else
+ jupe->ju_lastmod = lastmod;
+ }
+
+ if ((saveflags & JUPE_ACTMASK) != JUPE_ACTIVE)
+ return 0; /* was inactive to begin with */
}
- propagate_jupe(cptr, sptr, jupe);
+ /* Inform ops and log it */
+ sendto_opmask_butone(0, SNO_NETWORK, "%s %s JUPE for %s, expiring at %Tu: "
+ "%s",
+ (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
+ cli_name(sptr) :
+ cli_name((cli_user(sptr))->server),
+ JupeIsLocal(jupe) ? "removing local" : "deactivating",
+ jupe->ju_server, jupe->ju_expire + TSoffset,
+ jupe->ju_reason);
+
+ log_write(LS_JUPE, L_INFO, LOG_NOSNOTICE,
+ "%#C %s JUPE for %s, expiring at %Tu: %s", sptr,
+ JupeIsLocal(jupe) ? "removing local" : "deactivating",
+ jupe->ju_server, jupe->ju_expire + TSoffset, jupe->ju_reason);
+
+ if (JupeIsLocal(jupe))
+ jupe_free(jupe);
+ else if (!(flags & JUPE_LOCAL)) /* don't propagate local changes */
+ propagate_jupe(cptr, sptr, jupe);
return 0;
}
+/** Find a jupe by name.
+ * @param[in] server %Jupe name to search for.
+ * @return Matching jupe (or NULL if none match).
+ */
struct Jupe *
jupe_find(char *server)
{
for (jupe = GlobalJupeList; jupe; jupe = sjupe) { /* go through jupes */
sjupe = jupe->ju_next;
- if (jupe->ju_expire <= TStime()) /* expire any that need expiring */
+ if (jupe->ju_expire <= CurrentTime) /* expire any that need expiring */
jupe_free(jupe);
else if (0 == ircd_strcmp(server, jupe->ju_server)) /* found it yet? */
return jupe;
return 0;
}
+/** Unlink and free an unused jupe.
+ * @param[in] jupe Server jupe to free.
+ */
void
jupe_free(struct Jupe* jupe)
{
MyFree(jupe);
}
+/** Send the full list of active global jupes to \a cptr.
+ * @param[in] cptr Local server to send jupes to.
+ */
void
jupe_burst(struct Client *cptr)
{
for (jupe = GlobalJupeList; jupe; jupe = sjupe) { /* go through jupes */
sjupe = jupe->ju_next;
- if (jupe->ju_expire <= TStime()) /* expire any that need expiring */
+ if (jupe->ju_expire <= CurrentTime) /* expire any that need expiring */
jupe_free(jupe);
else if (!JupeIsLocal(jupe)) /* forward global jupes */
- sendcmdto_one(cptr, CMD_JUPE, &me, "* %c%s %Tu %Tu :%s",
- JupeIsActive(jupe) ? '+' : '-', jupe->ju_server,
- jupe->ju_expire - TStime(), jupe->ju_lastmod,
+ sendcmdto_one(&me, CMD_JUPE, cptr, "* %c%s %Tu %Tu :%s",
+ JupeIsRemActive(jupe) ? '+' : '-', jupe->ju_server,
+ jupe->ju_expire - CurrentTime, jupe->ju_lastmod,
jupe->ju_reason);
}
}
+/** Forward a jupe to another server.
+ * @param[in] cptr %Server to send jupe to.
+ * @param[in] jupe Jupe to forward.
+ */
int
jupe_resend(struct Client *cptr, struct Jupe *jupe)
{
if (JupeIsLocal(jupe)) /* don't propagate local jupes */
return 0;
- sendcmdto_one(cptr, CMD_JUPE, &me, "* %c%s %Tu %Tu :%s",
- JupeIsActive(jupe) ? '+' : '-', jupe->ju_server,
- jupe->ju_expire - TStime(), jupe->ju_lastmod, jupe->ju_reason);
+ sendcmdto_one(&me, CMD_JUPE, cptr, "* %c%s %Tu %Tu :%s",
+ JupeIsRemActive(jupe) ? '+' : '-', jupe->ju_server,
+ jupe->ju_expire - CurrentTime, jupe->ju_lastmod,
+ jupe->ju_reason);
return 0;
}
+/** Send a jupe (or a list of jupes) to a server.
+ * @param[in] sptr Client searching for jupes.
+ * @param[in] server Name of jupe to search for (if NULL, list all).
+ * @return Zero.
+ */
int
jupe_list(struct Client *sptr, char *server)
{
if (server) {
if (!(jupe = jupe_find(server))) /* no such jupe */
- return send_error_to_client(sptr, ERR_NOSUCHJUPE, server);
+ return send_reply(sptr, ERR_NOSUCHJUPE, server);
/* send jupe information along */
- sendto_one(sptr, rpl_str(RPL_JUPELIST), me.name, sptr->name,
- jupe->ju_server, jupe->ju_expire, JupeIsLocal(jupe) ?
- me.name : "*", JupeIsActive(jupe) ? '+' : '-', jupe->ju_reason);
+ send_reply(sptr, RPL_JUPELIST, jupe->ju_server, jupe->ju_expire + TSoffset,
+ JupeIsLocal(jupe) ? cli_name(&me) : "*",
+ JupeIsActive(jupe) ? '+' : '-', jupe->ju_reason);
} else {
for (jupe = GlobalJupeList; jupe; jupe = sjupe) { /* go through jupes */
sjupe = jupe->ju_next;
- if (jupe->ju_expire <= TStime()) /* expire any that need expiring */
+ if (jupe->ju_expire <= CurrentTime) /* expire any that need expiring */
jupe_free(jupe);
else /* send jupe information along */
- sendto_one(sptr, rpl_str(RPL_JUPELIST), me.name, sptr->name,
- jupe->ju_server, jupe->ju_expire, JupeIsLocal(jupe) ?
- me.name : "*", JupeIsActive(jupe) ? '+' : '-',
- jupe->ju_reason);
+ send_reply(sptr, RPL_JUPELIST, jupe->ju_server,
+ jupe->ju_expire + TSoffset,
+ JupeIsLocal(jupe) ? cli_name(&me) : "*",
+ JupeIsActive(jupe) ? '+' : '-', jupe->ju_reason);
}
}
/* end of jupe information */
- sendto_one(sptr, rpl_str(RPL_ENDOFJUPELIST), me.name, sptr->name);
- return 0;
+ return send_reply(sptr, RPL_ENDOFJUPELIST);
+}
+
+/** Count jupes and memory used by them.
+ * @param[out] ju_size Receives total number of bytes allocated for jupes.
+ * @return Number of jupes currently allocated.
+ */
+int
+jupe_memory_count(size_t *ju_size)
+{
+ struct Jupe *jupe;
+ unsigned int ju = 0;
+
+ for (jupe = GlobalJupeList; jupe; jupe = jupe->ju_next)
+ {
+ ju++;
+ *ju_size += sizeof(struct Jupe);
+ *ju_size += jupe->ju_server ? (strlen(jupe->ju_server) + 1) : 0;
+ *ju_size += jupe->ju_reason ? (strlen(jupe->ju_reason) + 1) : 0;
+ }
+ return ju;
}