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 7313012d1737..b9f2186d0100 100644 --- a/src/reputation.c +++ b/src/reputation.c @@ -46,7 +46,7 @@ SC_ATOMIC_DECLARE(uint32_t, srep_eversion); /** reputation version set to the host's reputation, * this will be set to 1 before rep files are loaded, - * so hosts will always have a minial value of 1 */ + * so hosts will always have a minimal value of 1 */ static uint32_t srep_version = 0; static uint32_t SRepIncrVersion(void) @@ -99,8 +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) { - SCLogWarning("failed to add ipv6 host %s", ip); + if (!SCRadixAddKeyIPV6String(ip, cidr_ctx->srepIPV6_tree[cat], (void *)user_data)) { + SCFree(user_data); + if (sc_errno != SC_EEXIST) + SCLogWarning("failed to add ipv6 host %s", ip); } } else { @@ -114,8 +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) { - SCLogWarning("failed to add ipv4 host %s", ip); + if (!SCRadixAddKeyIPV4String(ip, cidr_ctx->srepIPV4_tree[cat], (void *)user_data)) { + SCFree(user_data); + if (sc_errno != SC_EEXIST) + SCLogWarning("failed to add ipv4 host %s", ip); } } } diff --git a/src/util-error.c b/src/util-error.c index 617ab161fe8f..01c2f9a01b73 100644 --- a/src/util-error.c +++ b/src/util-error.c @@ -46,6 +46,7 @@ const char * SCErrorToString(SCError err) CASE_CODE(SC_ENOMEM); CASE_CODE(SC_EINVAL); CASE_CODE(SC_ELIMIT); + CASE_CODE(SC_EEXIST); CASE_CODE (SC_ERR_MAX); } diff --git a/src/util-error.h b/src/util-error.h index 257dcc07c465..eaaf8cb34a2a 100644 --- a/src/util-error.h +++ b/src/util-error.h @@ -29,6 +29,7 @@ typedef enum { SC_ENOMEM, SC_EINVAL, SC_ELIMIT, + SC_EEXIST, SC_ERR_MAX } SCError; diff --git a/src/util-radix-tree.c b/src/util-radix-tree.c index e1fc79bb8894..97c85602d8a0 100644 --- a/src/util-radix-tree.c +++ b/src/util-radix-tree.c @@ -295,16 +295,14 @@ static int SCRadixPrefixNetmaskCount(SCRadixPrefix *prefix) * * \param prefix Pointer to the ip prefix that is being checked. * \param netmask The netmask value for which we will have to return the user_data - * \param exact_match Bool flag which indicates if we should check if the prefix + * \param exact_match flag which indicates if we should check if the prefix * holds proper netblock(< 32 for ipv4 and < 128 for ipv6) or not. * * \retval 1 On match. * \retval 0 On no match. */ -static int SCRadixPrefixContainNetmaskAndSetUserData(SCRadixPrefix *prefix, - uint16_t netmask, - int exact_match, - void **user_data_result) +static int SCRadixPrefixContainNetmaskAndSetUserData( + SCRadixPrefix *prefix, uint16_t netmask, bool exact_match, void **user_data_result) { SCRadixUserData *user_data = NULL; @@ -484,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; @@ -508,6 +507,7 @@ static SCRadixNode *SCRadixAddKey( if (tree == NULL) { SCLogError("Argument \"tree\" NULL"); + sc_errno = SC_EINVAL; return NULL; } @@ -520,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 @@ -547,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; @@ -642,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 @@ -674,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; @@ -707,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(); @@ -756,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; } @@ -826,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 * @@ -961,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; @@ -982,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; @@ -995,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) { @@ -1011,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; } /** @@ -1022,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 */ @@ -1042,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; @@ -1055,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) { @@ -1077,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) @@ -1449,7 +1504,8 @@ static inline SCRadixNode *SCRadixFindKeyIPNetblock( if (key_bitlen % 8 == 0 || (node->prefix->stream[bytes] & mask) == (key_stream[bytes] & mask)) { - if (SCRadixPrefixContainNetmaskAndSetUserData(node->prefix, netmask_node->netmasks[j], 0, user_data_result)) + if (SCRadixPrefixContainNetmaskAndSetUserData( + node->prefix, netmask_node->netmasks[j], false, user_data_result)) return node; } } @@ -1469,7 +1525,7 @@ static inline SCRadixNode *SCRadixFindKeyIPNetblock( * \param netmask Netmask used during exact match */ static SCRadixNode *SCRadixFindKey(uint8_t *key_stream, uint8_t key_bitlen, uint8_t netmask, - SCRadixTree *tree, int exact_match, void **user_data_result) + SCRadixTree *tree, bool exact_match, void **user_data_result) { if (tree == NULL || tree->head == NULL) return NULL; @@ -1506,7 +1562,7 @@ static SCRadixNode *SCRadixFindKey(uint8_t *key_stream, uint8_t key_bitlen, uint if (key_bitlen % 8 == 0 || (node->prefix->stream[bytes] & mask) == (tmp_stream[bytes] & mask)) { if (SCRadixPrefixContainNetmaskAndSetUserData( - node->prefix, netmask, 1, user_data_result)) { + node->prefix, netmask, true, user_data_result)) { return node; } } @@ -1530,7 +1586,7 @@ static SCRadixNode *SCRadixFindKey(uint8_t *key_stream, uint8_t key_bitlen, uint */ SCRadixNode *SCRadixFindKeyIPV4ExactMatch(uint8_t *key_stream, SCRadixTree *tree, void **user_data_result) { - return SCRadixFindKey(key_stream, 32, 32, tree, 1, user_data_result); + return SCRadixFindKey(key_stream, 32, 32, tree, true, user_data_result); } /** @@ -1542,7 +1598,7 @@ SCRadixNode *SCRadixFindKeyIPV4ExactMatch(uint8_t *key_stream, SCRadixTree *tree */ SCRadixNode *SCRadixFindKeyIPV4BestMatch(uint8_t *key_stream, SCRadixTree *tree, void **user_data_result) { - return SCRadixFindKey(key_stream, 32, 32, tree, 0, user_data_result); + return SCRadixFindKey(key_stream, 32, 32, tree, false, user_data_result); } /** @@ -1558,7 +1614,7 @@ SCRadixNode *SCRadixFindKeyIPV4Netblock(uint8_t *key_stream, SCRadixTree *tree, #if defined(DEBUG_VALIDATION) || defined(UNITTESTS) SCRadixValidateIPv4Key(key_stream, netmask); #endif - SCRadixNode *node = SCRadixFindKey(key_stream, 32, netmask, tree, 1, user_data_result); + SCRadixNode *node = SCRadixFindKey(key_stream, 32, netmask, tree, true, user_data_result); return node; } @@ -1575,7 +1631,7 @@ SCRadixNode *SCRadixFindKeyIPV6Netblock(uint8_t *key_stream, SCRadixTree *tree, #if defined(DEBUG_VALIDATION) || defined(UNITTESTS) SCRadixValidateIPv6Key(key_stream, netmask); #endif - SCRadixNode *node = SCRadixFindKey(key_stream, 128, netmask, tree, 1, user_data_result); + SCRadixNode *node = SCRadixFindKey(key_stream, 128, netmask, tree, true, user_data_result); return node; } @@ -1588,7 +1644,7 @@ SCRadixNode *SCRadixFindKeyIPV6Netblock(uint8_t *key_stream, SCRadixTree *tree, */ SCRadixNode *SCRadixFindKeyIPV6ExactMatch(uint8_t *key_stream, SCRadixTree *tree, void **user_data_result) { - return SCRadixFindKey(key_stream, 128, 128, tree, 1, user_data_result); + return SCRadixFindKey(key_stream, 128, 128, tree, true, user_data_result); } /** @@ -1600,7 +1656,7 @@ SCRadixNode *SCRadixFindKeyIPV6ExactMatch(uint8_t *key_stream, SCRadixTree *tree */ SCRadixNode *SCRadixFindKeyIPV6BestMatch(uint8_t *key_stream, SCRadixTree *tree, void **user_data_result) { - return SCRadixFindKey(key_stream, 128, 128, tree, 0, user_data_result); + return SCRadixFindKey(key_stream, 128, 128, tree, false, user_data_result); } /** 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);