X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fusers.cpp;h=268c61b3b783eecf8e0e5c01193fb683bc860bc1;hb=12ffb909a66401f540234aecbeeee6f94ef2fc6d;hp=5ec1417185f9f1225cbe4d3114aaa01192918437;hpb=31f1e7ad092f8bf16ee653cc105eea4a769650ca;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/users.cpp b/src/users.cpp index 5ec141718..268c61b3b 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -210,9 +210,9 @@ User::User(InspIRCd* Instance, const std::string &uid) : ServerInstance(Instance memset(snomasks,0,sizeof(snomasks)); if (uid.empty()) - uuid.assign(Instance->GetUID(), 0, UUID_LENGTH); + uuid.assign(Instance->GetUID(), 0, UUID_LENGTH - 1); else - uuid.assign(uid, 0, UUID_LENGTH); + uuid.assign(uid, 0, UUID_LENGTH - 1); ServerInstance->Logs->Log("USERS", DEBUG,"New UUID for user: %s (%s)", uuid.c_str(), uid.empty() ? "allocated new" : "used remote"); @@ -721,7 +721,7 @@ void User::Oper(const std::string &opertype, const std::string &opername) this->WriteServ("MODE %s :+o", this->nick.c_str()); FOREACH_MOD(I_OnOper, OnOper(this, opertype)); ServerInstance->Logs->Log("OPER", DEFAULT, "%s!%s@%s opered as type: %s", this->nick.c_str(), this->ident.c_str(), this->host.c_str(), opertype.c_str()); - this->oper.assign(opertype, 0, NICKMAX - 1); + this->oper.assign(opertype, 0, 512); ServerInstance->Users->all_opers.push_back(this); opertype_t::iterator iter_opertype = ServerInstance->Config->opertypes.find(this->oper.c_str()); @@ -886,7 +886,7 @@ void User::CheckClass() this->MaxChans = a->GetMaxChans(); } -void User::CheckLines() +bool User::CheckLines() { const char* check[] = { "G" , "K", NULL }; @@ -899,10 +899,12 @@ void User::CheckLines() if (r) { r->Apply(this); - return; + return true; } } } + + return false; } void User::FullConnect() @@ -927,7 +929,8 @@ void User::FullConnect() return; } - CheckLines(); + if (this->CheckLines()) + return; this->WriteServ("NOTICE Auth :Welcome to \002%s\002!",ServerInstance->Config->Network); this->WriteNumeric(001, "%s :Welcome to the %s IRC Network %s!%s@%s",this->nick.c_str(), ServerInstance->Config->Network, this->nick.c_str(), this->ident.c_str(), this->host.c_str()); @@ -947,9 +950,11 @@ void User::FullConnect() /* Trigger LUSERS output, give modules a chance too */ int MOD_RESULT = 0; - FOREACH_RESULT(I_OnPreCommand, OnPreCommand("LUSERS", std::vector(), this, true, "LUSERS")); + std::string command("LUSERS"); + std::vector parameters; + FOREACH_RESULT(I_OnPreCommand, OnPreCommand(command, parameters, this, true, "LUSERS")); if (!MOD_RESULT) - ServerInstance->CallCommandHandler("LUSERS", std::vector(), this); + ServerInstance->CallCommandHandler(command, parameters, this); /* * We don't set REG_ALL until triggering OnUserConnect, so some module events don't spew out stuff @@ -959,6 +964,8 @@ 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()); @@ -1094,13 +1101,117 @@ int User::GetProtocolFamily() return sin->sin_family; } -/* - * XXX the duplication here is horrid.. - * do we really need two methods doing essentially the same thing? - */ +const char* User::GetCIDRMask(int range) +{ + static char buf[44]; + + if (this->ip == NULL) + return ""; + + if (range < 0) + throw "Negative range, sorry, no."; + + /* + * Original code written by Oliver Lupton (Om). + * Integrated by me. Thanks. :) -- w00t + */ + switch (this->GetProtocolFamily()) + { +#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 + * which must be set to zero. + */ + bytestozero = (128 - range) / 8; + + /* Some of the least significant bits of the next most significant byte may also have to + * be zeroed. The number of bits is the remainder of the above division. + */ + extrabits = (128 - range) % 8; + + /* Populate our working struct with the parts of the user's IP which are required in the + * final CIDR mask. Set all the subsequent bytes to zero. + * (16 - bytestozero) is the number of bytes which must be populated with actual IP data. + */ + for(i = 0; i < (16 - bytestozero); i++) + { + v6.s6_addr[i] = sin->sin6_addr.s6_addr[i]; + } + + /* And zero all the remaining bytes in the IP. */ + for(; i < 16; i++) + { + v6.s6_addr[i] = 0; + } + + /* And finally, zero the extra bits required. */ + v6.s6_addr[15 - bytestozero] = (v6.s6_addr[15 - bytestozero] >> extrabits) << extrabits; + + snprintf(buf, 44, "%s/%d", inet_ntop(AF_INET6, &v6, buffer, 40), range); + return buf; + } + break; +#endif + case AF_INET: + { + struct in_addr v4; + sockaddr_in* sin; + uint32_t temp; + 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; + + /* 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. + * This is done by shifting the value right and then back left by (32 - range) bits. + */ + if(range > 0) + { + temp = ntohl(v4.s_addr); + temp = (temp >> (32 - range)) << (32 - range); + v4.s_addr = htonl(temp); + } + else + { + /* a range of zero would cause a 32 bit value to be shifted by 32 bits. + * this has undefined behaviour, but for CIDR purposes the resulting mask + * from a.b.c.d/0 is 0.0.0.0/0 + */ + v4.s_addr = 0; + } + + snprintf(buf, 44, "%s/%d", inet_ntop(AF_INET, &v4, buffer, 16), range); + return buf; + } + break; + } + + return ""; // unused, but oh well +} + const char* User::GetIPString(bool translate4in6) { - static char buf[1024]; + static char buf[40]; if (this->ip == NULL) return ""; @@ -1521,14 +1632,14 @@ bool User::ChangeName(const char* gecos) return false; FOREACH_MOD(I_OnChangeName,OnChangeName(this,gecos)); } - this->fullname.assign(gecos, 0, MAXGECOS+1); + this->fullname.assign(gecos, 0, ServerInstance->Config->Limits.MaxGecos); return true; } bool User::ChangeDisplayedHost(const char* shost) { - if (!this->dhost.compare(shost)) + if (dhost == shost) return true; if (IS_LOCAL(this)) @@ -1573,7 +1684,7 @@ bool User::ChangeIdent(const char* newident) if (this->ServerInstance->Config->CycleHosts) this->WriteCommonExcept("%s","QUIT :Changing ident"); - this->ident.assign(newident, 0, IDENTMAX + 1); + this->ident.assign(newident, 0, ServerInstance->Config->Limits.IdentMax + 1); this->InvalidateCache();