ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf_class.c
Revision: 1644
Committed: Tue Nov 6 22:20:16 2012 UTC (13 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 10148 byte(s)
Log Message:
- More config subsystem cleanups

File Contents

# User Rev Content
1 michael 1633 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     *
4     * Copyright (C) 2002 by the past and present ircd coders, and others.
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
23     * \brief Configuration managment for class{} blocks
24 michael 1635 * \version $Id$
25 michael 1633 */
26    
27     #include "stdinc.h"
28     #include "list.h"
29     #include "ircd_defs.h"
30     #include "balloc.h"
31     #include "conf.h"
32     #include "s_serv.h"
33     #include "resv.h"
34     #include "channel.h"
35     #include "client.h"
36     #include "event.h"
37     #include "hook.h"
38     #include "irc_string.h"
39     #include "s_bsd.h"
40     #include "ircd.h"
41     #include "listener.h"
42     #include "hostmask.h"
43     #include "modules.h"
44     #include "numeric.h"
45     #include "fdlist.h"
46     #include "log.h"
47     #include "send.h"
48     #include "s_gline.h"
49     #include "memory.h"
50     #include "irc_res.h"
51     #include "userhost.h"
52     #include "s_user.h"
53     #include "channel_mode.h"
54     #include "parse.h"
55     #include "s_misc.h"
56     #include "conf_db.h"
57    
58    
59     struct ClassItem *class_default;
60    
61     static dlink_list class_list = { NULL, NULL, 0 };
62    
63    
64     const dlink_list *
65     class_get_list(void)
66     {
67     return &class_list;
68     }
69    
70     struct ClassItem *
71     class_make(void)
72     {
73     struct ClassItem *class = MyMalloc(sizeof(*class));
74    
75     dlinkAdd(class, &class->node, &class_list);
76    
77     return class;
78     }
79    
80     void
81     class_free(struct ClassItem *class)
82     {
83     assert(class);
84     assert(class->active == 0);
85     assert(class->ref_count == 0);
86    
87     dlinkDelete(&class->node, &class_list);
88     MyFree(class->name);
89     MyFree(class);
90     }
91    
92     void
93     class_init(void)
94     {
95     class_default = class_make();
96    
97     DupString(class_default->name, "default");
98 michael 1636
99     class_default->active = 1;
100 michael 1633 class_default->con_freq = DEFAULT_CONNECTFREQUENCY;
101     class_default->ping_freq = DEFAULT_PINGFREQUENCY;
102     class_default->max_total = MAXIMUM_LINKS_DEFAULT;
103     class_default->max_sendq = DEFAULT_SENDQ;
104     class_default->max_recvq = DEFAULT_RECVQ;
105     }
106    
107     const char *
108     get_client_class(const dlink_list *const list)
109     {
110     const dlink_node *ptr = NULL;
111    
112     if ((ptr = list->head)) {
113     const struct MaskItem *conf = ptr->data;
114    
115     assert(conf->class);
116     assert(conf->type & (CONF_OPERATOR | CONF_CLIENT | CONF_SERVER));
117    
118     return conf->class->name;
119     }
120    
121     return class_default->name;
122     }
123    
124     unsigned int
125 michael 1644 get_client_ping(const dlink_list *const list)
126 michael 1633 {
127     const dlink_node *ptr = NULL;
128    
129     if ((ptr = list->head)) {
130     const struct MaskItem *conf = ptr->data;
131    
132     assert(aconf->class);
133     assert(aconf->type & (CONF_OPERATOR | CONF_CLIENT | CONF_SERVER));
134    
135 michael 1644 return conf->class->ping_freq;
136 michael 1633 }
137    
138     return class_default->ping_freq;
139     }
140    
141     unsigned int
142     get_sendq(const dlink_list *const list)
143     {
144     const dlink_node *ptr = NULL;
145    
146     if ((ptr = list->head)) {
147     const struct MaskItem *conf = ptr->data;
148    
149     assert(conf->class);
150     assert(conf->type & (CONF_OPERATOR | CONF_CLIENT | CONF_SERVER));
151    
152     return conf->class->max_sendq;
153     }
154    
155     return class_default->max_sendq;
156     }
157    
158     unsigned int
159     get_recvq(const dlink_list *const list)
160     {
161     const dlink_node *ptr = NULL;
162    
163     if ((ptr = list->head)) {
164     const struct MaskItem *conf = ptr->data;
165    
166     assert(conf->class);
167     assert(conf->type & (CONF_OPERATOR | CONF_CLIENT | CONF_SERVER));
168    
169     return conf->class->max_recvq;
170     }
171    
172     return class_default->max_recvq;
173     }
174    
175     /*
176     * inputs - Integer (Number of class)
177     * output - Pointer to ClassItem struct. Non-NULL expected
178     * side effects - NONE
179     */
180     struct ClassItem *
181     class_find(const char *name, int active)
182     {
183     dlink_node *ptr = NULL;
184    
185     DLINK_FOREACH(ptr, class_list.head) {
186     struct ClassItem *class = ptr->data;
187    
188     if (!irccmp(class->name, name))
189     return active && !class->active ? NULL : class;
190     }
191    
192     return NULL;
193     }
194    
195     /*
196     * We don't delete the class table, rather mark all entries for deletion.
197     * The table is cleaned up by delete_marked_classes. - avalon
198     */
199     void
200     class_mark_for_deletion(void)
201     {
202     dlink_node *ptr = NULL;
203    
204     DLINK_FOREACH(ptr, class_list.head)
205     {
206     struct ClassItem *class = ptr->data;
207    
208     if (class != class_default)
209     class->active = 0;
210     }
211     }
212    
213     void
214     class_delete_marked(void)
215     {
216     dlink_node *ptr = NULL, *ptr_next = NULL;
217    
218     DLINK_FOREACH_SAFE(ptr, ptr_next, class_list.head) {
219     struct ClassItem *class = ptr->data;
220    
221     if (!class->active && !class->ref_count)
222     {
223     destroy_cidr_class(class);
224     class_free(class);
225     }
226     }
227     }
228    
229     /*
230     * cidr_limit_reached
231     *
232     * inputs - int flag allowing over_rule of limits
233     * - pointer to the ip to be added
234     * - pointer to the class
235     * output - non zero if limit reached
236     * 0 if limit not reached
237     * side effects -
238     */
239     int
240     cidr_limit_reached(int over_rule,
241     struct irc_ssaddr *ip, struct ClassItem *class)
242     {
243     dlink_node *ptr = NULL;
244     struct CidrItem *cidr = NULL;
245    
246 michael 1644 if (class->number_per_cidr == 0)
247 michael 1633 return 0;
248    
249     if (ip->ss.ss_family == AF_INET)
250     {
251 michael 1644 if (class->cidr_bitlen_ipv4 == 0)
252 michael 1633 return 0;
253    
254     DLINK_FOREACH(ptr, class->list_ipv4.head)
255     {
256     cidr = ptr->data;
257     if (match_ipv4(ip, &cidr->mask, class->cidr_bitlen_ipv4))
258     {
259     if (!over_rule && (cidr->number_on_this_cidr >= class->number_per_cidr))
260     return -1;
261     cidr->number_on_this_cidr++;
262     return 0;
263     }
264     }
265     cidr = MyMalloc(sizeof(struct CidrItem));
266     cidr->number_on_this_cidr = 1;
267     cidr->mask = *ip;
268     mask_addr(&cidr->mask, class->cidr_bitlen_ipv4);
269     dlinkAdd(cidr, &cidr->node, &class->list_ipv4);
270     }
271     #ifdef IPV6
272     else if (class->cidr_bitlen_ipv6 > 0)
273     {
274     DLINK_FOREACH(ptr, class->list_ipv6.head)
275     {
276     cidr = ptr->data;
277     if (match_ipv6(ip, &cidr->mask, class->cidr_bitlen_ipv6))
278     {
279     if (!over_rule && (cidr->number_on_this_cidr >= class->number_per_cidr))
280     return -1;
281     cidr->number_on_this_cidr++;
282     return 0;
283     }
284     }
285     cidr = MyMalloc(sizeof(struct CidrItem));
286     cidr->number_on_this_cidr = 1;
287     cidr->mask = *ip;
288     mask_addr(&cidr->mask, class->cidr_bitlen_ipv6);
289     dlinkAdd(cidr, &cidr->node, &class->list_ipv6);
290     }
291     #endif
292     return 0;
293     }
294    
295     /*
296     * remove_from_cidr_check
297     *
298     * inputs - pointer to the ip to be removed
299     * - pointer to the class
300     * output - NONE
301     * side effects -
302     */
303     void
304     remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
305     {
306     dlink_node *ptr = NULL;
307     dlink_node *next_ptr = NULL;
308     struct CidrItem *cidr;
309    
310     if (aclass->number_per_cidr == 0)
311     return;
312    
313     if (ip->ss.ss_family == AF_INET)
314     {
315 michael 1644 if (aclass->cidr_bitlen_ipv4 == 0)
316 michael 1633 return;
317    
318     DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
319     {
320     cidr = ptr->data;
321     if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
322     {
323     cidr->number_on_this_cidr--;
324     if (cidr->number_on_this_cidr == 0)
325     {
326     dlinkDelete(ptr, &aclass->list_ipv4);
327     MyFree(cidr);
328     return;
329     }
330     }
331     }
332     }
333     #ifdef IPV6
334     else if (aclass->cidr_bitlen_ipv6 > 0)
335     {
336     DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
337     {
338     cidr = ptr->data;
339     if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
340     {
341     cidr->number_on_this_cidr--;
342     if (cidr->number_on_this_cidr == 0)
343     {
344     dlinkDelete(ptr, &aclass->list_ipv6);
345     MyFree(cidr);
346     return;
347     }
348     }
349     }
350     }
351     #endif
352     }
353    
354     static void
355     rebuild_cidr_list(int aftype, struct ClassItem *oldcl, struct ClassItem *newcl,
356     dlink_list *old_list, dlink_list *new_list, int changed)
357     {
358     dlink_node *ptr;
359     struct Client *client_p;
360     struct MaskItem *conf;
361    
362     if (!changed)
363     {
364     *new_list = *old_list;
365     old_list->head = old_list->tail = NULL;
366     old_list->length = 0;
367     return;
368     }
369    
370     DLINK_FOREACH(ptr, local_client_list.head)
371     {
372     client_p = ptr->data;
373     if (client_p->localClient->aftype != aftype)
374     continue;
375     if (dlink_list_length(&client_p->localClient->confs) == 0)
376     continue;
377    
378     conf = client_p->localClient->confs.tail->data;
379     if (conf->type == CONF_CLIENT)
380     if (conf->class == oldcl)
381     cidr_limit_reached(1, &client_p->localClient->ip, newcl);
382     }
383     }
384    
385     /*
386     * rebuild_cidr_class
387     *
388     * inputs - pointer to old conf
389     * - pointer to new_class
390     * output - none
391     * side effects - rebuilds the class link list of cidr blocks
392     */
393     void
394     rebuild_cidr_class(struct ClassItem *old_class, struct ClassItem *new_class)
395     {
396     if (old_class->number_per_cidr > 0 && new_class->number_per_cidr > 0)
397     {
398     if (old_class->cidr_bitlen_ipv4 > 0 && new_class->cidr_bitlen_ipv4 > 0)
399     rebuild_cidr_list(AF_INET, old_class, new_class,
400     &old_class->list_ipv4, &new_class->list_ipv4,
401     old_class->cidr_bitlen_ipv4 != new_class->cidr_bitlen_ipv4);
402    
403     #ifdef IPV6
404     if (old_class->cidr_bitlen_ipv6 > 0 && new_class->cidr_bitlen_ipv6 > 0)
405     rebuild_cidr_list(AF_INET6, old_class, new_class,
406     &old_class->list_ipv6, &new_class->list_ipv6,
407     old_class->cidr_bitlen_ipv6 != new_class->cidr_bitlen_ipv6);
408     #endif
409     }
410    
411     destroy_cidr_class(old_class);
412     }
413    
414     /*
415     * destroy_cidr_list
416     *
417     * inputs - pointer to class dlink list of cidr blocks
418     * output - none
419     * side effects - completely destroys the class link list of cidr blocks
420     */
421     static void
422     destroy_cidr_list(dlink_list *list)
423     {
424     dlink_node *ptr = NULL, *next_ptr = NULL;
425    
426     DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
427     {
428     dlinkDelete(ptr, list);
429     MyFree(ptr->data);
430     }
431     }
432    
433     /*
434     * destroy_cidr_class
435     *
436     * inputs - pointer to class
437     * output - none
438     * side effects - completely destroys the class link list of cidr blocks
439     */
440     void
441     destroy_cidr_class(struct ClassItem *class)
442     {
443     destroy_cidr_list(&class->list_ipv4);
444     destroy_cidr_list(&class->list_ipv6);
445     }

Properties

Name Value
svn:executable *
svn:keywords Id