ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf_class.c
Revision: 1783
Committed: Thu Jan 24 19:26:51 2013 UTC (13 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 8530 byte(s)
Log Message:
- Forward-port -r1774:
  - Configuration parser now does support 'year' and 'month' units
  - Add support for fake idle times to /whois. Known from csircd, this
    adds min_idle, and max_idle configuration directives to class{} blocks

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 michael 1658 #include "ircd.h"
30 michael 1633 #include "conf.h"
31 michael 1658 #include "hostmask.h"
32 michael 1633 #include "irc_string.h"
33     #include "memory.h"
34    
35    
36     struct ClassItem *class_default;
37    
38     static dlink_list class_list = { NULL, NULL, 0 };
39    
40    
41     const dlink_list *
42     class_get_list(void)
43     {
44     return &class_list;
45     }
46    
47     struct ClassItem *
48     class_make(void)
49     {
50     struct ClassItem *class = MyMalloc(sizeof(*class));
51    
52 michael 1650 class->active = 1;
53     class->con_freq = DEFAULT_CONNECTFREQUENCY;
54     class->ping_freq = DEFAULT_PINGFREQUENCY;
55     class->max_total = MAXIMUM_LINKS_DEFAULT;
56     class->max_sendq = DEFAULT_SENDQ;
57     class->max_recvq = DEFAULT_RECVQ;
58    
59 michael 1633 dlinkAdd(class, &class->node, &class_list);
60    
61     return class;
62     }
63    
64     void
65     class_free(struct ClassItem *class)
66     {
67     assert(class);
68     assert(class->active == 0);
69     assert(class->ref_count == 0);
70    
71     dlinkDelete(&class->node, &class_list);
72     MyFree(class->name);
73     MyFree(class);
74     }
75    
76     void
77     class_init(void)
78     {
79 michael 1650 (class_default = class_make())->name = xstrdup("default");
80 michael 1633 }
81    
82 michael 1783 struct ClassItem *
83     get_class_ptr(const dlink_list *const list)
84     {
85     const dlink_node *ptr = NULL;
86    
87     if ((ptr = list->head)) {
88     const struct MaskItem *conf = ptr->data;
89    
90     assert(conf->class);
91     assert(conf->type & (CONF_OPER | CONF_CLIENT | CONF_SERVER));
92    
93     return conf->class;
94     }
95    
96     return class_default;
97     }
98    
99 michael 1633 const char *
100     get_client_class(const dlink_list *const list)
101     {
102     const dlink_node *ptr = NULL;
103    
104     if ((ptr = list->head)) {
105     const struct MaskItem *conf = ptr->data;
106    
107     assert(conf->class);
108 michael 1654 assert(conf->type & (CONF_OPER | CONF_CLIENT | CONF_SERVER));
109 michael 1633
110     return conf->class->name;
111     }
112    
113     return class_default->name;
114     }
115    
116     unsigned int
117 michael 1644 get_client_ping(const dlink_list *const list)
118 michael 1633 {
119     const dlink_node *ptr = NULL;
120    
121     if ((ptr = list->head)) {
122     const struct MaskItem *conf = ptr->data;
123    
124 michael 1654 assert(conf->class);
125     assert(conf->type & (CONF_OPER | CONF_CLIENT | CONF_SERVER));
126 michael 1633
127 michael 1644 return conf->class->ping_freq;
128 michael 1633 }
129    
130     return class_default->ping_freq;
131     }
132    
133     unsigned int
134     get_sendq(const dlink_list *const list)
135     {
136     const dlink_node *ptr = NULL;
137    
138     if ((ptr = list->head)) {
139     const struct MaskItem *conf = ptr->data;
140    
141     assert(conf->class);
142 michael 1654 assert(conf->type & (CONF_OPER | CONF_CLIENT | CONF_SERVER));
143 michael 1633
144     return conf->class->max_sendq;
145     }
146    
147     return class_default->max_sendq;
148     }
149    
150     unsigned int
151     get_recvq(const dlink_list *const list)
152     {
153     const dlink_node *ptr = NULL;
154    
155     if ((ptr = list->head)) {
156     const struct MaskItem *conf = ptr->data;
157    
158     assert(conf->class);
159 michael 1654 assert(conf->type & (CONF_OPER | CONF_CLIENT | CONF_SERVER));
160 michael 1633
161     return conf->class->max_recvq;
162     }
163    
164     return class_default->max_recvq;
165     }
166    
167     /*
168     * inputs - Integer (Number of class)
169     * output - Pointer to ClassItem struct. Non-NULL expected
170     * side effects - NONE
171     */
172     struct ClassItem *
173     class_find(const char *name, int active)
174     {
175     dlink_node *ptr = NULL;
176    
177     DLINK_FOREACH(ptr, class_list.head) {
178     struct ClassItem *class = ptr->data;
179    
180     if (!irccmp(class->name, name))
181     return active && !class->active ? NULL : class;
182     }
183    
184     return NULL;
185     }
186    
187     /*
188     * We don't delete the class table, rather mark all entries for deletion.
189     * The table is cleaned up by delete_marked_classes. - avalon
190     */
191     void
192     class_mark_for_deletion(void)
193     {
194     dlink_node *ptr = NULL;
195    
196 michael 1650 DLINK_FOREACH_PREV(ptr, class_list.tail->prev)
197     ((struct ClassItem *)ptr->data)->active = 0;
198 michael 1633 }
199    
200     void
201     class_delete_marked(void)
202     {
203     dlink_node *ptr = NULL, *ptr_next = NULL;
204    
205     DLINK_FOREACH_SAFE(ptr, ptr_next, class_list.head) {
206     struct ClassItem *class = ptr->data;
207    
208     if (!class->active && !class->ref_count)
209     {
210     destroy_cidr_class(class);
211     class_free(class);
212     }
213     }
214     }
215    
216     /*
217     * cidr_limit_reached
218     *
219     * inputs - int flag allowing over_rule of limits
220     * - pointer to the ip to be added
221     * - pointer to the class
222     * output - non zero if limit reached
223     * 0 if limit not reached
224     * side effects -
225     */
226     int
227     cidr_limit_reached(int over_rule,
228     struct irc_ssaddr *ip, struct ClassItem *class)
229     {
230     dlink_node *ptr = NULL;
231     struct CidrItem *cidr = NULL;
232    
233 michael 1644 if (class->number_per_cidr == 0)
234 michael 1633 return 0;
235    
236     if (ip->ss.ss_family == AF_INET)
237     {
238 michael 1644 if (class->cidr_bitlen_ipv4 == 0)
239 michael 1633 return 0;
240    
241     DLINK_FOREACH(ptr, class->list_ipv4.head)
242     {
243     cidr = ptr->data;
244     if (match_ipv4(ip, &cidr->mask, class->cidr_bitlen_ipv4))
245     {
246     if (!over_rule && (cidr->number_on_this_cidr >= class->number_per_cidr))
247     return -1;
248     cidr->number_on_this_cidr++;
249     return 0;
250     }
251     }
252     cidr = MyMalloc(sizeof(struct CidrItem));
253     cidr->number_on_this_cidr = 1;
254     cidr->mask = *ip;
255     mask_addr(&cidr->mask, class->cidr_bitlen_ipv4);
256     dlinkAdd(cidr, &cidr->node, &class->list_ipv4);
257     }
258     #ifdef IPV6
259     else if (class->cidr_bitlen_ipv6 > 0)
260     {
261     DLINK_FOREACH(ptr, class->list_ipv6.head)
262     {
263     cidr = ptr->data;
264     if (match_ipv6(ip, &cidr->mask, class->cidr_bitlen_ipv6))
265     {
266     if (!over_rule && (cidr->number_on_this_cidr >= class->number_per_cidr))
267     return -1;
268     cidr->number_on_this_cidr++;
269     return 0;
270     }
271     }
272     cidr = MyMalloc(sizeof(struct CidrItem));
273     cidr->number_on_this_cidr = 1;
274     cidr->mask = *ip;
275     mask_addr(&cidr->mask, class->cidr_bitlen_ipv6);
276     dlinkAdd(cidr, &cidr->node, &class->list_ipv6);
277     }
278     #endif
279     return 0;
280     }
281    
282     /*
283     * remove_from_cidr_check
284     *
285     * inputs - pointer to the ip to be removed
286     * - pointer to the class
287     * output - NONE
288     * side effects -
289     */
290     void
291     remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
292     {
293     dlink_node *ptr = NULL;
294     dlink_node *next_ptr = NULL;
295     struct CidrItem *cidr;
296    
297     if (aclass->number_per_cidr == 0)
298     return;
299    
300     if (ip->ss.ss_family == AF_INET)
301     {
302 michael 1644 if (aclass->cidr_bitlen_ipv4 == 0)
303 michael 1633 return;
304    
305     DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
306     {
307     cidr = ptr->data;
308     if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
309     {
310     cidr->number_on_this_cidr--;
311     if (cidr->number_on_this_cidr == 0)
312     {
313     dlinkDelete(ptr, &aclass->list_ipv4);
314     MyFree(cidr);
315     return;
316     }
317     }
318     }
319     }
320     #ifdef IPV6
321     else if (aclass->cidr_bitlen_ipv6 > 0)
322     {
323     DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
324     {
325     cidr = ptr->data;
326     if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
327     {
328     cidr->number_on_this_cidr--;
329     if (cidr->number_on_this_cidr == 0)
330     {
331     dlinkDelete(ptr, &aclass->list_ipv6);
332     MyFree(cidr);
333     return;
334     }
335     }
336     }
337     }
338     #endif
339     }
340    
341 michael 1647 void
342     rebuild_cidr_list(struct ClassItem *class)
343 michael 1633 {
344     dlink_node *ptr;
345    
346 michael 1647 destroy_cidr_class(class);
347 michael 1633
348     DLINK_FOREACH(ptr, local_client_list.head)
349     {
350 michael 1647 struct Client *client_p = ptr->data;
351     struct MaskItem *conf = client_p->localClient->confs.tail->data;
352 michael 1633
353 michael 1647 if (conf && (conf->type == CONF_CLIENT))
354     if (conf->class == class)
355     cidr_limit_reached(1, &client_p->localClient->ip, class);
356 michael 1633 }
357     }
358    
359     /*
360     * destroy_cidr_list
361     *
362     * inputs - pointer to class dlink list of cidr blocks
363     * output - none
364     * side effects - completely destroys the class link list of cidr blocks
365     */
366     static void
367     destroy_cidr_list(dlink_list *list)
368     {
369     dlink_node *ptr = NULL, *next_ptr = NULL;
370    
371     DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
372     {
373     dlinkDelete(ptr, list);
374     MyFree(ptr->data);
375     }
376     }
377    
378     /*
379     * destroy_cidr_class
380     *
381     * inputs - pointer to class
382     * output - none
383     * side effects - completely destroys the class link list of cidr blocks
384     */
385     void
386     destroy_cidr_class(struct ClassItem *class)
387     {
388     destroy_cidr_list(&class->list_ipv4);
389     destroy_cidr_list(&class->list_ipv6);
390     }

Properties

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