ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/src/ipcache.c
Revision: 8495
Committed: Thu Apr 5 12:40:05 2018 UTC (8 years, 6 months ago) by michael
Content type: text/x-csrc
File size: 6436 byte(s)
Log Message:
- Killed userhost.c. Rewrote everything to use ipcache.c

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 1997-2018 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 "memory.h"
32 #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 const struct sockaddr_in *const v4 = (const struct sockaddr_in *)addr;
51 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 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
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 ipcache_find_or_add_address(const struct irc_ssaddr *addr)
80 {
81 dlink_node *node;
82 const uint32_t hash_index = ipcache_hash_address(addr);
83 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
86 DLINK_FOREACH(node, ip_hash_table[hash_index].head)
87 {
88 struct ip_entry *iptr = node->data;
89
90 if (iptr->ip.ss.ss_family != addr->ss.ss_family)
91 continue;
92
93 if (addr->ss.ss_family == AF_INET6)
94 {
95 ptr_v6 = (const struct sockaddr_in6 *)&iptr->ip;
96 if (!memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr)))
97 return iptr; /* Found entry already in hash, return it. */
98 }
99 else
100 {
101 ptr_v4 = (const struct sockaddr_in *)&iptr->ip;
102 if (!memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr)))
103 return iptr; /* Found entry already in hash, return it. */
104 }
105 }
106
107 struct ip_entry *iptr = xcalloc(sizeof(*iptr));
108 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 ipcache_remove_address(const struct irc_ssaddr *addr, int local)
126 {
127 dlink_node *node;
128 const uint32_t hash_index = ipcache_hash_address(addr);
129 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
132 DLINK_FOREACH(node, ip_hash_table[hash_index].head)
133 {
134 struct ip_entry *iptr = node->data;
135
136 if (iptr->ip.ss.ss_family != addr->ss.ss_family)
137 continue;
138
139 if (addr->ss.ss_family == AF_INET6)
140 {
141 ptr_v6 = (const struct sockaddr_in6 *)&iptr->ip;
142 if (memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr)))
143 continue;
144 }
145 else
146 {
147 ptr_v4 = (const struct sockaddr_in *)&iptr->ip;
148 if (memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr)))
149 continue;
150 }
151
152 assert(iptr->count_local > 0 || iptr->count_remote > 0);
153
154 if (local)
155 --iptr->count_local;
156 else
157 --iptr->count_remote;
158
159 if (iptr->count_local == 0 && iptr->count_remote == 0 &&
160 (CurrentTime - iptr->last_attempt) >= ConfigGeneral.throttle_time)
161 {
162 dlinkDelete(&iptr->node, &ip_hash_table[hash_index]);
163 xfree(iptr);
164 return;
165 }
166 }
167 }
168
169 /* ipcache_remove_expired_entries()
170 *
171 * input - NONE
172 * output - NONE
173 * side effects - free up all ip entries with no connections
174 */
175 static void
176 ipcache_remove_expired_entries(void *unused)
177 {
178 dlink_node *node, *node_next;
179
180 for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)
181 {
182 DLINK_FOREACH_SAFE(node, node_next, ip_hash_table[i].head)
183 {
184 struct ip_entry *iptr = node->data;
185
186 if (iptr->count_local == 0 && iptr->count_remote == 0 &&
187 (CurrentTime - iptr->last_attempt) >= ConfigGeneral.throttle_time)
188 {
189 dlinkDelete(&iptr->node, &ip_hash_table[i]);
190 xfree(iptr);
191 }
192 }
193 }
194 }
195
196 /* ipcache_get_stats()
197 *
198 * inputs - pointer to counter of number of ips hashed
199 * - pointer to memory used for ip hash
200 * output - returned via pointers input
201 * side effects - NONE
202 *
203 * number of hashed ip #'s is counted up, plus the amount of memory
204 * used in the hash.
205 */
206 void
207 ipcache_get_stats(unsigned int *const number_ips_stored, size_t *const mem_ips_stored)
208 {
209 for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)
210 *number_ips_stored += dlink_list_length(&ip_hash_table[i]);
211 *mem_ips_stored = *number_ips_stored * sizeof(struct ip_entry);
212 }
213
214 void
215 ipcache_init(void)
216 {
217 static struct event event_expire_ipcache =
218 {
219 .name = "ipcache_remove_expired_entries",
220 .handler = ipcache_remove_expired_entries,
221 .when = 123
222 };
223
224 event_add(&event_expire_ipcache, NULL);
225 }

Properties

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