diff --git a/src/app-layer-htp.c b/src/app-layer-htp.c index 312ca78ba29f..b576ba3b7b97 100644 --- a/src/app-layer-htp.c +++ b/src/app-layer-htp.c @@ -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); diff --git a/src/defrag-config.c b/src/defrag-config.c index 9e565c66b0a8..7e2ae0cde96a 100644 --- a/src/defrag-config.c +++ b/src/defrag-config.c @@ -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); + } } } } diff --git a/src/reputation.c b/src/reputation.c index 23080620c1c1..b9f2186d0100 100644 --- a/src/reputation.c +++ b/src/reputation.c @@ -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); } } } diff --git a/src/util-radix-tree.c b/src/util-radix-tree.c index d5601ba0546e..97c85602d8a0 100644 --- a/src/util-radix-tree.c +++ b/src/util-radix-tree.c @@ -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) diff --git a/src/util-radix-tree.h b/src/util-radix-tree.h index c8fdef689ab1..c43e14eb0126 100644 --- a/src/util-radix-tree.h +++ b/src/util-radix-tree.h @@ -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);