summaryrefslogtreecommitdiff
path: root/src/sockets.cpp
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2010-11-20 21:45:30 -0500
committerAdam <Adam@anope.org>2010-12-12 19:35:27 -0500
commit246f44b9888161aecefc81f0ff17ddd893287e3c (patch)
treeb89607a9ad9c91914f292fc54cc32213a8d9f5c4 /src/sockets.cpp
parenta85112172d842aa74aa5531788d383328d153e74 (diff)
Added cs_mode, rewrote the old list mode code, and added CIDR support
Diffstat (limited to 'src/sockets.cpp')
-rw-r--r--src/sockets.cpp74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/sockets.cpp b/src/sockets.cpp
index 9e32f85eb..0eb7733cf 100644
--- a/src/sockets.cpp
+++ b/src/sockets.cpp
@@ -171,6 +171,80 @@ void sockaddrs::ntop(int type, const void *src)
throw CoreException("Invalid socket type");
}
+cidr::cidr(const Anope::string &ip)
+{
+ if (ip.find_first_not_of("01234567890:./") != Anope::string::npos)
+ throw SocketException("Invalid IP");
+
+ bool ipv6 = ip.find(':') != Anope::string::npos;
+ size_t sl = ip.find_last_of('/');
+ if (sl == Anope::string::npos)
+ {
+ this->cidr_ip = ip;
+ this->cidr_len = ipv6 ? 128 : 32;
+ this->addr.pton(ipv6 ? AF_INET6 : AF_INET, ip);
+ }
+ else
+ {
+ Anope::string real_ip = ip.substr(0, sl);
+ Anope::string cidr_range = ip.substr(sl + 1);
+ if (!cidr_range.is_pos_number_only())
+ throw SocketException("Invalid CIDR range");
+
+ this->cidr_ip = real_ip;
+ this->cidr_len = convertTo<unsigned int>(cidr_range);
+ this->addr.pton(ipv6 ? AF_INET6 : AF_INET, real_ip);
+ }
+}
+
+cidr::cidr(const Anope::string &ip, unsigned char len)
+{
+ bool ipv6 = ip.find(':') != Anope::string::npos;
+ this->addr.pton(ipv6 ? AF_INET6 : AF_INET, ip);
+ this->cidr_ip = ip;
+ this->cidr_len = len;
+}
+
+Anope::string cidr::mask() const
+{
+ return this->cidr_ip + "/" + this->cidr_len;
+}
+
+bool cidr::match(sockaddrs &other)
+{
+ if (this->addr.sa.sa_family != other.sa.sa_family)
+ return false;
+
+ unsigned char *ip, *their_ip, byte;
+
+ switch (this->addr.sa.sa_family)
+ {
+ case AF_INET:
+ ip = reinterpret_cast<unsigned char *>(&this->addr.sa4.sin_addr);
+ byte = this->cidr_len / 8;
+ their_ip = reinterpret_cast<unsigned char *>(&other.sa4.sin_addr);
+ break;
+ case AF_INET6:
+ ip = reinterpret_cast<unsigned char *>(&this->addr.sa6.sin6_addr);
+ byte = this->cidr_len / 8;
+ their_ip = reinterpret_cast<unsigned char *>(&other.sa6.sin6_addr);
+ break;
+ default:
+ throw SocketException("Invalid address type");
+ }
+
+ if (memcmp(ip, their_ip, byte))
+ return false;
+
+ ip += byte;
+ their_ip += byte;
+ byte = this->cidr_len % 8;
+ if ((*ip & byte) != (*their_ip & byte))
+ return false;
+
+ return true;
+}
+
/** Default constructor
*/
SocketEngineBase::SocketEngineBase()