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/trunk/src/hostmask.c (file contents):
Revision 1628 by michael, Thu Nov 1 21:08:56 2012 UTC vs.
Revision 3005 by michael, Wed Feb 19 10:40:15 2014 UTC

# Line 1 | Line 1
1   /*
2 < *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 < *  hostmask.c: Code to efficiently find IP & hostmask based configs.
2 > *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (C) 2005 by the past and present ircd coders, and others.
4 > *  Copyright (c) 2001-2014 ircd-hybrid development team
5   *
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
# Line 18 | Line 17
17   *  along with this program; if not, write to the Free Software
18   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
19   *  USA
20 < *
21 < *  $Id$
20 > */
21 >
22 > /*! \file hostmask.c
23 > * \brief Code to efficiently find IP & hostmask based configs.
24 > * \version $Id$
25   */
26  
27   #include "stdinc.h"
# Line 51 | Line 53
53   * Side effects: None
54   * Comments: Called from parse_netmask
55   */
56 < /* Fixed so ::/0 (any IPv6 address) is valid
56 > /* Fixed so ::/0 (any IPv6 address) is valid
57     Also a bug in DigitParse above.
58     -Gozem 2002-07-19 gozem@linux.nu
59   */
# Line 71 | Line 73 | try_parse_v6_netmask(const char *text, s
73    struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
74  
75    for (p = text; (c = *p); p++)
76 +  {
77      if (IsXDigit(c))
78      {
79        if (nyble == 0)
# Line 119 | Line 122 | try_parse_v6_netmask(const char *text, s
122      }
123      else
124        return HM_HOST;
125 +  }
126  
127    d[dp] = d[dp] >> 4 * nyble;
128  
# Line 180 | Line 184 | try_parse_v4_netmask(const char *text, s
184    digits[n++] = text;
185  
186    for (p = text; (c = *p); p++)
187 +  {
188      if (c >= '0' && c <= '9')   /* empty */
189        ;
190      else if (c == '.')
# Line 202 | Line 207 | try_parse_v4_netmask(const char *text, s
207        char *after;
208        bits = strtoul(p + 1, &after, 10);
209  
210 <      if (!bits || *after)
210 >      if (bits < 0 || *after)
211          return HM_HOST;
212        if (bits > n * 8)
213          return HM_HOST;
# Line 211 | Line 216 | try_parse_v4_netmask(const char *text, s
216      }
217      else
218        return HM_HOST;
219 +  }
220  
221    if (n < 4 && bits == 0)
222      bits = n * 8;
# Line 247 | Line 253 | try_parse_v4_netmask(const char *text, s
253   int
254   parse_netmask(const char *text, struct irc_ssaddr *addr, int *b)
255   {
256 +  if (strchr(text, '.'))
257 +    return try_parse_v4_netmask(text, addr, b);
258   #ifdef IPV6
259    if (strchr(text, ':'))
260      return try_parse_v6_netmask(text, addr, b);
261   #endif
254  if (strchr(text, '.'))
255    return try_parse_v4_netmask(text, addr, b);
262    return HM_HOST;
263   }
264  
# Line 357 | Line 363 | init_host_hash(void)
363   * Side effects: None
364   */
365   static uint32_t
366 < hash_ipv4(struct irc_ssaddr *addr, int bits)
366 > hash_ipv4(const struct irc_ssaddr *addr, int bits)
367   {
368    if (bits != 0)
369    {
370 <    struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
370 >    const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
371      uint32_t av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
372  
373      return (av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1);
# Line 377 | Line 383 | hash_ipv4(struct irc_ssaddr *addr, int b
383   */
384   #ifdef IPV6
385   static uint32_t
386 < hash_ipv6(struct irc_ssaddr *addr, int bits)
386 > hash_ipv6(const struct irc_ssaddr *addr, int bits)
387   {
388    uint32_t v = 0, n;
389 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
389 >  const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
390  
391    for (n = 0; n < 16; n++)
392    {
# Line 413 | Line 419 | hash_text(const char *start)
419    uint32_t h = 0;
420  
421    for (; *p; ++p)
422 <    h = (h << 4) - (h + (unsigned char)ToLower(*p));
422 >    h = (h << 4) - (h + ToLower(*p));
423  
424    return h & (ATABLE_SIZE - 1);
425   }
# Line 437 | Line 443 | get_mask_hash(const char *text)
443    return hash_text(text);
444   }
445  
446 < /* struct AccessItem *find_conf_by_address(const char *, struct irc_ssaddr *,
446 > /* struct MaskItem *find_conf_by_address(const char *, struct irc_ssaddr *,
447   *                                         int type, int fam, const char *username)
448   * Input: The hostname, the address, the type of mask to find, the address
449   *        family, the username.
# Line 445 | Line 451 | get_mask_hash(const char *text)
451   * Side-effects: None
452   * Note: Setting bit 0 of the type means that the username is ignored.
453   * Warning: IsNeedPassword for everything that is not an auth{} entry
454 < * should always be true (i.e. aconf->flags & CONF_FLAGS_NEED_PASSWORD == 0)
454 > * should always be true (i.e. conf->flags & CONF_FLAGS_NEED_PASSWORD == 0)
455   */
456 < struct AccessItem *
456 > struct MaskItem *
457   find_conf_by_address(const char *name, struct irc_ssaddr *addr, unsigned int type,
458                       int fam, const char *username, const char *password, int do_match)
459   {
460    unsigned int hprecv = 0;
461    dlink_node *ptr = NULL;
462 <  struct AccessItem *hprec = NULL;
463 <  struct AddressRec *arec;
462 >  struct MaskItem *hprec = NULL;
463 >  struct AddressRec *arec = NULL;
464    int b;
465    int (*cmpfunc)(const char *, const char *) = do_match ? match : irccmp;
466  
461  if (username == NULL)
462    username = "";
463  if (password == NULL)
464    password = "";
465
467    if (addr)
468    {
469      /* Check for IPV6 matches... */
# Line 473 | Line 474 | find_conf_by_address(const char *name, s
474        {
475          DLINK_FOREACH(ptr, atable[hash_ipv6(addr, b)].head)
476          {
477 <          arec = ptr->data;
477 >          arec = ptr->data;
478  
479 <          if (arec->type == (type & ~0x1) &&
479 >          if ((arec->type == type) &&
480                arec->precedence > hprecv &&
481                arec->masktype == HM_IPV6 &&
482                match_ipv6(addr, &arec->Mask.ipa.addr,
483                           arec->Mask.ipa.bits) &&
484 <              (type & 0x1 || cmpfunc(arec->username, username) == do_match) &&
485 <              (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
486 <               match_conf_password(password, arec->aconf)))
484 >              (!username || !cmpfunc(arec->username, username)) &&
485 >              (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
486 >               match_conf_password(password, arec->conf)))
487            {
488              hprecv = arec->precedence;
489 <            hprec = arec->aconf;
489 >            hprec = arec->conf;
490            }
491          }
492        }
# Line 500 | Line 501 | find_conf_by_address(const char *name, s
501          {
502            arec = ptr->data;
503  
504 <          if (arec->type == (type & ~0x1) &&
504 >          if ((arec->type == type) &&
505                arec->precedence > hprecv &&
506                arec->masktype == HM_IPV4 &&
507                match_ipv4(addr, &arec->Mask.ipa.addr,
508                           arec->Mask.ipa.bits) &&
509 <              (type & 0x1 || cmpfunc(arec->username, username) == do_match) &&
510 <              (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
511 <               match_conf_password(password, arec->aconf)))
509 >              (!username || !cmpfunc(arec->username, username)) &&
510 >              (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
511 >               match_conf_password(password, arec->conf)))
512            {
513              hprecv = arec->precedence;
514 <            hprec = arec->aconf;
514 >            hprec = arec->conf;
515            }
516          }
517        }
# Line 526 | Line 527 | find_conf_by_address(const char *name, s
527          DLINK_FOREACH(ptr, atable[hash_text(p)].head)
528          {
529            arec = ptr->data;
530 <          if ((arec->type == (type & ~0x1)) &&
530 >          if ((arec->type == type) &&
531              arec->precedence > hprecv &&
532              (arec->masktype == HM_HOST) &&
533 <            cmpfunc(arec->Mask.hostname, name) == do_match &&
534 <            (type & 0x1 || cmpfunc(arec->username, username) == do_match) &&
535 <            (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
536 <             match_conf_password(password, arec->aconf)))
533 >            !cmpfunc(arec->Mask.hostname, name) &&
534 >            (!username || !cmpfunc(arec->username, username)) &&
535 >            (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
536 >             match_conf_password(password, arec->conf)))
537          {
538            hprecv = arec->precedence;
539 <          hprec = arec->aconf;
539 >          hprec = arec->conf;
540          }
541        }
542        p = strchr(p, '.');
# Line 548 | Line 549 | find_conf_by_address(const char *name, s
549      {
550        arec = ptr->data;
551  
552 <      if (arec->type == (type & ~0x1) &&
552 >      if (arec->type == type &&
553            arec->precedence > hprecv &&
554            arec->masktype == HM_HOST &&
555 <          cmpfunc(arec->Mask.hostname, name) == do_match &&
556 <          (type & 0x1 || cmpfunc(arec->username, username) == do_match) &&
557 <          (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
558 <           match_conf_password(password, arec->aconf)))
555 >          !cmpfunc(arec->Mask.hostname, name) &&
556 >          (!username || !cmpfunc(arec->username, username)) &&
557 >          (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
558 >           match_conf_password(password, arec->conf)))
559        {
560          hprecv = arec->precedence;
561 <        hprec = arec->aconf;
561 >        hprec = arec->conf;
562        }
563      }
564    }
# Line 565 | Line 566 | find_conf_by_address(const char *name, s
566    return hprec;
567   }
568  
569 < /* struct AccessItem* find_address_conf(const char*, const char*,
569 > /* struct MaskItem* find_address_conf(const char*, const char*,
570   *                                     struct irc_ssaddr*, int, char *);
571   * Input: The hostname, username, address, address family.
572 < * Output: The applicable AccessItem.
572 > * Output: The applicable MaskItem.
573   * Side-effects: None
574   */
575 < struct AccessItem *
575 > struct MaskItem *
576   find_address_conf(const char *host, const char *user,
577                    struct irc_ssaddr *ip, int aftype, char *password)
578   {
579 <  struct AccessItem *iconf, *kconf;
579 >  struct MaskItem *authcnf = NULL, *killcnf = NULL;
580  
581    /* Find the best auth{} block... If none, return NULL -A1kmm */
582 <  if ((iconf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
583 <                                    password, 1)) == NULL)
582 >  if ((authcnf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
583 >                                      password, 1)) == NULL)
584      return NULL;
585  
586    /* If they are exempt from K-lines, return the best auth{} block. -A1kmm */
587 <  if (IsConfExemptKline(iconf))
588 <    return iconf;
587 >  if (IsConfExemptKline(authcnf))
588 >    return authcnf;
589  
590    /* Find the best K-line... -A1kmm */
591 <  kconf = find_conf_by_address(host, ip, CONF_KLINE, aftype, user, NULL, 1);
591 >  killcnf = find_conf_by_address(host, ip, CONF_KLINE, aftype, user, NULL, 1);
592  
593    /*
594     * If they are K-lined, return the K-line. Otherwise, return the
595     * auth{} block. -A1kmm
596     */
597 <  if (kconf != NULL)
598 <    return kconf;
597 >  if (killcnf != NULL)
598 >    return killcnf;
599 >
600 >  if (IsConfExemptGline(authcnf))
601 >    return authcnf;
602  
603 <  kconf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL, 1);
604 <  if (kconf != NULL && !IsConfExemptGline(iconf))
605 <    return kconf;
603 >  killcnf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL, 1);
604 >  if (killcnf != NULL)
605 >    return killcnf;
606  
607 <  return iconf;
607 >  return authcnf;
608   }
609  
610 < /* struct AccessItem* find_dline_conf(struct irc_ssaddr*, int)
610 > /* struct MaskItem* find_dline_conf(struct irc_ssaddr*, int)
611   *
612   * Input:       An address, an address family.
613   * Output:      The best matching D-line or exempt line.
614   * Side effects: None.
615   */
616 < struct AccessItem *
616 > struct MaskItem *
617   find_dline_conf(struct irc_ssaddr *addr, int aftype)
618   {
619 <  struct AccessItem *eline;
619 >  struct MaskItem *eline;
620  
621 <  eline = find_conf_by_address(NULL, addr, CONF_EXEMPTDLINE | 1, aftype,
618 <                               NULL, NULL, 1);
621 >  eline = find_conf_by_address(NULL, addr, CONF_EXEMPT, aftype, NULL, NULL, 1);
622    if (eline != NULL)
623      return eline;
624  
625 <  return find_conf_by_address(NULL, addr, CONF_DLINE | 1, aftype, NULL, NULL, 1);
625 >  return find_conf_by_address(NULL, addr, CONF_DLINE, aftype, NULL, NULL, 1);
626   }
627  
628 < /* void add_conf_by_address(int, struct AccessItem *aconf)
629 < * Input:
628 > /* void add_conf_by_address(int, struct MaskItem *aconf)
629 > * Input:
630   * Output: None
631   * Side-effects: Adds this entry to the hash table.
632   */
633 < void
634 < add_conf_by_address(const unsigned int type, struct AccessItem *aconf)
633 > struct AddressRec *
634 > add_conf_by_address(const unsigned int type, struct MaskItem *conf)
635   {
636 <  const char *address;
637 <  const char *username;
636 >  const char *hostname = conf->host;
637 >  const char *username = conf->user;
638    static unsigned int prec_value = 0xFFFFFFFF;
639    int bits = 0;
640 <  struct AddressRec *arec;
640 >  struct AddressRec *arec = NULL;
641  
642 <  address = aconf->host;
640 <  username = aconf->user;
641 <
642 <  assert(type != 0);
643 <  assert(aconf != NULL);
644 <
645 <  if (EmptyString(address))
646 <    address = "/NOMATCH!/";
642 >  assert(type && !EmptyString(hostname));
643  
644    arec = MyMalloc(sizeof(struct AddressRec));
645 <  arec->masktype = parse_netmask(address, &arec->Mask.ipa.addr, &bits);
645 >  arec->masktype = parse_netmask(hostname, &arec->Mask.ipa.addr, &bits);
646    arec->Mask.ipa.bits = bits;
647    arec->username = username;
648 <  arec->aconf = aconf;
648 >  arec->conf = conf;
649    arec->precedence = prec_value--;
650    arec->type = type;
651  
# Line 668 | Line 664 | add_conf_by_address(const unsigned int t
664        break;
665   #endif
666      default: /* HM_HOST */
667 <      arec->Mask.hostname = address;
668 <      dlinkAdd(arec, &arec->node, &atable[get_mask_hash(address)]);
667 >      arec->Mask.hostname = hostname;
668 >      dlinkAdd(arec, &arec->node, &atable[get_mask_hash(hostname)]);
669        break;
670    }
671 +
672 +  return arec;
673   }
674  
675 < /* void delete_one_address(const char*, struct AccessItem*)
676 < * Input: An address string, the associated AccessItem.
675 > /* void delete_one_address(const char*, struct MaskItem*)
676 > * Input: An address string, the associated MaskItem.
677   * Output: None
678 < * Side effects: Deletes an address record. Frees the AccessItem if there
678 > * Side effects: Deletes an address record. Frees the MaskItem if there
679   *               is nothing referencing it, sets it as illegal otherwise.
680   */
681   void
682 < delete_one_address_conf(const char *address, struct AccessItem *aconf)
682 > delete_one_address_conf(const char *address, struct MaskItem *conf)
683   {
684    int bits = 0;
685    uint32_t hv = 0;
# Line 711 | Line 709 | delete_one_address_conf(const char *addr
709    {
710      struct AddressRec *arec = ptr->data;
711  
712 <    if (arec->aconf == aconf)
712 >    if (arec->conf == conf)
713      {
714        dlinkDelete(&arec->node, &atable[hv]);
717      aconf->status |= CONF_ILLEGAL;
715  
716 <      if (!aconf->clients)
717 <        free_access_item(aconf);
716 >      if (!conf->ref_count)
717 >        conf_free(conf);
718  
719        MyFree(arec);
720        return;
# Line 729 | Line 726 | delete_one_address_conf(const char *addr
726   * Input: None
727   * Output: None
728   * Side effects: Clears out all address records in the hash table,
729 < *               frees them, and frees the AccessItems if nothing references
730 < *               them, otherwise sets them as illegal.  
729 > *               frees them, and frees the MaskItems if nothing references
730 > *               them, otherwise sets them as illegal.
731   */
732   void
733   clear_out_address_conf(void)
734   {
735    unsigned int i = 0;
736    dlink_node *ptr = NULL, *ptr_next = NULL;
737 <
737 >
738    for (i = 0; i < ATABLE_SIZE; ++i)
739    {
740      DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
# Line 748 | Line 745 | clear_out_address_conf(void)
745         * We keep the temporary K-lines and destroy the permanent ones,
746         * just to be confusing :) -A1kmm
747         */
748 <      if (arec->aconf->hold || IsConfDatabase(arec->aconf))
748 >      if (arec->conf->until || IsConfDatabase(arec->conf))
749          continue;
750  
751        dlinkDelete(&arec->node, &atable[i]);
755      arec->aconf->status |= CONF_ILLEGAL;
752  
753 <      if (!arec->aconf->clients)
754 <        free_access_item(arec->aconf);
753 >      if (!arec->conf->ref_count)
754 >        conf_free(arec->conf);
755        MyFree(arec);
756      }
757    }
# Line 780 | Line 776 | hostmask_send_expiration(struct AddressR
776      case CONF_GLINE:
777        ban_type = 'G';
778        break;
779 +    default: break;
780    }
781 <  
781 >
782    sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
783                         "Temporary %c-line for [%s@%s] expired", ban_type,
784 <                       (arec->aconf->user) ? arec->aconf->user : "*",
785 <                       (arec->aconf->host) ? arec->aconf->host : "*");
784 >                       (arec->conf->user) ? arec->conf->user : "*",
785 >                       (arec->conf->host) ? arec->conf->host : "*");
786   }
787  
788   void
# Line 800 | Line 797 | hostmask_expire_temporary(void)
797      {
798        struct AddressRec *arec = ptr->data;
799  
800 <      if (!arec->aconf->hold || arec->aconf->hold > CurrentTime)
800 >      if (!arec->conf->until || arec->conf->until > CurrentTime)
801          continue;
802  
803        switch (arec->type)
# Line 811 | Line 808 | hostmask_expire_temporary(void)
808            hostmask_send_expiration(arec);
809  
810            dlinkDelete(&arec->node, &atable[i]);
811 <          free_access_item(arec->aconf);
811 >          conf_free(arec->conf);
812            MyFree(arec);
813            break;
814 +        default: break;
815        }
816      }
817    }

Diff Legend

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