Coverage Report

Created: 2025-08-29 06:29

/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
}