hostserv.c

Go to the documentation of this file.
00001 /* HostServ functions
00002  *
00003  * (C) 2003-2013 Anope Team
00004  * Contact us at team@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church. 
00010  * 
00011  *
00012  */
00013 
00014 /*************************************************************************/
00015 #include "services.h"
00016 #include "pseudo.h"
00017 
00018 #define HASH(nick)      ((tolower((nick)[0])&31)<<5 | (tolower((nick)[1])&31))
00019 
00020 void load_hs_dbase_v1(dbFILE * f);
00021 void load_hs_dbase_v2(dbFILE * f);
00022 void load_hs_dbase_v3(dbFILE * f);
00023 
00024 HostCore *head = NULL;          /* head of the HostCore list */
00025 
00026 E int do_hs_sync(NickCore * nc, char *vIdent, char *hostmask,
00027                  char *creator, time_t time);
00028 
00029 E void moduleAddHostServCmds(void);
00030 
00031 /*************************************************************************/
00032 
00033 void moduleAddHostServCmds(void)
00034 {
00035     modules_core_init(HostServCoreNumber, HostServCoreModules);
00036 }
00037 
00038 /*************************************************************************/
00039 
00045 void get_hostserv_stats(long *nrec, long *memuse)
00046 {
00047     long count = 0, mem = 0;
00048     HostCore *hc;
00049 
00050     for (hc = head; hc; hc = hc->next) {
00051         count++;
00052         mem += sizeof(*hc);
00053         if (hc->nick)
00054             mem += strlen(hc->nick) + 1;
00055         if (hc->vIdent)
00056             mem += strlen(hc->vIdent) + 1;
00057         if (hc->vHost)
00058             mem += strlen(hc->vHost) + 1;
00059         if (hc->creator)
00060             mem += strlen(hc->creator) + 1;
00061     }
00062 
00063     *nrec = count;
00064     *memuse = mem;
00065 }
00066 
00067 /*************************************************************************/
00068 
00073 void hostserv_init(void)
00074 {
00075     if (s_HostServ) {
00076         moduleAddHostServCmds();
00077     }
00078 }
00079 
00080 /*************************************************************************/
00081 
00088 void hostserv(User * u, char *buf)
00089 {
00090     char *cmd, *s;
00091 
00092     cmd = strtok(buf, " ");
00093 
00094     if (!cmd) {
00095         return;
00096     } else if (stricmp(cmd, "\1PING") == 0) {
00097         if (!(s = strtok(NULL, ""))) {
00098             s = "";
00099         }
00100         anope_cmd_ctcp(s_HostServ, u->nick, "PING %s", s);
00101     } else if (skeleton) {
00102         notice_lang(s_HostServ, u, SERVICE_OFFLINE, s_HostServ);
00103     } else {
00104         if (ircd->vhost) {
00105             mod_run_cmd(s_HostServ, u, HOSTSERV, cmd);
00106         } else {
00107             notice_lang(s_HostServ, u, SERVICE_OFFLINE, s_HostServ);
00108         }
00109     }
00110 }
00111 
00112 /*************************************************************************/
00113 /*      Start of Linked List routines                                                        */
00114 /*************************************************************************/
00115 
00116 HostCore *hostCoreListHead()
00117 {
00118     return head;
00119 }
00120 
00131 HostCore *createHostCorelist(HostCore * next, char *nick, char *vIdent,
00132                              char *vHost, char *creator, int32 tmp_time)
00133 {
00134 
00135     next = malloc(sizeof(HostCore));
00136     if (next == NULL) {
00137         anope_cmd_global(s_HostServ,
00138                          "Unable to allocate memory to create the vHost LL, problems i sense..");
00139     } else {
00140         next->nick = malloc(sizeof(char) * strlen(nick) + 1);
00141         next->vHost = malloc(sizeof(char) * strlen(vHost) + 1);
00142         next->creator = malloc(sizeof(char) * strlen(creator) + 1);
00143         if (vIdent)
00144             next->vIdent = malloc(sizeof(char) * strlen(vIdent) + 1);
00145         if ((next->nick == NULL) || (next->vHost == NULL)
00146             || (next->creator == NULL)) {
00147             anope_cmd_global(s_HostServ,
00148                              "Unable to allocate memory to create the vHost LL, problems i sense..");
00149             return NULL;
00150         }
00151         strcpy(next->nick, nick);
00152         strcpy(next->vHost, vHost);
00153         strcpy(next->creator, creator);
00154         if (vIdent) {
00155             if ((next->vIdent == NULL)) {
00156                 anope_cmd_global(s_HostServ,
00157                                  "Unable to allocate memory to create the vHost LL, problems i sense..");
00158                 return NULL;
00159             }
00160             strcpy(next->vIdent, vIdent);
00161         } else {
00162             next->vIdent = NULL;
00163         }
00164         next->time = tmp_time;
00165         next->next = NULL;
00166         return next;
00167     }
00168     return NULL;
00169 }
00170 
00171 /*************************************************************************/
00180 HostCore *findHostCore(HostCore * head, char *nick, boolean * found)
00181 {
00182     HostCore *previous, *current;
00183 
00184     *found = false;
00185     current = head;
00186     previous = current;
00187 
00188     if (!nick) {
00189         return NULL;
00190     }
00191 
00192     while (current != NULL) {
00193         if (stricmp(nick, current->nick) == 0) {
00194             *found = true;
00195             break;
00196         } else if (stricmp(nick, current->nick) < 0) {
00197             /* we know were not gonna find it now.... */
00198             break;
00199         } else {
00200             previous = current;
00201             current = current->next;
00202         }
00203     }
00204     if (current == head) {
00205         return NULL;
00206     } else {
00207         return previous;
00208     }
00209 }
00210 
00211 /*************************************************************************/
00212 HostCore *insertHostCore(HostCore * head, HostCore * prev, char *nick,
00213                          char *vIdent, char *vHost, char *creator,
00214                          int32 tmp_time)
00215 {
00216 
00217     HostCore *newCore, *tmp;
00218 
00219     if (!nick || !vHost || !creator) {
00220         return NULL;
00221     }
00222 
00223     newCore = malloc(sizeof(HostCore));
00224     if (newCore == NULL) {
00225         anope_cmd_global(s_HostServ,
00226                          "Unable to allocate memory to insert into the vHost LL, problems i sense..");
00227         return NULL;
00228     } else {
00229         newCore->nick = malloc(sizeof(char) * strlen(nick) + 1);
00230         newCore->vHost = malloc(sizeof(char) * strlen(vHost) + 1);
00231         newCore->creator = malloc(sizeof(char) * strlen(creator) + 1);
00232         if (vIdent)
00233             newCore->vIdent = malloc(sizeof(char) * strlen(vIdent) + 1);
00234         if ((newCore->nick == NULL) || (newCore->vHost == NULL)
00235             || (newCore->creator == NULL)) {
00236             anope_cmd_global(s_HostServ,
00237                              "Unable to allocate memory to create the vHost LL, problems i sense..");
00238             return NULL;
00239         }
00240         strcpy(newCore->nick, nick);
00241         strcpy(newCore->vHost, vHost);
00242         strcpy(newCore->creator, creator);
00243         if (vIdent) {
00244             if ((newCore->vIdent == NULL)) {
00245                 anope_cmd_global(s_HostServ,
00246                                  "Unable to allocate memory to create the vHost LL, problems i sense..");
00247                 return NULL;
00248             }
00249             strcpy(newCore->vIdent, vIdent);
00250         } else {
00251             newCore->vIdent = NULL;
00252         }
00253         newCore->time = tmp_time;
00254         if (prev == NULL) {
00255             tmp = head;
00256             head = newCore;
00257             newCore->next = tmp;
00258         } else {
00259             tmp = prev->next;
00260             prev->next = newCore;
00261             newCore->next = tmp;
00262         }
00263     }
00264     return head;
00265 }
00266 
00267 /*************************************************************************/
00268 HostCore *deleteHostCore(HostCore * head, HostCore * prev)
00269 {
00270 
00271     HostCore *tmp;
00272 
00273     if (prev == NULL) {
00274         tmp = head;
00275         head = head->next;
00276     } else {
00277         tmp = prev->next;
00278         prev->next = tmp->next;
00279     }
00280     free(tmp->vHost);
00281     free(tmp->nick);
00282     free(tmp->creator);
00283     if (tmp->vIdent) {
00284         free(tmp->vIdent);
00285     }
00286     free(tmp);
00287     return head;
00288 }
00289 
00290 /*************************************************************************/
00291 void addHostCore(char *nick, char *vIdent, char *vhost, char *creator,
00292                  int32 tmp_time)
00293 {
00294     HostCore *tmp;
00295     boolean found = false;
00296 
00297     if (head == NULL) {
00298         head =
00299             createHostCorelist(head, nick, vIdent, vhost, creator,
00300                                tmp_time);
00301     } else {
00302         tmp = findHostCore(head, nick, &found);
00303         if (!found) {
00304             head =
00305                 insertHostCore(head, tmp, nick, vIdent, vhost, creator,
00306                                tmp_time);
00307         } else {
00308             head = deleteHostCore(head, tmp);   /* delete the old entry */
00309             addHostCore(nick, vIdent, vhost, creator, tmp_time);        /* recursive call to add new entry */
00310         }
00311     }
00312 }
00313 
00314 /*************************************************************************/
00315 char *getvHost(char *nick)
00316 {
00317     HostCore *tmp;
00318     boolean found = false;
00319     tmp = findHostCore(head, nick, &found);
00320     if (found) {
00321         if (tmp == NULL)
00322             return head->vHost;
00323         else
00324             return tmp->next->vHost;
00325     }
00326     return NULL;
00327 }
00328 
00329 /*************************************************************************/
00330 char *getvIdent(char *nick)
00331 {
00332     HostCore *tmp;
00333     boolean found = false;
00334     tmp = findHostCore(head, nick, &found);
00335     if (found) {
00336         if (tmp == NULL)
00337             return head->vIdent;
00338         else
00339             return tmp->next->vIdent;
00340     }
00341     return NULL;
00342 }
00343 
00344 /*************************************************************************/
00345 void delHostCore(char *nick)
00346 {
00347 #ifdef USE_RDB
00348     static char clause[128];
00349     char *q_nick;
00350 #endif
00351     HostCore *tmp;
00352     boolean found = false;
00353     tmp = findHostCore(head, nick, &found);
00354     if (found) {
00355         head = deleteHostCore(head, tmp);
00356 
00357 #ifdef USE_RDB
00358         /* Reflect this change in the database right away. */
00359         if (rdb_open()) {
00360             q_nick = rdb_quote(nick);
00361             snprintf(clause, sizeof(clause), "nick='%s'", q_nick);
00362             if (rdb_scrub_table("anope_hs_core", clause) == 0)
00363                 alog("Unable to scrub table 'anope_hs_core' - HostServ RDB update failed.");
00364             rdb_close();
00365             free(q_nick);
00366         }
00367 #endif
00368 
00369     }
00370 
00371 }
00372 
00373 /*************************************************************************/
00374 /*      End of Linked List routines                                      */
00375 /*************************************************************************/
00376 /*************************************************************************/
00377 /*      Start of Load/Save routines                                      */
00378 /*************************************************************************/
00379 #define SAFE(x) do {                                    \
00380     if ((x) < 0) {                                      \
00381         if (!forceload)                                 \
00382             fatal("Read error on %s", HostDBName);      \
00383         failed = 1;                                     \
00384         break;                                          \
00385     }                                                   \
00386 } while (0)
00387 
00388 void load_hs_dbase(void)
00389 {
00390     dbFILE *f;
00391     int ver;
00392 
00393     if (!(f = open_db(s_HostServ, HostDBName, "r", HOST_VERSION))) {
00394         return;
00395     }
00396     ver = get_file_version(f);
00397 
00398     if (ver == 1) {
00399         load_hs_dbase_v1(f);
00400     } else if (ver == 2) {
00401         load_hs_dbase_v2(f);
00402     } else if (ver == 3) {
00403         load_hs_dbase_v3(f);
00404     }
00405     close_db(f);
00406 }
00407 
00408 void load_hs_dbase_v1(dbFILE * f)
00409 {
00410     int c;
00411     int failed = 0;
00412     int32 tmp;
00413 
00414     char *nick;
00415     char *vHost;
00416 
00417     tmp = time(NULL);
00418 
00419     while (!failed && (c = getc_db(f)) == 1) {
00420 
00421         if (c == 1) {
00422             SAFE(read_string(&nick, f));
00423             SAFE(read_string(&vHost, f));
00424             addHostCore(nick, NULL, vHost, "Unknown", tmp);     /* could get a speed increase by not searching the list */
00425             free(nick);         /* as we know the db is in alphabetical order... */
00426             free(vHost);
00427         } else {
00428             fatal("Invalid format in %s %d", HostDBName, c);
00429         }
00430     }
00431 }
00432 
00433 void load_hs_dbase_v2(dbFILE * f)
00434 {
00435     int c;
00436     int failed = 0;
00437 
00438     char *nick;
00439     char *vHost;
00440     char *creator;
00441     uint32 time;
00442 
00443     while (!failed && (c = getc_db(f)) == 1) {
00444 
00445         if (c == 1) {
00446             SAFE(read_string(&nick, f));
00447             SAFE(read_string(&vHost, f));
00448             SAFE(read_string(&creator, f));
00449             SAFE(read_int32(&time, f));
00450             addHostCore(nick, NULL, vHost, creator, time);      /* could get a speed increase by not searching the list */
00451             free(nick);         /* as we know the db is in alphabetical order... */
00452             free(vHost);
00453             free(creator);
00454         } else {
00455             fatal("Invalid format in %s %d", HostDBName, c);
00456         }
00457     }
00458 }
00459 
00460 void load_hs_dbase_v3(dbFILE * f)
00461 {
00462     int c;
00463     int failed = 0;
00464 
00465     char *nick;
00466     char *vHost;
00467     char *creator;
00468     char *vIdent;
00469     uint32 time;
00470 
00471     while (!failed && (c = getc_db(f)) == 1) {
00472         if (c == 1) {
00473             SAFE(read_string(&nick, f));
00474             SAFE(read_string(&vIdent, f));
00475             SAFE(read_string(&vHost, f));
00476             SAFE(read_string(&creator, f));
00477             SAFE(read_int32(&time, f));
00478             addHostCore(nick, vIdent, vHost, creator, time);    /* could get a speed increase by not searching the list */
00479             free(nick);         /* as we know the db is in alphabetical order... */
00480             free(vHost);
00481             free(creator);
00482             free(vIdent);
00483         } else {
00484             fatal("Invalid format in %s %d", HostDBName, c);
00485         }
00486     }
00487 }
00488 
00489 #undef SAFE
00490 /*************************************************************************/
00491 #define SAFE(x) do {                                            \
00492     if ((x) < 0) {                                              \
00493         restore_db(f);                                          \
00494         log_perror("Write error on %s", HostDBName);            \
00495         if (time(NULL) - lastwarn > WarningTimeout) {           \
00496             anope_cmd_global(NULL, "Write error on %s: %s", HostDBName, \
00497                         strerror(errno));                       \
00498             lastwarn = time(NULL);                              \
00499         }                                                       \
00500         return;                                                 \
00501     }                                                           \
00502 } while (0)
00503 
00504 void save_hs_dbase(void)
00505 {
00506     dbFILE *f;
00507     static time_t lastwarn = 0;
00508     HostCore *current;
00509 
00510     if (!(f = open_db(s_HostServ, HostDBName, "w", HOST_VERSION)))
00511         return;
00512 
00513     current = head;
00514     while (current != NULL) {
00515         SAFE(write_int8(1, f));
00516         SAFE(write_string(current->nick, f));
00517         SAFE(write_string(current->vIdent, f));
00518         SAFE(write_string(current->vHost, f));
00519         SAFE(write_string(current->creator, f));
00520         SAFE(write_int32(current->time, f));
00521         current = current->next;
00522     }
00523     SAFE(write_int8(0, f));
00524     close_db(f);
00525 
00526 }
00527 
00528 #undef SAFE
00529 
00530 void save_hs_rdb_dbase(void)
00531 {
00532 #ifdef USE_RDB
00533     HostCore *current;
00534 
00535     if (!rdb_open())
00536         return;
00537 
00538     if (rdb_tag_table("anope_hs_core") == 0) {
00539         alog("Unable to tag table 'anope_hs_core' - HostServ RDB save failed.");
00540         rdb_close();
00541         return;
00542     }
00543 
00544     current = head;
00545     while (current != NULL) {
00546         if (rdb_save_hs_core(current) == 0) {
00547             alog("Unable to save HostCore for %s - HostServ RDB save failed.", current->nick);
00548             rdb_close();
00549             return;
00550         }
00551         current = current->next;
00552     }
00553 
00554     if (rdb_clean_table("anope_hs_core") == 0)
00555         alog("Unable to clean table 'anope_hs_core' - HostServ RDB save failed.");
00556 
00557     rdb_close();
00558 #endif
00559 }
00560 
00561 /*************************************************************************/
00562 /*      End of Load/Save Functions                                       */
00563 /*************************************************************************/
00564 /*************************************************************************/
00565 /*      Start of Generic Functions                                       */
00566 /*************************************************************************/
00567 
00568 int do_hs_sync(NickCore * nc, char *vIdent, char *hostmask, char *creator,
00569                time_t time)
00570 {
00571     int i;
00572     NickAlias *na;
00573 
00574     for (i = 0; i < nc->aliases.count; i++) {
00575         na = nc->aliases.list[i];
00576         addHostCore(na->nick, vIdent, hostmask, creator, time);
00577     }
00578     return MOD_CONT;
00579 }
00580 
00581 /*************************************************************************/
00582 int do_on_id(User * u)
00583 {                               /* we've assumed that the user exists etc.. */
00584     char *vHost;                /* as were only gonna call this from nsid routine */
00585     char *vIdent;
00586     vHost = getvHost(u->nick);
00587     vIdent = getvIdent(u->nick);
00588     if (vHost != NULL) {
00589         if (vIdent) {
00590             notice_lang(s_HostServ, u, HOST_IDENT_ACTIVATED, vIdent,
00591                         vHost);
00592         } else {
00593             notice_lang(s_HostServ, u, HOST_ACTIVATED, vHost);
00594         }
00595         anope_cmd_vhost_on(u->nick, vIdent, vHost);
00596         if (ircd->vhost) {
00597             if (u->vhost)
00598                 free(u->vhost);
00599             u->vhost = sstrdup(vHost);
00600         }
00601         if (ircd->vident) {
00602             if (vIdent) {
00603                 if (u->vident)
00604                     free(u->vident);
00605                 u->vident = sstrdup(vIdent);
00606             }
00607         }
00608         set_lastmask(u);
00609     }
00610     return MOD_CONT;
00611 }
00612 
00613 /*************************************************************************/
00614 int is_host_setter(User * u)
00615 {
00616     int i, j;
00617     NickAlias *na;
00618 
00619     if (is_services_oper(u)) {
00620         return 1;
00621     }
00622     if (!nick_identified(u)) {
00623         return 0;
00624     }
00625 
00626     /* Look through all user's aliases (0000412) */
00627     for (i = 0; i < u->na->nc->aliases.count; i++) {
00628         na = u->na->nc->aliases.list[i];
00629         for (j = 0; j < HostNumber; j++) {
00630             if (stricmp(HostSetters[j], na->nick) == 0) {
00631                 return 1;
00632             }
00633         }
00634     }
00635 
00636     return 0;
00637 }
00638 
00639 int is_host_remover(User * u)
00640 {
00641     return is_host_setter(u);   /* only here incase we want to split them up later */
00642 }
00643 
00644 /*
00645  * Sets the last_usermak properly. Using virtual ident and/or host 
00646  */
00647 void set_lastmask(User * u)
00648 {
00649     if (u->na->last_usermask)
00650         free(u->na->last_usermask);
00651 
00652     u->na->last_usermask =
00653         smalloc(strlen(common_get_vident(u)) +
00654                 strlen(common_get_vhost(u)) + 2);
00655     sprintf(u->na->last_usermask, "%s@%s", common_get_vident(u),
00656             common_get_vhost(u));
00657 
00658 }