diff options
author | sjaz <sjaz@5417fbe8-f217-4b02-8779-1006273d7864> | 2009-01-01 12:00:20 +0000 |
---|---|---|
committer | sjaz <sjaz@5417fbe8-f217-4b02-8779-1006273d7864> | 2009-01-01 12:00:20 +0000 |
commit | c777c8d9aa7cd5c2e9a399727a7fa9985a77fb1c (patch) | |
tree | 9e996ae4a1bbb833cec036c5cd4d87a590149e85 /src/hostserv.c |
Anope Stable Branch
git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/stable@1902 5417fbe8-f217-4b02-8779-1006273d7864
Diffstat (limited to 'src/hostserv.c')
-rw-r--r-- | src/hostserv.c | 655 |
1 files changed, 655 insertions, 0 deletions
diff --git a/src/hostserv.c b/src/hostserv.c new file mode 100644 index 000000000..bdb6dbba3 --- /dev/null +++ b/src/hostserv.c @@ -0,0 +1,655 @@ +/* HostServ functions + * + * (C) 2003-2008 Anope Team + * Contact us at info@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. + * + * $Id$ + * + */ + +/*************************************************************************/ +#include "services.h" +#include "pseudo.h" + +#define HASH(nick) ((tolower((nick)[0])&31)<<5 | (tolower((nick)[1])&31)) + +void load_hs_dbase_v1(dbFILE * f); +void load_hs_dbase_v2(dbFILE * f); +void load_hs_dbase_v3(dbFILE * f); + +HostCore *head = NULL; /* head of the HostCore list */ + +E int do_hs_sync(NickCore * nc, char *vIdent, char *hostmask, + char *creator, time_t time); + +E void moduleAddHostServCmds(void); + +/*************************************************************************/ + +void moduleAddHostServCmds(void) +{ + modules_core_init(HostServCoreNumber, HostServCoreModules); +} + +/*************************************************************************/ + +/** + * Return information on memory use. + * Assumes pointers are valid. + **/ + +void get_hostserv_stats(long *nrec, long *memuse) +{ + long count = 0, mem = 0; + int i; + HostCore *hc; + + for (hc = head; hc; hc = hc->next) { + count++; + mem += sizeof(*hc); + if (hc->nick) + mem += strlen(hc->nick) + 1; + if (hc->vIdent) + mem += strlen(hc->vIdent) + 1; + if (hc->vHost) + mem += strlen(hc->vHost) + 1; + if (hc->creator) + mem += strlen(hc->creator) + 1; + } + + *nrec = count; + *memuse = mem; +} + +/*************************************************************************/ + +/** + * HostServ initialization. + * @return void + */ +void hostserv_init(void) +{ + if (s_HostServ) { + moduleAddHostServCmds(); + } +} + +/*************************************************************************/ + +/** + * Main HostServ routine. + * @param u User Struct + * @param buf Buffer holding the message + * @return void + */ +void hostserv(User * u, char *buf) +{ + char *cmd, *s; + + cmd = strtok(buf, " "); + + if (!cmd) { + return; + } else if (stricmp(cmd, "\1PING") == 0) { + if (!(s = strtok(NULL, ""))) { + s = ""; + } + anope_cmd_ctcp(s_HostServ, u->nick, "PING %s", s); + } else if (skeleton) { + notice_lang(s_HostServ, u, SERVICE_OFFLINE, s_HostServ); + } else { + if (ircd->vhost) { + mod_run_cmd(s_HostServ, u, HOSTSERV, cmd); + } else { + notice_lang(s_HostServ, u, SERVICE_OFFLINE, s_HostServ); + } + } +} + +/*************************************************************************/ +/* Start of Linked List routines */ +/*************************************************************************/ + +HostCore *hostCoreListHead() +{ + return head; +} + +/** + * Create HostCore list member + * @param next HostCore next slot + * @param nick Nick to add + * @param vIdent Virtual Ident + * @param vHost Virtual Host + * @param creator Person whom set the vhost + * @param time Time the vhost was Set + * @return HostCore + */ +HostCore *createHostCorelist(HostCore * next, char *nick, char *vIdent, + char *vHost, char *creator, int32 tmp_time) +{ + + next = malloc(sizeof(HostCore)); + if (next == NULL) { + anope_cmd_global(s_HostServ, + "Unable to allocate memory to create the vHost LL, problems i sense.."); + } else { + next->nick = malloc(sizeof(char) * strlen(nick) + 1); + next->vHost = malloc(sizeof(char) * strlen(vHost) + 1); + next->creator = malloc(sizeof(char) * strlen(creator) + 1); + if (vIdent) + next->vIdent = malloc(sizeof(char) * strlen(vIdent) + 1); + if ((next->nick == NULL) || (next->vHost == NULL) + || (next->creator == NULL)) { + anope_cmd_global(s_HostServ, + "Unable to allocate memory to create the vHost LL, problems i sense.."); + return NULL; + } + strcpy(next->nick, nick); + strcpy(next->vHost, vHost); + strcpy(next->creator, creator); + if (vIdent) { + if ((next->vIdent == NULL)) { + anope_cmd_global(s_HostServ, + "Unable to allocate memory to create the vHost LL, problems i sense.."); + return NULL; + } + strcpy(next->vIdent, vIdent); + } else { + next->vIdent = NULL; + } + next->time = tmp_time; + next->next = NULL; + return next; + } + return NULL; +} + +/*************************************************************************/ +/** + * Returns either NULL for the head, or the location of the *PREVIOUS* + * record, this is where we need to insert etc.. + * @param head HostCore head + * @param nick Nick to find + * @param found If found + * @return HostCore + */ +HostCore *findHostCore(HostCore * head, char *nick, boolean * found) +{ + HostCore *previous, *current; + + *found = false; + current = head; + previous = current; + + if (!nick) { + return NULL; + } + + while (current != NULL) { + if (stricmp(nick, current->nick) == 0) { + *found = true; + break; + } else if (stricmp(nick, current->nick) < 0) { + /* we know were not gonna find it now.... */ + break; + } else { + previous = current; + current = current->next; + } + } + if (current == head) { + return NULL; + } else { + return previous; + } +} + +/*************************************************************************/ +HostCore *insertHostCore(HostCore * head, HostCore * prev, char *nick, + char *vIdent, char *vHost, char *creator, + int32 tmp_time) +{ + + HostCore *newCore, *tmp; + + if (!nick || !vHost || !creator) { + return NULL; + } + + newCore = malloc(sizeof(HostCore)); + if (newCore == NULL) { + anope_cmd_global(s_HostServ, + "Unable to allocate memory to insert into the vHost LL, problems i sense.."); + return NULL; + } else { + newCore->nick = malloc(sizeof(char) * strlen(nick) + 1); + newCore->vHost = malloc(sizeof(char) * strlen(vHost) + 1); + newCore->creator = malloc(sizeof(char) * strlen(creator) + 1); + if (vIdent) + newCore->vIdent = malloc(sizeof(char) * strlen(vIdent) + 1); + if ((newCore->nick == NULL) || (newCore->vHost == NULL) + || (newCore->creator == NULL)) { + anope_cmd_global(s_HostServ, + "Unable to allocate memory to create the vHost LL, problems i sense.."); + return NULL; + } + strcpy(newCore->nick, nick); + strcpy(newCore->vHost, vHost); + strcpy(newCore->creator, creator); + if (vIdent) { + if ((newCore->vIdent == NULL)) { + anope_cmd_global(s_HostServ, + "Unable to allocate memory to create the vHost LL, problems i sense.."); + return NULL; + } + strcpy(newCore->vIdent, vIdent); + } else { + newCore->vIdent = NULL; + } + newCore->time = tmp_time; + if (prev == NULL) { + tmp = head; + head = newCore; + newCore->next = tmp; + } else { + tmp = prev->next; + prev->next = newCore; + newCore->next = tmp; + } + } + return head; +} + +/*************************************************************************/ +HostCore *deleteHostCore(HostCore * head, HostCore * prev) +{ + + HostCore *tmp; + + if (prev == NULL) { + tmp = head; + head = head->next; + } else { + tmp = prev->next; + prev->next = tmp->next; + } + free(tmp->vHost); + free(tmp->nick); + free(tmp->creator); + if (tmp->vIdent) { + free(tmp->vIdent); + } + free(tmp); + return head; +} + +/*************************************************************************/ +void addHostCore(char *nick, char *vIdent, char *vhost, char *creator, + int32 tmp_time) +{ + HostCore *tmp; + boolean found = false; + + if (head == NULL) { + head = + createHostCorelist(head, nick, vIdent, vhost, creator, + tmp_time); + } else { + tmp = findHostCore(head, nick, &found); + if (!found) { + head = + insertHostCore(head, tmp, nick, vIdent, vhost, creator, + tmp_time); + } else { + head = deleteHostCore(head, tmp); /* delete the old entry */ + addHostCore(nick, vIdent, vhost, creator, tmp_time); /* recursive call to add new entry */ + } + } +} + +/*************************************************************************/ +char *getvHost(char *nick) +{ + HostCore *tmp; + boolean found = false; + tmp = findHostCore(head, nick, &found); + if (found) { + if (tmp == NULL) + return head->vHost; + else + return tmp->next->vHost; + } + return NULL; +} + +/*************************************************************************/ +char *getvIdent(char *nick) +{ + HostCore *tmp; + boolean found = false; + tmp = findHostCore(head, nick, &found); + if (found) { + if (tmp == NULL) + return head->vIdent; + else + return tmp->next->vIdent; + } + return NULL; +} + +/*************************************************************************/ +void delHostCore(char *nick) +{ +#ifdef USE_RDB + static char clause[128]; + char *q_nick; +#endif + HostCore *tmp; + boolean found = false; + tmp = findHostCore(head, nick, &found); + if (found) { + head = deleteHostCore(head, tmp); + +#ifdef USE_RDB + /* Reflect this change in the database right away. */ + if (rdb_open()) { + q_nick = rdb_quote(nick); + snprintf(clause, sizeof(clause), "nick='%s'", q_nick); + if (rdb_scrub_table("anope_hs_core", clause) == 0) + alog("Unable to scrub table 'anope_hs_core' - HostServ RDB update failed."); + rdb_close(); + free(q_nick); + } +#endif + + } + +} + +/*************************************************************************/ +/* End of Linked List routines */ +/*************************************************************************/ +/*************************************************************************/ +/* Start of Load/Save routines */ +/*************************************************************************/ +#define SAFE(x) do { \ + if ((x) < 0) { \ + if (!forceload) \ + fatal("Read error on %s", HostDBName); \ + failed = 1; \ + break; \ + } \ +} while (0) + +void load_hs_dbase(void) +{ + dbFILE *f; + int ver; + + if (!(f = open_db(s_HostServ, HostDBName, "r", HOST_VERSION))) { + return; + } + ver = get_file_version(f); + + if (ver == 1) { + load_hs_dbase_v1(f); + } else if (ver == 2) { + load_hs_dbase_v2(f); + } else if (ver == 3) { + load_hs_dbase_v3(f); + } + close_db(f); +} + +void load_hs_dbase_v1(dbFILE * f) +{ + int c; + int failed = 0; + int32 tmp; + + char *nick; + char *vHost; + + tmp = time(NULL); + + while (!failed && (c = getc_db(f)) == 1) { + + if (c == 1) { + SAFE(read_string(&nick, f)); + SAFE(read_string(&vHost, f)); + addHostCore(nick, NULL, vHost, "Unknown", tmp); /* could get a speed increase by not searching the list */ + free(nick); /* as we know the db is in alphabetical order... */ + free(vHost); + } else { + fatal("Invalid format in %s %d", HostDBName, c); + } + } +} + +void load_hs_dbase_v2(dbFILE * f) +{ + int c; + int failed = 0; + + char *nick; + char *vHost; + char *creator; + uint32 time; + + while (!failed && (c = getc_db(f)) == 1) { + + if (c == 1) { + SAFE(read_string(&nick, f)); + SAFE(read_string(&vHost, f)); + SAFE(read_string(&creator, f)); + SAFE(read_int32(&time, f)); + addHostCore(nick, NULL, vHost, creator, time); /* could get a speed increase by not searching the list */ + free(nick); /* as we know the db is in alphabetical order... */ + free(vHost); + free(creator); + } else { + fatal("Invalid format in %s %d", HostDBName, c); + } + } +} + +void load_hs_dbase_v3(dbFILE * f) +{ + int c; + int failed = 0; + + char *nick; + char *vHost; + char *creator; + char *vIdent; + uint32 time; + + while (!failed && (c = getc_db(f)) == 1) { + if (c == 1) { + SAFE(read_string(&nick, f)); + SAFE(read_string(&vIdent, f)); + SAFE(read_string(&vHost, f)); + SAFE(read_string(&creator, f)); + SAFE(read_int32(&time, f)); + addHostCore(nick, vIdent, vHost, creator, time); /* could get a speed increase by not searching the list */ + free(nick); /* as we know the db is in alphabetical order... */ + free(vHost); + free(creator); + free(vIdent); + } else { + fatal("Invalid format in %s %d", HostDBName, c); + } + } +} + +#undef SAFE +/*************************************************************************/ +#define SAFE(x) do { \ + if ((x) < 0) { \ + restore_db(f); \ + log_perror("Write error on %s", HostDBName); \ + if (time(NULL) - lastwarn > WarningTimeout) { \ + anope_cmd_global(NULL, "Write error on %s: %s", HostDBName, \ + strerror(errno)); \ + lastwarn = time(NULL); \ + } \ + return; \ + } \ +} while (0) + +void save_hs_dbase(void) +{ + dbFILE *f; + static time_t lastwarn = 0; + HostCore *current; + + if (!(f = open_db(s_HostServ, HostDBName, "w", HOST_VERSION))) + return; + + current = head; + while (current != NULL) { + SAFE(write_int8(1, f)); + SAFE(write_string(current->nick, f)); + SAFE(write_string(current->vIdent, f)); + SAFE(write_string(current->vHost, f)); + SAFE(write_string(current->creator, f)); + SAFE(write_int32(current->time, f)); + current = current->next; + } + SAFE(write_int8(0, f)); + close_db(f); + +} + +#undef SAFE + +void save_hs_rdb_dbase(void) +{ +#ifdef USE_RDB + HostCore *current; + + if (!rdb_open()) + return; + + if (rdb_tag_table("anope_hs_core") == 0) { + alog("Unable to tag table 'anope_hs_core' - HostServ RDB save failed."); + rdb_close(); + return; + } + + current = head; + while (current != NULL) { + if (rdb_save_hs_core(current) == 0) { + alog("Unable to save HostCore for %s - HostServ RDB save failed.", current->nick); + rdb_close(); + return; + } + current = current->next; + } + + if (rdb_clean_table("anope_hs_core") == 0) + alog("Unable to clean table 'anope_hs_core' - HostServ RDB save failed."); + + rdb_close(); +#endif +} + +/*************************************************************************/ +/* End of Load/Save Functions */ +/*************************************************************************/ +/*************************************************************************/ +/* Start of Generic Functions */ +/*************************************************************************/ + +int do_hs_sync(NickCore * nc, char *vIdent, char *hostmask, char *creator, + time_t time) +{ + int i; + NickAlias *na; + + for (i = 0; i < nc->aliases.count; i++) { + na = nc->aliases.list[i]; + addHostCore(na->nick, vIdent, hostmask, creator, time); + } + return MOD_CONT; +} + +/*************************************************************************/ +int do_on_id(User * u) +{ /* we've assumed that the user exists etc.. */ + char *vHost; /* as were only gonna call this from nsid routine */ + char *vIdent; + vHost = getvHost(u->nick); + vIdent = getvIdent(u->nick); + if (vHost != NULL) { + if (vIdent) { + notice_lang(s_HostServ, u, HOST_IDENT_ACTIVATED, vIdent, + vHost); + } else { + notice_lang(s_HostServ, u, HOST_ACTIVATED, vHost); + } + anope_cmd_vhost_on(u->nick, vIdent, vHost); + if (ircd->vhost) { + u->vhost = sstrdup(vHost); + } + if (ircd->vident) { + if (vIdent) + u->vident = sstrdup(vIdent); + } + set_lastmask(u); + } + return MOD_CONT; +} + +/*************************************************************************/ +int is_host_setter(User * u) +{ + int i, j; + NickAlias *na; + + if (is_services_oper(u)) { + return 1; + } + if (!nick_identified(u)) { + return 0; + } + + /* Look through all user's aliases (0000412) */ + for (i = 0; i < u->na->nc->aliases.count; i++) { + na = u->na->nc->aliases.list[i]; + for (j = 0; j < HostNumber; j++) { + if (stricmp(HostSetters[j], na->nick) == 0) { + return 1; + } + } + } + + return 0; +} + +int is_host_remover(User * u) +{ + return is_host_setter(u); /* only here incase we want to split them up later */ +} + +/* + * Sets the last_usermak properly. Using virtual ident and/or host + */ +void set_lastmask(User * u) +{ + if (u->na->last_usermask) + free(u->na->last_usermask); + + u->na->last_usermask = + smalloc(strlen(common_get_vident(u)) + + strlen(common_get_vhost(u)) + 2); + sprintf(u->na->last_usermask, "%s@%s", common_get_vident(u), + common_get_vhost(u)); + +} |