ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/ipcache.c
Revision: 4327
Committed: Fri Aug 1 18:16:05 2014 UTC (11 years ago) by michael
Content type: text/x-csrc
File size: 6420 byte(s)
Log Message:
- svn propset on ipcache.c, ipcache.h

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 1997-2014 ircd-hybrid development team
5 *
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 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 * USA
20 */
21
22 /*! \file ipcache.c
23 * \brief Routines to count connections from particular IP addresses.
24 * \version $Id$
25 */
26
27 #include "stdinc.h"
28 #include "list.h"
29 #include "ipcache.h"
30 #include "event.h"
31 #include "mempool.h"
32 #include "conf.h"
33 #include "ircd.h"
34
35
36 static dlink_list ip_hash_table[IP_HASH_SIZE];
37 static mp_pool_t *ip_entry_pool;
38
39
40
41 /* ipcache_hash_address()
42 *
43 * input - pointer to an irc_inaddr
44 * output - integer value used as index into hash table
45 * side effects - hopefully, none
46 */
47 static uint32_t
48 ipcache_hash_address(const struct irc_ssaddr *addr)
49 {
50 if (addr->ss.ss_family == AF_INET)
51 {
52 const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
53 uint32_t hash = 0, ip = ntohl(v4->sin_addr.s_addr);
54
55 hash = ((ip >> 12) + ip) & (IP_HASH_SIZE - 1);
56 return hash;
57 }
58 #ifdef IPV6
59 else
60 {
61 const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
62 uint32_t hash = 0, *ip = (uint32_t *)&v6->sin6_addr.s6_addr;
63
64 hash = ip[0] ^ ip[3];
65 hash ^= hash >> 16;
66 hash ^= hash >> 8;
67 hash = hash & (IP_HASH_SIZE - 1);
68 return hash;
69 }
70 #else
71 return 0;
72 #endif
73 }
74
75 /* ipcache_find_or_add_address()
76 *
77 * inputs - pointer to struct irc_ssaddr
78 * output - pointer to a struct ip_entry
79 * side effects -
80 *
81 * If the ip # was not found, a new struct ip_entry is created, and the ip
82 * count set to 0.
83 */
84 struct ip_entry *
85 ipcache_find_or_add_address(struct irc_ssaddr *addr)
86 {
87 dlink_node *ptr = NULL;
88 struct ip_entry *iptr = NULL;
89 uint32_t hash_index = ipcache_hash_address(addr);
90 int res = 0;
91 struct sockaddr_in *v4 = (struct sockaddr_in *)addr, *ptr_v4;
92 #ifdef IPV6
93 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr, *ptr_v6;
94 #endif
95
96 DLINK_FOREACH(ptr, ip_hash_table[hash_index].head)
97 {
98 iptr = ptr->data;
99 #ifdef IPV6
100 if (iptr->ip.ss.ss_family != addr->ss.ss_family)
101 continue;
102
103 if (addr->ss.ss_family == AF_INET6)
104 {
105 ptr_v6 = (struct sockaddr_in6 *)&iptr->ip;
106 res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
107 }
108 else
109 #endif
110 {
111 ptr_v4 = (struct sockaddr_in *)&iptr->ip;
112 res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
113 }
114
115 if (res == 0)
116 return iptr; /* Found entry already in hash, return it. */
117 }
118
119 iptr = mp_pool_get(ip_entry_pool);
120 memcpy(&iptr->ip, addr, sizeof(struct irc_ssaddr));
121
122 dlinkAdd(iptr, &iptr->node, &ip_hash_table[hash_index]);
123
124 return iptr;
125 }
126
127 /* ipcache_remove_addres()
128 *
129 * inputs - unsigned long IP address value
130 * output - NONE
131 * side effects - The ip address given, is looked up in ip hash table
132 * and number of ip#'s for that ip decremented.
133 * If ip # count reaches 0 and has expired,
134 * the struct ip_entry is returned to the ip_entry_heap
135 */
136 void
137 ipcache_remove_address(struct irc_ssaddr *addr)
138 {
139 dlink_node *ptr = NULL;
140 uint32_t hash_index = ipcache_hash_address(addr);
141 int res = 0;
142 struct sockaddr_in *v4 = (struct sockaddr_in *)addr, *ptr_v4;
143 #ifdef IPV6
144 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr, *ptr_v6;
145 #endif
146
147 DLINK_FOREACH(ptr, ip_hash_table[hash_index].head)
148 {
149 struct ip_entry *iptr = ptr->data;
150 #ifdef IPV6
151 if (iptr->ip.ss.ss_family != addr->ss.ss_family)
152 continue;
153 if (addr->ss.ss_family == AF_INET6)
154 {
155 ptr_v6 = (struct sockaddr_in6 *)&iptr->ip;
156 res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
157 }
158 else
159 #endif
160 {
161 ptr_v4 = (struct sockaddr_in *)&iptr->ip;
162 res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
163 }
164
165 if (res)
166 continue;
167 assert(iptr->count > 0);
168
169 if (--iptr->count == 0 &&
170 (CurrentTime - iptr->last_attempt) >= ConfigFileEntry.throttle_time)
171 {
172 dlinkDelete(&iptr->node, &ip_hash_table[hash_index]);
173 mp_pool_release(iptr);
174 return;
175 }
176 }
177 }
178
179 /* ipcache_remove_expired_entries()
180 *
181 * input - NONE
182 * output - NONE
183 * side effects - free up all ip entries with no connections
184 */
185 static void
186 ipcache_remove_expired_entries(void *unused)
187 {
188 dlink_node *ptr = NULL, *ptr_next = NULL;
189
190 for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)
191 {
192 DLINK_FOREACH_SAFE(ptr, ptr_next, ip_hash_table[i].head)
193 {
194 struct ip_entry *iptr = ptr->data;
195
196 if (iptr->count == 0 &&
197 (CurrentTime - iptr->last_attempt) >= ConfigFileEntry.throttle_time)
198 {
199 dlinkDelete(&iptr->node, &ip_hash_table[i]);
200 mp_pool_release(iptr);
201 }
202 }
203 }
204 }
205
206 /* ipcache_get_stats()
207 *
208 * inputs - pointer to counter of number of ips hashed
209 * - pointer to memory used for ip hash
210 * output - returned via pointers input
211 * side effects - NONE
212 *
213 * number of hashed ip #'s is counted up, plus the amount of memory
214 * used in the hash.
215 */
216 void
217 ipcache_get_stats(unsigned int *number_ips_stored, uint64_t *mem_ips_stored)
218 {
219 *number_ips_stored = 0;
220 *mem_ips_stored = 0;
221
222 for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)
223 *number_ips_stored += dlink_list_length(&ip_hash_table[i]);
224 *mem_ips_stored = *number_ips_stored * sizeof(struct ip_entry);
225 }
226
227 void
228 ipcache_init(void)
229 {
230 static struct event event_expire_ipcache =
231 {
232 .name = "ipcache_remove_expired_entries",
233 .handler = ipcache_remove_expired_entries,
234 .when = 123
235 };
236
237 event_add(&event_expire_ipcache, NULL);
238 ip_entry_pool = mp_pool_new(sizeof(struct ip_entry), MP_CHUNK_SIZE_IP_ENTRY);
239 }

Properties

Name Value
svn:keywords Id Revision