X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fcommands.cpp;h=2b96b0a8ffb9f3323899fbcd8ed781c7afb85f31;hb=9e81044ffde2b1fc62456aca512d0cd7f1e52ad8;hp=00ee9a20fc05a1509ed1792ee665ba30f017ac30;hpb=ceb22bce3d8a04e7951dd2e4fbb52f37135c3708;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/commands.cpp b/src/commands.cpp index 00ee9a20f..2b96b0a8f 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -14,15 +14,27 @@ * --------------------------------------------------- */ +using namespace std; + #include "inspircd.h" #include "inspircd_io.h" #include "inspircd_util.h" #include "inspircd_config.h" #include -#include #include #include #include + +#ifdef USE_KQUEUE +#include +#include +#include +#endif + +#ifdef USE_EPOLL +#include +#endif + #include #include #include @@ -34,11 +46,14 @@ #include #include #include -#include #include -#include -#include -#include +#include +#include +#include +#ifndef RUSAGE_SELF +#define RUSAGE_SELF 0 +#define RUSAGE_CHILDREN -1 +#endif #include "connection.h" #include "users.h" #include "servers.h" @@ -52,14 +67,16 @@ #include "xline.h" #include "inspstring.h" #include "dnsqueue.h" +#include "helperfuncs.h" +#include "hashcomp.h" -#ifdef GCC3 -#define nspace __gnu_cxx -#else -#define nspace std +#ifdef USE_KQUEUE +extern int kq; #endif -using namespace std; +#ifdef USE_EPOLL +int ep; +#endif extern int MODCOUNT; extern std::vector modules; @@ -98,7 +115,7 @@ extern std::vector module_names; extern char MyExecutable[1024]; extern int boundPortCount; extern int portCount; -extern int UDPportCount; +extern int SERVERportCount; extern int ports[MAXSOCKS]; extern int defaultRoute; @@ -117,85 +134,29 @@ const long duration_d = duration_h * 24; const long duration_w = duration_d * 7; const long duration_y = duration_w * 52; -namespace nspace -{ -#ifdef GCC34 - template<> struct hash -#else - template<> struct nspace::hash -#endif - { - size_t operator()(const struct in_addr &a) const - { - size_t q; - memcpy(&q,&a,sizeof(size_t)); - return q; - } - }; -#ifdef GCC34 - template<> struct hash -#else - template<> struct nspace::hash -#endif - { - size_t operator()(const string &s) const - { - char a[MAXBUF]; - static struct hash strhash; - strlcpy(a,s.c_str(),MAXBUF); - strlower(a); - return strhash(a); - } - }; -} - - -struct StrHashComp -{ - - bool operator()(const string& s1, const string& s2) const - { - char a[MAXBUF],b[MAXBUF]; - strlcpy(a,s1.c_str(),MAXBUF); - strlcpy(b,s2.c_str(),MAXBUF); - strlower(a); - strlower(b); - return (strcasecmp(a,b) == 0); - } - -}; - -struct InAddr_HashComp -{ - - bool operator()(const in_addr &s1, const in_addr &s2) const - { - size_t q; - size_t p; - - memcpy(&q,&s1,sizeof(size_t)); - memcpy(&p,&s2,sizeof(size_t)); - - return (q == p); - } - -}; - - -typedef nspace::hash_map, StrHashComp> user_hash; -typedef nspace::hash_map, StrHashComp> chan_hash; -typedef nspace::hash_map, InAddr_HashComp> address_cache; +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 user_hash whowas; +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; + +// This table references users by file descriptor. +// its an array to make it VERY fast, as all lookups are referenced +// 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; void handle_join(char **parameters, int pcnt, userrec *user) { @@ -226,6 +187,15 @@ void handle_part(char **parameters, int pcnt, userrec *user) } } +void handle_commands(char **parameters, int pcnt, userrec *user) +{ + for (int i = 0; i < command_table.size(); i++) + { + WriteServ(user->fd,"902 %s :%s %s",user->nick,command_table[i].command,command_table[i].source); + } + WriteServ(user->fd,"903 %s :End of COMMANDS list"); +} + void handle_kick(char **parameters, int pcnt, userrec *user) { chanrec* Ptr = FindChan(parameters[0]); @@ -391,6 +361,8 @@ void handle_kill(char **parameters, int pcnt, userrec *user) { purge_empty_chans(u); } + if (u->fd > -1) + fd_ref_table[u->fd] = NULL; delete u; } else @@ -436,59 +408,75 @@ void handle_pass(char **parameters, int pcnt, userrec *user) void handle_invite(char **parameters, int pcnt, userrec *user) { - userrec* u = Find(parameters[0]); - chanrec* c = FindChan(parameters[1]); - - if ((!c) || (!u)) + if (pcnt == 2) { - if (!c) + userrec* u = Find(parameters[0]); + chanrec* c = FindChan(parameters[1]); + + if ((!c) || (!u)) { - WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[1]); + if (!c) + { + WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[1]); + } + else + { + if (c->binarymodes & CM_INVITEONLY) + { + WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]); + } + } + + return; } - else + + if (c->binarymodes & CM_INVITEONLY) { - if (c->inviteonly) + if (cstatus(user,c) < STATUS_HOP) { - WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]); + WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, c->name); + return; } } + if (has_channel(u,c)) + { + WriteServ(user->fd,"443 %s %s %s :Is already on channel %s",user->nick,u->nick,c->name,c->name); + return; + } + if (!has_channel(user,c)) + { + WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, c->name); + return; + } - return; - } + int MOD_RESULT = 0; + FOREACH_RESULT(OnUserPreInvite(user,u,c)); + if (MOD_RESULT == 1) { + return; + } - if (c->inviteonly) + u->InviteTo(c->name); + WriteFrom(u->fd,user,"INVITE %s :%s",u->nick,c->name); + WriteServ(user->fd,"341 %s %s %s",user->nick,u->nick,c->name); + + // i token must go to ALL servers!!! + char buffer[MAXBUF]; + snprintf(buffer,MAXBUF,"i %s %s %s",u->nick,user->nick,c->name); + NetSendToAll(buffer); + } + else { - if (cstatus(user,c) < STATUS_HOP) + // pinched from ircu - invite with not enough parameters shows channels + // youve been invited to but haven't joined yet. + InvitedList* il = user->GetInviteList(); + for (InvitedList::iterator i = il->begin(); i != il->end(); i++) { - WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, c->name); - return; + if (i->channel) { + WriteServ(user->fd,"346 %s :%s",user->nick,i->channel); + } } + WriteServ(user->fd,"347 %s :End of INVITE list",user->nick); } - if (has_channel(u,c)) - { - WriteServ(user->fd,"443 %s %s %s :Is already on channel %s",user->nick,u->nick,c->name,c->name); - return; - } - if (!has_channel(user,c)) - { - WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, c->name); - return; - } - - int MOD_RESULT = 0; - FOREACH_RESULT(OnUserPreInvite(user,u,c)); - if (MOD_RESULT == 1) { - return; - } - - u->InviteTo(c->name); - WriteFrom(u->fd,user,"INVITE %s :%s",u->nick,c->name); - WriteServ(user->fd,"341 %s %s %s",user->nick,u->nick,c->name); - - // i token must go to ALL servers!!! - char buffer[MAXBUF]; - snprintf(buffer,MAXBUF,"i %s %s %s",u->nick,user->nick,c->name); - NetSendToAll(buffer); } void handle_topic(char **parameters, int pcnt, userrec *user) @@ -502,7 +490,7 @@ void handle_topic(char **parameters, int pcnt, userrec *user) Ptr = FindChan(parameters[0]); if (Ptr) { - if (((Ptr) && (!has_channel(user,Ptr))) && (Ptr->secret)) + 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); return; @@ -536,7 +524,7 @@ void handle_topic(char **parameters, int pcnt, userrec *user) WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, Ptr->name); return; } - if ((Ptr->topiclock) && (cstatus(user,Ptr)binarymodes & CM_TOPICLOCK) && (cstatus(user,Ptr)fd,"482 %s %s :You must be at least a half-operator to change modes on this channel", user->nick, Ptr->name); return; @@ -590,7 +578,7 @@ void handle_names(char **parameters, int pcnt, userrec *user) c = FindChan(parameters[0]); if (c) { - if (((c) && (!has_channel(user,c))) && (c->secret)) + 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); return; @@ -618,12 +606,12 @@ void handle_privmsg(char **parameters, int pcnt, userrec *user) chan = FindChan(parameters[0]); if (chan) { - if ((chan->noexternal) && (!has_channel(user,chan))) + if ((chan->binarymodes & CM_NOEXTERNAL) && (!has_channel(user,chan))) { WriteServ(user->fd,"404 %s %s :Cannot send to channel (no external messages)", user->nick, chan->name); return; } - if ((chan->moderated) && (cstatus(user,chan)binarymodes & CM_MODERATED) && (cstatus(user,chan)fd,"404 %s %s :Cannot send to channel (+m)", user->nick, chan->name); return; @@ -637,6 +625,12 @@ void handle_privmsg(char **parameters, int pcnt, userrec *user) return; } parameters[1] = (char*)temp.c_str(); + + if (temp == "") + { + WriteServ(user->fd,"412 %s No text to send", user->nick); + return; + } ChanExceptSender(chan, user, "PRIVMSG %s :%s", chan->name, parameters[1]); @@ -706,12 +700,12 @@ void handle_notice(char **parameters, int pcnt, userrec *user) chan = FindChan(parameters[0]); if (chan) { - if ((chan->noexternal) && (!has_channel(user,chan))) + if ((chan->binarymodes & CM_NOEXTERNAL) && (!has_channel(user,chan))) { WriteServ(user->fd,"404 %s %s :Cannot send to channel (no external messages)", user->nick, chan->name); return; } - if ((chan->moderated) && (cstatus(user,chan)binarymodes & CM_MODERATED) && (cstatus(user,chan)fd,"404 %s %s :Cannot send to channel (+m)", user->nick, chan->name); return; @@ -726,6 +720,12 @@ void handle_notice(char **parameters, int pcnt, userrec *user) } parameters[1] = (char*)temp.c_str(); + if (temp == "") + { + WriteServ(user->fd,"412 %s No text to send", user->nick); + return; + } + ChanExceptSender(chan, user, "NOTICE %s :%s", chan->name, parameters[1]); // if any users of this channel are on remote servers, broadcast the packet @@ -843,11 +843,12 @@ void handle_whois(char **parameters, int pcnt, userrec *user) 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",user->nick, dest->nick, dest->host); + WriteServ(user->fd,"378 %s %s :is connecting from *@%s %s",user->nick, dest->nick, dest->host, dest->ip); } - if (strcmp(chlist(dest),"")) + char* cl = chlist(dest,user); + if (strcmp(cl,"")) { - WriteServ(user->fd,"319 %s %s :%s",user->nick, dest->nick, chlist(dest)); + WriteServ(user->fd,"319 %s %s :%s",user->nick, dest->nick, cl); } WriteServ(user->fd,"312 %s %s %s :%s",user->nick, dest->nick, dest->server, GetServerDescription(dest->server).c_str()); if (strcmp(dest->awaymsg,"")) @@ -871,12 +872,14 @@ void handle_whois(char **parameters, int pcnt, userrec *user) 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]); } } 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]); } } @@ -928,8 +931,27 @@ 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) { - shutdown(user->fd,2); - close(user->fd); +#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 + shutdown(user->fd,2); + close(user->fd); } if (iter != clientlist.end()) @@ -940,6 +962,8 @@ void handle_quit(char **parameters, int pcnt, userrec *user) if (user->registered == 7) { purge_empty_chans(user); } + if (user->fd > -1) + fd_ref_table[user->fd] = NULL; delete user; } @@ -965,11 +989,11 @@ void handle_who(char **parameters, int pcnt, userrec *user) // Bug Fix #29 strcpy(tmp, ""); if (strcmp(i->second->awaymsg, "")) { - strncat(tmp, "G", 9); + strlcat(tmp, "G", 9); } else { - strncat(tmp, "H", 9); + strlcat(tmp, "H", 9); } - if (strchr(i->second->modes,'o')) { strncat(tmp, "*", 9); } + 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) @@ -999,12 +1023,12 @@ void handle_who(char **parameters, int pcnt, userrec *user) // Fix Bug #29 - Part 2.. strcpy(tmp, ""); if (strcmp(i->second->awaymsg, "")) { - strncat(tmp, "G", 9); + strlcat(tmp, "G", 9); } else { - strncat(tmp, "H", 9); + strlcat(tmp, "H", 9); } - if (strchr(i->second->modes,'o')) { strncat(tmp, "*", 9); } - strcat(tmp, cmode(i->second, Ptr)); + if (strchr(i->second->modes,'o')) { strlcat(tmp, "*", 9); } + 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); } } @@ -1023,12 +1047,13 @@ void handle_who(char **parameters, int pcnt, userrec *user) // Bug Fix #29 -- Part 29.. strcpy(tmp, ""); if (strcmp(u->awaymsg, "")) { - strncat(tmp, "G" ,9); + strlcat(tmp, "G" ,9); } else { - strncat(tmp, "H" ,9); + strlcat(tmp, "H" ,9); } - if (strchr(u->modes,'o')) { strncat(tmp, "*" ,9); } - WriteServ(user->fd,"352 %s %s %s %s %s %s %s :0 %s",user->nick, u->nick, u->ident, u->dhost, u->server, u->nick, tmp, u->fullname); + 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 + : "*", 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]); } @@ -1037,24 +1062,19 @@ void handle_who(char **parameters, int pcnt, userrec *user) { if ((!strcmp(parameters[0],"0")) || (!strcmp(parameters[0],"*")) && (!strcmp(parameters[1],"o"))) { - for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++) + for (std::vector::iterator i = all_opers.begin(); i != all_opers.end(); i++) { - if ((common_channels(user,i->second)) && (isnick(i->second->nick))) - { - if (strchr(i->second->modes,'o')) - { - // If i were a rich man.. I wouldn't need to me making these bugfixes.. - // But i'm a poor bastard with nothing better to do. - strcpy(tmp, ""); - if (strcmp(i->second->awaymsg, "")) { - strncat(tmp, "G" ,9); - } else { - strncat(tmp, "H" ,9); - } - - WriteServ(user->fd,"352 %s %s %s %s %s %s %s* :0 %s",user->nick, user->nick, i->second->ident, i->second->dhost, i->second->server, i->second->nick, tmp, i->second->fullname); - } - } + // If i were a rich man.. I wouldn't need to me making these bugfixes.. + // But i'm a poor bastard with nothing better to do. + userrec* oper = *i; + strcpy(tmp, ""); + if (strcmp(oper->awaymsg, "")) { + strlcat(tmp, "G" ,9); + } 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 + : "*", 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]); return; @@ -1072,7 +1092,8 @@ void handle_list(char **parameters, int pcnt, userrec *user) WriteServ(user->fd,"321 %s Channel :Users Name",user->nick); for (chan_hash::const_iterator i = chanlist.begin(); i != chanlist.end(); i++) { - if ((!i->second->c_private) && (!i->second->secret)) + // if the channel is not private/secret, OR the user is on the channel anyway + if (((!(i->second->binarymodes & CM_PRIVATE)) && (!(i->second->binarymodes & CM_SECRET))) || (has_channel(user,i->second))) { WriteServ(user->fd,"322 %s %s %d :[+%s] %s",user->nick,i->second->name,usercount_i(i->second),chanmodes(i->second),i->second->topic); } @@ -1215,7 +1236,7 @@ void handle_away(char **parameters, int pcnt, userrec *user) void handle_whowas(char **parameters, int pcnt, userrec* user) { - user_hash::iterator i = whowas.find(parameters[0]); + whowas_hash::iterator i = whowas.find(parameters[0]); if (i == whowas.end()) { @@ -1292,6 +1313,7 @@ void handle_modules(char **parameters, int pcnt, userrec *user) WriteServ(user->fd,"900 %s :%s",user->nick,CleanFilename(modulename)); } } + WriteServ(user->fd,"901 %s :End of MODULES list",user->nick); } void handle_stats(char **parameters, int pcnt, userrec *user) @@ -1411,6 +1433,7 @@ void handle_stats(char **parameters, int pcnt, userrec *user) /* stats z (debug and memory info) */ if (*parameters[0] == 'z') { + rusage R; 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)); @@ -1419,6 +1442,24 @@ void handle_stats(char **parameters, int pcnt, userrec *user) 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)); WriteServ(user->fd,"249 %s :Ports(STATIC_ARRAY) %d",user->nick,boundPortCount); + if (!getrusage(RUSAGE_SELF,&R)) + { + WriteServ(user->fd,"249 %s :Total allocation: %luK (0x%lx)",user->nick,R.ru_maxrss,R.ru_maxrss); + WriteServ(user->fd,"249 %s :Signals: %lu (0x%lx)",user->nick,R.ru_nsignals,R.ru_nsignals); + WriteServ(user->fd,"249 %s :Page faults: %lu (0x%lx)",user->nick,R.ru_majflt,R.ru_majflt); + WriteServ(user->fd,"249 %s :Swaps: %lu (0x%lx)",user->nick,R.ru_nswap,R.ru_nswap); + WriteServ(user->fd,"249 %s :Context Switches: %lu (0x%lx)",user->nick,R.ru_nvcsw+R.ru_nivcsw,R.ru_nvcsw+R.ru_nivcsw); + } + } + + 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)); } /* stats o */ @@ -1551,6 +1592,7 @@ void handle_squit(char **parameters, int pcnt, userrec *user) } bool have_this_server = true; int n_count = 0; + std::string server_to_squit = ""; while (have_this_server) { have_this_server = false; @@ -1564,6 +1606,7 @@ void handle_squit(char **parameters, int pcnt, userrec *user) { // found a valid ircd_connector. have_this_server = true; + server_to_squit = me[j]->connectors[x].GetServerName().c_str(); break; } } @@ -1571,12 +1614,12 @@ void handle_squit(char **parameters, int pcnt, userrec *user) } if (have_this_server) { - WriteOpers("SQUIT command issued by %s to remove %s from the mesh",user->nick,parameters[0]); - WriteServ(user->fd,"NOTICE %s :*** Removing remote server %s.",user->nick,parameters[0]); + WriteOpers("SQUIT command issued by %s to remove %s from the mesh",user->nick,server_to_squit.c_str()); + WriteServ(user->fd,"NOTICE %s :*** Removing remote server %s.",user->nick,server_to_squit.c_str()); char buffer[MAXBUF]; - snprintf(buffer,MAXBUF,"& %s",parameters[0]); + snprintf(buffer,MAXBUF,"& %s",server_to_squit.c_str()); NetSendToAll(buffer); - DoSplit(parameters[0]); + DoSplit(server_to_squit.c_str()); n_count++; } } @@ -1628,6 +1671,10 @@ void handle_map(char **parameters, int pcnt, userrec *user) bool is_uline(const char* server) { + if (!server) + return false; + if (!(*server)) + return true; char ServName[MAXBUF]; for (int i = 0; i < ConfValueEnum("uline",&config_f); i++) { @@ -1842,36 +1889,67 @@ void handle_nick(char **parameters, int pcnt, userrec *user) } -void handle_v(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_v(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { char* servername = strtok(params," "); char* versionstr = strtok(NULL,"\r\n"); - ircd_connector* cn = reply->FindHost(servername); - cn->SetVersionString(versionstr); + + if ((!servername) || (!versionstr)) + return; + + for (int j = 0; j < 32; j++) + { + if (me[j] != NULL) + { + for (int x = 0; x < me[j]->connectors.size(); x++) + { + if (!strcasecmp(me[j]->connectors[x].GetServerName().c_str(),servername)) + { + me[j]->connectors[x].SetVersionString(versionstr); + WriteOpers("Server '%s' (%d:%d) announces itself as version '%s'",me[j]->connectors[x].GetServerName().c_str(),j,x,me[j]->connectors[x].GetVersionString().c_str()); + } + } + } + } } -void handle_V(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_V(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { char* src = strtok(params," "); char* dest = strtok(NULL," :"); char* text = strtok(NULL,"\r\n"); + + if ((!src) || (!dest) || (!text)) + return; + text++; userrec* user = Find(src); if (user) { - userrec* dst = Find(dest); - - if (dst) + // notice all - only issuable by a server + if (!strcmp(dest,"*")) + { + NoticeAll(user,true,"%s",text); + } + if (!strcmp(dest,"@*")) { - WriteTo(user, dst, "NOTICE %s :%s", dst->nick, text); + NoticeAllOpers(user,true,"%s",text); } else { - chanrec* d = FindChan(dest); - if (d) + userrec* dst = Find(dest); + if (dst) { - ChanExceptSender(d, user, "NOTICE %s :%s", d->name, text); + WriteTo(user, dst, "NOTICE %s :%s", dst->nick, text); + } + else + { + chanrec* d = FindChan(dest); + if (d) + { + ChanExceptSender(d, user, "NOTICE %s :%s", d->name, text); + } } } } @@ -1879,11 +1957,15 @@ void handle_V(char token,char* params,serverrec* source,serverrec* reply, char* } -void handle_P(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_P(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { char* src = strtok(params," "); char* dest = strtok(NULL," :"); char* text = strtok(NULL,"\r\n"); + + if ((!src) || (!dest) || (!text)) + return; + text++; userrec* user = Find(src); @@ -1907,11 +1989,15 @@ void handle_P(char token,char* params,serverrec* source,serverrec* reply, char* } -void handle_i(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_i(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { char* nick = strtok(params," "); char* from = strtok(NULL," "); char* channel = strtok(NULL," "); + + if ((!nick) || (!from) || (!channel)) + return; + userrec* u = Find(nick); userrec* user = Find(from); chanrec* c = FindChan(channel); @@ -1922,11 +2008,15 @@ void handle_i(char token,char* params,serverrec* source,serverrec* reply, char* } } -void handle_t(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_t(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { char* setby = strtok(params," "); char* channel = strtok(NULL," :"); char* topic = strtok(NULL,"\r\n"); + + if ((!setby) || (!channel) || (!topic)) + return; + topic++; userrec* u = Find(setby); chanrec* c = FindChan(channel); @@ -1940,12 +2030,16 @@ void handle_t(char token,char* params,serverrec* source,serverrec* reply, char* } -void handle_T(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_T(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { char* tm = strtok(params," "); char* setby = strtok(NULL," "); char* channel = strtok(NULL," :"); char* topic = strtok(NULL,"\r\n"); + + if ((!tm) || (!setby) || (!channel) || (!topic)) + return; + topic++; time_t TS = atoi(tm); chanrec* c = FindChan(channel); @@ -1961,13 +2055,17 @@ void handle_T(char token,char* params,serverrec* source,serverrec* reply, char* } } -void handle_M(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_M(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { char* pars[128]; char original[MAXBUF],target[MAXBUF]; strlcpy(original,params,MAXBUF); int index = 0; char* parameter = strtok(params," "); + + if (!parameter) + return; + strlcpy(target,parameter,MAXBUF); while (parameter) { @@ -1976,25 +2074,31 @@ void handle_M(char token,char* params,serverrec* source,serverrec* reply, char* pars[index++] = parameter; parameter = strtok(NULL," "); } - log(DEBUG,"*** MODE: %s %s",pars[0],pars[1]); + log(DEBUG,"*** MODE: '%s %s'",pars[0],pars[1]); merge_mode(pars,index); if (FindChan(target)) { WriteChannelLocal(FindChan(target), NULL, "MODE %s",original); + return; } if (Find(target)) { - Write(Find(target)->fd,":%s MODE %s",ServerName,original); + if (original[0]) + Write(Find(target)->fd,":%s MODE %s",ServerName,original); } } // m is modes set by users only (not servers) valid targets are channels or users. -void handle_m(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_m(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { // m blah #chatspike +b *!test@*4 char* pars[128]; char original[MAXBUF]; + + if (!params) + return; + strlcpy(original,params,MAXBUF); if (!strchr(params,' ')) @@ -2006,6 +2110,10 @@ void handle_m(char token,char* params,serverrec* source,serverrec* reply, char* int index = 0; char* src = strtok(params," "); + + if (!src) + return; + userrec* user = Find(src); if (user) @@ -2019,12 +2127,13 @@ void handle_m(char token,char* params,serverrec* source,serverrec* reply, char* } log(DEBUG,"Calling merge_mode2"); - merge_mode2(pars,index,user); + if (index) + merge_mode2(pars,index,user); } } -void handle_L(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_L(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { char* nick = NULL; char* channel = NULL; @@ -2034,6 +2143,8 @@ void handle_L(char token,char* params,serverrec* source,serverrec* reply, char* { nick = strtok(params," "); channel = strtok(NULL,"\r\n"); + if ((!nick) || (!channel)) + return; channel++; reason = ""; } @@ -2042,6 +2153,8 @@ void handle_L(char token,char* params,serverrec* source,serverrec* reply, char* nick = strtok(params," "); channel = strtok(NULL," :"); reason = strtok(NULL,"\r\n"); + if ((!nick) || (!channel) || (!reason)) + return; reason++; } userrec* user = Find(nick); @@ -2058,11 +2171,13 @@ void handle_L(char token,char* params,serverrec* source,serverrec* reply, char* } } -void handle_K(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_K(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { char* src = strtok(params," "); char* nick = strtok(NULL," :"); char* reason = strtok(NULL,"\r\n"); + if ((!src) || (!nick) || (!reason)) + return; char kreason[MAXBUF]; reason++; @@ -2071,17 +2186,20 @@ void handle_K(char token,char* params,serverrec* source,serverrec* reply, char* if ((user) && (u)) { - WriteTo(user, u, "KILL %s :%s!%s!%s!%s (%s)", u->nick, source->name, ServerName, user->dhost,user->nick,reason); - WriteOpers("*** Remote kill from %s by %s: %s!%s@%s (%s)",source->name,user->nick,u->nick,u->ident,u->host,reason); - snprintf(kreason,MAXBUF,"[%s] Killed (From: '%s' (%s))",source->name,user->nick,reason); + WriteTo(user, u, "KILL %s :%s!%s!%s!%s (%s)", u->nick, tcp_host, ServerName, user->dhost,user->nick,reason); + WriteOpers("*** Remote kill from %s by %s: %s!%s@%s (%s)",tcp_host,user->nick,u->nick,u->ident,u->host,reason); + snprintf(kreason,MAXBUF,"[%s] Killed (From: '%s' (%s))",tcp_host,user->nick,reason); kill_link(u,kreason); } } -void handle_Q(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_Q(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { char* nick = strtok(params," :"); char* reason = strtok(NULL,"\r\n"); + + if ((!nick) || (!reason)) + return; reason++; userrec* user = Find(nick); @@ -2112,10 +2230,13 @@ void handle_Q(char token,char* params,serverrec* source,serverrec* reply, char* } } -void handle_n(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_n(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { char* oldnick = strtok(params," "); char* newnick = strtok(NULL," "); + + if ((!oldnick) || (!newnick)) + return; userrec* user = Find(oldnick); @@ -2127,11 +2248,13 @@ void handle_n(char token,char* params,serverrec* source,serverrec* reply, char* FOREACH_RESULT(OnUserPreNick(user,newnick)); if (MOD_RESULT) { // if a module returns true, the nick change couldnt be allowed + statsCollisions++; kill_link(user,"Nickname collision"); return; } if (matches_qline(newnick)) { + statsCollisions++; kill_link(user,"Nickname collision"); return; } @@ -2139,7 +2262,7 @@ void handle_n(char token,char* params,serverrec* source,serverrec* reply, char* // broadcast this because its a services thingy char buffer[MAXBUF]; snprintf(buffer,MAXBUF,"n %s %s",user->nick,newnick); - NetSendToAllExcept(tcp_host,buffer); + NetSendToAllExcept_WithSum(tcp_host,buffer,tcp_sum); } WriteCommon(user,"NICK %s",newnick); user = ReHashNick(user->nick, newnick); @@ -2151,12 +2274,16 @@ void handle_n(char token,char* params,serverrec* source,serverrec* reply, char* } // k : -void handle_k(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_k(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { char* src = strtok(params," "); char* dest = strtok(NULL," "); char* channel = strtok(NULL," :"); char* reason = strtok(NULL,"\r\n"); + + if ((!src) || (!dest) || (!channel) || (!reason)) + return; + reason++; userrec* s = Find(src); userrec* d = Find(dest); @@ -2175,10 +2302,14 @@ void handle_k(char token,char* params,serverrec* source,serverrec* reply, char* } } -void handle_AT(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_AT(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { char* who = strtok(params," :"); char* text = strtok(NULL,"\r\n"); + + if ((!who) || (!text)) + return; + text++; userrec* s = Find(who); if (s) @@ -2187,11 +2318,15 @@ void handle_AT(char token,char* params,serverrec* source,serverrec* reply, char* } } -void handle_H(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_H(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { log(DEBUG,"Adding ULined server %s to my map",params); ircd_connector s; s.SetState(STATE_DISCONNECTED); + + if (!params) + return; + s.SetServerName(params); for (int j = 0; j < 32; j++) @@ -2214,7 +2349,7 @@ void handle_H(char token,char* params,serverrec* source,serverrec* reply, char* WriteOpers("Non-Mesh server %s has joined the network",params); } -void handle_N(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_N(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { char* tm = strtok(params," "); char* nick = strtok(NULL," "); @@ -2225,13 +2360,22 @@ void handle_N(char token,char* params,serverrec* source,serverrec* reply, char* char* ipaddr = strtok(NULL," "); char* server = strtok(NULL," :"); char* gecos = strtok(NULL,"\r\n"); - gecos++; - modes++; + + if ((!tm) || (!nick) || (!host) || (!dhost) || (!ident) || (!modes) || (!ipaddr) || (!server) || (!gecos)) + return; + + if (*gecos == ':') + gecos++; + + if (*modes == '+') + modes++; + time_t TS = atoi(tm); user_hash::iterator iter = clientlist.find(nick); if (iter != clientlist.end()) { // nick collision + statsCollisions++; WriteOpers("Nickname collision: %s@%s != %s@%s",nick,server,iter->second->nick,iter->second->server); char str[MAXBUF]; snprintf(str,MAXBUF,"Killed (Nick Collision (%s@%s < %s@%s))",nick,server,iter->second->nick,iter->second->server); @@ -2249,7 +2393,7 @@ void handle_N(char token,char* params,serverrec* source,serverrec* reply, char* strlcpy(clientlist[nick]->server, server,256); strlcpy(clientlist[nick]->ident, ident,10); // +1 char to compensate for tilde strlcpy(clientlist[nick]->fullname, gecos,128); - strlcpy(clientlist[nick]->ip,ipaddr,32); + strlcpy(clientlist[nick]->ip,ipaddr,16); clientlist[nick]->signon = TS; clientlist[nick]->nping = 0; // this is ignored for a remote user anyway. clientlist[nick]->lastping = 1; @@ -2268,17 +2412,22 @@ void handle_N(char token,char* params,serverrec* source,serverrec* reply, char* } } -void handle_F(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_F(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { + if (!params) + return; long tdiff = TIME - atoi(params); if (tdiff) WriteOpers("TS split for %s -> %s: %d",source->name,reply->name,tdiff); } -void handle_a(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_a(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { char* nick = strtok(params," :"); char* gecos = strtok(NULL,"\r\n"); + + if ((!nick) || (!gecos)) + return; userrec* user = Find(nick); @@ -2286,10 +2435,13 @@ void handle_a(char token,char* params,serverrec* source,serverrec* reply, char* strlcpy(user->fullname,gecos,MAXBUF); } -void handle_b(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_b(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { char* nick = strtok(params," "); char* host = strtok(NULL," "); + + if ((!nick) || (!host)) + return; userrec* user = Find(nick); @@ -2297,7 +2449,7 @@ void handle_b(char token,char* params,serverrec* source,serverrec* reply, char* strlcpy(user->dhost,host,160); } -void handle_plus(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_plus(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { // %s %s %d %d // + test3.chatspike.net 7010 -2016508415 @@ -2305,6 +2457,10 @@ void handle_plus(char token,char* params,serverrec* source,serverrec* reply, cha char* ipaddr = strtok(NULL," "); char* ipport = strtok(NULL," "); char* cookie = strtok(NULL," "); + + if ((!servername) || (!ipaddr) || (!ipport) || (!cookie)) + return; + log(DEBUG,"*** Connecting back to %s:%d",ipaddr,atoi(ipport)); @@ -2330,10 +2486,11 @@ void handle_plus(char token,char* params,serverrec* source,serverrec* reply, cha me[defaultRoute]->MeshCookie(ipaddr,atoi(ipport),atoi(cookie),servername); } -void handle_R(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_R(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { char* server = strtok(params," "); char* data = strtok(NULL,"\r\n"); + if ((!data) || (!server)) { log(DEBUG,"Someones playing silly buggers, attempting to send to a null server or send a null message (BUG?)"); @@ -2344,14 +2501,16 @@ void handle_R(char token,char* params,serverrec* source,serverrec* reply, char* NetSendToOne(server,data); } -void handle_J(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_J(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { - // IMPORTANT NOTE - // The J token currently has no timestamp - this needs looking at - // because it will allow splitriding. char* nick = strtok(params," "); char* channel = strtok(NULL," "); + + if ((!nick) || (!channel)) + return; + userrec* user = Find(nick); + while (channel) { if ((user != NULL) && (strcmp(channel,""))) @@ -2396,11 +2555,15 @@ void handle_J(char token,char* params,serverrec* source,serverrec* reply, char* } } -void handle_dollar(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_dollar(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { log(DEBUG,"Storing routing table..."); char* sourceserver = strtok(params," "); char* server = strtok(NULL," "); + + if ((!sourceserver) || (!server)) + return; + for (int i = 0; i < 32; i++) { if (me[i] != NULL) @@ -2426,8 +2589,11 @@ void handle_dollar(char token,char* params,serverrec* source,serverrec* reply, c log(DEBUG,"Warning! routing table received from nonexistent server!"); } -void handle_amp(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_amp(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { + if (!params) + return; + log(DEBUG,"Netsplit! %s split from mesh, removing!",params); WriteOpers("*** NOTICE - Controlled netsplit: %s split from %s",params,ServerName); bool go_again = true; @@ -2476,7 +2642,7 @@ void handle_amp(char token,char* params,serverrec* source,serverrec* reply, char unsigned long authcookie; -void handle_hash(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_hash(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { // # : log(DEBUG,"Adding G-line"); @@ -2485,6 +2651,10 @@ void handle_hash(char token,char* params,serverrec* source,serverrec* reply, cha char* create_time = strtok(NULL," "); char* duration = strtok(NULL," :"); char* reason = strtok(NULL,"\r\n"); + + if ((!mask) || (!who) || (!create_time) || (!duration) || (!reason)) + return; + reason++; add_gline(atoi(duration),(const char*)who,(const char*)reason,(const char*)mask); // we must update the creation time on this gline @@ -2501,11 +2671,15 @@ void handle_hash(char token,char* params,serverrec* source,serverrec* reply, cha apply_lines(); } -void handle_dot(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_dot(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { log(DEBUG,"Removing G-line"); char* mask = strtok(params," "); char* who = strtok(NULL," "); + + if ((!mask) || (!who)) + return; + if (mask) { if (del_gline((const char*)mask)) @@ -2518,7 +2692,7 @@ void handle_dot(char token,char* params,serverrec* source,serverrec* reply, char } } -void handle_add_sqline(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_add_sqline(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { // { : log(DEBUG,"Adding Q-line"); @@ -2527,6 +2701,10 @@ void handle_add_sqline(char token,char* params,serverrec* source,serverrec* repl char* create_time = strtok(NULL," "); char* duration = strtok(NULL," :"); char* reason = strtok(NULL,"\r\n"); + + if ((!mask) || (!who) || (!create_time) || (!duration) || (!reason)) + return; + reason++; add_qline(atoi(duration),(const char*)who,(const char*)reason,(const char*)mask); // we must update the creation time on this gline @@ -2544,11 +2722,15 @@ void handle_add_sqline(char token,char* params,serverrec* source,serverrec* repl apply_lines(); } -void handle_del_sqline(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_del_sqline(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { log(DEBUG,"Removing Q-line"); char* mask = strtok(params," "); char* who = strtok(NULL," "); + + if ((!mask) || (!who)) + return; + if (mask) { if (del_qline((const char*)mask)) @@ -2561,7 +2743,7 @@ void handle_del_sqline(char token,char* params,serverrec* source,serverrec* repl } } -void handle_add_szline(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_add_szline(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { // } : log(DEBUG,"Adding Z-line"); @@ -2570,6 +2752,10 @@ void handle_add_szline(char token,char* params,serverrec* source,serverrec* repl char* create_time = strtok(NULL," "); char* duration = strtok(NULL," :"); char* reason = strtok(NULL,"\r\n"); + + if ((!mask) || (!who) || (!create_time) || (!duration) || (!reason)) + return; + reason++; add_zline(atoi(duration),(const char*)who,(const char*)reason,(const char*)mask); // we must update the creation time on this gline @@ -2587,11 +2773,15 @@ void handle_add_szline(char token,char* params,serverrec* source,serverrec* repl apply_lines(); } -void handle_del_szline(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_del_szline(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { log(DEBUG,"Removing Z-line"); char* mask = strtok(params," "); char* who = strtok(NULL," "); + + if ((!mask) || (!who)) + return; + if (mask) { if (del_zline((const char*)mask)) @@ -2604,10 +2794,14 @@ void handle_del_szline(char token,char* params,serverrec* source,serverrec* repl } } -void handle_pipe(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +void handle_pipe(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum) { char* nick = strtok(params," "); char* type = strtok(params," "); + + if ((!nick) || (!type)) + return; + userrec* u = Find(nick); if (u) { @@ -2616,7 +2810,7 @@ void handle_pipe(char token,char* params,serverrec* source,serverrec* reply, cha } -void process_restricted_commands(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host,char* ipaddr,int port) +void process_restricted_commands(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host,char* ipaddr,int port,char* tcp_sum) { char buffer[MAXBUF]; int MOD_RESULT = 0; @@ -2632,7 +2826,7 @@ void process_restricted_commands(char token,char* params,serverrec* source,serve // except the newcomer. They'll all attempt to connect back to it. authcookie = rand()*rand(); snprintf(buffer,MAXBUF,"~ %lu",(unsigned long)authcookie); - NetSendToAll(buffer); + NetSendToAll_WithSum(buffer,tcp_sum); break; // ~ // Store authcookie @@ -2644,22 +2838,22 @@ void process_restricted_commands(char token,char* params,serverrec* source,serve break; // connect back to a server using an authcookie case '+': - handle_plus(token,params,source,reply,tcp_host); + handle_plus(token,params,source,reply,tcp_host,tcp_sum); break; // routing table case '$': - handle_dollar(token,params,source,reply,tcp_host); + handle_dollar(token,params,source,reply,tcp_host,tcp_sum); break; // node unreachable - we cant route to a server, sooooo we slit it off. // servers can generate these for themselves for an squit. case '&': - handle_amp(token,params,source,reply,tcp_host); + handle_amp(token,params,source,reply,tcp_host,tcp_sum); break; // R // redirect token, send all of along to the given // server as this server has been found to still have a route to it case 'R': - handle_R(token,params,source,reply,tcp_host); + handle_R(token,params,source,reply,tcp_host,tcp_sum); break; // ? // ping @@ -2674,147 +2868,150 @@ void process_restricted_commands(char token,char* params,serverrec* source,serve // no operation case '*': break; + // no operation - reserved to prevent services issues + case ':': + break; // N : // introduce remote client case 'N': - handle_N(token,params,source,reply,tcp_host); + handle_N(token,params,source,reply,tcp_host,tcp_sum); break; // a : // change GECOS (SETNAME) case 'a': - handle_a(token,params,source,reply,tcp_host); + handle_a(token,params,source,reply,tcp_host,tcp_sum); break; // b : // change displayed host (SETHOST) case 'b': - handle_b(token,params,source,reply,tcp_host); + handle_b(token,params,source,reply,tcp_host,tcp_sum); break; // t : // change a channel topic case 't': - handle_t(token,params,source,reply,tcp_host); + handle_t(token,params,source,reply,tcp_host,tcp_sum); break; // i // invite a user to a channel case 'i': - handle_i(token,params,source,reply,tcp_host); + handle_i(token,params,source,reply,tcp_host,tcp_sum); break; // k : // kick a user from a channel case 'k': - handle_k(token,params,source,reply,tcp_host); + handle_k(token,params,source,reply,tcp_host,tcp_sum); break; // n // change nickname of client -- a server should only be able to // change the nicknames of clients that reside on it unless // they are ulined. case 'n': - handle_n(token,params,source,reply,tcp_host); + handle_n(token,params,source,reply,tcp_host,tcp_sum); break; // J // Join user to channel list, merge channel permissions case 'J': - handle_J(token,params,source,reply,tcp_host); + handle_J(token,params,source,reply,tcp_host,tcp_sum); break; // T : // change channel topic (netburst only) case 'T': - handle_T(token,params,source,reply,tcp_host); + handle_T(token,params,source,reply,tcp_host,tcp_sum); break; // M [MODE-PARAMETERS] // Server setting modes on an object case 'M': - handle_M(token,params,source,reply,tcp_host); + handle_M(token,params,source,reply,tcp_host,tcp_sum); break; // m [MODE-PARAMETERS] // User setting modes on an object case 'm': - handle_m(token,params,source,reply,tcp_host); + handle_m(token,params,source,reply,tcp_host,tcp_sum); break; // P : // Send a private/channel message case 'P': - handle_P(token,params,source,reply,tcp_host); + handle_P(token,params,source,reply,tcp_host,tcp_sum); break; // V : // Send a private/channel notice case 'V': - handle_V(token,params,source,reply,tcp_host); + handle_V(token,params,source,reply,tcp_host,tcp_sum); break; // v case 'v': - handle_v(token,params,source,reply,tcp_host); + handle_v(token,params,source,reply,tcp_host,tcp_sum); break; // L : // User parting a channel case 'L': - handle_L(token,params,source,reply,tcp_host); + handle_L(token,params,source,reply,tcp_host,tcp_sum); break; // Q : // user quitting case 'Q': - handle_Q(token,params,source,reply,tcp_host); + handle_Q(token,params,source,reply,tcp_host,tcp_sum); break; // H // introduce non-meshable server (such as a services server) case 'H': - handle_H(token,params,source,reply,tcp_host); + handle_H(token,params,source,reply,tcp_host,tcp_sum); break; // K : // remote kill case 'K': - handle_K(token,params,source,reply,tcp_host); + handle_K(token,params,source,reply,tcp_host,tcp_sum); break; // @ : // wallops case '@': - handle_AT(token,params,source,reply,tcp_host); + handle_AT(token,params,source,reply,tcp_host,tcp_sum); break; // # : // add gline case '#': - handle_hash(token,params,source,reply,tcp_host); + handle_hash(token,params,source,reply,tcp_host,tcp_sum); break; // . // remove gline case '.': - handle_dot(token,params,source,reply,tcp_host); + handle_dot(token,params,source,reply,tcp_host,tcp_sum); break; // # : // add gline case '{': - handle_add_sqline(token,params,source,reply,tcp_host); + handle_add_sqline(token,params,source,reply,tcp_host,tcp_sum); break; // . // remove gline case '[': - handle_del_sqline(token,params,source,reply,tcp_host); + handle_del_sqline(token,params,source,reply,tcp_host,tcp_sum); break; // # : // add gline case '}': - handle_add_szline(token,params,source,reply,tcp_host); + handle_add_szline(token,params,source,reply,tcp_host,tcp_sum); break; // . // remove gline case ']': - handle_del_szline(token,params,source,reply,tcp_host); + handle_del_szline(token,params,source,reply,tcp_host,tcp_sum); break; // | // set opertype case '|': - handle_pipe(token,params,source,reply,tcp_host); + handle_pipe(token,params,source,reply,tcp_host,tcp_sum); break; // F // end netburst case 'F': WriteOpers("Server %s has completed netburst. (%d secs)",tcp_host,TIME-nb_start); - handle_F(token,params,source,reply,tcp_host); + handle_F(token,params,source,reply,tcp_host,tcp_sum); nb_start = 0; // tell all the other servers to use this authcookie to connect back again // got '+ test3.chatspike.net 7010 -2016508415' from test.chatspike.net snprintf(buffer,MAXBUF,"+ %s %s %d %lu",tcp_host,ipaddr,port,(unsigned long)authcookie); - NetSendToAllExcept(tcp_host,buffer); + NetSendToAllExcept_WithSum(tcp_host,buffer,tcp_sum); break; case '/': WriteOpers("Server %s is IRCServices-based server (assumes-SVSMODE) - Nickname Services: %s",tcp_host,params); @@ -2824,12 +3021,12 @@ void process_restricted_commands(char token,char* params,serverrec* source,serve // end netburst with no mesh creation case 'f': WriteOpers("Server %s has completed netburst. (%d secs)",tcp_host,TIME-nb_start); - handle_F(token,params,source,reply,tcp_host); + handle_F(token,params,source,reply,tcp_host,tcp_sum); nb_start = 0; // tell everyone else about the new server name so they just add it in the disconnected // state snprintf(buffer,MAXBUF,"u %s :%s",tcp_host,GetServerDescription(tcp_host).c_str()); - NetSendToAllExcept(tcp_host,buffer); + NetSendToAllExcept_WithSum(tcp_host,buffer,tcp_sum); break; // X // Send netburst now @@ -2873,9 +3070,9 @@ void process_restricted_commands(char token,char* params,serverrec* source,serve } -void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) +void handle_link_packet(char* tcp_msg, char* tcp_host, serverrec *serv,char* tcp_sum) { - if ((!strncmp(udp_msg,"USER ",5)) || (!strncmp(udp_msg,"NICK ",5)) || (!strncmp(udp_msg,"PASS ",5)) || (!strncmp(udp_msg,"SERVER ",7))) + if ((!strncmp(tcp_msg,"USER ",5)) || (!strncmp(tcp_msg,"NICK ",5)) || (!strncmp(tcp_msg,"PASS ",5)) || (!strncmp(tcp_msg,"SERVER ",7))) { // a user on a server port, just close their connection. RemoveServer(tcp_host); @@ -2883,33 +3080,39 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) } char response[10240]; - char token = udp_msg[0]; - char* old = udp_msg; + char token = tcp_msg[0]; + char* old = tcp_msg; - if ((token != ':') && (strlen(udp_msg)>1) && (udp_msg[1] != ' ')) + if (!strncmp(tcp_msg,"PING",4)) { - WriteOpers("*** Discarded %d chars illegal data from %s",strlen(udp_msg),tcp_host); + // some muppet of a server is sending PING. We don't know what PING is. drop it silently. + return; + } + + if ((token != ':') && (strlen(tcp_msg)>1) && (tcp_msg[1] != ' ')) + { + WriteOpers("*** Discarded %d chars illegal data from %s",strlen(tcp_msg),tcp_host); } if (token == ':') // leading :servername or details - strip them off (services does this, sucky) { - char* src = udp_msg+1; - while (udp_msg[0] != ' ') - udp_msg++; - udp_msg[0] = 0; - udp_msg++; - char* comd = udp_msg; - while (udp_msg[0] != ' ') - udp_msg++; - udp_msg[0] = 0; - udp_msg++; + char* src = tcp_msg+1; + while (tcp_msg[0] != ' ') + tcp_msg++; + tcp_msg[0] = 0; + tcp_msg++; + char* comd = tcp_msg; + while (tcp_msg[0] != ' ') + tcp_msg++; + tcp_msg[0] = 0; + tcp_msg++; char data[MAXBUF]; char source[MAXBUF]; char command[MAXBUF]; - strlcpy(data,udp_msg,512); + strlcpy(data,tcp_msg,512); strlcpy(source,src,MAXBUF); strlcpy(command,comd,MAXBUF); - udp_msg = old; + tcp_msg = old; // unused numeric: // :services-dev.chatspike.net 433 Craig Craig :Nickname is registered to someone else @@ -2927,13 +3130,13 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) } if (!strcmp(command,"NOTICE")) { - snprintf(udp_msg,MAXBUF,"V %s %s",source,data); - log(DEBUG,"Rewrote NOTICE from services to: '%s'",udp_msg); - token = udp_msg[0]; + snprintf(tcp_msg,MAXBUF,"V %s %s",source,data); + log(DEBUG,"Rewrote NOTICE from services to: '%s'",tcp_msg); + token = tcp_msg[0]; } if (!strcmp(command,"QUIT")) { - if ((!udp_msg) || (!strcmp(data,"")) || (strcmp(data,":"))) + if ((!tcp_msg) || (!strcmp(data,"")) || (strcmp(data,":"))) { strcpy(data,":No reason"); } @@ -2941,70 +3144,70 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) { strcpy(data,":No reason"); } - snprintf(udp_msg,MAXBUF,"Q %s %s",source,data); - log(DEBUG,"Rewrote QUIT from services to: '%s'",udp_msg); - token = udp_msg[0]; + snprintf(tcp_msg,MAXBUF,"Q %s %s",source,data); + log(DEBUG,"Rewrote QUIT from services to: '%s'",tcp_msg); + token = tcp_msg[0]; } if (!strcmp(command,"SQUIT")) { - snprintf(udp_msg,MAXBUF,"& %s",source); - log(DEBUG,"Rewrote SQUIT from services to: '%s'",udp_msg); - token = udp_msg[0]; + snprintf(tcp_msg,MAXBUF,"& %s",source); + log(DEBUG,"Rewrote SQUIT from services to: '%s'",tcp_msg); + token = tcp_msg[0]; } if (!strcmp(command,"SVSMODE")) { - snprintf(udp_msg,MAXBUF,"m %s %s",source,data); - log(DEBUG,"Rewrote SVSMODE from services to: '%s'",udp_msg); - token = udp_msg[0]; + snprintf(tcp_msg,MAXBUF,"m %s %s",source,data); + log(DEBUG,"Rewrote SVSMODE from services to: '%s'",tcp_msg); + token = tcp_msg[0]; } if (!strcmp(command,"SVS2MODE")) { - snprintf(udp_msg,MAXBUF,"m %s %s",source,data); - log(DEBUG,"Rewrote SVS2MODE from services to: '%s'",udp_msg); - token = udp_msg[0]; + snprintf(tcp_msg,MAXBUF,"m %s %s",source,data); + log(DEBUG,"Rewrote SVS2MODE from services to: '%s'",tcp_msg); + token = tcp_msg[0]; } // todo: this wont work without u:lines // in give_ops etc allow nick on a u:lined serv to do just about anything if (!strcmp(command,"MODE")) { - snprintf(udp_msg,MAXBUF,"m %s %s",source,data); - log(DEBUG,"Rewrote MODE from services to: '%s'",udp_msg); - token = udp_msg[0]; + snprintf(tcp_msg,MAXBUF,"m %s %s",source,data); + log(DEBUG,"Rewrote MODE from services to: '%s'",tcp_msg); + token = tcp_msg[0]; } if (!strcmp(command,"KICK")) { - snprintf(udp_msg,MAXBUF,"k %s %s",source,data); - log(DEBUG,"Rewrote KICK from services to: '%s'",udp_msg); - token = udp_msg[0]; + snprintf(tcp_msg,MAXBUF,"k %s %s",source,data); + log(DEBUG,"Rewrote KICK from services to: '%s'",tcp_msg); + token = tcp_msg[0]; } if (!strcmp(command,"KILL")) { - snprintf(udp_msg,MAXBUF,"K %s %s",source,data); - log(DEBUG,"Rewrote KILL from services to: '%s'",udp_msg); - token = udp_msg[0]; + snprintf(tcp_msg,MAXBUF,"K %s %s",source,data); + log(DEBUG,"Rewrote KILL from services to: '%s'",tcp_msg); + token = tcp_msg[0]; } if (!strcmp(command,"SVSJOIN")) { - snprintf(udp_msg,MAXBUF,"J %s",data); - NetSendToOne(tcp_host,udp_msg); + snprintf(tcp_msg,MAXBUF,"J %s",data); + NetSendToOne(tcp_host,tcp_msg); char* nick = strtok(data," "); char* chan = strtok(NULL," "); - log(DEBUG,"Rewrote SVSJOIN from services to: '%s'",udp_msg); + log(DEBUG,"Rewrote SVSJOIN from services to: '%s'",tcp_msg); userrec* u = Find(nick); if (u) { add_channel(u,chan,"",true); } - token = udp_msg[0]; + token = tcp_msg[0]; } } - char* params = udp_msg + 2; + char* params = tcp_msg + 2; char finalparam[1024]; strcpy(finalparam," :xxxx"); - if (strstr(udp_msg," :")) { - strlcpy(finalparam,strstr(udp_msg," :"),1024); + if (strstr(tcp_msg," :")) { + strlcpy(finalparam,strstr(tcp_msg," :"),1024); } @@ -3013,6 +3216,10 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) char* servername = strtok(NULL," "); char* serverdesc = finalparam+2; + if ((!cookie) || (!servername) || (!serverdesc)) + return; + + WriteOpers("AuthCookie CONNECT from %s (%s)",servername,tcp_host); for (int u = 0; u < auth_cookies.size(); u++) @@ -3059,7 +3266,8 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) char* revision = strtok(NULL," "); char* serverdesc = finalparam+2; - password = password; + if ((!servername) || (!password) || (!myport) || (!revision) || (!serverdesc)) + return; WriteOpers("CONNECT from %s (%s) (their port: %d)",servername,tcp_host,atoi(myport)); @@ -3079,7 +3287,7 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) { WriteOpers("CONNECT aborted: Could not link to %s, is an incompatible version %s, our version is %d",servername,revision,GetRevision()); char buffer[MAXBUF]; - sprintf(buffer,"E :Version number mismatch"); + snprintf(buffer,MAXBUF,"E :Version number mismatch"); serv->SendPacket(buffer,tcp_host); RemoveServer(tcp_host); RemoveServer(servername); @@ -3118,7 +3326,7 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) { // we have a matching link line - // send a 'diminutive' server message back... - snprintf(response,10240,"s %s %s :%s",ServerName,Link_SendPass,ServerDesc); + snprintf(response,10240,"%s s %s %s :%s",CreateSum().c_str(),ServerName,Link_SendPass,ServerDesc); serv->SendPacket(response,servername); for (int t = 0; t < serv->connectors.size(); t++) @@ -3133,7 +3341,7 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) } } char buffer[MAXBUF]; - sprintf(buffer,"E :Access is denied (no matching link block)"); + snprintf(buffer,MAXBUF,"E :Access is denied (no matching link block)"); serv->SendPacket(buffer,tcp_host); WriteOpers("CONNECT from %s denied, no matching link block",servername); RemoveServer(tcp_host); @@ -3147,8 +3355,9 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) char* password = strtok(NULL," "); char* serverdesc = finalparam+2; - password = password; - + if ((!servername) || (!password) || (!serverdesc)) + return; + // TODO: we should do a check here to ensure that this server is one we recently initiated a // link with, and didnt hear an 's' or 'E' back from yet (these are the only two valid responses // to an 'S' command. If we didn't recently send an 'S' to this server, theyre trying to spoof @@ -3190,7 +3399,7 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) char buffer[MAXBUF]; me[j]->connectors[k].SetDescription(serverdesc); me[j]->connectors[k].SetState(STATE_CONNECTED); - sprintf(buffer,"X 0"); + snprintf(buffer,MAXBUF,"%s X 0",CreateSum().c_str()); serv->SendPacket(buffer,tcp_host); DoSync(me[j],tcp_host); NetSendMyRoutingTable(); @@ -3205,7 +3414,7 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) } } char buffer[MAXBUF]; - sprintf(buffer,"E :Access is denied (no matching link block)"); + snprintf(buffer,MAXBUF,"E :Access is denied (no matching link block)"); serv->SendPacket(buffer,tcp_host); WriteOpers("CONNECT from %s denied, no matching link block",servername); RemoveServer(tcp_host); @@ -3220,6 +3429,9 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) char* servername = strtok(params," "); char* password = strtok(NULL," "); char* serverdesc = finalparam+2; + + if ((!password) || (!servername) || (!serverdesc)) + return; char Link_ServerName[1024]; char Link_IPAddr[1024]; @@ -3240,7 +3452,7 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) if (!strcasecmp(me[j]->connectors[k].GetServerName().c_str(),servername)) { char buffer[MAXBUF]; - sprintf(buffer,"E :Access is denied (Server exists in the mesh)"); + snprintf(buffer,MAXBUF,"E :Access is denied (Server exists in the mesh)"); serv->SendPacket(buffer,tcp_host); WriteOpers("CONNECT from %s denied, \"%s\" already exists!",tcp_host,servername); RemoveServer(tcp_host); @@ -3278,9 +3490,9 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) me[j]->connectors[k].SetDescription(serverdesc); me[j]->connectors[k].SetServerName(servername); me[j]->connectors[k].SetState(STATE_SERVICES); - sprintf(buffer,"X 0"); + snprintf(buffer,MAXBUF,"%s X 0",CreateSum().c_str()); serv->SendPacket(buffer,servername); - sprintf(buffer,"s %s %s %lu :%s",ServerName,Link_SendPass,LinkPort,ServerDesc); + snprintf(buffer,MAXBUF,"%s s %s %s %lu :%s",CreateSum().c_str(),ServerName,Link_SendPass,LinkPort,ServerDesc); serv->SendPacket(buffer,servername); DoSync(me[j],servername); snprintf(buffer,MAXBUF,"H %s",servername); @@ -3300,7 +3512,7 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) } log(DEBUG,"No matching link block found"); char buffer[MAXBUF]; - sprintf(buffer,"E :Access is denied (no matching link block)"); + snprintf(buffer,MAXBUF,"E :Access is denied (no matching link block)"); serv->SendPacket(buffer,tcp_host); WriteOpers("CONNECT from %s denied, no matching link block",servername); RemoveServer(tcp_host); @@ -3310,6 +3522,10 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) else if (token == 'E') { char* error_message = finalparam+2; + + if (!error_message) + return; + WriteOpers("ERROR from %s: %s",tcp_host,error_message); return; } @@ -3326,7 +3542,8 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) if ((me[j]->connectors[x].GetState() == STATE_CONNECTED) || (me[j]->connectors[x].GetState() == STATE_SERVICES)) { // found a valid ircd_connector. - process_restricted_commands(token,params,me[j],serv,tcp_host,me[j]->connectors[x].GetServerIP(),me[j]->connectors[x].GetServerPort()); + if ((params) && (*params)) + process_restricted_commands(token,params,me[j],serv,tcp_host,me[j]->connectors[x].GetServerIP(),me[j]->connectors[x].GetServerPort(),tcp_sum); return; } }