ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/ipcache.c
Revision: 8385
Committed: Fri Mar 16 20:09:55 2018 UTC (7 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 6249 byte(s)
Log Message:
- Rip out mempool

File Contents

# User Rev Content
1 michael 4325 /*
2     * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3     *
4 michael 8279 * Copyright (c) 1997-2018 ircd-hybrid development team
5 michael 4325 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program 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 General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18 michael 4565 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 michael 4325 * USA
20     */
21    
22     /*! \file ipcache.c
23     * \brief Routines to count connections from particular IP addresses.
24 michael 4327 * \version $Id$
25 michael 4325 */
26    
27     #include "stdinc.h"
28     #include "list.h"
29     #include "ipcache.h"
30     #include "event.h"
31 michael 8385 #include "memory.h"
32 michael 4325 #include "conf.h"
33     #include "ircd.h"
34    
35    
36     static dlink_list ip_hash_table[IP_HASH_SIZE];
37    
38    
39     /* ipcache_hash_address()
40     *
41     * input - pointer to an irc_inaddr
42     * output - integer value used as index into hash table
43     * side effects - hopefully, none
44     */
45     static uint32_t
46     ipcache_hash_address(const struct irc_ssaddr *addr)
47     {
48     if (addr->ss.ss_family == AF_INET)
49     {
50 michael 4977 const struct sockaddr_in *const v4 = (const struct sockaddr_in *)addr;
51 michael 4325 uint32_t hash = 0, ip = ntohl(v4->sin_addr.s_addr);
52    
53     hash = ((ip >> 12) + ip) & (IP_HASH_SIZE - 1);
54     return hash;
55     }
56     else
57     {
58 michael 4977 const struct sockaddr_in6 *const v6 = (const struct sockaddr_in6 *)addr;
59     uint32_t hash = 0, *const ip = (uint32_t *)&v6->sin6_addr.s6_addr;
60 michael 4325
61     hash = ip[0] ^ ip[3];
62     hash ^= hash >> 16;
63     hash ^= hash >> 8;
64     hash = hash & (IP_HASH_SIZE - 1);
65     return hash;
66     }
67     }
68    
69     /* ipcache_find_or_add_address()
70     *
71     * inputs - pointer to struct irc_ssaddr
72     * output - pointer to a struct ip_entry
73     * side effects -
74     *
75     * If the ip # was not found, a new struct ip_entry is created, and the ip
76     * count set to 0.
77     */
78     struct ip_entry *
79 michael 6651 ipcache_find_or_add_address(const struct irc_ssaddr *addr)
80 michael 4325 {
81 michael 8349 dlink_node *node;
82 michael 4977 const uint32_t hash_index = ipcache_hash_address(addr);
83 michael 6651 const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr, *ptr_v4;
84     const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr, *ptr_v6;
85 michael 4325
86 michael 4800 DLINK_FOREACH(node, ip_hash_table[hash_index].head)
87 michael 4325 {
88 michael 8349 struct ip_entry *iptr = node->data;
89 michael 4415
90 michael 4325 if (iptr->ip.ss.ss_family != addr->ss.ss_family)
91     continue;
92    
93     if (addr->ss.ss_family == AF_INET6)
94     {
95 michael 6651 ptr_v6 = (const struct sockaddr_in6 *)&iptr->ip;
96 michael 4367 if (!memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr)))
97     return iptr; /* Found entry already in hash, return it. */
98 michael 4325 }
99     else
100     {
101 michael 6651 ptr_v4 = (const struct sockaddr_in *)&iptr->ip;
102 michael 4367 if (!memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr)))
103     return iptr; /* Found entry already in hash, return it. */
104 michael 4325 }
105     }
106    
107 michael 8385 struct ip_entry *iptr = xcalloc(sizeof(*iptr));
108 michael 4325 memcpy(&iptr->ip, addr, sizeof(struct irc_ssaddr));
109    
110     dlinkAdd(iptr, &iptr->node, &ip_hash_table[hash_index]);
111    
112     return iptr;
113     }
114    
115     /* ipcache_remove_addres()
116     *
117     * inputs - unsigned long IP address value
118     * output - NONE
119     * side effects - The ip address given, is looked up in ip hash table
120     * and number of ip#'s for that ip decremented.
121     * If ip # count reaches 0 and has expired,
122     * the struct ip_entry is returned to the ip_entry_heap
123     */
124     void
125 michael 6651 ipcache_remove_address(const struct irc_ssaddr *addr)
126 michael 4325 {
127 michael 8349 dlink_node *node;
128 michael 4977 const uint32_t hash_index = ipcache_hash_address(addr);
129 michael 6651 const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr, *ptr_v4;
130     const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr, *ptr_v6;
131 michael 4325
132 michael 4800 DLINK_FOREACH(node, ip_hash_table[hash_index].head)
133 michael 4325 {
134 michael 4800 struct ip_entry *iptr = node->data;
135 michael 4415
136 michael 4325 if (iptr->ip.ss.ss_family != addr->ss.ss_family)
137     continue;
138 michael 4367
139 michael 4325 if (addr->ss.ss_family == AF_INET6)
140     {
141 michael 6651 ptr_v6 = (const struct sockaddr_in6 *)&iptr->ip;
142 michael 4367 if (memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr)))
143     continue;
144 michael 4325 }
145     else
146     {
147 michael 6651 ptr_v4 = (const struct sockaddr_in *)&iptr->ip;
148 michael 4367 if (memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr)))
149     continue;
150 michael 4325 }
151    
152     assert(iptr->count > 0);
153    
154     if (--iptr->count == 0 &&
155 michael 4340 (CurrentTime - iptr->last_attempt) >= ConfigGeneral.throttle_time)
156 michael 4325 {
157     dlinkDelete(&iptr->node, &ip_hash_table[hash_index]);
158 michael 8385 xfree(iptr);
159 michael 4325 return;
160     }
161     }
162     }
163    
164     /* ipcache_remove_expired_entries()
165     *
166     * input - NONE
167     * output - NONE
168     * side effects - free up all ip entries with no connections
169     */
170     static void
171     ipcache_remove_expired_entries(void *unused)
172     {
173 michael 8349 dlink_node *node, *node_next;
174 michael 4325
175     for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)
176     {
177 michael 4800 DLINK_FOREACH_SAFE(node, node_next, ip_hash_table[i].head)
178 michael 4325 {
179 michael 4800 struct ip_entry *iptr = node->data;
180 michael 4325
181     if (iptr->count == 0 &&
182 michael 4340 (CurrentTime - iptr->last_attempt) >= ConfigGeneral.throttle_time)
183 michael 4325 {
184     dlinkDelete(&iptr->node, &ip_hash_table[i]);
185 michael 8385 xfree(iptr);
186 michael 4325 }
187     }
188     }
189     }
190    
191     /* ipcache_get_stats()
192     *
193     * inputs - pointer to counter of number of ips hashed
194     * - pointer to memory used for ip hash
195     * output - returned via pointers input
196     * side effects - NONE
197     *
198     * number of hashed ip #'s is counted up, plus the amount of memory
199     * used in the hash.
200     */
201     void
202 michael 6719 ipcache_get_stats(unsigned int *const number_ips_stored, size_t *const mem_ips_stored)
203 michael 4325 {
204     for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)
205     *number_ips_stored += dlink_list_length(&ip_hash_table[i]);
206     *mem_ips_stored = *number_ips_stored * sizeof(struct ip_entry);
207     }
208    
209     void
210     ipcache_init(void)
211     {
212     static struct event event_expire_ipcache =
213     {
214     .name = "ipcache_remove_expired_entries",
215     .handler = ipcache_remove_expired_entries,
216     .when = 123
217     };
218    
219     event_add(&event_expire_ipcache, NULL);
220     }

Properties

Name Value
svn:eol-style native
svn:keywords Id