/[svn]/ircd-hybrid/trunk/src/ipcache.c
ViewVC logotype

Diff of /ircd-hybrid/trunk/src/ipcache.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 8592 by michael, Thu Apr 5 12:46:00 2018 UTC revision 8593 by michael, Sun Oct 21 18:11:04 2018 UTC
# Line 31  Line 31 
31  #include "memory.h"  #include "memory.h"
32  #include "conf.h"  #include "conf.h"
33  #include "ircd.h"  #include "ircd.h"
34    #include "patricia.h"
35    
36    
37  static dlink_list ip_hash_table[IP_HASH_SIZE];  static dlink_list ipcache_list;
38    static patricia_tree_t *ipcache_trie;
39    
40    
 /* ipcache_hash_address()  
  *  
  * input        - pointer to an irc_inaddr  
  * output       - integer value used as index into hash table  
  * side effects - hopefully, none  
  */  
 static uint32_t  
 ipcache_hash_address(const struct irc_ssaddr *addr)  
 {  
   if (addr->ss.ss_family == AF_INET)  
   {  
     const struct sockaddr_in *const v4 = (const struct sockaddr_in *)addr;  
     uint32_t hash = 0, ip = ntohl(v4->sin_addr.s_addr);  
   
     hash = ((ip >> 12) + ip) & (IP_HASH_SIZE - 1);  
     return hash;  
   }  
   else  
   {  
     const struct sockaddr_in6 *const v6 = (const struct sockaddr_in6 *)addr;  
     uint32_t hash = 0, *const ip = (uint32_t *)&v6->sin6_addr.s6_addr;  
   
     hash  = ip[0] ^ ip[3];  
     hash ^= hash >> 16;  
     hash ^= hash >> 8;  
     hash  = hash & (IP_HASH_SIZE - 1);  
     return hash;  
   }  
 }  
   
41  /* ipcache_find_or_add_address()  /* ipcache_find_or_add_address()
42   *   *
43   * inputs       - pointer to struct irc_ssaddr   * inputs       - pointer to struct irc_ssaddr
# Line 76  ipcache_hash_address(const struct irc_ss Line 48  ipcache_hash_address(const struct irc_ss
48   * count set to 0.   * count set to 0.
49   */   */
50  struct ip_entry *  struct ip_entry *
51  ipcache_find_or_add_address(const struct irc_ssaddr *addr)  ipcache_record_find_or_add(void *addr)
52  {  {
53    dlink_node *node;    patricia_node_t *pnode = patricia_make_and_lookup_addr(ipcache_trie, addr, 0);
   const uint32_t hash_index = ipcache_hash_address(addr);  
   const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr, *ptr_v4;  
   const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr, *ptr_v6;  
54    
55    DLINK_FOREACH(node, ip_hash_table[hash_index].head)    if (pnode->data)  /* Deliberate crash if 'pnode' is NULL */
56    {      return pnode->data;  /* Already added to the trie */
     struct ip_entry *iptr = node->data;  
   
     if (iptr->ip.ss.ss_family != addr->ss.ss_family)  
       continue;  
   
     if (addr->ss.ss_family == AF_INET6)  
     {  
       ptr_v6 = (const struct sockaddr_in6 *)&iptr->ip;  
       if (!memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr)))  
         return iptr;  /* Found entry already in hash, return it. */  
     }  
     else  
     {  
       ptr_v4 = (const struct sockaddr_in *)&iptr->ip;  
       if (!memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr)))  
         return iptr;  /* Found entry already in hash, return it. */  
     }  
   }  
57    
58    struct ip_entry *iptr = xcalloc(sizeof(*iptr));    struct ip_entry *iptr = xcalloc(sizeof(*iptr));
59    memcpy(&iptr->ip, addr, sizeof(struct irc_ssaddr));    dlinkAdd(pnode, &iptr->node, &ipcache_list);
60    
61    dlinkAdd(iptr, &iptr->node, &ip_hash_table[hash_index]);    PATRICIA_DATA_SET(pnode, iptr);
62    
63    return iptr;    return iptr;
64  }  }
65    
66    static void
67    ipcache_record_delete(patricia_node_t *pnode)
68    {
69      struct ip_entry *iptr = PATRICIA_DATA_GET(pnode, struct ip_entry);
70    
71      if (iptr->count_local == 0 && iptr->count_remote == 0 &&
72          (CurrentTime - iptr->last_attempt) >= ConfigGeneral.throttle_time)
73      {
74        dlinkDelete(&iptr->node, &ipcache_list);
75        xfree(iptr);
76    
77        patricia_remove(ipcache_trie, pnode);
78      }
79    }
80    
81  /* ipcache_remove_addres()  /* ipcache_remove_addres()
82   *   *
83   * inputs        - unsigned long IP address value   * inputs        - unsigned long IP address value
# Line 122  ipcache_find_or_add_address(const struct Line 88  ipcache_find_or_add_address(const struct
88   *                 the struct ip_entry is returned to the ip_entry_heap   *                 the struct ip_entry is returned to the ip_entry_heap
89   */   */
90  void  void
91  ipcache_remove_address(const struct irc_ssaddr *addr, int local)  ipcache_record_remove(void *addr, int local)
92  {  {
93    dlink_node *node;    patricia_node_t *pnode = patricia_try_search_exact_addr(ipcache_trie, addr, 0);
   const uint32_t hash_index = ipcache_hash_address(addr);  
   const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr, *ptr_v4;  
   const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr, *ptr_v6;  
94    
95    DLINK_FOREACH(node, ip_hash_table[hash_index].head)    if (pnode == NULL)
96    {      return;
     struct ip_entry *iptr = node->data;  
97    
98      if (iptr->ip.ss.ss_family != addr->ss.ss_family)    struct ip_entry *iptr = PATRICIA_DATA_GET(pnode, struct ip_entry);
99        continue;    assert(iptr->count_local > 0 || iptr->count_remote > 0);
100    
101      if (addr->ss.ss_family == AF_INET6)    if (local)
102      {      --iptr->count_local;
103        ptr_v6 = (const struct sockaddr_in6 *)&iptr->ip;    else
104        if (memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr)))      --iptr->count_remote;
105          continue;  
106      }    ipcache_record_delete(pnode);
     else  
     {  
       ptr_v4 = (const struct sockaddr_in *)&iptr->ip;  
       if (memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr)))  
         continue;  
     }  
   
     assert(iptr->count_local > 0 || iptr->count_remote > 0);  
   
     if (local)  
       --iptr->count_local;  
     else  
       --iptr->count_remote;  
   
     if (iptr->count_local == 0 && iptr->count_remote == 0 &&  
         (CurrentTime - iptr->last_attempt) >= ConfigGeneral.throttle_time)  
     {  
       dlinkDelete(&iptr->node, &ip_hash_table[hash_index]);  
       xfree(iptr);  
       return;  
     }  
   }  
107  }  }
108    
109  /* ipcache_remove_expired_entries()  /* ipcache_remove_expired_entries()
# Line 173  ipcache_remove_address(const struct irc_ Line 113  ipcache_remove_address(const struct irc_
113   * side effects - free up all ip entries with no connections   * side effects - free up all ip entries with no connections
114   */   */
115  static void  static void
116  ipcache_remove_expired_entries(void *unused)  ipcache_remove_expired_records(void *unused)
117  {  {
118    dlink_node *node, *node_next;    dlink_node *node, *node_next;
119    
120    for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)    DLINK_FOREACH_SAFE(node, node_next, ipcache_list.head)
121    {      ipcache_record_delete(node->data);
     DLINK_FOREACH_SAFE(node, node_next, ip_hash_table[i].head)  
     {  
       struct ip_entry *iptr = node->data;  
   
       if (iptr->count_local == 0 && iptr->count_remote == 0 &&  
           (CurrentTime - iptr->last_attempt) >= ConfigGeneral.throttle_time)  
       {  
         dlinkDelete(&iptr->node, &ip_hash_table[i]);  
         xfree(iptr);  
       }  
     }  
   }  
122  }  }
123    
124  /* ipcache_get_stats()  /* ipcache_get_stats()
# Line 206  ipcache_remove_expired_entries(void *unu Line 134  ipcache_remove_expired_entries(void *unu
134  void  void
135  ipcache_get_stats(unsigned int *const number_ips_stored, size_t *const mem_ips_stored)  ipcache_get_stats(unsigned int *const number_ips_stored, size_t *const mem_ips_stored)
136  {  {
137    for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)    /* TBD: inaccurate for now as it does only count the amount of memory for struct ip_entry items */
138      *number_ips_stored += dlink_list_length(&ip_hash_table[i]);    (*number_ips_stored) = dlink_list_length(&ipcache_list);
139    *mem_ips_stored = *number_ips_stored * sizeof(struct ip_entry);    (*mem_ips_stored) = dlink_list_length(&ipcache_list) * sizeof(struct ip_entry);
140  }  }
141    
142  void  void
# Line 216  ipcache_init(void) Line 144  ipcache_init(void)
144  {  {
145    static struct event event_expire_ipcache =    static struct event event_expire_ipcache =
146    {    {
147      .name = "ipcache_remove_expired_entries",      .name = "ipcache_remove_expired_records",
148      .handler = ipcache_remove_expired_entries,      .handler = ipcache_remove_expired_records,
149      .when = 123      .when = 123
150    };    };
151    
152      ipcache_trie = patricia_new(PATRICIA_MAXBITS);
153    
154    event_add(&event_expire_ipcache, NULL);    event_add(&event_expire_ipcache, NULL);
155  }  }

Legend:
Removed from v.8592  
changed lines
  Added in v.8593

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.28