X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fcommands.cpp;h=5db288ffaa4745f9109f2216e19ad09f1fe64c5f;hb=e66fefe4310264f8f11b5035b174fc8cb9287149;hp=c9bddbcd868bef702f2c8b902bcf45e62b38ee11;hpb=d7205720a51b0cb389ab43e80aa045576ed26b1e;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/commands.cpp b/src/commands.cpp index c9bddbcd8..5db288ffa 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -24,17 +24,6 @@ using namespace std; #include #include #include - -#ifdef USE_KQUEUE -#include -#include -#include -#endif - -#ifdef USE_EPOLL -#include -#endif - #include #include #include @@ -50,6 +39,9 @@ using namespace std; #include #include #include +#ifdef THREADED_DNS +#include +#endif #ifndef RUSAGE_SELF #define RUSAGE_SELF 0 #define RUSAGE_CHILDREN -1 @@ -61,88 +53,37 @@ using namespace std; #include "dynamic.h" #include "wildcard.h" #include "message.h" +#include "commands.h" #include "mode.h" #include "xline.h" #include "inspstring.h" #include "dnsqueue.h" #include "helperfuncs.h" #include "hashcomp.h" +#include "socketengine.h" +#include "typedefs.h" -#ifdef USE_KQUEUE -extern int kq; -#endif - -#ifdef USE_EPOLL -int ep; -#endif +extern SocketEngine* SE; +extern ServerConfig* Config; extern int MODCOUNT; extern std::vector modules; extern std::vector factory; - -extern int LogLevel; -extern char ServerName[MAXBUF]; -extern char Network[MAXBUF]; -extern char ServerDesc[MAXBUF]; -extern char AdminName[MAXBUF]; -extern char AdminEmail[MAXBUF]; -extern char AdminNick[MAXBUF]; -extern char diepass[MAXBUF]; -extern char restartpass[MAXBUF]; -extern char motd[MAXBUF]; -extern char rules[MAXBUF]; -extern char list[MAXBUF]; -extern char PrefixQuit[MAXBUF]; -extern char DieValue[MAXBUF]; - -extern int debugging; extern int WHOWAS_STALE; extern int WHOWAS_MAX; -extern int DieDelay; extern time_t startup_time; -extern int NetBufferSize; -extern int MaxWhoResults; -extern time_t nb_start; - -extern bool nofork; - extern time_t TIME; -extern std::vector module_names; - -extern char MyExecutable[1024]; -extern int boundPortCount; -extern int portCount; - -extern int ports[MAXSOCKS]; - -extern std::stringstream config_f; - - - -extern FILE *log_file; - -extern ClassVector Classes; - const long duration_m = 60; const long duration_h = duration_m * 60; const long duration_d = duration_h * 24; const long duration_w = duration_d * 7; const long duration_y = duration_w * 52; -typedef nspace::hash_map, irc::StrHashComp> user_hash; -typedef nspace::hash_map, irc::StrHashComp> chan_hash; -typedef nspace::hash_map, irc::InAddr_HashComp> address_cache; -typedef nspace::hash_map, irc::StrHashComp> whowas_hash; -typedef std::deque command_table; - - extern user_hash clientlist; extern chan_hash chanlist; extern whowas_hash whowas; extern command_table cmdlist; -extern file_cache MOTD; -extern file_cache RULES; extern address_cache IP; extern std::vector all_opers; @@ -152,7 +93,7 @@ extern std::vector all_opers; // by an integer, meaning there is no need for a scan/search operation. extern userrec* fd_ref_table[65536]; -extern int statsAccept,statsRefused,statsUnknown,statsCollisions,statsDns,statsDnsGood,statsDnsBad,statsConnects,statsSent,statsRecv; +extern serverstats* stats; void handle_join(char **parameters, int pcnt, userrec *user) { @@ -203,7 +144,7 @@ void handle_kick(char **parameters, int pcnt, userrec *user) return; } - if (!has_channel(user,Ptr)) + if ((!has_channel(user,Ptr)) && (!is_uline(user->server))) { WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, parameters[0]); return; @@ -258,10 +199,10 @@ void handle_unloadmodule(char **parameters, int pcnt, userrec *user) void handle_die(char **parameters, int pcnt, userrec *user) { log(DEBUG,"die: %s",user->nick); - if (!strcmp(parameters[0],diepass)) + if (!strcmp(parameters[0],Config->diepass)) { WriteOpers("*** DIE command from %s!%s@%s, terminating...",user->nick,user->ident,user->host); - sleep(DieDelay); + sleep(Config->DieDelay); Exit(ERROR); } else @@ -274,13 +215,13 @@ void handle_restart(char **parameters, int pcnt, userrec *user) { char *argv[32]; log(DEFAULT,"Restart: %s",user->nick); - if (!strcmp(parameters[0],restartpass)) + if (!strcmp(parameters[0],Config->restartpass)) { WriteOpers("*** RESTART command from %s!%s@%s, restarting server.",user->nick,user->ident,user->host); - argv[0] = MyExecutable; + argv[0] = Config->MyExecutable; argv[1] = "-wait"; - if (nofork) + if (Config->nofork) { argv[2] = "-nofork"; } @@ -300,7 +241,7 @@ void handle_restart(char **parameters, int pcnt, userrec *user) } sleep(2); - execv(MyExecutable,argv); + execv(Config->MyExecutable,argv); exit(0); } @@ -326,11 +267,11 @@ void handle_kill(char **parameters, int pcnt, userrec *user) return; } - if (strcmp(ServerName,u->server)) + if (u->fd < 0) { // remote kill WriteOpers("*** Remote kill by %s: %s!%s@%s (%s)",user->nick,u->nick,u->ident,u->host,parameters[1]); - snprintf(killreason,MAXBUF,"[%s] Killed (%s (%s))",ServerName,user->nick,parameters[1]); + snprintf(killreason,MAXBUF,"[%s] Killed (%s (%s))",Config->ServerName,user->nick,parameters[1]); WriteCommonExcept(u,"QUIT :%s",killreason); FOREACH_MOD OnRemoteKill(user,u,killreason); @@ -352,8 +293,8 @@ void handle_kill(char **parameters, int pcnt, userrec *user) else { // local kill - log(DEFAULT,"LOCAL KILL: %s :%s!%s!%s (%s)", u->nick, ServerName,user->dhost,user->nick,parameters[1]); - WriteTo(user, u, "KILL %s :%s!%s!%s (%s)", u->nick, ServerName,user->dhost,user->nick,parameters[1]); + log(DEFAULT,"LOCAL KILL: %s :%s!%s!%s (%s)", u->nick, Config->ServerName,user->dhost,user->nick,parameters[1]); + WriteTo(user, u, "KILL %s :%s!%s!%s (%s)", u->nick, Config->ServerName,user->dhost,user->nick,parameters[1]); WriteOpers("*** Local Kill by %s: %s!%s@%s (%s)",user->nick,u->nick,u->ident,u->host,parameters[1]); snprintf(killreason,MAXBUF,"Killed (%s (%s))",user->nick,parameters[1]); kill_link(u,killreason); @@ -472,7 +413,7 @@ void handle_topic(char **parameters, int pcnt, userrec *user) { if (((Ptr) && (!has_channel(user,Ptr))) && (Ptr->binarymodes & CM_SECRET)) { - WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, Ptr->name); + WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, Ptr->name); return; } if (Ptr->topicset) @@ -517,7 +458,7 @@ void handle_topic(char **parameters, int pcnt, userrec *user) topic[MAXTOPIC] = '\0'; } - if (!strcasecmp(user->server,ServerName)) + if (user->fd > -1) { int MOD_RESULT = 0; FOREACH_RESULT(OnLocalTopicChange(user,Ptr,topic)); @@ -525,13 +466,13 @@ void handle_topic(char **parameters, int pcnt, userrec *user) return; } - strlcpy(Ptr->topic,topic,MAXBUF); + strlcpy(Ptr->topic,topic,MAXTOPIC); strlcpy(Ptr->setby,user->nick,NICKMAX); Ptr->topicset = TIME; WriteChannel(Ptr,user,"TOPIC %s :%s",Ptr->name, Ptr->topic); - if (!strcasecmp(user->server,ServerName)) + if (user->fd > -1) { - FOREACH_MOD OnPostLocalTopicChange(user,Ptr,topic) + FOREACH_MOD OnPostLocalTopicChange(user,Ptr,topic); } } else @@ -559,7 +500,7 @@ void handle_names(char **parameters, int pcnt, userrec *user) { if (((c) && (!has_channel(user,c))) && (c->binarymodes & CM_SECRET)) { - WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, c->name); + WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, c->name); return; } userlist(user,c); @@ -580,7 +521,18 @@ void handle_privmsg(char **parameters, int pcnt, userrec *user) if (loop_call(handle_privmsg,parameters,pcnt,user,0,pcnt-2,0)) return; - if (parameters[0][0] == '#') + if (parameters[0][0] == '$') + { + // notice to server mask + char* servermask = parameters[0]; + servermask++; + if (match(Config->ServerName,servermask)) + { + ServerPrivmsgAll("%s",parameters[1]); + } + return; + } + else if (parameters[0][0] == '#') { chan = FindChan(parameters[0]); if (chan) @@ -621,12 +573,10 @@ void handle_privmsg(char **parameters, int pcnt, userrec *user) } return; } - - log(DEBUG,"*** PRIVMSG HANDLER"); + dest = Find(parameters[0]); if (dest) { - log(DEBUG,"*** FOUND NICK %s",dest->nick); if (strcmp(dest->awaymsg,"")) { /* auto respond with aweh msg */ @@ -642,10 +592,9 @@ void handle_privmsg(char **parameters, int pcnt, userrec *user) } parameters[1] = (char*)temp.c_str(); - if (!strcmp(dest->server,ServerName)) + if (dest->fd > -1) { // direct write, same server - log(DEBUG,"*** CALL WRITETO"); WriteTo(user, dest, "PRIVMSG %s :%s", dest->nick, parameters[1]); } @@ -667,7 +616,18 @@ void handle_notice(char **parameters, int pcnt, userrec *user) if (loop_call(handle_notice,parameters,pcnt,user,0,pcnt-2,0)) return; - if (parameters[0][0] == '#') + if (parameters[0][0] == '$') + { + // notice to server mask + char* servermask = parameters[0]; + servermask++; + if (match(Config->ServerName,servermask)) + { + NoticeAll(user, true, "%s",parameters[1]); + } + return; + } + else if (parameters[0][0] == '#') { chan = FindChan(parameters[0]); if (chan) @@ -722,7 +682,7 @@ void handle_notice(char **parameters, int pcnt, userrec *user) } parameters[1] = (char*)temp.c_str(); - if (!strcmp(dest->server,ServerName)) + if (dest->fd > -1) { // direct write, same server WriteTo(user, dest, "NOTICE %s :%s", dest->nick, parameters[1]); @@ -756,6 +716,7 @@ void handle_info(char **parameters, int pcnt, userrec *user) WriteServ(user->fd,"371 %s : Jazza",user->nick); WriteServ(user->fd,"371 %s : ",user->nick); WriteServ(user->fd,"371 %s :Testers: CC",user->nick); + WriteServ(user->fd,"371 %s : Om",user->nick); WriteServ(user->fd,"371 %s : Piggles",user->nick); WriteServ(user->fd,"371 %s : Foamy",user->nick); WriteServ(user->fd,"371 %s : Hart",user->nick); @@ -771,6 +732,7 @@ void handle_info(char **parameters, int pcnt, userrec *user) WriteServ(user->fd,"371 %s : Rob",user->nick); WriteServ(user->fd,"371 %s : angelic",user->nick); WriteServ(user->fd,"371 %s : Jason",user->nick); + WriteServ(user->fd,"371 %s : ThaPrince",user->nick); WriteServ(user->fd,"371 %s : ",user->nick); WriteServ(user->fd,"371 %s :Thanks to irc-junkie and searchirc",user->nick); WriteServ(user->fd,"371 %s :for the nice comments and the help",user->nick); @@ -787,64 +749,109 @@ void handle_time(char **parameters, int pcnt, userrec *user) time_t rawtime; struct tm * timeinfo; - time ( &rawtime ); - timeinfo = localtime ( &rawtime ); - WriteServ(user->fd,"391 %s %s :%s",user->nick,ServerName, asctime (timeinfo) ); + time(&rawtime); + timeinfo = localtime(&rawtime); + WriteServ(user->fd,"391 %s %s :%s",user->nick,Config->ServerName,asctime(timeinfo)); } void handle_whois(char **parameters, int pcnt, userrec *user) { userrec *dest; - - if (loop_call(handle_whois,parameters,pcnt,user,0,pcnt-1,0)) - return; + if (loop_call(handle_whois,parameters,pcnt,user,0,pcnt-1,0)) + return; dest = Find(parameters[0]); if (dest) { - // bug found by phidjit - were able to whois an incomplete connection if it had sent a NICK or USER - if (dest->registered == 7) + do_whois(user,dest,0,0,parameters[0]); + } + else + { + /* no such nick/channel */ + WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]); + WriteServ(user->fd,"318 %s %s :End of /WHOIS list.",user->nick, parameters[0]); + } +} + +void split_chlist(userrec* user, userrec* dest, std::string &cl) +{ + std::stringstream channels(cl); + std::string line = ""; + std::string cname = ""; + while (!channels.eof()) + { + channels >> cname; + line = line + cname + " "; + if (line.length() > 400) { - WriteServ(user->fd,"311 %s %s %s %s * :%s",user->nick, dest->nick, dest->ident, dest->dhost, dest->fullname); - if ((user == dest) || (strchr(user->modes,'o'))) + WriteServ(user->fd,"319 %s %s :%s",user->nick, dest->nick, line.c_str()); + line = ""; + } + } + if (line.length()) + { + WriteServ(user->fd,"319 %s %s :%s",user->nick, dest->nick, line.c_str()); + } +} + +void do_whois(userrec* user, userrec* dest,unsigned long signon, unsigned long idle, char* nick) +{ + // bug found by phidjit - were able to whois an incomplete connection if it had sent a NICK or USER + if (dest->registered == 7) + { + WriteServ(user->fd,"311 %s %s %s %s * :%s",user->nick, dest->nick, dest->ident, dest->dhost, dest->fullname); + if ((user == dest) || (strchr(user->modes,'o'))) + { + WriteServ(user->fd,"378 %s %s :is connecting from *@%s %s",user->nick, dest->nick, dest->host, dest->ip); + } + std::string cl = chlist(dest,user); + if (cl.length()) + { + if (cl.length() > 400) { - WriteServ(user->fd,"378 %s %s :is connecting from *@%s %s",user->nick, dest->nick, dest->host, dest->ip); + split_chlist(user,dest,cl); } - char* cl = chlist(dest,user); - if (strcmp(cl,"")) + else { - WriteServ(user->fd,"319 %s %s :%s",user->nick, dest->nick, cl); + WriteServ(user->fd,"319 %s %s :%s",user->nick, dest->nick, cl.c_str()); } - WriteServ(user->fd,"312 %s %s %s :%s",user->nick, dest->nick, dest->server, GetServerDescription(dest->server).c_str()); - if (strcmp(dest->awaymsg,"")) + } + WriteServ(user->fd,"312 %s %s %s :%s",user->nick, dest->nick, dest->server, GetServerDescription(dest->server).c_str()); + if (*dest->awaymsg) + { + WriteServ(user->fd,"301 %s %s :%s",user->nick, dest->nick, dest->awaymsg); + } + if (strchr(dest->modes,'o')) + { + if (*dest->oper) { - WriteServ(user->fd,"301 %s %s :%s",user->nick, dest->nick, dest->awaymsg); + WriteServ(user->fd,"313 %s %s :is %s %s on %s",user->nick, dest->nick, (strchr("aeiou",dest->oper[0]) ? "an" : "a"),dest->oper, Config->Network); } - if ((strchr(dest->modes,'o')) && (strcmp(dest->oper,""))) + else { - WriteServ(user->fd,"313 %s %s :is %s %s on %s",user->nick, dest->nick, - (strchr("aeiou",dest->oper[0]) ? "an" : "a"),dest->oper, Network); + WriteServ(user->fd,"313 %s %s :is opered but has an unknown type",user->nick, dest->nick); } + } + if ((!signon) && (!idle)) + { FOREACH_MOD OnWhois(user,dest); - if (!strcasecmp(user->server,dest->server)) - { - // idle time and signon line can only be sent if youre on the same server (according to RFC) - WriteServ(user->fd,"317 %s %s %d %d :seconds idle, signon time",user->nick, dest->nick, abs((dest->idle_lastmsg)-TIME), dest->signon); - } - - WriteServ(user->fd,"318 %s %s :End of /WHOIS list.",user->nick, dest->nick); + } + if (!strcasecmp(user->server,dest->server)) + { + // idle time and signon line can only be sent if youre on the same server (according to RFC) + WriteServ(user->fd,"317 %s %s %d %d :seconds idle, signon time",user->nick, dest->nick, abs((dest->idle_lastmsg)-TIME), dest->signon); } else { - WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]); - WriteServ(user->fd,"318 %s %s :End of /WHOIS list.",user->nick, parameters[0]); + if ((idle) || (signon)) + WriteServ(user->fd,"317 %s %s %d %d :seconds idle, signon time",user->nick, dest->nick, idle, signon); } + WriteServ(user->fd,"318 %s %s :End of /WHOIS list.",user->nick, dest->nick); } else { - /* no such nick/channel */ - WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]); - WriteServ(user->fd,"318 %s %s :End of /WHOIS list.",user->nick, parameters[0]); + WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, nick); + WriteServ(user->fd,"318 %s %s :End of /WHOIS list.",user->nick, nick); } } @@ -869,10 +876,21 @@ void handle_quit(char **parameters, int pcnt, userrec *user) reason[MAXQUIT-1] = '\0'; } - Write(user->fd,"ERROR :Closing link (%s@%s) [%s%s]",user->ident,user->host,PrefixQuit,parameters[0]); - WriteOpers("*** Client exiting: %s!%s@%s [%s%s]",user->nick,user->ident,user->host,PrefixQuit,parameters[0]); - WriteCommonExcept(user,"QUIT :%s%s",PrefixQuit,parameters[0]); - FOREACH_MOD OnUserQuit(user,std::string(PrefixQuit)+std::string(parameters[0])); + /* We should only prefix the quit for a local user. Remote users have + * already been prefixed, where neccessary, by the upstream server. + */ + if (user->fd > -1) + { + Write(user->fd,"ERROR :Closing link (%s@%s) [%s%s]",user->ident,user->host,Config->PrefixQuit,parameters[0]); + WriteOpers("*** Client exiting: %s!%s@%s [%s%s]",user->nick,user->ident,user->host,Config->PrefixQuit,parameters[0]); + WriteCommonExcept(user,"QUIT :%s%s",Config->PrefixQuit,parameters[0]); + } + else + { + WriteOpers("*** Client exiting at %s: %s!%s@%s [%s]",user->server,user->nick,user->ident,user->host,parameters[0]); + WriteCommonExcept(user,"QUIT :%s",parameters[0]); + } + FOREACH_MOD OnUserQuit(user,std::string(Config->PrefixQuit)+std::string(parameters[0])); } else @@ -891,25 +909,7 @@ void handle_quit(char **parameters, int pcnt, userrec *user) /* push the socket on a stack of sockets due to be closed at the next opportunity */ if (user->fd > -1) { -#ifdef USE_KQUEUE - struct kevent ke; - EV_SET(&ke, user->fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); - int i = kevent(kq, &ke, 1, 0, 0, NULL); - if (i == -1) - { - log(DEBUG,"kqueue: Failed to remove user from queue!"); - } -#endif -#ifdef USE_EPOLL - struct epoll_event ev; - ev.events = EPOLLIN | EPOLLET; - ev.data.fd = user->fd; - int i = epoll_ctl(ep, EPOLL_CTL_DEL, user->fd, &ev); - if (i < 0) - { - log(DEBUG,"epoll: List deletion failure!"); - } -#endif + SE->DelFd(user->fd); user->CloseSocket(); } @@ -936,7 +936,7 @@ void handle_who(char **parameters, int pcnt, userrec *user) { if ((!strcmp(parameters[0],"0")) || (!strcmp(parameters[0],"*"))) { - if (user->chans[0].channel) + if ((user->chans.size()) && (user->chans[0].channel)) { int n_list = 0; for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++) @@ -955,7 +955,7 @@ void handle_who(char **parameters, int pcnt, userrec *user) if (strchr(i->second->modes,'o')) { strlcat(tmp, "*", 9); } WriteServ(user->fd,"352 %s %s %s %s %s %s %s :0 %s",user->nick, Ptr ? Ptr->name : "*", i->second->ident, i->second->dhost, i->second->server, i->second->nick, tmp, i->second->fullname); n_list++; - if (n_list > MaxWhoResults) + if (n_list > Config->MaxWhoResults) { WriteServ(user->fd,"523 %s WHO :Command aborted: More results than configured limit",user->nick); break; @@ -994,7 +994,7 @@ void handle_who(char **parameters, int pcnt, userrec *user) strlcat(tmp, cmode(i->second, Ptr),5); WriteServ(user->fd,"352 %s %s %s %s %s %s %s :0 %s",user->nick, Ptr->name, i->second->ident, i->second->dhost, i->second->server, i->second->nick, tmp, i->second->fullname); n_list++; - if (n_list > MaxWhoResults) + if (n_list > Config->MaxWhoResults) { WriteServ(user->fd,"523 %s WHO :Command aborted: More results than configured limit",user->nick); break; @@ -1022,7 +1022,7 @@ void handle_who(char **parameters, int pcnt, userrec *user) strlcat(tmp, "H" ,9); } if (strchr(u->modes,'o')) { strlcat(tmp, "*" ,9); } - WriteServ(user->fd,"352 %s %s %s %s %s %s %s :0 %s",user->nick, u->chans[0].channel ? u->chans[0].channel->name + WriteServ(user->fd,"352 %s %s %s %s %s %s %s :0 %s",user->nick, u->chans.size() ? u->chans[0].channel->name : "*", u->ident, u->dhost, u->server, u->nick, tmp, u->fullname); } WriteServ(user->fd,"315 %s %s :End of /WHO list.",user->nick, parameters[0]); @@ -1043,7 +1043,7 @@ void handle_who(char **parameters, int pcnt, userrec *user) } else { strlcat(tmp, "H" ,9); } - WriteServ(user->fd,"352 %s %s %s %s %s %s %s* :0 %s", user->nick, oper->chans[0].channel ? oper->chans[0].channel->name + WriteServ(user->fd,"352 %s %s %s %s %s %s %s* :0 %s", user->nick, oper->chans.size() ? oper->chans[0].channel->name : "*", oper->ident, oper->dhost, oper->server, oper->nick, tmp, oper->fullname); } WriteServ(user->fd,"315 %s %s :End of /WHO list.",user->nick, parameters[0]); @@ -1055,6 +1055,7 @@ void handle_who(char **parameters, int pcnt, userrec *user) void handle_wallops(char **parameters, int pcnt, userrec *user) { WriteWallOps(user,false,"%s",parameters[0]); + FOREACH_MOD OnWallops(user,parameters[0]); } void handle_list(char **parameters, int pcnt, userrec *user) @@ -1075,31 +1076,41 @@ void handle_list(char **parameters, int pcnt, userrec *user) void handle_rehash(char **parameters, int pcnt, userrec *user) { WriteServ(user->fd,"382 %s %s :Rehashing",user->nick,CleanFilename(CONFIG_FILE)); - ReadConfig(false,user); - FOREACH_MOD OnRehash(); - WriteOpers("%s is rehashing config file %s",user->nick,CleanFilename(CONFIG_FILE)); + std::string parameter = ""; + if (pcnt) + { + parameter = parameters[0]; + } + else + { + WriteOpers("%s is rehashing config file %s",user->nick,CleanFilename(CONFIG_FILE)); + Config->Read(false,user); + } + FOREACH_MOD OnRehash(parameter); } void handle_lusers(char **parameters, int pcnt, userrec *user) { - WriteServ(user->fd,"251 %s :There are %d users and %d invisible on %d servers",user->nick,usercnt()-usercount_invisible(),usercount_invisible(),servercount()); + // this lusers command shows one server at all times because + // a protocol module must override it to show those stats. + WriteServ(user->fd,"251 %s :There are %d users and %d invisible on 1 server",user->nick,usercnt()-usercount_invisible(),usercount_invisible()); WriteServ(user->fd,"252 %s %d :operator(s) online",user->nick,usercount_opers()); WriteServ(user->fd,"253 %s %d :unknown connections",user->nick,usercount_unknown()); WriteServ(user->fd,"254 %s %d :channels formed",user->nick,chancount()); - WriteServ(user->fd,"254 %s :I have %d clients and %d servers",user->nick,local_count(),count_servs()); + WriteServ(user->fd,"254 %s :I have %d clients and 0 servers",user->nick,local_count()); } void handle_admin(char **parameters, int pcnt, userrec *user) { - WriteServ(user->fd,"256 %s :Administrative info for %s",user->nick,ServerName); - WriteServ(user->fd,"257 %s :Name - %s",user->nick,AdminName); - WriteServ(user->fd,"258 %s :Nickname - %s",user->nick,AdminNick); - WriteServ(user->fd,"258 %s :E-Mail - %s",user->nick,AdminEmail); + WriteServ(user->fd,"256 %s :Administrative info for %s",user->nick,Config->ServerName); + WriteServ(user->fd,"257 %s :Name - %s",user->nick,Config->AdminName); + WriteServ(user->fd,"258 %s :Nickname - %s",user->nick,Config->AdminNick); + WriteServ(user->fd,"258 %s :E-Mail - %s",user->nick,Config->AdminEmail); } void handle_ping(char **parameters, int pcnt, userrec *user) { - WriteServ(user->fd,"PONG %s :%s",ServerName,parameters[0]); + WriteServ(user->fd,"PONG %s :%s",Config->ServerName,parameters[0]); } void handle_pong(char **parameters, int pcnt, userrec *user) @@ -1260,7 +1271,7 @@ void handle_trace(char **parameters, int pcnt, userrec *user) void handle_modules(char **parameters, int pcnt, userrec *user) { - for (unsigned int i = 0; i < module_names.size(); i++) + for (unsigned int i = 0; i < Config->module_names.size(); i++) { Version V = modules[i]->GetVersion(); char modulename[MAXBUF]; @@ -1276,7 +1287,7 @@ void handle_modules(char **parameters, int pcnt, userrec *user) strlcat(flagstate,", service provider",MAXBUF); if (!flagstate[0]) strcpy(flagstate," "); - strlcpy(modulename,module_names[i].c_str(),256); + strlcpy(modulename,Config->module_names[i].c_str(),256); if (strchr(user->modes,'o')) { WriteServ(user->fd,"900 %s :0x%08lx %d.%d.%d.%d %s (%s)",user->nick,modules[i],V.Major,V.Minor,V.Revision,V.Build,CleanFilename(modulename),flagstate+2); @@ -1291,7 +1302,6 @@ void handle_modules(char **parameters, int pcnt, userrec *user) void handle_stats(char **parameters, int pcnt, userrec *user) { - char Link_ServerName[MAXBUF],Link_IPAddr[MAXBUF],Link_Port[MAXBUF]; if (pcnt != 1) { return; @@ -1307,22 +1317,15 @@ void handle_stats(char **parameters, int pcnt, userrec *user) if (*parameters[0] == 'c') { - for (int i = 0; i < ConfValueEnum("link",&config_f); i++) - { - ConfValue("link","name",i,Link_ServerName,&config_f); - ConfValue("link","ipaddr",i,Link_IPAddr,&config_f); - ConfValue("link","port",i,Link_Port,&config_f); - WriteServ(user->fd,"213 %s C *@%s * %s %s 0 M",user->nick,Link_IPAddr,Link_ServerName,Link_Port); - WriteServ(user->fd,"244 %s H * * %s",user->nick,Link_ServerName); - } + /* This stats symbol must be handled by a linking module */ } if (*parameters[0] == 'i') { int idx = 0; - for (ClassVector::iterator i = Classes.begin(); i != Classes.end(); i++) + for (ClassVector::iterator i = Config->Classes.begin(); i != Config->Classes.end(); i++) { - WriteServ(user->fd,"215 %s I * * * %d %d %s *",user->nick,MAXCLIENTS,idx,ServerName); + WriteServ(user->fd,"215 %s I * * * %d %d %s *",user->nick,MAXCLIENTS,idx,Config->ServerName); idx++; } } @@ -1330,7 +1333,7 @@ void handle_stats(char **parameters, int pcnt, userrec *user) if (*parameters[0] == 'y') { int idx = 0; - for (ClassVector::iterator i = Classes.begin(); i != Classes.end(); i++) + for (ClassVector::iterator i = Config->Classes.begin(); i != Config->Classes.end(); i++) { WriteServ(user->fd,"218 %s Y %d %d 0 %d %d",user->nick,idx,120,i->flood,i->registration_timeout); idx++; @@ -1339,10 +1342,11 @@ void handle_stats(char **parameters, int pcnt, userrec *user) if (*parameters[0] == 'U') { - for (int i = 0; i < ConfValueEnum("uline",&config_f); i++) + char ulined[MAXBUF]; + for (int i = 0; i < Config->ConfValueEnum("uline",&Config->config_f); i++) { - ConfValue("uline","server",i,Link_ServerName,&config_f); - WriteServ(user->fd,"248 %s U %s",user->nick,Link_ServerName); + Config->ConfValue("uline","server",i,ulined,&Config->config_f); + WriteServ(user->fd,"248 %s U %s",user->nick,ulined); } } @@ -1409,7 +1413,7 @@ void handle_stats(char **parameters, int pcnt, userrec *user) WriteServ(user->fd,"249 %s :Users(HASH_MAP) %d (%d bytes, %d buckets)",user->nick,clientlist.size(),clientlist.size()*sizeof(userrec),clientlist.bucket_count()); WriteServ(user->fd,"249 %s :Channels(HASH_MAP) %d (%d bytes, %d buckets)",user->nick,chanlist.size(),chanlist.size()*sizeof(chanrec),chanlist.bucket_count()); WriteServ(user->fd,"249 %s :Commands(VECTOR) %d (%d bytes)",user->nick,cmdlist.size(),cmdlist.size()*sizeof(command_t)); - WriteServ(user->fd,"249 %s :MOTD(VECTOR) %d, RULES(VECTOR) %d",user->nick,MOTD.size(),RULES.size()); + WriteServ(user->fd,"249 %s :MOTD(VECTOR) %d, RULES(VECTOR) %d",user->nick,Config->MOTD.size(),Config->RULES.size()); WriteServ(user->fd,"249 %s :address_cache(HASH_MAP) %d (%d buckets)",user->nick,IP.size(),IP.bucket_count()); WriteServ(user->fd,"249 %s :Modules(VECTOR) %d (%d)",user->nick,modules.size(),modules.size()*sizeof(Module)); WriteServ(user->fd,"249 %s :ClassFactories(VECTOR) %d (%d)",user->nick,factory.size(),factory.size()*sizeof(ircd_module)); @@ -1426,25 +1430,25 @@ void handle_stats(char **parameters, int pcnt, userrec *user) if (*parameters[0] == 'T') { - WriteServ(user->fd,"249 Brain :accepts %d refused %d",statsAccept,statsRefused); - WriteServ(user->fd,"249 Brain :unknown commands %d",statsUnknown); - WriteServ(user->fd,"249 Brain :nick collisions %d",statsCollisions); - WriteServ(user->fd,"249 Brain :dns requests %d succeeded %d failed %d",statsDns,statsDnsGood,statsDnsBad); - WriteServ(user->fd,"249 Brain :connections %d",statsConnects); - WriteServ(user->fd,"249 Brain :bytes sent %dK recv %dK",(statsSent / 1024),(statsRecv / 1024)); + WriteServ(user->fd,"249 Brain :accepts %d refused %d",stats->statsAccept,stats->statsRefused); + WriteServ(user->fd,"249 Brain :unknown commands %d",stats->statsUnknown); + WriteServ(user->fd,"249 Brain :nick collisions %d",stats->statsCollisions); + WriteServ(user->fd,"249 Brain :dns requests %d succeeded %d failed %d",stats->statsDns,stats->statsDnsGood,stats->statsDnsBad); + WriteServ(user->fd,"249 Brain :connections %d",stats->statsConnects); + WriteServ(user->fd,"249 Brain :bytes sent %dK recv %dK",(stats->statsSent / 1024),(stats->statsRecv / 1024)); } /* stats o */ if (*parameters[0] == 'o') { - for (int i = 0; i < ConfValueEnum("oper",&config_f); i++) + for (int i = 0; i < Config->ConfValueEnum("oper",&Config->config_f); i++) { char LoginName[MAXBUF]; char HostName[MAXBUF]; char OperType[MAXBUF]; - ConfValue("oper","name",i,LoginName,&config_f); - ConfValue("oper","host",i,HostName,&config_f); - ConfValue("oper","type",i,OperType,&config_f); + Config->ConfValue("oper","name",i,LoginName,&Config->config_f); + Config->ConfValue("oper","host",i,HostName,&Config->config_f); + Config->ConfValue("oper","type",i,OperType,&Config->config_f); WriteServ(user->fd,"243 %s O %s * %s %s 0",user->nick,HostName,LoginName,OperType); } } @@ -1503,14 +1507,16 @@ void handle_squit(char **parameters, int pcnt, userrec *user) void handle_links(char **parameters, int pcnt, userrec *user) { - WriteServ(user->fd,"364 %s %s %s :0 %s",user->nick,ServerName,ServerName,ServerDesc); + WriteServ(user->fd,"364 %s %s %s :0 %s",user->nick,Config->ServerName,Config->ServerName,Config->ServerDesc); WriteServ(user->fd,"365 %s * :End of /LINKS list.",user->nick); } void handle_map(char **parameters, int pcnt, userrec *user) { - char line[MAXBUF]; - snprintf(line,MAXBUF,"006 %s :%s",user->nick,ServerName); + // as with /LUSERS this does nothing without a linking + // module to override its behaviour and display something + // better. + WriteServ(user->fd,"006 %s :%s",user->nick,Config->ServerName); WriteServ(user->fd,"007 %s :End of /MAP",user->nick); } @@ -1518,13 +1524,14 @@ bool is_uline(const char* server) { char ServName[MAXBUF]; - /* fix, by w00t - per nenolod. I don't see how we can want '""' as a uline. */ - if (!server || !(*server)) + if (!server) + return false; + if (!(*server)) return true; - for (int i = 0; i < ConfValueEnum("uline",&config_f); i++) + for (int i = 0; i < Config->ConfValueEnum("uline",&Config->config_f); i++) { - ConfValue("uline","server",i,ServName,&config_f); + Config->ConfValue("uline","server",i,ServName,&Config->config_f); if (!strcasecmp(server,ServName)) { return true; @@ -1559,23 +1566,23 @@ void handle_oper(char **parameters, int pcnt, userrec *user) snprintf(TheHost,MAXBUF,"%s@%s",user->ident,user->host); - for (int i = 0; i < ConfValueEnum("oper",&config_f); i++) + for (int i = 0; i < Config->ConfValueEnum("oper",&Config->config_f); i++) { - ConfValue("oper","name",i,LoginName,&config_f); - ConfValue("oper","password",i,Password,&config_f); - ConfValue("oper","type",i,OperType,&config_f); - ConfValue("oper","host",i,HostName,&config_f); + Config->ConfValue("oper","name",i,LoginName,&Config->config_f); + Config->ConfValue("oper","password",i,Password,&Config->config_f); + Config->ConfValue("oper","type",i,OperType,&Config->config_f); + Config->ConfValue("oper","host",i,HostName,&Config->config_f); if ((!strcmp(LoginName,parameters[0])) && (!operstrcmp(Password,parameters[1])) && (match(TheHost,HostName))) { fail2 = true; - for (j =0; j < ConfValueEnum("type",&config_f); j++) + for (j =0; j < Config->ConfValueEnum("type",&Config->config_f); j++) { - ConfValue("type","name",j,TypeName,&config_f); + Config->ConfValue("type","name",j,TypeName,&Config->config_f); if (!strcmp(TypeName,OperType)) { /* found this oper's opertype */ - ConfValue("type","host",j,HostName,&config_f); + Config->ConfValue("type","host",j,HostName,&Config->config_f); if (*HostName) ChangeDisplayedHost(user,HostName); strlcpy(user->oper,TypeName,NICKMAX); @@ -1710,9 +1717,22 @@ void handle_nick(char **parameters, int pcnt, userrec *user) user->registered = (user->registered | 2); // dont attempt to look up the dns until they pick a nick... because otherwise their pointer WILL change // and unless we're lucky we'll get a duff one later on. + //user->dns_done = (!lookup_dns(user->nick)); + //if (user->dns_done) + // log(DEBUG,"Aborting dns lookup of %s because dns server experienced a failure.",user->nick); + +#ifdef THREADED_DNS + // initialize their dns lookup thread + if (pthread_create(&user->dnsthread, NULL, dns_task, (void *)user) != 0) + { + log(DEBUG,"Failed to create DNS lookup thread for user %s",user->nick); + } +#else user->dns_done = (!lookup_dns(user->nick)); if (user->dns_done) log(DEBUG,"Aborting dns lookup of %s because dns server experienced a failure.",user->nick); +#endif + } if (user->registered == 3) { @@ -1732,6 +1752,13 @@ long duration(const char* str) long total = 0; const char* str_end = str + strlen(str); n_field[0] = 0; + + if ((!strchr(str,'s')) && (!strchr(str,'m')) && (!strchr(str,'h')) && (!strchr(str,'d')) && (!strchr(str,'w')) && (!strchr(str,'y'))) + { + std::string n = str; + n = n + "s"; + return duration(n.c_str()); + } for (char* i = (char*)str; i < str_end; i++) { @@ -1779,12 +1806,95 @@ long duration(const char* str) return total; } +/* All other ircds when doing this check usually just look for a string of *@* or *. We're smarter than that, though. */ + +bool host_matches_everyone(std::string mask, userrec* user) +{ + char insanemasks[MAXBUF]; + char buffer[MAXBUF]; + char itrigger[MAXBUF]; + Config->ConfValue("insane","hostmasks",0,insanemasks,&Config->config_f); + Config->ConfValue("insane","trigger",0,itrigger,&Config->config_f); + if (*itrigger == 0) + strlcpy(itrigger,"95.5",MAXBUF); + if ((*insanemasks == 'y') || (*insanemasks == 't') || (*insanemasks == '1')) + return false; + long matches = 0; + for (user_hash::iterator u = clientlist.begin(); u != clientlist.end(); u++) + { + strlcpy(buffer,u->second->ident,MAXBUF); + strlcat(buffer,"@",MAXBUF); + strlcat(buffer,u->second->host,MAXBUF); + if (match(buffer,mask.c_str())) + matches++; + } + float percent = ((float)matches / (float)clientlist.size()) * 100; + if (percent > (float)atof(itrigger)) + { + WriteOpers("*** \2WARNING\2: %s tried to set a G/K/E line mask of %s, which covers %.2f%% of the network!",user->nick,mask.c_str(),percent); + return true; + } + return false; +} + +bool ip_matches_everyone(std::string ip, userrec* user) +{ + char insanemasks[MAXBUF]; + char itrigger[MAXBUF]; + Config->ConfValue("insane","ipmasks",0,insanemasks,&Config->config_f); + Config->ConfValue("insane","trigger",0,itrigger,&Config->config_f); + if (*itrigger == 0) + strlcpy(itrigger,"95.5",MAXBUF); + if ((*insanemasks == 'y') || (*insanemasks == 't') || (*insanemasks == '1')) + return false; + long matches = 0; + for (user_hash::iterator u = clientlist.begin(); u != clientlist.end(); u++) + { + if (match(u->second->ip,ip.c_str())) + matches++; + } + float percent = ((float)matches / (float)clientlist.size()) * 100; + if (percent > (float)atof(itrigger)) + { + WriteOpers("*** \2WARNING\2: %s tried to set a Z line mask of %s, which covers %.2f%% of the network!",user->nick,ip.c_str(),percent); + return true; + } + return false; +} + +bool nick_matches_everyone(std::string nick, userrec* user) +{ + char insanemasks[MAXBUF]; + char itrigger[MAXBUF]; + Config->ConfValue("insane","nickmasks",0,insanemasks,&Config->config_f); + Config->ConfValue("insane","trigger",0,itrigger,&Config->config_f); + if (*itrigger == 0) + strlcpy(itrigger,"95.5",MAXBUF); + if ((*insanemasks == 'y') || (*insanemasks == 't') || (*insanemasks == '1')) + return false; + long matches = 0; + for (user_hash::iterator u = clientlist.begin(); u != clientlist.end(); u++) + { + if (match(u->second->nick,nick.c_str())) + matches++; + } + float percent = ((float)matches / (float)clientlist.size()) * 100; + if (percent > (float)atof(itrigger)) + { + WriteOpers("*** \2WARNING\2: %s tried to set a Q line mask of %s, which covers %.2f%% of the network!",user->nick,nick.c_str(),percent); + return true; + } + return false; +} void handle_kline(char **parameters, int pcnt, userrec *user) { if (pcnt >= 3) { + if (host_matches_everyone(parameters[0],user)) + return; add_kline(duration(parameters[1]),user->nick,parameters[2],parameters[0]); + FOREACH_MOD OnAddKLine(duration(parameters[1]), user, parameters[2], parameters[0]); if (!duration(parameters[1])) { WriteOpers("*** %s added permenant K-line for %s.",user->nick,parameters[0]); @@ -1793,11 +1903,13 @@ void handle_kline(char **parameters, int pcnt, userrec *user) { WriteOpers("*** %s added timed K-line for %s, expires in %d seconds.",user->nick,parameters[0],duration(parameters[1])); } + apply_lines(APPLY_KLINES); } else { if (del_kline(parameters[0])) { + FOREACH_MOD OnDelKLine(user, parameters[0]); WriteOpers("*** %s Removed K-line on %s.",user->nick,parameters[0]); } else @@ -1805,14 +1917,16 @@ void handle_kline(char **parameters, int pcnt, userrec *user) WriteServ(user->fd,"NOTICE %s :*** K-Line %s not found in list, try /stats k.",user->nick,parameters[0]); } } - apply_lines(); } void handle_eline(char **parameters, int pcnt, userrec *user) { if (pcnt >= 3) { + if (host_matches_everyone(parameters[0],user)) + return; add_eline(duration(parameters[1]),user->nick,parameters[2],parameters[0]); + FOREACH_MOD OnAddELine(duration(parameters[1]), user, parameters[2], parameters[0]); if (!duration(parameters[1])) { WriteOpers("*** %s added permenant E-line for %s.",user->nick,parameters[0]); @@ -1826,6 +1940,7 @@ void handle_eline(char **parameters, int pcnt, userrec *user) { if (del_eline(parameters[0])) { + FOREACH_MOD OnDelELine(user, parameters[0]); WriteOpers("*** %s Removed E-line on %s.",user->nick,parameters[0]); } else @@ -1838,10 +1953,12 @@ void handle_eline(char **parameters, int pcnt, userrec *user) void handle_gline(char **parameters, int pcnt, userrec *user) { - char netdata[MAXBUF]; if (pcnt >= 3) { + if (host_matches_everyone(parameters[0],user)) + return; add_gline(duration(parameters[1]),user->nick,parameters[2],parameters[0]); + FOREACH_MOD OnAddGLine(duration(parameters[1]), user, parameters[2], parameters[0]); if (!duration(parameters[1])) { WriteOpers("*** %s added permenant G-line for %s.",user->nick,parameters[0]); @@ -1850,13 +1967,13 @@ void handle_gline(char **parameters, int pcnt, userrec *user) { WriteOpers("*** %s added timed G-line for %s, expires in %d seconds.",user->nick,parameters[0],duration(parameters[1])); } + apply_lines(APPLY_GLINES); } else { if (del_gline(parameters[0])) { - // . - snprintf(netdata,MAXBUF,". %s %s",parameters[0],user->nick); + FOREACH_MOD OnDelGLine(user, parameters[0]); WriteOpers("*** %s Removed G-line on %s.",user->nick,parameters[0]); } else @@ -1864,14 +1981,21 @@ void handle_gline(char **parameters, int pcnt, userrec *user) WriteServ(user->fd,"NOTICE %s :*** G-Line %s not found in list, try /stats g.",user->nick,parameters[0]); } } - apply_lines(); } void handle_zline(char **parameters, int pcnt, userrec *user) { if (pcnt >= 3) { + if (strchr(parameters[0],'@')) + { + WriteServ(user->fd,"NOTICE %s :*** You cannot include a username in a zline, a zline must ban only an IP mask",user->nick); + return; + } + if (ip_matches_everyone(parameters[0],user)) + return; add_zline(duration(parameters[1]),user->nick,parameters[2],parameters[0]); + FOREACH_MOD OnAddZLine(duration(parameters[1]), user, parameters[2], parameters[0]); if (!duration(parameters[1])) { WriteOpers("*** %s added permenant Z-line for %s.",user->nick,parameters[0]); @@ -1880,11 +2004,13 @@ void handle_zline(char **parameters, int pcnt, userrec *user) { WriteOpers("*** %s added timed Z-line for %s, expires in %d seconds.",user->nick,parameters[0],duration(parameters[1])); } + apply_lines(APPLY_ZLINES); } else { if (del_zline(parameters[0])) { + FOREACH_MOD OnDelZLine(user, parameters[0]); WriteOpers("*** %s Removed Z-line on %s.",user->nick,parameters[0]); } else @@ -1892,14 +2018,16 @@ void handle_zline(char **parameters, int pcnt, userrec *user) WriteServ(user->fd,"NOTICE %s :*** Z-Line %s not found in list, try /stats Z.",user->nick,parameters[0]); } } - apply_lines(); } void handle_qline(char **parameters, int pcnt, userrec *user) { if (pcnt >= 3) { + if (nick_matches_everyone(parameters[0],user)) + return; add_qline(duration(parameters[1]),user->nick,parameters[2],parameters[0]); + FOREACH_MOD OnAddQLine(duration(parameters[1]), user, parameters[2], parameters[0]); if (!duration(parameters[1])) { WriteOpers("*** %s added permenant Q-line for %s.",user->nick,parameters[0]); @@ -1908,19 +2036,20 @@ void handle_qline(char **parameters, int pcnt, userrec *user) { WriteOpers("*** %s added timed Q-line for %s, expires in %d seconds.",user->nick,parameters[0],duration(parameters[1])); } + apply_lines(APPLY_QLINES); } else { if (del_qline(parameters[0])) { + FOREACH_MOD OnDelQLine(user, parameters[0]); WriteOpers("*** %s Removed Q-line on %s.",user->nick,parameters[0]); } else { - WriteServ(user->fd,"NOTICE %s :*** Q-Line %s not found in list, try /stats k.",user->nick,parameters[0]); + WriteServ(user->fd,"NOTICE %s :*** Q-Line %s not found in list, try /stats q.",user->nick,parameters[0]); } } - apply_lines(); }