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, 6 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

# Content
1 /*
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 * \version $Id$
25 */
26
27 #include "stdinc.h"
28 #include "list.h"
29 #include "ircd.h"
30 #include "conf.h"
31 #include "hostmask.h"
32 #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 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 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 (class_default = class_make())->name = xstrdup("default");
80 }
81
82 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 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 assert(conf->type & (CONF_OPER | CONF_CLIENT | CONF_SERVER));
109
110 return conf->class->name;
111 }
112
113 return class_default->name;
114 }
115
116 unsigned int
117 get_client_ping(const dlink_list *const list)
118 {
119 const dlink_node *ptr = NULL;
120
121 if ((ptr = list->head)) {
122 const struct MaskItem *conf = ptr->data;
123
124 assert(conf->class);
125 assert(conf->type & (CONF_OPER | CONF_CLIENT | CONF_SERVER));
126
127 return conf->class->ping_freq;
128 }
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 assert(conf->type & (CONF_OPER | CONF_CLIENT | CONF_SERVER));
143
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 assert(conf->type & (CONF_OPER | CONF_CLIENT | CONF_SERVER));
160
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 DLINK_FOREACH_PREV(ptr, class_list.tail->prev)
197 ((struct ClassItem *)ptr->data)->active = 0;
198 }
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 if (class->number_per_cidr == 0)
234 return 0;
235
236 if (ip->ss.ss_family == AF_INET)
237 {
238 if (class->cidr_bitlen_ipv4 == 0)
239 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 if (aclass->cidr_bitlen_ipv4 == 0)
303 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 void
342 rebuild_cidr_list(struct ClassItem *class)
343 {
344 dlink_node *ptr;
345
346 destroy_cidr_class(class);
347
348 DLINK_FOREACH(ptr, local_client_list.head)
349 {
350 struct Client *client_p = ptr->data;
351 struct MaskItem *conf = client_p->localClient->confs.tail->data;
352
353 if (conf && (conf->type == CONF_CLIENT))
354 if (conf->class == class)
355 cidr_limit_reached(1, &client_p->localClient->ip, class);
356 }
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