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 3504 by michael, Sat May 10 19:51:29 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 65 | Line 61 | static unsigned long hash_ipv4(struct ir
61   static int
62   try_parse_v6_netmask(const char *text, struct irc_ssaddr *addr, int *b)
63   {
68  const char *p;
64    char c;
65    int d[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
66    int dp = 0;
# Line 74 | Line 69 | try_parse_v6_netmask(const char *text, s
69    int bits = 128;
70    int deficit = 0;
71    short dc[8];
72 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6*) addr;
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 114 | 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)
117          return HM_HOST;
118        if (bits > dp * 4 && !(finsert >= 0 && bits <= 128))
# Line 124 | 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 +
133    /* How many words are missing? -A1kmm */
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 143 | Line 144 | try_parse_v6_netmask(const char *text, s
144      else
145        dc[dp] = d[nyble++];
146    }
147 +
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 <  if (b != NULL)
159 >
160 >  if (b)
161      *b = bits;
162    return HM_IPV6;
163   }
# Line 169 | 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   {
172  const char *p;
176    const char *digits[4];
177    unsigned char addb[4];
178    int n = 0, bits = 0;
179    char c;
180 <  struct sockaddr_in *v4 = (struct sockaddr_in*) addr;
180 >  struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
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 == '.')
189      {
190        if (n >= 4)
191          return HM_HOST;
192 +
193        digits[n++] = p + 1;
194      }
195      else if (c == '*')
196      {
197        if (*(p + 1) || n == 0 || *(p - 1) != '.')
198          return HM_HOST;
199 +
200        bits = (n - 1) * 8;
201        break;
202      }
# Line 198 | Line 204 | try_parse_v4_netmask(const char *text, s
204      {
205        char *after;
206        bits = strtoul(p + 1, &after, 10);
207 <      if (!bits || *after)
207 >
208 >      if (bits < 0 || *after)
209          return HM_HOST;
210        if (bits > n * 8)
211          return HM_HOST;
212 +
213        break;
214      }
215      else
216        return HM_HOST;
217 +  }
218  
219    if (n < 4 && bits == 0)
220      bits = n * 8;
221    if (bits)
222      while (n < 4)
223        digits[n++] = "0";
224 <  for (n = 0; n < 4; n++)
224 >
225 >  for (n = 0; n < 4; ++n)
226      addb[n] = strtoul(digits[n], NULL, 10);
227 +
228    if (bits == 0)
229      bits = 32;
230 +
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 239 | 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, ':'))
257 >  if (strchr(text, ':'))
258      return try_parse_v6_netmask(text, addr, b);
259   #endif
246  if (strchr(text, '.'))
247    return try_parse_v4_netmask(text, addr, b);
260    return HM_HOST;
261   }
262  
# Line 256 | Line 268 | parse_netmask(const char *text, struct i
268   */
269   #ifdef IPV6
270   int
271 < match_ipv6(struct irc_ssaddr *addr, struct irc_ssaddr *mask, int bits)
271 > match_ipv6(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
272   {
273    int i, m, n = bits / 8;
274 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6*)addr;
275 <  struct sockaddr_in6 *v6mask = (struct sockaddr_in6*)mask;
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 273 | Line 286 | match_ipv6(struct irc_ssaddr *addr, stru
286    return 0;
287   }
288   #endif
289 +
290   /* int match_ipv4(struct irc_ssaddr *, struct irc_ssaddr *, int)
291   * Input: An IP address, an IP mask, the number of bits in the mask.
292   * Output: if match, -1 else 0
293   * Side Effects: None
294   */
295   int
296 < match_ipv4(struct irc_ssaddr *addr, struct irc_ssaddr *mask, int bits)
296 > match_ipv4(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
297   {
298 <  struct sockaddr_in *v4 = (struct sockaddr_in*) addr;
299 <  struct sockaddr_in *v4mask = (struct sockaddr_in*) mask;
298 >  const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
299 >  const struct sockaddr_in *v4mask = (const struct sockaddr_in *)mask;
300 >
301    if ((ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1)) !=
302        ntohl(v4mask->sin_addr.s_addr))
303      return 0;
# Line 311 | Line 326 | mask_addr(struct irc_ssaddr *ip, int bit
326    if (ip->ss.ss_family != AF_INET6)
327   #endif
328    {
329 <    v4_base_ip = (struct sockaddr_in*)ip;
329 >    v4_base_ip = (struct sockaddr_in *)ip;
330 >
331      mask = ~((1 << (32 - bits)) - 1);
332 <    v4_base_ip->sin_addr.s_addr =
317 <      htonl(ntohl(v4_base_ip->sin_addr.s_addr) & mask);
332 >    v4_base_ip->sin_addr.s_addr = htonl(ntohl(v4_base_ip->sin_addr.s_addr) & mask);
333    }
334   #ifdef IPV6
335    else
336    {
337      n = bits / 8;
338      m = bits % 8;
339 <    v6_base_ip = (struct sockaddr_in6*)ip;
339 >    v6_base_ip = (struct sockaddr_in6 *)ip;
340  
341      mask = ~((1 << (8 - m)) -1 );
342      v6_base_ip->sin6_addr.s6_addr[n] = v6_base_ip->sin6_addr.s6_addr[n] & mask;
343 <    for (i = n + 1; n < 16; i++)
344 <      v6_base_ip->sin6_addr.s6_addr[n] = 0;
343 >
344 >    for (i = n + 1; i < 16; i++)
345 >      v6_base_ip->sin6_addr.s6_addr[i] = 0;
346    }
347   #endif
348   }
349  
350   /* Hashtable stuff...now external as its used in m_stats.c */
351 < struct AddressRec *atable[ATABLE_SIZE];
351 > dlink_list atable[ATABLE_SIZE];
352  
353   void
354   init_host_hash(void)
# Line 345 | Line 361 | init_host_hash(void)
361   * Output: A hash value of the IP address.
362   * Side effects: None
363   */
364 < static unsigned long
365 < hash_ipv4(struct irc_ssaddr *addr, int bits)
364 > static uint32_t
365 > hash_ipv4(const struct irc_ssaddr *addr, int bits)
366   {
367    if (bits != 0)
368    {
369 <    struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
370 <    unsigned long av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
371 <    return((av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1));
369 >    const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
370 >    uint32_t av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
371 >
372 >    return (av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1);
373    }
374  
375 <  return(0);
375 >  return 0;
376   }
377  
378   /* unsigned long hash_ipv6(struct irc_ssaddr*)
# Line 364 | Line 381 | hash_ipv4(struct irc_ssaddr *addr, int b
381   * Side effects: None
382   */
383   #ifdef IPV6
384 < static unsigned long
385 < hash_ipv6(struct irc_ssaddr *addr, int bits)
384 > static uint32_t
385 > hash_ipv6(const struct irc_ssaddr *addr, int bits)
386   {
387 <  unsigned long v = 0, n;
388 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6*) addr;
389 <  
390 <  for (n = 0; n < 16; n++)
387 >  uint32_t v = 0, n;
388 >  const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
389 >
390 >  for (n = 0; n < 16; ++n)
391    {
392      if (bits >= 8)
393      {
# Line 394 | Line 411 | hash_ipv6(struct irc_ssaddr *addr, int b
411   * Output: The hash of the string between 1 and (TH_MAX-1)
412   * Side-effects: None.
413   */
414 < static int
414 > static uint32_t
415   hash_text(const char *start)
416   {
417 <  const char *p = start;
401 <  unsigned long h = 0;
417 >  uint32_t h = 0;
418  
419 <  while (*p)
420 <  {
421 <    h = (h << 4) - (h + (unsigned char)ToLower(*p++));
422 <  }
407 <  return (h & (ATABLE_SIZE - 1));
419 >  for (const char *p = start; *p; ++p)
420 >    h = (h << 4) - (h + ToLower(*p));
421 >
422 >  return h & (ATABLE_SIZE - 1);
423   }
424  
425   /* unsigned long get_hash_mask(const char *)
# Line 413 | Line 428 | hash_text(const char *start)
428   *         wildcard in the string.
429   * Side-effects: None.
430   */
431 < static unsigned long
431 > static uint32_t
432   get_mask_hash(const char *text)
433   {
434    const char *hp = "", *p;
435  
436 <  for (p = text + strlen(text) - 1; p >= text; p--)
437 <    if (*p == '*' || *p == '?')
436 >  for (p = text + strlen(text) - 1; p >= text; --p)
437 >    if (IsMWildChar(*p))
438        return hash_text(hp);
439      else if (*p == '.')
440        hp = p + 1;
441    return hash_text(text);
442   }
443  
444 < /* struct AccessItem *find_conf_by_address(const char *, struct irc_ssaddr *,
444 > /* struct MaskItem *find_conf_by_address(const char *, struct irc_ssaddr *,
445   *                                         int type, int fam, const char *username)
446   * Input: The hostname, the address, the type of mask to find, the address
447   *        family, the username.
# Line 434 | Line 449 | get_mask_hash(const char *text)
449   * Side-effects: None
450   * Note: Setting bit 0 of the type means that the username is ignored.
451   * Warning: IsNeedPassword for everything that is not an auth{} entry
452 < * should always be true (i.e. aconf->flags & CONF_FLAGS_NEED_PASSWORD == 0)
452 > * should always be true (i.e. conf->flags & CONF_FLAGS_NEED_PASSWORD == 0)
453   */
454 < struct AccessItem *
455 < find_conf_by_address(const char *name, struct irc_ssaddr *addr, int type,
456 <                     int fam, const char *username, const char *password)
457 < {
458 <  unsigned long hprecv = 0;
459 <  struct AccessItem *hprec = NULL;
460 <  struct AddressRec *arec;
454 > struct MaskItem *
455 > find_conf_by_address(const char *name, struct irc_ssaddr *addr, unsigned int type,
456 >                     int fam, const char *username, const char *password, int do_match)
457 > {
458 >  unsigned int hprecv = 0;
459 >  dlink_node *ptr = NULL;
460 >  struct MaskItem *hprec = NULL;
461 >  struct AddressRec *arec = NULL;
462    int b;
463 <
448 <  if (username == NULL)
449 <    username = "";
450 <  if (password == NULL)
451 <    password = "";
463 >  int (*cmpfunc)(const char *, const char *) = do_match ? match : irccmp;
464  
465    if (addr)
466    {
# Line 458 | Line 470 | find_conf_by_address(const char *name, s
470      {
471        for (b = 128; b >= 0; b -= 16)
472        {
473 <        for (arec = atable[hash_ipv6(addr, b)]; arec; arec = arec->next)
474 <          if (arec->type == (type & ~0x1) &&
473 >        DLINK_FOREACH(ptr, atable[hash_ipv6(addr, b)].head)
474 >        {
475 >          arec = ptr->data;
476 >
477 >          if ((arec->type == type) &&
478                arec->precedence > hprecv &&
479                arec->masktype == HM_IPV6 &&
480                match_ipv6(addr, &arec->Mask.ipa.addr,
481                           arec->Mask.ipa.bits) &&
482 <              (type & 0x1 || match(arec->username, username)) &&
483 <              (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
484 <               match_conf_password(password, arec->aconf)))
482 >              (!username || !cmpfunc(arec->username, username)) &&
483 >              (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
484 >               match_conf_password(password, arec->conf)))
485            {
486              hprecv = arec->precedence;
487 <            hprec = arec->aconf;
487 >            hprec = arec->conf;
488            }
489 +        }
490        }
491      }
492      else
# Line 479 | Line 495 | find_conf_by_address(const char *name, s
495      {
496        for (b = 32; b >= 0; b -= 8)
497        {
498 <        for (arec = atable[hash_ipv4(addr, b)]; arec; arec = arec->next)
499 <          if (arec->type == (type & ~0x1) &&
498 >        DLINK_FOREACH(ptr, atable[hash_ipv4(addr, b)].head)
499 >        {
500 >          arec = ptr->data;
501 >
502 >          if ((arec->type == type) &&
503                arec->precedence > hprecv &&
504                arec->masktype == HM_IPV4 &&
505                match_ipv4(addr, &arec->Mask.ipa.addr,
506                           arec->Mask.ipa.bits) &&
507 <              (type & 0x1 || match(arec->username, username)) &&
508 <              (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
509 <               match_conf_password(password, arec->aconf)))
507 >              (!username || !cmpfunc(arec->username, username)) &&
508 >              (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
509 >               match_conf_password(password, arec->conf)))
510            {
511              hprecv = arec->precedence;
512 <            hprec = arec->aconf;
512 >            hprec = arec->conf;
513            }
514 +        }
515        }
516      }
517    }
518  
519 <  if (name != NULL)
519 >  if (name)
520    {
521      const char *p = name;
522  
523      while (1)
524      {
525 <      for (arec = atable[hash_text(p)]; arec != NULL; arec = arec->next)
526 <        if ((arec->type == (type & ~0x1)) &&
525 >        DLINK_FOREACH(ptr, atable[hash_text(p)].head)
526 >        {
527 >          arec = ptr->data;
528 >          if ((arec->type == type) &&
529              arec->precedence > hprecv &&
530              (arec->masktype == HM_HOST) &&
531 <            match(arec->Mask.hostname, name) &&
532 <            (type & 0x1 || match(arec->username, username)) &&
533 <            (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
534 <             match_conf_password(password, arec->aconf)))
531 >            !cmpfunc(arec->Mask.hostname, name) &&
532 >            (!username || !cmpfunc(arec->username, username)) &&
533 >            (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
534 >             match_conf_password(password, arec->conf)))
535          {
536            hprecv = arec->precedence;
537 <          hprec = arec->aconf;
537 >          hprec = arec->conf;
538          }
539 <      p = strchr(p, '.');
540 <      if (p == NULL)
539 >      }
540 >
541 >      if ((p = strchr(p, '.')) == NULL)
542          break;
543 <      p++;
543 >      ++p;
544      }
545 <    for (arec = atable[0]; arec; arec = arec->next)
546 <      if (arec->type == (type & ~0x1) &&
545 >
546 >    DLINK_FOREACH(ptr, atable[0].head)
547 >    {
548 >      arec = ptr->data;
549 >
550 >      if (arec->type == type &&
551            arec->precedence > hprecv &&
552            arec->masktype == HM_HOST &&
553 <          match(arec->Mask.hostname, name) &&
554 <          (type & 0x1 || match(arec->username, username)) &&
555 <          (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
556 <           match_conf_password(password, arec->aconf)))
553 >          !cmpfunc(arec->Mask.hostname, name) &&
554 >          (!username || !cmpfunc(arec->username, username)) &&
555 >          (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
556 >           match_conf_password(password, arec->conf)))
557        {
558          hprecv = arec->precedence;
559 <        hprec = arec->aconf;
559 >        hprec = arec->conf;
560        }
561 +    }
562    }
563  
564    return hprec;
565   }
566  
567 < /* struct AccessItem* find_address_conf(const char*, const char*,
567 > /* struct MaskItem* find_address_conf(const char*, const char*,
568   *                                     struct irc_ssaddr*, int, char *);
569   * Input: The hostname, username, address, address family.
570 < * Output: The applicable AccessItem.
570 > * Output: The applicable MaskItem.
571   * Side-effects: None
572   */
573 < struct AccessItem *
573 > struct MaskItem *
574   find_address_conf(const char *host, const char *user,
575                    struct irc_ssaddr *ip, int aftype, char *password)
576   {
577 <  struct AccessItem *iconf, *kconf;
577 >  struct MaskItem *authcnf = NULL, *killcnf = NULL;
578  
579 <  /* Find the best I-line... If none, return NULL -A1kmm */
580 <  if ((iconf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
581 <                                    password)) == NULL)
582 <    return(NULL);
583 <
584 <  /* If they are exempt from K-lines, return the best I-line. -A1kmm */
585 <  if (IsConfExemptKline(iconf))
586 <    return(iconf);
579 >  /* Find the best auth{} block... If none, return NULL -A1kmm */
580 >  if ((authcnf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
581 >                                      password, 1)) == NULL)
582 >    return NULL;
583 >
584 >  /* If they are exempt from K-lines, return the best auth{} block. -A1kmm */
585 >  if (IsConfExemptKline(authcnf))
586 >    return authcnf;
587  
588    /* Find the best K-line... -A1kmm */
589 <  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);
567 <
568 <  kconf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL);
569 <  if (kconf != NULL && !IsConfExemptGline(iconf))
570 <    return(kconf);
571 <
572 <  return(iconf);
573 < }
589 >  killcnf = find_conf_by_address(host, ip, CONF_KLINE, aftype, user, NULL, 1);
590  
591 < struct AccessItem *
592 < find_gline_conf(const char *host, const char *user,
593 <                struct irc_ssaddr *ip, int aftype)
594 < {
595 <  struct AccessItem *eline;
596 <
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 < }
591 >  /*
592 >   * If they are K-lined, return the K-line. Otherwise, return the
593 >   * auth{} block. -A1kmm
594 >   */
595 >  if (killcnf)
596 >    return killcnf;
597  
598 < /* find_kline_conf
599 < *
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;
598 >  if (IsConfExemptGline(authcnf))
599 >    return authcnf;
600  
601 <  eline = find_conf_by_address(host, ip, CONF_EXEMPTKLINE, aftype,
602 <                               user, NULL);
603 <  if (eline != NULL)
606 <    return(eline);
601 >  killcnf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL, 1);
602 >  if (killcnf)
603 >    return killcnf;
604  
605 <  return(find_conf_by_address(host, ip, CONF_KILL, aftype, user, NULL));
605 >  return authcnf;
606   }
607  
608 < /* struct AccessItem* find_dline_conf(struct irc_ssaddr*, int)
608 > /* struct MaskItem* find_dline_conf(struct irc_ssaddr*, int)
609   *
610   * Input:       An address, an address family.
611   * Output:      The best matching D-line or exempt line.
612   * Side effects: None.
613   */
614 < struct AccessItem *
614 > struct MaskItem *
615   find_dline_conf(struct irc_ssaddr *addr, int aftype)
616   {
617 <  struct AccessItem *eline;
617 >  struct MaskItem *eline;
618  
619 <  eline = find_conf_by_address(NULL, addr, CONF_EXEMPTDLINE | 1, aftype,
620 <                               NULL, NULL);
621 <  if (eline != NULL)
622 <    return(eline);
623 <  return(find_conf_by_address(NULL, addr, CONF_DLINE | 1, aftype, NULL, NULL));
619 >  eline = find_conf_by_address(NULL, addr, CONF_EXEMPT, aftype, NULL, NULL, 1);
620 >  if (eline)
621 >    return eline;
622 >
623 >  return find_conf_by_address(NULL, addr, CONF_DLINE, aftype, NULL, NULL, 1);
624   }
625  
626 < /* void add_conf_by_address(int, struct AccessItem *aconf)
627 < * Input:
626 > /* void add_conf_by_address(int, struct MaskItem *aconf)
627 > * Input:
628   * Output: None
629   * Side-effects: Adds this entry to the hash table.
630   */
631 < void
632 < add_conf_by_address(int type, struct AccessItem *aconf)
631 > struct AddressRec *
632 > add_conf_by_address(const unsigned int type, struct MaskItem *conf)
633   {
634 <  const char *address;
635 <  const char *username;
636 <  static unsigned long prec_value = 0xFFFFFFFF;
637 <  int masktype, bits;
638 <  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);
634 >  const char *hostname = conf->host;
635 >  const char *username = conf->user;
636 >  static unsigned int prec_value = 0xFFFFFFFF;
637 >  int bits = 0;
638 >  struct AddressRec *arec = NULL;
639  
640 <  if (EmptyString(address))
651 <    address = "/NOMATCH!/";
640 >  assert(type && !EmptyString(hostname));
641  
642 <  arec = MyMalloc(sizeof(struct AddressRec));
643 <  masktype = parse_netmask(address, &arec->Mask.ipa.addr, &bits);
642 >  arec = MyCalloc(sizeof(struct AddressRec));
643 >  arec->masktype = parse_netmask(hostname, &arec->Mask.ipa.addr, &bits);
644    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  }
645    arec->username = username;
646 <  arec->aconf = aconf;
646 >  arec->conf = conf;
647    arec->precedence = prec_value--;
648    arec->type = type;
649 +
650 +  switch (arec->masktype)
651 +  {
652 +    case HM_IPV4:
653 +      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
654 +      bits -= bits % 8;
655 +      dlinkAdd(arec, &arec->node, &atable[hash_ipv4(&arec->Mask.ipa.addr, bits)]);
656 +      break;
657 + #ifdef IPV6
658 +    case HM_IPV6:
659 +      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
660 +      bits -= bits % 16;
661 +      dlinkAdd(arec, &arec->node, &atable[hash_ipv6(&arec->Mask.ipa.addr, bits)]);
662 +      break;
663 + #endif
664 +    default: /* HM_HOST */
665 +      arec->Mask.hostname = hostname;
666 +      dlinkAdd(arec, &arec->node, &atable[get_mask_hash(hostname)]);
667 +      break;
668 +  }
669 +
670 +  return arec;
671   }
672  
673 < /* void delete_one_address(const char*, struct AccessItem*)
674 < * Input: An address string, the associated AccessItem.
673 > /* void delete_one_address(const char*, struct MaskItem*)
674 > * Input: An address string, the associated MaskItem.
675   * Output: None
676 < * Side effects: Deletes an address record. Frees the AccessItem if there
676 > * Side effects: Deletes an address record. Frees the MaskItem if there
677   *               is nothing referencing it, sets it as illegal otherwise.
678   */
679   void
680 < delete_one_address_conf(const char *address, struct AccessItem *aconf)
680 > delete_one_address_conf(const char *address, struct MaskItem *conf)
681   {
682 <  int masktype, bits;
683 <  unsigned long hv;
684 <  struct AddressRec *arec, *arecl = NULL;
682 >  int bits = 0;
683 >  uint32_t hv = 0;
684 >  dlink_node *ptr = NULL, *ptr_next = NULL;
685    struct irc_ssaddr addr;
699  masktype = parse_netmask(address, &addr, &bits);
686  
687 < #ifdef IPV6
702 <  if (masktype == HM_IPV6)
687 >  switch (parse_netmask(address, &addr, &bits))
688    {
689 <    /* We have to do this, since we do not re-hash for every bit -A1kmm. */
690 <    bits -= bits % 16;
691 <    hv = hash_ipv6(&addr, bits);
692 <  }
693 <  else
689 >    case HM_IPV4:
690 >      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
691 >      bits -= bits % 8;
692 >      hv = hash_ipv4(&addr, bits);
693 >      break;
694 > #ifdef IPV6
695 >    case HM_IPV6:
696 >      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
697 >      bits -= bits % 16;
698 >      hv = hash_ipv6(&addr, bits);
699 >      break;
700   #endif
701 <  if (masktype == HM_IPV4)
702 <  {
703 <    /* 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);
701 >    default: /* HM_HOST */
702 >      hv = get_mask_hash(address);
703 >      break;
704    }
705 <  else
706 <    hv = get_mask_hash(address);
718 <  for (arec = atable[hv]; arec; arec = arec->next)
705 >
706 >  DLINK_FOREACH_SAFE(ptr, ptr_next, atable[hv].head)
707    {
708 <    if (arec->aconf == aconf)
708 >    struct AddressRec *arec = ptr->data;
709 >
710 >    if (arec->conf == conf)
711      {
712 <      if (arecl)
713 <        arecl->next = arec->next;
714 <      else
715 <        atable[hv] = arec->next;
716 <      aconf->status |= CONF_ILLEGAL;
727 <      if (aconf->clients == 0)
728 <        free_access_item(aconf);
712 >      dlinkDelete(&arec->node, &atable[hv]);
713 >
714 >      if (!conf->ref_count)
715 >        conf_free(conf);
716 >
717        MyFree(arec);
718        return;
719      }
732    arecl = arec;
720    }
721   }
722  
# Line 737 | Line 724 | delete_one_address_conf(const char *addr
724   * Input: None
725   * Output: None
726   * Side effects: Clears out all address records in the hash table,
727 < *               frees them, and frees the AccessItems if nothing references
728 < *               them, otherwise sets them as illegal.  
727 > *               frees them, and frees the MaskItems if nothing references
728 > *               them, otherwise sets them as illegal.
729   */
730   void
731   clear_out_address_conf(void)
732   {
733 <  int i;
747 <  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;
733 >  dlink_node *ptr = NULL, *ptr_next = NULL;
734  
735 <      if (arec->aconf->flags & CONF_FLAGS_TEMPORARY)
736 <      {
737 <        last_arec = arec;
738 <      }
739 <      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 <        }
735 >  for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
736 >  {
737 >    DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
738 >    {
739 >      struct AddressRec *arec = ptr->data;
740  
741 <        arec->aconf->status |= CONF_ILLEGAL;
742 <        if (arec->aconf->clients == 0)
743 <          free_access_item(arec->aconf);
744 <        MyFree(arec);
745 <      }
746 <    }
784 <  }
785 < }
741 >      /*
742 >       * We keep the temporary K-lines and destroy the permanent ones,
743 >       * just to be confusing :) -A1kmm
744 >       */
745 >      if (arec->conf->until || IsConfDatabase(arec->conf))
746 >        continue;
747  
748 < /*
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);
748 >      dlinkDelete(&arec->node, &atable[i]);
749  
750 <  return(prefix_of_host);
750 >      if (!arec->conf->ref_count)
751 >        conf_free(arec->conf);
752 >      MyFree(arec);
753 >    }
754 >  }
755   }
756  
757 < /* report_auth()
758 < *
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)
757 > static void
758 > hostmask_send_expiration(struct AddressRec *arec)
759   {
760 <  struct AddressRec *arec;
842 <  struct ConfItem *conf;
843 <  struct AccessItem *aconf;
844 <  int i;
760 >  char ban_type = '\0';
761  
762 <  for (i = 0; i < ATABLE_SIZE; i++)
763 <  {
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);
762 >  if (!ConfigFileEntry.tkline_expire_notices)
763 >    return;
764  
765 <        /* We are doing a partial list, based on what matches the u@h of the
766 <         * sender, so prepare the strings for comparing --fl_
767 <         */
768 <        if (ConfigFileEntry.hide_spoof_ips)
769 <          sendto_one(client_p, form_str(RPL_STATSILINE), me.name,
770 <                     client_p->name, 'I',
771 <                     conf->name == NULL ? "*" : conf->name,
772 <                     show_iline_prefix(client_p, aconf, aconf->user),
773 <                     IsConfDoSpoofIp(aconf) ? "255.255.255.255" :
774 <                     aconf->host, aconf->port,
775 <                     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
776 <                    
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 <    }
765 >  switch (arec->type)
766 >  {
767 >    case CONF_KLINE:
768 >      ban_type = 'K';
769 >      break;
770 >    case CONF_DLINE:
771 >      ban_type = 'D';
772 >      break;
773 >    case CONF_GLINE:
774 >      ban_type = 'G';
775 >      break;
776 >    default: break;
777    }
778 +
779 +  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
780 +                       "Temporary %c-line for [%s@%s] expired", ban_type,
781 +                       (arec->conf->user) ? arec->conf->user : "*",
782 +                       (arec->conf->host) ? arec->conf->host : "*");
783   }
784  
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 */
785   void
786 < report_Klines(struct Client *client_p, int tkline)
786 > hostmask_expire_temporary(void)
787   {
788 <  struct AddressRec *arec = NULL;
894 <  struct AccessItem *aconf = NULL;
895 <  int i;
896 <  const char *p = NULL;
788 >  dlink_node *ptr = NULL, *ptr_next = NULL;
789  
790 <  if (tkline)
899 <    p = "k";
900 <  else
901 <    p = "K";
902 <
903 <  for (i = 0; i < ATABLE_SIZE; i++)
790 >  for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
791    {
792 <    for (arec = atable[i]; arec; arec = arec->next)
792 >    DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
793      {
794 <      if (arec->type == CONF_KILL)
794 >      struct AddressRec *arec = ptr->data;
795 >
796 >      if (!arec->conf->until || arec->conf->until > CurrentTime)
797 >        continue;
798 >
799 >      switch (arec->type)
800        {
801 <        if ((tkline && !((aconf = arec->aconf)->flags & CONF_FLAGS_TEMPORARY)) ||
802 <            (!tkline && ((aconf = arec->aconf)->flags & CONF_FLAGS_TEMPORARY)))
803 <          continue;
804 <
805 <        if (IsOper(client_p))
806 <          sendto_one(client_p, form_str(RPL_STATSKLINE), me.name,
807 <                     client_p->name, p, aconf->host, aconf->user,
808 <                     aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
809 <        else
810 <          sendto_one(client_p, form_str(RPL_STATSKLINE), me.name,
919 <                     client_p->name, p, aconf->host, aconf->user,
920 <                     aconf->reason, "");
801 >        case CONF_KLINE:
802 >        case CONF_DLINE:
803 >        case CONF_GLINE:
804 >          hostmask_send_expiration(arec);
805 >
806 >          dlinkDelete(&arec->node, &atable[i]);
807 >          conf_free(arec->conf);
808 >          MyFree(arec);
809 >          break;
810 >        default: break;
811        }
812      }
813    }

Diff Legend

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