ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf_class.c
Revision: 1636
Committed: Sun Nov 4 17:09:47 2012 UTC (13 years, 11 months ago) by michael
Content type: text/x-csrc
File size: 10293 byte(s)
Log Message:
- Cleanup configuration subsystem
- Fixed broken CIDR support for /challenge

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

Properties

Name Value
svn:executable *
svn:keywords Id