/[svn]/ircd-hybrid/src/conf/access.c
ViewVC logotype

Contents of /ircd-hybrid/src/conf/access.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 725 - (show annotations)
Sun Jul 16 21:58:09 2006 UTC (14 years, 2 months ago) by adx
File MIME type: text/x-chdr
File size: 7032 byte(s)
+ turned a variable static

1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * access.c: Common code for user@host access control blocks.
4 *
5 * Copyright (C) 2006 by the Hybrid Development Team.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 *
22 * $Id$
23 */
24
25 #include "stdinc.h"
26 #include "conf/conf.h"
27
28 struct AccessConf *atable[ATABLE_SIZE] = {0};
29 struct Callback *cb_expire_confs = NULL;
30
31 static ACB_FREE_HANDLER *acb_types[MAX_ACB_TYPES] = {0};
32 static dlink_node *hreset;
33
34 /*
35 * hash_ipv4()
36 *
37 * Hash algorithm for IPv4.
38 *
39 * inputs: the IP address
40 * output: hash value
41 */
42 static unsigned int
43 hash_ipv4(const struct irc_ssaddr *addr, int bits)
44 {
45 if (bits != 0)
46 {
47 const struct sockaddr_in *v4 = (const struct sockaddr_in *) addr;
48 unsigned int av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
49
50 return (av ^ (av >> 12) ^ (av >> 24)) % ATABLE_SIZE;
51 }
52
53 return 0;
54 }
55
56 /*
57 * hash_ipv6()
58 *
59 * Hash algorithm for IPv6.
60 *
61 * inputs: the IP address
62 * output: hash value
63 */
64 #ifdef IPV6
65 static unsigned int
66 hash_ipv6(const struct irc_ssaddr *addr, int bits)
67 {
68 const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *) addr;
69 unsigned int av = 0, n;
70
71 for (n = 0; n < 16; n++)
72 if (bits >= 8)
73 {
74 av ^= v6->sin6_addr.s6_addr[n];
75 bits -= 8;
76 }
77 else
78 {
79 if (bits > 0)
80 av ^= v6->sin6_addr.s6_addr[n] & ~((1 << (8 - bits)) - 1);
81 break;
82 }
83
84 return av % ATABLE_SIZE;
85 }
86 #endif
87
88 /*
89 * hash_text()
90 *
91 * Hash algorithm for DNS names.
92 *
93 * inputs: the start of text to hash
94 * output: hash value
95 */
96 static unsigned int
97 hash_text(const char *p)
98 {
99 unsigned int av = 0;
100
101 for (; *p; p++)
102 av = (av << 4) - (av + ToLower(*p));
103
104 return av % ATABLE_SIZE;
105 }
106
107 /*
108 * hash_hostmask()
109 *
110 * Calculates the hash value for a given hostmask.
111 *
112 * inputs:
113 * p - the hostname to hash
114 * addr - where to store mask info
115 * output: hash value
116 */
117 static unsigned int
118 hash_hostmask(const char *p, struct irc_ssaddr *addr)
119 {
120 int bits;
121 unsigned int hv;
122 const char *seg;
123
124 switch (parse_netmask(p, addr, &bits))
125 {
126 case HM_IPV4:
127 hv = hash_ipv4(addr, bits - bits % 8);
128 break;
129 #ifdef IPV6
130 case HM_IPV6:
131 hv = hash_ipv6(addr, bits - bits % 16);
132 break;
133 #endif
134 default:
135 //
136 // Choose the longest domain substring which contains no wildcards.
137 // This way hash value will be as precise as possible.
138 //
139 for (seg = p; *p; p++)
140 if (*p == '.' && !seg)
141 seg = p + 1;
142 else if (IsMWildChar(*p))
143 seg = NULL;
144
145 hv = seg ? hash_text(seg) : 0;
146 }
147
148 addr->ss_port = (in_port_t) bits;
149
150 return hv;
151 }
152
153 /*
154 * add_access_conf()
155 *
156 * Adds an AccessConf entry to the hash table.
157 *
158 * inputs: pointer to AccessConf struct
159 * output: none
160 */
161 void
162 add_access_conf(struct AccessConf *conf)
163 {
164 unsigned int hv = hash_hostmask(conf->host, &conf->ip);
165 static uint64_t curprec = ~0;
166
167 conf->precedence = curprec--;
168 conf->hnext = atable[hv];
169 atable[hv] = conf;
170 }
171
172 /*
173 * destroy_access_conf()
174 *
175 * Deletes an AccessConf entry from the hash table and frees its memory.
176 *
177 * inputs: pointer to AccessConf struct
178 * output: none
179 */
180 void
181 destroy_access_conf(struct AccessConf *conf)
182 {
183 struct irc_ssaddr addr;
184 unsigned int hv = hash_hostmask(conf->host, &addr);
185 struct AccessConf *prev;
186
187 if (conf == atable[hv])
188 atable[hv] = conf->hnext;
189 else
190 {
191 for (prev = atable[hv]; prev->hnext != conf; prev = prev->hnext)
192 ; // let it core if not found
193 prev->hnext = conf->hnext;
194 }
195
196 acb_types[conf->type](conf);
197 }
198
199 /*
200 * acb_generic_free()
201 *
202 * Generic free procedure for ACB's.
203 *
204 * inputs: pointer to AccessConf struct
205 * output: none
206 */
207 void
208 acb_generic_free(struct AccessConf *conf)
209 {
210 MyFree(conf->user);
211 MyFree(conf->host);
212 MyFree(conf->text);
213 MyFree(conf);
214 }
215
216 /*
217 * del_matching_access_confs()
218 *
219 * Enumerates all AccessConfs. Calls the supplied routine on each one,
220 * if 1 is returned then this one is deleted and freed.
221 * Any number of AccessConfs can be deleted by this function.
222 *
223 * inputs: pointer to checking routine
224 * output: none
225 */
226 void
227 del_matching_access_confs(ACB_EXAMINE_HANDLER *examine)
228 {
229 unsigned int hv;
230 struct AccessConf *prev, *conf;
231
232 for (hv = 0; hv < ATABLE_SIZE; hv++)
233 for (prev = NULL, conf = atable[hv]; conf != NULL;
234 conf = (prev ? prev->hnext : atable[hv]))
235 {
236 if (examine(conf))
237 {
238 if (prev != NULL)
239 prev->hnext = conf->hnext;
240 else
241 atable[hv] = conf->hnext;
242
243 acb_types[conf->type](conf);
244 }
245 else
246 prev = conf;
247 }
248 }
249
250 static int is_acb_permanent(struct AccessConf *conf)
251 {
252 return !conf->expires;
253 }
254
255 static int is_acb_expired(struct AccessConf *conf)
256 {
257 return conf->expires && conf->expires <= CurrentTime;
258 }
259
260 static int is_acb_orphaned(struct AccessConf *conf)
261 {
262 return !acb_types[conf->type];
263 }
264
265 /*
266 * register_acb_type()
267 *
268 * Allocates a unique value for AccessConf.type field to be used by modules.
269 *
270 * inputs: pointer to routine which frees a conf entry of this type
271 * output: requested value
272 */
273 int
274 register_acb_type(void *fh)
275 {
276 int i;
277
278 for (i = 0; i < MAX_ACB_TYPES; i++)
279 if (acb_types[i] == NULL)
280 {
281 acb_types[i] = (ACB_FREE_HANDLER *) fh;
282 return i;
283 }
284
285 return -1;
286 }
287
288 /*
289 * unregister_acb_type()
290 *
291 * Deallocates an AccessConf.type specifier.
292 *
293 * inputs: type value
294 * output: none
295 */
296 void
297 unregister_acb_type(int id)
298 {
299 acb_types[id] = NULL;
300 del_matching_access_confs(is_acb_orphaned);
301 }
302
303 /*
304 * reset_access()
305 *
306 * Deletes all non-expiring ACB's before a rehash.
307 *
308 * inputs: none
309 * output: none
310 */
311 static void *
312 reset_access(va_list args)
313 {
314 del_matching_access_confs(is_acb_permanent);
315 return pass_callback(hreset);
316 }
317
318 /*
319 * expire_confs()
320 *
321 * Called periodically to remove expired conf entries.
322 *
323 * inputs: none
324 * output: none
325 */
326 static void
327 expire_confs(void *unused)
328 {
329 del_matching_access_confs(is_acb_expired);
330 execute_callback(cb_expire_confs);
331 }
332
333 /*
334 * init_access()
335 *
336 * Initializes ACB's support.
337 *
338 * inputs: none
339 * output: none
340 */
341 void
342 init_access(void)
343 {
344 hreset = install_hook(reset_conf, reset_access);
345
346 cb_expire_confs = register_callback(NULL, NULL);
347 eventAddIsh("expire_confs", expire_confs, NULL, EXPIRE_FREQUENCY);
348 }

Properties

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

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.28