ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf_class.c
(Generate patch)

Comparing ircd-hybrid/trunk/src/conf_class.c (file contents):
Revision 8606 by michael, Tue Apr 24 19:48:22 2018 UTC vs.
Revision 8607 by michael, Mon Oct 29 21:26:54 2018 UTC

# Line 31 | Line 31
31   #include "hostmask.h"
32   #include "irc_string.h"
33   #include "memory.h"
34 + #include "patricia.h"
35  
36  
37   struct ClassItem *class_default;
# Line 55 | Line 56 | class_make(void)
56    class->max_total = MAXIMUM_LINKS_DEFAULT;
57    class->max_sendq = DEFAULT_SENDQ;
58    class->max_recvq = DEFAULT_RECVQ;
59 +  class->ip_tree   = patricia_new(PATRICIA_MAXBITS);
60  
61    dlinkAdd(class, &class->node, &class_list);
62  
# Line 68 | Line 70 | class_free(struct ClassItem *const class
70    assert(class->active    == 0);
71    assert(class->ref_count == 0);
72  
73 +  if (class->ip_tree)
74 +    patricia_destroy(class->ip_tree, NULL);
75 +
76    dlinkDelete(&class->node, &class_list);
77    xfree(class->name);
78    xfree(class);
# Line 166 | Line 171 | class_delete_marked(void)
171      struct ClassItem *class = node->data;
172  
173      if (class->active == 0 && class->ref_count == 0)
169    {
170      destroy_cidr_class(class);
174        class_free(class);
172    }
175    }
176   }
177  
176 /*
177 * cidr_limit_reached
178 *
179 * inputs       - int flag allowing over_rule of limits
180 *              - pointer to the ip to be added
181 *              - pointer to the class
182 * output       - non zero if limit reached
183 *                0 if limit not reached
184 * side effects -
185 */
178   int
179 < cidr_limit_reached(int over_rule, struct irc_ssaddr *ip, struct ClassItem *class)
179 > class_ip_limit_add(struct ClassItem *class, struct sockaddr *addr, int over_rule)
180   {
181 <  dlink_node *node;
181 >  int bitlen;
182  
183 <  if (class->number_per_cidr == 0)
184 <    return 0;
183 >  if (addr->sa_family == AF_INET6)
184 >    bitlen = class->cidr_bitlen_ipv6;
185 >  else
186 >    bitlen = class->cidr_bitlen_ipv4;
187  
188 <  if (ip->ss.ss_family == AF_INET)
189 <  {
196 <    if (class->cidr_bitlen_ipv4 == 0)
197 <      return 0;
188 >  if (class->number_per_cidr == 0 || bitlen == 0)
189 >    return 0;
190  
191 <    DLINK_FOREACH(node, class->list_ipv4.head)
192 <    {
193 <      struct CidrItem *cidr = node->data;
202 <
203 <      if (match_ipv4(ip, &cidr->mask, class->cidr_bitlen_ipv4))
204 <      {
205 <        if (!over_rule && (cidr->number_on_this_cidr >= class->number_per_cidr))
206 <          return -1;
207 <
208 <        cidr->number_on_this_cidr++;
209 <        return 0;
210 <      }
211 <    }
212 <
213 <    struct CidrItem *cidr = xcalloc(sizeof(*cidr));
214 <    cidr->number_on_this_cidr = 1;
215 <    cidr->mask = *ip;
216 <    mask_addr(&cidr->mask, class->cidr_bitlen_ipv4);
217 <    dlinkAdd(cidr, &cidr->node, &class->list_ipv4);
218 <  }
219 <  else if (class->cidr_bitlen_ipv6 > 0)
220 <  {
221 <    DLINK_FOREACH(node, class->list_ipv6.head)
222 <    {
223 <      struct CidrItem *cidr = node->data;
224 <
225 <      if (match_ipv6(ip, &cidr->mask, class->cidr_bitlen_ipv6))
226 <      {
227 <        if (!over_rule && (cidr->number_on_this_cidr >= class->number_per_cidr))
228 <          return -1;
229 <
230 <        cidr->number_on_this_cidr++;
231 <        return 0;
232 <      }
233 <    }
234 <
235 <    struct CidrItem *cidr = xcalloc(sizeof(*cidr));
236 <    cidr->number_on_this_cidr = 1;
237 <    cidr->mask = *ip;
238 <    mask_addr(&cidr->mask, class->cidr_bitlen_ipv6);
239 <    dlinkAdd(cidr, &cidr->node, &class->list_ipv6);
240 <  }
191 >  patricia_node_t *pnode = patricia_make_and_lookup_addr(class->ip_tree, addr, bitlen);
192 >  if (((uintptr_t)pnode->data) >= class->number_per_cidr && over_rule == 0)
193 >    return 1;
194  
195 +  PATRICIA_DATA_SET(pnode, (((uintptr_t)pnode->data) + 1));
196    return 0;
197   }
198  
199 < /*
200 < * remove_from_cidr_check
247 < *
248 < * inputs       - pointer to the ip to be removed
249 < *              - pointer to the class
250 < * output       - NONE
251 < * side effects -
252 < */
253 < void
254 < remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
199 > int
200 > class_ip_limit_remove(struct ClassItem *class, struct sockaddr *addr)
201   {
202 <  dlink_node *node, *node_next;
202 >  int bitlen;
203  
204 <  if (aclass->number_per_cidr == 0)
205 <    return;
204 >  if (addr->sa_family == AF_INET6)
205 >    bitlen = class->cidr_bitlen_ipv6;
206 >  else
207 >    bitlen = class->cidr_bitlen_ipv4;
208  
209 <  if (ip->ss.ss_family == AF_INET)
210 <  {
263 <    if (aclass->cidr_bitlen_ipv4 == 0)
264 <      return;
209 >  if (class->number_per_cidr == 0 || bitlen == 0)
210 >    return 0;
211  
212 <    DLINK_FOREACH_SAFE(node, node_next, aclass->list_ipv4.head)
213 <    {
214 <      struct CidrItem *cidr = node->data;
215 <
216 <      if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
217 <      {
218 <        cidr->number_on_this_cidr--;
273 <
274 <        if (cidr->number_on_this_cidr == 0)
275 <        {
276 <          dlinkDelete(node, &aclass->list_ipv4);
277 <          xfree(cidr);
278 <          return;
279 <        }
280 <      }
281 <    }
282 <  }
283 <  else if (aclass->cidr_bitlen_ipv6 > 0)
212 >  patricia_node_t *pnode = patricia_try_search_best_addr(class->ip_tree, addr, 0);
213 >  if (pnode == NULL)
214 >    return 0;
215 >
216 >  PATRICIA_DATA_SET(pnode, (((uintptr_t)pnode->data) - 1));
217 >
218 >  if (((uintptr_t)pnode->data) == 0)
219    {
220 <    DLINK_FOREACH_SAFE(node, node_next, aclass->list_ipv6.head)
221 <    {
287 <      struct CidrItem *cidr = node->data;
288 <
289 <      if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
290 <      {
291 <        cidr->number_on_this_cidr--;
292 <
293 <        if (cidr->number_on_this_cidr == 0)
294 <        {
295 <          dlinkDelete(node, &aclass->list_ipv6);
296 <          xfree(cidr);
297 <          return;
298 <        }
299 <      }
300 <    }
220 >    patricia_remove(class->ip_tree, pnode);
221 >    return 1;
222    }
223 +
224 +  return 0;
225   }
226  
227   void
228 < rebuild_cidr_list(struct ClassItem *class)
228 > class_ip_limit_rebuild(struct ClassItem *class)
229   {
230    dlink_node *node;
231  
232 <  destroy_cidr_class(class);
232 >  patricia_clear(class->ip_tree, NULL);
233  
234    DLINK_FOREACH(node, local_client_list.head)
235    {
236      struct Client *client_p = node->data;
237      struct MaskItem *conf = client_p->connection->confs.tail->data;
238  
239 <    if (conf && (conf->type == CONF_CLIENT))
239 >    if (conf->type == CONF_CLIENT)
240        if (conf->class == class)
241 <        cidr_limit_reached(1, &client_p->ip, class);
319 <  }
320 < }
321 <
322 < /*
323 < * destroy_cidr_list
324 < *
325 < * inputs       - pointer to class dlink list of cidr blocks
326 < * output       - none
327 < * side effects - completely destroys the class link list of cidr blocks
328 < */
329 < static void
330 < destroy_cidr_list(dlink_list *list)
331 < {
332 <  while (list->head)
333 <  {
334 <    struct CidrItem *cidr = list->head->data;
335 <    dlinkDelete(&cidr->node, list);
336 <    xfree(cidr);
241 >        class_ip_limit_add(class, (struct sockaddr *)&client_p->ip, 1);
242    }
243   }
339
340 /*
341 * destroy_cidr_class
342 *
343 * inputs       - pointer to class
344 * output       - none
345 * side effects - completely destroys the class link list of cidr blocks
346 */
347 void
348 destroy_cidr_class(struct ClassItem *class)
349 {
350  destroy_cidr_list(&class->list_ipv4);
351  destroy_cidr_list(&class->list_ipv6);
352 }

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)