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 1652 by michael, Tue Nov 13 20:28:53 2012 UTC vs.
Revision 4340 by michael, Sat Aug 2 16:53:22 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 59 | Line 61
61   static int
62   try_parse_v6_netmask(const char *text, struct irc_ssaddr *addr, int *b)
63   {
62  const char *p;
64    char c;
65    int d[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
66    int dp = 0;
# Line 70 | Line 71 | try_parse_v6_netmask(const char *text, s
71    short dc[8];
72    struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
73  
74 <  for (p = text; (c = *p); p++)
74 >  for (const char *p = text; (c = *p); ++p)
75 >  {
76      if (IsXDigit(c))
77      {
78        if (nyble == 0)
# Line 108 | Line 110 | try_parse_v6_netmask(const char *text, s
110        char *after;
111  
112        d[dp] = d[dp] >> 4 * nyble;
113 <      dp++;
113 >      ++dp;
114        bits = strtoul(p + 1, &after, 10);
115  
116        if (bits < 0 || *after)
# Line 119 | Line 121 | try_parse_v6_netmask(const char *text, s
121      }
122      else
123        return HM_HOST;
124 +  }
125  
126    d[dp] = d[dp] >> 4 * nyble;
127  
128    if (c == 0)
129 <    dp++;
129 >    ++dp;
130    if (finsert < 0 && bits == 0)
131      bits = dp * 16;
132  
# Line 131 | Line 134 | try_parse_v6_netmask(const char *text, s
134    deficit = bits / 16 + ((bits % 16) ? 1 : 0) - dp;
135  
136    /* Now fill in the gaps(from ::) in the copied table... -A1kmm */
137 <  for (dp = 0, nyble = 0; dp < 8; dp++)
137 >  for (dp = 0, nyble = 0; dp < 8; ++dp)
138    {
139      if (nyble == finsert && deficit)
140      {
# Line 145 | Line 148 | try_parse_v6_netmask(const char *text, s
148    /* Set unused bits to 0... -A1kmm */
149    if (bits < 128 && (bits % 16 != 0))
150      dc[bits / 16] &= ~((1 << (15 - bits % 16)) - 1);
151 <  for (dp = bits / 16 + (bits % 16 ? 1 : 0); dp < 8; dp++)
151 >  for (dp = bits / 16 + (bits % 16 ? 1 : 0); dp < 8; ++dp)
152      dc[dp] = 0;
153  
154    /* And assign... -A1kmm */
155    if (addr)
156 <    for (dp = 0; dp < 8; dp++)
156 >    for (dp = 0; dp < 8; ++dp)
157        /* The cast is a kludge to make netbsd work. */
158        ((unsigned short *)&v6->sin6_addr)[dp] = htons(dc[dp]);
159  
160 <  if (b != NULL)
160 >  if (b)
161      *b = bits;
162    return HM_IPV6;
163   }
# Line 170 | Line 173 | try_parse_v6_netmask(const char *text, s
173   static int
174   try_parse_v4_netmask(const char *text, struct irc_ssaddr *addr, int *b)
175   {
173  const char *p;
176    const char *digits[4];
177    unsigned char addb[4];
178    int n = 0, bits = 0;
# Line 179 | Line 181 | try_parse_v4_netmask(const char *text, s
181  
182    digits[n++] = text;
183  
184 <  for (p = text; (c = *p); p++)
184 >  for (const char *p = text; (c = *p); ++p)
185 >  {
186      if (c >= '0' && c <= '9')   /* empty */
187        ;
188      else if (c == '.')
# Line 202 | Line 205 | try_parse_v4_netmask(const char *text, s
205        char *after;
206        bits = strtoul(p + 1, &after, 10);
207  
208 <      if (!bits || *after)
208 >      if (bits < 0 || *after)
209          return HM_HOST;
210        if (bits > n * 8)
211          return HM_HOST;
# Line 211 | Line 214 | try_parse_v4_netmask(const char *text, s
214      }
215      else
216        return HM_HOST;
217 +  }
218  
219    if (n < 4 && bits == 0)
220      bits = n * 8;
# Line 218 | Line 222 | try_parse_v4_netmask(const char *text, s
222      while (n < 4)
223        digits[n++] = "0";
224  
225 <  for (n = 0; n < 4; n++)
225 >  for (n = 0; n < 4; ++n)
226      addb[n] = strtoul(digits[n], NULL, 10);
227  
228    if (bits == 0)
# Line 227 | Line 231 | try_parse_v4_netmask(const char *text, s
231    /* Set unused bits to 0... -A1kmm */
232    if (bits < 32 && bits % 8)
233      addb[bits / 8] &= ~((1 << (8 - bits % 8)) - 1);
234 <  for (n = bits / 8 + (bits % 8 ? 1 : 0); n < 4; n++)
234 >  for (n = bits / 8 + (bits % 8 ? 1 : 0); n < 4; ++n)
235      addb[n] = 0;
236    if (addr)
237      v4->sin_addr.s_addr =
238        htonl(addb[0] << 24 | addb[1] << 16 | addb[2] << 8 | addb[3]);
239 <  if (b != NULL)
239 >  if (b)
240      *b = bits;
241    return HM_IPV4;
242   }
# Line 247 | Line 251 | try_parse_v4_netmask(const char *text, s
251   int
252   parse_netmask(const char *text, struct irc_ssaddr *addr, int *b)
253   {
254 +  if (strchr(text, '.'))
255 +    return try_parse_v4_netmask(text, addr, b);
256   #ifdef IPV6
257    if (strchr(text, ':'))
258      return try_parse_v6_netmask(text, addr, b);
259   #endif
254  if (strchr(text, '.'))
255    return try_parse_v4_netmask(text, addr, b);
260    return HM_HOST;
261   }
262  
# Line 270 | Line 274 | match_ipv6(const struct irc_ssaddr *addr
274    const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
275    const struct sockaddr_in6 *v6mask = (const struct sockaddr_in6 *)mask;
276  
277 <  for (i = 0; i < n; i++)
277 >  for (i = 0; i < n; ++i)
278      if (v6->sin6_addr.s6_addr[i] != v6mask->sin6_addr.s6_addr[i])
279        return 0;
280 +
281    if ((m = bits % 8) == 0)
282      return -1;
283    if ((v6->sin6_addr.s6_addr[n] & ~((1 << (8 - m)) - 1)) ==
# Line 321 | Line 326 | mask_addr(struct irc_ssaddr *ip, int bit
326    if (ip->ss.ss_family != AF_INET6)
327   #endif
328    {
329 +    uint32_t tmp = 0;
330      v4_base_ip = (struct sockaddr_in *)ip;
331  
332      mask = ~((1 << (32 - bits)) - 1);
333 <    v4_base_ip->sin_addr.s_addr = htonl(ntohl(v4_base_ip->sin_addr.s_addr) & mask);
333 >    tmp = ntohl(v4_base_ip->sin_addr.s_addr);
334 >    v4_base_ip->sin_addr.s_addr = htonl(tmp & mask);
335    }
336   #ifdef IPV6
337    else
# Line 342 | Line 349 | mask_addr(struct irc_ssaddr *ip, int bit
349   #endif
350   }
351  
352 < /* Hashtable stuff...now external as its used in m_stats.c */
352 > /* Hashtable stuff...now external as it's used in m_stats.c */
353   dlink_list atable[ATABLE_SIZE];
354  
355   void
# Line 357 | Line 364 | init_host_hash(void)
364   * Side effects: None
365   */
366   static uint32_t
367 < hash_ipv4(struct irc_ssaddr *addr, int bits)
367 > hash_ipv4(const struct irc_ssaddr *addr, int bits)
368   {
369    if (bits != 0)
370    {
371 <    struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
371 >    const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
372      uint32_t av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
373  
374      return (av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1);
# Line 377 | Line 384 | hash_ipv4(struct irc_ssaddr *addr, int b
384   */
385   #ifdef IPV6
386   static uint32_t
387 < hash_ipv6(struct irc_ssaddr *addr, int bits)
387 > hash_ipv6(const struct irc_ssaddr *addr, int bits)
388   {
389    uint32_t v = 0, n;
390 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
390 >  const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
391  
392 <  for (n = 0; n < 16; n++)
392 >  for (n = 0; n < 16; ++n)
393    {
394      if (bits >= 8)
395      {
# Line 409 | Line 416 | hash_ipv6(struct irc_ssaddr *addr, int b
416   static uint32_t
417   hash_text(const char *start)
418   {
412  const char *p = start;
419    uint32_t h = 0;
420  
421 <  for (; *p; ++p)
422 <    h = (h << 4) - (h + (unsigned char)ToLower(*p));
421 >  for (const char *p = start; *p; ++p)
422 >    h = (h << 4) - (h + ToLower(*p));
423  
424    return h & (ATABLE_SIZE - 1);
425   }
# Line 429 | Line 435 | get_mask_hash(const char *text)
435   {
436    const char *hp = "", *p;
437  
438 <  for (p = text + strlen(text) - 1; p >= text; p--)
438 >  for (p = text + strlen(text) - 1; p >= text; --p)
439      if (IsMWildChar(*p))
440        return hash_text(hp);
441      else if (*p == '.')
# Line 458 | Line 464 | find_conf_by_address(const char *name, s
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)) &&
485 <              (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
486 <               match_conf_password(password, arec->conf)))
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->conf;
# 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)) &&
510 <              (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
511 <               match_conf_password(password, arec->conf)))
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->conf;
# Line 517 | Line 518 | find_conf_by_address(const char *name, s
518      }
519    }
520  
521 <  if (name != NULL)
521 >  if (name)
522    {
523      const char *p = name;
524  
# 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) &&
534 <            (type & 0x1 || !cmpfunc(arec->username, username)) &&
534 >            (!username || !cmpfunc(arec->username, username)) &&
535              (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
536               match_conf_password(password, arec->conf)))
537          {
# Line 538 | Line 539 | find_conf_by_address(const char *name, s
539            hprec = arec->conf;
540          }
541        }
542 <      p = strchr(p, '.');
543 <      if (p == NULL)
542 >
543 >      if ((p = strchr(p, '.')) == NULL)
544          break;
545 <      p++;
545 >      ++p;
546      }
547  
548      DLINK_FOREACH(ptr, atable[0].head)
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) &&
556 <          (type & 0x1 || cmpfunc(arec->username, username)) &&
556 >          (!username || !cmpfunc(arec->username, username)) &&
557            (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
558             match_conf_password(password, arec->conf)))
559        {
# Line 572 | Line 573 | find_conf_by_address(const char *name, s
573   * Side-effects: None
574   */
575   struct MaskItem *
576 < find_address_conf(const char *host, const char *user,
577 <                  struct irc_ssaddr *ip, int aftype, char *password)
576 > find_address_conf(const char *host, const char *user, struct irc_ssaddr *ip,
577 >                  int aftype, const char *password)
578   {
579    struct MaskItem *authcnf = NULL, *killcnf = NULL;
580  
# Line 593 | Line 594 | find_address_conf(const char *host, cons
594     * If they are K-lined, return the K-line. Otherwise, return the
595     * auth{} block. -A1kmm
596     */
597 <  if (killcnf != NULL)
597 >  if (killcnf)
598      return killcnf;
599  
600    if (IsConfExemptGline(authcnf))
601      return authcnf;
602  
603    killcnf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL, 1);
604 <  if (killcnf != NULL)
604 >  if (killcnf)
605      return killcnf;
606  
607    return authcnf;
# Line 617 | Line 618 | find_dline_conf(struct irc_ssaddr *addr,
618   {
619    struct MaskItem *eline;
620  
621 <  eline = find_conf_by_address(NULL, addr, CONF_EXEMPT | 1, aftype,
622 <                               NULL, NULL, 1);
622 <  if (eline != NULL)
621 >  eline = find_conf_by_address(NULL, addr, CONF_EXEMPT, aftype, NULL, NULL, 1);
622 >  if (eline)
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 MaskItem *aconf)
629 < * Input:
629 > * Input:
630   * Output: None
631   * Side-effects: Adds this entry to the hash table.
632   */
633 < void
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;
641 <
642 <  address = conf->host;
643 <  username = conf->user;
644 <
645 <  assert(type);
640 >  struct AddressRec *arec = NULL;
641  
642 <  if (EmptyString(address))
648 <    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);
644 >  arec = MyCalloc(sizeof(struct AddressRec));
645 >  arec->masktype = parse_netmask(hostname, &arec->Mask.ipa.addr, &bits);
646    arec->Mask.ipa.bits = bits;
647    arec->username = username;
648    arec->conf = conf;
# Line 670 | 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 MaskItem*)
# Line 687 | Line 683 | delete_one_address_conf(const char *addr
683   {
684    int bits = 0;
685    uint32_t hv = 0;
686 <  dlink_node *ptr = NULL, *ptr_next = NULL;
686 >  dlink_node *ptr = NULL;
687    struct irc_ssaddr addr;
688  
689    switch (parse_netmask(address, &addr, &bits))
# Line 709 | Line 705 | delete_one_address_conf(const char *addr
705        break;
706    }
707  
708 <  DLINK_FOREACH_SAFE(ptr, ptr_next, atable[hv].head)
708 >  DLINK_FOREACH(ptr, atable[hv].head)
709    {
710      struct AddressRec *arec = ptr->data;
711  
# Line 731 | Line 727 | delete_one_address_conf(const char *addr
727   * Output: None
728   * Side effects: Clears out all address records in the hash table,
729   *               frees them, and frees the MaskItems if nothing references
730 < *               them, otherwise sets them as illegal.  
730 > *               them, otherwise sets them as illegal.
731   */
732   void
733   clear_out_address_conf(void)
734   {
739  unsigned int i = 0;
735    dlink_node *ptr = NULL, *ptr_next = NULL;
736 <
737 <  for (i = 0; i < ATABLE_SIZE; ++i)
736 >
737 >  for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
738    {
739      DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
740      {
# Line 766 | Line 761 | hostmask_send_expiration(struct AddressR
761   {
762    char ban_type = '\0';
763  
764 <  if (!ConfigFileEntry.tkline_expire_notices)
764 >  if (!ConfigGeneral.tkline_expire_notices)
765      return;
766  
767    switch (arec->type)
# Line 782 | Line 777 | hostmask_send_expiration(struct AddressR
777        break;
778      default: break;
779    }
780 <  
780 >
781    sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
782                         "Temporary %c-line for [%s@%s] expired", ban_type,
783                         (arec->conf->user) ? arec->conf->user : "*",
# Line 792 | Line 787 | hostmask_send_expiration(struct AddressR
787   void
788   hostmask_expire_temporary(void)
789   {
795  unsigned int i = 0;
790    dlink_node *ptr = NULL, *ptr_next = NULL;
791  
792 <  for (i = 0; i < ATABLE_SIZE; ++i)
792 >  for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
793    {
794      DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
795      {

Diff Legend

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