37#define ADDRESS_BYTES (uint8_t)4
38#define NETMASK_MAX (uint8_t)32
40#define RADIX_TREE_TYPE SCRadix4Tree
41#define RADIX_NODE_TYPE SCRadix4Node
42#define RADIX_CONFIG_TYPE SCRadix4Config
43#define RADIX_TREE_COMPARE_CALLBACK SCRadix4TreeCompareFunc
45static void PrintUserdata(
SCRadix4Node *node,
int level,
void (*PrintData)(
void *));
47static inline void AddNetmaskToMasks(
SCRadix4Node *node,
int netmask)
49 SCLogDebug(
"masks %" PRIX64
", adding %d/%" PRIX64, (uint64_t)node->
masks, netmask,
55static inline void RemoveNetmaskFromMasks(
SCRadix4Node *node,
int netmask)
57 SCLogDebug(
"masks %" PRIX64
", removing %d/%" PRIX64, (uint64_t)node->
masks, netmask,
59 node->
masks &= ~BIT_U64(netmask);
68static inline bool NetmasksEmpty(
const SCRadix4Node *node)
70 return (node->
masks == 0);
73static inline bool NetmaskEqualsMask(
const SCRadix4Node *node,
int netmask)
78static inline bool NetmaskIssetInMasks(
const SCRadix4Node *node,
int netmask)
85 const int differ_bit = inter_node->
bit;
97 inter_node->
masks &= ~rem;
107static void PrintNodeInfo(
SCRadix4Node *node,
int level,
void (*PrintData)(
void *))
112 for (
int i = 0; i < level; i++)
115 printf(
"%d [", node->
bit);
117 if (node->
masks == 0) {
120 for (
int i = 0, x = 0; i <= 32; i++) {
122 printf(
"%s%d", (x && x < 32) ?
", " :
"", i);
132 printf(
"%s - user_data %p)\n", addr, node->
user_data);
133 PrintUserdata(node, level + 1, PrintData);
135 printf(
"no prefix)\n");
143 const SCRadix4Tree *tree,
const uint8_t *key,
void **user_data)
145 return FindExactMatch(tree, key, user_data);
149 const SCRadix4Tree *tree,
const uint8_t *key,
const uint8_t netmask,
void **user_data)
151 return FindNetblock(tree, key, netmask, user_data);
155 const SCRadix4Tree *tree,
const uint8_t *key,
void **user_data)
157 return FindBestMatch(tree, key, user_data);
161 const SCRadix4Tree *tree,
const uint8_t *key,
void **user_data, uint8_t *out_netmask)
163 return FindBestMatch2(tree, key, user_data, out_netmask);
174 TreeRelease(tree, config);
191 return AddKey(tree, config, key_stream, 32, user,
false);
207 const uint8_t *key_stream, uint8_t netmask,
void *user)
209 return AddKey(tree, config, key_stream, netmask, user,
false);
231 uint8_t netmask = 32;
233 char *mask_str = NULL;
238 *(ip_str + (
sizeof(ip_str) - 1)) =
'\0';
241 if (NULL != (mask_str = strchr(ip_str,
'/'))) {
242 *(mask_str++) =
'\0';
245 if (strchr(mask_str,
'.') != NULL) {
255 netmask = (uint8_t)cidr;
259 if (inet_pton(AF_INET, ip_str, &addr) <= 0) {
265 if (AddKey(tree, config, (uint8_t *)&ip, netmask, user,
true) == NULL) {
285 RemoveKey(tree, config, key_stream, 32);
297 const uint8_t *key_stream, uint8_t netmask)
300 RemoveKey(tree, config, key_stream, netmask);
305 PrintTree(tree, config);
308static void PrintUserdata(
SCRadix4Node *node,
int level,
void (*PrintData)(
void *))
310 if (PrintData != NULL) {
313 for (
int i = 0; i < level; i++)
322 for (
int i = 0; i < level; i++)
324 printf(
" [%d], ", ud->
netmask);
330static int SCRadix4ForEachNodeSub(
337 if (Callback(node, ud->
user, ud->
netmask, data) < 0)
342 if (SCRadix4ForEachNodeSub(node->
left, Callback, data) < 0)
346 if (SCRadix4ForEachNodeSub(node->
right, Callback, data) < 0)
354 if (tree->
head == NULL)
356 return SCRadix4ForEachNodeSub(tree->
head, Callback, data);
362 return CompareTrees(t1, t2, Callback);
371#define GET_IPV4(str) \
372 SCLogDebug("setting up %s", (str)); \
373 memset(&(sa), 0, sizeof((sa))); \
374 FAIL_IF(inet_pton(AF_INET, (str), &(sa).sin_addr) <= 0);
376#define ADD_IPV4(str) \
378 SCRadix4AddKeyIPV4(&tree, &ut_ip_radix4_config, (uint8_t *)&(sa).sin_addr, NULL);
380#define REM_IPV4(str) \
382 SCRadix4RemoveKeyIPV4(&tree, &ut_ip_radix4_config, (uint8_t *)&(sa).sin_addr);
384#define ADD_IPV4_MASK(str, cidr) \
386 SCRadix4AddKeyIPV4Netblock( \
387 &tree, &ut_ip_radix4_config, (uint8_t *)&(sa).sin_addr, (cidr), NULL);
389#define REM_IPV4_MASK(str, cidr) \
391 SCRadix4RemoveKeyIPV4Netblock(&tree, &ut_ip_radix4_config, (uint8_t *)&(sa).sin_addr, (cidr));
393static int SCRadix4TestIPV4Insertion03(
void)
395 struct sockaddr_in sa;
444static int SCRadix4TestIPV4Removal04(
void)
446 struct sockaddr_in sa;
487static int SCRadix4TestIPV4NetblockInsertion09(
void)
489 struct sockaddr_in sa;
528static int SCRadix4TestIPV4NetblockInsertion10(
void)
531 struct sockaddr_in sa;
545 &tree, &ut_ip_radix4_config, (uint8_t *)&sa.sin_addr, 24, NULL);
548 node[1] =
SCRadix4AddKeyIPV4(&tree, &ut_ip_radix4_config, (uint8_t *)&sa.sin_addr, NULL);
578static int SCRadix4TestIPV4NetblockInsertion11(
void)
580 struct sockaddr_in sa;
598 &tree, &ut_ip_radix4_config, (uint8_t *)&sa.sin_addr, 0, NULL);
660static int SCRadix4TestIPV4NetblockInsertion12(
void)
662 struct sockaddr_in sa;
677 &tree, &ut_ip_radix4_config, (uint8_t *)&sa.sin_addr, 24, NULL);
681 node[1] =
SCRadix4AddKeyIPV4(&tree, &ut_ip_radix4_config, (uint8_t *)&sa.sin_addr, NULL);
721static int SCRadix4TestIPV4NetBlocksAndBestSearch16(
void)
723 struct sockaddr_in sa;
728 for (uint32_t i = 0; i <= 32; i++) {
729 uint32_t *user =
SCMalloc(
sizeof(uint32_t));
733 void *user_data = NULL;
737 FAIL_IF(*((uint32_t *)user_data) != i);
748static int SCRadix4TestIPV4NetBlocksAndBestSearch19(
void)
750 struct sockaddr_in sa;
751 void *user_data = NULL;
755 uint32_t *user =
SCMalloc(
sizeof(uint32_t));
764 FAIL_IF(*((uint32_t *)user_data) != 100);
777 FAIL_IF(*((uint32_t *)user_data) != 200);
784 FAIL_IF(*((uint32_t *)user_data) != 100);
797 FAIL_IF(*((uint32_t *)user_data) != 300);
804 FAIL_IF(*((uint32_t *)user_data) != 300);
811 FAIL_IF(*((uint32_t *)user_data) != 200);
818 FAIL_IF(*((uint32_t *)user_data) != 100);
830static int SCRadix4TestIPV4NetblockInsertion25(
void)
832 struct sockaddr_in sa;
846static int SCRadix4TestIPV4NetblockInsertion26(
void)
849 struct sockaddr_in sa;
868 FAIL_IF_NOT(strcmp((
char *)retptr,
"Hello3") == 0);
873static int SCRadix4TestIPV4InsertRemove01(
void)
875 struct sockaddr_in sa;
925 UtRegisterTest(
"SCRadix4TestIPV4Insertion03", SCRadix4TestIPV4Insertion03);
926 UtRegisterTest(
"SCRadix4TestIPV4Removal04", SCRadix4TestIPV4Removal04);
927 UtRegisterTest(
"SCRadix4TestIPV4NetblockInsertion09", SCRadix4TestIPV4NetblockInsertion09);
928 UtRegisterTest(
"SCRadix4TestIPV4NetblockInsertion10", SCRadix4TestIPV4NetblockInsertion10);
929 UtRegisterTest(
"SCRadix4TestIPV4NetblockInsertion11", SCRadix4TestIPV4NetblockInsertion11);
930 UtRegisterTest(
"SCRadix4TestIPV4NetblockInsertion12", SCRadix4TestIPV4NetblockInsertion12);
932 "SCRadix4TestIPV4NetBlocksAndBestSearch16", SCRadix4TestIPV4NetBlocksAndBestSearch16);
934 "SCRadix4TestIPV4NetBlocksAndBestSearch19", SCRadix4TestIPV4NetBlocksAndBestSearch19);
935 UtRegisterTest(
"SCRadix4TestIPV4NetblockInsertion25", SCRadix4TestIPV4NetblockInsertion25);
936 UtRegisterTest(
"SCRadix4TestIPV4NetblockInsertion26", SCRadix4TestIPV4NetblockInsertion26);
937 UtRegisterTest(
"SCRadix4TestIPV4InsertRemove01", SCRadix4TestIPV4InsertRemove01);
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define PASS
Pass the test.
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Structure that hold the user data and the netmask associated with it.
struct RadixUserData * next
Structure for the node in the radix tree.
struct SCRadix4Node_ * right
struct SCRadix4Node_ * left
struct RadixUserData * user_data
Structure for the radix tree.
size_t strlcpy(char *dst, const char *src, size_t siz)
int StringParseU8RangeCheck(uint8_t *res, int base, size_t len, const char *str, uint8_t min, uint8_t max)
#define SCLogNotice(...)
Macro used to log NOTICE messages.
thread_local SCError sc_errno
const char * PrintInet(int af, const void *src, char *dst, socklen_t size)
#define ADD_IPV4_MASK(str, cidr)
SCRadix4Node * SCRadix4TreeFindBestMatch2(const SCRadix4Tree *tree, const uint8_t *key, void **user_data, uint8_t *out_netmask)
SCRadix4Node * SCRadix4TreeFindBestMatch(const SCRadix4Tree *tree, const uint8_t *key, void **user_data)
void SCRadix4RemoveKeyIPV4Netblock(SCRadix4Tree *tree, const SCRadix4Config *config, const uint8_t *key_stream, uint8_t netmask)
Removes an IPV4 address netblock key from the Radix4 tree.
#define REM_IPV4_MASK(str, cidr)
SCRadix4Tree SCRadix4TreeInitialize(void)
SCRadix4Node * SCRadix4TreeFindNetblock(const SCRadix4Tree *tree, const uint8_t *key, const uint8_t netmask, void **user_data)
bool SCRadix4AddKeyIPV4String(SCRadix4Tree *tree, const SCRadix4Config *config, const char *str, void *user)
Adds a new IPV4/netblock to the Radix4 tree from a string.
SCRadix4Node * SCRadix4AddKeyIPV4(SCRadix4Tree *tree, const SCRadix4Config *config, const uint8_t *key_stream, void *user)
Adds a new IPV4 address to the Radix4 tree.
void SCRadix4PrintTree(SCRadix4Tree *tree, const SCRadix4Config *config)
int SCRadix4ForEachNode(const SCRadix4Tree *tree, SCRadix4ForEachNodeFunc Callback, void *data)
void SCRadix4TreeRelease(SCRadix4Tree *tree, const SCRadix4Config *config)
void SCRadix4RegisterTests(void)
void SCRadix4RemoveKeyIPV4(SCRadix4Tree *tree, const SCRadix4Config *config, const uint8_t *key_stream)
Removes an IPV4 address key(not a netblock) from the Radix4 tree. Instead of using this function,...
SCRadix4Node * SCRadix4TreeFindExactMatch(const SCRadix4Tree *tree, const uint8_t *key, void **user_data)
bool SCRadix4CompareTrees(const SCRadix4Tree *t1, const SCRadix4Tree *t2, SCRadix4TreeCompareFunc Callback)
SCRadix4Node * SCRadix4AddKeyIPV4Netblock(SCRadix4Tree *tree, const SCRadix4Config *config, const uint8_t *key_stream, uint8_t netmask, void *user)
Adds a new IPV4 netblock to the Radix4 tree.
bool(* SCRadix4TreeCompareFunc)(const void *ud1, const void *ud2)
compare content of 2 user data entries
int(* SCRadix4ForEachNodeFunc)(const SCRadix4Node *node, void *user_data, const uint8_t netmask, void *data)
#define SC_RADIX4_TREE_INITIALIZER
#define DEBUG_VALIDATE_BUG_ON(exp)