X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fusers.cpp;h=cd5aa247ec23bd399f25dfa9ecabf7941f113d8d;hb=7c340cba11b16d3c4a95c274c22f1617ac4711f2;hp=cbc59a49c66a32a7676343475ab28ac529035462;hpb=0036e3a70cabea02e9ec2103ed1dfdf5c799289f;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/users.cpp b/src/users.cpp index cbc59a49c..cd5aa247e 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -107,9 +107,7 @@ void User::StartDNSLookup() const char* sip = this->GetIPString(); UserResolver *res_reverse; - QueryType resolvtype = strchr(sip, ':') ? DNS_QUERY_PTR6 : DNS_QUERY_PTR4; - // when GetProtocolFamily() works correctly with 4in6, this can be replaced by - // this->GetProtocolFamily() == AF_INET ? DNS_QUERY_PTR4 : DNS_QUERY_PTR6; + QueryType resolvtype = this->client_sa.sa.sa_family == AF_INET6 ? DNS_QUERY_PTR6 : DNS_QUERY_PTR4; res_reverse = new UserResolver(this->ServerInstance, this, sip, resolvtype, cached); this->ServerInstance->AddResolver(res_reverse, cached); @@ -208,17 +206,18 @@ void User::DecrementModes() User::User(InspIRCd* Instance, const std::string &uid) : ServerInstance(Instance) { - server = (char*)Instance->FindServerNamePtr(Instance->Config->ServerName); + server = Instance->FindServerNamePtr(Instance->Config->ServerName); age = ServerInstance->Time(); Penalty = 0; lastping = signon = idle_lastmsg = nping = registered = 0; bytes_in = bytes_out = cmds_in = cmds_out = 0; quietquit = quitting = exempt = haspassed = dns_done = false; fd = -1; + server_sa.sa.sa_family = AF_UNSPEC; + client_sa.sa.sa_family = AF_UNSPEC; recvq.clear(); sendq.clear(); Visibility = NULL; - ip = NULL; MyClass = NULL; AllowedPrivs = AllowedOperCommands = NULL; chans.clear(); @@ -264,22 +263,9 @@ User::~User() this->InvalidateCache(); this->DecrementModes(); - if (ip) - { + if (client_sa.sa.sa_family != AF_UNSPEC) ServerInstance->Users->RemoveCloneCounts(this); - if (this->GetProtocolFamily() == AF_INET) - { - delete (sockaddr_in*)ip; - } -#ifdef SUPPORT_IP6LINKS - else - { - delete (sockaddr_in6*)ip; - } -#endif - } - ServerInstance->Users->uuidlist->erase(uuid); } @@ -520,7 +506,6 @@ bool User::HasPermission(const std::string &command) bool User::HasPrivPermission(const std::string &privstr, bool noisy) { - ServerInstance->Logs->Log("PRIVS", DEBUG, "Checking if I have " + privstr); if (!IS_LOCAL(this)) { ServerInstance->Logs->Log("PRIVS", DEBUG, "Remote (yes)"); @@ -531,7 +516,6 @@ bool User::HasPrivPermission(const std::string &privstr, bool noisy) { if (noisy) this->WriteServ("NOTICE %s :You are not an oper", this->nick.c_str()); - ServerInstance->Logs->Log("PRIVS", DEBUG, "Not oper (no)"); return false; } @@ -539,7 +523,6 @@ bool User::HasPrivPermission(const std::string &privstr, bool noisy) { if (noisy) this->WriteServ("NOTICE %s :Privset empty(!?)", this->nick.c_str()); - ServerInstance->Logs->Log("PRIVS", DEBUG, "No privs(?) (no)"); return false; } @@ -1002,11 +985,10 @@ void User::FullConnect() this->registered = REG_ALL; - ServerInstance->PI->Introduce(this); - FOREACH_MOD(I_OnPostConnect,OnPostConnect(this)); - ServerInstance->SNO->WriteToSnoMask('c',"Client connecting on port %d: %s!%s@%s [%s] [%s]", this->GetPort(), this->nick.c_str(), this->ident.c_str(), this->host.c_str(), this->GetIPString(), this->fullname.c_str()); + ServerInstance->SNO->WriteToSnoMask('c',"Client connecting on port %d: %s!%s@%s [%s] [%s]", + this->GetServerPort(), this->nick.c_str(), this->ident.c_str(), this->host.c_str(), this->GetIPString(), this->fullname.c_str()); ServerInstance->Logs->Log("BANCACHE", DEBUG, "BanCache: Adding NEGATIVE hit for %s", this->GetIPString()); ServerInstance->BanCache->AddHit(this->GetIPString(), "", ""); } @@ -1077,81 +1059,22 @@ bool User::ForceNickChange(const char* newnick) return false; } -void User::SetSockAddr(int protocol_family, const char* sip, int port) +int User::GetServerPort() { - this->cachedip = ""; - - switch (protocol_family) + switch (this->server_sa.sa.sa_family) { -#ifdef SUPPORT_IP6LINKS case AF_INET6: - { - sockaddr_in6* sin = new sockaddr_in6; - sin->sin6_family = AF_INET6; - sin->sin6_port = port; - inet_pton(AF_INET6, sip, &sin->sin6_addr); - this->ip = (sockaddr*)sin; - } - break; -#endif + return htons(this->server_sa.in6.sin6_port); case AF_INET: - { - sockaddr_in* sin = new sockaddr_in; - sin->sin_family = AF_INET; - sin->sin_port = port; - inet_pton(AF_INET, sip, &sin->sin_addr); - this->ip = (sockaddr*)sin; - } - break; - default: - ServerInstance->Logs->Log("USERS",DEBUG,"Uh oh, I dont know protocol %d to be set on '%s'!", protocol_family, this->nick.c_str()); - break; - } -} - -int User::GetPort() -{ - if (this->ip == NULL) - return 0; - - switch (this->GetProtocolFamily()) - { -#ifdef SUPPORT_IP6LINKS - case AF_INET6: - { - sockaddr_in6* sin = (sockaddr_in6*)this->ip; - return sin->sin6_port; - } - break; -#endif - case AF_INET: - { - sockaddr_in* sin = (sockaddr_in*)this->ip; - return sin->sin_port; - } - break; - default: - break; + return htons(this->server_sa.in4.sin_port); } return 0; } -int User::GetProtocolFamily() -{ - if (this->ip == NULL) - return 0; - - sockaddr_in* sin = (sockaddr_in*)this->ip; - return sin->sin_family; -} - const char* User::GetCIDRMask(int range) { static char buf[44]; - if (this->ip == NULL) - return ""; - if (range < 0) throw "Negative range, sorry, no."; @@ -1159,23 +1082,18 @@ const char* User::GetCIDRMask(int range) * Original code written by Oliver Lupton (Om). * Integrated by me. Thanks. :) -- w00t */ - switch (this->GetProtocolFamily()) + switch (this->client_sa.sa.sa_family) { -#ifdef SUPPORT_IP6LINKS case AF_INET6: { /* unsigned char s6_addr[16]; */ struct in6_addr v6; - sockaddr_in6* sin; int i, bytestozero, extrabits; char buffer[40]; if(range > 128) throw "CIDR mask width greater than address width (IPv6, 128 bit)"; - /* Access the user's IP structure directly */ - sin = (sockaddr_in6*)this->ip; - /* To create the CIDR mask we want to set all the bits after 'range' bits of the address * to zero. This means the last (128 - range) bits of the address must be set to zero. * Hence this number divided by 8 is the number of whole bytes from the end of the address @@ -1194,7 +1112,7 @@ const char* User::GetCIDRMask(int range) */ for(i = 0; i < (16 - bytestozero); i++) { - v6.s6_addr[i] = sin->sin6_addr.s6_addr[i]; + v6.s6_addr[i] = client_sa.in6.sin6_addr.s6_addr[i]; } /* And zero all the remaining bytes in the IP. */ @@ -1210,19 +1128,16 @@ const char* User::GetCIDRMask(int range) return buf; } break; -#endif case AF_INET: { struct in_addr v4; - sockaddr_in* sin; char buffer[16]; if (range > 32) throw "CIDR mask width greater than address width (IPv4, 32 bit)"; /* Users already have a sockaddr* pointer (User::ip) which contains either a v4 or v6 structure */ - sin = (sockaddr_in*)this->ip; - v4.s_addr = sin->sin_addr.s_addr; + v4.s_addr = client_sa.in4.sin_addr.s_addr; /* To create the CIDR mask we want to set all the bits after 'range' bits of the address * to zero. This means the last (32 - range) bits of the address must be set to zero. @@ -1252,76 +1167,40 @@ const char* User::GetCIDRMask(int range) return ""; // unused, but oh well } -const char* User::GetIPString() +std::string User::GetServerIP() { - static char buf[40]; - - if (this->ip == NULL) - return ""; - - if (!this->cachedip.empty()) - return this->cachedip.c_str(); + int port; + std::string ip; + irc::sockets::satoap(&server_sa, ip, port); + return ip; +} - switch (this->GetProtocolFamily()) +const char* User::GetIPString() +{ + int port; + if (cachedip.empty()) { -#ifdef SUPPORT_IP6LINKS - case AF_INET6: - { - static char temp[1024]; - - sockaddr_in6* sin = (sockaddr_in6*)this->ip; - inet_ntop(sin->sin6_family, &sin->sin6_addr, buf, sizeof(buf)); - /* IP addresses starting with a : on irc are a Bad Thing (tm) */ - if (*buf == ':') - { - strlcpy(&temp[1], buf, sizeof(temp) - 1); - *temp = '0'; - this->cachedip = temp; - return temp; - } - - this->cachedip = buf; - return buf; - } - break; -#endif - case AF_INET: - { - sockaddr_in* sin = (sockaddr_in*)this->ip; - inet_ntop(sin->sin_family, &sin->sin_addr, buf, sizeof(buf)); - this->cachedip = buf; - return buf; - } - break; - default: - break; + irc::sockets::satoap(&client_sa, cachedip, port); + /* IP addresses starting with a : on irc are a Bad Thing (tm) */ + if (cachedip.c_str()[0] == ':') + cachedip.insert(0,1,'0'); } - // Unreachable, probably - return ""; + return cachedip.c_str(); } -/** NOTE: We cannot pass a const reference to this method. - * The string is changed by the workings of the method, - * so that if we pass const ref, we end up copying it to - * something we can change anyway. Makes sense to just let - * the compiler do that copy for us. - */ -void User::Write(std::string text) +bool User::SetClientIP(const char* sip) +{ + this->cachedip = ""; + return irc::sockets::aptosa(sip, 0, &client_sa); +} + +void User::Write(const std::string& text) { if (!ServerInstance->SE->BoundsCheckFd(this)) return; - try - { - ServerInstance->Logs->Log("USEROUTPUT", DEBUG,"C[%d] O %s", this->GetFd(), text.c_str()); - text.append("\r\n"); - } - catch (...) - { - ServerInstance->Logs->Log("USEROUTPUT", DEBUG,"Exception in User::Write() std::string::append"); - return; - } + ServerInstance->Logs->Log("USEROUTPUT", DEBUG,"C[%d] O %s", this->GetFd(), text.c_str()); if (this->GetIOHook()) { @@ -1331,6 +1210,7 @@ void User::Write(std::string text) try { this->GetIOHook()->OnRawSocketWrite(this->fd, text.data(), text.length()); + this->GetIOHook()->OnRawSocketWrite(this->fd, "\r\n", 2); } catch (CoreException& modexcept) { @@ -1340,8 +1220,9 @@ void User::Write(std::string text) else { this->AddWriteBuf(text); + this->AddWriteBuf("\r\n"); } - ServerInstance->stats->statsSent += text.length(); + ServerInstance->stats->statsSent += text.length() + 2; this->ServerInstance->SE->WantWrite(this); } @@ -1361,10 +1242,7 @@ void User::Write(const char *text, ...) void User::WriteServ(const std::string& text) { - char textbuffer[MAXBUF]; - - snprintf(textbuffer,MAXBUF,":%s %s",ServerInstance->Config->ServerName,text.c_str()); - this->Write(std::string(textbuffer)); + this->Write(":%s %s",ServerInstance->Config->ServerName,text.c_str()); } /** WriteServ() @@ -1671,6 +1549,52 @@ bool User::ChangeName(const char* gecos) return true; } +void User::DoHostCycle(const std::string &quitline) +{ + char buffer[MAXBUF]; + + int MOD_RESULT = 0; + FOREACH_RESULT(I_OnHostCycle, OnHostCycle(this)); + + if (!ServerInstance->Config->CycleHosts || MOD_RESULT) + return; + + uniq_id++; + + if (!already_sent) + InitializeAlreadySent(ServerInstance->SE); + + for (UCListIter v = this->chans.begin(); v != this->chans.end(); v++) + { + Channel* c = v->first; + snprintf(buffer, MAXBUF, ":%s JOIN %s", GetFullHost().c_str(), c->name.c_str()); + std::string joinline(buffer); + std::string modeline = this->ServerInstance->Modes->ModeString(this, c); + if (modeline.length() > 0) + { + snprintf(buffer, MAXBUF, ":%s MODE %s +%s", GetFullHost().c_str(), c->name.c_str(), modeline.c_str()); + modeline = buffer; + } + + CUList *ulist = c->GetUsers(); + for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++) + { + User* u = i->first; + if (u == this || !IS_LOCAL(u)) + continue; + + if (already_sent[i->first->fd] != uniq_id) + { + u->Write(quitline); + already_sent[i->first->fd] = uniq_id; + } + u->Write(joinline); + if (modeline.length() > 0) + u->Write(modeline); + } + } +} + bool User::ChangeDisplayedHost(const char* shost) { if (dhost == shost) @@ -1686,27 +1610,14 @@ bool User::ChangeDisplayedHost(const char* shost) FOREACH_MOD(I_OnChangeHost, OnChangeHost(this,shost)); - int MOD_RESULT = 0; - FOREACH_RESULT(I_OnHostCycle, OnHostCycle(this)); - - if (this->ServerInstance->Config->CycleHosts && !MOD_RESULT) - this->WriteCommonExcept("QUIT :Changing hosts"); + std::string quitstr = ":" + GetFullHost() + " QUIT :Changing host"; /* Fix by Om: User::dhost is 65 long, this was truncating some long hosts */ this->dhost.assign(shost, 0, 64); this->InvalidateCache(); - if (this->ServerInstance->Config->CycleHosts && !MOD_RESULT) - { - for (UCListIter i = this->chans.begin(); i != this->chans.end(); i++) - { - i->first->WriteAllExceptSender(this, false, 0, "JOIN %s", i->first->name.c_str()); - std::string n = this->ServerInstance->Modes->ModeString(this, i->first); - if (n.length() > 0) - i->first->WriteAllExceptSender(this, true, 0, "MODE %s +%s", i->first->name.c_str(), n.c_str()); - } - } + this->DoHostCycle(quitstr); if (IS_LOCAL(this)) this->WriteNumeric(RPL_YOURDISPLAYEDHOST, "%s %s :is now your displayed host",this->nick.c_str(),this->dhost.c_str()); @@ -1719,26 +1630,13 @@ bool User::ChangeIdent(const char* newident) if (this->ident == newident) return true; - int MOD_RESULT = 0; - FOREACH_RESULT(I_OnHostCycle, OnHostCycle(this)); - - if (this->ServerInstance->Config->CycleHosts && !MOD_RESULT) - this->WriteCommonExcept("%s","QUIT :Changing ident"); + std::string quitstr = ":" + GetFullHost() + " QUIT :Changing ident"; this->ident.assign(newident, 0, ServerInstance->Config->Limits.IdentMax + 1); this->InvalidateCache(); - if (this->ServerInstance->Config->CycleHosts && !MOD_RESULT) - { - for (UCListIter i = this->chans.begin(); i != this->chans.end(); i++) - { - i->first->WriteAllExceptSender(this, false, 0, "JOIN %s", i->first->name.c_str()); - std::string n = this->ServerInstance->Modes->ModeString(this, i->first); - if (n.length() > 0) - i->first->WriteAllExceptSender(this, true, 0, "MODE %s +%s", i->first->name.c_str(), n.c_str()); - } - } + this->DoHostCycle(quitstr); return true; } @@ -1887,9 +1785,9 @@ ConnectClass* User::SetClass(const std::string &explicit_name) ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "Requires port (%d)", c->GetPort()); /* and our port doesn't match, fail. */ - if (this->GetPort() != c->GetPort()) + if (this->GetServerPort() != c->GetPort()) { - ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "Port match failed (%d)", this->GetPort()); + ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "Port match failed (%d)", this->GetServerPort()); continue; } } @@ -2081,12 +1979,12 @@ bool VisData::VisibleTo(User* user) ConnectClass::ConnectClass(char t, const std::string& mask) - : type(t), name("unnamed"), registration_timeout(0), host(mask), pingtime(0), pass(""), hash(""), sendqmax(0), recvqmax(0), maxlocal(0), maxglobal(0), limit(0), RefCount(1) + : type(t), name("unnamed"), registration_timeout(0), host(mask), pingtime(0), pass(""), hash(""), sendqmax(0), recvqmax(0), maxlocal(0), maxglobal(0), maxchans(0), port(0), limit(0), RefCount(1) { } ConnectClass::ConnectClass(char t, const std::string& mask, const ConnectClass& parent) - : type(t), name("unnamed"), registration_timeout(parent.registration_timeout), host(mask), pingtime(parent.pingtime), pass(parent.pass), hash(parent.hash), sendqmax(parent.sendqmax), recvqmax(parent.recvqmax), maxlocal(parent.maxlocal), maxglobal(parent.maxglobal), limit(parent.limit), RefCount(1) + : type(t), name("unnamed"), registration_timeout(parent.registration_timeout), host(mask), pingtime(parent.pingtime), pass(parent.pass), hash(parent.hash), sendqmax(parent.sendqmax), recvqmax(parent.recvqmax), maxlocal(parent.maxlocal), maxglobal(parent.maxglobal), maxchans(parent.maxchans), port(parent.port), limit(parent.limit), RefCount(1) { }