ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/conf/access.c
Revision: 730
Committed: Thu Jul 20 19:43:58 2006 UTC (20 years ago) by adx
Content type: text/x-csrc
File size: 9677 byte(s)
Log Message:
+ implemented K-lines, yet without callback for kline.conf load/store

File Contents

# Content
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 #include "client.h"
28 #include "send.h"
29
30 struct AccessConf *atable[ATABLE_SIZE] = {0};
31 struct Callback *cb_expire_confs = NULL;
32 uint64_t curprec = ~0;
33
34 static dlink_node *hreset;
35 static struct
36 {
37 const char *name;
38 ACB_FREE_HANDLER *free;
39 } acb_types[MAX_ACB_TYPES] = {{0}};
40
41 /*
42 * hash_ipv4()
43 *
44 * Hash algorithm for IPv4.
45 *
46 * inputs: the IP address
47 * output: hash value
48 */
49 static unsigned int
50 hash_ipv4(const struct irc_ssaddr *addr, int bits)
51 {
52 if (bits != 0)
53 {
54 const struct sockaddr_in *v4 = (const struct sockaddr_in *) addr;
55 unsigned int av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
56
57 return (av ^ (av >> 12) ^ (av >> 24)) % ATABLE_SIZE;
58 }
59
60 return 0;
61 }
62
63 /*
64 * hash_ipv6()
65 *
66 * Hash algorithm for IPv6.
67 *
68 * inputs: the IP address
69 * output: hash value
70 */
71 #ifdef IPV6
72 static unsigned int
73 hash_ipv6(const struct irc_ssaddr *addr, int bits)
74 {
75 const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *) addr;
76 unsigned int av = 0, n;
77
78 for (n = 0; n < 16; n++)
79 if (bits >= 8)
80 {
81 av ^= v6->sin6_addr.s6_addr[n];
82 bits -= 8;
83 }
84 else
85 {
86 if (bits > 0)
87 av ^= v6->sin6_addr.s6_addr[n] & ~((1 << (8 - bits)) - 1);
88 break;
89 }
90
91 return av % ATABLE_SIZE;
92 }
93 #endif
94
95 /*
96 * hash_text()
97 *
98 * Hash algorithm for DNS names.
99 *
100 * inputs: the start of text to hash
101 * output: hash value
102 */
103 static unsigned int
104 hash_text(const char *p)
105 {
106 unsigned int av = 0;
107
108 for (; *p; p++)
109 av = (av << 4) - (av + ToLower(*p));
110
111 return av % ATABLE_SIZE;
112 }
113
114 /*
115 * hash_hostmask()
116 *
117 * Calculates the hash value for a given hostmask.
118 *
119 * inputs:
120 * p - the hostname to hash
121 * addr - where to store mask info
122 * output: hash value
123 */
124 static unsigned int
125 hash_hostmask(const char *p, struct irc_ssaddr *addr)
126 {
127 int bits;
128 unsigned int hv;
129 const char *seg;
130
131 switch (parse_netmask(p, addr, &bits))
132 {
133 case HM_IPV4:
134 hv = hash_ipv4(addr, bits - bits % 8);
135 break;
136 #ifdef IPV6
137 case HM_IPV6:
138 hv = hash_ipv6(addr, bits - bits % 16);
139 break;
140 #endif
141 default:
142 //
143 // Choose the longest domain substring which contains no wildcards.
144 // This way hash value will be as precise as possible.
145 //
146 for (seg = p; *p; p++)
147 if (*p == '.' && !seg)
148 seg = p + 1;
149 else if (IsMWildChar(*p))
150 seg = NULL;
151
152 hv = seg ? hash_text(seg) : 0;
153 }
154
155 addr->ss_port = (in_port_t) bits;
156
157 return hv;
158 }
159
160 /*
161 * add_access_conf()
162 *
163 * Adds an AccessConf entry to the hash table.
164 *
165 * inputs: pointer to AccessConf struct
166 * output: none
167 */
168 void
169 add_access_conf(struct AccessConf *conf)
170 {
171 unsigned int hv = hash_hostmask(conf->host, &conf->ip);
172
173 conf->precedence = curprec--;
174 conf->hnext = atable[hv];
175 atable[hv] = conf;
176 }
177
178 /*
179 * destroy_access_conf()
180 *
181 * Deletes an AccessConf entry from the hash table and frees its memory.
182 *
183 * inputs: pointer to AccessConf struct
184 * output: none
185 */
186 void
187 destroy_access_conf(struct AccessConf *conf)
188 {
189 struct irc_ssaddr addr;
190 unsigned int hv = hash_hostmask(conf->host, &addr);
191 struct AccessConf *prev;
192
193 if (conf == atable[hv])
194 atable[hv] = conf->hnext;
195 else
196 {
197 for (prev = atable[hv]; prev->hnext != conf; prev = prev->hnext)
198 assert(prev->type >= 0); // let it core if not found
199 prev->hnext = conf->hnext;
200 }
201
202 acb_types[conf->type].free(conf);
203 }
204
205 /*
206 * acb_generic_free()
207 *
208 * Generic free procedure for ACB's.
209 *
210 * inputs: pointer to AccessConf struct
211 * output: none
212 */
213 void
214 acb_generic_free(struct AccessConf *conf)
215 {
216 MyFree(conf->user);
217 MyFree(conf->host);
218 MyFree(conf);
219 }
220
221 /*
222 * enum_access_confs()
223 *
224 * Enumerates all AccessConfs. Calls the supplied routine on each one,
225 * if 1 is returned then this one is deleted and freed.
226 * Any number of AccessConfs can be deleted by this function.
227 *
228 * inputs: pointer to checking routine
229 * output: none
230 */
231 void
232 enum_access_confs(ACB_EXAMINE_HANDLER *examine, void *param)
233 {
234 unsigned int hv;
235 struct AccessConf *prev, *conf;
236
237 for (hv = 0; hv < ATABLE_SIZE; hv++)
238 for (prev = NULL, conf = atable[hv]; conf != NULL;
239 conf = (prev ? prev->hnext : atable[hv]))
240 {
241 assert(conf->type >= 0);
242 if (examine(conf, param))
243 {
244 if (prev != NULL)
245 prev->hnext = conf->hnext;
246 else
247 atable[hv] = conf->hnext;
248
249 acb_types[conf->type].free(conf);
250 }
251 else
252 prev = conf;
253 }
254 }
255
256 static int is_acb_permanent(struct AccessConf *conf, void *unused)
257 {
258 return !conf->expires;
259 }
260
261 static int is_acb_expired(struct AccessConf *conf, void *unused)
262 {
263 if (conf->expires && conf->expires <= CurrentTime)
264 {
265 sendto_realops_flags(UMODE_ALL, L_ALL,
266 "Temporary %s for [%s@%s] expired",
267 acb_types[conf->type].name, conf->user, conf->host);
268 return YES;
269 }
270
271 return NO;
272 }
273
274 static int is_acb_orphaned(struct AccessConf *conf, void *unused)
275 {
276 return !acb_types[conf->type].name;
277 }
278
279 /*
280 * register_acb_type()
281 *
282 * Allocates a unique value for AccessConf.type field to be used by modules.
283 *
284 * inputs: pointer to routine which frees a conf entry of this type
285 * output: requested value
286 */
287 int
288 register_acb_type(const char *name, void *fh)
289 {
290 int i;
291
292 assert(name != NULL);
293 assert(fh != NULL);
294
295 for (i = 0; i < MAX_ACB_TYPES; i++)
296 if (acb_types[i].name == NULL)
297 {
298 acb_types[i].name = name;
299 acb_types[i].free = (ACB_FREE_HANDLER *) fh;
300 return i;
301 }
302
303 return -1;
304 }
305
306 /*
307 * unregister_acb_type()
308 *
309 * Deallocates an AccessConf.type specifier.
310 *
311 * inputs: type value
312 * output: none
313 */
314 void
315 unregister_acb_type(int id)
316 {
317 acb_types[id].name = NULL;
318 acb_types[id].free = NULL;
319 enum_access_confs(is_acb_orphaned, NULL);
320 }
321
322 /*
323 * reset_access()
324 *
325 * Deletes all non-expiring ACB's before a rehash.
326 *
327 * inputs: none
328 * output: none
329 */
330 static void *
331 reset_access(va_list args)
332 {
333 enum_access_confs(is_acb_permanent, NULL);
334 return pass_callback(hreset);
335 }
336
337 /*
338 * find_access_conf()
339 *
340 * Looks for an access conf matching given criteria.
341 *
342 * inputs:
343 * type - only check confs of this type
344 * user - if non-NULL, limit to confs matching given username
345 * host - limit to confs matching given hostname...
346 * ip - ...or IP address (either host or ip must be non-NULL)
347 * func - function which verifies additional criteria, can be NULL
348 * output: pointer to struct AccessConf or NULL if not found
349 */
350 struct AccessConf *
351 find_access_conf(int type, const char *user, const char *host,
352 const struct irc_ssaddr *ip, ACB_EXAMINE_HANDLER *func,
353 void *param)
354 {
355 struct AccessConf *conf, *best = NULL;
356 int bits;
357
358 if (ip != NULL)
359 if (ip->ss.sin_family == AF_INET)
360 for (bits = 32; bits >= 0; bits -= 8)
361 for (conf = atable[hash_ipv4(ip, bits)]; conf; conf = conf->hnext)
362 if ((best == NULL || conf->precedence > best->precedence) &&
363 conf->type == type && match_ipv4(ip, &conf->ip, conf->ip.ss_port)
364 && (EmptyString(user) || match(conf->user, user)) &&
365 (!func || func(conf, param)))
366 best = conf;
367 #ifdef IPV6
368 else if (ip->ss.sin_family == AF_INET6)
369 for (bits = 128; bits >= 0; bits -= 16)
370 for (conf = atable[hash_ipv6(ip, bits)]; conf; conf = conf->hnext)
371 if ((best == NULL || conf->precedence > best->precedence) &&
372 conf->type == type && match_ipv6(ip, &conf->ip, conf->ip.ss_port)
373 && (EmptyString(user) || match(conf->user, user)) &&
374 (!func || func(conf, param)))
375 best = conf;
376 #endif
377
378 if (host != NULL)
379 while (1)
380 {
381 for (conf = atable[hash_text(host)]; conf; conf = conf->hnext)
382 if ((best == NULL || conf->precedence > best->precedence) &&
383 conf->type == type && match(conf->host, host) &&
384 (EmptyString(user) || match(conf->user, user)) &&
385 (!func || func(conf, param)))
386 best = conf;
387
388 if (*host)
389 do {
390 if (*host++ == '.')
391 break;
392 }
393 while (*host);
394 else
395 break;
396 }
397
398 return best;
399 }
400
401 /*
402 * expire_confs()
403 *
404 * Called periodically to remove expired conf entries.
405 *
406 * inputs: none
407 * output: none
408 */
409 static void
410 expire_confs(void *unused)
411 {
412 enum_access_confs(is_acb_expired, NULL);
413 execute_callback(cb_expire_confs);
414 }
415
416 /*
417 * init_access()
418 *
419 * Initializes ACB's support.
420 *
421 * inputs: none
422 * output: none
423 */
424 void
425 init_access(void)
426 {
427 hreset = install_hook(reset_conf, reset_access);
428
429 cb_expire_confs = register_callback(NULL, NULL);
430 eventAddIsh("expire_confs", expire_confs, NULL, EXPIRE_FREQUENCY);
431 }

Properties

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