ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/ipcache.c
Revision: 7668
Committed: Wed Jul 20 17:09:49 2016 UTC (9 years, 1 month ago) by michael
Content type: text/x-csrc
File size: 6413 byte(s)
Log Message:
- Fixed svn properties

File Contents

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

Properties

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