Coverage Report

Created: 2026-09-28 07:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata8/src/util-radix-tree-common.h
Line
Count
Source
1
/* Copyright (C) 2007-2022 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17
18
/**
19
 * \file
20
 *
21
 * \author Victor Julien <victor@inliniac.net>
22
 * \author Anoop Saldanha <anoopsaldanha@gmail.com>
23
 *
24
 * Implementation of radix trees
25
 */
26
27
#include "util-validate.h"
28
29
#ifndef ADDRESS_BYTES
30
#error "define ADDRESS_BYTES"
31
#endif
32
#ifndef NETMASK_MAX
33
#error "define NETMASK_MAX"
34
#endif
35
36
908k
#define RADIX_BITTEST(x, y) ((x) & (y))
37
38
/**
39
 * \brief Structure that hold the user data and the netmask associated with it.
40
 */
41
typedef struct RadixUserData {
42
    /* holds a pointer to the user data associated with the particular netmask */
43
    void *user;
44
    /* pointer to the next user data in the list */
45
    struct RadixUserData *next;
46
    /* holds the netmask value that corresponds to this user data pointer */
47
    uint8_t netmask;
48
} RadixUserData;
49
50
/**
51
 * \brief Allocates and returns a new instance of RadixUserData.
52
 *
53
 * \param netmask The netmask entry (cidr) that has to be made in the new
54
 *                RadixUserData instance
55
 * \param user    The user data that has to be set for the above
56
 *                netmask in the newly created RadixUserData instance.
57
 *
58
 * \retval user_data Pointer to a new instance of RadixUserData.
59
 */
60
static RadixUserData *AllocUserData(uint8_t netmask, void *user)
61
57.2k
{
62
57.2k
    RadixUserData *user_data = SCCalloc(1, sizeof(RadixUserData));
63
57.2k
    if (unlikely(user_data == NULL)) {
64
0
        sc_errno = SC_ENOMEM;
65
0
        return NULL;
66
0
    }
67
57.2k
    user_data->netmask = netmask;
68
57.2k
    user_data->user = user;
69
57.2k
    return user_data;
70
57.2k
}
util-radix4-tree.c:AllocUserData
Line
Count
Source
61
33.8k
{
62
33.8k
    RadixUserData *user_data = SCCalloc(1, sizeof(RadixUserData));
63
33.8k
    if (unlikely(user_data == NULL)) {
64
0
        sc_errno = SC_ENOMEM;
65
0
        return NULL;
66
0
    }
67
33.8k
    user_data->netmask = netmask;
68
33.8k
    user_data->user = user;
69
33.8k
    return user_data;
70
33.8k
}
util-radix6-tree.c:AllocUserData
Line
Count
Source
61
23.3k
{
62
23.3k
    RadixUserData *user_data = SCCalloc(1, sizeof(RadixUserData));
63
23.3k
    if (unlikely(user_data == NULL)) {
64
0
        sc_errno = SC_ENOMEM;
65
0
        return NULL;
66
0
    }
67
23.3k
    user_data->netmask = netmask;
68
23.3k
    user_data->user = user;
69
23.3k
    return user_data;
70
23.3k
}
71
72
/**
73
 * \brief Deallocates an instance of RadixUserData.
74
 *
75
 * \param user_data Pointer to the instance of RadixUserData that has to be
76
 *                  freed.
77
 */
78
static void FreeUserData(RadixUserData *user_data)
79
57.2k
{
80
57.2k
    SCFree(user_data);
81
57.2k
}
util-radix4-tree.c:FreeUserData
Line
Count
Source
79
33.8k
{
80
33.8k
    SCFree(user_data);
81
33.8k
}
util-radix6-tree.c:FreeUserData
Line
Count
Source
79
23.3k
{
80
23.3k
    SCFree(user_data);
81
23.3k
}
82
83
/**
84
 * \brief Appends a user_data instance(RadixUserData) to a
85
 *        user_data(RadixUserData) list.  We add the new entry in descending
86
 *        order with respect to the netmask contained in the RadixUserData.
87
 *
88
 * \param new  Pointer to the RadixUserData to be added to the list.
89
 * \param list Pointer to the RadixUserData list head, to which "new" has to
90
 *             be appended.
91
 */
92
static void AppendToUserDataList(RadixUserData *add, RadixUserData **list)
93
3.99k
{
94
3.99k
    RadixUserData *temp = NULL;
95
96
3.99k
    BUG_ON(add == NULL || list == NULL);
97
98
    /* add to the list in descending order.  The reason we do this is for
99
     * optimizing key retrieval for a ip key under a netblock */
100
3.99k
    RadixUserData *prev = temp = *list;
101
6.23k
    while (temp != NULL) {
102
5.77k
        if (add->netmask > temp->netmask)
103
3.52k
            break;
104
2.24k
        prev = temp;
105
2.24k
        temp = temp->next;
106
2.24k
    }
107
108
3.99k
    if (temp == *list) {
109
3.11k
        add->next = *list;
110
3.11k
        *list = add;
111
3.11k
    } else {
112
873
        add->next = prev->next;
113
873
        prev->next = add;
114
873
    }
115
3.99k
}
util-radix4-tree.c:AppendToUserDataList
Line
Count
Source
93
1.12k
{
94
1.12k
    RadixUserData *temp = NULL;
95
96
1.12k
    BUG_ON(add == NULL || list == NULL);
97
98
    /* add to the list in descending order.  The reason we do this is for
99
     * optimizing key retrieval for a ip key under a netblock */
100
1.12k
    RadixUserData *prev = temp = *list;
101
2.02k
    while (temp != NULL) {
102
1.84k
        if (add->netmask > temp->netmask)
103
953
            break;
104
895
        prev = temp;
105
895
        temp = temp->next;
106
895
    }
107
108
1.12k
    if (temp == *list) {
109
790
        add->next = *list;
110
790
        *list = add;
111
790
    } else {
112
339
        add->next = prev->next;
113
339
        prev->next = add;
114
339
    }
115
1.12k
}
util-radix6-tree.c:AppendToUserDataList
Line
Count
Source
93
2.86k
{
94
2.86k
    RadixUserData *temp = NULL;
95
96
2.86k
    BUG_ON(add == NULL || list == NULL);
97
98
    /* add to the list in descending order.  The reason we do this is for
99
     * optimizing key retrieval for a ip key under a netblock */
100
2.86k
    RadixUserData *prev = temp = *list;
101
4.21k
    while (temp != NULL) {
102
3.92k
        if (add->netmask > temp->netmask)
103
2.57k
            break;
104
1.34k
        prev = temp;
105
1.34k
        temp = temp->next;
106
1.34k
    }
107
108
2.86k
    if (temp == *list) {
109
2.32k
        add->next = *list;
110
2.32k
        *list = add;
111
2.32k
    } else {
112
534
        add->next = prev->next;
113
534
        prev->next = add;
114
534
    }
115
2.86k
}
116
117
/**
118
 * \brief Adds a netmask and its user_data for a particular prefix stream.
119
 *
120
 * \param prefix  The prefix stream to which the netmask and its corresponding
121
 *                user data has to be added.
122
 * \param netmask The netmask value (cidr) that has to be added to the prefix.
123
 * \param user    The pointer to the user data corresponding to the above
124
 *                netmask.
125
 */
126
static void AddNetmaskUserDataToNode(RADIX_NODE_TYPE *node, uint8_t netmask, void *user)
127
3.99k
{
128
3.99k
    BUG_ON(!node);
129
3.99k
    AppendToUserDataList(AllocUserData(netmask, user), &node->user_data);
130
3.99k
}
util-radix4-tree.c:AddNetmaskUserDataToNode
Line
Count
Source
127
1.12k
{
128
1.12k
    BUG_ON(!node);
129
1.12k
    AppendToUserDataList(AllocUserData(netmask, user), &node->user_data);
130
1.12k
}
util-radix6-tree.c:AddNetmaskUserDataToNode
Line
Count
Source
127
2.86k
{
128
2.86k
    BUG_ON(!node);
129
2.86k
    AppendToUserDataList(AllocUserData(netmask, user), &node->user_data);
130
2.86k
}
131
132
/**
133
 * \brief Removes a particular user_data corresponding to a particular netmask
134
 *        entry, from a prefix.
135
 *
136
 * \param prefix  Pointer to the prefix from which the user_data/netmask entry
137
 *                has to be removed.
138
 * \param netmask The netmask value (cidr) whose user_data has to be deleted.
139
 */
140
static void RemoveNetmaskUserDataFromNode(RADIX_NODE_TYPE *node, uint8_t netmask)
141
0
{
142
0
    BUG_ON(!node);
143
144
0
    RadixUserData *temp = NULL, *prev = NULL;
145
0
    prev = temp = node->user_data;
146
0
    while (temp != NULL) {
147
0
        if (temp->netmask == netmask) {
148
0
            if (temp == node->user_data)
149
0
                node->user_data = temp->next;
150
0
            else
151
0
                prev->next = temp->next;
152
153
0
            FreeUserData(temp);
154
0
            break;
155
0
        }
156
0
        prev = temp;
157
0
        temp = temp->next;
158
0
    }
159
0
}
Unexecuted instantiation: util-radix4-tree.c:RemoveNetmaskUserDataFromNode
Unexecuted instantiation: util-radix6-tree.c:RemoveNetmaskUserDataFromNode
160
161
/**
162
 * \brief Indicates if prefix contains an entry for an ip with a specific netmask.
163
 *
164
 * \param prefix  Pointer to the ip prefix that is being checked.
165
 * \param netmask The netmask value (cidr) that has to be checked for
166
 *                presence in the prefix.
167
 *
168
 * \retval 1 On match.
169
 * \retval 0 On no match.
170
 */
171
static int ContainNetmask(RADIX_NODE_TYPE *node, uint8_t netmask)
172
8.42k
{
173
8.42k
    BUG_ON(!node);
174
8.42k
    RadixUserData *user_data = node->user_data;
175
18.9k
    while (user_data != NULL) {
176
14.9k
        if (user_data->netmask == netmask)
177
4.43k
            return 1;
178
10.5k
        user_data = user_data->next;
179
10.5k
    }
180
3.99k
    return 0;
181
8.42k
}
util-radix4-tree.c:ContainNetmask
Line
Count
Source
172
2.28k
{
173
2.28k
    BUG_ON(!node);
174
2.28k
    RadixUserData *user_data = node->user_data;
175
4.98k
    while (user_data != NULL) {
176
3.85k
        if (user_data->netmask == netmask)
177
1.15k
            return 1;
178
2.69k
        user_data = user_data->next;
179
2.69k
    }
180
1.12k
    return 0;
181
2.28k
}
util-radix6-tree.c:ContainNetmask
Line
Count
Source
172
6.14k
{
173
6.14k
    BUG_ON(!node);
174
6.14k
    RadixUserData *user_data = node->user_data;
175
13.9k
    while (user_data != NULL) {
176
11.1k
        if (user_data->netmask == netmask)
177
3.27k
            return 1;
178
7.83k
        user_data = user_data->next;
179
7.83k
    }
180
2.86k
    return 0;
181
6.14k
}
182
183
/**
184
 * \brief Returns the total netmask count for this prefix.
185
 *
186
 * \param prefix Pointer to the prefix
187
 *
188
 * \retval count The total netmask count for this prefix.
189
 */
190
static int NetmaskCount(RADIX_NODE_TYPE *node)
191
0
{
192
0
    BUG_ON(!node);
193
0
    uint32_t count = 0;
194
0
    RadixUserData *user_data = node->user_data;
195
0
    while (user_data != NULL) {
196
0
        count++;
197
0
        user_data = user_data->next;
198
0
    }
199
0
    return count;
200
0
}
Unexecuted instantiation: util-radix4-tree.c:NetmaskCount
Unexecuted instantiation: util-radix6-tree.c:NetmaskCount
201
202
/**
203
 * \brief Indicates if prefix contains an entry for an ip with a specific netmask
204
 *        and if it does, it sets `user_data_result` to the netmask user_data entry.
205
 *
206
 * \param prefix      Pointer to the ip prefix that is being checked.
207
 * \param netmask     The netmask value for which we will have to return the user_data
208
 * \param exact_match Bool flag which indicates if we should check if the prefix
209
 *                    holds proper netblock  or not.
210
 * \param[out] user_data_result user data pointer
211
 *
212
 * \retval 1 On match.
213
 * \retval 0 On no match.
214
 */
215
static int ContainNetmaskAndSetUserData(
216
        RADIX_NODE_TYPE *node, uint8_t netmask, bool exact_match, void **user_data_result)
217
269k
{
218
269k
    DEBUG_VALIDATE_BUG_ON(!node);
219
220
269k
    RadixUserData *user_data = node->user_data;
221
    /* Check if we have a match for an exact ip.  An exact ip as in not a proper
222
     * netblock, i.e. an ip with a netmask of 32. */
223
269k
    if (exact_match) {
224
56.1k
        if (user_data->netmask == netmask) {
225
40.4k
            if (user_data_result)
226
40.4k
                *user_data_result = user_data->user;
227
40.4k
            return 1;
228
40.4k
        } else {
229
15.7k
            goto no_match;
230
15.7k
        }
231
56.1k
    }
232
233
    /* Check for the user_data entry for this netmask_value */
234
221k
    while (user_data != NULL) {
235
221k
        if (user_data->netmask == netmask) {
236
213k
            if (user_data_result)
237
213k
                *user_data_result = user_data->user;
238
213k
            return 1;
239
213k
        }
240
7.39k
        user_data = user_data->next;
241
7.39k
    }
242
243
15.7k
no_match:
244
15.7k
    if (user_data_result != NULL)
245
15.7k
        *user_data_result = NULL;
246
15.7k
    return 0;
247
213k
}
util-radix4-tree.c:ContainNetmaskAndSetUserData
Line
Count
Source
217
193k
{
218
193k
    DEBUG_VALIDATE_BUG_ON(!node);
219
220
193k
    RadixUserData *user_data = node->user_data;
221
    /* Check if we have a match for an exact ip.  An exact ip as in not a proper
222
     * netblock, i.e. an ip with a netmask of 32. */
223
193k
    if (exact_match) {
224
32.1k
        if (user_data->netmask == netmask) {
225
21.8k
            if (user_data_result)
226
21.8k
                *user_data_result = user_data->user;
227
21.8k
            return 1;
228
21.8k
        } else {
229
10.3k
            goto no_match;
230
10.3k
        }
231
32.1k
    }
232
233
    /* Check for the user_data entry for this netmask_value */
234
163k
    while (user_data != NULL) {
235
163k
        if (user_data->netmask == netmask) {
236
160k
            if (user_data_result)
237
160k
                *user_data_result = user_data->user;
238
160k
            return 1;
239
160k
        }
240
2.34k
        user_data = user_data->next;
241
2.34k
    }
242
243
10.3k
no_match:
244
10.3k
    if (user_data_result != NULL)
245
10.3k
        *user_data_result = NULL;
246
10.3k
    return 0;
247
160k
}
util-radix6-tree.c:ContainNetmaskAndSetUserData
Line
Count
Source
217
76.9k
{
218
76.9k
    DEBUG_VALIDATE_BUG_ON(!node);
219
220
76.9k
    RadixUserData *user_data = node->user_data;
221
    /* Check if we have a match for an exact ip.  An exact ip as in not a proper
222
     * netblock, i.e. an ip with a netmask of 32. */
223
76.9k
    if (exact_match) {
224
23.9k
        if (user_data->netmask == netmask) {
225
18.5k
            if (user_data_result)
226
18.5k
                *user_data_result = user_data->user;
227
18.5k
            return 1;
228
18.5k
        } else {
229
5.38k
            goto no_match;
230
5.38k
        }
231
23.9k
    }
232
233
    /* Check for the user_data entry for this netmask_value */
234
58.0k
    while (user_data != NULL) {
235
58.0k
        if (user_data->netmask == netmask) {
236
52.9k
            if (user_data_result)
237
52.9k
                *user_data_result = user_data->user;
238
52.9k
            return 1;
239
52.9k
        }
240
5.05k
        user_data = user_data->next;
241
5.05k
    }
242
243
5.38k
no_match:
244
5.38k
    if (user_data_result != NULL)
245
5.38k
        *user_data_result = NULL;
246
5.38k
    return 0;
247
52.9k
}
248
249
/**
250
 * \brief Creates a new node for the Radix tree
251
 *
252
 * \retval node The newly created node for the radix tree
253
 */
254
static inline RADIX_NODE_TYPE *RadixCreateNode(void)
255
83.3k
{
256
83.3k
    RADIX_NODE_TYPE *node = NULL;
257
258
83.3k
    if ((node = SCCalloc(1, sizeof(RADIX_NODE_TYPE))) == NULL) {
259
0
        sc_errno = SC_ENOMEM;
260
0
        return NULL;
261
0
    }
262
83.3k
    node->bit = NETMASK_MAX;
263
83.3k
    return node;
264
83.3k
}
util-radix4-tree.c:RadixCreateNode
Line
Count
Source
255
54.5k
{
256
54.5k
    RADIX_NODE_TYPE *node = NULL;
257
258
54.5k
    if ((node = SCCalloc(1, sizeof(RADIX_NODE_TYPE))) == NULL) {
259
0
        sc_errno = SC_ENOMEM;
260
0
        return NULL;
261
0
    }
262
54.5k
    node->bit = NETMASK_MAX;
263
54.5k
    return node;
264
54.5k
}
util-radix6-tree.c:RadixCreateNode
Line
Count
Source
255
28.8k
{
256
28.8k
    RADIX_NODE_TYPE *node = NULL;
257
258
28.8k
    if ((node = SCCalloc(1, sizeof(RADIX_NODE_TYPE))) == NULL) {
259
0
        sc_errno = SC_ENOMEM;
260
0
        return NULL;
261
0
    }
262
28.8k
    node->bit = NETMASK_MAX;
263
28.8k
    return node;
264
28.8k
}
265
266
/**
267
 * \brief Frees a Radix tree node
268
 *
269
 * \param node Pointer to a Radix tree node
270
 * \param tree Pointer to the Radix tree to which this node belongs
271
 */
272
static void ReleaseNode(
273
        RADIX_NODE_TYPE *node, RADIX_TREE_TYPE *tree, const RADIX_CONFIG_TYPE *config)
274
83.3k
{
275
83.3k
    DEBUG_VALIDATE_BUG_ON(config == NULL);
276
83.3k
    if (node != NULL) {
277
83.3k
        RadixUserData *ud = node->user_data;
278
140k
        while (ud != NULL) {
279
57.2k
            RadixUserData *next = ud->next;
280
57.2k
            if (config->Free != NULL && ud->user) {
281
57.2k
                config->Free(ud->user);
282
57.2k
            }
283
57.2k
            FreeUserData(ud);
284
57.2k
            ud = next;
285
57.2k
        }
286
83.3k
        SCFree(node);
287
83.3k
    }
288
83.3k
}
util-radix4-tree.c:ReleaseNode
Line
Count
Source
274
54.5k
{
275
54.5k
    DEBUG_VALIDATE_BUG_ON(config == NULL);
276
54.5k
    if (node != NULL) {
277
54.5k
        RadixUserData *ud = node->user_data;
278
88.4k
        while (ud != NULL) {
279
33.8k
            RadixUserData *next = ud->next;
280
33.8k
            if (config->Free != NULL && ud->user) {
281
33.8k
                config->Free(ud->user);
282
33.8k
            }
283
33.8k
            FreeUserData(ud);
284
33.8k
            ud = next;
285
33.8k
        }
286
54.5k
        SCFree(node);
287
54.5k
    }
288
54.5k
}
util-radix6-tree.c:ReleaseNode
Line
Count
Source
274
28.8k
{
275
28.8k
    DEBUG_VALIDATE_BUG_ON(config == NULL);
276
28.8k
    if (node != NULL) {
277
28.8k
        RadixUserData *ud = node->user_data;
278
52.2k
        while (ud != NULL) {
279
23.3k
            RadixUserData *next = ud->next;
280
23.3k
            if (config->Free != NULL && ud->user) {
281
23.3k
                config->Free(ud->user);
282
23.3k
            }
283
23.3k
            FreeUserData(ud);
284
23.3k
            ud = next;
285
23.3k
        }
286
28.8k
        SCFree(node);
287
28.8k
    }
288
28.8k
}
289
290
/**
291
 * \brief Internal helper function used by TreeRelease to free a subtree
292
 *
293
 * \param node Pointer to the root of the subtree that has to be freed
294
 * \param tree Pointer to the Radix tree to which this subtree belongs
295
 */
296
static void ReleaseSubtree(
297
        RADIX_NODE_TYPE *node, RADIX_TREE_TYPE *tree, const RADIX_CONFIG_TYPE *config)
298
16.5M
{
299
16.5M
    DEBUG_VALIDATE_BUG_ON(config == NULL);
300
16.5M
    if (node != NULL) {
301
83.3k
        ReleaseSubtree(node->left, tree, config);
302
83.3k
        ReleaseSubtree(node->right, tree, config);
303
83.3k
        ReleaseNode(node, tree, config);
304
83.3k
    }
305
16.5M
}
util-radix4-tree.c:ReleaseSubtree
Line
Count
Source
298
8.32M
{
299
8.32M
    DEBUG_VALIDATE_BUG_ON(config == NULL);
300
8.32M
    if (node != NULL) {
301
54.5k
        ReleaseSubtree(node->left, tree, config);
302
54.5k
        ReleaseSubtree(node->right, tree, config);
303
54.5k
        ReleaseNode(node, tree, config);
304
54.5k
    }
305
8.32M
}
util-radix6-tree.c:ReleaseSubtree
Line
Count
Source
298
8.26M
{
299
8.26M
    DEBUG_VALIDATE_BUG_ON(config == NULL);
300
8.26M
    if (node != NULL) {
301
28.8k
        ReleaseSubtree(node->left, tree, config);
302
28.8k
        ReleaseSubtree(node->right, tree, config);
303
28.8k
        ReleaseNode(node, tree, config);
304
28.8k
    }
305
8.26M
}
306
307
/**
308
 * \brief frees a Radix tree and all its nodes
309
 *
310
 * \param tree Pointer to the Radix tree that has to be freed
311
 */
312
static void TreeRelease(RADIX_TREE_TYPE *tree, const RADIX_CONFIG_TYPE *config)
313
16.4M
{
314
16.4M
    DEBUG_VALIDATE_BUG_ON(config == NULL);
315
16.4M
    if (tree == NULL)
316
0
        return;
317
318
16.4M
    ReleaseSubtree(tree->head, tree, config);
319
16.4M
    tree->head = NULL;
320
16.4M
    return;
321
16.4M
}
util-radix4-tree.c:TreeRelease
Line
Count
Source
313
8.21M
{
314
8.21M
    DEBUG_VALIDATE_BUG_ON(config == NULL);
315
8.21M
    if (tree == NULL)
316
0
        return;
317
318
8.21M
    ReleaseSubtree(tree->head, tree, config);
319
    tree->head = NULL;
320
8.21M
    return;
321
8.21M
}
util-radix6-tree.c:TreeRelease
Line
Count
Source
313
8.21M
{
314
8.21M
    DEBUG_VALIDATE_BUG_ON(config == NULL);
315
8.21M
    if (tree == NULL)
316
0
        return;
317
318
8.21M
    ReleaseSubtree(tree->head, tree, config);
319
    tree->head = NULL;
320
8.21M
    return;
321
8.21M
}
322
323
/**
324
 * \brief Adds a key to the Radix tree. Used internally by the API.
325
 *
326
 * \param tree       Pointer to the Radix tree
327
 * \param key_stream Data that has to added to the Radix tree
328
 * \param netmask    The netmask (cidr)
329
 * \param user       Pointer to the user data that has to be associated with
330
 *                   this key
331
 * \param exclusive  True if the node should be added iff it doesn't exist.
332
 *
333
 * \retval node Pointer to the newly created node
334
 */
335
static RADIX_NODE_TYPE *AddKey(RADIX_TREE_TYPE *tree, const RADIX_CONFIG_TYPE *config,
336
        const uint8_t *key_stream, uint8_t netmask, void *user, const bool exclusive)
337
61.7k
{
338
61.7k
    DEBUG_VALIDATE_BUG_ON(config == NULL);
339
61.7k
    RADIX_NODE_TYPE *node = NULL;
340
61.7k
    RADIX_NODE_TYPE *parent = NULL;
341
61.7k
    RADIX_NODE_TYPE *bottom_node = NULL;
342
343
61.7k
    uint8_t tmp_stream[ADDRESS_BYTES];
344
61.7k
    memcpy(tmp_stream, key_stream, sizeof(tmp_stream));
345
346
61.7k
    if (tree == NULL) {
347
0
        SCLogError("Argument \"tree\" NULL");
348
0
        sc_errno = SC_EINVAL;
349
0
        return NULL;
350
0
    }
351
352
    /* chop the ip address against a netmask */
353
61.7k
    MaskIPNetblock(tmp_stream, netmask, NETMASK_MAX);
354
355
    /* the very first element in the radix tree */
356
61.7k
    if (tree->head == NULL) {
357
23.1k
        node = RadixCreateNode();
358
23.1k
        if (node == NULL)
359
0
            return NULL;
360
23.1k
        memcpy(node->prefix_stream, tmp_stream, sizeof(tmp_stream));
361
23.1k
        node->has_prefix = true;
362
23.1k
        node->user_data = AllocUserData(netmask, user);
363
23.1k
        if (node->user_data == NULL) {
364
0
            ReleaseNode(node, tree, config);
365
0
            return NULL;
366
0
        }
367
23.1k
        tree->head = node;
368
23.1k
        if (netmask == NETMASK_MAX)
369
2.05k
            return node;
370
371
21.1k
        AddNetmaskToMasks(node, netmask);
372
21.1k
        return node;
373
23.1k
    }
374
38.5k
    node = tree->head;
375
376
    /* we walk down the tree only when we satisfy 2 conditions.  The first one
377
     * being the incoming prefix is shorter than the differ bit of the current
378
     * node.  In case we fail in this aspect, we walk down to the tree, till we
379
     * arrive at a node that ends in a prefix */
380
290k
    while (node->bit < NETMASK_MAX || !node->has_prefix) {
381
        /* if the bitlen isn't long enough to handle the bit test, we just walk
382
         * down along one of the paths, since either paths should end up with a
383
         * node that has a common prefix whose differ bit is greater than the
384
         * bitlen of the incoming prefix */
385
251k
        if (NETMASK_MAX <= node->bit) {
386
0
            if (node->right == NULL)
387
0
                break;
388
0
            node = node->right;
389
251k
        } else {
390
251k
            if (RADIX_BITTEST(tmp_stream[node->bit >> 3], (0x80 >> (node->bit % 8)))) {
391
53.5k
                if (node->right == NULL)
392
0
                    break;
393
53.5k
                node = node->right;
394
198k
            } else {
395
198k
                if (node->left == NULL)
396
0
                    break;
397
198k
                node = node->left;
398
198k
            }
399
251k
        }
400
251k
    }
401
402
    /* we need to keep a reference to the bottom-most node, that actually holds
403
     * the prefix */
404
38.5k
    bottom_node = node;
405
406
    /* get the first bit position where the ips differ */
407
38.5k
    uint8_t check_bit = MIN(node->bit, NETMASK_MAX);
408
38.5k
    uint8_t differ_bit = 0;
409
38.5k
    uint8_t j = 0;
410
223k
    for (uint8_t i = 0; (i * 8) < check_bit; i++) {
411
214k
        int temp = 0;
412
214k
        if ((temp = (tmp_stream[i] ^ bottom_node->prefix_stream[i])) == 0) {
413
184k
            differ_bit = (i + 1) * 8;
414
184k
            continue;
415
184k
        }
416
417
        /* find out the position where the first bit differs.  This method is
418
         * faster, but at the cost of being larger.  But with larger caches
419
         * these days we don't have to worry about cache misses */
420
30.1k
        temp = temp * 2;
421
30.1k
        if (temp >= 256)
422
3.26k
            j = 0;
423
26.8k
        else if (temp >= 128)
424
4.40k
            j = 1;
425
22.4k
        else if (temp >= 64)
426
3.85k
            j = 2;
427
18.5k
        else if (temp >= 32)
428
3.05k
            j = 3;
429
15.5k
        else if (temp >= 16)
430
4.38k
            j = 4;
431
11.1k
        else if (temp >= 8)
432
4.00k
            j = 5;
433
7.15k
        else if (temp >= 4)
434
3.61k
            j = 6;
435
3.54k
        else if (temp >= 2)
436
3.54k
            j = 7;
437
438
30.1k
        differ_bit = i * 8 + j;
439
30.1k
        break;
440
214k
    }
441
38.5k
    if (check_bit < differ_bit)
442
0
        differ_bit = check_bit;
443
444
    /* walk up the tree till we find the position, to fit our new node in */
445
38.5k
    parent = node->parent;
446
50.6k
    while (parent && differ_bit <= parent->bit) {
447
12.1k
        node = parent;
448
12.1k
        parent = node->parent;
449
12.1k
    }
450
38.5k
    BUG_ON(differ_bit == NETMASK_MAX && node->bit != NETMASK_MAX);
451
452
    /* We already have the node in the tree with the same differing bit position */
453
38.5k
    if (differ_bit == NETMASK_MAX && node->bit == NETMASK_MAX) {
454
8.42k
        if (node->has_prefix) {
455
            /* Check if we already have this netmask entry covered by this prefix */
456
8.42k
            if (ContainNetmask(node, netmask)) {
457
                /* Basically we already have this stream prefix, as well as the
458
                 * netblock entry for this.  A perfect duplicate. */
459
4.43k
                if (exclusive) {
460
4.43k
                    SCLogDebug("not inserting since it already exists");
461
4.43k
                    sc_errno = SC_EEXIST;
462
4.43k
                    return NULL;
463
4.43k
                }
464
0
                SCLogDebug("Duplicate entry for this ip address/netblock");
465
3.99k
            } else {
466
                /* Basically we already have this stream prefix, but we don't
467
                 * have an entry for this particular netmask value for this
468
                 * prefix.  For example, we have an entry for 192.168.0.0 and
469
                 * 192.168.0.0/16 and now we are trying to enter 192.168.0.0/20 */
470
3.99k
                AddNetmaskUserDataToNode(node, netmask, user);
471
472
                /* if we are adding a netmask of 32 it indicates we are adding
473
                 * an exact host ip into the radix tree, in which case we don't
474
                 * need to add the netmask value into the tree */
475
3.99k
                if (netmask == NETMASK_MAX)
476
1.03k
                    return node;
477
478
                /* looks like we have a netmask which is != 32, in which
479
                 * case we walk up the tree to insert this netmask value in the
480
                 * correct node */
481
2.96k
                parent = node->parent;
482
4.99k
                while (parent != NULL && netmask < (parent->bit + 1)) {
483
2.03k
                    node = parent;
484
2.03k
                    parent = parent->parent;
485
2.03k
                }
486
487
2.96k
                AddNetmaskToMasks(node, netmask);
488
2.96k
                if (NetmaskEqualsMask(node, netmask)) {
489
181
                    return node;
490
181
                }
491
2.96k
            }
492
8.42k
        }
493
2.77k
        return node;
494
8.42k
    }
495
496
    /* create the leaf node for the new key */
497
30.1k
    RADIX_NODE_TYPE *new_node = RadixCreateNode();
498
30.1k
    if (new_node == NULL)
499
0
        return NULL;
500
30.1k
    memcpy(new_node->prefix_stream, tmp_stream, sizeof(tmp_stream));
501
30.1k
    new_node->has_prefix = true;
502
30.1k
    new_node->user_data = AllocUserData(netmask, user);
503
30.1k
    if (new_node->user_data == NULL) {
504
0
        ReleaseNode(new_node, tree, config);
505
0
        return NULL;
506
0
    }
507
508
    /* stick our new_node into the tree.  Create a node that holds the
509
     * differing bit position and break the branch.  Also handle the
510
     * tranfer of netmasks between node and inter_node(explained in more
511
     * detail below) */
512
30.1k
    RADIX_NODE_TYPE *inter_node = RadixCreateNode();
513
30.1k
    if (inter_node == NULL) {
514
0
        ReleaseNode(new_node, tree, config);
515
0
        return NULL;
516
0
    }
517
30.1k
    inter_node->has_prefix = false;
518
30.1k
    inter_node->bit = differ_bit;
519
30.1k
    inter_node->parent = node->parent;
520
30.1k
    SCLogDebug("inter_node: differ_bit %u", differ_bit);
521
522
    /* update netmasks for node and set them for inter_node */
523
30.1k
    ProcessInternode(node, inter_node);
524
525
30.1k
    if (RADIX_BITTEST(tmp_stream[differ_bit >> 3], (0x80 >> (differ_bit % 8)))) {
526
18.3k
        inter_node->left = node;
527
18.3k
        inter_node->right = new_node;
528
18.3k
    } else {
529
11.7k
        inter_node->left = new_node;
530
11.7k
        inter_node->right = node;
531
11.7k
    }
532
30.1k
    new_node->parent = inter_node;
533
534
30.1k
    if (node->parent == NULL)
535
6.25k
        tree->head = inter_node;
536
23.8k
    else if (node->parent->right == node)
537
8.69k
        node->parent->right = inter_node;
538
15.1k
    else
539
15.1k
        node->parent->left = inter_node;
540
541
30.1k
    node->parent = inter_node;
542
543
    /* insert the netmask into the tree */
544
30.1k
    if (netmask != NETMASK_MAX) {
545
21.1k
        node = new_node;
546
21.1k
        parent = new_node->parent;
547
22.3k
        while (parent != NULL && netmask < (parent->bit + 1)) {
548
1.25k
            node = parent;
549
1.25k
            parent = parent->parent;
550
1.25k
        }
551
21.1k
        AddNetmaskToMasks(node, netmask);
552
21.1k
    }
553
30.1k
    return new_node;
554
30.1k
}
util-radix4-tree.c:AddKey
Line
Count
Source
337
35.0k
{
338
35.0k
    DEBUG_VALIDATE_BUG_ON(config == NULL);
339
35.0k
    RADIX_NODE_TYPE *node = NULL;
340
35.0k
    RADIX_NODE_TYPE *parent = NULL;
341
35.0k
    RADIX_NODE_TYPE *bottom_node = NULL;
342
343
35.0k
    uint8_t tmp_stream[ADDRESS_BYTES];
344
35.0k
    memcpy(tmp_stream, key_stream, sizeof(tmp_stream));
345
346
35.0k
    if (tree == NULL) {
347
0
        SCLogError("Argument \"tree\" NULL");
348
0
        sc_errno = SC_EINVAL;
349
0
        return NULL;
350
0
    }
351
352
    /* chop the ip address against a netmask */
353
35.0k
    MaskIPNetblock(tmp_stream, netmask, NETMASK_MAX);
354
355
    /* the very first element in the radix tree */
356
35.0k
    if (tree->head == NULL) {
357
10.9k
        node = RadixCreateNode();
358
10.9k
        if (node == NULL)
359
0
            return NULL;
360
10.9k
        memcpy(node->prefix_stream, tmp_stream, sizeof(tmp_stream));
361
10.9k
        node->has_prefix = true;
362
10.9k
        node->user_data = AllocUserData(netmask, user);
363
10.9k
        if (node->user_data == NULL) {
364
0
            ReleaseNode(node, tree, config);
365
0
            return NULL;
366
0
        }
367
10.9k
        tree->head = node;
368
10.9k
        if (netmask == NETMASK_MAX)
369
441
            return node;
370
371
10.5k
        AddNetmaskToMasks(node, netmask);
372
10.5k
        return node;
373
10.9k
    }
374
24.0k
    node = tree->head;
375
376
    /* we walk down the tree only when we satisfy 2 conditions.  The first one
377
     * being the incoming prefix is shorter than the differ bit of the current
378
     * node.  In case we fail in this aspect, we walk down to the tree, till we
379
     * arrive at a node that ends in a prefix */
380
235k
    while (node->bit < NETMASK_MAX || !node->has_prefix) {
381
        /* if the bitlen isn't long enough to handle the bit test, we just walk
382
         * down along one of the paths, since either paths should end up with a
383
         * node that has a common prefix whose differ bit is greater than the
384
         * bitlen of the incoming prefix */
385
211k
        if (NETMASK_MAX <= node->bit) {
386
0
            if (node->right == NULL)
387
0
                break;
388
0
            node = node->right;
389
211k
        } else {
390
211k
            if (RADIX_BITTEST(tmp_stream[node->bit >> 3], (0x80 >> (node->bit % 8)))) {
391
46.8k
                if (node->right == NULL)
392
0
                    break;
393
46.8k
                node = node->right;
394
164k
            } else {
395
164k
                if (node->left == NULL)
396
0
                    break;
397
164k
                node = node->left;
398
164k
            }
399
211k
        }
400
211k
    }
401
402
    /* we need to keep a reference to the bottom-most node, that actually holds
403
     * the prefix */
404
24.0k
    bottom_node = node;
405
406
    /* get the first bit position where the ips differ */
407
24.0k
    uint8_t check_bit = MIN(node->bit, NETMASK_MAX);
408
24.0k
    uint8_t differ_bit = 0;
409
24.0k
    uint8_t j = 0;
410
68.9k
    for (uint8_t i = 0; (i * 8) < check_bit; i++) {
411
66.6k
        int temp = 0;
412
66.6k
        if ((temp = (tmp_stream[i] ^ bottom_node->prefix_stream[i])) == 0) {
413
44.8k
            differ_bit = (i + 1) * 8;
414
44.8k
            continue;
415
44.8k
        }
416
417
        /* find out the position where the first bit differs.  This method is
418
         * faster, but at the cost of being larger.  But with larger caches
419
         * these days we don't have to worry about cache misses */
420
21.8k
        temp = temp * 2;
421
21.8k
        if (temp >= 256)
422
2.79k
            j = 0;
423
19.0k
        else if (temp >= 128)
424
2.78k
            j = 1;
425
16.2k
        else if (temp >= 64)
426
3.02k
            j = 2;
427
13.2k
        else if (temp >= 32)
428
2.52k
            j = 3;
429
10.6k
        else if (temp >= 16)
430
2.97k
            j = 4;
431
7.70k
        else if (temp >= 8)
432
2.66k
            j = 5;
433
5.03k
        else if (temp >= 4)
434
2.66k
            j = 6;
435
2.37k
        else if (temp >= 2)
436
2.37k
            j = 7;
437
438
21.8k
        differ_bit = i * 8 + j;
439
21.8k
        break;
440
66.6k
    }
441
24.0k
    if (check_bit < differ_bit)
442
0
        differ_bit = check_bit;
443
444
    /* walk up the tree till we find the position, to fit our new node in */
445
24.0k
    parent = node->parent;
446
28.0k
    while (parent && differ_bit <= parent->bit) {
447
3.98k
        node = parent;
448
3.98k
        parent = node->parent;
449
3.98k
    }
450
24.0k
    BUG_ON(differ_bit == NETMASK_MAX && node->bit != NETMASK_MAX);
451
452
    /* We already have the node in the tree with the same differing bit position */
453
24.0k
    if (differ_bit == NETMASK_MAX && node->bit == NETMASK_MAX) {
454
2.28k
        if (node->has_prefix) {
455
            /* Check if we already have this netmask entry covered by this prefix */
456
2.28k
            if (ContainNetmask(node, netmask)) {
457
                /* Basically we already have this stream prefix, as well as the
458
                 * netblock entry for this.  A perfect duplicate. */
459
1.15k
                if (exclusive) {
460
1.15k
                    SCLogDebug("not inserting since it already exists");
461
1.15k
                    sc_errno = SC_EEXIST;
462
1.15k
                    return NULL;
463
1.15k
                }
464
0
                SCLogDebug("Duplicate entry for this ip address/netblock");
465
1.12k
            } else {
466
                /* Basically we already have this stream prefix, but we don't
467
                 * have an entry for this particular netmask value for this
468
                 * prefix.  For example, we have an entry for 192.168.0.0 and
469
                 * 192.168.0.0/16 and now we are trying to enter 192.168.0.0/20 */
470
1.12k
                AddNetmaskUserDataToNode(node, netmask, user);
471
472
                /* if we are adding a netmask of 32 it indicates we are adding
473
                 * an exact host ip into the radix tree, in which case we don't
474
                 * need to add the netmask value into the tree */
475
1.12k
                if (netmask == NETMASK_MAX)
476
63
                    return node;
477
478
                /* looks like we have a netmask which is != 32, in which
479
                 * case we walk up the tree to insert this netmask value in the
480
                 * correct node */
481
1.06k
                parent = node->parent;
482
1.91k
                while (parent != NULL && netmask < (parent->bit + 1)) {
483
849
                    node = parent;
484
849
                    parent = parent->parent;
485
849
                }
486
487
1.06k
                AddNetmaskToMasks(node, netmask);
488
1.06k
                if (NetmaskEqualsMask(node, netmask)) {
489
181
                    return node;
490
181
                }
491
1.06k
            }
492
2.28k
        }
493
885
        return node;
494
2.28k
    }
495
496
    /* create the leaf node for the new key */
497
21.8k
    RADIX_NODE_TYPE *new_node = RadixCreateNode();
498
21.8k
    if (new_node == NULL)
499
0
        return NULL;
500
21.8k
    memcpy(new_node->prefix_stream, tmp_stream, sizeof(tmp_stream));
501
21.8k
    new_node->has_prefix = true;
502
21.8k
    new_node->user_data = AllocUserData(netmask, user);
503
21.8k
    if (new_node->user_data == NULL) {
504
0
        ReleaseNode(new_node, tree, config);
505
0
        return NULL;
506
0
    }
507
508
    /* stick our new_node into the tree.  Create a node that holds the
509
     * differing bit position and break the branch.  Also handle the
510
     * tranfer of netmasks between node and inter_node(explained in more
511
     * detail below) */
512
21.8k
    RADIX_NODE_TYPE *inter_node = RadixCreateNode();
513
21.8k
    if (inter_node == NULL) {
514
0
        ReleaseNode(new_node, tree, config);
515
0
        return NULL;
516
0
    }
517
21.8k
    inter_node->has_prefix = false;
518
21.8k
    inter_node->bit = differ_bit;
519
21.8k
    inter_node->parent = node->parent;
520
21.8k
    SCLogDebug("inter_node: differ_bit %u", differ_bit);
521
522
    /* update netmasks for node and set them for inter_node */
523
21.8k
    ProcessInternode(node, inter_node);
524
525
21.8k
    if (RADIX_BITTEST(tmp_stream[differ_bit >> 3], (0x80 >> (differ_bit % 8)))) {
526
11.4k
        inter_node->left = node;
527
11.4k
        inter_node->right = new_node;
528
11.4k
    } else {
529
10.4k
        inter_node->left = new_node;
530
10.4k
        inter_node->right = node;
531
10.4k
    }
532
21.8k
    new_node->parent = inter_node;
533
534
21.8k
    if (node->parent == NULL)
535
2.67k
        tree->head = inter_node;
536
19.1k
    else if (node->parent->right == node)
537
6.88k
        node->parent->right = inter_node;
538
12.2k
    else
539
12.2k
        node->parent->left = inter_node;
540
541
21.8k
    node->parent = inter_node;
542
543
    /* insert the netmask into the tree */
544
21.8k
    if (netmask != NETMASK_MAX) {
545
17.9k
        node = new_node;
546
17.9k
        parent = new_node->parent;
547
18.4k
        while (parent != NULL && netmask < (parent->bit + 1)) {
548
449
            node = parent;
549
449
            parent = parent->parent;
550
449
        }
551
17.9k
        AddNetmaskToMasks(node, netmask);
552
17.9k
    }
553
21.8k
    return new_node;
554
21.8k
}
util-radix6-tree.c:AddKey
Line
Count
Source
337
26.6k
{
338
26.6k
    DEBUG_VALIDATE_BUG_ON(config == NULL);
339
26.6k
    RADIX_NODE_TYPE *node = NULL;
340
26.6k
    RADIX_NODE_TYPE *parent = NULL;
341
26.6k
    RADIX_NODE_TYPE *bottom_node = NULL;
342
343
26.6k
    uint8_t tmp_stream[ADDRESS_BYTES];
344
26.6k
    memcpy(tmp_stream, key_stream, sizeof(tmp_stream));
345
346
26.6k
    if (tree == NULL) {
347
0
        SCLogError("Argument \"tree\" NULL");
348
0
        sc_errno = SC_EINVAL;
349
0
        return NULL;
350
0
    }
351
352
    /* chop the ip address against a netmask */
353
26.6k
    MaskIPNetblock(tmp_stream, netmask, NETMASK_MAX);
354
355
    /* the very first element in the radix tree */
356
26.6k
    if (tree->head == NULL) {
357
12.2k
        node = RadixCreateNode();
358
12.2k
        if (node == NULL)
359
0
            return NULL;
360
12.2k
        memcpy(node->prefix_stream, tmp_stream, sizeof(tmp_stream));
361
12.2k
        node->has_prefix = true;
362
12.2k
        node->user_data = AllocUserData(netmask, user);
363
12.2k
        if (node->user_data == NULL) {
364
0
            ReleaseNode(node, tree, config);
365
0
            return NULL;
366
0
        }
367
12.2k
        tree->head = node;
368
12.2k
        if (netmask == NETMASK_MAX)
369
1.60k
            return node;
370
371
10.6k
        AddNetmaskToMasks(node, netmask);
372
10.6k
        return node;
373
12.2k
    }
374
14.4k
    node = tree->head;
375
376
    /* we walk down the tree only when we satisfy 2 conditions.  The first one
377
     * being the incoming prefix is shorter than the differ bit of the current
378
     * node.  In case we fail in this aspect, we walk down to the tree, till we
379
     * arrive at a node that ends in a prefix */
380
54.2k
    while (node->bit < NETMASK_MAX || !node->has_prefix) {
381
        /* if the bitlen isn't long enough to handle the bit test, we just walk
382
         * down along one of the paths, since either paths should end up with a
383
         * node that has a common prefix whose differ bit is greater than the
384
         * bitlen of the incoming prefix */
385
39.7k
        if (NETMASK_MAX <= node->bit) {
386
0
            if (node->right == NULL)
387
0
                break;
388
0
            node = node->right;
389
39.7k
        } else {
390
39.7k
            if (RADIX_BITTEST(tmp_stream[node->bit >> 3], (0x80 >> (node->bit % 8)))) {
391
6.65k
                if (node->right == NULL)
392
0
                    break;
393
6.65k
                node = node->right;
394
33.1k
            } else {
395
33.1k
                if (node->left == NULL)
396
0
                    break;
397
33.1k
                node = node->left;
398
33.1k
            }
399
39.7k
        }
400
39.7k
    }
401
402
    /* we need to keep a reference to the bottom-most node, that actually holds
403
     * the prefix */
404
14.4k
    bottom_node = node;
405
406
    /* get the first bit position where the ips differ */
407
14.4k
    uint8_t check_bit = MIN(node->bit, NETMASK_MAX);
408
14.4k
    uint8_t differ_bit = 0;
409
14.4k
    uint8_t j = 0;
410
154k
    for (uint8_t i = 0; (i * 8) < check_bit; i++) {
411
147k
        int temp = 0;
412
147k
        if ((temp = (tmp_stream[i] ^ bottom_node->prefix_stream[i])) == 0) {
413
139k
            differ_bit = (i + 1) * 8;
414
139k
            continue;
415
139k
        }
416
417
        /* find out the position where the first bit differs.  This method is
418
         * faster, but at the cost of being larger.  But with larger caches
419
         * these days we don't have to worry about cache misses */
420
8.30k
        temp = temp * 2;
421
8.30k
        if (temp >= 256)
422
471
            j = 0;
423
7.83k
        else if (temp >= 128)
424
1.61k
            j = 1;
425
6.22k
        else if (temp >= 64)
426
835
            j = 2;
427
5.38k
        else if (temp >= 32)
428
524
            j = 3;
429
4.86k
        else if (temp >= 16)
430
1.41k
            j = 4;
431
3.45k
        else if (temp >= 8)
432
1.33k
            j = 5;
433
2.11k
        else if (temp >= 4)
434
947
            j = 6;
435
1.16k
        else if (temp >= 2)
436
1.16k
            j = 7;
437
438
8.30k
        differ_bit = i * 8 + j;
439
8.30k
        break;
440
147k
    }
441
14.4k
    if (check_bit < differ_bit)
442
0
        differ_bit = check_bit;
443
444
    /* walk up the tree till we find the position, to fit our new node in */
445
14.4k
    parent = node->parent;
446
22.6k
    while (parent && differ_bit <= parent->bit) {
447
8.15k
        node = parent;
448
8.15k
        parent = node->parent;
449
8.15k
    }
450
14.4k
    BUG_ON(differ_bit == NETMASK_MAX && node->bit != NETMASK_MAX);
451
452
    /* We already have the node in the tree with the same differing bit position */
453
14.4k
    if (differ_bit == NETMASK_MAX && node->bit == NETMASK_MAX) {
454
6.14k
        if (node->has_prefix) {
455
            /* Check if we already have this netmask entry covered by this prefix */
456
6.14k
            if (ContainNetmask(node, netmask)) {
457
                /* Basically we already have this stream prefix, as well as the
458
                 * netblock entry for this.  A perfect duplicate. */
459
3.27k
                if (exclusive) {
460
3.27k
                    SCLogDebug("not inserting since it already exists");
461
3.27k
                    sc_errno = SC_EEXIST;
462
3.27k
                    return NULL;
463
3.27k
                }
464
0
                SCLogDebug("Duplicate entry for this ip address/netblock");
465
2.86k
            } else {
466
                /* Basically we already have this stream prefix, but we don't
467
                 * have an entry for this particular netmask value for this
468
                 * prefix.  For example, we have an entry for 192.168.0.0 and
469
                 * 192.168.0.0/16 and now we are trying to enter 192.168.0.0/20 */
470
2.86k
                AddNetmaskUserDataToNode(node, netmask, user);
471
472
                /* if we are adding a netmask of 32 it indicates we are adding
473
                 * an exact host ip into the radix tree, in which case we don't
474
                 * need to add the netmask value into the tree */
475
2.86k
                if (netmask == NETMASK_MAX)
476
969
                    return node;
477
478
                /* looks like we have a netmask which is != 32, in which
479
                 * case we walk up the tree to insert this netmask value in the
480
                 * correct node */
481
1.89k
                parent = node->parent;
482
3.08k
                while (parent != NULL && netmask < (parent->bit + 1)) {
483
1.18k
                    node = parent;
484
1.18k
                    parent = parent->parent;
485
1.18k
                }
486
487
1.89k
                AddNetmaskToMasks(node, netmask);
488
1.89k
                if (NetmaskEqualsMask(node, netmask)) {
489
0
                    return node;
490
0
                }
491
1.89k
            }
492
6.14k
        }
493
1.89k
        return node;
494
6.14k
    }
495
496
    /* create the leaf node for the new key */
497
8.30k
    RADIX_NODE_TYPE *new_node = RadixCreateNode();
498
8.30k
    if (new_node == NULL)
499
0
        return NULL;
500
8.30k
    memcpy(new_node->prefix_stream, tmp_stream, sizeof(tmp_stream));
501
8.30k
    new_node->has_prefix = true;
502
8.30k
    new_node->user_data = AllocUserData(netmask, user);
503
8.30k
    if (new_node->user_data == NULL) {
504
0
        ReleaseNode(new_node, tree, config);
505
0
        return NULL;
506
0
    }
507
508
    /* stick our new_node into the tree.  Create a node that holds the
509
     * differing bit position and break the branch.  Also handle the
510
     * tranfer of netmasks between node and inter_node(explained in more
511
     * detail below) */
512
8.30k
    RADIX_NODE_TYPE *inter_node = RadixCreateNode();
513
8.30k
    if (inter_node == NULL) {
514
0
        ReleaseNode(new_node, tree, config);
515
0
        return NULL;
516
0
    }
517
8.30k
    inter_node->has_prefix = false;
518
8.30k
    inter_node->bit = differ_bit;
519
8.30k
    inter_node->parent = node->parent;
520
8.30k
    SCLogDebug("inter_node: differ_bit %u", differ_bit);
521
522
    /* update netmasks for node and set them for inter_node */
523
8.30k
    ProcessInternode(node, inter_node);
524
525
8.30k
    if (RADIX_BITTEST(tmp_stream[differ_bit >> 3], (0x80 >> (differ_bit % 8)))) {
526
6.97k
        inter_node->left = node;
527
6.97k
        inter_node->right = new_node;
528
6.97k
    } else {
529
1.33k
        inter_node->left = new_node;
530
1.33k
        inter_node->right = node;
531
1.33k
    }
532
8.30k
    new_node->parent = inter_node;
533
534
8.30k
    if (node->parent == NULL)
535
3.58k
        tree->head = inter_node;
536
4.72k
    else if (node->parent->right == node)
537
1.80k
        node->parent->right = inter_node;
538
2.92k
    else
539
2.92k
        node->parent->left = inter_node;
540
541
8.30k
    node->parent = inter_node;
542
543
    /* insert the netmask into the tree */
544
8.30k
    if (netmask != NETMASK_MAX) {
545
3.12k
        node = new_node;
546
3.12k
        parent = new_node->parent;
547
3.93k
        while (parent != NULL && netmask < (parent->bit + 1)) {
548
806
            node = parent;
549
806
            parent = parent->parent;
550
806
        }
551
3.12k
        AddNetmaskToMasks(node, netmask);
552
3.12k
    }
553
8.30k
    return new_node;
554
8.30k
}
555
556
/**
557
 * \brief Removes a netblock entry from an ip node.  The function first
558
 *        deletes the netblock/user_data entry for the prefix and then
559
 *        removes the netmask entry that has been made in the tree, by
560
 *        walking up the tree and deleting the entry from the specific node.
561
 *
562
 * \param node    The node from which the netblock entry has to be removed.
563
 * \param netmask The netmask entry (cidr) that has to be removed.
564
 */
565
static void RemoveNetblockEntry(RADIX_NODE_TYPE *node, uint8_t netmask)
566
0
{
567
0
    BUG_ON(!node);
568
569
0
    RemoveNetmaskUserDataFromNode(node, netmask);
570
571
0
    if (netmask == NETMASK_MAX) {
572
0
        SCLogDebug("%d == %d", netmask, NETMASK_MAX);
573
0
        return;
574
0
    }
575
576
0
    RemoveNetmaskFromMasks(node, netmask);
577
0
    if (node->parent != NULL)
578
0
        RemoveNetmaskFromMasks(node->parent, netmask);
579
0
    return;
580
0
}
Unexecuted instantiation: util-radix4-tree.c:RemoveNetblockEntry
Unexecuted instantiation: util-radix6-tree.c:RemoveNetblockEntry
581
582
/**
583
 * \brief Removes a key from the Radix tree
584
 *
585
 * \param key_stream Data that has to be removed from the Radix tree
586
 * \param tree       Pointer to the Radix tree from which the key has to be
587
 *                   removed
588
 */
589
static void RemoveKey(RADIX_TREE_TYPE *tree, const RADIX_CONFIG_TYPE *config,
590
        const uint8_t *key_stream, const uint8_t netmask)
591
0
{
592
0
    RADIX_NODE_TYPE *node = tree->head;
593
0
    RADIX_NODE_TYPE *parent = NULL;
594
0
    RADIX_NODE_TYPE *temp_dest = NULL;
595
596
0
    if (node == NULL) {
597
0
        SCLogDebug("tree is empty");
598
0
        return;
599
0
    }
600
601
0
    uint8_t tmp_stream[ADDRESS_BYTES];
602
0
    memcpy(tmp_stream, key_stream, sizeof(tmp_stream));
603
604
0
    while (node->bit < NETMASK_MAX) {
605
0
        if (RADIX_BITTEST(tmp_stream[node->bit >> 3], (0x80 >> (node->bit % 8)))) {
606
0
            node = node->right;
607
0
        } else {
608
0
            node = node->left;
609
0
        }
610
611
0
        if (node == NULL) {
612
0
            SCLogDebug("no matching node found");
613
0
            return;
614
0
        }
615
0
    }
616
617
0
    if (node->bit != NETMASK_MAX || !node->has_prefix) {
618
0
        SCLogDebug("node %p bit %d != %d, or not has_prefix %s", node, node->bit, NETMASK_MAX,
619
0
                node->has_prefix ? "true" : "false");
620
0
        return;
621
0
    }
622
623
0
    if (SCMemcmp(node->prefix_stream, tmp_stream, sizeof(tmp_stream)) == 0) {
624
0
        if (!ContainNetmask(node, netmask)) {
625
0
            SCLogDebug("key exists in the tree, but this (%d) "
626
0
                       "netblock entry doesn't exist",
627
0
                    netmask);
628
0
            return;
629
0
        }
630
0
    } else {
631
0
        SCLogDebug("You are trying to remove a key that doesn't exist in the "
632
0
                   "Radix Tree");
633
0
        return;
634
0
    }
635
636
    /* The ip node does exist, and the netblock entry does exist in this node, if
637
     * we have reached this point.  If we have more than one netblock entry, it
638
     * indicates we have multiple entries for this key.  So we delete that
639
     * particular netblock entry, and make our way out of this function */
640
0
    if (NetmaskCount(node) > 1) { // || !NoneNegated(node)) {
641
0
        RemoveNetblockEntry(node, netmask);
642
0
        SCLogDebug("NetmaskCount");
643
0
        return;
644
0
    }
645
0
    SCLogDebug("not netmask cnt");
646
647
    /* we are deleting the root of the tree.  This would be the only node left
648
     * in the tree */
649
0
    if (tree->head == node) {
650
0
        ReleaseNode(node, tree, config);
651
0
        tree->head = NULL;
652
0
        SCLogDebug("tree->head == node");
653
0
        return;
654
0
    }
655
656
0
    parent = node->parent;
657
    /* parent->parent is not the root of the tree */
658
0
    if (parent->parent != NULL) {
659
0
        if (parent->parent->left == parent) {
660
0
            if (node->parent->left == node) {
661
0
                temp_dest = parent->right;
662
0
                parent->parent->left = parent->right;
663
0
                parent->right->parent = parent->parent;
664
0
            } else {
665
0
                temp_dest = parent->left;
666
0
                parent->parent->left = parent->left;
667
0
                parent->left->parent = parent->parent;
668
0
            }
669
0
        } else {
670
0
            if (node->parent->left == node) {
671
0
                temp_dest = parent->right;
672
0
                parent->parent->right = parent->right;
673
0
                parent->right->parent = parent->parent;
674
0
            } else {
675
0
                temp_dest = parent->left;
676
0
                parent->parent->right = parent->left;
677
0
                parent->left->parent = parent->parent;
678
0
            }
679
0
        }
680
        /* parent is the root of the tree */
681
0
    } else {
682
0
        if (parent->left == node) {
683
0
            temp_dest = tree->head->right;
684
0
            tree->head->right->parent = NULL;
685
0
            tree->head = tree->head->right;
686
0
        } else {
687
0
            temp_dest = tree->head->left;
688
0
            tree->head->left->parent = NULL;
689
0
            tree->head = tree->head->left;
690
0
        }
691
0
    }
692
    /* We need to shift the netmask entries from the node that would be
693
     * deleted to its immediate descendant */
694
0
    AddNetmasksFromNode(temp_dest, parent);
695
0
    RemoveNetmaskFromMasks(temp_dest, netmask);
696
    /* release the nodes */
697
0
    ReleaseNode(parent, tree, config);
698
0
    ReleaseNode(node, tree, config);
699
700
0
    SCLogDebug("end (netmask %d)", netmask);
701
0
    return;
702
0
}
Unexecuted instantiation: util-radix4-tree.c:RemoveKey
Unexecuted instantiation: util-radix6-tree.c:RemoveKey
703
704
/**
705
 * \brief Checks if an IP prefix falls under a netblock, in the path to the root
706
 *        of the tree, from the node.  Used internally by FindKey()
707
 *
708
 * \param prefix Pointer to the prefix that contains the ip address
709
 * \param node   Pointer to the node from where we have to climb the tree
710
 */
711
static inline RADIX_NODE_TYPE *FindKeyIPNetblock(const uint8_t *key_stream, RADIX_NODE_TYPE *node,
712
        void **user_data_result, uint8_t *out_netmask)
713
240k
{
714
371k
    while (node != NULL && NetmasksEmpty(node))
715
131k
        node = node->parent;
716
240k
    if (node == NULL)
717
9.42k
        return NULL;
718
719
231k
    uint8_t tmp_stream[ADDRESS_BYTES];
720
231k
    memcpy(tmp_stream, key_stream, sizeof(tmp_stream));
721
722
    /* hold the node found containing a netmask.  We will need it when we call
723
     * this function recursively */
724
231k
    RADIX_NODE_TYPE *netmask_node = node;
725
726
12.6M
    for (uint8_t j = 0; j <= NETMASK_MAX; j++) {
727
12.5M
        uint8_t m = NETMASK_MAX - j;
728
729
12.5M
        if (!(NetmaskIssetInMasks(netmask_node, m)))
730
12.3M
            continue;
731
732
1.82M
        for (uint8_t i = 0; i < ADDRESS_BYTES; i++) {
733
1.59M
            uint32_t mask = UINT_MAX;
734
1.59M
            if (((i + 1) * 8) > m) {
735
1.52M
                if (((i + 1) * 8 - m) < 8)
736
27.5k
                    mask = UINT_MAX << ((i + 1) * 8 - m);
737
1.49M
                else
738
1.49M
                    mask = 0;
739
1.52M
            }
740
1.59M
            tmp_stream[i] &= mask;
741
1.59M
        }
742
743
285k
        while (node->bit < NETMASK_MAX) {
744
52.4k
            if (RADIX_BITTEST(tmp_stream[node->bit >> 3], (0x80 >> (node->bit % 8)))) {
745
0
                node = node->right;
746
52.4k
            } else {
747
52.4k
                node = node->left;
748
52.4k
            }
749
750
52.4k
            if (node == NULL)
751
0
                return NULL;
752
52.4k
        }
753
754
233k
        if (node->bit != NETMASK_MAX || !node->has_prefix)
755
0
            return NULL;
756
757
233k
        if (SCMemcmp(node->prefix_stream, tmp_stream, sizeof(tmp_stream)) == 0) {
758
213k
            if (ContainNetmaskAndSetUserData(node, m, false, user_data_result)) {
759
213k
                *out_netmask = m;
760
213k
                return node;
761
213k
            }
762
213k
        }
763
233k
    }
764
765
17.3k
    return FindKeyIPNetblock(tmp_stream, netmask_node->parent, user_data_result, out_netmask);
766
231k
}
util-radix4-tree.c:FindKeyIPNetblock
Line
Count
Source
713
186k
{
714
308k
    while (node != NULL && NetmasksEmpty(node))
715
122k
        node = node->parent;
716
186k
    if (node == NULL)
717
8.90k
        return NULL;
718
719
177k
    uint8_t tmp_stream[ADDRESS_BYTES];
720
177k
    memcpy(tmp_stream, key_stream, sizeof(tmp_stream));
721
722
    /* hold the node found containing a netmask.  We will need it when we call
723
     * this function recursively */
724
177k
    RADIX_NODE_TYPE *netmask_node = node;
725
726
5.76M
    for (uint8_t j = 0; j <= NETMASK_MAX; j++) {
727
5.74M
        uint8_t m = NETMASK_MAX - j;
728
729
5.74M
        if (!(NetmaskIssetInMasks(netmask_node, m)))
730
5.56M
            continue;
731
732
890k
        for (uint8_t i = 0; i < ADDRESS_BYTES; i++) {
733
712k
            uint32_t mask = UINT_MAX;
734
712k
            if (((i + 1) * 8) > m) {
735
665k
                if (((i + 1) * 8 - m) < 8)
736
23.2k
                    mask = UINT_MAX << ((i + 1) * 8 - m);
737
642k
                else
738
642k
                    mask = 0;
739
665k
            }
740
712k
            tmp_stream[i] &= mask;
741
712k
        }
742
743
217k
        while (node->bit < NETMASK_MAX) {
744
39.3k
            if (RADIX_BITTEST(tmp_stream[node->bit >> 3], (0x80 >> (node->bit % 8)))) {
745
0
                node = node->right;
746
39.3k
            } else {
747
39.3k
                node = node->left;
748
39.3k
            }
749
750
39.3k
            if (node == NULL)
751
0
                return NULL;
752
39.3k
        }
753
754
178k
        if (node->bit != NETMASK_MAX || !node->has_prefix)
755
0
            return NULL;
756
757
178k
        if (SCMemcmp(node->prefix_stream, tmp_stream, sizeof(tmp_stream)) == 0) {
758
160k
            if (ContainNetmaskAndSetUserData(node, m, false, user_data_result)) {
759
160k
                *out_netmask = m;
760
160k
                return node;
761
160k
            }
762
160k
        }
763
178k
    }
764
765
16.5k
    return FindKeyIPNetblock(tmp_stream, netmask_node->parent, user_data_result, out_netmask);
766
177k
}
util-radix6-tree.c:FindKeyIPNetblock
Line
Count
Source
713
54.3k
{
714
63.3k
    while (node != NULL && NetmasksEmpty(node))
715
9.02k
        node = node->parent;
716
54.3k
    if (node == NULL)
717
516
        return NULL;
718
719
53.7k
    uint8_t tmp_stream[ADDRESS_BYTES];
720
53.7k
    memcpy(tmp_stream, key_stream, sizeof(tmp_stream));
721
722
    /* hold the node found containing a netmask.  We will need it when we call
723
     * this function recursively */
724
53.7k
    RADIX_NODE_TYPE *netmask_node = node;
725
726
6.85M
    for (uint8_t j = 0; j <= NETMASK_MAX; j++) {
727
6.84M
        uint8_t m = NETMASK_MAX - j;
728
729
6.84M
        if (!(NetmaskIssetInMasks(netmask_node, m)))
730
6.79M
            continue;
731
732
936k
        for (uint8_t i = 0; i < ADDRESS_BYTES; i++) {
733
881k
            uint32_t mask = UINT_MAX;
734
881k
            if (((i + 1) * 8) > m) {
735
856k
                if (((i + 1) * 8 - m) < 8)
736
4.27k
                    mask = UINT_MAX << ((i + 1) * 8 - m);
737
851k
                else
738
851k
                    mask = 0;
739
856k
            }
740
881k
            tmp_stream[i] &= mask;
741
881k
        }
742
743
68.1k
        while (node->bit < NETMASK_MAX) {
744
13.0k
            if (RADIX_BITTEST(tmp_stream[node->bit >> 3], (0x80 >> (node->bit % 8)))) {
745
0
                node = node->right;
746
13.0k
            } else {
747
13.0k
                node = node->left;
748
13.0k
            }
749
750
13.0k
            if (node == NULL)
751
0
                return NULL;
752
13.0k
        }
753
754
55.0k
        if (node->bit != NETMASK_MAX || !node->has_prefix)
755
0
            return NULL;
756
757
55.0k
        if (SCMemcmp(node->prefix_stream, tmp_stream, sizeof(tmp_stream)) == 0) {
758
52.9k
            if (ContainNetmaskAndSetUserData(node, m, false, user_data_result)) {
759
52.9k
                *out_netmask = m;
760
52.9k
                return node;
761
52.9k
            }
762
52.9k
        }
763
55.0k
    }
764
765
838
    return FindKeyIPNetblock(tmp_stream, netmask_node->parent, user_data_result, out_netmask);
766
53.7k
}
767
768
/**
769
 * \brief Checks if an IP address key is present in the tree.  The function
770
 *        apart from handling any normal data, also handles ipv4/ipv6 netblocks
771
 *
772
 * \param key_stream  Data that has to be found in the Radix tree
773
 * \param tree        Pointer to the Radix tree
774
 * \param exact_match The key to be searched is an ip address
775
 */
776
static RADIX_NODE_TYPE *FindKey(const RADIX_TREE_TYPE *tree, const uint8_t *key_stream,
777
        const uint8_t netmask, bool exact_match, void **user_data_result, uint8_t *out_netmask)
778
4.00M
{
779
4.00M
    if (tree == NULL || tree->head == NULL)
780
3.71M
        return NULL;
781
782
290k
    RADIX_NODE_TYPE *node = tree->head;
783
290k
    uint8_t tmp_stream[ADDRESS_BYTES];
784
290k
    memcpy(tmp_stream, key_stream, sizeof(tmp_stream));
785
786
864k
    while (node->bit < NETMASK_MAX) {
787
574k
        if (RADIX_BITTEST(tmp_stream[node->bit >> 3], (0x80 >> (node->bit % 8)))) {
788
137k
            node = node->right;
789
436k
        } else {
790
436k
            node = node->left;
791
436k
        }
792
793
574k
        if (node == NULL) {
794
0
            return NULL;
795
0
        }
796
574k
    }
797
798
290k
    if (node->bit != NETMASK_MAX || !node->has_prefix) {
799
0
        return NULL;
800
0
    }
801
802
290k
    if (SCMemcmp(node->prefix_stream, tmp_stream, sizeof(tmp_stream)) == 0) {
803
56.1k
        SCLogDebug("stream match");
804
56.1k
        if (ContainNetmaskAndSetUserData(node, netmask, true, user_data_result)) {
805
40.4k
            SCLogDebug("contains netmask etc");
806
40.4k
            *out_netmask = netmask;
807
40.4k
            return node;
808
40.4k
        }
809
56.1k
    }
810
811
    /* if you are not an ip key, get out of here */
812
250k
    if (exact_match) {
813
26.8k
        SCLogDebug("no node found and need exact match, so failed");
814
26.8k
        return NULL;
815
26.8k
    }
816
817
223k
    RADIX_NODE_TYPE *ret = FindKeyIPNetblock(tmp_stream, node, user_data_result, out_netmask);
818
223k
    return ret;
819
250k
}
util-radix4-tree.c:FindKey
Line
Count
Source
778
2.71M
{
779
2.71M
    if (tree == NULL || tree->head == NULL)
780
2.49M
        return NULL;
781
782
211k
    RADIX_NODE_TYPE *node = tree->head;
783
211k
    uint8_t tmp_stream[ADDRESS_BYTES];
784
211k
    memcpy(tmp_stream, key_stream, sizeof(tmp_stream));
785
786
755k
    while (node->bit < NETMASK_MAX) {
787
544k
        if (RADIX_BITTEST(tmp_stream[node->bit >> 3], (0x80 >> (node->bit % 8)))) {
788
125k
            node = node->right;
789
418k
        } else {
790
418k
            node = node->left;
791
418k
        }
792
793
544k
        if (node == NULL) {
794
0
            return NULL;
795
0
        }
796
544k
    }
797
798
211k
    if (node->bit != NETMASK_MAX || !node->has_prefix) {
799
0
        return NULL;
800
0
    }
801
802
211k
    if (SCMemcmp(node->prefix_stream, tmp_stream, sizeof(tmp_stream)) == 0) {
803
32.1k
        SCLogDebug("stream match");
804
32.1k
        if (ContainNetmaskAndSetUserData(node, netmask, true, user_data_result)) {
805
21.8k
            SCLogDebug("contains netmask etc");
806
21.8k
            *out_netmask = netmask;
807
21.8k
            return node;
808
21.8k
        }
809
32.1k
    }
810
811
    /* if you are not an ip key, get out of here */
812
189k
    if (exact_match) {
813
19.8k
        SCLogDebug("no node found and need exact match, so failed");
814
19.8k
        return NULL;
815
19.8k
    }
816
817
169k
    RADIX_NODE_TYPE *ret = FindKeyIPNetblock(tmp_stream, node, user_data_result, out_netmask);
818
169k
    return ret;
819
189k
}
util-radix6-tree.c:FindKey
Line
Count
Source
778
1.29M
{
779
1.29M
    if (tree == NULL || tree->head == NULL)
780
1.21M
        return NULL;
781
782
79.1k
    RADIX_NODE_TYPE *node = tree->head;
783
79.1k
    uint8_t tmp_stream[ADDRESS_BYTES];
784
79.1k
    memcpy(tmp_stream, key_stream, sizeof(tmp_stream));
785
786
109k
    while (node->bit < NETMASK_MAX) {
787
30.2k
        if (RADIX_BITTEST(tmp_stream[node->bit >> 3], (0x80 >> (node->bit % 8)))) {
788
11.5k
            node = node->right;
789
18.6k
        } else {
790
18.6k
            node = node->left;
791
18.6k
        }
792
793
30.2k
        if (node == NULL) {
794
0
            return NULL;
795
0
        }
796
30.2k
    }
797
798
79.1k
    if (node->bit != NETMASK_MAX || !node->has_prefix) {
799
0
        return NULL;
800
0
    }
801
802
79.1k
    if (SCMemcmp(node->prefix_stream, tmp_stream, sizeof(tmp_stream)) == 0) {
803
23.9k
        SCLogDebug("stream match");
804
23.9k
        if (ContainNetmaskAndSetUserData(node, netmask, true, user_data_result)) {
805
18.5k
            SCLogDebug("contains netmask etc");
806
18.5k
            *out_netmask = netmask;
807
18.5k
            return node;
808
18.5k
        }
809
23.9k
    }
810
811
    /* if you are not an ip key, get out of here */
812
60.5k
    if (exact_match) {
813
7.05k
        SCLogDebug("no node found and need exact match, so failed");
814
7.05k
        return NULL;
815
7.05k
    }
816
817
53.4k
    RADIX_NODE_TYPE *ret = FindKeyIPNetblock(tmp_stream, node, user_data_result, out_netmask);
818
53.4k
    return ret;
819
60.5k
}
820
821
/**
822
 * \brief Checks if an IPV4 address is present in the tree
823
 *
824
 * \param key_stream Data that has to be found in the Radix tree.  In this case
825
 *                   an IPV4 address
826
 * \param tree       Pointer to the Radix tree instance
827
 */
828
static RADIX_NODE_TYPE *FindExactMatch(
829
        const RADIX_TREE_TYPE *tree, const uint8_t *key_stream, void **user_data_result)
830
20.8k
{
831
20.8k
    uint8_t unused = 0;
832
20.8k
    return FindKey(tree, key_stream, NETMASK_MAX, true, user_data_result, &unused);
833
20.8k
}
util-radix4-tree.c:FindExactMatch
Line
Count
Source
830
5.19k
{
831
5.19k
    uint8_t unused = 0;
832
5.19k
    return FindKey(tree, key_stream, NETMASK_MAX, true, user_data_result, &unused);
833
5.19k
}
util-radix6-tree.c:FindExactMatch
Line
Count
Source
830
15.6k
{
831
15.6k
    uint8_t unused = 0;
832
15.6k
    return FindKey(tree, key_stream, NETMASK_MAX, true, user_data_result, &unused);
833
15.6k
}
834
835
/**
836
 * \brief Checks if an IPV4 address is present in the tree under a netblock
837
 *
838
 * \param key_stream Data that has to be found in the Radix tree.  In this case
839
 *                   an IPV4 address
840
 * \param tree       Pointer to the Radix tree instance
841
 */
842
static RADIX_NODE_TYPE *FindBestMatch(
843
        const RADIX_TREE_TYPE *tree, const uint8_t *key_stream, void **user_data_result)
844
3.91M
{
845
3.91M
    uint8_t unused = 0;
846
3.91M
    return FindKey(tree, key_stream, NETMASK_MAX, false, user_data_result, &unused);
847
3.91M
}
util-radix4-tree.c:FindBestMatch
Line
Count
Source
844
2.65M
{
845
2.65M
    uint8_t unused = 0;
846
2.65M
    return FindKey(tree, key_stream, NETMASK_MAX, false, user_data_result, &unused);
847
2.65M
}
util-radix6-tree.c:FindBestMatch
Line
Count
Source
844
1.25M
{
845
1.25M
    uint8_t unused = 0;
846
1.25M
    return FindKey(tree, key_stream, NETMASK_MAX, false, user_data_result, &unused);
847
1.25M
}
848
849
static RADIX_NODE_TYPE *FindBestMatch2(const RADIX_TREE_TYPE *tree, const uint8_t *key_stream,
850
        void **user_data_result, uint8_t *out_netmask)
851
0
{
852
0
    return FindKey(tree, key_stream, NETMASK_MAX, false, user_data_result, out_netmask);
853
0
}
Unexecuted instantiation: util-radix4-tree.c:FindBestMatch2
Unexecuted instantiation: util-radix6-tree.c:FindBestMatch2
854
855
/**
856
 * \brief Checks if an IPV4 Netblock address is present in the tree
857
 *
858
 * \param key_stream Data that has to be found in the Radix tree.  In this case
859
 *                   an IPV4  netblock address
860
 * \param tree       Pointer to the Radix tree instance
861
 */
862
static RADIX_NODE_TYPE *FindNetblock(const RADIX_TREE_TYPE *tree, const uint8_t *key_stream,
863
        const uint8_t netmask, void **user_data_result)
864
68.2k
{
865
68.2k
    uint8_t unused = 0;
866
68.2k
    RADIX_NODE_TYPE *node = FindKey(tree, key_stream, netmask, true, user_data_result, &unused);
867
68.2k
    return node;
868
68.2k
}
util-radix4-tree.c:FindNetblock
Line
Count
Source
864
46.9k
{
865
46.9k
    uint8_t unused = 0;
866
46.9k
    RADIX_NODE_TYPE *node = FindKey(tree, key_stream, netmask, true, user_data_result, &unused);
867
46.9k
    return node;
868
46.9k
}
util-radix6-tree.c:FindNetblock
Line
Count
Source
864
21.3k
{
865
21.3k
    uint8_t unused = 0;
866
21.3k
    RADIX_NODE_TYPE *node = FindKey(tree, key_stream, netmask, true, user_data_result, &unused);
867
21.3k
    return node;
868
21.3k
}
869
870
/**
871
 * \brief Helper function used by PrintTree.  Prints the subtree with
872
 *        node as the root of the subtree
873
 *
874
 * \param node  Pointer to the node that is the root of the subtree to be printed
875
 * \param level Used for indentation purposes
876
 */
877
static void PrintSubtree(RADIX_NODE_TYPE *node, int level, void (*PrintData)(void *))
878
0
{
879
0
    if (node != NULL) {
880
0
        PrintNodeInfo(node, level, PrintData);
881
0
        PrintSubtree(node->left, level + 1, PrintData);
882
0
        PrintSubtree(node->right, level + 1, PrintData);
883
0
    }
884
885
0
    return;
886
0
}
Unexecuted instantiation: util-radix4-tree.c:PrintSubtree
Unexecuted instantiation: util-radix6-tree.c:PrintSubtree
887
888
/**
889
 * \brief Prints the Radix Tree. While printing the radix tree we use the
890
 *        following format
891
 *
892
 *        Parent_0
893
 *            Left_Child_1
894
 *                Left_Child_2
895
 *                Right_Child_2
896
 *            Right_Child_1
897
 *                Left_Child_2
898
 *                Right_Child_2     and so on
899
 *
900
 *        Each node printed out holds details on the next bit that differs
901
 *        amongst its children, and if the node holds a prefix, the perfix is
902
 *        printed as well.
903
 *
904
 * \param tree Pointer to the Radix tree that has to be printed
905
 */
906
static void PrintTree(RADIX_TREE_TYPE *tree, const RADIX_CONFIG_TYPE *config)
907
0
{
908
0
    printf("Printing the Radix Tree: \n");
909
0
    PrintSubtree(tree->head, 0, config->PrintData);
910
0
}
Unexecuted instantiation: util-radix4-tree.c:PrintTree
Unexecuted instantiation: util-radix6-tree.c:PrintTree
911
912
static bool CompareTreesSub(
913
        RADIX_NODE_TYPE *n1, RADIX_NODE_TYPE *n2, RADIX_TREE_COMPARE_CALLBACK Callback)
914
0
{
915
    // compare nodes
916
0
    bool n1_has_left = n1->left != NULL;
917
0
    bool n2_has_left = n2->left != NULL;
918
0
    if (n1_has_left != n2_has_left)
919
0
        return false;
920
921
0
    bool n1_has_right = n1->right != NULL;
922
0
    bool n2_has_right = n2->right != NULL;
923
0
    if (n1_has_right != n2_has_right)
924
0
        return false;
925
926
0
    if (SCMemcmp(n1->prefix_stream, n2->prefix_stream, ADDRESS_BYTES) != 0)
927
0
        return false;
928
929
0
    RadixUserData *u1 = n1->user_data;
930
0
    RadixUserData *u2 = n2->user_data;
931
0
    while (1) {
932
0
        if (u1 == NULL && u2 == NULL)
933
0
            break;
934
0
        if ((u1 != NULL && u2 == NULL) || (u1 == NULL && u2 != NULL))
935
0
            return false;
936
0
        if (u1->netmask != u2->netmask)
937
0
            return false;
938
939
0
        if (Callback != NULL) {
940
0
            if (!Callback(u1->user, u2->user))
941
0
                return false;
942
0
        }
943
944
0
        u1 = u1->next;
945
0
        u2 = u2->next;
946
0
    }
947
948
0
    if (n1->left && n2->left)
949
0
        if (!CompareTreesSub(n1->left, n2->left, Callback))
950
0
            return false;
951
0
    if (n1->right && n2->right)
952
0
        if (!CompareTreesSub(n1->right, n2->right, Callback))
953
0
            return false;
954
955
0
    return true;
956
0
}
Unexecuted instantiation: util-radix4-tree.c:CompareTreesSub
Unexecuted instantiation: util-radix6-tree.c:CompareTreesSub
957
958
static bool CompareTrees(
959
        const RADIX_TREE_TYPE *t1, const RADIX_TREE_TYPE *t2, RADIX_TREE_COMPARE_CALLBACK Callback)
960
0
{
961
0
    if (t1->head == NULL && t2->head == NULL)
962
0
        return true;
963
0
    if ((t1->head == NULL && t2->head != NULL) || (t1->head != NULL && t2->head == NULL))
964
0
        return false;
965
0
    return CompareTreesSub(t1->head, t2->head, Callback);
966
0
}
Unexecuted instantiation: util-radix4-tree.c:CompareTrees
Unexecuted instantiation: util-radix6-tree.c:CompareTrees