/* Main processing code for Services. * Auspice Services is copyright (c) 2000-2001 In Mean. * E-mail: * * SirvNET Services is copyright (c) 1998-2000 Trevor Klingbeil. * E-mail: * Originally based on EsperNet Services(c) by Andy Church. * This program is free but copyrighted software; see the file LICENSE for * details. */ #include "../inc/services.h" #include "version.h" char **textinfo2 = giveinfo; char **textcred = givecredit; void m_info(char *source, int ac, char **av); void m_credits(char *source, int ac, char **av); void m_realcredits(const char *source); void m_realinfo(const char *source); /*************************************************************************/ /* Response to the VERSION message. */ void m_version(char *source, int ac, char **av) { User *u = finduser(source); int isn = nofork + debug; char buf2[512]; send_cmd(server_name, "351 %s Running Auspice%s%s. %s :%s%s%s %s [%s]", source, version_number, version_dec, server_name, debug?"D":"", nofork?"N":"", isn?"":"Normal", version_build, IRCD); strscpy(buf2, "", sizeof(buf2)); #ifdef DEFHALFOP strcat(buf2, "HALFOP"); #endif #ifdef DEFPROTECT strcat(buf2, " PROTECT"); #endif #ifdef DEFHOSTSERV strcat(buf2, " HOSTSERV"); #endif #ifdef SVSJOIN strcat(buf2, " SVSJOIN="); strcat(buf2, SVSJOIN); #endif #ifdef ALLOWUMODE strcat(buf2, " UMODE="); strcat(buf2, ALLOWUMODE); #endif #ifdef BOTMODE strcat(buf2, " BOTMODE="); strcat(buf2, BOTMODE); #endif #ifdef ALLOW_GLINE strcat(buf2, " GLINE"); #endif #ifdef CYGWIN strcat(buf2, " WIN32"); #endif send_cmd(server_name, "351 %s %s \2Using\2: %s ", source, server_name, buf2); if (u) do_update_flood(u, 1); } /*************************************************************************/ void m_sendmotd(const char *source) { int tmpnow; tmpnow = time(NULL) - start_time; send_cmd (server_name, "372 %s :***** \2\37Services Info\37\2 *****",source); send_cmd (server_name, "372 %s :Welcome to %s IRC Network", source, NETWORK_NAME); send_cmd (server_name, "372 %s :%s Running Auspice%s\2(%s)\2 %s",source, server_name, version_number, version_dec, version_build); send_cmd (server_name, "372 %s :Services On-Line %d day%s, %d:%02d:%02d ", source, tmpnow/86400, (tmpnow/86400 == 1) ? "" : "s", (tmpnow/3600)%24, (tmpnow/60)%60, tmpnow%60); send_cmd (server_name, "372 %s :Default Services help channel is: \2%s\2", source, tokn[17]); send_cmd (server_name, "372 %s :Type \2/MOTD %s\2 for Password Admin.", source, server_name); send_cmd (server_name, "372 %s :Type \2/Msg HelpServ CREDITS\2 for Credits peoples", source); send_cmd (server_name, "372 %s :***** \2End Services Info\2 *****", source); } /*************************************************************************/ void m_smartinfo(const char *source) { int tmpnow; long count, mem; tmpnow = time(NULL) - start_time; notice(s_Agent, source, "***** \2Services Report\2 *****"); notice(s_Agent, source, "==============="); notice(s_Agent, source, "Services Version: Auspice%s%s", version_number, version_dec); notice(s_Agent, source, "Services On-Line: %d day%s, %d:%02d:%02d", tmpnow/86400, (tmpnow/86400 == 1) ? "" : "s", (tmpnow/3600)%24, (tmpnow/60)%60, tmpnow%60); notice(s_Agent, source, "Current User : %d (%d ops); maximum %d", usercnt, opcnt, maxusercnt); notice(s_Agent, source, "Channels : %d", channel_form()); get_nickserv_stats(&count, &mem); notice(s_Agent, source, "Registered Nicks: %d", count); get_chanserv_stats(&count, &mem); notice(s_Agent, source, "Registered Chans: %d", count); notice(s_Agent, source, "Total Connect in: %li", connectscnt); notice(s_Agent, source, "Total akill mask: %d", nakill); notice(s_Agent, source, "There are \2%d\2 servers linked.", numserver); notice(s_Agent, source, "***** \2End Report\2 *****"); } /*************************************************************************/ void make_netstats_html(void) { FILE *fp; int tmpnow; long count, mem, count2, mem2; tmpnow = time(NULL) - start_time; if (ishtml == 0) return; fp = fopen(netstats_path, "w"); if (fp) { get_nickserv_stats(&count, &mem); get_chanserv_stats(&count2, &mem2); fprintf (fp, "

Network Statistic

\n"); fprintf (fp, "

Services Version: Auspice%s%s
", version_number,version_dec); fprintf (fp, "Services On-Line: %d day%s, %d:%02d:%02d
", tmpnow/86400, (tmpnow/86400 == 1) ? "" : "s", (tmpnow/3600)%24, (tmpnow/60)%60, tmpnow%60); fprintf (fp, "Current User : %d (%d ops); maximum %d
", usercnt, opcnt, maxusercnt); fprintf (fp, "There are %d channels form
", channel_form()); fprintf (fp, "Total Connect in: %li
", connectscnt); fprintf (fp, "There are %d servers linked.

", numserver); fprintf (fp, "

Registered Nicks: %lu
", count); fprintf (fp, "Registered Chans: %lu
", count2); fclose (fp); } } /*************************************************************************/ /* Response Admin message */ void m_admin(char *source, int ac, char **av) { if (source) { send_cmd(server_name, "256 %s :Administrative info about %s", source, server_name); send_cmd(server_name, "257 %s :Admin Name: %s", source, tokn[27]); send_cmd(server_name, "258 %s :Admin Nick: %s", source, SERVICES_MASTER); send_cmd(server_name, "259 %s :Admin Email: %s", source, tokn[28]); } } /*************************************************************************/ void m_info(char *source, int ac, char **av) { m_realinfo(source); } /*************************************************************************/ void m_realinfo(const char *source) { struct tm tm; char timebuf[64]; char **textinfo = textinfo2; tm = *localtime(&start_time); strftime(timebuf, sizeof(timebuf), "%b %d %Y at %H:%M:%S %Z", &tm); timebuf[sizeof(timebuf)-1] = 0; send_cmd (server_name, "373 %s :Auspice IRC Services %s%s", source, version_number, version_dec); while (*textinfo) { send_cmd (server_name, "371 %s :%s", source, *textinfo++); } send_cmd (server_name, "371 %s :Auspice services %s", source, version_number); send_cmd (server_name, "371 %s :Birth Date: %s, compile # %s", source, timebuf, version_build); send_cmd (server_name, "371 %s :On-line since %s", source, ctime (&start_time)); send_cmd (server_name, "374 %s :End of /INFO list.", source); } /*************************************************************************/ void m_realcredits(const char *source) { struct tm tm; char timebuf[64]; char **text = textcred; tm = *localtime(&start_time); strftime(timebuf, sizeof(timebuf), "%b %d %Y at %H:%M:%S %Z", &tm); timebuf[sizeof(timebuf)-1] = 0; while (*text) { send_cmd (server_name, "371 %s :%s", source, *text++); } send_cmd (server_name, "371 %s :Auspice services %s%s", source, version_number, version_dec); send_cmd (server_name, "371 %s :Birth Date: %s, compile # %s", source, timebuf, version_build); send_cmd (server_name, "371 %s :On-line since %s", source, ctime (&start_time)); send_cmd (server_name, "374 %s :End of /CREDITS list.", source); } /*************************************************************************/ void m_credits(char *source, int ac, char **av) { m_realcredits(source); } /***********************************************************************/ void do_version(const char *source) { notice(s_OperServ, source, "Version: %s%s", version_number, version_dec); notice(s_OperServ, source, "Build: %s", version_build); notice(s_OperServ, source, "DataBase Version: \2%d\2", FILE_VERSION); notice(s_OperServ, source, "Coder(s): \2Auspice\2"); notice(s_OperServ, source, "Auspice Services copyright (c) 2000-2002 In Mean."); notice(s_OperServ, source, "\2END OF VERSION\2"); } /***********************************************************************/ /* Channel to suspend (hashed by first character of chan). */ C_SuspendData *c_suspend[256]; /*************************************************************************/ /* Updates flood levels of a user. If exceeds max, warn, if continues, kill user */ int do_update_flood(User *u, unsigned short idflood) { time_t now = CTime; if (u->flood_time < now) { u->flood_time = now + F_RESET; u->floodlev = 0; } else if (u->flood_time > now) { u->flood_time = now + F_RESET; u->floodlev += 1; } if (idflood == 2) u->motd += 1; else if (idflood == 1) u->version += 1; if ((u->motd == 30) || (u->version == 30) || (u->motd == 50) || (u->version == 50)) { wallops(SERVER_NAME, "WARNING: User %s!%s@%s has been found " "sending atleast %d %s requests to services", u->nick, u->username, u->host, u->motd == 30 ? u->motd : u->version, u->motd == 30 ? "MOTD" : "VERSION"); notice(s_GlobalNoticer, u->nick, "You have been constantly flooding services with %s " "requests. Please stop immediately.", u->motd == 30 ? "MOTD" : "VERSION"); notice(s_GlobalNoticer, u->nick, "You have been constantly flooding services with %s " "requests. Please stop immediately.", u->motd == 30 ? "MOTD" : "VERSION"); } if ((u->floodlev == 5) && (u->floodlev2 == 3)) { u->floodlev2 = 4; if (is_oper(u->nick)) { wallops(SERVER_NAME, "Oper %s has been SEVERELY flooding services", u->nick); } else { kill_user(s_OperServ, u->nick, "Stop flooding services"); return 1; } } else if ((u->floodlev == F_TLEV) && (u->floodlev2 == 2)) { u->floodlev2 = 3; u->floodlev = 1; notice(s_OperServ, u->nick, "You have been warned twice. STOP FLOODING SERVICES"); if (!is_oper(u->nick)) wallops(SERVER_NAME, "Services are being \2SEVERELY\2 flooded by %s!%s@%s", u->nick, u->username, u->host); } else if ((u->floodlev == F_TLEV) && (u->floodlev2 == 1)) { u->floodlev2 = 2; u->floodlev = 1; notice(s_OperServ, u->nick, "You are flooding services, please slow down"); if (!is_oper(u->nick)) wallops(SERVER_NAME, "Services are being flooded by %s!%s@%s", u->nick, u->username, u->host); } else if ((u->floodlev == 8) && (u->floodlev2 == 0)) { u->floodlev2 = 1; } return 0; } /*************************************************************************/ /* add_c_suspend: Add a channel to the suspend list for the next `delta' * seconds. */ void add_c_suspend(const char *wchan, time_t delta) { C_SuspendData *c_spn; char chan[CHANMAX]; time_t now = time(NULL); C_SuspendData **whichlist = &c_suspend[tolower(wchan[0])]; strscpy(chan, wchan, CHANMAX); for (c_spn = *whichlist; c_spn; c_spn = c_spn->next) { if (stricmp(c_spn->chan, chan) == 0) break; } if (c_spn) { if (c_spn->time > now) c_spn->time += delta; else c_spn->time = now + delta; } else { c_spn = smalloc(sizeof(*c_spn)); strcpy(c_spn->chan, chan); c_spn->time = now + delta; c_spn->next = *whichlist; *whichlist = c_spn; } } /*************************************************************************/ /* get_c_suspend: Retrieve a suspend record for a chan. If the chan isn't * being suspended, return NULL and flush the record from the * in-core list if it exists (i.e. suspend timed out). */ C_SuspendData *get_c_suspend(const char *chan) { C_SuspendData *c_spn, *prev; time_t now = time(NULL); C_SuspendData **whichlist = &c_suspend[tolower(chan[0])]; for (c_spn = *whichlist, prev = NULL; c_spn; prev = c_spn, c_spn = c_spn->next) { if (stricmp(c_spn->chan, chan) == 0) break; } if (c_spn && c_spn->time <= now) { if (prev) prev->next = c_spn->next; else *whichlist = c_spn->next; free(c_spn); c_spn = NULL; } return c_spn; } /*************************************************************************/ /* split_buf: Split a buffer into arguments and store the arguments in an * argument vector pointed to by argv (which will be malloc'd * as necessary); return the argument count. If colon_special * is non-zero, then treat a parameter with a leading ':' as * the last parameter of the line, per the IRC RFC. Destroys * the buffer by side effect. */ int split_buf(char *buf, char ***argv, int colon_special) { int argvsize = 8; int argc; char *s; *argv = smalloc(sizeof(char *) * argvsize); argc = 0; while (*buf) { if (argc == argvsize) { argvsize += 8; *argv = srealloc(*argv, sizeof(char *) * argvsize); } if (*buf == ':') { (*argv)[argc++] = buf+1; buf = ""; } else { s = strpbrk(buf, " "); if (s) { *s++ = 0; while (isspace(*s)) s++; } else { s = buf + strlen(buf); } (*argv)[argc++] = buf; buf = s; } } return argc; } /*************************************************************************/ /* process: Main processing routine. Takes the string in inbuf (global * variable) and does something appropriate with it. */ void process() { char source[64]; char cmd[64]; char buf[512]; /* Longest legal IRC command line */ char *s; int ac; /* Parameters for the command */ char **av; Message *m; /* If debugging, log the buffer. */ if (debug) log("debug: Received: %s", inbuf); /* First make a copy of the buffer so we have the original in case we * crash - in that case, we want to know what we crashed on. */ strscpy(buf, inbuf, sizeof(buf)); /* Split the buffer into pieces. */ if (*buf == ':') { s = strpbrk(buf, " "); if (!s) return; *s = 0; while (isspace(*++s)) ; strscpy(source, buf+1, sizeof(source)); strcpy(buf, s); } else { *source = 0; } if (!*buf) return; s = strpbrk(buf, " "); if (s) { *s = 0; while (isspace(*++s)) ; } else s = buf + strlen(buf); strscpy(cmd, buf, sizeof(cmd)); ac = split_buf(s, &av, 1); /* Do something with the message. */ m = find_message(cmd); if (m) { if (m->func) { m->func(source, ac, av); } } else { log("unknown message from server (%s)", inbuf); } /* Free argument list we created */ free(av); } /*************************************************************************/