/[svn]/ircd-hybrid/trunk/src/conf_class.c
ViewVC logotype

Contents of /ircd-hybrid/trunk/src/conf_class.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1633 - (show annotations)
Sun Nov 4 15:51:30 2012 UTC (7 years, 9 months ago) by michael
File MIME type: text/x-chdr
File size: 10341 byte(s)
- Add conf_class.c, conf_class.h

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

Properties

Name Value
svn:executable *

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.28