381 lines
7.4 KiB
C
381 lines
7.4 KiB
C
/* NeoStats - IRC Statistical Services
|
|
** Copyright (c) 1999-2004 Adam Rutter, Justin Hammond
|
|
** http://www.neostats.net/
|
|
**
|
|
** Portions Copyright (c) 2000-2001 ^Enigma^
|
|
**
|
|
** Portions Copyright (c) 1999 Johnathan George net@lite.net
|
|
**
|
|
** 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 2 of the License, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
** USA
|
|
**
|
|
** NeoStats CVS Identification
|
|
** $Id$
|
|
*/
|
|
|
|
#include "stats.h"
|
|
#include "dl.h"
|
|
#include "hash.h"
|
|
#include "log.h"
|
|
#include "ircd.h"
|
|
#include "exclude.h"
|
|
#include "server.h"
|
|
#include "users.h"
|
|
#ifdef SQLSRV
|
|
#include "sqlsrv/rta.h"
|
|
#endif
|
|
|
|
hash_t *sh;
|
|
|
|
static Server *
|
|
new_server (const char *name)
|
|
{
|
|
Server *s;
|
|
hnode_t *sn;
|
|
|
|
SET_SEGV_LOCATION();
|
|
s = calloc (sizeof (Server), 1);
|
|
bzero(s, sizeof(Server));
|
|
strlcpy (s->name, name, MAXHOST);
|
|
sn = hnode_create (s);
|
|
if (!sn) {
|
|
nlog (LOG_WARNING, LOG_CORE, "Eeek, Hash is broken\n");
|
|
}
|
|
if (hash_isfull (sh)) {
|
|
nlog (LOG_WARNING, LOG_CORE, "Eeek, Server Hash is full!\n");
|
|
} else {
|
|
hash_insert (sh, sn, s->name);
|
|
}
|
|
return s;
|
|
}
|
|
|
|
Server *
|
|
AddServer (const char *name, const char *uplink, const char* hops, const char *numeric, const char *infoline)
|
|
{
|
|
Server *s;
|
|
char **av;
|
|
int ac = 0;
|
|
|
|
nlog (LOG_DEBUG1, LOG_CORE, "New Server: %s Uplink; %s", name, uplink);
|
|
s = new_server (name);
|
|
if(hops) {
|
|
s->hops = atoi (hops);
|
|
}
|
|
if (uplink) {
|
|
strlcpy (s->uplink, uplink, MAXHOST);
|
|
}
|
|
if(infoline) {
|
|
strlcpy (s->infoline, infoline, MAXINFO);
|
|
}
|
|
if(numeric) {
|
|
s->numeric = atoi(numeric);
|
|
}
|
|
s->connected_since = me.now;
|
|
|
|
if (!ircstrcasecmp(name, me.name)) {
|
|
s->flags |= NS_FLAGS_ME;
|
|
}
|
|
|
|
/* check exclusions */
|
|
ns_do_exclude_server(s);
|
|
|
|
/* run the module event for a new server. */
|
|
AddStringToList (&av, (char*)name, &ac);
|
|
AddStringToList (&av, (char*)uplink, &ac);
|
|
AddStringToList (&av, (char*)hops, &ac);
|
|
AddStringToList (&av, (char*)numeric, &ac);
|
|
AddStringToList (&av, (char*)infoline, &ac);
|
|
ModuleEvent (EVENT_SERVER, av, ac);
|
|
free (av);
|
|
return(s);
|
|
}
|
|
|
|
static void del_server_leaves(Server* hub)
|
|
{
|
|
Server *s;
|
|
hscan_t ss;
|
|
hnode_t *sn;
|
|
|
|
nlog (LOG_DEBUG1, LOG_CORE, "del_server_leaves: %s", hub->name);
|
|
hash_scan_begin (&ss, sh);
|
|
while ((sn = hash_scan_next (&ss)) != NULL) {
|
|
s = hnode_get (sn);
|
|
if(ircstrcasecmp(hub->name, s->uplink) == 0) {
|
|
nlog (LOG_DEBUG1, LOG_CORE, "del_server_leaves: del child %s", s->name);
|
|
DelServer(s->name, hub->name);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
DelServer (const char *name, const char* reason)
|
|
{
|
|
Server *s;
|
|
hnode_t *sn;
|
|
char **av;
|
|
int ac = 0;
|
|
|
|
if (!name) {
|
|
return;
|
|
}
|
|
sn = hash_lookup (sh, name);
|
|
if (!sn) {
|
|
nlog (LOG_WARNING, LOG_CORE, "DelServer: squit from unknown server %s", name);
|
|
return;
|
|
}
|
|
s = hnode_get (sn);
|
|
del_server_leaves(s);
|
|
if(ircd_srv.noquit) {
|
|
QuitServerUsers (s);
|
|
}
|
|
/* run the event for delete server */
|
|
AddStringToList (&av, s->name, &ac);
|
|
if(reason) {
|
|
AddStringToList (&av, (char*)reason, &ac);
|
|
}
|
|
ModuleEvent (EVENT_SQUIT, av, ac);
|
|
free (av);
|
|
|
|
hash_delete (sh, sn);
|
|
hnode_destroy (sn);
|
|
free (s);
|
|
}
|
|
|
|
#ifdef BASE64SERVERNAME
|
|
Server *
|
|
findserverbase64 (const char *num)
|
|
{
|
|
Server *s;
|
|
hscan_t ss;
|
|
hnode_t *sn;
|
|
|
|
hash_scan_begin (&ss, sh);
|
|
while ((sn = hash_scan_next (&ss)) != NULL) {
|
|
s = hnode_get (sn);
|
|
if(strncmp(s->name64, num, BASE64SERVERSIZE) == 0) {
|
|
nlog (LOG_DEBUG1, LOG_CORE, "findserverbase64: %s -> %s", num, s->name);
|
|
return s;
|
|
}
|
|
}
|
|
nlog (LOG_DEBUG3, LOG_CORE, "findserverbase64: %s not found!", num);
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
Server *
|
|
findserver (const char *name)
|
|
{
|
|
Server *s;
|
|
hnode_t *sn;
|
|
|
|
sn = hash_lookup (sh, name);
|
|
if (sn) {
|
|
s = hnode_get (sn);
|
|
return s;
|
|
}
|
|
nlog (LOG_DEBUG3, LOG_CORE, "findserver: %s not found!", name);
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
dumpserver (Server *s)
|
|
{
|
|
#ifdef BASE64SERVERNAME
|
|
debugtochannel("Server: %s (%s)", s->name, s->name64);
|
|
#else
|
|
debugtochannel("Server: %s", s->name);
|
|
#endif
|
|
debugtochannel("Flags: %lx", s->flags);
|
|
debugtochannel("Uplink: %s", s->uplink);
|
|
debugtochannel("========================================");
|
|
}
|
|
|
|
void
|
|
ServerDump (const char *name)
|
|
{
|
|
Server *s;
|
|
hscan_t ss;
|
|
hnode_t *sn;
|
|
|
|
debugtochannel("================SERVDUMP================");
|
|
if (!name) {
|
|
hash_scan_begin (&ss, sh);
|
|
while ((sn = hash_scan_next (&ss)) != NULL) {
|
|
s = hnode_get (sn);
|
|
dumpserver (s);
|
|
}
|
|
} else {
|
|
s = findserver (name);
|
|
if (s) {
|
|
dumpserver (s);
|
|
} else {
|
|
debugtochannel("ServerDump: can't find server %s", name);
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef SQLSRV
|
|
COLDEF neo_serverscols[] = {
|
|
{
|
|
"servers",
|
|
"name",
|
|
RTA_STR,
|
|
MAXHOST,
|
|
offsetof(struct Server, name),
|
|
RTA_READONLY,
|
|
NULL,
|
|
NULL,
|
|
"The name of the server linked to the IRC network"
|
|
},
|
|
{
|
|
"servers",
|
|
"hops",
|
|
RTA_INT,
|
|
sizeof(int),
|
|
offsetof(struct Server, hops),
|
|
RTA_READONLY,
|
|
NULL,
|
|
NULL,
|
|
"The Number of hops away from the NeoStats Server"
|
|
},
|
|
{
|
|
"servers",
|
|
"connected",
|
|
RTA_INT,
|
|
sizeof(int),
|
|
offsetof(struct Server, connected_since),
|
|
RTA_READONLY,
|
|
NULL,
|
|
NULL,
|
|
"The time the server connected to the IRC network"
|
|
},
|
|
{
|
|
"servers",
|
|
"last_ping",
|
|
RTA_INT,
|
|
sizeof(int),
|
|
offsetof(struct Server, ping),
|
|
RTA_READONLY,
|
|
NULL,
|
|
NULL,
|
|
"The last ping time to this server from the NeoStats Server"
|
|
},
|
|
{
|
|
"servers",
|
|
"flags",
|
|
RTA_INT,
|
|
sizeof(int),
|
|
offsetof(struct Server, flags),
|
|
RTA_READONLY,
|
|
NULL,
|
|
NULL,
|
|
"Flags that specify special functions for this Server"
|
|
},
|
|
{
|
|
"servers",
|
|
"uplink",
|
|
RTA_STR,
|
|
MAXHOST,
|
|
offsetof(struct Server, uplink),
|
|
RTA_READONLY,
|
|
NULL,
|
|
NULL,
|
|
"The uplink Server this server is connected to. if it = self, means the NeoStats Server"
|
|
},
|
|
{
|
|
"servers",
|
|
"infoline",
|
|
RTA_STR,
|
|
MAXINFO,
|
|
offsetof(struct Server, infoline),
|
|
RTA_READONLY,
|
|
NULL,
|
|
NULL,
|
|
"The description of this server"
|
|
},
|
|
};
|
|
|
|
TBLDEF neo_servers = {
|
|
"servers",
|
|
NULL, /* for now */
|
|
sizeof(struct Server),
|
|
0,
|
|
TBL_HASH,
|
|
neo_serverscols,
|
|
sizeof(neo_serverscols) / sizeof(COLDEF),
|
|
"",
|
|
"The list of Servers connected to the IRC network"
|
|
};
|
|
#endif /* SQLSRV */
|
|
|
|
|
|
int
|
|
init_server_hash (void)
|
|
{
|
|
sh = hash_create (S_TABLE_SIZE, 0, 0);
|
|
if (!sh) {
|
|
nlog (LOG_CRITICAL, LOG_CORE, "Create Server Hash Failed\n");
|
|
return NS_FAILURE;
|
|
}
|
|
AddServer (me.name, NULL, 0, NULL, me.infoline);
|
|
#ifdef SQLSRV
|
|
/* add the server hash to the sql library */
|
|
neo_servers.address = sh;
|
|
rta_add_table(&neo_servers);
|
|
#endif
|
|
return NS_SUCCESS;
|
|
}
|
|
|
|
|
|
void
|
|
PingServers (void)
|
|
{
|
|
Server *s;
|
|
hscan_t ss;
|
|
hnode_t *sn;
|
|
|
|
if(!me.synced)
|
|
return;
|
|
nlog (LOG_DEBUG3, LOG_CORE, "Sending pings...");
|
|
ping.ulag = 0;
|
|
|
|
hash_scan_begin (&ss, sh);
|
|
while ((sn = hash_scan_next (&ss)) != NULL) {
|
|
s = hnode_get (sn);
|
|
if (!strcmp (me.name, s->name)) {
|
|
s->ping = 0;
|
|
continue;
|
|
}
|
|
send_ping (me.name, me.name, s->name);
|
|
}
|
|
}
|
|
|
|
void
|
|
FreeServers ()
|
|
{
|
|
Server *s;
|
|
hnode_t *sn;
|
|
hscan_t hs;
|
|
|
|
hash_scan_begin(&hs, sh);
|
|
while ((sn = hash_scan_next(&hs)) != NULL ) {
|
|
s = hnode_get (sn);
|
|
hash_delete (sh, sn);
|
|
hnode_destroy (sn);
|
|
free (s);
|
|
}
|
|
hash_destroy(sh);
|
|
|
|
}
|