summaryrefslogtreecommitdiff
path: root/src/servers.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/servers.c')
-rw-r--r--src/servers.c702
1 files changed, 0 insertions, 702 deletions
diff --git a/src/servers.c b/src/servers.c
deleted file mode 100644
index 0978e8f30..000000000
--- a/src/servers.c
+++ /dev/null
@@ -1,702 +0,0 @@
-/* Routines to maintain a list of connected servers
- *
- * (C) 2003-2010 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- *
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
- *
- *
- */
-
-#include "services.h"
-#include "modules.h"
-
-Server *servlist = NULL;
-Server *me_server = NULL; /* This are we */
-Server *serv_uplink = NULL; /* This is our uplink */
-Flags<CapabType> Capab;
-char *uplink;
-char *TS6UPLINK;
-char *TS6SID;
-
-/* For first_server / next_server */
-static Server *server_cur;
-
-CapabInfo Capab_Info[] = {
- {"NOQUIT", CAPAB_NOQUIT},
- {"TSMODE", CAPAB_TSMODE},
- {"UNCONNECT", CAPAB_UNCONNECT},
- {"NICKIP", CAPAB_NICKIP},
- {"SSJOIN", CAPAB_NSJOIN},
- {"ZIP", CAPAB_ZIP},
- {"BURST", CAPAB_BURST},
- {"TS5", CAPAB_TS5},
- {"TS3", CAPAB_TS3},
- {"DKEY", CAPAB_DKEY},
- {"PT4", CAPAB_PT4},
- {"SCS", CAPAB_SCS},
- {"QS", CAPAB_QS},
- {"UID", CAPAB_UID},
- {"KNOCK", CAPAB_KNOCK},
- {"CLIENT", CAPAB_CLIENT},
- {"IPV6", CAPAB_IPV6},
- {"SSJ5", CAPAB_SSJ5},
- {"SN2", CAPAB_SN2},
- {"TOK1", CAPAB_TOKEN},
- {"TOKEN", CAPAB_TOKEN},
- {"VHOST", CAPAB_VHOST},
- {"SSJ3", CAPAB_SSJ3},
- {"SJB64", CAPAB_SJB64},
- {"CHANMODES", CAPAB_CHANMODE},
- {"NICKCHARS", CAPAB_NICKCHARS},
- {"", CAPAB_END}
-};
-
-/*************************************************************************/
-
-/**
- * Return the first server in the server struct
- * @param flag Server Flag, see services.h
- * @return Server Struct
- */
-Server *first_server(ServerFlag flag)
-{
- server_cur = servlist;
-
- while (server_cur && !server_cur->HasFlag(flag))
- server_cur = next_server(flag);
- return server_cur;
-}
-
-/*************************************************************************/
-
-/**
- * Return the next server in the server struct
- * @param flags Server Flags, see services.h
- * @return Server Struct
- */
-Server *next_server(ServerFlag flag)
-{
- if (!server_cur)
- return NULL;
-
- do {
- if (server_cur->links) {
- server_cur = server_cur->links;
- } else if (server_cur->next) {
- server_cur = server_cur->next;
- } else {
- do {
- server_cur = server_cur->uplink;
- if (server_cur && server_cur->next) {
- server_cur = server_cur->next;
- break;
- }
- } while (server_cur);
- }
- } while (server_cur && !server_cur->HasFlag(flag));
-
- return server_cur;
-}
-
-/*************************************************************************/
-
-/**
- * This function makes a new Server structure and links it in the right
- * places in the linked list if a Server struct to it's uplink if provided.
- * It can also be NULL to indicate it's the uplink and should be first in
- * the server list.
- * @param server_uplink Server struct
- * @param name Server Name
- * @param desc Server Description
- * @param flags Server Flags, see services.h
- * @param suid Server Universal ID
- * @return Server Struct
- */
-Server *new_server(Server * server_uplink, const char *name, const char *desc,
- ServerFlag flag, const std::string &suid)
-{
- Server *serv;
-
- Alog(LOG_DEBUG) << "Creating " << name << "(" << suid << ") uplinked to " << (server_uplink ? server_uplink->name : "No uplink");
- serv = new Server;
- if (!name)
- name = "";
- serv->name = sstrdup(name);
- serv->desc = sstrdup(desc);
- if (flag != SERVER_START)
- serv->SetFlag(flag);
- serv->uplink = server_uplink;
- if (!suid.empty())
- serv->suid = sstrdup(suid.c_str());
- else
- serv->suid = NULL;
-
- serv->sync = SSYNC_IN_PROGRESS;
- serv->links = NULL;
- serv->prev = NULL;
-
- if (!server_uplink) {
- serv->hops = 0;
- serv->next = servlist;
- if (servlist)
- servlist->prev = serv;
- servlist = serv;
- } else {
- serv->hops = server_uplink->hops + 1;
- serv->next = server_uplink->links;
- if (server_uplink->links)
- server_uplink->links->prev = serv;
- server_uplink->links = serv;
- }
-
- /* Check if this is our uplink server */
- if ((server_uplink == me_server) && flag != SERVER_JUPED)
- {
- // XXX: Apparantly we set ourselves as serv_uplink before we (really) set the uplink when we recieve SERVER. This is wrong and ugly.
- if (serv_uplink != NULL)
- {
- /* Bring in our pseudo-clients */
- introduce_user("");
-
- /* And hybrid needs Global joined in the logchan */
- if (LogChan && ircd->join2msg) {
- /* XXX might desync */
- ircdproto->SendJoin(findbot(Config.s_GlobalNoticer), Config.LogChannel, time(NULL));
- }
- }
- serv_uplink = serv;
- serv->SetFlag(SERVER_ISUPLINK);
- }
-
- return serv;
-}
-
-/*************************************************************************/
-
-/**
- * Remove and free a Server structure. This function is the most complete
- * remove treatment a server can get, as it first quits all clients which
- * still pretend to be on this server, then it walks through all connected
- * servers and disconnects them too. If all mess is cleared, the server
- * itself will be too.
- * @param Server struct
- * @param reason the server quit
- * @return void
- */
-static void delete_server(Server * serv, const char *quitreason)
-{
- Server *s, *snext;
- User *u, *unext;
- NickAlias *na;
-
- if (!serv) {
- Alog(LOG_DEBUG) << "delete_server() called with NULL arg!";
- return;
- }
-
- Alog(LOG_DEBUG) << "delete_server() called, deleting " << serv->name << "(" << serv->suid << ") uplinked to "
- << (serv->uplink ? serv->uplink->name : "NOTHING") << "("
- << (serv->uplink ? serv->uplink->suid : "NOSUIDUPLINK") << ")";
-
- if (Capab.HasFlag(CAPAB_NOQUIT) || Capab.HasFlag(CAPAB_QS))
- {
- u = firstuser();
- while (u)
- {
- unext = nextuser();
- if (u->server == serv)
- {
- if ((na = findnick(u->nick)) && !na->HasFlag(NS_FORBIDDEN)
- && (!na->nc->HasFlag(NI_SUSPENDED))
- && (u->IsRecognized() || u->IsIdentified())) {
- na->last_seen = time(NULL);
- if (na->last_quit)
- delete [] na->last_quit;
- na->last_quit = (quitreason ? sstrdup(quitreason) : NULL);
- }
- if (Config.LimitSessions && !is_ulined(u->server->name)) {
- del_session(u->host);
- }
- delete u;
- }
- u = unext;
- }
- Alog(LOG_DEBUG) << "delete_server() cleared all users";
- }
-
- s = serv->links;
- while (s) {
- snext = s->next;
- delete_server(s, quitreason);
- s = snext;
- }
-
- Alog(LOG_DEBUG) << "delete_server() cleared all servers";
-
- delete [] serv->name;
- delete [] serv->desc;
- if (serv->prev)
- serv->prev->next = serv->next;
- if (serv->next)
- serv->next->prev = serv->prev;
- if (serv->uplink->links == serv)
- serv->uplink->links = serv->next;
-
- Alog(LOG_DEBUG) << "delete_server() completed";
-}
-
-/*************************************************************************/
-
-/**
- * Find a server by name, returns NULL if not found
- * @param s Server struct
- * @param name Server Name
- * @return Server struct
- */
-Server *findserver(Server * s, const char *name)
-{
- Server *sl;
-
- if (!name || !*name) {
- return NULL;
- }
-
- Alog(LOG_DEBUG) << "findserver(" << name << ")";
-
- while (s && (stricmp(s->name, name) != 0))
- {
- Alog(LOG_DEBUG_3) << "Compared " << s->name << ", not a match";
- if (s->links)
- {
- sl = findserver(s->links, name);
- if (sl)
- {
- s = sl;
- }
- else
- {
- s = s->next;
- }
- }
- else
- {
- s = s->next;
- }
- }
-
- Alog(LOG_DEBUG) << "findserver(" << name << ") -> " << static_cast<void *>(s);
- return s;
-}
-
-/*************************************************************************/
-
-/**
- * Find a server by UID, returns NULL if not found
- * @param s Server struct
- * @param name Server Name
- * @return Server struct
- */
-Server *findserver_uid(Server * s, const char *name)
-{
- Server *sl;
-
- if (!name || !*name) {
- return NULL;
- }
-
- Alog(LOG_DEBUG) << "findserver_uid(" << name << ")";
-
- while (s && s->suid && (stricmp(s->suid, name) != 0))
- {
- Alog(LOG_DEBUG_3) << "Compared " << s->suid << ", not a match";
- if (s->links)
- {
- sl = findserver_uid(s->links, name);
- if (sl)
- {
- s = sl;
- }
- else
- {
- s = s->next;
- }
- }
- else
- {
- s = s->next;
- }
- }
-
- Alog(LOG_DEBUG) << "findserver_uid(" << name << ") -> " << static_cast<void *>(s);
- return s;
-}
-
-/*************************************************************************/
-
-/**
- * Find if the server is synced with the network
- * @param s Server struct
- * @param name Server Name
- * @return Not Synced returns -1, Synced returns 1, Error returns 0
- */
-int anope_check_sync(const char *name)
-{
- Server *s;
- s = findserver(servlist, name);
-
- if (!s)
- return 0;
-
- if (is_sync(s))
- return 1;
- else
- return -1;
-}
-
-/*************************************************************************/
-
-/**
- * Handle adding the server to the Server struct
- * @param source Name of the uplink if any
- * @param servername Name of the server being linked
- * @param hops Number of hops to reach this server
- * @param descript Description of the server
- * @param numeric Server Numberic/SUID
- * @return void
- */
-void do_server(const char *source, const char *servername, const char *hops,
- const char *descript, const std::string &numeric)
-{
- Server *s, *newserver;
-
- Alog(LOG_DEBUG) << "Server introduced (" << servername << ")" << (*source ? " from " : "") << (*source ? source : "");
-
-
- if (source[0] == '\0')
- s = me_server;
- else
- s = findserver(servlist, source);
-
- if (s == NULL)
- s = findserver_uid(servlist, source);
-
- if (s == NULL)
- throw CoreException("Recieved a server from a nonexistant uplink?");
-
- /* Create a server structure. */
- newserver = new_server(s, servername, descript, SERVER_START, numeric);
-
- /* Announce services being online. */
- if (Config.GlobalOnCycle && Config.GlobalOnCycleUP)
- notice_server(Config.s_GlobalNoticer, newserver, "%s", Config.GlobalOnCycleUP);
-
- /* Let modules know about the connection */
- FOREACH_MOD(I_OnNewServer, OnNewServer(newserver));
-}
-
-/*************************************************************************/
-
-/**
- * Handle removing the server from the Server struct
- * @param source Name of the server leaving
- * @param ac Number of arguments in av
- * @param av Agruments as part of the SQUIT
- * @return void
- */
-void do_squit(const char *source, int ac, const char **av)
-{
- char buf[BUFSIZE];
- Server *s;
-
- if (ircd->ts6) {
- s = findserver_uid(servlist, av[0]);
- if (!s) {
- s = findserver(servlist, av[0]);
- }
- } else {
- s = findserver(servlist, av[0]);
- }
- if (!s)
- {
- Alog() << "SQUIT for nonexistent server (" << av[0] << ")!!";
- return;
- }
- FOREACH_MOD(I_OnServerQuit, OnServerQuit(s));
-
- /* If this is a juped server, send a nice global to inform the online
- * opers that we received it.
- */
- if (s->HasFlag(SERVER_JUPED))
- {
- snprintf(buf, BUFSIZE, "Received SQUIT for juped server %s",
- s->name);
- ircdproto->SendGlobops(findbot(Config.s_OperServ), buf);
- }
-
- snprintf(buf, sizeof(buf), "%s %s", s->name,
- (s->uplink ? s->uplink->name : ""));
-
- if (s->uplink == me_server && Capab.HasFlag(CAPAB_UNCONNECT))
- {
- Alog(LOG_DEBUG) << "Sending UNCONNECT SQUIT for " << s->name;
- /* need to fix */
- ircdproto->SendSquit(s->name, buf);
- }
-
- delete_server(s, buf);
-}
-
-/*************************************************************************/
-
-/** Handle parsing the CAPAB/PROTOCTL messages
- * @param ac Number of args
- * @param av Args
- */
-void CapabParse(int ac, const char **av)
-{
- for (int i = 0; i < ac; ++i)
- {
- for (unsigned j = 0; !Capab_Info[j].Token.empty(); ++j)
- {
- if (av[i] == Capab_Info[j].Token)
- {
- Capab.SetFlag(Capab_Info[j].Flag);
-
- if (Capab_Info[j].Token == "NICKIP" && !ircd->nickip)
- ircd->nickip = 1;
- break;
- }
- }
- }
-}
-
-/*************************************************************************/
-
-/**
- * Search the uline servers array to find out if the server that just set the
- * mode is in our uline list
- * @param server Server Setting the mode
- * @return int 0 if not found, 1 if found
- */
-int is_ulined(const char *server)
-{
- int j;
-
- for (j = 0; j < Config.NumUlines; j++) {
- if (stricmp(Config.Ulines[j], server) == 0) {
- return 1;
- }
- }
-
- return 0;
-}
-
-/*************************************************************************/
-
-/**
- * See if the current server is synced, or has an unknown sync state
- * (in which case we pretend it is always synced)
- * @param server Server of which we want to know the state
- * @return int 0 if not synced, 1 if synced
- */
-int is_sync(Server * server)
-{
- if (server->sync == SSYNC_DONE)
- return 1;
- return 0;
-}
-
-/*************************************************************************/
-
-/* Finish the syncing process for this server and (optionally) for all
- * it's leaves as well
- * @param serv Server to finish syncing
- * @param sync_links Should all leaves be synced as well? (1: yes, 0: no)
- * @return void
- */
-void finish_sync(Server * serv, int sync_links)
-{
- Server *s;
-
- if (!serv || is_sync(serv))
- return;
-
- /* Mark each server as in sync */
- s = serv;
- do {
- if (!is_sync(s))
- {
- Alog(LOG_DEBUG) << "Finishing sync for server " << s->name;
- s->sync = SSYNC_DONE;
- }
-
- if (!sync_links)
- break;
-
- if (s->links) {
- s = s->links;
- } else if (s->next) {
- s = s->next;
- } else {
- do {
- s = s->uplink;
- if (s == serv)
- s = NULL;
- if (s == me_server)
- s = NULL;
- } while (s && !(s->next));
- if (s)
- s = s->next;
- }
- } while (s);
-
- if (serv == serv_uplink)
- {
- FOREACH_MOD(I_OnFinishSync, OnFinishSync(serv));
- ircdproto->SendEOB();
- }
-
- /* Do some general stuff which should only be done once */
- // XXX: this doesn't actually match the description. finish_sync(), depending on the ircd, can be called multiple times
- // Perhaps this should be done if serv == serv_uplink?
- restore_unsynced_topics();
- Alog() << "Server " << serv->name << " is done syncing";
-
- FOREACH_MOD(I_OnServerSync, OnServerSync(s));
- if (serv == serv_uplink)
- {
- FOREACH_MOD(I_OnUplinkSync, OnUplinkSync());
- }
-}
-
-/*******************************************************************/
-
-/* TS6 UID generator common code.
- *
- * Derived from atheme-services, uid.c (hg 2954:116d46894b4c).
- * -nenolod
- */
-static int ts6_uid_initted = 0;
-static char ts6_new_uid[10]; /* allow for \0 */
-static unsigned int ts6_uid_index = 9; /* last slot in uid buf */
-
-void ts6_uid_init()
-{
- snprintf(ts6_new_uid, 10, "%sAAAAAA", TS6SID);
- ts6_uid_initted = 1;
-}
-
-void ts6_uid_increment(unsigned int slot)
-{
- if (slot != strlen(TS6SID)) {
- if (ts6_new_uid[slot] == 'Z')
- ts6_new_uid[slot] = '0';
- else if (ts6_new_uid[slot] == '9') {
- ts6_new_uid[slot] = 'A';
- ts6_uid_increment(slot - 1);
- } else
- ts6_new_uid[slot]++;
- } else {
- if (ts6_new_uid[slot] == 'Z')
- for (slot = 3; slot < 9; slot++)
- ts6_new_uid[slot] = 'A';
- else
- ts6_new_uid[slot]++;
- }
-}
-
-const char *ts6_uid_retrieve()
-{
- if (ircd->ts6 == 0)
- {
- Alog(LOG_DEBUG) << "ts6_uid_retrieve(): TS6 not supported on this ircd";
- return "";
- }
-
- if (ts6_uid_initted != 1)
- {
- throw CoreException("TS6 IRCd and ts6_uid_init() hasn't been called!");
- }
-
- ts6_uid_increment(ts6_uid_index - 1);
- return ts6_new_uid;
-}
-
-/*******************************************************************/
-
-/*
- * TS6 generator code, provided by DukePyrolator
- */
-
-static int ts6_sid_initted = 0;
-static char ts6_new_sid[4];
-
-static void ts6_sid_increment(unsigned pos)
-{
- /*
- * An SID must be exactly 3 characters long, starts with a digit,
- * and the other two characters are A-Z or digits
- * The rules for generating an SID go like this...
- * --> ABCDEFGHIJKLMNOPQRSTUVWXYZ --> 0123456789 --> WRAP
- */
- if (!pos)
- {
- /* At pos 0, if we hit '9', we've run out of available SIDs,
- * reset the SID to the smallest possible value and try again. */
- if (ts6_new_sid[pos] == '9')
- {
- ts6_new_sid[0] = '0';
- ts6_new_sid[1] = 'A';
- ts6_new_sid[2] = 'A';
- }
- else
- // But if we haven't, just keep incrementing merrily.
- ++ts6_new_sid[0];
- }
- else
- {
- if (ts6_new_sid[pos] == 'Z')
- ts6_new_sid[pos] = '0';
- else if (ts6_new_sid[pos] == '9')
- {
- ts6_new_sid[pos] = 'A';
- ts6_sid_increment(pos - 1);
- }
- else
- ++ts6_new_sid[pos];
- }
-}
-
-const char *ts6_sid_retrieve()
-{
- if (!ircd->ts6)
- {
- Alog(LOG_DEBUG) << "ts6_sid_retrieve(): TS6 not supported on this ircd";
- return "";
- }
-
- if (!ts6_sid_initted)
- {
- // Initialize ts6_new_sid with the services server SID
- snprintf(ts6_new_sid, 4, "%s", TS6SID);
- ts6_sid_initted = 1;
- }
- while (1)
- {
- // Check if the new SID is used by a known server
- if (!findserver_uid(servlist, ts6_new_sid))
- // return the new SID
- return ts6_new_sid;
-
- // Add one to the last SID
- ts6_sid_increment(2);
- }
- /* not reached */
- return "";
-}
-
-/* EOF */