* 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;
if (tree == NULL) {
SCLogError("Argument \"tree\" NULL");
+ sc_errno = SC_EINVAL;
return NULL;
}
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
SCFree(node->netmasks);
node->netmasks = NULL;
SCLogError("Fatal error encountered in SCRadixAddKey. Mem not allocated");
+ sc_errno = SC_ENOMEM;
return NULL;
}
node->netmasks = ptmp;
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
SCFree(node->netmasks);
node->netmasks = NULL;
SCLogError("Fatal error encountered in SCRadixAddKey. Mem not allocated...");
+ sc_errno = SC_ENOMEM;
return NULL;
}
node->netmasks = ptmp;
if ( (prefix = SCRadixCreatePrefix(key_stream, key_bitlen, user,
netmask)) == NULL) {
SCLogError("Error creating prefix");
+ sc_errno = SC_EINVAL;
return NULL;
}
new_node = SCRadixCreateNode();
SCLogError("Fatal error encountered in SCRadixAddKey. Mem not allocated...");
SCRadixReleaseNode(inter_node, tree);
SCRadixReleaseNode(new_node, tree);
+ sc_errno = SC_ENOMEM;
return NULL;
}
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
*
* \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;
/* 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;
/* 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) {
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;
}
/**
* \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 */
/* 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;
/* Validate the IP */
if (inet_pton(AF_INET6, ip_str, &addr) <= 0) {
- return NULL;
+ sc_errno = SC_EINVAL;
+ return false;
}
if (netmask != 128) {
#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)