ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf_class.c
Revision: 8611
Committed: Thu Nov 1 15:56:52 2018 UTC (6 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 5788 byte(s)
Log Message:
- ipcache, conf_class: use separate trees for ipv6 and ipv4 addresses. Until fixed, this is to work around a patricia.c limitation/bug where
  a ipv6 and a ipv4 prefix can share the same tree node in case they have the same length and bit pattern.

File Contents

# User Rev Content
1 michael 1633 /*
2 michael 2916 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 michael 1633 *
4 michael 8279 * Copyright (c) 1997-2018 ircd-hybrid development team
5 michael 1633 *
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 michael 4565 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 michael 1633 * USA
20     */
21    
22 michael 2916 /*! \file conf_class.c
23 michael 1633 * \brief Configuration managment for class{} blocks
24 michael 1635 * \version $Id$
25 michael 1633 */
26    
27     #include "stdinc.h"
28     #include "list.h"
29 michael 1658 #include "ircd.h"
30 michael 1633 #include "conf.h"
31 michael 1658 #include "hostmask.h"
32 michael 1633 #include "irc_string.h"
33     #include "memory.h"
34 michael 8607 #include "patricia.h"
35 michael 1633
36    
37     struct ClassItem *class_default;
38    
39 michael 3250 static dlink_list class_list;
40 michael 1633
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 michael 8431 struct ClassItem *class = xcalloc(sizeof(*class));
52 michael 1633
53 michael 1650 class->active = 1;
54     class->con_freq = DEFAULT_CONNECTFREQUENCY;
55     class->ping_freq = DEFAULT_PINGFREQUENCY;
56     class->max_total = MAXIMUM_LINKS_DEFAULT;
57     class->max_sendq = DEFAULT_SENDQ;
58     class->max_recvq = DEFAULT_RECVQ;
59 michael 8611 class->ip_tree_v6 = patricia_new(128);
60     class->ip_tree_v4 = patricia_new( 32);
61 michael 1650
62 michael 1633 dlinkAdd(class, &class->node, &class_list);
63    
64     return class;
65     }
66    
67     void
68 michael 4874 class_free(struct ClassItem *const class)
69 michael 1633 {
70 michael 3547 assert(class != class_default);
71 michael 1633 assert(class->active == 0);
72     assert(class->ref_count == 0);
73    
74 michael 8611 if (class->ip_tree_v6)
75     patricia_destroy(class->ip_tree_v6, NULL);
76     if (class->ip_tree_v4)
77     patricia_destroy(class->ip_tree_v4, NULL);
78 michael 8607
79 michael 1633 dlinkDelete(&class->node, &class_list);
80 michael 7032 xfree(class->name);
81     xfree(class);
82 michael 1633 }
83    
84     void
85     class_init(void)
86     {
87 michael 7937 class_default = class_make();
88     class_default->name = xstrdup("default");
89 michael 1633 }
90    
91 michael 5411 const struct ClassItem *
92 michael 8437 class_get_ptr(const dlink_list *const list)
93 michael 1783 {
94 michael 4848 const dlink_node *const node = list->head;
95 michael 1783
96 michael 4848 if (node)
97 michael 2213 {
98 michael 4833 const struct MaskItem *const conf = node->data;
99 michael 1783
100     assert(conf->class);
101     assert(conf->type & (CONF_OPER | CONF_CLIENT | CONF_SERVER));
102    
103     return conf->class;
104     }
105    
106     return class_default;
107     }
108    
109 michael 1633 const char *
110     get_client_class(const dlink_list *const list)
111     {
112 michael 8437 return class_get_ptr(list)->name;
113 michael 1633 }
114    
115     unsigned int
116 michael 1644 get_client_ping(const dlink_list *const list)
117 michael 1633 {
118 michael 8437 return class_get_ptr(list)->ping_freq;
119 michael 1633 }
120    
121     unsigned int
122     get_sendq(const dlink_list *const list)
123     {
124 michael 8437 return class_get_ptr(list)->max_sendq;
125 michael 1633 }
126    
127     unsigned int
128     get_recvq(const dlink_list *const list)
129     {
130 michael 8437 return class_get_ptr(list)->max_recvq;
131 michael 1633 }
132    
133     /*
134     * inputs - Integer (Number of class)
135     * output - Pointer to ClassItem struct. Non-NULL expected
136     * side effects - NONE
137     */
138     struct ClassItem *
139     class_find(const char *name, int active)
140     {
141 michael 8059 dlink_node *node;
142 michael 1633
143 michael 4800 DLINK_FOREACH(node, class_list.head)
144 michael 2213 {
145 michael 4800 struct ClassItem *class = node->data;
146 michael 1633
147 michael 8522 if (irccmp(class->name, name) == 0)
148     return active && class->active == 0 ? NULL : class;
149 michael 1633 }
150    
151     return NULL;
152     }
153    
154     /*
155     * We don't delete the class table, rather mark all entries for deletion.
156     * The table is cleaned up by delete_marked_classes. - avalon
157     */
158     void
159     class_mark_for_deletion(void)
160     {
161 michael 8059 dlink_node *node;
162 michael 1633
163 michael 4800 DLINK_FOREACH_PREV(node, class_list.tail->prev)
164     ((struct ClassItem *)node->data)->active = 0;
165 michael 1633 }
166    
167     void
168     class_delete_marked(void)
169     {
170 michael 8059 dlink_node *node, *node_next;
171 michael 1633
172 michael 4800 DLINK_FOREACH_SAFE(node, node_next, class_list.head)
173 michael 2213 {
174 michael 4800 struct ClassItem *class = node->data;
175 michael 1633
176 michael 8431 if (class->active == 0 && class->ref_count == 0)
177 michael 1633 class_free(class);
178     }
179     }
180    
181 michael 8611 static void *
182     class_ip_limit_trie(struct ClassItem *class, void *addr)
183     {
184     if (((struct sockaddr *)addr)->sa_family == AF_INET6)
185     return class->ip_tree_v6;
186     else
187     return class->ip_tree_v4;
188     }
189    
190 michael 1633 int
191 michael 8608 class_ip_limit_add(struct ClassItem *class, void *addr, int over_rule)
192 michael 1633 {
193 michael 8607 int bitlen;
194 michael 1633
195 michael 8608 if (((struct sockaddr *)addr)->sa_family == AF_INET6)
196 michael 8607 bitlen = class->cidr_bitlen_ipv6;
197     else
198     bitlen = class->cidr_bitlen_ipv4;
199    
200     if (class->number_per_cidr == 0 || bitlen == 0)
201 michael 1633 return 0;
202    
203 michael 8611 patricia_node_t *pnode = patricia_make_and_lookup_addr(class_ip_limit_trie(class, addr), addr, bitlen);
204 michael 8607 if (((uintptr_t)pnode->data) >= class->number_per_cidr && over_rule == 0)
205     return 1;
206 michael 1633
207 michael 8607 PATRICIA_DATA_SET(pnode, (((uintptr_t)pnode->data) + 1));
208 michael 1633 return 0;
209     }
210    
211 michael 8607 int
212 michael 8608 class_ip_limit_remove(struct ClassItem *class, void *addr)
213 michael 1633 {
214 michael 8607 int bitlen;
215 michael 1633
216 michael 8608 if (((struct sockaddr *)addr)->sa_family == AF_INET6)
217 michael 8607 bitlen = class->cidr_bitlen_ipv6;
218     else
219     bitlen = class->cidr_bitlen_ipv4;
220 michael 1633
221 michael 8607 if (class->number_per_cidr == 0 || bitlen == 0)
222     return 0;
223 michael 1633
224 michael 8611 patricia_node_t *pnode = patricia_try_search_best_addr(class_ip_limit_trie(class, addr), addr, 0);
225 michael 8607 if (pnode == NULL)
226     return 0;
227 michael 2213
228 michael 8607 PATRICIA_DATA_SET(pnode, (((uintptr_t)pnode->data) - 1));
229 michael 2213
230 michael 8607 if (((uintptr_t)pnode->data) == 0)
231     {
232 michael 8611 patricia_remove(class_ip_limit_trie(class, addr), pnode);
233 michael 8607 return 1;
234 michael 1633 }
235 michael 2213
236 michael 8607 return 0;
237 michael 1633 }
238    
239 michael 1647 void
240 michael 8607 class_ip_limit_rebuild(struct ClassItem *class)
241 michael 1633 {
242 michael 8059 dlink_node *node;
243 michael 1633
244 michael 8611 patricia_clear(class->ip_tree_v6, NULL);
245     patricia_clear(class->ip_tree_v4, NULL);
246 michael 1633
247 michael 4800 DLINK_FOREACH(node, local_client_list.head)
248 michael 1633 {
249 michael 4800 struct Client *client_p = node->data;
250 michael 4588 struct MaskItem *conf = client_p->connection->confs.tail->data;
251 michael 1633
252 michael 8607 if (conf->type == CONF_CLIENT)
253 michael 1647 if (conf->class == class)
254 michael 8608 class_ip_limit_add(class, &client_p->ip, 1);
255 michael 1633 }
256     }

Properties

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