summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2012-09-07 12:04:25 -0400
committerAdam <Adam@anope.org>2012-09-07 12:04:25 -0400
commit9d6626f70ce866e2e98ce7ce607695b14a8375b7 (patch)
treef9cf4e1bb295d4707be097898c4544101fcd7340 /src
parent5c07863ad503edfc8deb1dee38e6222602db54fd (diff)
Made session tracking ip based, not host based, and allow using CIDR to group multiple ips from one subnet to one session
Diffstat (limited to 'src')
-rw-r--r--src/config.cpp5
-rw-r--r--src/sockets.cpp32
2 files changed, 36 insertions, 1 deletions
diff --git a/src/config.cpp b/src/config.cpp
index 91cf8a805..fb1849e6c 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -214,6 +214,9 @@ ServerConfig::ServerConfig() : config_data(), NSDefFlags(NickCoreFlagStrings), C
Log() << "Unknown casemap " << this->CaseMap << " - casemap not changed";
}
}
+
+ if (this->SessionIPv4CIDR > 32 || this->SessionIPv6CIDR > 128)
+ throw ConfigException("Session CIDR value out of range");
}
bool ServerConfig::CheckOnce(const Anope::string &tag)
@@ -1284,6 +1287,8 @@ ConfigItems::ConfigItems(ServerConfig *conf)
{"operserv", "sessionlimitdetailsloc", "", new ValueContainerString(&conf->SessionLimitDetailsLoc), DT_STRING, NoValidation},
{"operserv", "maxsessionkill", "0", new ValueContainerUInt(&conf->MaxSessionKill), DT_UINTEGER, NoValidation},
{"operserv", "sessionautokillexpiry", "0", new ValueContainerTime(&conf->SessionAutoKillExpiry), DT_TIME, NoValidation},
+ {"operserv", "session_ipv4_cidr", "32", new ValueContainerUInt(&conf->SessionIPv4CIDR), DT_UINTEGER | DT_NORELOAD, NoValidation},
+ {"operserv", "session_ipv6_cidr", "128", new ValueContainerUInt(&conf->SessionIPv6CIDR), DT_UINTEGER | DT_NORELOAD, NoValidation},
{"operserv", "addakiller", "no", new ValueContainerBool(&conf->AddAkiller), DT_BOOLEAN, NoValidation},
{"operserv", "akillids", "no", new ValueContainerBool(&conf->AkillIds), DT_BOOLEAN, NoValidation},
{"operserv", "opersonly", "no", new ValueContainerBool(&conf->OSOpersOnly), DT_BOOLEAN, NoValidation},
diff --git a/src/sockets.cpp b/src/sockets.cpp
index 3d2df8dc9..7bb07f5c5 100644
--- a/src/sockets.cpp
+++ b/src/sockets.cpp
@@ -227,7 +227,7 @@ cidr::cidr(const Anope::string &ip, unsigned char len)
Anope::string cidr::mask() const
{
- return this->cidr_ip + "/" + this->cidr_len;
+ return Anope::printf("%s/%d", this->cidr_ip.c_str(), this->cidr_len);
}
bool cidr::match(sockaddrs &other)
@@ -265,6 +265,36 @@ bool cidr::match(sockaddrs &other)
return true;
}
+bool cidr::operator<(const cidr &other) const
+{
+ if (this->addr.sa.sa_family != other.addr.sa.sa_family)
+ return this->addr.sa.sa_family < other.addr.sa.sa_family;
+
+ switch (this->addr.sa.sa_family)
+ {
+ case AF_INET:
+ {
+ unsigned int m = 0xFFFFFFFFU >> (32 - this->cidr_len);
+
+ return (this->addr.sa4.sin_addr.s_addr & m) < (other.addr.sa4.sin_addr.s_addr & m);
+ }
+ case AF_INET6:
+ {
+ int i = memcmp(&this->addr.sa6.sin6_addr.s6_addr, &other.addr.sa6.sin6_addr.s6_addr, this->cidr_len / 8);
+ if (i || this->cidr_len >= 128)
+ return i < 0;
+
+ // Now all thats left is to compare 'remainig' bits at offset this->cidr_len / 8
+ int remaining = this->cidr_len % 8;
+ unsigned char m = 0xFF << (8 - remaining);
+
+ return (this->addr.sa6.sin6_addr.s6_addr[this->cidr_len / 8] & m) < (other.addr.sa6.sin6_addr.s6_addr[this->cidr_len / 8] & m);
+ }
+ default:
+ throw CoreException("Unknown AFTYPE for cidr");
+ }
+}
+
/** Receive something from the buffer
* @param s The socket
* @param buf The buf to read to