2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2011 Daniel Borkmann, rewritten
5 * Copyright 1991-2007 Kawahara Lab., Kyoto University
6 * Copyright 2000-2005 Shikano Lab., Nara Institute of Science and Technology
7 * Copyright 2005-2007 Julius project team, Nagoya Institute of Technology
9 * Subject to the GPL, version 2.
20 static unsigned char mbit
[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
22 static inline int testbit(char *str
, size_t slen
, int bitplace
)
25 if ((maskptr
= bitplace
>> 3) > slen
)
27 return (str
[maskptr
] & mbit
[bitplace
& 7]);
30 static inline int testbit_max(char *str
, int bitplace
, int maxbitplace
)
32 if (bitplace
>= maxbitplace
)
34 return (str
[bitplace
>> 3] & mbit
[bitplace
& 7]);
37 static int where_the_bit_differ(char *str1
, size_t l1
, char *str2
, size_t l2
)
40 while (str1
[p
] == str2
[p
])
43 while (testbit(str1
, l1
, bitloc
) ==
44 testbit(str2
, l2
, bitloc
))
49 static struct patricia_node
*new_node(void)
51 struct patricia_node
*n
= xzmalloc(sizeof(*n
));
56 static void free_node(struct patricia_node
*n
)
65 void ptree_display(struct patricia_node
*node
, int level
)
68 for (i
= 0; i
< level
; ++i
)
70 if (node
->l
== NULL
&& node
->r
== NULL
)
71 printf("leaf: (%s -> %d)\n", (char *) node
->key
, node
->value
.data
);
73 printf("thres: %d\n", node
->value
.thres_bit
);
75 ptree_display(node
->l
, level
+ 1);
77 ptree_display(node
->r
, level
+ 1);
81 void ptree_get_key(int data
, struct patricia_node
*node
,
82 struct patricia_node
**wanted
)
86 if (node
->l
== NULL
&& node
->r
== NULL
) {
87 if (node
->value
.data
== data
)
91 ptree_get_key(data
, node
->l
, wanted
);
93 ptree_get_key(data
, node
->r
, wanted
);
97 void ptree_get_key_addr(struct sockaddr_storage
*addr
, size_t alen
,
98 struct patricia_node
*node
, struct patricia_node
**wanted
)
102 if (node
->l
== NULL
&& node
->r
== NULL
) {
103 if (!memcmp(node
->addr
, addr
, node
->alen
))
107 ptree_get_key_addr(addr
, alen
, node
->l
, wanted
);
109 ptree_get_key_addr(addr
, alen
, node
->r
, wanted
);
113 static int ptree_search_data_r(struct patricia_node
*node
, char *str
,
114 size_t slen
, struct sockaddr_storage
*addr
,
115 size_t *alen
, int maxbitplace
)
117 if (node
->l
== NULL
&& node
->r
== NULL
) {
118 if (node
->addr
&& addr
)
119 memcpy(addr
, node
->addr
, node
->alen
);
120 (*alen
) = node
->alen
;
121 return node
->value
.data
;
123 if (testbit_max(str
, node
->value
.thres_bit
, maxbitplace
) != 0)
124 return ptree_search_data_r(node
->r
, str
, slen
, addr
,
127 return ptree_search_data_r(node
->l
, str
, slen
, addr
,
131 static int *ptree_search_data_r_p(struct patricia_node
*node
, char *str
,
132 size_t slen
, int maxbitplace
)
134 if (node
->l
== NULL
&& node
->r
== NULL
)
135 return &(node
->value
.data
);
136 if (testbit_max(str
, node
->value
.thres_bit
, maxbitplace
) != 0)
137 return ptree_search_data_r_p(node
->r
, str
, slen
, maxbitplace
);
139 return ptree_search_data_r_p(node
->l
, str
, slen
, maxbitplace
);
142 static int ptree_search_data_r_x(struct patricia_node
*node
, char *str
,
143 size_t slen
, struct sockaddr_storage
*addr
,
144 size_t *alen
, int maxbitplace
)
146 if (node
->l
== NULL
&& node
->r
== NULL
) {
147 if (node
->klen
== slen
&& !memcmp(str
, node
->key
, node
->klen
)) {
148 if (node
->addr
&& addr
)
149 memcpy(addr
, node
->addr
, node
->alen
);
150 (*alen
) = node
->alen
;
151 return node
->value
.data
;
155 if (testbit_max(str
, node
->value
.thres_bit
, maxbitplace
) != 0)
156 return ptree_search_data_r_x(node
->r
, str
, slen
, addr
,
159 return ptree_search_data_r_x(node
->l
, str
, slen
, addr
,
163 int ptree_search_data_nearest(void *str
, size_t sstr
, struct sockaddr_storage
*addr
,
164 size_t *alen
, struct patricia_node
*root
)
168 return ptree_search_data_r(root
, str
, sstr
, addr
, alen
, sstr
* 8);
171 static int *ptree_search_data_nearest_ptr(char *str
, size_t sstr
,
172 struct patricia_node
*root
)
174 return ptree_search_data_r_p(root
, str
, sstr
, sstr
* 8);
177 int ptree_search_data_exact(void *str
, size_t sstr
, struct sockaddr_storage
*addr
,
178 size_t *alen
, struct patricia_node
*root
)
182 return ptree_search_data_r_x(root
, str
, sstr
, addr
, alen
, sstr
* 8);
185 static struct patricia_node
*ptree_make_root_node(char *str
, size_t sstr
,
186 int data
, struct sockaddr_storage
*addr
,
189 struct patricia_node
*n
= new_node();
190 n
->value
.data
= data
;
191 n
->key
= xmemdupz(str
, sstr
);
194 n
->addr
= xmemdupz(addr
, alen
);
201 static void ptree_add_entry_at(char *str
, size_t slen
, int bitloc
, int data
,
202 struct sockaddr_storage
*addr
, size_t alen
,
203 struct patricia_node
**parentlink
)
205 struct patricia_node
*node
= (*parentlink
);
206 if (node
->value
.thres_bit
> bitloc
||
207 (node
->l
== NULL
&& node
->r
== NULL
)) {
208 struct patricia_node
*newleaf
, *newbranch
;
210 newleaf
= new_node();
211 newleaf
->value
.data
= data
;
212 newleaf
->key
= xmemdupz(str
, slen
);
213 newleaf
->klen
= slen
;
215 newleaf
->addr
= xmemdupz(addr
, alen
);
217 newleaf
->addr
= NULL
;
218 newleaf
->alen
= alen
;
220 newbranch
= new_node();
221 newbranch
->value
.thres_bit
= bitloc
;
222 (*parentlink
) = newbranch
;
223 if (testbit(str
, slen
, bitloc
) ==0) {
224 newbranch
->l
= newleaf
;
228 newbranch
->r
= newleaf
;
232 if (testbit(str
, slen
, node
->value
.thres_bit
) != 0)
233 ptree_add_entry_at(str
, slen
, bitloc
, data
,
234 addr
, alen
, &(node
->r
));
236 ptree_add_entry_at(str
, slen
, bitloc
, data
,
237 addr
, alen
, &(node
->l
));
241 int ptree_add_entry(void *str
, size_t sstr
, int data
, struct sockaddr_storage
*addr
,
242 size_t alen
, struct patricia_node
**root
)
244 int *ptr
, bitloc
, malicious
= 0;
245 struct patricia_node
*n
;
248 (*root
) = ptree_make_root_node(str
, sstr
, data
, addr
, alen
);
250 ptr
= ptree_search_data_nearest_ptr(str
, sstr
, (*root
));
251 n
= container_of(ptr
, struct patricia_node
, value
.data
);
252 if (n
->klen
== sstr
&& !memcmp(str
, n
->key
, n
->klen
)) {
253 /* Make sure if entry exists, that we also have the
254 * same data, otherwise, we drop the packet */
255 if (n
->value
.data
!= data
)
257 else if (n
->alen
!= alen
)
259 else if ((n
->addr
&& !addr
) || (!n
->addr
&& addr
))
261 else if (n
->alen
== alen
&& n
->addr
&& addr
) {
262 if (memcmp(n
->addr
, addr
, alen
))
267 bitloc
= where_the_bit_differ(str
, sstr
, n
->key
, n
->klen
);
268 ptree_add_entry_at(str
, sstr
, bitloc
, data
, addr
, alen
, root
);
274 static void ptree_remove_entry_r(struct patricia_node
*now
,
275 struct patricia_node
*up
,
276 struct patricia_node
*up2
,
277 char *str
, size_t slen
, int maxbitplace
,
278 struct patricia_node
**root
)
280 struct patricia_node
*b
;
282 if (now
->l
== NULL
&& now
->r
== NULL
) {
283 if (now
->klen
!= slen
)
285 if (memcmp(now
->key
, str
, slen
))
292 b
= (up
->r
== now
) ? up
->l
: up
->r
;
307 if (testbit_max(str
, now
->value
.thres_bit
, maxbitplace
) != 0)
308 ptree_remove_entry_r(now
->r
, now
, up
, str
, slen
,
311 ptree_remove_entry_r(now
->l
, now
, up
, str
, slen
,
316 void ptree_del_entry(void *str
, size_t sstr
, struct patricia_node
**root
)
320 ptree_remove_entry_r(*root
, NULL
, NULL
, str
, sstr
, sstr
* 8, root
);
323 void ptree_free(struct patricia_node
*node
)