ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf_class.c
Revision: 1646
Committed: Wed Nov 7 21:02:43 2012 UTC (12 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 10151 byte(s)
Log Message:
- First pass of conf parser stabilization/cleanup

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 michael 1646 class_default->name = xstrdup("default");
98 michael 1636 class_default->active = 1;
99 michael 1633 class_default->con_freq = DEFAULT_CONNECTFREQUENCY;
100     class_default->ping_freq = DEFAULT_PINGFREQUENCY;
101     class_default->max_total = MAXIMUM_LINKS_DEFAULT;
102     class_default->max_sendq = DEFAULT_SENDQ;
103     class_default->max_recvq = DEFAULT_RECVQ;
104     }
105    
106     const char *
107     get_client_class(const dlink_list *const list)
108     {
109     const dlink_node *ptr = NULL;
110    
111     if ((ptr = list->head)) {
112     const struct MaskItem *conf = ptr->data;
113    
114     assert(conf->class);
115     assert(conf->type & (CONF_OPERATOR | CONF_CLIENT | CONF_SERVER));
116    
117     return conf->class->name;
118     }
119    
120     return class_default->name;
121     }
122    
123     unsigned int
124 michael 1644 get_client_ping(const dlink_list *const list)
125 michael 1633 {
126     const dlink_node *ptr = NULL;
127    
128     if ((ptr = list->head)) {
129     const struct MaskItem *conf = ptr->data;
130    
131     assert(aconf->class);
132     assert(aconf->type & (CONF_OPERATOR | CONF_CLIENT | CONF_SERVER));
133    
134 michael 1644 return conf->class->ping_freq;
135 michael 1633 }
136    
137     return class_default->ping_freq;
138     }
139    
140     unsigned int
141     get_sendq(const dlink_list *const list)
142     {
143     const dlink_node *ptr = NULL;
144    
145     if ((ptr = list->head)) {
146     const struct MaskItem *conf = ptr->data;
147    
148     assert(conf->class);
149     assert(conf->type & (CONF_OPERATOR | CONF_CLIENT | CONF_SERVER));
150    
151     return conf->class->max_sendq;
152     }
153    
154     return class_default->max_sendq;
155     }
156    
157     unsigned int
158     get_recvq(const dlink_list *const list)
159     {
160     const dlink_node *ptr = NULL;
161    
162     if ((ptr = list->head)) {
163     const struct MaskItem *conf = ptr->data;
164    
165     assert(conf->class);
166     assert(conf->type & (CONF_OPERATOR | CONF_CLIENT | CONF_SERVER));
167    
168     return conf->class->max_recvq;
169     }
170    
171     return class_default->max_recvq;
172     }
173    
174     /*
175     * inputs - Integer (Number of class)
176     * output - Pointer to ClassItem struct. Non-NULL expected
177     * side effects - NONE
178     */
179     struct ClassItem *
180     class_find(const char *name, int active)
181     {
182     dlink_node *ptr = NULL;
183    
184     DLINK_FOREACH(ptr, class_list.head) {
185     struct ClassItem *class = ptr->data;
186    
187     if (!irccmp(class->name, name))
188     return active && !class->active ? NULL : class;
189     }
190    
191     return NULL;
192     }
193    
194     /*
195     * We don't delete the class table, rather mark all entries for deletion.
196     * The table is cleaned up by delete_marked_classes. - avalon
197     */
198     void
199     class_mark_for_deletion(void)
200     {
201     dlink_node *ptr = NULL;
202    
203     DLINK_FOREACH(ptr, class_list.head)
204     {
205     struct ClassItem *class = ptr->data;
206    
207     if (class != class_default)
208     class->active = 0;
209     }
210     }
211    
212     void
213     class_delete_marked(void)
214     {
215     dlink_node *ptr = NULL, *ptr_next = NULL;
216    
217     DLINK_FOREACH_SAFE(ptr, ptr_next, class_list.head) {
218     struct ClassItem *class = ptr->data;
219    
220     if (!class->active && !class->ref_count)
221     {
222     destroy_cidr_class(class);
223     class_free(class);
224     }
225     }
226     }
227    
228     /*
229     * cidr_limit_reached
230     *
231     * inputs - int flag allowing over_rule of limits
232     * - pointer to the ip to be added
233     * - pointer to the class
234     * output - non zero if limit reached
235     * 0 if limit not reached
236     * side effects -
237     */
238     int
239     cidr_limit_reached(int over_rule,
240     struct irc_ssaddr *ip, struct ClassItem *class)
241     {
242     dlink_node *ptr = NULL;
243     struct CidrItem *cidr = NULL;
244    
245 michael 1644 if (class->number_per_cidr == 0)
246 michael 1633 return 0;
247    
248     if (ip->ss.ss_family == AF_INET)
249     {
250 michael 1644 if (class->cidr_bitlen_ipv4 == 0)
251 michael 1633 return 0;
252    
253     DLINK_FOREACH(ptr, class->list_ipv4.head)
254     {
255     cidr = ptr->data;
256     if (match_ipv4(ip, &cidr->mask, class->cidr_bitlen_ipv4))
257     {
258     if (!over_rule && (cidr->number_on_this_cidr >= class->number_per_cidr))
259     return -1;
260     cidr->number_on_this_cidr++;
261     return 0;
262     }
263     }
264     cidr = MyMalloc(sizeof(struct CidrItem));
265     cidr->number_on_this_cidr = 1;
266     cidr->mask = *ip;
267     mask_addr(&cidr->mask, class->cidr_bitlen_ipv4);
268     dlinkAdd(cidr, &cidr->node, &class->list_ipv4);
269     }
270     #ifdef IPV6
271     else if (class->cidr_bitlen_ipv6 > 0)
272     {
273     DLINK_FOREACH(ptr, class->list_ipv6.head)
274     {
275     cidr = ptr->data;
276     if (match_ipv6(ip, &cidr->mask, class->cidr_bitlen_ipv6))
277     {
278     if (!over_rule && (cidr->number_on_this_cidr >= class->number_per_cidr))
279     return -1;
280     cidr->number_on_this_cidr++;
281     return 0;
282     }
283     }
284     cidr = MyMalloc(sizeof(struct CidrItem));
285     cidr->number_on_this_cidr = 1;
286     cidr->mask = *ip;
287     mask_addr(&cidr->mask, class->cidr_bitlen_ipv6);
288     dlinkAdd(cidr, &cidr->node, &class->list_ipv6);
289     }
290     #endif
291     return 0;
292     }
293    
294     /*
295     * remove_from_cidr_check
296     *
297     * inputs - pointer to the ip to be removed
298     * - pointer to the class
299     * output - NONE
300     * side effects -
301     */
302     void
303     remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
304     {
305     dlink_node *ptr = NULL;
306     dlink_node *next_ptr = NULL;
307     struct CidrItem *cidr;
308    
309     if (aclass->number_per_cidr == 0)
310     return;
311    
312     if (ip->ss.ss_family == AF_INET)
313     {
314 michael 1644 if (aclass->cidr_bitlen_ipv4 == 0)
315 michael 1633 return;
316    
317     DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
318     {
319     cidr = ptr->data;
320     if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
321     {
322     cidr->number_on_this_cidr--;
323     if (cidr->number_on_this_cidr == 0)
324     {
325     dlinkDelete(ptr, &aclass->list_ipv4);
326     MyFree(cidr);
327     return;
328     }
329     }
330     }
331     }
332     #ifdef IPV6
333     else if (aclass->cidr_bitlen_ipv6 > 0)
334     {
335     DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
336     {
337     cidr = ptr->data;
338     if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
339     {
340     cidr->number_on_this_cidr--;
341     if (cidr->number_on_this_cidr == 0)
342     {
343     dlinkDelete(ptr, &aclass->list_ipv6);
344     MyFree(cidr);
345     return;
346     }
347     }
348     }
349     }
350     #endif
351     }
352    
353     static void
354     rebuild_cidr_list(int aftype, struct ClassItem *oldcl, struct ClassItem *newcl,
355     dlink_list *old_list, dlink_list *new_list, int changed)
356     {
357     dlink_node *ptr;
358     struct Client *client_p;
359     struct MaskItem *conf;
360    
361     if (!changed)
362     {
363     *new_list = *old_list;
364     old_list->head = old_list->tail = NULL;
365     old_list->length = 0;
366     return;
367     }
368    
369     DLINK_FOREACH(ptr, local_client_list.head)
370     {
371     client_p = ptr->data;
372     if (client_p->localClient->aftype != aftype)
373     continue;
374     if (dlink_list_length(&client_p->localClient->confs) == 0)
375     continue;
376    
377     conf = client_p->localClient->confs.tail->data;
378     if (conf->type == CONF_CLIENT)
379     if (conf->class == oldcl)
380     cidr_limit_reached(1, &client_p->localClient->ip, newcl);
381     }
382     }
383    
384     /*
385     * rebuild_cidr_class
386     *
387     * inputs - pointer to old conf
388     * - pointer to new_class
389     * output - none
390     * side effects - rebuilds the class link list of cidr blocks
391     */
392     void
393     rebuild_cidr_class(struct ClassItem *old_class, struct ClassItem *new_class)
394     {
395     if (old_class->number_per_cidr > 0 && new_class->number_per_cidr > 0)
396     {
397     if (old_class->cidr_bitlen_ipv4 > 0 && new_class->cidr_bitlen_ipv4 > 0)
398     rebuild_cidr_list(AF_INET, old_class, new_class,
399     &old_class->list_ipv4, &new_class->list_ipv4,
400     old_class->cidr_bitlen_ipv4 != new_class->cidr_bitlen_ipv4);
401    
402     #ifdef IPV6
403     if (old_class->cidr_bitlen_ipv6 > 0 && new_class->cidr_bitlen_ipv6 > 0)
404     rebuild_cidr_list(AF_INET6, old_class, new_class,
405     &old_class->list_ipv6, &new_class->list_ipv6,
406     old_class->cidr_bitlen_ipv6 != new_class->cidr_bitlen_ipv6);
407     #endif
408     }
409    
410     destroy_cidr_class(old_class);
411     }
412    
413     /*
414     * destroy_cidr_list
415     *
416     * inputs - pointer to class dlink list of cidr blocks
417     * output - none
418     * side effects - completely destroys the class link list of cidr blocks
419     */
420     static void
421     destroy_cidr_list(dlink_list *list)
422     {
423     dlink_node *ptr = NULL, *next_ptr = NULL;
424    
425     DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
426     {
427     dlinkDelete(ptr, list);
428     MyFree(ptr->data);
429     }
430     }
431    
432     /*
433     * destroy_cidr_class
434     *
435     * inputs - pointer to class
436     * output - none
437     * side effects - completely destroys the class link list of cidr blocks
438     */
439     void
440     destroy_cidr_class(struct ClassItem *class)
441     {
442     destroy_cidr_list(&class->list_ipv4);
443     destroy_cidr_list(&class->list_ipv6);
444     }

Properties

Name Value
svn:executable *
svn:keywords Id