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

Comparing ircd-hybrid-8/src/hostmask.c (file contents):
Revision 1309 by michael, Sun Mar 25 11:24:18 2012 UTC vs.
Revision 1376 by michael, Sun Apr 29 17:08:42 2012 UTC

# Line 28 | Line 28
28   #include "list.h"
29   #include "conf.h"
30   #include "hostmask.h"
31 – #include "numeric.h"
31   #include "send.h"
32   #include "irc_string.h"
33 + #include "ircd.h"
34  
35 – #ifdef IPV6
36 – static int try_parse_v6_netmask(const char *, struct irc_ssaddr *, int *);
37 – static unsigned long hash_ipv6(struct irc_ssaddr *, int);
38 – #endif
39 – static int try_parse_v4_netmask(const char *, struct irc_ssaddr *, int *);
40 – static unsigned long hash_ipv4(struct irc_ssaddr *, int);
35  
36   #define DigitParse(ch) do { \
37                         if (ch >= '0' && ch <= '9') \
# Line 287 | Line 281 | match_ipv6(struct irc_ssaddr *addr, stru
281    return 0;
282   }
283   #endif
284 +
285   /* int match_ipv4(struct irc_ssaddr *, struct irc_ssaddr *, int)
286   * Input: An IP address, an IP mask, the number of bits in the mask.
287   * Output: if match, -1 else 0
# Line 348 | Line 343 | mask_addr(struct irc_ssaddr *ip, int bit
343   }
344  
345   /* Hashtable stuff...now external as its used in m_stats.c */
346 < struct AddressRec *atable[ATABLE_SIZE];
346 > dlink_list atable[ATABLE_SIZE];
347  
348   void
349   init_host_hash(void)
# Line 361 | Line 356 | init_host_hash(void)
356   * Output: A hash value of the IP address.
357   * Side effects: None
358   */
359 < static unsigned long
359 > static uint32_t
360   hash_ipv4(struct irc_ssaddr *addr, int bits)
361   {
362    if (bits != 0)
363    {
364      struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
365 <    unsigned long av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
365 >    uint32_t av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
366  
367      return (av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1);
368    }
# Line 381 | Line 376 | hash_ipv4(struct irc_ssaddr *addr, int b
376   * Side effects: None
377   */
378   #ifdef IPV6
379 < static unsigned long
379 > static uint32_t
380   hash_ipv6(struct irc_ssaddr *addr, int bits)
381   {
382 <  unsigned long v = 0, n;
382 >  uint32_t v = 0, n;
383    struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
384  
385    for (n = 0; n < 16; n++)
# Line 411 | Line 406 | hash_ipv6(struct irc_ssaddr *addr, int b
406   * Output: The hash of the string between 1 and (TH_MAX-1)
407   * Side-effects: None.
408   */
409 < static int
409 > static uint32_t
410   hash_text(const char *start)
411   {
412    const char *p = start;
413 <  unsigned long h = 0;
413 >  uint32_t h = 0;
414  
415 <  while (*p)
416 <    h = (h << 4) - (h + (unsigned char)ToLower(*p++));
415 >  for (; *p; ++p)
416 >    h = (h << 4) - (h + (unsigned char)ToLower(*p));
417  
418    return h & (ATABLE_SIZE - 1);
419   }
# Line 429 | Line 424 | hash_text(const char *start)
424   *         wildcard in the string.
425   * Side-effects: None.
426   */
427 < static unsigned long
427 > static uint32_t
428   get_mask_hash(const char *text)
429   {
430    const char *hp = "", *p;
# Line 453 | Line 448 | get_mask_hash(const char *text)
448   * should always be true (i.e. aconf->flags & CONF_FLAGS_NEED_PASSWORD == 0)
449   */
450   struct AccessItem *
451 < find_conf_by_address(const char *name, struct irc_ssaddr *addr, int type,
452 <                     int fam, const char *username, const char *password)
451 > find_conf_by_address(const char *name, struct irc_ssaddr *addr, unsigned int type,
452 >                     int fam, const char *username, const char *password, int do_match)
453   {
454 <  unsigned long hprecv = 0;
454 >  unsigned int hprecv = 0;
455 >  dlink_node *ptr = NULL;
456    struct AccessItem *hprec = NULL;
457    struct AddressRec *arec;
458    int b;
459 +  int (*cmpfunc)(const char *, const char *) = do_match ? match : irccmp;
460  
461    if (username == NULL)
462      username = "";
# Line 474 | Line 471 | find_conf_by_address(const char *name, s
471      {
472        for (b = 128; b >= 0; b -= 16)
473        {
474 <        for (arec = atable[hash_ipv6(addr, b)]; arec; arec = arec->next)
474 >        DLINK_FOREACH(ptr, atable[hash_ipv6(addr, b)].head)
475 >        {
476 >          arec = ptr->data;
477 >
478            if (arec->type == (type & ~0x1) &&
479                arec->precedence > hprecv &&
480                arec->masktype == HM_IPV6 &&
481                match_ipv6(addr, &arec->Mask.ipa.addr,
482                           arec->Mask.ipa.bits) &&
483 <              (type & 0x1 || match(arec->username, username)) &&
483 >              (type & 0x1 || cmpfunc(arec->username, username) == do_match) &&
484                (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
485                 match_conf_password(password, arec->aconf)))
486            {
487              hprecv = arec->precedence;
488              hprec = arec->aconf;
489            }
490 +        }
491        }
492      }
493      else
# Line 495 | Line 496 | find_conf_by_address(const char *name, s
496      {
497        for (b = 32; b >= 0; b -= 8)
498        {
499 <        for (arec = atable[hash_ipv4(addr, b)]; arec; arec = arec->next)
499 >        DLINK_FOREACH(ptr, atable[hash_ipv4(addr, b)].head)
500 >        {
501 >          arec = ptr->data;
502 >
503            if (arec->type == (type & ~0x1) &&
504                arec->precedence > hprecv &&
505                arec->masktype == HM_IPV4 &&
506                match_ipv4(addr, &arec->Mask.ipa.addr,
507                           arec->Mask.ipa.bits) &&
508 <              (type & 0x1 || match(arec->username, username)) &&
508 >              (type & 0x1 || cmpfunc(arec->username, username) == do_match) &&
509                (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
510                 match_conf_password(password, arec->aconf)))
511            {
512              hprecv = arec->precedence;
513              hprec = arec->aconf;
514            }
515 +        }
516        }
517      }
518    }
# Line 518 | Line 523 | find_conf_by_address(const char *name, s
523  
524      while (1)
525      {
526 <      for (arec = atable[hash_text(p)]; arec != NULL; arec = arec->next)
527 <        if ((arec->type == (type & ~0x1)) &&
526 >        DLINK_FOREACH(ptr, atable[hash_text(p)].head)
527 >        {
528 >          arec = ptr->data;
529 >          if ((arec->type == (type & ~0x1)) &&
530              arec->precedence > hprecv &&
531              (arec->masktype == HM_HOST) &&
532 <            match(arec->Mask.hostname, name) &&
533 <            (type & 0x1 || match(arec->username, username)) &&
532 >            cmpfunc(arec->Mask.hostname, name) == do_match &&
533 >            (type & 0x1 || cmpfunc(arec->username, username) == do_match) &&
534              (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
535               match_conf_password(password, arec->aconf)))
536          {
537            hprecv = arec->precedence;
538            hprec = arec->aconf;
539          }
540 +      }
541        p = strchr(p, '.');
542        if (p == NULL)
543          break;
544        p++;
545      }
546 <    for (arec = atable[0]; arec; arec = arec->next)
546 >
547 >    DLINK_FOREACH(ptr, atable[0].head)
548 >    {
549 >      arec = ptr->data;
550 >
551        if (arec->type == (type & ~0x1) &&
552            arec->precedence > hprecv &&
553            arec->masktype == HM_HOST &&
554 <          match(arec->Mask.hostname, name) &&
555 <          (type & 0x1 || match(arec->username, username)) &&
554 >          cmpfunc(arec->Mask.hostname, name) == do_match &&
555 >          (type & 0x1 || cmpfunc(arec->username, username) == do_match) &&
556            (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
557             match_conf_password(password, arec->aconf)))
558        {
559          hprecv = arec->precedence;
560          hprec = arec->aconf;
561        }
562 +    }
563    }
564  
565    return hprec;
# Line 566 | Line 579 | find_address_conf(const char *host, cons
579  
580    /* Find the best I-line... If none, return NULL -A1kmm */
581    if ((iconf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
582 <                                    password)) == NULL)
582 >                                    password, 1)) == NULL)
583      return NULL;
584  
585    /* If they are exempt from K-lines, return the best I-line. -A1kmm */
# Line 574 | Line 587 | find_address_conf(const char *host, cons
587      return iconf;
588  
589    /* Find the best K-line... -A1kmm */
590 <  kconf = find_conf_by_address(host, ip, CONF_KILL, aftype, user, NULL);
590 >  kconf = find_conf_by_address(host, ip, CONF_KLINE, aftype, user, NULL, 1);
591  
592    /* If they are K-lined, return the K-line. Otherwise, return the
593     * I-line. -A1kmm */
594    if (kconf != NULL)
595      return kconf;
596  
597 <  kconf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL);
597 >  kconf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL, 1);
598    if (kconf != NULL && !IsConfExemptGline(iconf))
599      return kconf;
600  
# Line 595 | Line 608 | find_gline_conf(const char *host, const
608    struct AccessItem *eline;
609  
610    eline = find_conf_by_address(host, ip, CONF_EXEMPTKLINE, aftype,
611 <                               user, NULL);
611 >                               user, NULL, 1);
612    if (eline != NULL)
613      return eline;
614  
615 <  return find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL);
615 >  return find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL, 1);
616   }
617  
618   /* find_kline_conf
# Line 617 | Line 630 | find_kline_conf(const char *host, const
630    struct AccessItem *eline;
631  
632    eline = find_conf_by_address(host, ip, CONF_EXEMPTKLINE, aftype,
633 <                               user, NULL);
633 >                               user, NULL, 1);
634    if (eline != NULL)
635      return eline;
636  
637 <  return find_conf_by_address(host, ip, CONF_KILL, aftype, user, NULL);
637 >  return find_conf_by_address(host, ip, CONF_KLINE, aftype, user, NULL, 1);
638   }
639  
640   /* struct AccessItem* find_dline_conf(struct irc_ssaddr*, int)
# Line 636 | Line 649 | find_dline_conf(struct irc_ssaddr *addr,
649    struct AccessItem *eline;
650  
651    eline = find_conf_by_address(NULL, addr, CONF_EXEMPTDLINE | 1, aftype,
652 <                               NULL, NULL);
652 >                               NULL, NULL, 1);
653    if (eline != NULL)
654      return eline;
655  
656 <  return find_conf_by_address(NULL, addr, CONF_DLINE | 1, aftype, NULL, NULL);
656 >  return find_conf_by_address(NULL, addr, CONF_DLINE | 1, aftype, NULL, NULL, 1);
657   }
658  
659   /* void add_conf_by_address(int, struct AccessItem *aconf)
# Line 649 | Line 662 | find_dline_conf(struct irc_ssaddr *addr,
662   * Side-effects: Adds this entry to the hash table.
663   */
664   void
665 < add_conf_by_address(int type, struct AccessItem *aconf)
665 > add_conf_by_address(const unsigned int type, struct AccessItem *aconf)
666   {
667    const char *address;
668    const char *username;
669 <  static unsigned long prec_value = 0xFFFFFFFF;
670 <  int masktype, bits;
658 <  unsigned long hv;
669 >  static unsigned int prec_value = 0xFFFFFFFF;
670 >  int bits = 0;
671    struct AddressRec *arec;
672  
673    address = aconf->host;
# Line 668 | Line 680 | add_conf_by_address(int type, struct Acc
680      address = "/NOMATCH!/";
681  
682    arec = MyMalloc(sizeof(struct AddressRec));
683 <  masktype = parse_netmask(address, &arec->Mask.ipa.addr, &bits);
683 >  arec->masktype = parse_netmask(address, &arec->Mask.ipa.addr, &bits);
684    arec->Mask.ipa.bits = bits;
673 –  arec->masktype = masktype;
674 –
675 – #ifdef IPV6
676 –  if (masktype == HM_IPV6)
677 –  {
678 –    /* We have to do this, since we do not re-hash for every bit -A1kmm. */
679 –    bits -= bits % 16;
680 –    arec->next = atable[(hv = hash_ipv6(&arec->Mask.ipa.addr, bits))];
681 –    atable[hv] = arec;
682 –  }
683 –  else
684 – #endif
685 –  if (masktype == HM_IPV4)
686 –  {
687 –    /* We have to do this, since we do not re-hash for every bit -A1kmm. */
688 –    bits -= bits % 8;
689 –    arec->next = atable[(hv = hash_ipv4(&arec->Mask.ipa.addr, bits))];
690 –    atable[hv] = arec;
691 –  }
692 –  else
693 –  {
694 –    arec->Mask.hostname = address;
695 –    arec->next = atable[(hv = get_mask_hash(address))];
696 –    atable[hv] = arec;
697 –  }
698 –
685    arec->username = username;
686    arec->aconf = aconf;
687    arec->precedence = prec_value--;
688    arec->type = type;
689 +
690 +  switch (arec->masktype)
691 +  {
692 +    case HM_IPV4:
693 +      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
694 +      bits -= bits % 8;
695 +      dlinkAdd(arec, &arec->node, &atable[hash_ipv4(&arec->Mask.ipa.addr, bits)]);
696 +      break;
697 + #ifdef IPV6
698 +    case HM_IPV6:
699 +      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
700 +      bits -= bits % 16;
701 +      dlinkAdd(arec, &arec->node, &atable[hash_ipv6(&arec->Mask.ipa.addr, bits)]);
702 +      break;
703 + #endif
704 +    default: /* HM_HOST */
705 +      arec->Mask.hostname = address;
706 +      dlinkAdd(arec, &arec->node, &atable[get_mask_hash(address)]);
707 +      break;
708 +  }
709   }
710  
711   /* void delete_one_address(const char*, struct AccessItem*)
# Line 711 | Line 717 | add_conf_by_address(int type, struct Acc
717   void
718   delete_one_address_conf(const char *address, struct AccessItem *aconf)
719   {
720 <  int masktype, bits;
721 <  unsigned long hv;
722 <  struct AddressRec *arec, *arecl = NULL;
720 >  int bits = 0;
721 >  uint32_t hv = 0;
722 >  dlink_node *ptr = NULL, *ptr_next = NULL;
723    struct irc_ssaddr addr;
724  
725 <  masktype = parse_netmask(address, &addr, &bits);
720 <
721 < #ifdef IPV6
722 <  if (masktype == HM_IPV6)
725 >  switch (parse_netmask(address, &addr, &bits))
726    {
727 <    /* We have to do this, since we do not re-hash for every bit -A1kmm. */
728 <    bits -= bits % 16;
729 <    hv = hash_ipv6(&addr, bits);
730 <  }
731 <  else
727 >    case HM_IPV4:
728 >      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
729 >      bits -= bits % 8;
730 >      hv = hash_ipv4(&addr, bits);
731 >      break;
732 > #ifdef IPV6
733 >    case HM_IPV6:
734 >      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
735 >      bits -= bits % 16;
736 >      hv = hash_ipv6(&addr, bits);
737 >      break;
738   #endif
739 <  if (masktype == HM_IPV4)
740 <  {
741 <    /* We have to do this, since we do not re-hash for every bit -A1kmm. */
733 <    bits -= bits % 8;
734 <    hv = hash_ipv4(&addr, bits);
739 >    default: /* HM_HOST */
740 >      hv = get_mask_hash(address);
741 >      break;
742    }
736 –  else
737 –    hv = get_mask_hash(address);
743  
744 <  for (arec = atable[hv]; arec; arec = arec->next)
744 >  DLINK_FOREACH_SAFE(ptr, ptr_next, atable[hv].head)
745    {
746 +    struct AddressRec *arec = ptr->data;
747 +
748      if (arec->aconf == aconf)
749      {
750 <      if (arecl)
744 <        arecl->next = arec->next;
745 <      else
746 <        atable[hv] = arec->next;
747 <
750 >      dlinkDelete(&arec->node, &atable[hv]);
751        aconf->status |= CONF_ILLEGAL;
752  
753 <      if (aconf->clients == 0)
753 >      if (!aconf->clients)
754          free_access_item(aconf);
755  
756        MyFree(arec);
757        return;
758      }
756 –    arecl = arec;
759    }
760   }
761  
# Line 767 | Line 769 | delete_one_address_conf(const char *addr
769   void
770   clear_out_address_conf(void)
771   {
772 <  int i;
773 <  struct AddressRec *arec;
772 <  struct AddressRec *last_arec;
773 <  struct AddressRec *next_arec;
772 >  unsigned int i = 0;
773 >  dlink_node *ptr = NULL, *ptr_next = NULL;
774  
775 <  for (i = 0; i < ATABLE_SIZE; i++)
775 >  for (i = 0; i < ATABLE_SIZE; ++i)
776    {
777 <    last_arec = NULL;
778 <
779 <    for (arec = atable[i]; arec; arec = next_arec)
777 >    DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
778      {
779 +      struct AddressRec *arec = ptr->data;
780 +
781        /* We keep the temporary K-lines and destroy the
782         * permanent ones, just to be confusing :) -A1kmm
783         */  
784 <      next_arec = arec->next;
785 <
786 <      if (arec->aconf->flags & CONF_FLAGS_TEMPORARY)
787 <      {
788 <        last_arec = arec;
789 <      }
790 <      else  
784 >      if (!(arec->aconf->flags & CONF_FLAGS_TEMPORARY))
785        {
786 +        dlinkDelete(&arec->node, &atable[i]);
787          /* unlink it from link list - Dianora */
793 –  
794 –        if (last_arec == NULL)
795 –        {
796 –          atable[i] = next_arec;
797 –        }
798 –        else
799 –        {
800 –          last_arec->next = next_arec;
801 –        }
802 –
788          arec->aconf->status |= CONF_ILLEGAL;
789  
790 <        if (arec->aconf->clients == 0)
790 >        if (!arec->aconf->clients)
791            free_access_item(arec->aconf);
792          MyFree(arec);
793        }
# Line 810 | Line 795 | clear_out_address_conf(void)
795    }
796   }
797  
798 < /*
799 < * show_iline_prefix()
815 < *
816 < * inputs       - pointer to struct Client requesting output
817 < *              - pointer to struct AccessItem
818 < *              - name to which iline prefix will be prefixed to
819 < * output       - pointer to static string with prefixes listed in ascii form
820 < * side effects - NONE
821 < */
822 < char *
823 < show_iline_prefix(struct Client *sptr, struct AccessItem *aconf, const char *name)
824 < {
825 <  static char prefix_of_host[USERLEN + 14];
826 <  char *prefix_ptr = prefix_of_host;
827 <
828 <  if (IsNoTilde(aconf))
829 <    *prefix_ptr++ = '-';
830 <  if (IsLimitIp(aconf))
831 <    *prefix_ptr++ = '!';
832 <  if (IsNeedIdentd(aconf))
833 <    *prefix_ptr++ = '+';
834 <  if (!IsNeedPassword(aconf))
835 <    *prefix_ptr++ = '&';
836 <  if (IsConfExemptResv(aconf))
837 <    *prefix_ptr++ = '$';
838 <  if (IsNoMatchIp(aconf))
839 <    *prefix_ptr++ = '%';
840 <  if (IsConfDoSpoofIp(aconf))
841 <    *prefix_ptr++ = '=';
842 <  if (MyOper(sptr) && IsConfExemptKline(aconf))
843 <    *prefix_ptr++ = '^';
844 <  if (MyOper(sptr) && IsConfExemptGline(aconf))
845 <    *prefix_ptr++ = '_';
846 <  if (MyOper(sptr) && IsConfExemptLimits(aconf))
847 <    *prefix_ptr++ = '>';
848 <  if (IsConfCanFlood(aconf))
849 <    *prefix_ptr++ = '|';
850 <
851 <  strlcpy(prefix_ptr, name, USERLEN+1);
852 <
853 <  return prefix_of_host;
854 < }
855 <
856 < /* report_auth()
857 < *
858 < * Inputs: pointer to client to report to
859 < * Output: None
860 < * Side effects: Reports configured auth{} blocks to client_p
861 < */
862 < void
863 < report_auth(struct Client *client_p)
798 > static void
799 > hostmask_send_expiration(struct AddressRec *arec)
800   {
801 <  struct AddressRec *arec;
866 <  struct ConfItem *conf;
867 <  struct AccessItem *aconf;
868 <  int i;
869 <
870 <  for (i = 0; i < ATABLE_SIZE; i++)
871 <  {
872 <    for (arec = atable[i]; arec; arec = arec->next)
873 <    {
874 <      if (arec->type == CONF_CLIENT)
875 <      {
876 <        aconf = arec->aconf;
801 >  char ban_type = '\0';
802  
803 <        if (!MyOper(client_p) && IsConfDoSpoofIp(aconf))
804 <          continue;
803 >  if (!ConfigFileEntry.tkline_expire_notices)
804 >    return;
805  
806 <        conf = unmap_conf_item(aconf);
807 <
808 <        /* We are doing a partial list, based on what matches the u@h of the
809 <         * sender, so prepare the strings for comparing --fl_
810 <         */
811 <        if (ConfigFileEntry.hide_spoof_ips)
812 <          sendto_one(client_p, form_str(RPL_STATSILINE), me.name,
813 <                     client_p->name, 'I',
814 <                     conf->name == NULL ? "*" : conf->name,
815 <                     show_iline_prefix(client_p, aconf, aconf->user),
816 <                     IsConfDoSpoofIp(aconf) ? "255.255.255.255" :
892 <                     aconf->host, aconf->port,
893 <                     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
894 <                    
895 <        else
896 <          sendto_one(client_p, form_str(RPL_STATSILINE), me.name,
897 <                     client_p->name, 'I',
898 <                     conf->name == NULL ? "*" : conf->name,
899 <                     show_iline_prefix(client_p, aconf, aconf->user),
900 <                     aconf->host, aconf->port,
901 <                     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
902 <      }
903 <    }
806 >  switch (arec->type)
807 >  {
808 >    case CONF_KLINE:
809 >      ban_type = 'K';
810 >      break;
811 >    case CONF_DLINE:
812 >      ban_type = 'D';
813 >      break;
814 >    case CONF_GLINE:
815 >      ban_type = 'G';
816 >      break;
817    }
818 +  
819 +  sendto_realops_flags(UMODE_ALL, L_ALL,
820 +                       "Temporary %c-line for [%s@%s] expired", ban_type,
821 +                       (arec->aconf->user) ? arec->aconf->user : "*",
822 +                       (arec->aconf->host) ? arec->aconf->host : "*");
823   }
824  
907 – /* report_Klines()
908 – * Inputs: Client to report to,
909 – *         type(==0 for perm, !=0 for temporary)
910 – *         mask
911 – * Output: None
912 – * Side effects: Reports configured K(or k)-lines to client_p.
913 – */
825   void
826 < report_Klines(struct Client *client_p, int tkline)
826 > hostmask_expire_temporary(void)
827   {
828 <  struct AddressRec *arec = NULL;
829 <  struct AccessItem *aconf = NULL;
919 <  int i;
920 <  const char *p = NULL;
828 >  unsigned int i = 0;
829 >  dlink_node *ptr = NULL, *ptr_next = NULL;
830  
831 <  if (tkline)
923 <    p = "k";
924 <  else
925 <    p = "K";
926 <
927 <  for (i = 0; i < ATABLE_SIZE; i++)
831 >  for (i = 0; i < ATABLE_SIZE; ++i)
832    {
833 <    for (arec = atable[i]; arec; arec = arec->next)
833 >    DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
834      {
835 <      if (arec->type == CONF_KILL)
835 >      struct AddressRec *arec = ptr->data;
836 >
837 >      if (!IsConfTemporary(arec->aconf) || arec->aconf->hold > CurrentTime)
838 >        continue;
839 >
840 >      switch (arec->type)
841        {
842 <        if ((tkline && !((aconf = arec->aconf)->flags & CONF_FLAGS_TEMPORARY)) ||
843 <            (!tkline && ((aconf = arec->aconf)->flags & CONF_FLAGS_TEMPORARY)))
844 <          continue;
845 <
846 <        if (HasUMode(client_p, UMODE_OPER))
847 <          sendto_one(client_p, form_str(RPL_STATSKLINE), me.name,
848 <                     client_p->name, p, aconf->host, aconf->user,
849 <                     aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
850 <        else
942 <          sendto_one(client_p, form_str(RPL_STATSKLINE), me.name,
943 <                     client_p->name, p, aconf->host, aconf->user,
944 <                     aconf->reason, "");
842 >        case CONF_KLINE:
843 >        case CONF_DLINE:
844 >        case CONF_GLINE:
845 >          hostmask_send_expiration(arec);
846 >
847 >          dlinkDelete(&arec->node, &atable[i]);
848 >          free_access_item(arec->aconf);
849 >          MyFree(arec);
850 >          break;
851        }
852      }
853    }

Diff Legend

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