00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "inspircd.h"
00017
00018
00019
00020
00021
00022
00023 const unsigned char inverted_bits[8] = { 0x00,
00024 0x80,
00025 0xC0,
00026 0xE0,
00027 0xF0,
00028 0xF8,
00029 0xFC,
00030 0xFE
00031 };
00032
00033
00034
00035 bool irc::sockets::MatchCIDRBits(const unsigned char* address, const unsigned char* mask, unsigned int mask_bits)
00036 {
00037 unsigned int divisor = mask_bits / 8;
00038 unsigned int modulus = mask_bits % 8;
00039
00040
00041 if (modulus)
00042 if ((address[divisor] & inverted_bits[modulus]) != (mask[divisor] & inverted_bits[modulus]))
00043
00044 return false;
00045
00046
00047 if (memcmp(address, mask, divisor))
00048 return false;
00049
00050
00051 return true;
00052 }
00053
00054
00055 bool irc::sockets::MatchCIDR(const std::string &address, const std::string &cidr_mask)
00056 {
00057 return MatchCIDR(address, cidr_mask, false);
00058 }
00059
00060
00061
00062
00063
00064
00065
00066
00067 bool irc::sockets::MatchCIDR(const std::string &address, const std::string &cidr_mask, bool match_with_username)
00068 {
00069 unsigned char addr_raw[16];
00070 unsigned char mask_raw[16];
00071 unsigned int bits = 0;
00072
00073 std::string address_copy;
00074 std::string cidr_copy;
00075
00076
00077
00078
00079
00080 if (match_with_username)
00081 {
00082
00083 std::string::size_type username_mask_pos = cidr_mask.rfind('@');
00084 std::string::size_type username_addr_pos = address.rfind('@');
00085
00086
00087 if (username_mask_pos != std::string::npos && username_addr_pos != std::string::npos)
00088 {
00089
00090
00091
00092
00093 return (InspIRCd::Match(address.substr(0, username_addr_pos), cidr_mask.substr(0, username_mask_pos), NULL) &&
00094 MatchCIDR(address.substr(username_addr_pos + 1), cidr_mask.substr(username_mask_pos + 1), false));
00095 }
00096 else
00097 {
00098 address_copy = address.substr(username_addr_pos + 1);
00099 cidr_copy = cidr_mask.substr(username_mask_pos + 1);
00100 }
00101 }
00102 else
00103 {
00104 address_copy.assign(address);
00105 cidr_copy.assign(cidr_mask);
00106 }
00107
00108 in_addr address_in4;
00109 in_addr mask_in4;
00110
00111 std::string::size_type bits_chars = cidr_copy.rfind('/');
00112
00113 if (bits_chars != std::string::npos)
00114 {
00115 bits = atoi(cidr_copy.substr(bits_chars + 1).c_str());
00116 cidr_copy.erase(bits_chars, cidr_copy.length() - bits_chars);
00117 }
00118 else
00119 {
00120
00121 return false;
00122 }
00123
00124 #ifdef SUPPORT_IP6LINKS
00125 in6_addr address_in6;
00126 in6_addr mask_in6;
00127
00128 if (inet_pton(AF_INET6, address_copy.c_str(), &address_in6) > 0)
00129 {
00130 if (inet_pton(AF_INET6, cidr_copy.c_str(), &mask_in6) > 0)
00131 {
00132 memcpy(&addr_raw, &address_in6.s6_addr, 16);
00133 memcpy(&mask_raw, &mask_in6.s6_addr, 16);
00134
00135 if (bits > 128)
00136 bits = 128;
00137 }
00138 else
00139 {
00140
00141
00142
00143 return false;
00144 }
00145 }
00146 else
00147 #endif
00148 if (inet_pton(AF_INET, address_copy.c_str(), &address_in4) > 0)
00149 {
00150 if (inet_pton(AF_INET, cidr_copy.c_str(), &mask_in4) > 0)
00151 {
00152 memcpy(&addr_raw, &address_in4.s_addr, 4);
00153 memcpy(&mask_raw, &mask_in4.s_addr, 4);
00154
00155 if (bits > 32)
00156 bits = 32;
00157 }
00158 else
00159 {
00160
00161
00162
00163 return false;
00164 }
00165 }
00166 else
00167 {
00168
00169 return false;
00170 }
00171
00172
00173 return MatchCIDRBits(addr_raw, mask_raw, bits);
00174 }
00175
00176