ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf_class.c
Revision: 1644
Committed: Tue Nov 6 22:20:16 2012 UTC (11 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 10148 byte(s)
Log Message:
- More config subsystem cleanups

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

Properties

Name Value
svn:executable *
svn:keywords Id