/[svn]/ircd-hybrid/trunk/src/conf_class.c
ViewVC logotype

Diff of /ircd-hybrid/trunk/src/conf_class.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 8606 by michael, Tue Apr 24 19:48:22 2018 UTC revision 8607 by michael, Mon Oct 29 21:26:54 2018 UTC
# Line 31  Line 31 
31  #include "hostmask.h"  #include "hostmask.h"
32  #include "irc_string.h"  #include "irc_string.h"
33  #include "memory.h"  #include "memory.h"
34    #include "patricia.h"
35    
36    
37  struct ClassItem *class_default;  struct ClassItem *class_default;
# Line 55  class_make(void) Line 56  class_make(void)
56    class->max_total = MAXIMUM_LINKS_DEFAULT;    class->max_total = MAXIMUM_LINKS_DEFAULT;
57    class->max_sendq = DEFAULT_SENDQ;    class->max_sendq = DEFAULT_SENDQ;
58    class->max_recvq = DEFAULT_RECVQ;    class->max_recvq = DEFAULT_RECVQ;
59      class->ip_tree   = patricia_new(PATRICIA_MAXBITS);
60    
61    dlinkAdd(class, &class->node, &class_list);    dlinkAdd(class, &class->node, &class_list);
62    
# Line 68  class_free(struct ClassItem *const class Line 70  class_free(struct ClassItem *const class
70    assert(class->active    == 0);    assert(class->active    == 0);
71    assert(class->ref_count == 0);    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);    dlinkDelete(&class->node, &class_list);
77    xfree(class->name);    xfree(class->name);
78    xfree(class);    xfree(class);
# Line 166  class_delete_marked(void) Line 171  class_delete_marked(void)
171      struct ClassItem *class = node->data;      struct ClassItem *class = node->data;
172    
173      if (class->active == 0 && class->ref_count == 0)      if (class->active == 0 && class->ref_count == 0)
     {  
       destroy_cidr_class(class);  
174        class_free(class);        class_free(class);
     }  
175    }    }
176  }  }
177    
 /*  
  * cidr_limit_reached  
  *  
  * inputs       - int flag allowing over_rule of limits  
  *              - pointer to the ip to be added  
  *              - pointer to the class  
  * output       - non zero if limit reached  
  *                0 if limit not reached  
  * side effects -  
  */  
178  int  int
179  cidr_limit_reached(int over_rule, struct irc_ssaddr *ip, struct ClassItem *class)  class_ip_limit_add(struct ClassItem *class, struct sockaddr *addr, int over_rule)
180  {  {
181    dlink_node *node;    int bitlen;
182    
183    if (class->number_per_cidr == 0)    if (addr->sa_family == AF_INET6)
184      return 0;      bitlen = class->cidr_bitlen_ipv6;
185      else
186        bitlen = class->cidr_bitlen_ipv4;
187    
188    if (ip->ss.ss_family == AF_INET)    if (class->number_per_cidr == 0 || bitlen == 0)
189    {      return 0;
     if (class->cidr_bitlen_ipv4 == 0)  
       return 0;  
190    
191      DLINK_FOREACH(node, class->list_ipv4.head)    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        struct CidrItem *cidr = node->data;      return 1;
   
       if (match_ipv4(ip, &cidr->mask, class->cidr_bitlen_ipv4))  
       {  
         if (!over_rule && (cidr->number_on_this_cidr >= class->number_per_cidr))  
           return -1;  
   
         cidr->number_on_this_cidr++;  
         return 0;  
       }  
     }  
   
     struct CidrItem *cidr = xcalloc(sizeof(*cidr));  
     cidr->number_on_this_cidr = 1;  
     cidr->mask = *ip;  
     mask_addr(&cidr->mask, class->cidr_bitlen_ipv4);  
     dlinkAdd(cidr, &cidr->node, &class->list_ipv4);  
   }  
   else if (class->cidr_bitlen_ipv6 > 0)  
   {  
     DLINK_FOREACH(node, class->list_ipv6.head)  
     {  
       struct CidrItem *cidr = node->data;  
   
       if (match_ipv6(ip, &cidr->mask, class->cidr_bitlen_ipv6))  
       {  
         if (!over_rule && (cidr->number_on_this_cidr >= class->number_per_cidr))  
           return -1;  
   
         cidr->number_on_this_cidr++;  
         return 0;  
       }  
     }  
   
     struct CidrItem *cidr = xcalloc(sizeof(*cidr));  
     cidr->number_on_this_cidr = 1;  
     cidr->mask = *ip;  
     mask_addr(&cidr->mask, class->cidr_bitlen_ipv6);  
     dlinkAdd(cidr, &cidr->node, &class->list_ipv6);  
   }  
194    
195      PATRICIA_DATA_SET(pnode, (((uintptr_t)pnode->data) + 1));
196    return 0;    return 0;
197  }  }
198    
199  /*  int
200   * remove_from_cidr_check  class_ip_limit_remove(struct ClassItem *class, struct sockaddr *addr)
  *  
  * inputs       - pointer to the ip to be removed  
  *              - pointer to the class  
  * output       - NONE  
  * side effects -  
  */  
 void  
 remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)  
201  {  {
202    dlink_node *node, *node_next;    int bitlen;
203    
204    if (aclass->number_per_cidr == 0)    if (addr->sa_family == AF_INET6)
205      return;      bitlen = class->cidr_bitlen_ipv6;
206      else
207        bitlen = class->cidr_bitlen_ipv4;
208    
209    if (ip->ss.ss_family == AF_INET)    if (class->number_per_cidr == 0 || bitlen == 0)
210    {      return 0;
     if (aclass->cidr_bitlen_ipv4 == 0)  
       return;  
211    
212      DLINK_FOREACH_SAFE(node, node_next, aclass->list_ipv4.head)    patricia_node_t *pnode = patricia_try_search_best_addr(class->ip_tree, addr, 0);
213      {    if (pnode == NULL)
214        struct CidrItem *cidr = node->data;      return 0;
215    
216        if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))    PATRICIA_DATA_SET(pnode, (((uintptr_t)pnode->data) - 1));
217        {  
218          cidr->number_on_this_cidr--;    if (((uintptr_t)pnode->data) == 0)
   
         if (cidr->number_on_this_cidr == 0)  
         {  
           dlinkDelete(node, &aclass->list_ipv4);  
           xfree(cidr);  
           return;  
         }  
       }  
     }  
   }  
   else if (aclass->cidr_bitlen_ipv6 > 0)  
219    {    {
220      DLINK_FOREACH_SAFE(node, node_next, aclass->list_ipv6.head)      patricia_remove(class->ip_tree, pnode);
221      {      return 1;
       struct CidrItem *cidr = node->data;  
   
       if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))  
       {  
         cidr->number_on_this_cidr--;  
   
         if (cidr->number_on_this_cidr == 0)  
         {  
           dlinkDelete(node, &aclass->list_ipv6);  
           xfree(cidr);  
           return;  
         }  
       }  
     }  
222    }    }
223    
224      return 0;
225  }  }
226    
227  void  void
228  rebuild_cidr_list(struct ClassItem *class)  class_ip_limit_rebuild(struct ClassItem *class)
229  {  {
230    dlink_node *node;    dlink_node *node;
231    
232    destroy_cidr_class(class);    patricia_clear(class->ip_tree, NULL);
233    
234    DLINK_FOREACH(node, local_client_list.head)    DLINK_FOREACH(node, local_client_list.head)
235    {    {
236      struct Client *client_p = node->data;      struct Client *client_p = node->data;
237      struct MaskItem *conf = client_p->connection->confs.tail->data;      struct MaskItem *conf = client_p->connection->confs.tail->data;
238    
239      if (conf && (conf->type == CONF_CLIENT))      if (conf->type == CONF_CLIENT)
240        if (conf->class == class)        if (conf->class == class)
241          cidr_limit_reached(1, &client_p->ip, class);          class_ip_limit_add(class, (struct sockaddr *)&client_p->ip, 1);
   }  
 }  
   
 /*  
  * destroy_cidr_list  
  *  
  * inputs       - pointer to class dlink list of cidr blocks  
  * output       - none  
  * side effects - completely destroys the class link list of cidr blocks  
  */  
 static void  
 destroy_cidr_list(dlink_list *list)  
 {  
   while (list->head)  
   {  
     struct CidrItem *cidr = list->head->data;  
     dlinkDelete(&cidr->node, list);  
     xfree(cidr);  
242    }    }
243  }  }
   
 /*  
  * destroy_cidr_class  
  *  
  * inputs       - pointer to class  
  * output       - none  
  * side effects - completely destroys the class link list of cidr blocks  
  */  
 void  
 destroy_cidr_class(struct ClassItem *class)  
 {  
   destroy_cidr_list(&class->list_ipv4);  
   destroy_cidr_list(&class->list_ipv6);  
 }  

Legend:
Removed from v.8606  
changed lines
  Added in v.8607

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.28