aboutsummaryrefslogtreecommitdiffstats
path: root/src/negcache.c
blob: 4a36b2a03670925a20825d89eae0f2b031945c51 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*
 *  Copyright (c) 2002-2003 Andy Smith
 *  Copyright (c) 2014-2020 ircd-hybrid development team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
 *  USA
 */

/*
 * A Negative caching implementation for IPv4/IPv6 addresses.  The idea is that
 * every time an IP address is seen, it is checked against a patricia trie.  If
 * the IP address was previously seen and within an acceptable period of time,
 * it is not scanned again.  Otherwise, the address is scanned as normal.  If
 * it is proven to be OK (i.e.  it doesn't run an open proxy) then it is added
 * to the trie.
 */

#include "setup.h"

#include <time.h>

#include "list.h"
#include "patricia.h"
#include "negcache.h"
#include "config.h"
#include "memory.h"
#include "log.h"


extern unsigned int OPT_DEBUG;

static list_t negcache_list;
static patricia_tree_t *negcache_trie;


/*
 * Initialise the patricia trie we use for storing our negative cache.
 */
void
negcache_init(void)
{
  if (negcache_trie)
    return;  /* Cache already exists */

  negcache_trie = patricia_new(PATRICIA_MAXBITS);
}

/*
 * Check whether an IP address is in our negative cache and was added
 * recently enough.  Return a pointer to its node if so, NULL otherwise.
 */
struct negcache_item *
negcache_check(const char *ipstr)
{
  if (OptionsItem.negcache == 0)
    return NULL;

  patricia_node_t *pnode = patricia_try_search_exact(negcache_trie, ipstr);
  if (pnode)
  {
    struct negcache_item *n = pnode->data;

    if (time(NULL) - n->seen <= OptionsItem.negcache)
      return n;
  }

  return NULL;
}

/*
 * Prepare an ASCII string representing an IPv4/IPv6 address for inserting into
 * our negative cache.
 */
void
negcache_insert(const char *ipstr)
{
  patricia_node_t *pnode = patricia_make_and_lookup(negcache_trie, ipstr);
  if (pnode == NULL || pnode->data)
    return;  /* Malformed IP address or already added to the trie */

  struct negcache_item *n = xcalloc(sizeof(*n));
  n->seen = time(NULL);

  pnode->data = n;
  list_add(pnode, &n->node, &negcache_list);
}

/*
 * Wrapper for recursive rebuild function.
 */
void
negcache_rebuild(void)
{
  node_t *node, *node_next;

  LIST_FOREACH_SAFE(node, node_next, negcache_list.head)
  {
    patricia_node_t *pnode = node->data;
    struct negcache_item *n = pnode->data;

    if (n->seen + OptionsItem.negcache < time(NULL))
    {
      if (OPT_DEBUG >= 2)
        log_printf("NEGCACHE -> Deleting expired negcache node for %s added at %lu",
                   patricia_prefix_toa(pnode->prefix, 0), n->seen);

      list_remove(&n->node, &negcache_list);

      xfree(n);
      patricia_remove(negcache_trie, pnode);
    }
  }
}