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-7.2/src/hostmask.c (file contents), Revision 34 by lusky, Sun Oct 2 21:05:51 2005 UTC vs.
ircd-hybrid/trunk/src/hostmask.c (file contents), 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"
28   #include "memory.h"
29   #include "ircd_defs.h"
30 < #include "tools.h"
31 < #include "s_conf.h"
30 > #include "list.h"
31 > #include "conf.h"
32   #include "hostmask.h"
31 #include "numeric.h"
33   #include "send.h"
34   #include "irc_string.h"
35 + #include "ircd.h"
36  
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);
37  
38   #define DigitParse(ch) do { \
39                         if (ch >= '0' && ch <= '9') \
# Line 46 | Line 42 | static unsigned long hash_ipv4(struct ir
42                           ch = ch - 'A' + 10; \
43                         else if (ch >= 'a' && ch <= 'f') \
44                           ch = ch - 'a' + 10; \
45 <                       } while(0);
45 >                       } while (0);
46  
47   /* The mask parser/type determination code... */
48  
# Line 57 | Line 53 | static unsigned long hash_ipv4(struct ir
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 74 | Line 70 | try_parse_v6_netmask(const char *text, s
70    int bits = 128;
71    int deficit = 0;
72    short dc[8];
73 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6*) addr;
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 116 | Line 113 | try_parse_v6_netmask(const char *text, s
113        d[dp] = d[dp] >> 4 * nyble;
114        dp++;
115        bits = strtoul(p + 1, &after, 10);
116 +
117        if (bits < 0 || *after)
118          return HM_HOST;
119        if (bits > dp * 4 && !(finsert >= 0 && bits <= 128))
# Line 124 | 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 +
129    if (c == 0)
130      dp++;
131    if (finsert < 0 && bits == 0)
132      bits = dp * 16;
133 +
134    /* How many words are missing? -A1kmm */
135    deficit = bits / 16 + ((bits % 16) ? 1 : 0) - dp;
136 +
137    /* Now fill in the gaps(from ::) in the copied table... -A1kmm */
138    for (dp = 0, nyble = 0; dp < 8; dp++)
139    {
# Line 143 | Line 145 | try_parse_v6_netmask(const char *text, s
145      else
146        dc[dp] = d[nyble++];
147    }
148 +
149    /* Set unused bits to 0... -A1kmm */
150    if (bits < 128 && (bits % 16 != 0))
151      dc[bits / 16] &= ~((1 << (15 - bits % 16)) - 1);
152    for (dp = bits / 16 + (bits % 16 ? 1 : 0); dp < 8; dp++)
153      dc[dp] = 0;
154 +
155    /* And assign... -A1kmm */
156    if (addr)
157      for (dp = 0; dp < 8; dp++)
158        /* The cast is a kludge to make netbsd work. */
159        ((unsigned short *)&v6->sin6_addr)[dp] = htons(dc[dp]);
160 +
161    if (b != NULL)
162      *b = bits;
163    return HM_IPV6;
# Line 174 | Line 179 | try_parse_v4_netmask(const char *text, s
179    unsigned char addb[4];
180    int n = 0, bits = 0;
181    char c;
182 <  struct sockaddr_in *v4 = (struct sockaddr_in*) addr;
182 >  struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
183  
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 == '.')
191      {
192        if (n >= 4)
193          return HM_HOST;
194 +
195        digits[n++] = p + 1;
196      }
197      else if (c == '*')
198      {
199        if (*(p + 1) || n == 0 || *(p - 1) != '.')
200          return HM_HOST;
201 +
202        bits = (n - 1) * 8;
203        break;
204      }
# Line 198 | Line 206 | try_parse_v4_netmask(const char *text, s
206      {
207        char *after;
208        bits = strtoul(p + 1, &after, 10);
209 <      if (!bits || *after)
209 >
210 >      if (bits < 0 || *after)
211          return HM_HOST;
212        if (bits > n * 8)
213          return HM_HOST;
214 +
215        break;
216      }
217      else
218        return HM_HOST;
219 +  }
220  
221    if (n < 4 && bits == 0)
222      bits = n * 8;
223    if (bits)
224      while (n < 4)
225        digits[n++] = "0";
226 +
227    for (n = 0; n < 4; n++)
228      addb[n] = strtoul(digits[n], NULL, 10);
229 +
230    if (bits == 0)
231      bits = 32;
232 +
233    /* Set unused bits to 0... -A1kmm */
234    if (bits < 32 && bits % 8)
235      addb[bits / 8] &= ~((1 << (8 - bits % 8)) - 1);
# Line 239 | 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, ':'))
259 >  if (strchr(text, ':'))
260      return try_parse_v6_netmask(text, addr, b);
261   #endif
246  if (strchr(text, '.'))
247    return try_parse_v4_netmask(text, addr, b);
262    return HM_HOST;
263   }
264  
# Line 256 | Line 270 | parse_netmask(const char *text, struct i
270   */
271   #ifdef IPV6
272   int
273 < match_ipv6(struct irc_ssaddr *addr, struct irc_ssaddr *mask, int bits)
273 > match_ipv6(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
274   {
275    int i, m, n = bits / 8;
276 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6*)addr;
277 <  struct sockaddr_in6 *v6mask = (struct sockaddr_in6*)mask;
276 >  const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
277 >  const struct sockaddr_in6 *v6mask = (const struct sockaddr_in6 *)mask;
278  
279    for (i = 0; i < n; i++)
280      if (v6->sin6_addr.s6_addr[i] != v6mask->sin6_addr.s6_addr[i])
# Line 273 | Line 287 | match_ipv6(struct irc_ssaddr *addr, stru
287    return 0;
288   }
289   #endif
290 +
291   /* int match_ipv4(struct irc_ssaddr *, struct irc_ssaddr *, int)
292   * Input: An IP address, an IP mask, the number of bits in the mask.
293   * Output: if match, -1 else 0
294   * Side Effects: None
295   */
296   int
297 < match_ipv4(struct irc_ssaddr *addr, struct irc_ssaddr *mask, int bits)
297 > match_ipv4(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
298   {
299 <  struct sockaddr_in *v4 = (struct sockaddr_in*) addr;
300 <  struct sockaddr_in *v4mask = (struct sockaddr_in*) mask;
299 >  const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
300 >  const struct sockaddr_in *v4mask = (const struct sockaddr_in *)mask;
301 >
302    if ((ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1)) !=
303        ntohl(v4mask->sin_addr.s_addr))
304      return 0;
# Line 311 | Line 327 | mask_addr(struct irc_ssaddr *ip, int bit
327    if (ip->ss.ss_family != AF_INET6)
328   #endif
329    {
330 <    v4_base_ip = (struct sockaddr_in*)ip;
330 >    v4_base_ip = (struct sockaddr_in *)ip;
331 >
332      mask = ~((1 << (32 - bits)) - 1);
333 <    v4_base_ip->sin_addr.s_addr =
317 <      htonl(ntohl(v4_base_ip->sin_addr.s_addr) & mask);
333 >    v4_base_ip->sin_addr.s_addr = htonl(ntohl(v4_base_ip->sin_addr.s_addr) & mask);
334    }
335   #ifdef IPV6
336    else
337    {
338      n = bits / 8;
339      m = bits % 8;
340 <    v6_base_ip = (struct sockaddr_in6*)ip;
340 >    v6_base_ip = (struct sockaddr_in6 *)ip;
341  
342      mask = ~((1 << (8 - m)) -1 );
343      v6_base_ip->sin6_addr.s6_addr[n] = v6_base_ip->sin6_addr.s6_addr[n] & mask;
344 <    for (i = n + 1; n < 16; i++)
345 <      v6_base_ip->sin6_addr.s6_addr[n] = 0;
344 >
345 >    for (i = n + 1; i < 16; i++)
346 >      v6_base_ip->sin6_addr.s6_addr[i] = 0;
347    }
348   #endif
349   }
350  
351   /* Hashtable stuff...now external as its used in m_stats.c */
352 < struct AddressRec *atable[ATABLE_SIZE];
352 > dlink_list atable[ATABLE_SIZE];
353  
354   void
355   init_host_hash(void)
# Line 345 | Line 362 | init_host_hash(void)
362   * Output: A hash value of the IP address.
363   * Side effects: None
364   */
365 < static unsigned long
366 < hash_ipv4(struct irc_ssaddr *addr, int bits)
365 > static uint32_t
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;
371 <    unsigned long av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
372 <    return((av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1));
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);
374    }
375  
376 <  return(0);
376 >  return 0;
377   }
378  
379   /* unsigned long hash_ipv6(struct irc_ssaddr*)
# Line 364 | Line 382 | hash_ipv4(struct irc_ssaddr *addr, int b
382   * Side effects: None
383   */
384   #ifdef IPV6
385 < static unsigned long
386 < hash_ipv6(struct irc_ssaddr *addr, int bits)
385 > static uint32_t
386 > hash_ipv6(const struct irc_ssaddr *addr, int bits)
387   {
388 <  unsigned long v = 0, n;
389 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6*) addr;
390 <  
388 >  uint32_t v = 0, n;
389 >  const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
390 >
391    for (n = 0; n < 16; n++)
392    {
393      if (bits >= 8)
# Line 394 | Line 412 | hash_ipv6(struct irc_ssaddr *addr, int b
412   * Output: The hash of the string between 1 and (TH_MAX-1)
413   * Side-effects: None.
414   */
415 < static int
415 > static uint32_t
416   hash_text(const char *start)
417   {
418    const char *p = start;
419 <  unsigned long h = 0;
419 >  uint32_t h = 0;
420  
421 <  while (*p)
422 <  {
423 <    h = (h << 4) - (h + (unsigned char)ToLower(*p++));
424 <  }
407 <  return (h & (ATABLE_SIZE - 1));
421 >  for (; *p; ++p)
422 >    h = (h << 4) - (h + ToLower(*p));
423 >
424 >  return h & (ATABLE_SIZE - 1);
425   }
426  
427   /* unsigned long get_hash_mask(const char *)
# Line 413 | Line 430 | hash_text(const char *start)
430   *         wildcard in the string.
431   * Side-effects: None.
432   */
433 < static unsigned long
433 > static uint32_t
434   get_mask_hash(const char *text)
435   {
436    const char *hp = "", *p;
437  
438    for (p = text + strlen(text) - 1; p >= text; p--)
439 <    if (*p == '*' || *p == '?')
439 >    if (IsMWildChar(*p))
440        return hash_text(hp);
441      else if (*p == '.')
442        hp = p + 1;
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 434 | 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 *
457 < find_conf_by_address(const char *name, struct irc_ssaddr *addr, int type,
458 <                     int fam, const char *username, const char *password)
459 < {
460 <  unsigned long hprecv = 0;
461 <  struct AccessItem *hprec = NULL;
462 <  struct AddressRec *arec;
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 MaskItem *hprec = NULL;
463 >  struct AddressRec *arec = NULL;
464    int b;
465 <
448 <  if (username == NULL)
449 <    username = "";
450 <  if (password == NULL)
451 <    password = "";
465 >  int (*cmpfunc)(const char *, const char *) = do_match ? match : irccmp;
466  
467    if (addr)
468    {
# Line 458 | Line 472 | find_conf_by_address(const char *name, s
472      {
473        for (b = 128; b >= 0; b -= 16)
474        {
475 <        for (arec = atable[hash_ipv6(addr, b)]; arec; arec = arec->next)
476 <          if (arec->type == (type & ~0x1) &&
475 >        DLINK_FOREACH(ptr, atable[hash_ipv6(addr, b)].head)
476 >        {
477 >          arec = ptr->data;
478 >
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 || match(arec->username, username)) &&
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        }
493      }
494      else
# Line 479 | Line 497 | find_conf_by_address(const char *name, s
497      {
498        for (b = 32; b >= 0; b -= 8)
499        {
500 <        for (arec = atable[hash_ipv4(addr, b)]; arec; arec = arec->next)
501 <          if (arec->type == (type & ~0x1) &&
500 >        DLINK_FOREACH(ptr, atable[hash_ipv4(addr, b)].head)
501 >        {
502 >          arec = ptr->data;
503 >
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 || match(arec->username, username)) &&
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        }
518      }
519    }
# Line 502 | Line 524 | find_conf_by_address(const char *name, s
524  
525      while (1)
526      {
527 <      for (arec = atable[hash_text(p)]; arec != NULL; arec = arec->next)
528 <        if ((arec->type == (type & ~0x1)) &&
527 >        DLINK_FOREACH(ptr, atable[hash_text(p)].head)
528 >        {
529 >          arec = ptr->data;
530 >          if ((arec->type == type) &&
531              arec->precedence > hprecv &&
532              (arec->masktype == HM_HOST) &&
533 <            match(arec->Mask.hostname, name) &&
534 <            (type & 0x1 || match(arec->username, username)) &&
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, '.');
543        if (p == NULL)
544          break;
545        p++;
546      }
547 <    for (arec = atable[0]; arec; arec = arec->next)
548 <      if (arec->type == (type & ~0x1) &&
547 >
548 >    DLINK_FOREACH(ptr, atable[0].head)
549 >    {
550 >      arec = ptr->data;
551 >
552 >      if (arec->type == type &&
553            arec->precedence > hprecv &&
554            arec->masktype == HM_HOST &&
555 <          match(arec->Mask.hostname, name) &&
556 <          (type & 0x1 || match(arec->username, username)) &&
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    }
565  
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 I-line... If none, return NULL -A1kmm */
582 <  if ((iconf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
583 <                                    password)) == NULL)
584 <    return(NULL);
585 <
586 <  /* If they are exempt from K-lines, return the best I-line. -A1kmm */
587 <  if (IsConfExemptKline(iconf))
588 <    return(iconf);
581 >  /* Find the best auth{} block... If none, return NULL -A1kmm */
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(authcnf))
588 >    return authcnf;
589  
590    /* Find the best K-line... -A1kmm */
591 <  kconf = find_conf_by_address(host, ip, CONF_KILL, aftype, user, NULL);
562 <
563 <  /* If they are K-lined, return the K-line. Otherwise, return the
564 <   * I-line. -A1kmm */
565 <  if (kconf != NULL)
566 <    return(kconf);
591 >  killcnf = find_conf_by_address(host, ip, CONF_KLINE, aftype, user, NULL, 1);
592  
593 <  kconf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL);
594 <  if (kconf != NULL && !IsConfExemptGline(iconf))
595 <    return(kconf);
593 >  /*
594 >   * If they are K-lined, return the K-line. Otherwise, return the
595 >   * auth{} block. -A1kmm
596 >   */
597 >  if (killcnf != NULL)
598 >    return killcnf;
599  
600 <  return(iconf);
601 < }
574 <
575 < struct AccessItem *
576 < find_gline_conf(const char *host, const char *user,
577 <                struct irc_ssaddr *ip, int aftype)
578 < {
579 <  struct AccessItem *eline;
580 <
581 <  eline = find_conf_by_address(host, ip, CONF_EXEMPTKLINE, aftype,
582 <                               user, NULL);
583 <  if (eline != NULL)
584 <    return(eline);
585 <
586 <  return(find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL));
587 < }
588 <
589 < /* find_kline_conf
590 < *
591 < * inputs       - pointer to hostname
592 < *              - pointer to username
593 < *              - incoming IP and type (IPv4 vs. IPv6)
594 < * outut        - pointer to kline conf if found NULL if not
595 < * side effects -
596 < */
597 < struct AccessItem *
598 < find_kline_conf(const char *host, const char *user,
599 <                struct irc_ssaddr *ip, int aftype)
600 < {
601 <  struct AccessItem *eline;
600 >  if (IsConfExemptGline(authcnf))
601 >    return authcnf;
602  
603 <  eline = find_conf_by_address(host, ip, CONF_EXEMPTKLINE, aftype,
604 <                               user, NULL);
605 <  if (eline != NULL)
606 <    return(eline);
603 >  killcnf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL, 1);
604 >  if (killcnf != NULL)
605 >    return killcnf;
606  
607 <  return(find_conf_by_address(host, ip, CONF_KILL, aftype, user, NULL));
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,
623 <                               NULL, NULL);
621 >  eline = find_conf_by_address(NULL, addr, CONF_EXEMPT, aftype, NULL, NULL, 1);
622    if (eline != NULL)
623 <    return(eline);
624 <  return(find_conf_by_address(NULL, addr, CONF_DLINE | 1, aftype, NULL, NULL));
623 >    return eline;
624 >
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(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;
638 <  static unsigned long prec_value = 0xFFFFFFFF;
639 <  int masktype, bits;
640 <  unsigned long hv;
642 <  struct AddressRec *arec;
643 <
644 <  address = aconf->host;
645 <  username = aconf->user;
646 <
647 <  assert(type != 0);
648 <  assert(aconf != NULL);
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 = NULL;
641  
642 <  if (EmptyString(address))
651 <    address = "/NOMATCH!/";
642 >  assert(type && !EmptyString(hostname));
643  
644    arec = MyMalloc(sizeof(struct AddressRec));
645 <  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;
656  arec->masktype = masktype;
657 #ifdef IPV6
658  if (masktype == HM_IPV6)
659  {
660    /* We have to do this, since we do not re-hash for every bit -A1kmm. */
661    bits -= bits % 16;
662    arec->next = atable[(hv = hash_ipv6(&arec->Mask.ipa.addr, bits))];
663    atable[hv] = arec;
664  }
665  else
666 #endif
667  if (masktype == HM_IPV4)
668  {
669    /* We have to do this, since we do not re-hash for every bit -A1kmm. */
670    bits -= bits % 8;
671    arec->next = atable[(hv = hash_ipv4(&arec->Mask.ipa.addr, bits))];
672    atable[hv] = arec;
673  }
674  else
675  {
676    arec->Mask.hostname = address;
677    arec->next = atable[(hv = get_mask_hash(address))];
678    atable[hv] = arec;
679  }
647    arec->username = username;
648 <  arec->aconf = aconf;
648 >  arec->conf = conf;
649    arec->precedence = prec_value--;
650    arec->type = type;
651 +
652 +  switch (arec->masktype)
653 +  {
654 +    case HM_IPV4:
655 +      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
656 +      bits -= bits % 8;
657 +      dlinkAdd(arec, &arec->node, &atable[hash_ipv4(&arec->Mask.ipa.addr, bits)]);
658 +      break;
659 + #ifdef IPV6
660 +    case HM_IPV6:
661 +      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
662 +      bits -= bits % 16;
663 +      dlinkAdd(arec, &arec->node, &atable[hash_ipv6(&arec->Mask.ipa.addr, bits)]);
664 +      break;
665 + #endif
666 +    default: /* HM_HOST */
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 masktype, bits;
685 <  unsigned long hv;
686 <  struct AddressRec *arec, *arecl = NULL;
684 >  int bits = 0;
685 >  uint32_t hv = 0;
686 >  dlink_node *ptr = NULL, *ptr_next = NULL;
687    struct irc_ssaddr addr;
699  masktype = parse_netmask(address, &addr, &bits);
688  
689 < #ifdef IPV6
702 <  if (masktype == HM_IPV6)
689 >  switch (parse_netmask(address, &addr, &bits))
690    {
691 <    /* We have to do this, since we do not re-hash for every bit -A1kmm. */
692 <    bits -= bits % 16;
693 <    hv = hash_ipv6(&addr, bits);
694 <  }
695 <  else
691 >    case HM_IPV4:
692 >      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
693 >      bits -= bits % 8;
694 >      hv = hash_ipv4(&addr, bits);
695 >      break;
696 > #ifdef IPV6
697 >    case HM_IPV6:
698 >      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
699 >      bits -= bits % 16;
700 >      hv = hash_ipv6(&addr, bits);
701 >      break;
702   #endif
703 <  if (masktype == HM_IPV4)
704 <  {
705 <    /* We have to do this, since we do not re-hash for every bit -A1kmm. */
713 <    bits -= bits % 8;
714 <    hv = hash_ipv4(&addr, bits);
703 >    default: /* HM_HOST */
704 >      hv = get_mask_hash(address);
705 >      break;
706    }
707 <  else
708 <    hv = get_mask_hash(address);
718 <  for (arec = atable[hv]; arec; arec = arec->next)
707 >
708 >  DLINK_FOREACH_SAFE(ptr, ptr_next, atable[hv].head)
709    {
710 <    if (arec->aconf == aconf)
710 >    struct AddressRec *arec = ptr->data;
711 >
712 >    if (arec->conf == conf)
713      {
714 <      if (arecl)
715 <        arecl->next = arec->next;
716 <      else
717 <        atable[hv] = arec->next;
718 <      aconf->status |= CONF_ILLEGAL;
727 <      if (aconf->clients == 0)
728 <        free_access_item(aconf);
714 >      dlinkDelete(&arec->node, &atable[hv]);
715 >
716 >      if (!conf->ref_count)
717 >        conf_free(conf);
718 >
719        MyFree(arec);
720        return;
721      }
732    arecl = arec;
722    }
723   }
724  
# Line 737 | 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 <  int i;
736 <  struct AddressRec *arec;
748 <  struct AddressRec *last_arec;
749 <  struct AddressRec *next_arec;
750 <
751 <  for (i = 0; i < ATABLE_SIZE; i++)
752 <  {
753 <    last_arec = NULL;
754 <    for (arec = atable[i]; arec; arec = next_arec)
755 <    {
756 <      /* We keep the temporary K-lines and destroy the
757 <       * permanent ones, just to be confusing :) -A1kmm
758 <       */  
759 <      next_arec = arec->next;
735 >  unsigned int i = 0;
736 >  dlink_node *ptr = NULL, *ptr_next = NULL;
737  
738 <      if (arec->aconf->flags & CONF_FLAGS_TEMPORARY)
739 <      {
740 <        last_arec = arec;
741 <      }
742 <      else  
766 <      {
767 <        /* unlink it from link list - Dianora */
768 <  
769 <        if (last_arec == NULL)
770 <        {
771 <          atable[i] = next_arec;
772 <        }
773 <        else
774 <        {
775 <          last_arec->next = next_arec;
776 <        }
738 >  for (i = 0; i < ATABLE_SIZE; ++i)
739 >  {
740 >    DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
741 >    {
742 >      struct AddressRec *arec = ptr->data;
743  
744 <        arec->aconf->status |= CONF_ILLEGAL;
745 <        if (arec->aconf->clients == 0)
746 <          free_access_item(arec->aconf);
747 <        MyFree(arec);
748 <      }
749 <    }
784 <  }
785 < }
744 >      /*
745 >       * We keep the temporary K-lines and destroy the permanent ones,
746 >       * just to be confusing :) -A1kmm
747 >       */
748 >      if (arec->conf->until || IsConfDatabase(arec->conf))
749 >        continue;
750  
751 < /*
788 < * show_iline_prefix()
789 < *
790 < * inputs       - pointer to struct Client requesting output
791 < *              - pointer to struct AccessItem
792 < *              - name to which iline prefix will be prefixed to
793 < * output       - pointer to static string with prefixes listed in ascii form
794 < * side effects - NONE
795 < */
796 < char *
797 < show_iline_prefix(struct Client *sptr, struct AccessItem *aconf, const char *name)
798 < {
799 <  static char prefix_of_host[USERLEN + 14];
800 <  char *prefix_ptr;
801 <
802 <  prefix_ptr = prefix_of_host;
803 <  if (IsNoTilde(aconf))
804 <    *prefix_ptr++ = '-';
805 <  if (IsLimitIp(aconf))
806 <    *prefix_ptr++ = '!';
807 <  if (IsNeedIdentd(aconf))
808 <    *prefix_ptr++ = '+';
809 <  if (!IsNeedPassword(aconf))
810 <    *prefix_ptr++ = '&';
811 <  if (IsConfExemptResv(aconf))
812 <    *prefix_ptr++ = '$';
813 <  if (IsNoMatchIp(aconf))
814 <    *prefix_ptr++ = '%';
815 <  if (IsConfDoSpoofIp(aconf))
816 <    *prefix_ptr++ = '=';
817 <  if (MyOper(sptr) && IsConfExemptKline(aconf))
818 <    *prefix_ptr++ = '^';
819 <  if (MyOper(sptr) && IsConfExemptGline(aconf))
820 <    *prefix_ptr++ = '_';
821 <  if (MyOper(sptr) && IsConfExemptLimits(aconf))
822 <    *prefix_ptr++ = '>';
823 <  if (MyOper(sptr) && IsConfIdlelined(aconf))
824 <    *prefix_ptr++ = '<';
825 <  if (IsConfCanFlood(aconf))
826 <    *prefix_ptr++ = '|';
827 <  strlcpy(prefix_ptr, name, USERLEN);
751 >      dlinkDelete(&arec->node, &atable[i]);
752  
753 <  return(prefix_of_host);
753 >      if (!arec->conf->ref_count)
754 >        conf_free(arec->conf);
755 >      MyFree(arec);
756 >    }
757 >  }
758   }
759  
760 < /* report_auth()
761 < *
834 < * Inputs: pointer to client to report to
835 < * Output: None
836 < * Side effects: Reports configured auth{} blocks to client_p
837 < */
838 < void
839 < report_auth(struct Client *client_p)
760 > static void
761 > hostmask_send_expiration(struct AddressRec *arec)
762   {
763 <  struct AddressRec *arec;
842 <  struct ConfItem *conf;
843 <  struct AccessItem *aconf;
844 <  int i;
763 >  char ban_type = '\0';
764  
765 <  for (i = 0; i < ATABLE_SIZE; i++)
766 <  {
848 <    for (arec = atable[i]; arec; arec = arec->next)
849 <    {
850 <      if (arec->type == CONF_CLIENT)
851 <      {
852 <        aconf = arec->aconf;
853 <
854 <        if (!MyOper(client_p) && IsConfDoSpoofIp(aconf))
855 <          continue;
856 <
857 <        conf = unmap_conf_item(aconf);
765 >  if (!ConfigFileEntry.tkline_expire_notices)
766 >    return;
767  
768 <        /* We are doing a partial list, based on what matches the u@h of the
769 <         * sender, so prepare the strings for comparing --fl_
770 <         */
771 <        if (ConfigFileEntry.hide_spoof_ips)
772 <          sendto_one(client_p, form_str(RPL_STATSILINE), me.name,
773 <                     client_p->name, 'I',
774 <                     conf->name == NULL ? "*" : conf->name,
775 <                     show_iline_prefix(client_p, aconf, aconf->user),
776 <                     IsConfDoSpoofIp(aconf) ? "255.255.255.255" :
777 <                     aconf->host, aconf->port,
778 <                     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
779 <                    
871 <        else
872 <          sendto_one(client_p, form_str(RPL_STATSILINE), me.name,
873 <                     client_p->name, 'I',
874 <                     conf->name == NULL ? "*" : conf->name,
875 <                     show_iline_prefix(client_p, aconf, aconf->user),
876 <                     aconf->host, aconf->port,
877 <                     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
878 <      }
879 <    }
768 >  switch (arec->type)
769 >  {
770 >    case CONF_KLINE:
771 >      ban_type = 'K';
772 >      break;
773 >    case CONF_DLINE:
774 >      ban_type = 'D';
775 >      break;
776 >    case CONF_GLINE:
777 >      ban_type = 'G';
778 >      break;
779 >    default: break;
780    }
781 +
782 +  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
783 +                       "Temporary %c-line for [%s@%s] expired", ban_type,
784 +                       (arec->conf->user) ? arec->conf->user : "*",
785 +                       (arec->conf->host) ? arec->conf->host : "*");
786   }
787  
883 /* report_Klines()
884 * Inputs: Client to report to,
885 *         type(==0 for perm, !=0 for temporary)
886 *         mask
887 * Output: None
888 * Side effects: Reports configured K(or k)-lines to client_p.
889 */
788   void
789 < report_Klines(struct Client *client_p, int tkline)
789 > hostmask_expire_temporary(void)
790   {
791 <  struct AddressRec *arec = NULL;
792 <  struct AccessItem *aconf = NULL;
895 <  int i;
896 <  const char *p = NULL;
791 >  unsigned int i = 0;
792 >  dlink_node *ptr = NULL, *ptr_next = NULL;
793  
794 <  if (tkline)
899 <    p = "k";
900 <  else
901 <    p = "K";
902 <
903 <  for (i = 0; i < ATABLE_SIZE; i++)
794 >  for (i = 0; i < ATABLE_SIZE; ++i)
795    {
796 <    for (arec = atable[i]; arec; arec = arec->next)
796 >    DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
797      {
798 <      if (arec->type == CONF_KILL)
798 >      struct AddressRec *arec = ptr->data;
799 >
800 >      if (!arec->conf->until || arec->conf->until > CurrentTime)
801 >        continue;
802 >
803 >      switch (arec->type)
804        {
805 <        if ((tkline && !((aconf = arec->aconf)->flags & CONF_FLAGS_TEMPORARY)) ||
806 <            (!tkline && ((aconf = arec->aconf)->flags & CONF_FLAGS_TEMPORARY)))
807 <          continue;
808 <
809 <        if (IsOper(client_p))
810 <          sendto_one(client_p, form_str(RPL_STATSKLINE), me.name,
811 <                     client_p->name, p, aconf->host, aconf->user,
812 <                     aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
813 <        else
814 <          sendto_one(client_p, form_str(RPL_STATSKLINE), me.name,
919 <                     client_p->name, p, aconf->host, aconf->user,
920 <                     aconf->reason, "");
805 >        case CONF_KLINE:
806 >        case CONF_DLINE:
807 >        case CONF_GLINE:
808 >          hostmask_send_expiration(arec);
809 >
810 >          dlinkDelete(&arec->node, &atable[i]);
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)