ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf_class.c
Revision: 9883
Committed: Fri Jan 15 13:47:18 2021 UTC (4 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 6213 byte(s)
Log Message:
- conf_class.c:class_ip_limit_add() return 'true' even in case of overruling.  Add note why pnode->data needs to be increased in case of overruling, too

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 1997-2021 ircd-hybrid development team
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 * USA
20 */
21
22 /*! \file conf_class.c
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 #include "patricia.h"
35
36
37 struct ClassItem *class_default;
38
39 static dlink_list class_list;
40
41
42 const dlink_list *
43 class_get_list(void)
44 {
45 return &class_list;
46 }
47
48 struct ClassItem *
49 class_make(void)
50 {
51 struct ClassItem *class = xcalloc(sizeof(*class));
52
53 class->active = true;
54 class->con_freq = DEFAULT_CONNECTFREQUENCY;
55 class->ping_freq = DEFAULT_PINGFREQUENCY;
56 class->max_sendq = DEFAULT_SENDQ;
57 class->max_recvq = DEFAULT_RECVQ;
58 class->ip_tree_v6 = patricia_new(128);
59 class->ip_tree_v4 = patricia_new( 32);
60
61 dlinkAdd(class, &class->node, &class_list);
62
63 return class;
64 }
65
66 void
67 class_free(struct ClassItem *const class)
68 {
69 assert(class != class_default);
70 assert(class->active == false);
71 assert(class->ref_count == 0);
72
73 if (class->ip_tree_v6)
74 patricia_destroy(class->ip_tree_v6, NULL);
75 if (class->ip_tree_v4)
76 patricia_destroy(class->ip_tree_v4, NULL);
77
78 dlinkDelete(&class->node, &class_list);
79 xfree(class->name);
80 xfree(class);
81 }
82
83 void
84 class_init(void)
85 {
86 class_default = class_make();
87 class_default->name = xstrdup("default");
88 }
89
90 const struct ClassItem *
91 class_get_ptr(const dlink_list *const list)
92 {
93 const dlink_node *const node = list->head;
94
95 if (node)
96 {
97 const struct MaskItem *const conf = node->data;
98
99 assert(conf->class);
100 assert(conf->type & (CONF_OPER | CONF_CLIENT | CONF_SERVER));
101
102 return conf->class;
103 }
104
105 return class_default;
106 }
107
108 const char *
109 get_client_class(const dlink_list *const list)
110 {
111 return class_get_ptr(list)->name;
112 }
113
114 unsigned int
115 get_client_ping(const dlink_list *const list)
116 {
117 return class_get_ptr(list)->ping_freq;
118 }
119
120 unsigned int
121 get_sendq(const dlink_list *const list)
122 {
123 return class_get_ptr(list)->max_sendq;
124 }
125
126 unsigned int
127 get_recvq(const dlink_list *const list)
128 {
129 return class_get_ptr(list)->max_recvq;
130 }
131
132 /*
133 * inputs - Integer (Number of class)
134 * output - Pointer to ClassItem struct. Non-NULL expected
135 * side effects - NONE
136 */
137 struct ClassItem *
138 class_find(const char *name, bool active)
139 {
140 dlink_node *node;
141
142 DLINK_FOREACH(node, class_list.head)
143 {
144 struct ClassItem *class = node->data;
145
146 if (irccmp(class->name, name) == 0)
147 {
148 if (active == true && class->active == false)
149 return NULL;
150
151 return class;
152 }
153 }
154
155 return NULL;
156 }
157
158 /*
159 * We don't delete the class table, rather mark all entries for deletion.
160 * The table is cleaned up by delete_marked_classes. - avalon
161 */
162 void
163 class_mark_for_deletion(void)
164 {
165 dlink_node *node;
166
167 DLINK_FOREACH_PREV(node, class_list.tail->prev)
168 {
169 struct ClassItem *class = node->data;
170 class->active = false;
171 }
172 }
173
174 void
175 class_delete_marked(void)
176 {
177 dlink_node *node, *node_next;
178
179 DLINK_FOREACH_SAFE(node, node_next, class_list.head)
180 {
181 struct ClassItem *class = node->data;
182
183 if (class->active == false && class->ref_count == 0)
184 class_free(class);
185 }
186 }
187
188 static void *
189 class_ip_limit_trie(struct ClassItem *class, void *addr)
190 {
191 if (((struct sockaddr *)addr)->sa_family == AF_INET6)
192 return class->ip_tree_v6;
193 else
194 return class->ip_tree_v4;
195 }
196
197 bool
198 class_ip_limit_add(struct ClassItem *class, void *addr, bool over_rule)
199 {
200 int bitlen;
201
202 if (((struct sockaddr *)addr)->sa_family == AF_INET6)
203 bitlen = class->cidr_bitlen_ipv6;
204 else
205 bitlen = class->cidr_bitlen_ipv4;
206
207 if (class->number_per_cidr == 0 || bitlen == 0)
208 return false;
209
210 patricia_node_t *pnode = patricia_make_and_lookup_addr(class_ip_limit_trie(class, addr), addr, bitlen);
211 if (((uintptr_t)pnode->data) >= class->number_per_cidr)
212 {
213 if (over_rule == true)
214 /*
215 * In case of overruling, we continue with the client registration process
216 * which means we expect a class_ip_limit_remove() call when detaching the
217 * configuration record upon client exit, therefore pnode->data has to be
218 * increased.
219 */
220 PATRICIA_DATA_SET(pnode, (((uintptr_t)pnode->data) + 1));
221
222 return true;
223 }
224
225 PATRICIA_DATA_SET(pnode, (((uintptr_t)pnode->data) + 1));
226 return false;
227 }
228
229 bool
230 class_ip_limit_remove(struct ClassItem *class, void *addr)
231 {
232 int bitlen;
233
234 if (((struct sockaddr *)addr)->sa_family == AF_INET6)
235 bitlen = class->cidr_bitlen_ipv6;
236 else
237 bitlen = class->cidr_bitlen_ipv4;
238
239 if (class->number_per_cidr == 0 || bitlen == 0)
240 return false;
241
242 patricia_node_t *pnode = patricia_try_search_best_addr(class_ip_limit_trie(class, addr), addr, 0);
243 if (pnode == NULL)
244 return false;
245
246 PATRICIA_DATA_SET(pnode, (((uintptr_t)pnode->data) - 1));
247
248 if (((uintptr_t)pnode->data) == 0)
249 {
250 patricia_remove(class_ip_limit_trie(class, addr), pnode);
251 return true;
252 }
253
254 return false;
255 }
256
257 void
258 class_ip_limit_rebuild(struct ClassItem *class)
259 {
260 dlink_node *node;
261
262 patricia_clear(class->ip_tree_v6, NULL);
263 patricia_clear(class->ip_tree_v4, NULL);
264
265 DLINK_FOREACH(node, local_client_list.head)
266 {
267 struct Client *client = node->data;
268 struct MaskItem *conf = client->connection->confs.tail->data;
269
270 if (conf->type == CONF_CLIENT)
271 if (conf->class == class)
272 class_ip_limit_add(class, &client->ip, true);
273 }
274 }

Properties

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