Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 1891dfbe87
Fetching contributors…

Cannot retrieve contributors at this time

563 lines (434 sloc) 11.416 kb
/*
* atheme-services: A collection of minimalist IRC services
* node.c: Data structure management.
*
* Copyright (c) 2005-2007 Atheme Project (http://www.atheme.org)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "atheme.h"
#include "uplink.h"
#include "privs.h"
mowgli_list_t klnlist;
mowgli_list_t xlnlist;
mowgli_list_t qlnlist;
mowgli_heap_t *kline_heap; /* 16 */
mowgli_heap_t *xline_heap; /* 16 */
mowgli_heap_t *qline_heap; /* 16 */
/*************
* L I S T S *
*************/
void init_nodes(void)
{
kline_heap = sharedheap_get(sizeof(kline_t));
xline_heap = sharedheap_get(sizeof(xline_t));
qline_heap = sharedheap_get(sizeof(qline_t));
if (kline_heap == NULL || xline_heap == NULL || qline_heap == NULL)
{
slog(LG_INFO, "init_nodes(): block allocator failed.");
exit(EXIT_FAILURE);
}
init_uplinks();
init_servers();
init_metadata();
init_accounts();
init_entities();
init_users();
init_channels();
init_privs();
}
/* Mark everything illegal, to be called before a rehash -- jilles */
void mark_all_illegal()
{
mowgli_node_t *n, *tn;
uplink_t *u;
soper_t *soper;
operclass_t *operclass;
MOWGLI_ITER_FOREACH(n, uplinks.head)
{
u = (uplink_t *)n->data;
u->flags |= UPF_ILLEGAL;
}
/* just delete these, we can survive without for a while */
MOWGLI_ITER_FOREACH_SAFE(n, tn, soperlist.head)
{
soper = (soper_t *)n->data;
if (soper->flags & SOPER_CONF)
soper_delete(soper);
}
/* no sopers pointing to these anymore */
MOWGLI_ITER_FOREACH_SAFE(n, tn, operclasslist.head)
{
operclass = (operclass_t *)n->data;
operclass_delete(operclass);
}
}
/* Unmark everything illegal, to be called after a failed rehash -- jilles */
void unmark_all_illegal()
{
mowgli_node_t *n;
uplink_t *u;
MOWGLI_ITER_FOREACH(n, uplinks.head)
{
u = (uplink_t *)n->data;
u->flags &= ~UPF_ILLEGAL;
}
}
/* Remove illegal stuff, to be called after a successful rehash -- jilles */
void remove_illegals()
{
mowgli_node_t *n, *tn;
uplink_t *u;
MOWGLI_ITER_FOREACH_SAFE(n, tn, uplinks.head)
{
u = (uplink_t *)n->data;
if (u->flags & UPF_ILLEGAL && u != curr_uplink)
uplink_delete(u);
}
}
/*************
* K L I N E *
*************/
kline_t *kline_add_with_id(const char *user, const char *host, const char *reason, long duration, const char *setby, unsigned long id)
{
kline_t *k;
mowgli_node_t *n = mowgli_node_create();
slog(LG_DEBUG, "kline_add(): %s@%s -> %s (%ld)", user, host, reason, duration);
k = mowgli_heap_alloc(kline_heap);
mowgli_node_add(k, n, &klnlist);
k->user = sstrdup(user);
k->host = sstrdup(host);
k->reason = sstrdup(reason);
k->setby = sstrdup(setby);
k->duration = duration;
k->settime = CURRTIME;
k->expires = CURRTIME + duration;
k->number = id;
cnt.kline++;
char treason[BUFSIZE];
snprintf(treason, sizeof(treason), "[#%lu] %s", k->number, k->reason);
if (me.connected)
kline_sts("*", user, host, duration, treason);
return k;
}
kline_t *kline_add(const char *user, const char *host, const char *reason, long duration, const char *setby)
{
return kline_add_with_id(user, host, reason, duration, setby, ++me.kline_id);
}
void kline_delete(kline_t *k)
{
mowgli_node_t *n;
return_if_fail(k != NULL);
slog(LG_DEBUG, "kline_delete(): %s@%s -> %s", k->user, k->host, k->reason);
/* only unkline if ircd has not already removed this -- jilles */
if (me.connected && (k->duration == 0 || k->expires > CURRTIME))
unkline_sts("*", k->user, k->host);
n = mowgli_node_find(k, &klnlist);
mowgli_node_delete(n, &klnlist);
mowgli_node_free(n);
free(k->user);
free(k->host);
free(k->reason);
free(k->setby);
mowgli_heap_free(kline_heap, k);
cnt.kline--;
}
kline_t *kline_find(const char *user, const char *host)
{
kline_t *k;
mowgli_node_t *n;
MOWGLI_ITER_FOREACH(n, klnlist.head)
{
k = (kline_t *)n->data;
if ((!match(k->user, user)) && (!match(k->host, host)))
return k;
}
return NULL;
}
kline_t *kline_find_num(unsigned long number)
{
kline_t *k;
mowgli_node_t *n;
MOWGLI_ITER_FOREACH(n, klnlist.head)
{
k = (kline_t *)n->data;
if (k->number == number)
return k;
}
return NULL;
}
kline_t *kline_find_user(user_t *u)
{
kline_t *k;
mowgli_node_t *n;
MOWGLI_ITER_FOREACH(n, klnlist.head)
{
k = (kline_t *)n->data;
if (k->duration != 0 && k->expires <= CURRTIME)
continue;
if (!match(k->user, u->user) && (!match(k->host, u->host) || !match(k->host, u->ip) || !match_ips(k->host, u->ip)))
return k;
}
return NULL;
}
void kline_expire(void *arg)
{
kline_t *k;
char *reason;
mowgli_node_t *n, *tn;
MOWGLI_ITER_FOREACH_SAFE(n, tn, klnlist.head)
{
k = (kline_t *)n->data;
if (k->duration == 0)
continue;
if (k->expires <= CURRTIME)
{
/* TODO: determine validity of k->reason */
reason = k->reason ? k->reason : "(none)";
slog(LG_INFO, _("KLINE:EXPIRE: \2%s@%s\2 set \2%s\2 ago by \2%s\2 (reason: %s)"),
k->user, k->host, time_ago(k->settime), k->setby, reason);
verbose_wallops(_("AKILL expired on \2%s@%s\2, set by \2%s\2 (reason: %s)"),
k->user, k->host, k->setby, reason);
kline_delete(k);
}
}
}
/*************
* X L I N E *
*************/
xline_t *xline_add(const char *realname, const char *reason, long duration, const char *setby)
{
xline_t *x;
mowgli_node_t *n = mowgli_node_create();
static unsigned int xcnt = 0;
slog(LG_DEBUG, "xline_add(): %s -> %s (%ld)", realname, reason, duration);
x = mowgli_heap_alloc(xline_heap);
mowgli_node_add(x, n, &xlnlist);
x->realname = sstrdup(realname);
x->reason = sstrdup(reason);
x->setby = sstrdup(setby);
x->duration = duration;
x->settime = CURRTIME;
x->expires = CURRTIME + duration;
x->number = ++xcnt;
cnt.xline++;
if (me.connected)
xline_sts("*", realname, duration, reason);
return x;
}
void xline_delete(const char *realname)
{
xline_t *x = xline_find(realname);
mowgli_node_t *n;
if (!x)
{
slog(LG_DEBUG, "xline_delete(): called for nonexistant xline: %s", realname);
return;
}
slog(LG_DEBUG, "xline_delete(): %s -> %s", x->realname, x->reason);
/* only unxline if ircd has not already removed this -- jilles */
if (me.connected && (x->duration == 0 || x->expires > CURRTIME))
unxline_sts("*", x->realname);
n = mowgli_node_find(x, &xlnlist);
mowgli_node_delete(n, &xlnlist);
mowgli_node_free(n);
free(x->realname);
free(x->reason);
free(x->setby);
mowgli_heap_free(xline_heap, x);
cnt.xline--;
}
xline_t *xline_find(const char *realname)
{
xline_t *x;
mowgli_node_t *n;
MOWGLI_ITER_FOREACH(n, xlnlist.head)
{
x = (xline_t *)n->data;
if (!match(x->realname, realname))
return x;
}
return NULL;
}
xline_t *xline_find_num(unsigned int number)
{
xline_t *x;
mowgli_node_t *n;
MOWGLI_ITER_FOREACH(n, xlnlist.head)
{
x = (xline_t *)n->data;
if (x->number == number)
return x;
}
return NULL;
}
xline_t *xline_find_user(user_t *u)
{
xline_t *x;
mowgli_node_t *n;
MOWGLI_ITER_FOREACH(n, xlnlist.head)
{
x = (xline_t *)n->data;
if (x->duration != 0 && x->expires <= CURRTIME)
continue;
if (!match(x->realname, u->gecos))
return x;
}
return NULL;
}
void xline_expire(void *arg)
{
xline_t *x;
mowgli_node_t *n, *tn;
MOWGLI_ITER_FOREACH_SAFE(n, tn, xlnlist.head)
{
x = (xline_t *)n->data;
if (x->duration == 0)
continue;
if (x->expires <= CURRTIME)
{
slog(LG_INFO, _("XLINE:EXPIRE: \2%s\2 set \2%s\2 ago by \2%s\2"),
x->realname, time_ago(x->settime), x->setby);
verbose_wallops(_("XLINE expired on \2%s\2, set by \2%s\2"),
x->realname, x->setby);
xline_delete(x->realname);
}
}
}
/*************
* Q L I N E *
*************/
qline_t *qline_add(const char *mask, const char *reason, long duration, const char *setby)
{
qline_t *q;
mowgli_node_t *n = mowgli_node_create();
static unsigned int qcnt = 0;
slog(LG_DEBUG, "qline_add(): %s -> %s (%ld)", mask, reason, duration);
q = mowgli_heap_alloc(qline_heap);
mowgli_node_add(q, n, &qlnlist);
q->mask = sstrdup(mask);
q->reason = sstrdup(reason);
q->setby = sstrdup(setby);
q->duration = duration;
q->settime = CURRTIME;
q->expires = CURRTIME + duration;
q->number = ++qcnt;
cnt.qline++;
if (me.connected)
qline_sts("*", mask, duration, reason);
return q;
}
void qline_delete(const char *mask)
{
qline_t *q = qline_find(mask);
mowgli_node_t *n;
if (!q)
{
slog(LG_DEBUG, "qline_delete(): called for nonexistant qline: %s", mask);
return;
}
slog(LG_DEBUG, "qline_delete(): %s -> %s", q->mask, q->reason);
/* only unqline if ircd has not already removed this -- jilles */
if (me.connected && (q->duration == 0 || q->expires > CURRTIME))
unqline_sts("*", q->mask);
n = mowgli_node_find(q, &qlnlist);
mowgli_node_delete(n, &qlnlist);
mowgli_node_free(n);
free(q->mask);
free(q->reason);
free(q->setby);
mowgli_heap_free(qline_heap, q);
cnt.qline--;
}
qline_t *qline_find(const char *mask)
{
qline_t *q;
mowgli_node_t *n;
MOWGLI_ITER_FOREACH(n, qlnlist.head)
{
q = (qline_t *)n->data;
if (!irccasecmp(q->mask, mask))
return q;
}
return NULL;
}
qline_t *qline_find_num(unsigned int number)
{
qline_t *q;
mowgli_node_t *n;
MOWGLI_ITER_FOREACH(n, qlnlist.head)
{
q = (qline_t *)n->data;
if (q->number == number)
return q;
}
return NULL;
}
qline_t *qline_find_user(user_t *u)
{
qline_t *q;
mowgli_node_t *n;
MOWGLI_ITER_FOREACH(n, qlnlist.head)
{
q = (qline_t *)n->data;
if (q->duration != 0 && q->expires <= CURRTIME)
continue;
if (q->mask[0] == '#' || q->mask[0] == '&')
continue;
if (!match(q->mask, u->nick))
return q;
}
return NULL;
}
qline_t *qline_find_channel(channel_t *c)
{
qline_t *q;
mowgli_node_t *n;
MOWGLI_ITER_FOREACH(n, qlnlist.head)
{
q = (qline_t *)n->data;
if (q->duration != 0 && q->expires <= CURRTIME)
continue;
if (!irccasecmp(q->mask, c->name))
return q;
}
return NULL;
}
void qline_expire(void *arg)
{
qline_t *q;
mowgli_node_t *n, *tn;
MOWGLI_ITER_FOREACH_SAFE(n, tn, qlnlist.head)
{
q = (qline_t *)n->data;
if (q->duration == 0)
continue;
if (q->expires <= CURRTIME)
{
slog(LG_INFO, _("QLINE:EXPIRE: \2%s\2 set \2%s\2 ago by \2%s\2"),
q->mask, time_ago(q->settime), q->setby);
verbose_wallops(_("QLINE expired on \2%s\2, set by \2%s\2"),
q->mask, q->setby);
qline_delete(q->mask);
}
}
}
/* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs
* vim:ts=8
* vim:sw=8
* vim:noexpandtab
*/
Jump to Line
Something went wrong with that request. Please try again.