Skip to content

Commit

Permalink
Implement the cidr_match function
Browse files Browse the repository at this point in the history
fixes #10354
  • Loading branch information
gunnarbeutner committed Oct 14, 2015
1 parent a879f5e commit 06a0f18
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 0 deletions.
1 change: 1 addition & 0 deletions doc/21-library-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Function | Description
--------------------------------|-----------------------
regex(pattern, text) | Returns true if the regex pattern matches the text, false otherwise.
match(pattern, text) | Returns true if the wildcard pattern matches the text, false otherwise.
cidr_match(pattern, ip) | Returns true if the CIDR pattern matches the IP address, false otherwise. IPv4 addresses are converted to IPv4-mapped IPv6 addresses before being matched against the pattern.
len(value) | Returns the length of the value, i.e. the number of elements for an array or dictionary, or the length of the string in bytes.
union(array, array, ...) | Returns an array containing all unique elements from the specified arrays.
intersection(array, array, ...) | Returns an array containing all unique elements which are common to all specified arrays.
Expand Down
1 change: 1 addition & 0 deletions lib/base/scriptutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ using namespace icinga;

REGISTER_SAFE_SCRIPTFUNCTION(regex, &ScriptUtils::Regex);
REGISTER_SAFE_SCRIPTFUNCTION(match, &Utility::Match);
REGISTER_SAFE_SCRIPTFUNCTION(cidr_match, &Utility::CidrMatch);
REGISTER_SAFE_SCRIPTFUNCTION(len, &ScriptUtils::Len);
REGISTER_SAFE_SCRIPTFUNCTION(union, &ScriptUtils::Union);
REGISTER_SAFE_SCRIPTFUNCTION(intersection, &ScriptUtils::Intersection);
Expand Down
75 changes: 75 additions & 0 deletions lib/base/utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,81 @@ bool Utility::Match(const String& pattern, const String& text)
return (match(pattern.CStr(), text.CStr()) == 0);
}

static void ParseIpMask(const String& ip, char mask[16], int *bits)
{
String::SizeType slashp = ip.FindFirstOf("/");
String uip;

if (slashp == String::NPos) {
uip = ip;
*bits = 0;
} else {
uip = ip.SubStr(0, slashp);
*bits = Convert::ToLong(ip.SubStr(slashp + 1));
}

/* IPv4-mapped IPv6 address (::ffff:<ipv4-bits>) */
memset(mask, 0, 10);
memset(mask + 10, 0xff, 2);
if (inet_pton(AF_INET, uip.CStr(), mask + 12) < 1) {
if (inet_pton(AF_INET6, uip.CStr(), mask) < 1) {
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid IP address specified."));
}
} else
*bits += 96;

if (slashp == String::NPos)
*bits = 128;

if (*bits > 128)
BOOST_THROW_EXCEPTION(std::invalid_argument("Mask must not be greater than 128."));

/* TODO: validate mask */
for (int i = 0; i < 16; i++) {
int lbits = *bits - i * 8;

if (lbits >= 8)
continue;

if (mask[i] & (0xff >> lbits))
BOOST_THROW_EXCEPTION(std::invalid_argument("Masked-off bits must all be zero."));
}
}

static bool IpMaskCheck(char addr[16], char mask[16], int bits)
{
for (int i = 0; i < 16; i++) {
if (bits < 8)
return !((addr[i] ^ mask[i]) >> (8 - bits));

if (mask[i] != addr[i])
return false;

bits -= 8;

if (bits == 0)
return true;
}

return true;
}

bool Utility::CidrMatch(const String& pattern, const String& ip)
{
char mask[16], addr[16];
int bits;

try {
ParseIpMask(ip, addr, &bits);
} catch (const std::exception&) {
return false;
}

ParseIpMask(pattern, mask, &bits);

return IpMaskCheck(addr, mask, bits);
}

/**
* Returns the directory component of a path. See dirname(3) for details.
*
Expand Down
1 change: 1 addition & 0 deletions lib/base/utility.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class I2_BASE_API Utility
static String GetSymbolName(const void *addr);

static bool Match(const String& pattern, const String& text);
static bool CidrMatch(const String& pattern, const String& ip);

static String DirName(const String& path);
static String BaseName(const String& path);
Expand Down

0 comments on commit 06a0f18

Please sign in to comment.