diff options
Diffstat (limited to 'src/modules')
-rw-r--r-- | src/modules/extra/m_geoip.cpp | 63 | ||||
-rw-r--r-- | src/modules/m_cap.h | 9 | ||||
-rw-r--r-- | src/modules/m_check.cpp | 4 | ||||
-rw-r--r-- | src/modules/m_dnsbl.cpp | 22 | ||||
-rw-r--r-- | src/modules/m_ircv3.cpp | 214 | ||||
-rw-r--r-- | src/modules/m_namesx.cpp | 39 | ||||
-rw-r--r-- | src/modules/m_services_account.cpp | 4 | ||||
-rw-r--r-- | src/modules/m_spanningtree/main.cpp | 16 | ||||
-rw-r--r-- | src/modules/m_spanningtree/resolvers.cpp | 30 | ||||
-rw-r--r-- | src/modules/m_spanningtree/resolvers.h | 25 | ||||
-rw-r--r-- | src/modules/m_spanningtree/server.cpp | 8 | ||||
-rw-r--r-- | src/modules/m_spanningtree/treesocket1.cpp | 12 | ||||
-rw-r--r-- | src/modules/m_spanningtree/treesocket2.cpp | 13 | ||||
-rw-r--r-- | src/modules/m_spanningtree/uid.cpp | 2 | ||||
-rw-r--r-- | src/modules/m_spanningtree/utils.cpp | 79 | ||||
-rw-r--r-- | src/modules/m_stripcolor.cpp | 2 |
16 files changed, 421 insertions, 121 deletions
diff --git a/src/modules/extra/m_geoip.cpp b/src/modules/extra/m_geoip.cpp index 939752875..cf87de51e 100644 --- a/src/modules/extra/m_geoip.cpp +++ b/src/modules/extra/m_geoip.cpp @@ -35,6 +35,16 @@ class ModuleGeoIP : public Module LocalStringExt ext; GeoIP* gi; + void SetExt(LocalUser* user) + { + const char* c = GeoIP_country_code_by_addr(gi, user->GetIPString()); + if (!c) + c = "UNK"; + + std::string* cc = new std::string(c); + ext.set(user, cc); + } + public: ModuleGeoIP() : ext("geoip_cc", this), gi(NULL) { @@ -47,13 +57,23 @@ class ModuleGeoIP : public Module throw ModuleException("Unable to initialize geoip, are you missing GeoIP.dat?"); ServerInstance->Modules->AddService(ext); - Implementation eventlist[] = { I_OnSetConnectClass }; - ServerInstance->Modules->Attach(eventlist, this, 1); + Implementation eventlist[] = { I_OnSetConnectClass, I_OnStats }; + ServerInstance->Modules->Attach(eventlist, this, 2); + + for (std::vector<LocalUser*>::const_iterator i = ServerInstance->Users->local_users.begin(); i != ServerInstance->Users->local_users.end(); ++i) + { + LocalUser* user = *i; + if ((user->registered == REG_ALL) && (!ext.get(user))) + { + SetExt(user); + } + } } ~ModuleGeoIP() { - GeoIP_delete(gi); + if (gi) + GeoIP_delete(gi); } Version GetVersion() @@ -65,13 +85,8 @@ class ModuleGeoIP : public Module { std::string* cc = ext.get(user); if (!cc) - { - const char* c = GeoIP_country_code_by_addr(gi, user->GetIPString()); - if (!c) - c = "UNK"; - cc = new std::string(c); - ext.set(user, cc); - } + SetExt(user); + std::string geoip = myclass->config->getString("geoip"); if (geoip.empty()) return MOD_RES_PASSTHRU; @@ -82,6 +97,34 @@ class ModuleGeoIP : public Module return MOD_RES_PASSTHRU; return MOD_RES_DENY; } + + ModResult OnStats(char symbol, User* user, string_list &out) + { + if (symbol != 'G') + return MOD_RES_PASSTHRU; + + unsigned int unknown = 0; + std::map<std::string, unsigned int> results; + for (std::vector<LocalUser*>::const_iterator i = ServerInstance->Users->local_users.begin(); i != ServerInstance->Users->local_users.end(); ++i) + { + std::string* cc = ext.get(*i); + if (cc) + results[*cc]++; + else + unknown++; + } + + std::string p = ServerInstance->Config->ServerName + " 801 " + user->nick + " :GeoIPSTATS "; + for (std::map<std::string, unsigned int>::const_iterator i = results.begin(); i != results.end(); ++i) + { + out.push_back(p + i->first + " " + ConvToStr(i->second)); + } + + if (unknown) + out.push_back(p + "Unknown " + ConvToStr(unknown)); + + return MOD_RES_DENY; + } }; MODULE_INIT(ModuleGeoIP) diff --git a/src/modules/m_cap.h b/src/modules/m_cap.h index 0fc782b97..604fdb0ef 100644 --- a/src/modules/m_cap.h +++ b/src/modules/m_cap.h @@ -59,19 +59,16 @@ class GenericCap ext.set(data->user, 1); } } - - if (ev.id == "cap_ls") + else if (ev.id == "cap_ls") { data->wanted.push_back(cap); } - - if (ev.id == "cap_list") + else if (ev.id == "cap_list") { if (ext.get(data->user)) data->wanted.push_back(cap); } - - if (ev.id == "cap_clear") + else if (ev.id == "cap_clear") { data->ack.push_back("-" + cap); ext.set(data->user, 0); diff --git a/src/modules/m_check.cpp b/src/modules/m_check.cpp index 8316b09fe..099661de7 100644 --- a/src/modules/m_check.cpp +++ b/src/modules/m_check.cpp @@ -225,13 +225,13 @@ class CommandCheck : public Command if (InspIRCd::Match(a->second->host, parameters[0], ascii_case_insensitive_map) || InspIRCd::Match(a->second->dhost, parameters[0], ascii_case_insensitive_map)) { /* host or vhost matches mask */ - user->SendText(checkstr + " match " + ConvToStr(++x) + " " + a->second->GetFullRealHost()); + user->SendText(checkstr + " match " + ConvToStr(++x) + " " + a->second->GetFullRealHost() + " " + a->second->GetIPString() + " " + a->second->fullname); } /* IP address */ else if (InspIRCd::MatchCIDR(a->second->GetIPString(), parameters[0])) { /* same IP. */ - user->SendText(checkstr + " match " + ConvToStr(++x) + " " + a->second->GetFullRealHost()); + user->SendText(checkstr + " match " + ConvToStr(++x) + " " + a->second->GetFullRealHost() + " " + a->second->GetIPString() + " " + a->second->fullname); } } diff --git a/src/modules/m_dnsbl.cpp b/src/modules/m_dnsbl.cpp index 2160b02dc..6a41c484f 100644 --- a/src/modules/m_dnsbl.cpp +++ b/src/modules/m_dnsbl.cpp @@ -243,7 +243,7 @@ class ModuleDNSBL : public Module ReadConf(); ServerInstance->Modules->AddService(nameExt); ServerInstance->Modules->AddService(countExt); - Implementation eventlist[] = { I_OnRehash, I_OnUserInit, I_OnStats, I_OnSetConnectClass, I_OnCheckReady }; + Implementation eventlist[] = { I_OnRehash, I_OnSetClientIP, I_OnStats, I_OnSetConnectClass, I_OnCheckReady }; ServerInstance->Modules->Attach(eventlist, this, 5); } @@ -348,22 +348,24 @@ class ModuleDNSBL : public Module ReadConf(); } - void OnUserInit(LocalUser* user) + void OnSetClientIP(User* user) { - if (user->exempt) + LocalUser *luser = IS_LOCAL(user); + + if (!luser || luser->exempt) return; unsigned char a, b, c, d; char reversedipbuf[128]; std::string reversedip; - if (user->client_sa.sa.sa_family != AF_INET) + if (luser->client_sa.sa.sa_family != AF_INET) return; - d = (unsigned char) (user->client_sa.in4.sin_addr.s_addr >> 24) & 0xFF; - c = (unsigned char) (user->client_sa.in4.sin_addr.s_addr >> 16) & 0xFF; - b = (unsigned char) (user->client_sa.in4.sin_addr.s_addr >> 8) & 0xFF; - a = (unsigned char) user->client_sa.in4.sin_addr.s_addr & 0xFF; + d = (unsigned char) (luser->client_sa.in4.sin_addr.s_addr >> 24) & 0xFF; + c = (unsigned char) (luser->client_sa.in4.sin_addr.s_addr >> 16) & 0xFF; + b = (unsigned char) (luser->client_sa.in4.sin_addr.s_addr >> 8) & 0xFF; + a = (unsigned char) luser->client_sa.in4.sin_addr.s_addr & 0xFF; snprintf(reversedipbuf, 128, "%d.%d.%d.%d", d, c, b, a); reversedip = std::string(reversedipbuf); @@ -377,11 +379,11 @@ class ModuleDNSBL : public Module /* now we'd need to fire off lookups for `hostname'. */ bool cached; - DNSBLResolver *r = new DNSBLResolver(this, nameExt, countExt, hostname, user, DNSBLConfEntries[i], cached); + DNSBLResolver *r = new DNSBLResolver(this, nameExt, countExt, hostname, luser, DNSBLConfEntries[i], cached); ServerInstance->AddResolver(r, cached); i++; } - countExt.set(user, i); + countExt.set(luser, i); } ModResult OnSetConnectClass(LocalUser* user, ConnectClass* myclass) diff --git a/src/modules/m_ircv3.cpp b/src/modules/m_ircv3.cpp new file mode 100644 index 000000000..fe400fa80 --- /dev/null +++ b/src/modules/m_ircv3.cpp @@ -0,0 +1,214 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2012 Attila Molnar <attilamolnar@hush.com> + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* $ModDesc: Provides support for extended-join, away-notify and account-notify CAP capabilities */ + +#include "inspircd.h" +#include "account.h" +#include "m_cap.h" + +class ModuleIRCv3 : public Module +{ + GenericCap cap_accountnotify; + GenericCap cap_awaynotify; + GenericCap cap_extendedjoin; + bool accountnotify; + bool awaynotify; + bool extendedjoin; + + void WriteNeighboursWithExt(User* user, const std::string& line, const LocalIntExt& ext) + { + UserChanList chans(user->chans); + + std::map<User*, bool> exceptions; + FOREACH_MOD(I_OnBuildNeighborList, OnBuildNeighborList(user, chans, exceptions)); + + // Send it to all local users who were explicitly marked as neighbours by modules and have the required ext + for (std::map<User*, bool>::const_iterator i = exceptions.begin(); i != exceptions.end(); ++i) + { + LocalUser* u = IS_LOCAL(i->first); + if ((u) && (i->second) && (ext.get(u))) + u->Write(line); + } + + // Now consider sending it to all other users who has at least a common channel with the user + std::set<User*> already_sent; + for (UCListIter i = chans.begin(); i != chans.end(); ++i) + { + const UserMembList* userlist = (*i)->GetUsers(); + for (UserMembList::const_iterator m = userlist->begin(); m != userlist->end(); ++m) + { + /* + * Send the line if the channel member in question meets all of the following criteria: + * - local + * - not the user who is doing the action (i.e. whose channels we're iterating) + * - has the given extension + * - not on the except list built by modules + * - we haven't sent the line to the member yet + * + */ + LocalUser* member = IS_LOCAL(m->first); + if ((member) && (member != user) && (ext.get(member)) && (exceptions.find(member) == exceptions.end()) && (already_sent.insert(member).second)) + member->Write(line); + } + } + } + + public: + ModuleIRCv3() : cap_accountnotify(this, "account-notify"), + cap_awaynotify(this, "away-notify"), + cap_extendedjoin(this, "extended-join") + { + OnRehash(NULL); + Implementation eventlist[] = { I_OnUserJoin, I_OnSetAway, I_OnEvent }; + ServerInstance->Modules->Attach(eventlist, this, 3); + } + + void OnRehash(User* user) + { + ConfigTag* conf = ServerInstance->Config->ConfValue("ircv3"); + accountnotify = conf->getBool("accoutnotify", true); + awaynotify = conf->getBool("awaynotify", true); + extendedjoin = conf->getBool("extendedjoin", true); + } + + void OnEvent(Event& ev) + { + if (awaynotify) + cap_awaynotify.HandleEvent(ev); + if (extendedjoin) + cap_extendedjoin.HandleEvent(ev); + + if (accountnotify) + { + cap_accountnotify.HandleEvent(ev); + + if (ev.id == "account_login") + { + AccountEvent* ae = static_cast<AccountEvent*>(&ev); + + // :nick!user@host ACCOUNT account + // or + // :nick!user@host ACCOUNT * + std::string line = ":" + ae->user->GetFullHost() + " ACCOUNT "; + if (ae->account.empty()) + line += "*"; + else + line += std::string(ae->account); + + WriteNeighboursWithExt(ae->user, line, cap_accountnotify.ext); + } + } + } + + void OnUserJoin(Membership* memb, bool sync, bool created, CUList& excepts) + { + if (!extendedjoin) + return; + + /* + * Send extended joins to clients who have the extended-join capability. + * An extended join looks like this: + * + * :nick!user@host JOIN #chan account :realname + * + * account is the joining user's account if he's logged in, otherwise it's an asterisk (*). + */ + + std::string line; + std::string mode; + + const UserMembList* userlist = memb->chan->GetUsers(); + for (UserMembCIter it = userlist->begin(); it != userlist->end(); ++it) + { + // Send the extended join line if the current member is local, has the extended-join cap and isn't excepted + User* member = IS_LOCAL(it->first); + if ((member) && (cap_extendedjoin.ext.get(member)) && (excepts.find(member) == excepts.end())) + { + // Construct the lines we're going to send if we haven't constructed them already + if (line.empty()) + { + bool has_account = false; + line = ":" + memb->user->GetFullHost() + " JOIN " + memb->chan->name + " "; + const AccountExtItem* accountext = GetAccountExtItem(); + if (accountext) + { + std::string* accountname; + accountname = accountext->get(memb->user); + if (accountname) + { + line += *accountname; + has_account = true; + } + } + + if (!has_account) + line += "*"; + + line += " :" + memb->user->fullname; + + // If the joining user received privileges from another module then we must send them as well, + // since silencing the normal join means the MODE will be silenced as well + if (!memb->modes.empty()) + { + const std::string& modefrom = ServerInstance->Config->CycleHostsFromUser ? memb->user->GetFullHost() : ServerInstance->Config->ServerName; + mode = ":" + modefrom + " MODE " + memb->chan->name + " +" + memb->modes; + + for (unsigned int i = 0; i < memb->modes.length(); i++) + mode += " " + memb->user->nick; + } + } + + // Write the JOIN and the MODE, if any + member->Write(line); + if ((!mode.empty()) && (member != memb->user)) + member->Write(mode); + + // Prevent the core from sending the JOIN and MODE to this user + excepts.insert(it->first); + } + } + } + + ModResult OnSetAway(User* user, const std::string &awaymsg) + { + if (awaynotify) + { + // Going away: n!u@h AWAY :reason + // Back from away: n!u@h AWAY + std::string line = ":" + user->GetFullHost() + " AWAY"; + if (!awaymsg.empty()) + line += " :" + awaymsg; + + WriteNeighboursWithExt(user, line, cap_awaynotify.ext); + } + return MOD_RES_PASSTHRU; + } + + void Prioritize() + { + ServerInstance->Modules->SetPriority(this, I_OnUserJoin, PRIORITY_LAST); + } + + Version GetVersion() + { + return Version("Provides support for extended-join, away-notify and account-notify CAP capabilities", VF_VENDOR); + } +}; + +MODULE_INIT(ModuleIRCv3) diff --git a/src/modules/m_namesx.cpp b/src/modules/m_namesx.cpp index 1ab824388..2603b0ce5 100644 --- a/src/modules/m_namesx.cpp +++ b/src/modules/m_namesx.cpp @@ -31,8 +31,8 @@ class ModuleNamesX : public Module GenericCap cap; ModuleNamesX() : cap(this, "multi-prefix") { - Implementation eventlist[] = { I_OnPreCommand, I_OnNamesListItem, I_On005Numeric, I_OnEvent }; - ServerInstance->Modules->Attach(eventlist, this, 4); + Implementation eventlist[] = { I_OnPreCommand, I_OnNamesListItem, I_On005Numeric, I_OnEvent, I_OnSendWhoLine }; + ServerInstance->Modules->Attach(eventlist, this, 5); } @@ -81,6 +81,41 @@ class ModuleNamesX : public Module prefixes = memb->chan->GetAllPrefixChars(memb->user); } + void OnSendWhoLine(User* source, const std::vector<std::string>& params, User* user, std::string& line) + { + if (!cap.ext.get(source) || line.empty()) + return; + + std::string::size_type pos = line.find(':'); + if (pos == std::string::npos || pos < 2) + return; + pos -= 2; + // Don't do anything if the user has no prefixes + if ((line[pos] == 'H') || (line[pos] == 'G') || (line[pos] == '*')) + return; + + // 352 21DAAAAAB #chan ident localhost insp21.test 21DAAAAAB H@ :0 a + // a b pos + std::string::size_type a = 4 + source->nick.length() + 1; + std::string::size_type b = line.find(' ', a); + if (b == std::string::npos) + return; + + // Try to find this channel + std::string channame = line.substr(a, b-a); + Channel* chan = ServerInstance->FindChan(channame.c_str()); + if (!chan) + return; + + // Don't do anything if the user has only one prefix + std::string prefixes = chan->GetAllPrefixChars(user); + if (prefixes.length() <= 1) + return; + + line.erase(pos, 1); + line.insert(pos, prefixes); + } + void OnEvent(Event& ev) { cap.HandleEvent(ev); diff --git a/src/modules/m_services_account.cpp b/src/modules/m_services_account.cpp index 7f3c54907..cd34e955a 100644 --- a/src/modules/m_services_account.cpp +++ b/src/modules/m_services_account.cpp @@ -277,6 +277,10 @@ class ModuleServicesAccount : public Module AccountEvent(this, dest, *account).Send(); } + else + { + AccountEvent(this, dest, "").Send(); + } } } diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp index 1067852d1..f639a748d 100644 --- a/src/modules/m_spanningtree/main.cpp +++ b/src/modules/m_spanningtree/main.cpp @@ -765,7 +765,21 @@ void ModuleSpanningTree::OnPreRehash(User* user, const std::string ¶meter) void ModuleSpanningTree::OnRehash(User* user) { // Re-read config stuff - Utils->ReadConfiguration(); + try + { + Utils->ReadConfiguration(); + } + catch (ModuleException& e) + { + // Refresh the IP cache anyway, so servers read before the error will be allowed to connect + Utils->RefreshIPCache(); + // Always warn local opers with snomask +l, also warn globally (snomask +L) if the rehash was issued by a remote user + std::string msg = "Error in configuration: "; + msg.append(e.GetReason()); + ServerInstance->SNO->WriteToSnoMask('l', msg); + if (!IS_LOCAL(user)) + ServerInstance->PI->SendSNONotice("L", msg); + } } void ModuleSpanningTree::OnLoadModule(Module* mod) diff --git a/src/modules/m_spanningtree/resolvers.cpp b/src/modules/m_spanningtree/resolvers.cpp index ae951bd38..b69c5c29e 100644 --- a/src/modules/m_spanningtree/resolvers.cpp +++ b/src/modules/m_spanningtree/resolvers.cpp @@ -80,3 +80,33 @@ void ServernameResolver::OnError(ResolverError e, const std::string &errormessag Utils->Creator->ConnectServer(myautoconnect, false); } +SecurityIPResolver::SecurityIPResolver(Module* me, SpanningTreeUtilities* U, const std::string &hostname, Link* x, bool &cached, QueryType qt) + : Resolver(hostname, qt, cached, me), MyLink(x), Utils(U), mine(me), host(hostname), query(qt) +{ +} + +void SecurityIPResolver::OnLookupComplete(const std::string &result, unsigned int ttl, bool cached) +{ + for (std::vector<reference<Link> >::iterator i = Utils->LinkBlocks.begin(); i != Utils->LinkBlocks.end(); ++i) + { + Link* L = *i; + if (L->IPAddr == host) + { + Utils->ValidIPs.push_back(result); + break; + } + } +} + +void SecurityIPResolver::OnError(ResolverError e, const std::string &errormessage) +{ + if (query == DNS_QUERY_AAAA) + { + bool cached; + SecurityIPResolver* res = new SecurityIPResolver(mine, Utils, host, MyLink, cached, DNS_QUERY_A); + ServerInstance->AddResolver(res, cached); + return; + } + ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Could not resolve IP associated with Link '%s': %s", + MyLink->Name.c_str(),errormessage.c_str()); +} diff --git a/src/modules/m_spanningtree/resolvers.h b/src/modules/m_spanningtree/resolvers.h index cb3b38516..65b9e7249 100644 --- a/src/modules/m_spanningtree/resolvers.h +++ b/src/modules/m_spanningtree/resolvers.h @@ -39,28 +39,9 @@ class SecurityIPResolver : public Resolver std::string host; QueryType query; public: - SecurityIPResolver(Module* me, SpanningTreeUtilities* U, const std::string &hostname, Link* x, bool &cached, QueryType qt) - : Resolver(hostname, qt, cached, me), MyLink(x), Utils(U), mine(me), host(hostname), query(qt) - { - } - - void OnLookupComplete(const std::string &result, unsigned int ttl, bool cached) - { - Utils->ValidIPs.push_back(result); - } - - void OnError(ResolverError e, const std::string &errormessage) - { - if (query == DNS_QUERY_AAAA) - { - bool cached; - SecurityIPResolver* res = new SecurityIPResolver(mine, Utils, host, MyLink, cached, DNS_QUERY_A); - ServerInstance->AddResolver(res, cached); - return; - } - ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Could not resolve IP associated with Link '%s': %s", - MyLink->Name.c_str(),errormessage.c_str()); - } + SecurityIPResolver(Module* me, SpanningTreeUtilities* U, const std::string &hostname, Link* x, bool &cached, QueryType qt); + void OnLookupComplete(const std::string &result, unsigned int ttl, bool cached); + void OnError(ResolverError e, const std::string &errormessage); }; /** This class is used to resolve server hostnames during /connect and autoconnect. diff --git a/src/modules/m_spanningtree/server.cpp b/src/modules/m_spanningtree/server.cpp index 1b13fb2da..64c32e8fb 100644 --- a/src/modules/m_spanningtree/server.cpp +++ b/src/modules/m_spanningtree/server.cpp @@ -163,15 +163,15 @@ bool TreeSocket::Outbound_Reply_Server(parameterlist ¶ms) linkID = sname; MyRoot = new TreeServer(Utils, sname, description, sid, Utils->TreeRoot, this, x->Hidden); - Utils->TreeRoot->AddChild(MyRoot); + this->DoBurst(MyRoot); + params[4] = ":" + params[4]; /* IMPORTANT: Take password/hmac hash OUT of here before we broadcast the introduction! */ params[1] = "*"; Utils->DoOneToAllButSender(ServerInstance->Config->GetSID(),"SERVER",params,sname); - this->DoBurst(MyRoot); return true; } @@ -259,10 +259,6 @@ bool TreeSocket::Inbound_Server(parameterlist ¶ms) MyRoot = new TreeServer(Utils, sname, description, sid, Utils->TreeRoot, this, x->Hidden); Utils->TreeRoot->AddChild(MyRoot); - params[1] = "*"; - params[4] = ":" + params[4]; - Utils->DoOneToAllButSender(ServerInstance->Config->GetSID(),"SERVER",params,sname); - this->LinkState = WAIT_AUTH_2; return true; } diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp index 673b05c55..dcb35af31 100644 --- a/src/modules/m_spanningtree/treesocket1.cpp +++ b/src/modules/m_spanningtree/treesocket1.cpp @@ -183,10 +183,14 @@ void TreeSocket::Squit(TreeServer* Current, const std::string &reason) { DelServerEvent(Utils->Creator, Current->GetName()); - parameterlist params; - params.push_back(Current->GetName()); - params.push_back(":"+reason); - Utils->DoOneToAllButSender(Current->GetParent()->GetName(),"SQUIT",params,Current->GetName()); + if (!Current->GetSocket() || Current->GetSocket()->GetLinkState() == CONNECTED) + { + parameterlist params; + params.push_back(Current->GetName()); + params.push_back(":"+reason); + Utils->DoOneToAllButSender(Current->GetParent()->GetName(),"SQUIT",params,Current->GetName()); + } + if (Current->GetParent() == Utils->TreeRoot) { ServerInstance->SNO->WriteGlobalSno('l', "Server \002"+Current->GetName()+"\002 split: "+reason); diff --git a/src/modules/m_spanningtree/treesocket2.cpp b/src/modules/m_spanningtree/treesocket2.cpp index 4582eb4c5..cb49d92c9 100644 --- a/src/modules/m_spanningtree/treesocket2.cpp +++ b/src/modules/m_spanningtree/treesocket2.cpp @@ -165,12 +165,19 @@ void TreeSocket::ProcessLine(std::string &line) } } this->LinkState = CONNECTED; - Utils->timeoutlist.erase(this); - parameterlist sparams; - Utils->DoOneToAllButSender(MyRoot->GetID(), "BURST", params, MyRoot->GetName()); + MyRoot->bursting = true; this->DoBurst(MyRoot); + + parameterlist sparams; + sparams.push_back(MyRoot->GetName()); + sparams.push_back("*"); + sparams.push_back("0"); + sparams.push_back(MyRoot->GetID()); + sparams.push_back(":" + MyRoot->GetDesc()); + Utils->DoOneToAllButSender(ServerInstance->Config->GetSID(), "SERVER", sparams, MyRoot->GetName()); + Utils->DoOneToAllButSender(MyRoot->GetID(), "BURST", params, MyRoot->GetName()); } else if (command == "ERROR") { diff --git a/src/modules/m_spanningtree/uid.cpp b/src/modules/m_spanningtree/uid.cpp index 67a21a484..0a8f4dbfc 100644 --- a/src/modules/m_spanningtree/uid.cpp +++ b/src/modules/m_spanningtree/uid.cpp @@ -154,7 +154,7 @@ CmdResult CommandUID::Handle(const parameterlist ¶ms, User* serversrc) dosend = false; if (dosend) - ServerInstance->SNO->WriteToSnoMask('C',"Client connecting at %s: %s!%s@%s [%s] [%s]", _new->server.c_str(), _new->nick.c_str(), _new->ident.c_str(), _new->host.c_str(), _new->GetIPString(), _new->fullname.c_str()); + ServerInstance->SNO->WriteToSnoMask('C',"Client connecting at %s: %s!%s@%s (%s) [%s]", _new->server.c_str(), _new->nick.c_str(), _new->ident.c_str(), _new->host.c_str(), _new->GetIPString(), _new->fullname.c_str()); FOREACH_MOD(I_OnPostConnect,OnPostConnect(_new)); diff --git a/src/modules/m_spanningtree/utils.cpp b/src/modules/m_spanningtree/utils.cpp index ec9d5aacc..75d4eaca3 100644 --- a/src/modules/m_spanningtree/utils.cpp +++ b/src/modules/m_spanningtree/utils.cpp @@ -319,17 +319,9 @@ void SpanningTreeUtilities::RefreshIPCache() for (std::vector<reference<Link> >::iterator i = LinkBlocks.begin(); i != LinkBlocks.end(); ++i) { Link* L = *i; - if (L->IPAddr.empty() || L->RecvPass.empty() || L->SendPass.empty() || L->Name.empty() || !L->Port) + if (!L->Port) { - if (L->Name.empty()) - { - ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"m_spanningtree: Ignoring a malformed link block (all link blocks require a name!)"); - } - else - { - ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"m_spanningtree: Ignoring a link block missing recvpass, sendpass, port or ipaddr."); - } - + ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"m_spanningtree: Ignoring a link block without a port."); /* Invalid link block */ continue; } @@ -339,7 +331,7 @@ void SpanningTreeUtilities::RefreshIPCache() irc::sockets::sockaddrs dummy; bool ipvalid = irc::sockets::aptosa(L->IPAddr, L->Port, dummy); - if (ipvalid) + if ((L->IPAddr == "*") || (ipvalid)) ValidIPs.push_back(L->IPAddr); else { @@ -377,7 +369,6 @@ void SpanningTreeUtilities::ReadConfiguration() AutoconnectBlocks.clear(); LinkBlocks.clear(); - ValidIPs.clear(); ConfigTagList tags = ServerInstance->Config->ConfTags("link"); for(ConfigIter i = tags.first; i != tags.second; ++i) { @@ -396,55 +387,37 @@ void SpanningTreeUtilities::ReadConfiguration() L->Bind = tag->getString("bind"); L->Hidden = tag->getBool("hidden"); + if (L->Name.empty()) + throw ModuleException("Invalid configuration, found a link tag without a name!" + (!L->IPAddr.empty() ? " IP address: "+L->IPAddr : "")); + if (L->Name.find('.') == std::string::npos) - throw CoreException("The link name '"+assign(L->Name)+"' is invalid and must contain at least one '.' character"); + throw ModuleException("The link name '"+assign(L->Name)+"' is invalid as it must contain at least one '.' character"); if (L->Name.length() > 64) - throw CoreException("The link name '"+assign(L->Name)+"' is longer than 64 characters!"); + throw ModuleException("The link name '"+assign(L->Name)+"' is invalid as it is longer than 64 characters"); - if (L->Fingerprint.find(':') != std::string::npos) - { - std::string tmp = L->Fingerprint; - L->Fingerprint.clear(); - for(unsigned int j=0; j < tmp.length(); j++) - if (tmp[j] != ':') - L->Fingerprint.push_back(tmp[j]); - } + if (L->RecvPass.empty()) + throw ModuleException("Invalid configuration for server '"+assign(L->Name)+"', recvpass not defined"); - if ((!L->IPAddr.empty()) && (!L->RecvPass.empty()) && (!L->SendPass.empty()) && (!L->Name.empty()) && (L->Port)) - { - ValidIPs.push_back(L->IPAddr); - } - else - { - if (L->IPAddr.empty()) - { - L->IPAddr = "*"; - ValidIPs.push_back("*"); - ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Configuration warning: Link block " + assign(L->Name) + " has no IP defined! This will allow any IP to connect as this server, and MAY not be what you want."); - } + if (L->SendPass.empty()) + throw ModuleException("Invalid configuration for server '"+assign(L->Name)+"', sendpass not defined"); - if (L->RecvPass.empty()) - { - throw CoreException("Invalid configuration for server '"+assign(L->Name)+"', recvpass not defined!"); - } + if ((L->SendPass.find(' ') != std::string::npos) || (L->RecvPass.find(' ') != std::string::npos)) + throw ModuleException("Link block '" + assign(L->Name) + "' has a password set that contains a space character which is invalid"); - if (L->SendPass.empty()) - { - throw CoreException("Invalid configuration for server '"+assign(L->Name)+"', sendpass not defined!"); - } + if ((L->SendPass[0] == ':') || (L->RecvPass[0] == ':')) + throw ModuleException("Link block '" + assign(L->Name) + "' has a password set that begins with a colon (:) which is invalid"); - if (L->Name.empty()) - { - throw CoreException("Invalid configuration, link tag without a name! IP address: "+L->IPAddr); - } - - if (!L->Port) - { - ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Configuration warning: Link block " + assign(L->Name) + " has no port defined, you will not be able to /connect it."); - } + if (L->IPAddr.empty()) + { + L->IPAddr = "*"; + ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Configuration warning: Link block '" + assign(L->Name) + "' has no IP defined! This will allow any IP to connect as this server, and MAY not be what you want."); } + if (!L->Port) + ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Configuration warning: Link block '" + assign(L->Name) + "' has no port defined, you will not be able to /connect it."); + + L->Fingerprint.erase(std::remove(L->Fingerprint.begin(), L->Fingerprint.end(), ':'), L->Fingerprint.end()); LinkBlocks.push_back(L); } @@ -465,12 +438,12 @@ void SpanningTreeUtilities::ReadConfiguration() if (A->Period <= 0) { - throw CoreException("Invalid configuration for autoconnect, period not a positive integer!"); + throw ModuleException("Invalid configuration for autoconnect, period not a positive integer!"); } if (A->servers.empty()) { - throw CoreException("Invalid configuration for autoconnect, server cannot be empty!"); + throw ModuleException("Invalid configuration for autoconnect, server cannot be empty!"); } AutoconnectBlocks.push_back(A); diff --git a/src/modules/m_stripcolor.cpp b/src/modules/m_stripcolor.cpp index aab506fdc..cd4f35c4b 100644 --- a/src/modules/m_stripcolor.cpp +++ b/src/modules/m_stripcolor.cpp @@ -75,7 +75,7 @@ class ModuleStripColor : public Module std::string::iterator i,safei; for (i = sentence.begin(); i != sentence.end();) { - if ((*i == 3)) + if (*i == 3) seq = 1; else if (seq && (( ((*i >= '0') && (*i <= '9')) || (*i == ',') ) )) { |