X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fcommands.cpp;h=3a9399f7c5b9ae455c931710b229ab84858c23c8;hb=c2624f71e1260881610dc6109f0b3ad61ae4f31a;hp=d66c21125c654f5113cfc8c4566d6a3668a9a982;hpb=81722ff786becb636b5f5d5d92fe51bdaab65589;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/commands.cpp b/src/commands.cpp index d66c21125..3a9399f7c 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -14,15 +14,27 @@ * --------------------------------------------------- */ +using namespace std; + +#include "inspircd_config.h" #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 < cmdlist.size(); i++) + { + WriteServ(user->fd,"902 %s :%s %s %d",user->nick,cmdlist[i].command,cmdlist[i].source,cmdlist[i].min_params); + } + WriteServ(user->fd,"903 %s :End of COMMANDS list",user->nick); +} + void handle_kick(char **parameters, int pcnt, userrec *user) { chanrec* Ptr = FindChan(parameters[0]); @@ -333,13 +303,7 @@ void handle_restart(char **parameters, int pcnt, userrec *user) sleep(1); for (int i = 0; i < 65536; i++) { - int on = 1; - struct linger linger = { 0 }; - setsockopt(i, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)); - linger.l_onoff = 1; - linger.l_linger = 1; - setsockopt(i, SOL_SOCKET, SO_LINGER, (const char*)&linger,sizeof(linger)); - Blocking(i); + shutdown(i,2); close(i); } sleep(2); @@ -391,6 +355,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 +402,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 +484,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 +518,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; @@ -546,7 +528,7 @@ void handle_topic(char **parameters, int pcnt, userrec *user) strlcpy(topic,parameters[1],MAXBUF); if (strlen(topic)>MAXTOPIC) { - topic[MAXTOPIC-1] = '\0'; + topic[MAXTOPIC] = '\0'; } if (!strcasecmp(user->server,ServerName)) @@ -590,7 +572,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 +600,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 +619,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 +694,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 +714,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 +837,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 +866,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 +925,26 @@ 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 + user->CloseSocket(); } if (iter != clientlist.end()) @@ -940,6 +955,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,15 +982,18 @@ 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) + { + WriteServ(user->fd,"523 %s WHO :Command aborted: More results than configured limit",user->nick); break; + } } } } @@ -992,6 +1012,7 @@ void handle_who(char **parameters, int pcnt, userrec *user) Ptr = FindChan(parameters[0]); if (Ptr) { + int n_list = 0; for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++) { if ((has_channel(i->second,Ptr)) && (isnick(i->second->nick))) @@ -999,13 +1020,20 @@ 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); + n_list++; + if (n_list > MaxWhoResults) + { + WriteServ(user->fd,"523 %s WHO :Command aborted: More results than configured limit",user->nick); + break; + } + } } WriteServ(user->fd,"315 %s %s :End of /WHO list.",user->nick, parameters[0]); @@ -1023,12 +1051,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 +1066,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 +1096,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); } @@ -1138,8 +1163,8 @@ void handle_user(char **parameters, int pcnt, userrec *user) } else { strcpy(user->ident,"~"); /* we arent checking ident... but these days why bother anyway? */ - strlcat(user->ident,parameters[0],IDENTMAX); - strlcpy(user->fullname,parameters[3],128); + strlcat(user->ident,parameters[0],IDENTMAX+1); + strlcpy(user->fullname,parameters[3],MAXGECOS); user->registered = (user->registered | 1); } } @@ -1203,19 +1228,19 @@ void handle_away(char **parameters, int pcnt, userrec *user) { if (pcnt) { - strlcpy(user->awaymsg,parameters[0],512); + strlcpy(user->awaymsg,parameters[0],MAXAWAY); WriteServ(user->fd,"306 %s :You have been marked as being away",user->nick); } else { - strlcpy(user->awaymsg,"",512); + strlcpy(user->awaymsg,"",MAXAWAY); WriteServ(user->fd,"305 %s :You are no longer marked as being away",user->nick); } } 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()) { @@ -1412,6 +1437,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)); @@ -1420,6 +1446,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 */ @@ -1445,11 +1489,11 @@ void handle_stats(char **parameters, int pcnt, userrec *user) { if (isnick(i->second->nick)) { - WriteServ(user->fd,"211 %s :%s:%d %s %d %d %d %d",user->nick,ServerName,i->second->port,i->second->nick,i->second->bytes_in,i->second->cmds_in,i->second->bytes_out,i->second->cmds_out); + WriteServ(user->fd,"211 %s :%s:%d %s %d %d %d %d",user->nick,i->second->server,i->second->port,i->second->nick,i->second->bytes_in,i->second->cmds_in,i->second->bytes_out,i->second->cmds_out); } else { - WriteServ(user->fd,"211 %s :%s:%d (unknown@%d) %d %d %d %d",user->nick,ServerName,i->second->port,i->second->fd,i->second->bytes_in,i->second->cmds_in,i->second->bytes_out,i->second->cmds_out); + WriteServ(user->fd,"211 %s :%s:%d (unknown@%d) %d %d %d %d",user->nick,i->second->server,i->second->port,i->second->fd,i->second->bytes_in,i->second->cmds_in,i->second->bytes_out,i->second->cmds_out); } } @@ -1480,50 +1524,60 @@ void handle_stats(char **parameters, int pcnt, userrec *user) } -void handle_connect(char **parameters, int pcnt, userrec *user) + +void ConnectServer(char* servermask,userrec* user) { - char Link_ServerName[1024]; - char Link_IPAddr[1024]; - char Link_Port[1024]; - char Link_Pass[1024]; - int LinkPort; - bool found = false; + char Link_ServerName[1024]; + char Link_IPAddr[1024]; + char Link_Port[1024]; + char Link_Pass[1024]; + int LinkPort; + bool found = false; - for (int i = 0; i < ConfValueEnum("link",&config_f); i++) - { - if (!found) - { - ConfValue("link","name",i,Link_ServerName,&config_f); - ConfValue("link","ipaddr",i,Link_IPAddr,&config_f); - ConfValue("link","port",i,Link_Port,&config_f); - ConfValue("link","sendpass",i,Link_Pass,&config_f); - log(DEBUG,"(%d) Comparing against name='%s', ipaddr='%s', port='%s', recvpass='%s'",i,Link_ServerName,Link_IPAddr,Link_Port,Link_Pass); - LinkPort = atoi(Link_Port); - if (match(Link_ServerName,parameters[0])) { - found = true; - break; - } - } - } - - if (!found) { - WriteServ(user->fd,"NOTICE %s :*** Failed to connect to %s: No servers matching this pattern are configured for linking.",user->nick,parameters[0]); - return; - } - - // TODO: Perform a check here to stop a server being linked twice! + for (int i = 0; i < ConfValueEnum("link",&config_f); i++) + { + if (!found) + { + ConfValue("link","name",i,Link_ServerName,&config_f); + ConfValue("link","ipaddr",i,Link_IPAddr,&config_f); + ConfValue("link","port",i,Link_Port,&config_f); + ConfValue("link","sendpass",i,Link_Pass,&config_f); + LinkPort = atoi(Link_Port); + if (match(Link_ServerName,servermask)) { + found = true; + break; + } + } + } - WriteServ(user->fd,"NOTICE %s :*** Connecting to %s (%s) port %s...",user->nick,Link_ServerName,Link_IPAddr,Link_Port); + if (!found) { + if (user) + WriteServ(user->fd,"NOTICE %s :*** Failed to connect to %s: No servers matching this pattern are configured for linking.",user->nick,servermask); + return; + } - if (me[defaultRoute]) - { - me[defaultRoute]->BeginLink(Link_IPAddr,LinkPort,Link_Pass,Link_ServerName,me[defaultRoute]->port); - return; - } - else + if (user) { - WriteServ(user->fd,"NOTICE %s :No default route is defined for server connections on this server. You must define a server connection to be default route so that sockets can be bound to it.",user->nick); + WriteServ(user->fd,"NOTICE %s :*** Connecting to %s (%s) port %s...",user->nick,Link_ServerName,Link_IPAddr,Link_Port); } + else WriteOpers("*** Autoconnecting to %s (%s) port %s...",Link_ServerName,Link_IPAddr,Link_Port); + + if (me[defaultRoute]) + { + me[defaultRoute]->BeginLink(Link_IPAddr,LinkPort,Link_Pass,Link_ServerName,me[defaultRoute]->port); + return; + } + else + { + if (user) + WriteServ(user->fd,"NOTICE %s :No default route is defined for server connections on this server. You must define a server connection to be default route so that sockets can be bound to it.",user->nick); + } +} + + +void handle_connect(char **parameters, int pcnt, userrec *user) +{ + ConnectServer(parameters[0],user); } void handle_squit(char **parameters, int pcnt, userrec *user) @@ -1619,7 +1673,8 @@ void handle_map(char **parameters, int pcnt, userrec *user) { for (int k = 0; k < me[j]->connectors.size(); k++) { - snprintf(line,MAXBUF,"006 %s :%c-%s",user->nick,islast(me[j]->connectors[k].GetServerName().c_str()),me[j]->connectors[k].GetServerName().c_str()); + int state = me[j]->connectors[k].GetState(); + snprintf(line,MAXBUF,"006 %s :%c%s%s",user->nick,islast(me[j]->connectors[k].GetServerName().c_str()),state == STATE_NOAUTH_INBOUND || state == STATE_NOAUTH_OUTBOUND ? "-*" : "--", me[j]->connectors[k].GetServerName().c_str()); while (strlen(line) < 50) strcat(line," "); WriteServ(user->fd,"%s%d (%.2f%%)",line,map_count(me[j]->connectors[k].GetServerName().c_str()),(float)(((float)map_count(me[j]->connectors[k].GetServerName().c_str())/(float)registered_usercount())*100)); @@ -1631,6 +1686,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++) { @@ -1689,7 +1748,8 @@ void handle_oper(char **parameters, int pcnt, userrec *user) snprintf(global,MAXBUF,"| %s %s",user->nick,TypeName); NetSendToAll(global); ConfValue("type","host",j,HostName,&config_f); - ChangeDisplayedHost(user,HostName); + if (*HostName) + ChangeDisplayedHost(user,HostName); strlcpy(user->oper,TypeName,NICKMAX); found = true; fail2 = false; @@ -1845,11 +1905,14 @@ 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"); + if ((!servername) || (!versionstr)) + return; + for (int j = 0; j < 32; j++) { if (me[j] != NULL) @@ -1859,17 +1922,22 @@ void handle_v(char token,char* params,serverrec* source,serverrec* reply, char* 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); @@ -1905,11 +1973,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); @@ -1933,11 +2005,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); @@ -1948,11 +2024,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); @@ -1966,12 +2046,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); @@ -1987,13 +2071,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) { @@ -2002,25 +2090,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,' ')) @@ -2032,6 +2126,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) @@ -2045,12 +2143,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; @@ -2060,6 +2159,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 = ""; } @@ -2068,6 +2169,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); @@ -2084,11 +2187,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++; @@ -2097,17 +2202,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); @@ -2138,10 +2246,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); @@ -2153,11 +2264,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; } @@ -2165,7 +2278,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); @@ -2173,16 +2286,25 @@ void handle_n(char token,char* params,serverrec* source,serverrec* reply, char* if (!user->nick) return; strlcpy(user->nick, newnick,NICKMAX); log(DEBUG,"new nick set: %s",user->nick); + if (user->registered == 7) + { + FOREACH_MOD OnUserPostNick(user,oldnick); + } + } } // 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); @@ -2201,10 +2323,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) @@ -2213,11 +2339,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++) @@ -2240,7 +2370,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," "); @@ -2251,13 +2381,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); @@ -2272,10 +2411,10 @@ void handle_N(char token,char* params,serverrec* source,serverrec* reply, char* strlcpy(clientlist[nick]->nick, nick,NICKMAX); strlcpy(clientlist[nick]->host, host,160); strlcpy(clientlist[nick]->dhost, dhost,160); - 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); + clientlist[nick]->server = (char*)FindServerNamePtr(server); + strlcpy(clientlist[nick]->ident, ident,IDENTMAX+1); // +1 char to compensate for tilde + strlcpy(clientlist[nick]->fullname, gecos,MAXGECOS); + 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; @@ -2294,28 +2433,36 @@ 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); if (user) - strlcpy(user->fullname,gecos,MAXBUF); + strlcpy(user->fullname,gecos,MAXGECOS); } -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); @@ -2323,7 +2470,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 @@ -2331,6 +2478,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)); @@ -2356,10 +2507,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?)"); @@ -2370,14 +2522,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,""))) @@ -2422,11 +2576,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) @@ -2452,8 +2610,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; @@ -2498,11 +2659,12 @@ void handle_amp(char token,char* params,serverrec* source,serverrec* reply, char } } } + log(DEBUG,"Done with netsplit."); } 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"); @@ -2511,6 +2673,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 @@ -2527,11 +2693,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)) @@ -2544,7 +2714,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"); @@ -2553,6 +2723,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 @@ -2570,11 +2744,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)) @@ -2587,7 +2765,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"); @@ -2596,6 +2774,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 @@ -2613,11 +2795,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)) @@ -2630,10 +2816,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) { @@ -2642,11 +2832,13 @@ 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; + ircd_connector* cn = source->FindHost(tcp_host); + switch(token) { // Y @@ -2658,7 +2850,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 @@ -2670,177 +2862,183 @@ 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 case '?': - reply->SendPacket("!",tcp_host); + snprintf(buffer,MAXBUF,"%s !",CreateSum().c_str()); + reply->SendPacket(buffer,tcp_host); break; // ? // pong case '!': + if (cn) + cn->ResetPing(); break; // * // 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); @@ -2850,12 +3048,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 @@ -2899,9 +3097,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); @@ -2909,33 +3107,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 (!strncmp(tcp_msg,"PING",4)) + { + // some muppet of a server is sending PING. We don't know what PING is. drop it silently. + return; + } - if ((token != ':') && (strlen(udp_msg)>1) && (udp_msg[1] != ' ')) + if ((token != ':') && (strlen(tcp_msg)>1) && (tcp_msg[1] != ' ')) { - WriteOpers("*** Discarded %d chars illegal data from %s",strlen(udp_msg),tcp_host); + 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 @@ -2953,13 +3157,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"); } @@ -2967,70 +3171,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); } @@ -3039,6 +3243,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,6 +3267,7 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) me[j]->connectors[k].SetServerName(servername); me[j]->connectors[k].SetDescription(serverdesc); me[j]->connectors[k].SetState(STATE_CONNECTED); + AddServerName(servername); NetSendMyRoutingTable(); return; } @@ -3085,7 +3294,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)); @@ -3097,16 +3307,18 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) char buffer[MAXBUF]; snprintf(buffer,MAXBUF,"E :Server %s already exists!",servername); serv->SendPacket(buffer,tcp_host); + serv->FlushWriteBuffers(); RemoveServer(tcp_host); return; } - if (atoi(revision) != GetRevision()) + if (std::string(revision) != GetRevision()) { - WriteOpers("CONNECT aborted: Could not link to %s, is an incompatible version %s, our version is %d",servername,revision,GetRevision()); + WriteOpers("CONNECT aborted: Could not link to %s, is an incompatible version %s, our version is %s",servername,revision,GetRevision().c_str()); char buffer[MAXBUF]; - sprintf(buffer,"E :Version number mismatch"); + snprintf(buffer,MAXBUF,"E :Version number mismatch"); serv->SendPacket(buffer,tcp_host); + serv->FlushWriteBuffers(); RemoveServer(tcp_host); RemoveServer(servername); return; @@ -3122,7 +3334,6 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) } } - char Link_ServerName[1024]; char Link_IPAddr[1024]; char Link_Port[1024]; @@ -3144,7 +3355,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++) @@ -3152,6 +3363,7 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) if (!strcasecmp(serv->connectors[t].GetServerName().c_str(),servername)) { serv->connectors[t].SetState(STATE_CONNECTED); + AddServerName(servername); } } @@ -3159,8 +3371,9 @@ 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); + serv->FlushWriteBuffers(); WriteOpers("CONNECT from %s denied, no matching link block",servername); RemoveServer(tcp_host); RemoveServer(servername); @@ -3173,8 +3386,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 @@ -3216,7 +3430,8 @@ 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"); + AddServerName(servername); + snprintf(buffer,MAXBUF,"%s X 0",CreateSum().c_str()); serv->SendPacket(buffer,tcp_host); DoSync(me[j],tcp_host); NetSendMyRoutingTable(); @@ -3231,8 +3446,9 @@ 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); + serv->FlushWriteBuffers(); WriteOpers("CONNECT from %s denied, no matching link block",servername); RemoveServer(tcp_host); RemoveServer(servername); @@ -3246,6 +3462,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]; @@ -3266,8 +3485,9 @@ 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); + serv->FlushWriteBuffers(); WriteOpers("CONNECT from %s denied, \"%s\" already exists!",tcp_host,servername); RemoveServer(tcp_host); return; @@ -3304,9 +3524,10 @@ 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"); + AddServerName(servername); + 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); @@ -3326,8 +3547,9 @@ 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); + serv->FlushWriteBuffers(); WriteOpers("CONNECT from %s denied, no matching link block",servername); RemoveServer(tcp_host); RemoveServer(servername); @@ -3336,6 +3558,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; } @@ -3352,7 +3578,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; } }