/src/ndpi/src/lib/ndpi_cache.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * ndpi_main.c |
3 | | * |
4 | | * Copyright (C) 2011-25 - ntop.org |
5 | | * |
6 | | * nDPI is free software: you can redistribute it and/or modify |
7 | | * it under the terms of the GNU Lesser General Public License as published by |
8 | | * the Free Software Foundation, either version 3 of the License, or |
9 | | * (at your option) any later version. |
10 | | * |
11 | | * nDPI is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public License |
17 | | * along with nDPI. If not, see <http://www.gnu.org/licenses/>. |
18 | | * |
19 | | */ |
20 | | |
21 | | #include <stdlib.h> |
22 | | #include <errno.h> |
23 | | #include <sys/types.h> |
24 | | |
25 | | #ifdef __APPLE__ |
26 | | #include <netinet/ip.h> |
27 | | #endif |
28 | | |
29 | | #include "ndpi_config.h" |
30 | | #include "ndpi_api.h" |
31 | | #include "ndpi_private.h" |
32 | | |
33 | | #include "libcache.h" |
34 | | |
35 | | /* ******************************************************************** */ |
36 | | /* ******************************************************************** */ |
37 | | |
38 | | /* LRU cache */ |
39 | 105k | struct ndpi_lru_cache *ndpi_lru_cache_init(u_int32_t num_entries, u_int32_t ttl, int shared) { |
40 | 105k | struct ndpi_lru_cache *c = (struct ndpi_lru_cache *) ndpi_calloc(1, sizeof(struct ndpi_lru_cache)); |
41 | | |
42 | 105k | if(!c) |
43 | 2.00k | return(NULL); |
44 | | |
45 | 103k | c->ttl = ttl & 0x7FFFFFFF; |
46 | 103k | c->shared = !!shared; |
47 | | |
48 | 103k | #ifdef USE_GLOBAL_CONTEXT |
49 | 103k | if(c->shared) { |
50 | 334 | if(pthread_mutex_init(&c->mutex, NULL) != 0) { |
51 | 0 | ndpi_free(c); |
52 | 0 | return(NULL); |
53 | 0 | } |
54 | 334 | } |
55 | 103k | #endif |
56 | | |
57 | 103k | c->entries = (struct ndpi_lru_cache_entry *) ndpi_calloc(num_entries, sizeof(struct ndpi_lru_cache_entry)); |
58 | | |
59 | 103k | if(!c->entries) { |
60 | 2.78k | ndpi_free(c); |
61 | 2.78k | return(NULL); |
62 | 2.78k | } else |
63 | 100k | c->num_entries = num_entries; |
64 | | |
65 | 100k | return(c); |
66 | 103k | } |
67 | | |
68 | | /* ******************************************************************** */ |
69 | | |
70 | 100k | void ndpi_lru_free_cache(struct ndpi_lru_cache *c) { |
71 | 100k | ndpi_free(c->entries); |
72 | 100k | ndpi_free(c); |
73 | 100k | } |
74 | | |
75 | | /* ******************************************************************** */ |
76 | | |
77 | | static void __lru_cache_lock(struct ndpi_lru_cache *c) |
78 | 10.4M | { |
79 | 10.4M | #ifdef USE_GLOBAL_CONTEXT |
80 | 10.4M | if(c->shared) { |
81 | 145 | pthread_mutex_lock(&c->mutex); |
82 | 145 | } |
83 | | #else |
84 | | (void)c; |
85 | | #endif |
86 | 10.4M | } |
87 | | |
88 | | /* ******************************************************************** */ |
89 | | |
90 | | static void __lru_cache_unlock(struct ndpi_lru_cache *c) |
91 | 10.4M | { |
92 | 10.4M | #ifdef USE_GLOBAL_CONTEXT |
93 | 10.4M | if(c->shared) { |
94 | 145 | pthread_mutex_unlock(&c->mutex); |
95 | 145 | } |
96 | | #else |
97 | | (void)c; |
98 | | #endif |
99 | 10.4M | } |
100 | | |
101 | | /* ******************************************************************** */ |
102 | | |
103 | | u_int8_t ndpi_lru_find_cache(struct ndpi_lru_cache *c, u_int64_t key, |
104 | 10.0M | u_int16_t *value, u_int8_t clean_key_when_found, u_int32_t now_sec) { |
105 | 10.0M | u_int32_t slot = ndpi_quick_hash((unsigned char *)&key, sizeof(key)) % c->num_entries; |
106 | 10.0M | u_int8_t ret; |
107 | | |
108 | 10.0M | __lru_cache_lock(c); |
109 | | |
110 | 10.0M | c->stats.n_search++; |
111 | 10.0M | if(c->entries[slot].is_full && c->entries[slot].key == key && |
112 | 10.0M | now_sec >= c->entries[slot].timestamp && |
113 | 10.0M | (c->ttl == 0 || now_sec - c->entries[slot].timestamp <= c->ttl)) { |
114 | 1.90M | *value = c->entries[slot].value; |
115 | | |
116 | 1.90M | if(clean_key_when_found) |
117 | 0 | c->entries[slot].is_full = 0; |
118 | | |
119 | 1.90M | c->stats.n_found++; |
120 | 1.90M | ret = 1; |
121 | 1.90M | } else |
122 | 8.16M | ret = 0; |
123 | | |
124 | 10.0M | __lru_cache_unlock(c); |
125 | | |
126 | 10.0M | return ret; |
127 | 10.0M | } |
128 | | |
129 | | /* ******************************************************************** */ |
130 | | |
131 | 392k | void ndpi_lru_add_to_cache(struct ndpi_lru_cache *c, u_int64_t key, u_int16_t value, u_int32_t now_sec) { |
132 | 392k | u_int32_t slot = ndpi_quick_hash((unsigned char *)&key, sizeof(key)) % c->num_entries; |
133 | | |
134 | 392k | __lru_cache_lock(c); |
135 | | |
136 | 392k | c->stats.n_insert++; |
137 | 392k | c->entries[slot].is_full = 1, c->entries[slot].key = key, |
138 | 392k | c->entries[slot].value = value, c->entries[slot].timestamp = now_sec; |
139 | | |
140 | 392k | __lru_cache_unlock(c); |
141 | 392k | } |
142 | | |
143 | | /* ******************************************************************** */ |
144 | | |
145 | 59.6k | void ndpi_lru_get_stats(struct ndpi_lru_cache *c, struct ndpi_lru_cache_stats *stats) { |
146 | 59.6k | if(c) { |
147 | 56.7k | stats->n_insert = c->stats.n_insert; |
148 | 56.7k | stats->n_search = c->stats.n_search; |
149 | 56.7k | stats->n_found = c->stats.n_found; |
150 | 56.7k | } else { |
151 | 2.83k | stats->n_insert = 0; |
152 | 2.83k | stats->n_search = 0; |
153 | 2.83k | stats->n_found = 0; |
154 | 2.83k | } |
155 | 59.6k | } |
156 | | |
157 | | /* ******************************************************************** */ |
158 | | |
159 | | int ndpi_get_lru_cache_stats(struct ndpi_global_context *g_ctx, |
160 | | struct ndpi_detection_module_struct *ndpi_struct, |
161 | | lru_cache_type cache_type, |
162 | | struct ndpi_lru_cache_stats *stats) |
163 | 69.7k | { |
164 | 69.7k | int scope, is_local = 1; |
165 | 69.7k | char param[64], buf[8], *rc; |
166 | | |
167 | 69.7k | if(!stats || (!ndpi_struct && !g_ctx)) |
168 | 2.71k | return -1; |
169 | 67.0k | if(!ndpi_struct) { |
170 | 1.99k | is_local = 0; |
171 | 65.0k | } else { |
172 | 65.0k | snprintf(param, sizeof(param), "lru.%s.scope", ndpi_lru_cache_idx_to_name(cache_type)); |
173 | 65.0k | rc = ndpi_get_config(ndpi_struct, NULL, param, buf, sizeof(buf)); |
174 | | |
175 | 65.0k | if(rc == NULL) |
176 | 7.23k | return -1; |
177 | | |
178 | 57.8k | scope = atoi(buf); |
179 | | |
180 | 57.8k | if(scope == NDPI_LRUCACHE_SCOPE_GLOBAL) { |
181 | 343 | is_local = 0; |
182 | 343 | if(!g_ctx) |
183 | 0 | return -1; |
184 | 343 | } |
185 | 57.8k | } |
186 | | |
187 | 59.8k | switch(cache_type) { |
188 | 7.45k | case NDPI_LRUCACHE_OOKLA: |
189 | 7.45k | ndpi_lru_get_stats(is_local ? ndpi_struct->ookla_cache : g_ctx->ookla_global_cache, stats); |
190 | 7.45k | return 0; |
191 | 7.45k | case NDPI_LRUCACHE_BITTORRENT: |
192 | 7.45k | ndpi_lru_get_stats(is_local ? ndpi_struct->bittorrent_cache : g_ctx->bittorrent_global_cache, stats); |
193 | 7.45k | return 0; |
194 | 7.45k | case NDPI_LRUCACHE_STUN: |
195 | 7.45k | ndpi_lru_get_stats(is_local ? ndpi_struct->stun_cache : g_ctx->stun_global_cache, stats); |
196 | 7.45k | return 0; |
197 | 7.45k | case NDPI_LRUCACHE_TLS_CERT: |
198 | 7.45k | ndpi_lru_get_stats(is_local ? ndpi_struct->tls_cert_cache : g_ctx->tls_cert_global_cache, stats); |
199 | 7.45k | return 0; |
200 | 7.45k | case NDPI_LRUCACHE_MINING: |
201 | 7.45k | ndpi_lru_get_stats(is_local ? ndpi_struct->mining_cache : g_ctx->mining_global_cache, stats); |
202 | 7.45k | return 0; |
203 | 7.45k | case NDPI_LRUCACHE_MSTEAMS: |
204 | 7.45k | ndpi_lru_get_stats(is_local ? ndpi_struct->msteams_cache : g_ctx->msteams_global_cache, stats); |
205 | 7.45k | return 0; |
206 | 7.45k | case NDPI_LRUCACHE_FPC_DNS: |
207 | 7.45k | ndpi_lru_get_stats(is_local ? ndpi_struct->fpc_dns_cache : g_ctx->fpc_dns_global_cache, stats); |
208 | 7.45k | return 0; |
209 | 7.45k | case NDPI_LRUCACHE_SIGNAL: |
210 | 7.45k | ndpi_lru_get_stats(is_local ? ndpi_struct->signal_cache : g_ctx->signal_global_cache, stats); |
211 | 7.45k | return 0; |
212 | 222 | default: |
213 | 222 | return -1; |
214 | 59.8k | } |
215 | 59.8k | } |
216 | | |
217 | | /* ******************************************************************** */ |
218 | | /* ******************************************************************** */ |
219 | | |
220 | 516 | struct ndpi_address_cache* ndpi_init_address_cache(u_int32_t max_num_entries) { |
221 | 516 | struct ndpi_address_cache *ret = (struct ndpi_address_cache*)ndpi_malloc(sizeof(struct ndpi_address_cache)); |
222 | | |
223 | 516 | if(ret == NULL) return(ret); |
224 | | |
225 | 480 | ret->num_cached_addresses = 0, ret->num_entries = 0, |
226 | 480 | ret->max_num_entries = max_num_entries, |
227 | 480 | ret->num_root_nodes = ndpi_max(1, ndpi_min(NDPI_NUM_DEFAULT_ROOT_NODES, max_num_entries/16)); |
228 | 480 | ret->address_cache_root = (struct ndpi_address_cache_item**)ndpi_calloc(ret->num_root_nodes, sizeof(struct ndpi_address_cache_item*)); |
229 | | |
230 | 480 | if(ret->address_cache_root == NULL) { |
231 | 34 | ndpi_free(ret); |
232 | 34 | return(NULL); |
233 | 34 | } else |
234 | 446 | return(ret); |
235 | 480 | } |
236 | | |
237 | | /* ***************************************************** */ |
238 | | |
239 | 16.3k | static void ndpi_free_addr_item(struct ndpi_address_cache_item *addr) { |
240 | 16.3k | ndpi_free(addr->hostname); |
241 | 16.3k | ndpi_free(addr); |
242 | 16.3k | } |
243 | | |
244 | | /* ***************************************************** */ |
245 | | |
246 | 535 | void ndpi_term_address_cache(struct ndpi_address_cache *cache) { |
247 | 535 | u_int i; |
248 | | |
249 | 535 | if(!cache) |
250 | 96 | return; |
251 | | |
252 | 10.7k | for(i=0; i<cache->num_root_nodes; i++) { |
253 | 10.3k | struct ndpi_address_cache_item *root = cache->address_cache_root[i]; |
254 | | |
255 | 12.3k | while(root != NULL) { |
256 | 1.98k | struct ndpi_address_cache_item *next = root->next; |
257 | | |
258 | 1.98k | ndpi_free_addr_item(root); |
259 | 1.98k | root = next; |
260 | 1.98k | } |
261 | 10.3k | } |
262 | | |
263 | 439 | ndpi_free(cache->address_cache_root); |
264 | 439 | ndpi_free(cache); |
265 | 439 | } |
266 | | |
267 | | /* ***************************************************** */ |
268 | | |
269 | | /* Return the number of purged entries */ |
270 | | u_int32_t ndpi_address_cache_flush_expired(struct ndpi_address_cache *cache, |
271 | 4.00k | u_int32_t epoch_now) { |
272 | 4.00k | u_int32_t i, num_purged = 0; |
273 | | |
274 | 9.09k | for(i=0; i<cache->num_root_nodes; i++) { |
275 | 5.09k | struct ndpi_address_cache_item *root = cache->address_cache_root[i]; |
276 | 5.09k | struct ndpi_address_cache_item *prev = NULL; |
277 | | |
278 | 9.06k | while(root != NULL) { |
279 | 3.96k | struct ndpi_address_cache_item *next = root->next; |
280 | | |
281 | 3.96k | if(root->expire_epoch > epoch_now) { |
282 | | /* Time to purge */ |
283 | | |
284 | 761 | if(prev == NULL) { |
285 | | /* Head element */ |
286 | 521 | cache->address_cache_root[i] = next; |
287 | 521 | } else { |
288 | | /* Middle element */ |
289 | 240 | prev->next = next; |
290 | 240 | } |
291 | | |
292 | 761 | ndpi_free_addr_item(root), num_purged++; |
293 | 3.20k | } else { |
294 | 3.20k | prev = root; |
295 | 3.20k | } |
296 | | |
297 | 3.96k | root = next; |
298 | 3.96k | } /* while */ |
299 | 5.09k | } /* for */ |
300 | | |
301 | 4.00k | cache->num_entries -= num_purged; |
302 | | |
303 | 4.00k | return(num_purged); |
304 | 4.00k | } |
305 | | |
306 | | |
307 | | /* ***************************************************** */ |
308 | | |
309 | | struct ndpi_address_cache_item* ndpi_address_cache_find(struct ndpi_address_cache *cache, |
310 | 4.05M | ndpi_ip_addr_t ip_addr, u_int32_t epoch_now) { |
311 | 4.05M | u_int32_t hash_id = ndpi_quick_hash((const unsigned char *)&ip_addr, sizeof(ip_addr)) % cache->num_root_nodes; |
312 | 4.05M | struct ndpi_address_cache_item *root = cache->address_cache_root[hash_id], *prev = NULL; |
313 | | |
314 | 7.41M | while(root != NULL) { |
315 | 4.00M | if((epoch_now != 0) && (root->expire_epoch < epoch_now)) { |
316 | | /* Expired entry: let's remove it */ |
317 | 13.5k | struct ndpi_address_cache_item *next = root->next; |
318 | | |
319 | 13.5k | if(prev == NULL) |
320 | 11.0k | cache->address_cache_root[hash_id] = next; |
321 | 2.53k | else |
322 | 2.53k | prev->next = next; |
323 | | |
324 | 13.5k | ndpi_free_addr_item(root); |
325 | 13.5k | root = next, cache->num_entries--; |
326 | | |
327 | 13.5k | continue; /* Skip this entry */ |
328 | 13.5k | } |
329 | | |
330 | 3.98M | if(memcmp(&root->addr, &ip_addr, sizeof(ndpi_ip_addr_t)) == 0) { |
331 | 650k | return(root); |
332 | 3.33M | } else { |
333 | 3.33M | prev = root; |
334 | 3.33M | root = root->next; |
335 | 3.33M | } |
336 | 3.98M | } |
337 | | |
338 | 3.40M | return(NULL); |
339 | 4.05M | } |
340 | | |
341 | | /* ***************************************************** */ |
342 | | |
343 | | bool ndpi_address_cache_insert(struct ndpi_address_cache *cache, |
344 | | ndpi_ip_addr_t ip_addr, char *hostname, |
345 | | u_int32_t epoch_now, |
346 | 86.8k | u_int32_t ttl) { |
347 | 86.8k | u_int32_t hash_id = ndpi_quick_hash((const unsigned char *)&ip_addr, sizeof(ip_addr)) % cache->num_root_nodes; |
348 | 86.8k | struct ndpi_address_cache_item *ret; |
349 | 86.8k | u_int32_t epoch_valid_until; |
350 | | |
351 | 86.8k | if(!hostname) |
352 | 628 | return(false); |
353 | | |
354 | 86.2k | if(epoch_now == 0) epoch_now = (u_int32_t)time(NULL); |
355 | 86.2k | ret = ndpi_address_cache_find(cache, ip_addr, epoch_now); |
356 | 86.2k | epoch_valid_until = epoch_now + ttl; |
357 | | |
358 | | /* printf("**** %s [%u][ttl: %u]\n", hostname, epoch_now, ttl); */ |
359 | | |
360 | 86.2k | if(ret == NULL) { |
361 | 26.2k | if(cache->num_entries == cache->max_num_entries) { |
362 | 3.90k | ndpi_address_cache_flush_expired(cache, epoch_now); |
363 | | |
364 | 3.90k | if(cache->num_entries == cache->max_num_entries) |
365 | 3.54k | return(false); /* Still no room left */ |
366 | | |
367 | | /* We have room to add the new element */ |
368 | | /* Let's continue */ |
369 | 3.90k | } |
370 | | |
371 | | /* We have room to insert the new element */ |
372 | 22.7k | ret = (struct ndpi_address_cache_item*)ndpi_malloc(sizeof(struct ndpi_address_cache_item)); |
373 | 22.7k | if(ret == NULL) |
374 | 1.03k | return(false); /* No memory */ |
375 | | |
376 | 21.6k | memcpy(&ret->addr, &ip_addr, sizeof(ip_addr)), |
377 | 21.6k | ret->expire_epoch = epoch_valid_until, |
378 | 21.6k | ret->next = cache->address_cache_root[hash_id]; |
379 | | |
380 | 21.6k | if((ret->hostname = ndpi_strdup(hostname)) == NULL) { |
381 | 1.24k | ndpi_free(ret); |
382 | 1.24k | return(false); |
383 | 1.24k | } |
384 | | |
385 | | /* Create linked list */ |
386 | 20.4k | cache->address_cache_root[hash_id] = ret; |
387 | 59.9k | } else { |
388 | | /* Element found: update TTL of the existing element */ |
389 | 59.9k | ret->expire_epoch = ndpi_max(ret->expire_epoch, epoch_valid_until); |
390 | | |
391 | 59.9k | if(strcmp(ret->hostname, hostname)) { |
392 | | /* Hostnames are different: we overwrite it */ |
393 | 21.6k | char *new_hostname = ndpi_strdup(hostname); |
394 | | |
395 | 21.6k | if(new_hostname) { |
396 | | /* Allocation ok */ |
397 | 20.8k | ndpi_free(ret->hostname); |
398 | 20.8k | ret->hostname = new_hostname; |
399 | 20.8k | } |
400 | 21.6k | } |
401 | 59.9k | } |
402 | | |
403 | 80.4k | cache->num_entries++; |
404 | 80.4k | return(true); |
405 | 86.2k | } |
406 | | |
407 | | /* ***************************************************** */ |
408 | | |
409 | | bool ndpi_address_cache_dump(struct ndpi_address_cache *cache, |
410 | 369 | char *path, u_int32_t epoch_now) { |
411 | 369 | FILE *fd = fopen(path, "w"); |
412 | 369 | u_int i; |
413 | | |
414 | 369 | if(!fd) return(false); |
415 | | |
416 | 2.09k | for(i=0; i<cache->num_root_nodes; i++) { |
417 | 1.72k | struct ndpi_address_cache_item *root = cache->address_cache_root[i]; |
418 | | |
419 | 3.70k | while(root != NULL) { |
420 | 1.97k | char buf[33]; |
421 | 1.97k | u_char *a = (u_char*)&(root->addr); |
422 | 1.97k | u_int j, idx; |
423 | | |
424 | 1.97k | if(epoch_now && (root->expire_epoch < epoch_now)) { |
425 | 1.10k | root = root->next; |
426 | 1.10k | continue; /* Expired epoch */ |
427 | 1.10k | } |
428 | | |
429 | 14.9k | for(j=0, idx=0; j<sizeof(ndpi_ip_addr_t); j++, idx += 2) |
430 | 14.0k | snprintf(&buf[idx], sizeof(buf)-idx, "%02X", a[j]); |
431 | | |
432 | 878 | fprintf(fd, "%s\t%s\t%u\n", buf, root->hostname, root->expire_epoch); |
433 | | |
434 | 878 | root = root->next; |
435 | 878 | } |
436 | 1.72k | } |
437 | | |
438 | 369 | fclose(fd); |
439 | 369 | return(true); |
440 | 369 | } |
441 | | |
442 | | /* ***************************************************** */ |
443 | | |
444 | | /* Return the number of items restored */ |
445 | 420 | u_int32_t ndpi_address_cache_restore(struct ndpi_address_cache *cache, char *path, u_int32_t epoch_now) { |
446 | 420 | FILE *fd = fopen(path, "r"); |
447 | 420 | char ip[33], hostname[256]; |
448 | 420 | u_int32_t epoch, num_added = 0; |
449 | | |
450 | 420 | if(!fd) return(false); |
451 | | |
452 | 1.16k | while(fscanf(fd, "%32s\t%255s\t%u\n", ip, hostname, &epoch) == 3) { |
453 | 742 | if(epoch >= epoch_now) { /* Entry not yet expired */ |
454 | 561 | u_int ttl = epoch-epoch_now; |
455 | 561 | ndpi_ip_addr_t addr; |
456 | 561 | char *a = (char*)&addr; |
457 | 561 | u_int i, j; |
458 | | |
459 | 9.53k | for(i=0, j=0; i<(sizeof(ndpi_ip_addr_t)*2); i += 2, j++) { |
460 | 8.97k | char buf[3]; |
461 | | |
462 | 8.97k | buf[0] = ip[i], buf[1] = ip[i+1], buf[2] = '\0'; |
463 | 8.97k | a[j] = strtol(buf, NULL, 16); |
464 | 8.97k | } |
465 | | |
466 | 561 | if(ndpi_address_cache_insert(cache, addr, hostname, epoch_now, ttl)) |
467 | 495 | num_added++; |
468 | 561 | } |
469 | 742 | } |
470 | | |
471 | 420 | fclose(fd); |
472 | | |
473 | 420 | return(num_added); |
474 | 420 | } |
475 | | |
476 | | /* ***************************************************** */ |
477 | | /* ***************************************************** */ |
478 | | |
479 | | bool ndpi_cache_address(struct ndpi_detection_module_struct *ndpi_struct, |
480 | | ndpi_ip_addr_t ip_addr, char *hostname, |
481 | 88.1k | u_int32_t epoch_now, u_int32_t ttl) { |
482 | 88.1k | if(ndpi_struct->cfg.address_cache_size == 0) return(false); |
483 | | |
484 | 86.3k | if(ndpi_struct->address_cache == NULL) |
485 | 450 | ndpi_struct->address_cache = ndpi_init_address_cache(ndpi_struct->cfg.address_cache_size); |
486 | | |
487 | 86.3k | if(ndpi_struct->address_cache) |
488 | 86.3k | return(ndpi_address_cache_insert(ndpi_struct->address_cache, ip_addr, hostname, epoch_now, ttl)); |
489 | 55 | else |
490 | 55 | return(false); |
491 | 86.3k | } |
492 | | |
493 | | /* ***************************************************** */ |
494 | | |
495 | | struct ndpi_address_cache_item* ndpi_cache_address_find(struct ndpi_detection_module_struct *ndpi_struct, |
496 | 4.11M | ndpi_ip_addr_t ip_addr) { |
497 | 4.11M | if(ndpi_struct->address_cache == NULL) return(NULL); |
498 | | |
499 | 3.97M | return(ndpi_address_cache_find(ndpi_struct->address_cache, ip_addr, 0)); |
500 | 4.11M | } |
501 | | |
502 | | /* ***************************************************** */ |
503 | | |
504 | 516 | bool ndpi_cache_address_dump(struct ndpi_detection_module_struct *ndpi_struct, char *path, u_int32_t epoch_now) { |
505 | 516 | if(ndpi_struct->address_cache == NULL) return(false); |
506 | | |
507 | 369 | return(ndpi_address_cache_dump(ndpi_struct->address_cache, path, epoch_now)); |
508 | 516 | } |
509 | | |
510 | | /* ***************************************************** */ |
511 | | |
512 | 516 | u_int32_t ndpi_cache_address_restore(struct ndpi_detection_module_struct *ndpi_struct, char *path, u_int32_t epoch_now) { |
513 | 516 | if(ndpi_struct->address_cache == NULL) { |
514 | 147 | if(ndpi_struct->cfg.address_cache_size == 0) |
515 | 81 | return(0); |
516 | | |
517 | 66 | if((ndpi_struct->address_cache = ndpi_init_address_cache(ndpi_struct->cfg.address_cache_size)) == 0) |
518 | 15 | return(0); |
519 | 66 | } |
520 | | |
521 | 420 | return(ndpi_address_cache_restore(ndpi_struct->address_cache, path, epoch_now)); |
522 | 516 | } |
523 | | |
524 | | /* ***************************************************** */ |
525 | | |
526 | 143 | u_int32_t ndpi_cache_address_flush_expired(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t epoch_now) { |
527 | 143 | if(ndpi_struct->address_cache == NULL) |
528 | 48 | return(0); |
529 | 95 | else |
530 | 95 | return(ndpi_address_cache_flush_expired(ndpi_struct->address_cache, epoch_now)); |
531 | 143 | } |
532 | | |
533 | | /* ***************************************************** */ |
534 | | /* ***************************************************** */ |
535 | | |
536 | | /* |
537 | | Used to cache resolved IP addresses in order to trigger |
538 | | risk NDPI_UNRESOLVED_HOSTNAME |
539 | | */ |
540 | | static u_int32_t ndpi_cache_hash_hostname_ip(struct ndpi_detection_module_struct *ndpi_struct, |
541 | | ndpi_ip_addr_t *ip_addr, char *_hostname, |
542 | 311k | bool use_domain_name) { |
543 | 311k | u_char buf[128]; |
544 | 311k | const char *hostname = use_domain_name ? ndpi_get_host_domain(ndpi_struct, _hostname) : _hostname; |
545 | 311k | u_int32_t len = snprintf((char*)buf, sizeof(buf), "%s", hostname); |
546 | 311k | char *double_column = strchr((char*)buf, ':'); |
547 | | |
548 | 311k | if(double_column != NULL) { |
549 | 0 | double_column[0] = '\0'; |
550 | 0 | len = strlen(double_column); |
551 | 0 | } |
552 | | |
553 | 311k | if(len < sizeof(buf)) { |
554 | 308k | int32_t leftover = sizeof(buf) - len; |
555 | | |
556 | 308k | if(leftover > 0) { |
557 | 308k | u_int32_t to_add = ndpi_min((u_int32_t)leftover, sizeof(ndpi_ip_addr_t)); |
558 | | |
559 | 308k | if((u_int32_t)leftover >= to_add) { |
560 | 308k | memcpy(&buf[len], ip_addr, to_add); |
561 | 308k | len += to_add; |
562 | 308k | } |
563 | | |
564 | | #ifdef DEBUG_ADDR_CACHE |
565 | | printf("[DEBUG] Hashing %s [len=%u]\n", hostname, len); |
566 | | #endif |
567 | 308k | } |
568 | 308k | } else { |
569 | 2.38k | len = sizeof(buf); |
570 | 2.38k | } |
571 | | |
572 | 311k | return(ndpi_quick_hash(buf, len)); |
573 | 311k | } |
574 | | |
575 | | /* #define DEBUG_ADDR_CACHE */ |
576 | | |
577 | | /* ***************************************************** */ |
578 | | |
579 | | /* |
580 | | Used to cache resolved IP addresses in order to trigger |
581 | | risk NDPI_UNRESOLVED_HOSTNAME |
582 | | */ |
583 | | bool ndpi_cache_hostname_ip(struct ndpi_detection_module_struct *ndpi_struct, |
584 | 32.0k | ndpi_ip_addr_t *ip_addr, char *hostname) { |
585 | 32.0k | if(ndpi_struct->dns_hostname.cache == NULL) |
586 | 18 | ndpi_struct->dns_hostname.cache = ndpi_filter_alloc(); |
587 | | |
588 | 32.0k | if(ndpi_struct->dns_hostname.cache) { |
589 | 32.0k | u_int32_t hashval = ndpi_cache_hash_hostname_ip(ndpi_struct, ip_addr, hostname, false); |
590 | | |
591 | 32.0k | NDPI_LOG_DBG2(ndpi_struct, "[DEBUG] ->>> %s [%u]\n", hostname, hashval); |
592 | | |
593 | | #ifdef DEBUG_ADDR_CACHE |
594 | | { |
595 | | char buf[64]; |
596 | | |
597 | | printf("[DEBUG] Adding %s [%u][%s/%u]\n", hostname, ip_addr->ipv4, |
598 | | ndpi_intoav4(ntohl(ip_addr->ipv4), buf, sizeof(buf)), hashval); |
599 | | } |
600 | | #endif |
601 | | |
602 | 32.0k | return(ndpi_filter_add(ndpi_struct->dns_hostname.cache, hashval)); |
603 | 32.0k | } |
604 | | |
605 | 0 | return(false); |
606 | 32.0k | } |
607 | | |
608 | | /* ***************************************************** */ |
609 | | |
610 | | /* |
611 | | Check if the combination hostname/IP was found |
612 | | |
613 | | Return value |
614 | | - true if was found, false otherwise |
615 | | */ |
616 | | bool ndpi_cache_find_hostname_ip(struct ndpi_detection_module_struct *ndpi_struct, |
617 | 279k | ndpi_ip_addr_t *ip_addr, char *hostname) { |
618 | 279k | if(ndpi_struct->dns_hostname.cache) { |
619 | 279k | u_int32_t hashval = ndpi_cache_hash_hostname_ip(ndpi_struct, ip_addr, hostname, false); |
620 | 279k | bool ret; |
621 | | |
622 | 279k | ret = ndpi_filter_contains(ndpi_struct->dns_hostname.cache, hashval); |
623 | | |
624 | 279k | if((!ret) && (ndpi_struct->dns_hostname.cache_shadow != NULL)) |
625 | 0 | ret = ndpi_filter_contains(ndpi_struct->dns_hostname.cache_shadow, hashval); |
626 | | |
627 | | #ifdef DEBUG_ADDR_CACHE |
628 | | { |
629 | | char buf[64]; |
630 | | |
631 | | printf("[DEBUG] ->>> Searching %s [%u/%s][%u]: %s\n", |
632 | | hostname, ip_addr->ipv4, |
633 | | ndpi_intoav4(ntohl(ip_addr->ipv4), buf, sizeof(buf)), |
634 | | hashval, ret ? "found" : "NOT FOUND"); |
635 | | } |
636 | | #endif |
637 | | |
638 | 279k | return(ret); |
639 | 279k | } |
640 | | |
641 | 199 | return(false); |
642 | 279k | } |
643 | | |
644 | | /* ***************************************************** */ |
645 | | |
646 | 0 | void ndpi_cache_hostname_ip_swap(struct ndpi_detection_module_struct *ndpi_struct) { |
647 | 0 | if(ndpi_struct->cfg.hostname_dns_check_enabled) { |
648 | 0 | if(ndpi_struct->dns_hostname.cache_shadow) |
649 | 0 | ndpi_filter_free(ndpi_struct->dns_hostname.cache_shadow); |
650 | |
|
651 | 0 | ndpi_struct->dns_hostname.cache_shadow = ndpi_struct->dns_hostname.cache; |
652 | 0 | ndpi_struct->dns_hostname.cache = ndpi_filter_alloc(); |
653 | 0 | } |
654 | 0 | } |
655 | | |
656 | | /* ***************************************************** */ |
657 | | |
658 | 0 | void ndpi_cache_enable(struct ndpi_detection_module_struct *ndpi_struct) { |
659 | 0 | ndpi_struct->cfg.hostname_dns_check_enabled = 1; |
660 | 0 | } |