ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/conf/access.c
Revision: 734
Committed: Fri Jul 21 21:19:03 2006 UTC (20 years ago) by adx
Content type: text/x-csrc
File size: 9422 byte(s)
Log Message:
+ implemented resvs

File Contents

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

Properties

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