radix: Detect duplicate netblocks

This commit prevents duplicate IPV4/IPV6 netblocks from being added to the
radix tree.

Contributed by Giuseppe Longo <giuseppe@glongo.it>

Issue: 5748
pull/9306/head
Jeff Lucovsky 2 years ago committed by Victor Julien
parent a559d7c670
commit 427d2a71d5

@ -2606,7 +2606,7 @@ static void HTPConfigParseParameters(HTPCfgRec *cfg_prec, ConfNode *s,
if (strchr(pval->val, ':') != NULL) {
SCLogDebug("LIBHTP adding ipv6 server %s at %s: %p",
s->name, pval->val, cfg_prec->cfg);
if (SCRadixAddKeyIPV6String(pval->val, tree, cfg_prec) == NULL) {
if (!SCRadixAddKeyIPV6String(pval->val, tree, cfg_prec)) {
SCLogWarning("LIBHTP failed to "
"add ipv6 server %s, ignoring",
pval->val);
@ -2614,7 +2614,7 @@ static void HTPConfigParseParameters(HTPCfgRec *cfg_prec, ConfNode *s,
} else {
SCLogDebug("LIBHTP adding ipv4 server %s at %s: %p",
s->name, pval->val, cfg_prec->cfg);
if (SCRadixAddKeyIPV4String(pval->val, tree, cfg_prec) == NULL) {
if (!SCRadixAddKeyIPV4String(pval->val, tree, cfg_prec)) {
SCLogWarning("LIBHTP failed "
"to add ipv4 server %s, ignoring",
pval->val);

@ -51,13 +51,19 @@ static void DefragPolicyAddHostInfo(char *host_ip_range, uint64_t timeout)
if (strchr(host_ip_range, ':') != NULL) {
SCLogDebug("adding ipv6 host %s", host_ip_range);
if (SCRadixAddKeyIPV6String(host_ip_range, defrag_tree, (void *)user_data) == NULL) {
SCLogWarning("failed to add ipv6 host %s", host_ip_range);
if (!SCRadixAddKeyIPV6String(host_ip_range, defrag_tree, (void *)user_data)) {
SCFree(user_data);
if (sc_errno != SC_EEXIST) {
SCLogWarning("failed to add ipv6 host %s", host_ip_range);
}
}
} else {
SCLogDebug("adding ipv4 host %s", host_ip_range);
if (SCRadixAddKeyIPV4String(host_ip_range, defrag_tree, (void *)user_data) == NULL) {
SCLogWarning("failed to add ipv4 host %s", host_ip_range);
if (!SCRadixAddKeyIPV4String(host_ip_range, defrag_tree, (void *)user_data)) {
SCFree(user_data);
if (sc_errno != SC_EEXIST) {
SCLogWarning("failed to add ipv4 host %s", host_ip_range);
}
}
}
}

@ -99,9 +99,10 @@ static void SRepCIDRAddNetblock(SRepCIDRTree *cidr_ctx, char *ip, int cat, uint8
}
SCLogDebug("adding ipv6 host %s", ip);
if (SCRadixAddKeyIPV6String(ip, cidr_ctx->srepIPV6_tree[cat], (void *)user_data) == NULL) {
if (!SCRadixAddKeyIPV6String(ip, cidr_ctx->srepIPV6_tree[cat], (void *)user_data)) {
SCFree(user_data);
SCLogWarning("failed to add ipv6 host %s", ip);
if (sc_errno != SC_EEXIST)
SCLogWarning("failed to add ipv6 host %s", ip);
}
} else {
@ -115,9 +116,10 @@ static void SRepCIDRAddNetblock(SRepCIDRTree *cidr_ctx, char *ip, int cat, uint8
}
SCLogDebug("adding ipv4 host %s", ip);
if (SCRadixAddKeyIPV4String(ip, cidr_ctx->srepIPV4_tree[cat], (void *)user_data) == NULL) {
if (!SCRadixAddKeyIPV4String(ip, cidr_ctx->srepIPV4_tree[cat], (void *)user_data)) {
SCFree(user_data);
SCLogWarning("failed to add ipv4 host %s", ip);
if (sc_errno != SC_EEXIST)
SCLogWarning("failed to add ipv4 host %s", ip);
}
}
}

@ -482,11 +482,12 @@ void SCRadixReleaseRadixTree(SCRadixTree *tree)
* this key
* \param netmask The netmask (cidr) if we are adding an IP netblock; 255
* if we are not adding an IP netblock
* \param exclusive True if the node should be added iff it doesn't exist.
*
* \retval node Pointer to the newly created node
*/
static SCRadixNode *SCRadixAddKey(
uint8_t *key_stream, uint8_t key_bitlen, SCRadixTree *tree, void *user, uint8_t netmask)
static SCRadixNode *SCRadixAddKeyInternal(uint8_t *key_stream, uint8_t key_bitlen,
SCRadixTree *tree, void *user, uint8_t netmask, bool exclusive)
{
SCRadixNode *node = NULL;
SCRadixNode *new_node = NULL;
@ -506,6 +507,7 @@ static SCRadixNode *SCRadixAddKey(
if (tree == NULL) {
SCLogError("Argument \"tree\" NULL");
sc_errno = SC_EINVAL;
return NULL;
}
@ -518,18 +520,23 @@ static SCRadixNode *SCRadixAddKey(
if ( (prefix = SCRadixCreatePrefix(key_stream, key_bitlen, user,
netmask)) == NULL) {
SCLogError("Error creating prefix");
sc_errno = SC_EINVAL;
return NULL;
}
node = SCRadixCreateNode();
if (node == NULL) {
SCRadixReleasePrefix(prefix, tree);
sc_errno = SC_ENOMEM;
return NULL;
}
node->prefix = prefix;
node->bit = prefix->bitlen;
tree->head = node;
if (netmask == 255 || (netmask == 32 && key_bitlen == 32) || (netmask == 128 && key_bitlen == 128))
if (netmask == 255 || (netmask == 32 && key_bitlen == 32) ||
(netmask == 128 && key_bitlen == 128)) {
sc_errno = SC_EINVAL;
return node;
}
/* if we have reached here, we are actually having a proper netblock in
* our hand(i.e. < 32 for ipv4 and < 128 for ipv6). Add the netmask for
@ -545,6 +552,7 @@ static SCRadixNode *SCRadixAddKey(
SCFree(node->netmasks);
node->netmasks = NULL;
SCLogError("Fatal error encountered in SCRadixAddKey. Mem not allocated");
sc_errno = SC_ENOMEM;
return NULL;
}
node->netmasks = ptmp;
@ -640,6 +648,11 @@ static SCRadixNode *SCRadixAddKey(
if (SCRadixPrefixContainNetmask(node->prefix, netmask)) {
/* Basically we already have this stream prefix, as well as the
* netblock entry for this. A perfect duplicate. */
if (exclusive) {
SCLogDebug("not inserting since it already exists");
sc_errno = SC_EEXIST;
return NULL;
}
SCLogDebug("Duplicate entry for this ip address/netblock");
} else {
/* Basically we already have this stream prefix, but we don't
@ -672,6 +685,7 @@ static SCRadixNode *SCRadixAddKey(
SCFree(node->netmasks);
node->netmasks = NULL;
SCLogError("Fatal error encountered in SCRadixAddKey. Mem not allocated...");
sc_errno = SC_ENOMEM;
return NULL;
}
node->netmasks = ptmp;
@ -705,6 +719,7 @@ static SCRadixNode *SCRadixAddKey(
if ( (prefix = SCRadixCreatePrefix(key_stream, key_bitlen, user,
netmask)) == NULL) {
SCLogError("Error creating prefix");
sc_errno = SC_EINVAL;
return NULL;
}
new_node = SCRadixCreateNode();
@ -754,6 +769,7 @@ static SCRadixNode *SCRadixAddKey(
SCLogError("Fatal error encountered in SCRadixAddKey. Mem not allocated...");
SCRadixReleaseNode(inter_node, tree);
SCRadixReleaseNode(new_node, tree);
sc_errno = SC_ENOMEM;
return NULL;
}
@ -824,6 +840,18 @@ static SCRadixNode *SCRadixAddKey(
return new_node;
}
static SCRadixNode *SCRadixAddKeyExclusive(
uint8_t *key_stream, uint8_t key_bitlen, SCRadixTree *tree, void *user, uint8_t netmask)
{
return SCRadixAddKeyInternal(key_stream, key_bitlen, tree, user, netmask, true);
}
static SCRadixNode *SCRadixAddKey(
uint8_t *key_stream, uint8_t key_bitlen, SCRadixTree *tree, void *user, uint8_t netmask)
{
return SCRadixAddKeyInternal(key_stream, key_bitlen, tree, user, netmask, false);
}
/**
* \brief Adds a new IPV4 address to the Radix tree
*
@ -959,9 +987,14 @@ SCRadixNode *SCRadixAddKeyIPV6Netblock(uint8_t *key_stream, SCRadixTree *tree,
* \param user Pointer to the user data that has to be associated with
* the key
*
* \retval node Pointer to the newly created node
* \retval bool true (false) if the node was (wasn't) added.
*
* sc_errno is set:
* - SC_OK: Node added
* - SC_EEXIST: Node already exists
* - SC_EINVAL: Parameter value error
*/
SCRadixNode *SCRadixAddKeyIPV4String(const char *str, SCRadixTree *tree, void *user)
bool SCRadixAddKeyIPV4String(const char *str, SCRadixTree *tree, void *user)
{
uint32_t ip;
uint8_t netmask = 32;
@ -980,12 +1013,14 @@ SCRadixNode *SCRadixAddKeyIPV4String(const char *str, SCRadixTree *tree, void *u
/* Dotted type netmask not supported (yet) */
if (strchr(mask_str, '.') != NULL) {
return NULL;
sc_errno = SC_EINVAL;
return false;
}
/* Get binary values for cidr mask */
if (StringParseU8RangeCheck(&cidr, 10, 0, (const char *)mask_str, 0, 32) < 0) {
return NULL;
sc_errno = SC_EINVAL;
return false;
}
netmask = (uint8_t)cidr;
@ -993,7 +1028,8 @@ SCRadixNode *SCRadixAddKeyIPV4String(const char *str, SCRadixTree *tree, void *u
/* Validate the IP */
if (inet_pton(AF_INET, ip_str, &addr) <= 0) {
return NULL;
sc_errno = SC_EINVAL;
return false;
}
ip = addr.s_addr;
if (netmask != 32) {
@ -1009,7 +1045,14 @@ SCRadixNode *SCRadixAddKeyIPV4String(const char *str, SCRadixTree *tree, void *u
SCRadixValidateIPv4Key((uint8_t *)&ip, netmask);
#endif
}
return SCRadixAddKey((uint8_t *)&ip, 32, tree, user, netmask);
SCLogDebug("trying to add %s, but only if it doesn't exist", ip_str);
/* Add, but only if not there */
if (SCRadixAddKeyExclusive((uint8_t *)&ip, 32, tree, user, netmask) == NULL) {
return false;
}
return true;
}
/**
@ -1020,9 +1063,13 @@ SCRadixNode *SCRadixAddKeyIPV4String(const char *str, SCRadixTree *tree, void *u
* \param user Pointer to the user data that has to be associated with
* the key
*
* \retval node Pointer to the newly created node
* \retval bool true (false) if the node was (wasn't) added.
* sc_errno is set:
* - SC_OK: Node added
* - SC_EEXIST: Node already exists
* - SC_EINVAL: Parameter value error
*/
SCRadixNode *SCRadixAddKeyIPV6String(const char *str, SCRadixTree *tree, void *user)
bool SCRadixAddKeyIPV6String(const char *str, SCRadixTree *tree, void *user)
{
uint8_t netmask = 128;
char ip_str[80]; /* Max length for full ipv6/mask string with NUL */
@ -1040,12 +1087,14 @@ SCRadixNode *SCRadixAddKeyIPV6String(const char *str, SCRadixTree *tree, void *u
/* Dotted type netmask not supported (yet) */
if (strchr(mask_str, '.') != NULL) {
return NULL;
sc_errno = SC_EINVAL;
return false;
}
/* Get binary values for cidr mask */
if (StringParseU8RangeCheck(&cidr, 10, 0, (const char *)mask_str, 0, 128) < 0) {
return NULL;
sc_errno = SC_EINVAL;
return false;
}
netmask = (uint8_t)cidr;
@ -1053,7 +1102,8 @@ SCRadixNode *SCRadixAddKeyIPV6String(const char *str, SCRadixTree *tree, void *u
/* Validate the IP */
if (inet_pton(AF_INET6, ip_str, &addr) <= 0) {
return NULL;
sc_errno = SC_EINVAL;
return false;
}
if (netmask != 128) {
@ -1075,7 +1125,14 @@ SCRadixNode *SCRadixAddKeyIPV6String(const char *str, SCRadixTree *tree, void *u
#endif
}
return SCRadixAddKey(addr.s6_addr, 128, tree, user, netmask);
SCLogDebug("trying to add %s, but only if it doesn't exist", str);
/* Add, but only if not there */
if (SCRadixAddKeyExclusive(addr.s6_addr, 128, tree, user, netmask) == NULL) {
return false;
}
sc_errno = SC_OK;
return true;
}
static void SCRadixTransferNetmasksBWNodes(SCRadixNode *dest, SCRadixNode *src)

@ -102,8 +102,8 @@ SCRadixNode *SCRadixAddKeyIPV4Netblock(uint8_t *, SCRadixTree *, void *,
uint8_t);
SCRadixNode *SCRadixAddKeyIPV6Netblock(uint8_t *, SCRadixTree *, void *,
uint8_t);
SCRadixNode *SCRadixAddKeyIPV4String(const char *, SCRadixTree *, void *);
SCRadixNode *SCRadixAddKeyIPV6String(const char *, SCRadixTree *, void *);
bool SCRadixAddKeyIPV4String(const char *, SCRadixTree *, void *);
bool SCRadixAddKeyIPV6String(const char *, SCRadixTree *, void *);
void SCRadixRemoveKeyGeneric(uint8_t *, uint16_t, SCRadixTree *);
void SCRadixRemoveKeyIPV4Netblock(uint8_t *, SCRadixTree *, uint8_t);

Loading…
Cancel
Save