diff options
author | danieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7> | 2009-10-22 21:49:39 +0000 |
---|---|---|
committer | danieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7> | 2009-10-22 21:49:39 +0000 |
commit | b43fc66c17c2bef6dca66a966676b8128d5774ee (patch) | |
tree | 1d7aa401ffbf682595e1152ae97d2e2d0fcd8d7a | |
parent | f49a18e9abc210cb7ec4a691691cbbefe51a1854 (diff) |
Make irc::sockets::* parameters consistent, add irc::sockets::mask
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11953 e03df62e-2008-0410-955e-edbf42e46eb7
-rw-r--r-- | include/socket.h | 13 | ||||
-rw-r--r-- | include/users.h | 13 | ||||
-rw-r--r-- | src/dns.cpp | 2 | ||||
-rw-r--r-- | src/inspsocket.cpp | 4 | ||||
-rw-r--r-- | src/listensocket.cpp | 6 | ||||
-rw-r--r-- | src/modules/m_check.cpp | 4 | ||||
-rw-r--r-- | src/modules/m_connectban.cpp | 11 | ||||
-rw-r--r-- | src/modules/m_httpd.cpp | 2 | ||||
-rw-r--r-- | src/modules/m_httpd_stats.cpp | 2 | ||||
-rw-r--r-- | src/modules/m_spanningtree/treesocket1.cpp | 2 | ||||
-rw-r--r-- | src/modules/m_spanningtree/utils.cpp | 4 | ||||
-rw-r--r-- | src/socket.cpp | 98 | ||||
-rw-r--r-- | src/usermanager.cpp | 68 | ||||
-rw-r--r-- | src/users.cpp | 115 |
14 files changed, 123 insertions, 221 deletions
diff --git a/include/socket.h b/include/socket.h index a9b0a472e..bfde750ea 100644 --- a/include/socket.h +++ b/include/socket.h @@ -107,20 +107,27 @@ namespace irc * @param sa The structure to place the result in. Will be zeroed prior to conversion * @return true if the conversion was successful, false if not. */ - CoreExport bool aptosa(const std::string& addr, int port, irc::sockets::sockaddrs* sa); + CoreExport bool aptosa(const std::string& addr, int port, irc::sockets::sockaddrs& sa); + /** Convert a binary sockaddr to an address-port pair * @param sa The structure to convert * @param addr the IP address * @param port the port * @return true if the conversion was successful, false if unknown address family */ - CoreExport bool satoap(const irc::sockets::sockaddrs* sa, std::string& addr, int &port); + CoreExport bool satoap(const irc::sockets::sockaddrs& sa, std::string& addr, int &port); + /** Convert a binary sockaddr to a user-readable string. * This means IPv6 addresses are written as [::1]:6667, and *:6668 is used for 0.0.0.0:6668 * @param sa The structure to convert * @return The string; "<unknown>" if not a valid address */ - CoreExport std::string satouser(const irc::sockets::sockaddrs* sa); + CoreExport std::string satouser(const irc::sockets::sockaddrs& sa); + + /** Create a CIDR mask from the given address, of length <range> + * Result will be of the form 192.0.5.0/24 or 2001:af35::/48 + */ + CoreExport std::string mask(irc::sockets::sockaddrs sa, unsigned int range); } } diff --git a/include/users.h b/include/users.h index 49e43f0bf..fa56abc0e 100644 --- a/include/users.h +++ b/include/users.h @@ -388,20 +388,15 @@ class CoreExport User : public StreamSocket */ const char* GetIPString(); + /** Get CIDR mask, using default range, for this user + */ + irc::string GetCIDRMask(); + /** Sets the client IP for this user * @return true if the conversion was successful */ bool SetClientIP(const char* sip); - /** Get a CIDR mask from the IP of this user, using a static internal buffer. - * e.g., GetCIDRMask(16) for 223.254.214.52 returns 223.254.0.0/16 - * This may be used for CIDR clone detection, etc. - * - * (XXX, brief note: when we do the sockets rewrite, this should move down a - * level so it may be used on more derived objects. -- w00t) - */ - const char *GetCIDRMask(int range); - /** Default constructor * @throw CoreException if the UID allocated to the user already exists * @param Instance Creator instance diff --git a/src/dns.cpp b/src/dns.cpp index e4d0b73fb..7be0f6874 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -303,7 +303,7 @@ void DNS::Rehash() this->cache = new dnscache(); } - irc::sockets::aptosa(ServerInstance->Config->DNSServer, DNS::QUERY_PORT, &myserver); + irc::sockets::aptosa(ServerInstance->Config->DNSServer, DNS::QUERY_PORT, myserver); /* Initialize mastersocket */ int s = irc::sockets::OpenTCPSocket(ServerInstance->Config->DNSServer, SOCK_DGRAM); diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp index a37cb9ea0..7485324a2 100644 --- a/src/inspsocket.cpp +++ b/src/inspsocket.cpp @@ -52,7 +52,7 @@ void BufferedSocket::DoConnect(const std::string &ipaddr, int aport, unsigned lo BufferedSocketError BufferedSocket::BeginConnect(const std::string &ipaddr, int aport, unsigned long maxtime, const std::string &connectbindip) { irc::sockets::sockaddrs addr, bind; - if (!irc::sockets::aptosa(ipaddr, aport, &addr)) + if (!irc::sockets::aptosa(ipaddr, aport, addr)) { ServerInstance->Logs->Log("SOCKET", DEBUG, "BUG: Hostname passed to BufferedSocket, rather than an IP address!"); return I_ERR_CONNECT; @@ -61,7 +61,7 @@ BufferedSocketError BufferedSocket::BeginConnect(const std::string &ipaddr, int bind.sa.sa_family = 0; if (!connectbindip.empty()) { - if (!irc::sockets::aptosa(connectbindip, 0, &bind)) + if (!irc::sockets::aptosa(connectbindip, 0, bind)) { return I_ERR_BIND; } diff --git a/src/listensocket.cpp b/src/listensocket.cpp index 8b7053d8f..0d6bf89b6 100644 --- a/src/listensocket.cpp +++ b/src/listensocket.cpp @@ -23,13 +23,13 @@ ListenSocket::ListenSocket(ConfigTag* tag, const std::string& addr, int port) irc::sockets::sockaddrs bind_to; // canonicalize address if it is defined - if (!irc::sockets::aptosa(addr, port, &bind_to)) + if (!irc::sockets::aptosa(addr, port, bind_to)) { fd = -1; return; } - irc::sockets::satoap(&bind_to, bind_addr, bind_port); - bind_desc = irc::sockets::satouser(&bind_to); + irc::sockets::satoap(bind_to, bind_addr, bind_port); + bind_desc = irc::sockets::satouser(bind_to); fd = irc::sockets::OpenTCPSocket(bind_addr); diff --git a/src/modules/m_check.cpp b/src/modules/m_check.cpp index 158b0c533..0a0ecab2b 100644 --- a/src/modules/m_check.cpp +++ b/src/modules/m_check.cpp @@ -104,8 +104,8 @@ class CommandCheck : public Command LocalUser* loctarg = IS_LOCAL(targuser); if (loctarg) { - user->SendText(checkstr + " clientaddr " + irc::sockets::satouser(&loctarg->client_sa)); - user->SendText(checkstr + " serveraddr " + irc::sockets::satouser(&loctarg->server_sa)); + user->SendText(checkstr + " clientaddr " + irc::sockets::satouser(loctarg->client_sa)); + user->SendText(checkstr + " serveraddr " + irc::sockets::satouser(loctarg->server_sa)); std::string classname = loctarg->GetClass()->name; if (!classname.empty()) diff --git a/src/modules/m_connectban.cpp b/src/modules/m_connectban.cpp index 9506bc2fe..735f3da99 100644 --- a/src/modules/m_connectban.cpp +++ b/src/modules/m_connectban.cpp @@ -81,7 +81,8 @@ class ModuleConnectBan : public Module break; } - i = connects.find(u->GetCIDRMask(range)); + irc::string mask = assign(irc::sockets::mask(u->client_sa, range)); + i = connects.find(mask); if (i != connects.end()) { @@ -90,21 +91,21 @@ class ModuleConnectBan : public Module if (i->second >= threshold) { // Create zline for set duration. - ZLine* zl = new ZLine(ServerInstance->Time(), banduration, ServerInstance->Config->ServerName.c_str(), "Connect flooding", u->GetCIDRMask(range)); + ZLine* zl = new ZLine(ServerInstance->Time(), banduration, ServerInstance->Config->ServerName.c_str(), "Connect flooding", mask.c_str()); if (ServerInstance->XLines->AddLine(zl,NULL)) ServerInstance->XLines->ApplyLines(); else delete zl; ServerInstance->SNO->WriteGlobalSno('x',"Module m_connectban added Z:line on *@%s to expire on %s: Connect flooding", - u->GetCIDRMask(range), ServerInstance->TimeString(zl->expiry).c_str()); - ServerInstance->SNO->WriteGlobalSno('a', "Connect flooding from IP range %s (%d)", u->GetCIDRMask(range), threshold); + mask.c_str(), ServerInstance->TimeString(zl->expiry).c_str()); + ServerInstance->SNO->WriteGlobalSno('a', "Connect flooding from IP range %s (%d)", mask.c_str(), threshold); connects.erase(i); } } else { - connects[u->GetCIDRMask(range)] = 1; + connects[mask] = 1; } } diff --git a/src/modules/m_httpd.cpp b/src/modules/m_httpd.cpp index 7fc342e04..748f530ca 100644 --- a/src/modules/m_httpd.cpp +++ b/src/modules/m_httpd.cpp @@ -343,7 +343,7 @@ class ModuleHttpServer : public Module return MOD_RES_PASSTHRU; int port; std::string incomingip; - irc::sockets::satoap(client, incomingip, port); + irc::sockets::satoap(*client, incomingip, port); new HttpServerSocket(nfd, incomingip, from, client, server); return MOD_RES_ALLOW; } diff --git a/src/modules/m_httpd_stats.cpp b/src/modules/m_httpd_stats.cpp index 7e478ade4..a0aa202ab 100644 --- a/src/modules/m_httpd_stats.cpp +++ b/src/modules/m_httpd_stats.cpp @@ -171,7 +171,7 @@ class ModuleHttpStats : public Module LocalUser* lu = IS_LOCAL(u); if (lu) data << "<port>" << lu->GetServerPort() << "</port><servaddr>" - << irc::sockets::satouser(&lu->server_sa) << "</servaddr>"; + << irc::sockets::satouser(lu->server_sa) << "</servaddr>"; data << "<ipaddress>" << u->GetIPString() << "</ipaddress>"; DumpMeta(data, u); diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp index 962b63984..b8633ae14 100644 --- a/src/modules/m_spanningtree/treesocket1.cpp +++ b/src/modules/m_spanningtree/treesocket1.cpp @@ -73,7 +73,7 @@ TreeSocket::TreeSocket(SpanningTreeUtilities* Util, int newfd, ListenSocket* via : BufferedSocket(newfd), Utils(Util) { int dummy; - irc::sockets::satoap(client, IP, dummy); + irc::sockets::satoap(*client, IP, dummy); age = ServerInstance->Time(); LinkState = WAIT_AUTH_1; capab_phase = 0; diff --git a/src/modules/m_spanningtree/utils.cpp b/src/modules/m_spanningtree/utils.cpp index 11c96bf7c..0b9b8da3b 100644 --- a/src/modules/m_spanningtree/utils.cpp +++ b/src/modules/m_spanningtree/utils.cpp @@ -32,7 +32,7 @@ ModResult ModuleSpanningTree::OnAcceptConnection(int newsock, ListenSocket* from bool found = false; int port; std::string incomingip; - irc::sockets::satoap(client, incomingip, port); + irc::sockets::satoap(*client, incomingip, port); found = (std::find(Utils->ValidIPs.begin(), Utils->ValidIPs.end(), incomingip) != Utils->ValidIPs.end()); if (!found) @@ -335,7 +335,7 @@ void SpanningTreeUtilities::RefreshIPCache() ValidIPs.push_back(L->AllowMask); irc::sockets::sockaddrs dummy; - bool ipvalid = irc::sockets::aptosa(L->IPAddr, L->Port, &dummy); + bool ipvalid = irc::sockets::aptosa(L->IPAddr, L->Port, dummy); if (ipvalid) ValidIPs.push_back(L->IPAddr); else diff --git a/src/socket.cpp b/src/socket.cpp index 167d90b4f..a92343d91 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -35,7 +35,7 @@ bool InspIRCd::BindSocket(int sockfd, int port, const char* addr, bool dolisten) memset(&servaddr, 0, sizeof(servaddr)); servaddr.in4.sin_family = AF_INET; } - else if (!irc::sockets::aptosa(addr, port, &servaddr)) + else if (!irc::sockets::aptosa(addr, port, servaddr)) return false; ret = SE->Bind(sockfd, &servaddr.sa, sa_size(servaddr)); @@ -122,8 +122,8 @@ int InspIRCd::BindPorts(FailedPortList &failed_ports) while (0 != (portno = portrange.GetToken())) { irc::sockets::sockaddrs bindspec; - irc::sockets::aptosa(Addr, portno, &bindspec); - std::string bind_readable = irc::sockets::satouser(&bindspec); + irc::sockets::aptosa(Addr, portno, bindspec); + std::string bind_readable = irc::sockets::satouser(bindspec); bool skip = false; for (std::vector<ListenSocket*>::iterator n = old_ports.begin(); n != old_ports.end(); ++n) @@ -174,51 +174,52 @@ int InspIRCd::BindPorts(FailedPortList &failed_ports) return bound; } -bool irc::sockets::aptosa(const std::string& addr, int port, irc::sockets::sockaddrs* sa) +bool irc::sockets::aptosa(const std::string& addr, int port, irc::sockets::sockaddrs& sa) { - memset(sa, 0, sizeof(*sa)); + memset(&sa, 0, sizeof(sa)); if (addr.empty()) { #ifdef IPV6 - sa->in6.sin6_family = AF_INET6; - sa->in6.sin6_port = htons(port); + sa.in6.sin6_family = AF_INET6; + sa.in6.sin6_port = htons(port); #else - sa->in4.sin_family = AF_INET; - sa->in4.sin_port = htons(port); + sa.in4.sin_family = AF_INET; + sa.in4.sin_port = htons(port); #endif return true; } - else if (inet_pton(AF_INET, addr.c_str(), &sa->in4.sin_addr) > 0) + else if (inet_pton(AF_INET, addr.c_str(), &sa.in4.sin_addr) > 0) { - sa->in4.sin_family = AF_INET; - sa->in4.sin_port = htons(port); + sa.in4.sin_family = AF_INET; + sa.in4.sin_port = htons(port); return true; } - else if (inet_pton(AF_INET6, addr.c_str(), &sa->in6.sin6_addr) > 0) + else if (inet_pton(AF_INET6, addr.c_str(), &sa.in6.sin6_addr) > 0) { - sa->in6.sin6_family = AF_INET6; - sa->in6.sin6_port = htons(port); + sa.in6.sin6_family = AF_INET6; + sa.in6.sin6_port = htons(port); return true; } return false; } -bool irc::sockets::satoap(const irc::sockets::sockaddrs* sa, std::string& addr, int &port) { +bool irc::sockets::satoap(const irc::sockets::sockaddrs& sa, std::string& addr, int &port) +{ char addrv[INET6_ADDRSTRLEN+1]; - if (sa->sa.sa_family == AF_INET) + if (sa.sa.sa_family == AF_INET) { - if (!inet_ntop(AF_INET, &sa->in4.sin_addr, addrv, sizeof(addrv))) + if (!inet_ntop(AF_INET, &sa.in4.sin_addr, addrv, sizeof(addrv))) return false; addr = addrv; - port = ntohs(sa->in4.sin_port); + port = ntohs(sa.in4.sin_port); return true; } - else if (sa->sa.sa_family == AF_INET6) + else if (sa.sa.sa_family == AF_INET6) { - if (!inet_ntop(AF_INET6, &sa->in6.sin6_addr, addrv, sizeof(addrv))) + if (!inet_ntop(AF_INET6, &sa.in6.sin6_addr, addrv, sizeof(addrv))) return false; addr = addrv; - port = ntohs(sa->in6.sin6_port); + port = ntohs(sa.in6.sin6_port); return true; } return false; @@ -226,34 +227,35 @@ bool irc::sockets::satoap(const irc::sockets::sockaddrs* sa, std::string& addr, static const char all_zero[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; -std::string irc::sockets::satouser(const irc::sockets::sockaddrs* sa) { +std::string irc::sockets::satouser(const irc::sockets::sockaddrs& sa) +{ char buffer[MAXBUF]; - if (sa->sa.sa_family == AF_INET) + if (sa.sa.sa_family == AF_INET) { - if (sa->in4.sin_addr.s_addr == 0) + if (sa.in4.sin_addr.s_addr == 0) { - sprintf(buffer, "*:%u", ntohs(sa->in4.sin_port)); + sprintf(buffer, "*:%u", ntohs(sa.in4.sin_port)); } else { - const uint8_t* bits = reinterpret_cast<const uint8_t*>(&sa->in4.sin_addr); - sprintf(buffer, "%d.%d.%d.%d:%u", bits[0], bits[1], bits[2], bits[3], ntohs(sa->in4.sin_port)); + const uint8_t* bits = reinterpret_cast<const uint8_t*>(&sa.in4.sin_addr); + sprintf(buffer, "%d.%d.%d.%d:%u", bits[0], bits[1], bits[2], bits[3], ntohs(sa.in4.sin_port)); } } - else if (sa->sa.sa_family == AF_INET6) + else if (sa.sa.sa_family == AF_INET6) { - if (!memcmp(all_zero, &sa->in6.sin6_addr, 16)) + if (!memcmp(all_zero, &sa.in6.sin6_addr, 16)) { - sprintf(buffer, "*:%u", ntohs(sa->in6.sin6_port)); + sprintf(buffer, "*:%u", ntohs(sa.in6.sin6_port)); } else { buffer[0] = '['; - if (!inet_ntop(AF_INET6, &sa->in6.sin6_addr, buffer+1, MAXBUF - 10)) + if (!inet_ntop(AF_INET6, &sa.in6.sin6_addr, buffer+1, MAXBUF - 10)) return "<unknown>"; // should never happen, buffer is large enough int len = strlen(buffer); // no need for snprintf, buffer has at least 9 chars left, max short len = 5 - sprintf(buffer + len, "]:%u", ntohs(sa->in6.sin6_port)); + sprintf(buffer + len, "]:%u", ntohs(sa.in6.sin6_port)); } } else @@ -269,3 +271,33 @@ int irc::sockets::sa_size(const irc::sockets::sockaddrs& sa) return sizeof(sa.in6); return 0; } + +std::string irc::sockets::mask(irc::sockets::sockaddrs sa, unsigned int range) +{ + unsigned char* base; + unsigned int len; + if (sa.sa.sa_family == AF_INET) + { + base = (unsigned char*)&sa.in4.sin_addr; + len = 4; + } + else if (sa.sa.sa_family == AF_INET6) + { + base = (unsigned char*)&sa.in6.sin6_addr; + len = 16; + } + else + return ""; + if (range > 8*len) + range = 8*len; + unsigned int byte = range / 8; + unsigned int bits = (-1 << (range & 7)); + base[byte++] &= bits; + while (byte < len) + base[byte++] = 0; + int dummy; + std::string rv; + irc::sockets::satoap(sa, rv, dummy); + return rv + "/" + ConvToStr(range); +} + diff --git a/src/usermanager.cpp b/src/usermanager.cpp index bc058a462..511037596 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -254,60 +254,28 @@ void UserManager::QuitUser(User *user, const std::string &quitreason, const char void UserManager::AddLocalClone(User *user) { - int range = 32; clonemap::iterator x; - switch (user->client_sa.sa.sa_family) - { - case AF_INET6: - range = ServerInstance->Config->c_ipv6_range; - break; - case AF_INET: - range = ServerInstance->Config->c_ipv4_range; - break; - } - - x = local_clones.find(user->GetCIDRMask(range)); + x = local_clones.find(user->GetCIDRMask()); if (x != local_clones.end()) x->second++; else - local_clones[user->GetCIDRMask(range)] = 1; + local_clones[user->GetCIDRMask()] = 1; } void UserManager::AddGlobalClone(User *user) { - int range = 32; clonemap::iterator x; - switch (user->client_sa.sa.sa_family) - { - case AF_INET6: - range = ServerInstance->Config->c_ipv6_range; - break; - case AF_INET: - range = ServerInstance->Config->c_ipv4_range; - break; - } - x = global_clones.find(user->GetCIDRMask(range)); + x = global_clones.find(user->GetCIDRMask()); if (x != global_clones.end()) x->second++; else - global_clones[user->GetCIDRMask(range)] = 1; + global_clones[user->GetCIDRMask()] = 1; } void UserManager::RemoveCloneCounts(User *user) { - int range = 32; - switch (user->client_sa.sa.sa_family) - { - case AF_INET6: - range = ServerInstance->Config->c_ipv6_range; - break; - case AF_INET: - range = ServerInstance->Config->c_ipv4_range; - break; - } - - clonemap::iterator x = local_clones.find(user->GetCIDRMask(range)); + clonemap::iterator x = local_clones.find(user->GetCIDRMask()); if (x != local_clones.end()) { x->second--; @@ -317,7 +285,7 @@ void UserManager::RemoveCloneCounts(User *user) } } - clonemap::iterator y = global_clones.find(user->GetCIDRMask(range)); + clonemap::iterator y = global_clones.find(user->GetCIDRMask()); if (y != global_clones.end()) { y->second--; @@ -330,17 +298,7 @@ void UserManager::RemoveCloneCounts(User *user) unsigned long UserManager::GlobalCloneCount(User *user) { - int range = 32; - switch (user->client_sa.sa.sa_family) - { - case AF_INET6: - range = ServerInstance->Config->c_ipv6_range; - break; - case AF_INET: - range = ServerInstance->Config->c_ipv4_range; - break; - } - clonemap::iterator x = global_clones.find(user->GetCIDRMask(range)); + clonemap::iterator x = global_clones.find(user->GetCIDRMask()); if (x != global_clones.end()) return x->second; else @@ -349,17 +307,7 @@ unsigned long UserManager::GlobalCloneCount(User *user) unsigned long UserManager::LocalCloneCount(User *user) { - int range = 32; - switch (user->client_sa.sa.sa_family) - { - case AF_INET6: - range = ServerInstance->Config->c_ipv6_range; - break; - case AF_INET: - range = ServerInstance->Config->c_ipv4_range; - break; - } - clonemap::iterator x = local_clones.find(user->GetCIDRMask(range)); + clonemap::iterator x = local_clones.find(user->GetCIDRMask()); if (x != local_clones.end()) return x->second; else diff --git a/src/users.cpp b/src/users.cpp index e8e4a4825..d1a4b2528 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -936,108 +936,12 @@ int LocalUser::GetServerPort() return 0; } -const char* User::GetCIDRMask(int range) -{ - static char buf[44]; - - if (range < 0) - throw "Negative range, sorry, no."; - - /* - * Original code written by Oliver Lupton (Om). - * Integrated by me. Thanks. :) -- w00t - */ - switch (this->client_sa.sa.sa_family) - { - case AF_INET6: - { - /* unsigned char s6_addr[16]; */ - struct in6_addr v6; - int i, bytestozero, extrabits; - char buffer[40]; - - if(range > 128) - throw "CIDR mask width greater than address width (IPv6, 128 bit)"; - - /* 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] = client_sa.in6.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; - case AF_INET: - { - struct in_addr v4; - 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 */ - 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. - * This is done by shifting the value right and then back left by (32 - range) bits. - */ - if(range > 0) - { - v4.s_addr = ntohl(v4.s_addr); - v4.s_addr = (v4.s_addr >> (32 - range)) << (32 - range); - v4.s_addr = htonl(v4.s_addr); - } - 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() { int port; if (cachedip.empty()) { - irc::sockets::satoap(&client_sa, cachedip, port); + 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'); @@ -1046,10 +950,25 @@ const char* User::GetIPString() return cachedip.c_str(); } +irc::string User::GetCIDRMask() +{ + int range = 0; + switch (client_sa.sa.sa_family) + { + case AF_INET6: + range = ServerInstance->Config->c_ipv6_range; + break; + case AF_INET: + range = ServerInstance->Config->c_ipv4_range; + break; + } + return assign(irc::sockets::mask(client_sa, range)); +} + bool User::SetClientIP(const char* sip) { this->cachedip = ""; - return irc::sockets::aptosa(sip, 0, &client_sa); + return irc::sockets::aptosa(sip, 0, client_sa); } static std::string wide_newline("\r\n"); |