ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/ipcache.c
Revision: 4367
Committed: Sun Aug 3 10:33:39 2014 UTC (11 years ago) by michael
Content type: text/x-csrc
File size: 6398 byte(s)
Log Message:
- ipcache.c: minor cleanup

File Contents

# User Rev Content
1 michael 4325 /*
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 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     #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     struct sockaddr_in *v4 = (struct sockaddr_in *)addr, *ptr_v4;
91     #ifdef IPV6
92     struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr, *ptr_v6;
93     #endif
94    
95     DLINK_FOREACH(ptr, ip_hash_table[hash_index].head)
96     {
97     iptr = ptr->data;
98     #ifdef IPV6
99     if (iptr->ip.ss.ss_family != addr->ss.ss_family)
100     continue;
101    
102     if (addr->ss.ss_family == AF_INET6)
103     {
104     ptr_v6 = (struct sockaddr_in6 *)&iptr->ip;
105 michael 4367 if (!memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr)))
106     return iptr; /* Found entry already in hash, return it. */
107 michael 4325 }
108     else
109     #endif
110     {
111     ptr_v4 = (struct sockaddr_in *)&iptr->ip;
112 michael 4367 if (!memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr)))
113     return iptr; /* Found entry already in hash, return it. */
114 michael 4325 }
115     }
116    
117     iptr = mp_pool_get(ip_entry_pool);
118     memcpy(&iptr->ip, addr, sizeof(struct irc_ssaddr));
119    
120     dlinkAdd(iptr, &iptr->node, &ip_hash_table[hash_index]);
121    
122     return iptr;
123     }
124    
125     /* ipcache_remove_addres()
126     *
127     * inputs - unsigned long IP address value
128     * output - NONE
129     * side effects - The ip address given, is looked up in ip hash table
130     * and number of ip#'s for that ip decremented.
131     * If ip # count reaches 0 and has expired,
132     * the struct ip_entry is returned to the ip_entry_heap
133     */
134     void
135     ipcache_remove_address(struct irc_ssaddr *addr)
136     {
137     dlink_node *ptr = NULL;
138     uint32_t hash_index = ipcache_hash_address(addr);
139     struct sockaddr_in *v4 = (struct sockaddr_in *)addr, *ptr_v4;
140     #ifdef IPV6
141     struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr, *ptr_v6;
142     #endif
143    
144     DLINK_FOREACH(ptr, ip_hash_table[hash_index].head)
145     {
146     struct ip_entry *iptr = ptr->data;
147     #ifdef IPV6
148     if (iptr->ip.ss.ss_family != addr->ss.ss_family)
149     continue;
150 michael 4367
151 michael 4325 if (addr->ss.ss_family == AF_INET6)
152     {
153     ptr_v6 = (struct sockaddr_in6 *)&iptr->ip;
154 michael 4367 if (memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr)))
155     continue;
156 michael 4325 }
157     else
158     #endif
159     {
160     ptr_v4 = (struct sockaddr_in *)&iptr->ip;
161 michael 4367 if (memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr)))
162     continue;
163 michael 4325 }
164    
165     assert(iptr->count > 0);
166    
167     if (--iptr->count == 0 &&
168 michael 4340 (CurrentTime - iptr->last_attempt) >= ConfigGeneral.throttle_time)
169 michael 4325 {
170     dlinkDelete(&iptr->node, &ip_hash_table[hash_index]);
171     mp_pool_release(iptr);
172     return;
173     }
174     }
175     }
176    
177     /* ipcache_remove_expired_entries()
178     *
179     * input - NONE
180     * output - NONE
181     * side effects - free up all ip entries with no connections
182     */
183     static void
184     ipcache_remove_expired_entries(void *unused)
185     {
186     dlink_node *ptr = NULL, *ptr_next = NULL;
187    
188     for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)
189     {
190     DLINK_FOREACH_SAFE(ptr, ptr_next, ip_hash_table[i].head)
191     {
192     struct ip_entry *iptr = ptr->data;
193    
194     if (iptr->count == 0 &&
195 michael 4340 (CurrentTime - iptr->last_attempt) >= ConfigGeneral.throttle_time)
196 michael 4325 {
197     dlinkDelete(&iptr->node, &ip_hash_table[i]);
198     mp_pool_release(iptr);
199     }
200     }
201     }
202     }
203    
204     /* ipcache_get_stats()
205     *
206     * inputs - pointer to counter of number of ips hashed
207     * - pointer to memory used for ip hash
208     * output - returned via pointers input
209     * side effects - NONE
210     *
211     * number of hashed ip #'s is counted up, plus the amount of memory
212     * used in the hash.
213     */
214     void
215 michael 4329 ipcache_get_stats(unsigned int *const number_ips_stored, uint64_t *const mem_ips_stored)
216 michael 4325 {
217     for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)
218     *number_ips_stored += dlink_list_length(&ip_hash_table[i]);
219     *mem_ips_stored = *number_ips_stored * sizeof(struct ip_entry);
220     }
221    
222     void
223     ipcache_init(void)
224     {
225     static struct event event_expire_ipcache =
226     {
227     .name = "ipcache_remove_expired_entries",
228     .handler = ipcache_remove_expired_entries,
229     .when = 123
230     };
231    
232     event_add(&event_expire_ipcache, NULL);
233     ip_entry_pool = mp_pool_new(sizeof(struct ip_entry), MP_CHUNK_SIZE_IP_ENTRY);
234     }

Properties

Name Value
svn:keywords Id Revision