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

Comparing ircd-hybrid/trunk/src/conf.c (file contents):
Revision 4313 by michael, Thu Jul 31 18:50:11 2014 UTC vs.
Revision 4319 by michael, Fri Aug 1 16:48:38 2014 UTC

# Line 75 | Line 75 | extern int yyparse(); /* defined in y.ta
75   static void read_conf(FILE *);
76   static void clear_out_old_conf(void);
77   static void expire_tklines(dlink_list *);
78 < static void garbage_collect_ip_entries(void);
79 < static int hash_ip(struct irc_ssaddr *);
78 > static void ipcache_remove_expired_entries(void *);
79 > static uint32_t hash_ip(const struct irc_ssaddr *);
80   static int verify_access(struct Client *);
81   static int attach_iline(struct Client *, struct MaskItem *);
82   static struct ip_entry *find_or_add_ip(struct irc_ssaddr *);
# Line 92 | Line 92 | static int find_user_host(struct Client
92  
93   struct ip_entry
94   {
95 +  dlink_node node;                /**< Doubly linked list node. */
96    struct irc_ssaddr ip;
97 <  unsigned int count;  /**< Number of registered users using this IP */
97 >  unsigned int count;             /**< Number of registered users using this IP */
98    unsigned int connection_count;  /**< Number of connections from this IP in the last throttle_time duration */
99 <  time_t last_attempt;  /**< The last time someone connected from this IP */
99 <  struct ip_entry *next;
99 >  time_t last_attempt;            /**< The last time someone connected from this IP */
100   };
101  
102 < static struct ip_entry *ip_hash_table[IP_HASH_SIZE];
102 > static dlink_list ip_hash_table[IP_HASH_SIZE];
103   static mp_pool_t *ip_entry_pool = NULL;
104 static int ip_entries_count = 0;
104  
105  
106   /* conf_dns_callback()
# Line 427 | Line 426 | attach_iline(struct Client *client_p, st
426   *                      - clear the ip hash table
427   */
428   void
429 < init_ip_hash_table(void)
429 > ipcache_init(void)
430   {
431 +  static struct event event_expire_ipcache =
432 +  {
433 +    .name = "ipcache_remove_expired_entries",
434 +    .handler = ipcache_remove_expired_entries,
435 +    .when = 123
436 +  };
437 +
438 +  event_add(&event_expire_ipcache, NULL);
439    ip_entry_pool = mp_pool_new(sizeof(struct ip_entry), MP_CHUNK_SIZE_IP_ENTRY);
433  memset(ip_hash_table, 0, sizeof(ip_hash_table));
440   }
441  
442   /* find_or_add_ip()
# Line 443 | Line 449 | init_ip_hash_table(void)
449   * count set to 0.
450   */
451   static struct ip_entry *
452 < find_or_add_ip(struct irc_ssaddr *ip_in)
452 > find_or_add_ip(struct irc_ssaddr *addr)
453   {
454 <  struct ip_entry *ptr, *newptr;
455 <  int hash_index = hash_ip(ip_in), res;
456 <  struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
454 >  dlink_node *ptr = NULL;
455 >  struct ip_entry *iptr = NULL;
456 >  uint32_t hash_index = hash_ip(addr);
457 >  int res = 0;
458 >  struct sockaddr_in *v4 = (struct sockaddr_in *)addr, *ptr_v4;
459   #ifdef IPV6
460 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
460 >  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr, *ptr_v6;
461   #endif
462  
463 <  for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
463 >  DLINK_FOREACH(ptr, ip_hash_table[hash_index].head)
464    {
465 +    iptr = ptr->data;
466   #ifdef IPV6
467 <    if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
467 >    if (iptr->ip.ss.ss_family != addr->ss.ss_family)
468        continue;
469 <    if (ip_in->ss.ss_family == AF_INET6)
469 >
470 >    if (addr->ss.ss_family == AF_INET6)
471      {
472 <      ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
472 >      ptr_v6 = (struct sockaddr_in6 *)&iptr->ip;
473        res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
474      }
475      else
476   #endif
477      {
478 <      ptr_v4 = (struct sockaddr_in *)&ptr->ip;
478 >      ptr_v4 = (struct sockaddr_in *)&iptr->ip;
479        res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
480      }
481 +
482      if (res == 0)
483 <    {
473 <      /* Found entry already in hash, return it. */
474 <      return ptr;
475 <    }
483 >      return iptr;  /* Found entry already in hash, return it. */
484    }
485  
486 <  if (ip_entries_count >= 2 * hard_fdlimit)
487 <    garbage_collect_ip_entries();
480 <
481 <  newptr = mp_pool_get(ip_entry_pool);
482 <
483 <  ip_entries_count++;
484 <  memcpy(&newptr->ip, ip_in, sizeof(struct irc_ssaddr));
486 >  iptr = mp_pool_get(ip_entry_pool);
487 >  memcpy(&iptr->ip, addr, sizeof(struct irc_ssaddr));
488  
489 <  newptr->next = ip_hash_table[hash_index];
487 <  ip_hash_table[hash_index] = newptr;
489 >  dlinkAdd(iptr, &iptr->node, &atable[hash_index]);
490  
491 <  return newptr;
491 >  return iptr;
492   }
493  
494   /* remove_one_ip()
# Line 499 | Line 501 | find_or_add_ip(struct irc_ssaddr *ip_in)
501   *                 the struct ip_entry is returned to the ip_entry_heap
502   */
503   void
504 < remove_one_ip(struct irc_ssaddr *ip_in)
504 > remove_one_ip(struct irc_ssaddr *addr)
505   {
506 <  struct ip_entry *ptr;
507 <  struct ip_entry *last_ptr = NULL;
508 <  int hash_index = hash_ip(ip_in), res;
509 <  struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
506 >  dlink_node *ptr = NULL;
507 >  uint32_t hash_index = hash_ip(addr);
508 >  int res = 0;
509 >  struct sockaddr_in *v4 = (struct sockaddr_in *)addr, *ptr_v4;
510   #ifdef IPV6
511 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
511 >  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr, *ptr_v6;
512   #endif
513  
514 <  for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
514 >  DLINK_FOREACH(ptr, ip_hash_table[hash_index].head)
515    {
516 +    struct ip_entry *iptr = ptr->data;
517   #ifdef IPV6
518 <    if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
518 >    if (iptr->ip.ss.ss_family != addr->ss.ss_family)
519        continue;
520 <    if (ip_in->ss.ss_family == AF_INET6)
520 >    if (addr->ss.ss_family == AF_INET6)
521      {
522 <      ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
522 >      ptr_v6 = (struct sockaddr_in6 *)&iptr->ip;
523        res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
524      }
525      else
526   #endif
527      {
528 <      ptr_v4 = (struct sockaddr_in *)&ptr->ip;
528 >      ptr_v4 = (struct sockaddr_in *)&iptr->ip;
529        res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
530      }
531 +
532      if (res)
533        continue;
534 <    if (ptr->count > 0)
531 <      ptr->count--;
532 <    if (ptr->count == 0 &&
533 <        (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
534 <    {
535 <      if (last_ptr != NULL)
536 <        last_ptr->next = ptr->next;
537 <      else
538 <        ip_hash_table[hash_index] = ptr->next;
534 >    assert(iptr->count > 0);
535  
536 <      mp_pool_release(ptr);
537 <      ip_entries_count--;
536 >    if (--iptr->count == 0 &&
537 >        (CurrentTime - iptr->last_attempt) >= ConfigFileEntry.throttle_time)
538 >    {
539 >      dlinkDelete(&iptr->node, &ip_hash_table[hash_index]);
540 >      mp_pool_release(iptr);
541        return;
542      }
544    last_ptr = ptr;
543    }
544   }
545  
# Line 551 | Line 549 | remove_one_ip(struct irc_ssaddr *ip_in)
549   * output       - integer value used as index into hash table
550   * side effects - hopefully, none
551   */
552 < static int
553 < hash_ip(struct irc_ssaddr *addr)
552 > static uint32_t
553 > hash_ip(const struct irc_ssaddr *addr)
554   {
555    if (addr->ss.ss_family == AF_INET)
556    {
557 <    struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
558 <    int hash;
561 <    uint32_t ip;
557 >    const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
558 >    uint32_t hash = 0, ip = ntohl(v4->sin_addr.s_addr);
559  
560 <    ip   = ntohl(v4->sin_addr.s_addr);
564 <    hash = ((ip >> 12) + ip) & (IP_HASH_SIZE-1);
560 >    hash = ((ip >> 12) + ip) & (IP_HASH_SIZE - 1);
561      return hash;
562    }
563   #ifdef IPV6
564    else
565    {
566 <    int hash;
567 <    struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
572 <    uint32_t *ip = (uint32_t *)&v6->sin6_addr.s6_addr;
566 >    const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
567 >    uint32_t hash = 0, *ip = (uint32_t *)&v6->sin6_addr.s6_addr;
568  
569      hash  = ip[0] ^ ip[3];
570      hash ^= hash >> 16;
# Line 595 | Line 590 | hash_ip(struct irc_ssaddr *addr)
590   void
591   count_ip_hash(unsigned int *number_ips_stored, uint64_t *mem_ips_stored)
592   {
598  struct ip_entry *ptr;
599
593    *number_ips_stored = 0;
594    *mem_ips_stored    = 0;
595  
596    for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)
597    {
598 <    for (ptr = ip_hash_table[i]; ptr; ptr = ptr->next)
599 <    {
607 <      *number_ips_stored += 1;
608 <      *mem_ips_stored += sizeof(struct ip_entry);
609 <    }
598 >    *number_ips_stored += dlink_list_length(&ip_hash_table[i]);
599 >    *mem_ips_stored += dlink_list_length(&ip_hash_table[i]) * sizeof(struct ip_entry);
600    }
601   }
602  
# Line 617 | Line 607 | count_ip_hash(unsigned int *number_ips_s
607   * side effects - free up all ip entries with no connections
608   */
609   static void
610 < garbage_collect_ip_entries(void)
610 > ipcache_remove_expired_entries(void *unused)
611   {
612 <  struct ip_entry *ptr;
623 <  struct ip_entry *last_ptr;
624 <  struct ip_entry *next_ptr;
612 >  dlink_node *ptr = NULL;
613  
614    for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)
615    {
616 <    last_ptr = NULL;
629 <
630 <    for (ptr = ip_hash_table[i]; ptr; ptr = next_ptr)
616 >    DLINK_FOREACH(ptr, ip_hash_table[i].head)
617      {
618 <      next_ptr = ptr->next;
618 >      struct ip_entry *iptr = ptr->data;
619  
620 <      if (ptr->count == 0 &&
621 <          (CurrentTime - ptr->last_attempt) >= ConfigFileEntry.throttle_time)
620 >      if (iptr->count == 0 &&
621 >          (CurrentTime - iptr->last_attempt) >= ConfigFileEntry.throttle_time)
622        {
623 <        if (last_ptr != NULL)
624 <          last_ptr->next = ptr->next;
639 <        else
640 <          ip_hash_table[i] = ptr->next;
641 <        mp_pool_release(ptr);
642 <        ip_entries_count--;
623 >        dlinkDelete(&iptr->node, &ip_hash_table[i]);
624 >        mp_pool_release(iptr);
625        }
644      else
645        last_ptr = ptr;
626      }
627    }
628   }

Diff Legend

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