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 6579 by michael, Mon Oct 19 19:10:05 2015 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-2015 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 16 | Line 15
15   *
16   *  You should have received a copy of the GNU General Public License
17   *  along with this program; if not, write to the Free Software
18 < *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18 > *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
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 > /* Hashtable stuff...now external as it's used in m_stats.c */
48 > dlink_list atable[ATABLE_SIZE];
49  
50   /* The mask parser/type determination code... */
51  
# Line 57 | Line 56 | static unsigned long hash_ipv4(struct ir
56   * Side effects: None
57   * Comments: Called from parse_netmask
58   */
60 /* Fixed so ::/0 (any IPv6 address) is valid
61   Also a bug in DigitParse above.
62   -Gozem 2002-07-19 gozem@linux.nu
63 */
64 #ifdef IPV6
59   static int
60   try_parse_v6_netmask(const char *text, struct irc_ssaddr *addr, int *b)
61   {
68  const char *p;
62    char c;
63    int d[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
64    int dp = 0;
# Line 74 | Line 67 | try_parse_v6_netmask(const char *text, s
67    int bits = 128;
68    int deficit = 0;
69    short dc[8];
70 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6*) addr;
70 >  struct sockaddr_in6 *const v6 = (struct sockaddr_in6 *)addr;
71  
72 <  for (p = text; (c = *p); p++)
72 >  for (const char *p = text; (c = *p); ++p)
73 >  {
74      if (IsXDigit(c))
75      {
76        if (nyble == 0)
# Line 114 | Line 108 | try_parse_v6_netmask(const char *text, s
108        char *after;
109  
110        d[dp] = d[dp] >> 4 * nyble;
111 <      dp++;
111 >      ++dp;
112        bits = strtoul(p + 1, &after, 10);
113 +
114        if (bits < 0 || *after)
115          return HM_HOST;
116        if (bits > dp * 4 && !(finsert >= 0 && bits <= 128))
# Line 124 | Line 119 | try_parse_v6_netmask(const char *text, s
119      }
120      else
121        return HM_HOST;
122 +  }
123  
124    d[dp] = d[dp] >> 4 * nyble;
125 +
126    if (c == 0)
127 <    dp++;
127 >    ++dp;
128    if (finsert < 0 && bits == 0)
129      bits = dp * 16;
130 +
131    /* How many words are missing? -A1kmm */
132    deficit = bits / 16 + ((bits % 16) ? 1 : 0) - dp;
133 +
134    /* Now fill in the gaps(from ::) in the copied table... -A1kmm */
135 <  for (dp = 0, nyble = 0; dp < 8; dp++)
135 >  for (dp = 0, nyble = 0; dp < 8; ++dp)
136    {
137      if (nyble == finsert && deficit)
138      {
# Line 143 | Line 142 | try_parse_v6_netmask(const char *text, s
142      else
143        dc[dp] = d[nyble++];
144    }
145 +
146    /* Set unused bits to 0... -A1kmm */
147    if (bits < 128 && (bits % 16 != 0))
148      dc[bits / 16] &= ~((1 << (15 - bits % 16)) - 1);
149 <  for (dp = bits / 16 + (bits % 16 ? 1 : 0); dp < 8; dp++)
149 >  for (dp = bits / 16 + (bits % 16 ? 1 : 0); dp < 8; ++dp)
150      dc[dp] = 0;
151 +
152    /* And assign... -A1kmm */
153    if (addr)
154 <    for (dp = 0; dp < 8; dp++)
154 >    for (dp = 0; dp < 8; ++dp)
155        /* The cast is a kludge to make netbsd work. */
156        ((unsigned short *)&v6->sin6_addr)[dp] = htons(dc[dp]);
157 <  if (b != NULL)
157 >
158 >  if (b)
159      *b = bits;
160    return HM_IPV6;
161   }
160 #endif
162  
163   /* int try_parse_v4_netmask(const char *, struct irc_ssaddr *, int *);
164   * Input: A possible IPV4 address as a string.
# Line 169 | Line 170 | try_parse_v6_netmask(const char *text, s
170   static int
171   try_parse_v4_netmask(const char *text, struct irc_ssaddr *addr, int *b)
172   {
172  const char *p;
173    const char *digits[4];
174    unsigned char addb[4];
175    int n = 0, bits = 0;
176    char c;
177 <  struct sockaddr_in *v4 = (struct sockaddr_in*) addr;
177 >  struct sockaddr_in *const v4 = (struct sockaddr_in *)addr;
178  
179    digits[n++] = text;
180  
181 <  for (p = text; (c = *p); p++)
181 >  for (const char *p = text; (c = *p); ++p)
182 >  {
183      if (c >= '0' && c <= '9')   /* empty */
184        ;
185      else if (c == '.')
186      {
187        if (n >= 4)
188          return HM_HOST;
189 +
190        digits[n++] = p + 1;
191      }
192      else if (c == '*')
193      {
194 <      if (*(p + 1) || n == 0 || *(p - 1) != '.')
194 >      if (*(p + 1) || n == 1 || *(p - 1) != '.')
195          return HM_HOST;
196 +
197        bits = (n - 1) * 8;
198        break;
199      }
# Line 198 | Line 201 | try_parse_v4_netmask(const char *text, s
201      {
202        char *after;
203        bits = strtoul(p + 1, &after, 10);
204 <      if (!bits || *after)
204 >
205 >      if (bits < 0 || *after)
206          return HM_HOST;
207        if (bits > n * 8)
208          return HM_HOST;
209 +
210        break;
211      }
212      else
213        return HM_HOST;
214 +  }
215  
216    if (n < 4 && bits == 0)
217      bits = n * 8;
218    if (bits)
219      while (n < 4)
220        digits[n++] = "0";
221 <  for (n = 0; n < 4; n++)
221 >
222 >  for (n = 0; n < 4; ++n)
223      addb[n] = strtoul(digits[n], NULL, 10);
224 +
225    if (bits == 0)
226      bits = 32;
227 +
228    /* Set unused bits to 0... -A1kmm */
229    if (bits < 32 && bits % 8)
230      addb[bits / 8] &= ~((1 << (8 - bits % 8)) - 1);
231 <  for (n = bits / 8 + (bits % 8 ? 1 : 0); n < 4; n++)
231 >  for (n = bits / 8 + (bits % 8 ? 1 : 0); n < 4; ++n)
232      addb[n] = 0;
233    if (addr)
234      v4->sin_addr.s_addr =
235        htonl(addb[0] << 24 | addb[1] << 16 | addb[2] << 8 | addb[3]);
236 <  if (b != NULL)
236 >  if (b)
237      *b = bits;
238    return HM_IPV4;
239   }
# Line 239 | Line 248 | try_parse_v4_netmask(const char *text, s
248   int
249   parse_netmask(const char *text, struct irc_ssaddr *addr, int *b)
250   {
242 #ifdef IPV6
243    if (strchr(text, ':'))
244    return try_parse_v6_netmask(text, addr, b);
245 #endif
251    if (strchr(text, '.'))
252      return try_parse_v4_netmask(text, addr, b);
253 +  if (strchr(text, ':'))
254 +    return try_parse_v6_netmask(text, addr, b);
255 +
256    return HM_HOST;
257   }
258  
# Line 254 | Line 262 | parse_netmask(const char *text, struct i
262   * Output: if match, -1 else 0
263   * Side effects: None
264   */
257 #ifdef IPV6
265   int
266 < match_ipv6(struct irc_ssaddr *addr, struct irc_ssaddr *mask, int bits)
266 > match_ipv6(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
267   {
268    int i, m, n = bits / 8;
269 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6*)addr;
270 <  struct sockaddr_in6 *v6mask = (struct sockaddr_in6*)mask;
269 >  const struct sockaddr_in6 *const v6 = (const struct sockaddr_in6 *)addr;
270 >  const struct sockaddr_in6 *const v6mask = (const struct sockaddr_in6 *)mask;
271  
272 <  for (i = 0; i < n; i++)
272 >  for (i = 0; i < n; ++i)
273      if (v6->sin6_addr.s6_addr[i] != v6mask->sin6_addr.s6_addr[i])
274        return 0;
275 +
276    if ((m = bits % 8) == 0)
277      return -1;
278    if ((v6->sin6_addr.s6_addr[n] & ~((1 << (8 - m)) - 1)) ==
# Line 272 | Line 280 | match_ipv6(struct irc_ssaddr *addr, stru
280      return -1;
281    return 0;
282   }
283 < #endif
283 >
284   /* int match_ipv4(struct irc_ssaddr *, struct irc_ssaddr *, int)
285   * Input: An IP address, an IP mask, the number of bits in the mask.
286   * Output: if match, -1 else 0
287   * Side Effects: None
288   */
289   int
290 < match_ipv4(struct irc_ssaddr *addr, struct irc_ssaddr *mask, int bits)
290 > match_ipv4(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
291   {
292 <  struct sockaddr_in *v4 = (struct sockaddr_in*) addr;
293 <  struct sockaddr_in *v4mask = (struct sockaddr_in*) mask;
292 >  const struct sockaddr_in *const v4 = (const struct sockaddr_in *)addr;
293 >  const struct sockaddr_in *const v4mask = (const struct sockaddr_in *)mask;
294 >
295    if ((ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1)) !=
296        ntohl(v4mask->sin_addr.s_addr))
297      return 0;
# Line 301 | Line 310 | void
310   mask_addr(struct irc_ssaddr *ip, int bits)
311   {
312    int mask;
304 #ifdef IPV6
313    struct sockaddr_in6 *v6_base_ip;
314    int i, m, n;
307 #endif
315    struct sockaddr_in *v4_base_ip;
316  
317 < #ifdef IPV6
311 <  if (ip->ss.ss_family != AF_INET6)
312 < #endif
317 >  if (ip->ss.ss_family == AF_INET)
318    {
319 <    v4_base_ip = (struct sockaddr_in*)ip;
319 >    uint32_t tmp = 0;
320 >    v4_base_ip = (struct sockaddr_in *)ip;
321 >
322      mask = ~((1 << (32 - bits)) - 1);
323 <    v4_base_ip->sin_addr.s_addr =
324 <      htonl(ntohl(v4_base_ip->sin_addr.s_addr) & mask);
323 >    tmp = ntohl(v4_base_ip->sin_addr.s_addr);
324 >    v4_base_ip->sin_addr.s_addr = htonl(tmp & mask);
325    }
319 #ifdef IPV6
326    else
327    {
328      n = bits / 8;
329      m = bits % 8;
330 <    v6_base_ip = (struct sockaddr_in6*)ip;
330 >    v6_base_ip = (struct sockaddr_in6 *)ip;
331  
332 <    mask = ~((1 << (8 - m)) -1 );
332 >    mask = ~((1 << (8 - m)) - 1);
333      v6_base_ip->sin6_addr.s6_addr[n] = v6_base_ip->sin6_addr.s6_addr[n] & mask;
328    for (i = n + 1; n < 16; i++)
329      v6_base_ip->sin6_addr.s6_addr[n] = 0;
330  }
331 #endif
332 }
334  
335 < /* Hashtable stuff...now external as its used in m_stats.c */
336 < struct AddressRec *atable[ATABLE_SIZE];
337 <
337 < void
338 < init_host_hash(void)
339 < {
340 <  memset(&atable, 0, sizeof(atable));
335 >    for (i = n + 1; i < 16; i++)
336 >      v6_base_ip->sin6_addr.s6_addr[i] = 0;
337 >  }
338   }
339  
340   /* unsigned long hash_ipv4(struct irc_ssaddr*)
# Line 345 | Line 342 | init_host_hash(void)
342   * Output: A hash value of the IP address.
343   * Side effects: None
344   */
345 < static unsigned long
346 < hash_ipv4(struct irc_ssaddr *addr, int bits)
345 > static uint32_t
346 > hash_ipv4(const struct irc_ssaddr *addr, int bits)
347   {
348    if (bits != 0)
349    {
350 <    struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
351 <    unsigned long av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
352 <    return((av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1));
350 >    const struct sockaddr_in *const v4 = (const struct sockaddr_in *)addr;
351 >    uint32_t av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
352 >
353 >    return (av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1);
354    }
355  
356 <  return(0);
356 >  return 0;
357   }
358  
359   /* unsigned long hash_ipv6(struct irc_ssaddr*)
# Line 363 | Line 361 | hash_ipv4(struct irc_ssaddr *addr, int b
361   * Output: A hash value of the IP address.
362   * Side effects: None
363   */
364 < #ifdef IPV6
365 < static unsigned long
366 < hash_ipv6(struct irc_ssaddr *addr, int bits)
367 < {
368 <  unsigned long v = 0, n;
369 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6*) addr;
370 <  
373 <  for (n = 0; n < 16; n++)
364 > static uint32_t
365 > hash_ipv6(const struct irc_ssaddr *addr, int bits)
366 > {
367 >  uint32_t v = 0, n;
368 >  const struct sockaddr_in6 *const v6 = (const struct sockaddr_in6 *)addr;
369 >
370 >  for (n = 0; n < 16; ++n)
371    {
372      if (bits >= 8)
373      {
# Line 385 | Line 382 | hash_ipv6(struct irc_ssaddr *addr, int b
382      else
383        return v & (ATABLE_SIZE - 1);
384    }
385 +
386    return v & (ATABLE_SIZE - 1);
387   }
390 #endif
388  
389   /* int hash_text(const char *start)
390   * Input: The start of the text to hash.
391   * Output: The hash of the string between 1 and (TH_MAX-1)
392   * Side-effects: None.
393   */
394 < static int
394 > static uint32_t
395   hash_text(const char *start)
396   {
397 <  const char *p = start;
401 <  unsigned long h = 0;
397 >  uint32_t h = 0;
398  
399 <  while (*p)
400 <  {
401 <    h = (h << 4) - (h + (unsigned char)ToLower(*p++));
402 <  }
407 <  return (h & (ATABLE_SIZE - 1));
399 >  for (const char *p = start; *p; ++p)
400 >    h = (h << 4) - (h + ToLower(*p));
401 >
402 >  return h & (ATABLE_SIZE - 1);
403   }
404  
405   /* unsigned long get_hash_mask(const char *)
# Line 413 | Line 408 | hash_text(const char *start)
408   *         wildcard in the string.
409   * Side-effects: None.
410   */
411 < static unsigned long
411 > static uint32_t
412   get_mask_hash(const char *text)
413   {
414    const char *hp = "", *p;
415  
416 <  for (p = text + strlen(text) - 1; p >= text; p--)
417 <    if (*p == '*' || *p == '?')
416 >  for (p = text + strlen(text) - 1; p >= text; --p)
417 >    if (IsMWildChar(*p))
418        return hash_text(hp);
419      else if (*p == '.')
420        hp = p + 1;
421    return hash_text(text);
422   }
423  
424 < /* struct AccessItem *find_conf_by_address(const char *, struct irc_ssaddr *,
424 > /* struct MaskItem *find_conf_by_address(const char *, struct irc_ssaddr *,
425   *                                         int type, int fam, const char *username)
426   * Input: The hostname, the address, the type of mask to find, the address
427   *        family, the username.
# Line 434 | Line 429 | get_mask_hash(const char *text)
429   * Side-effects: None
430   * Note: Setting bit 0 of the type means that the username is ignored.
431   * Warning: IsNeedPassword for everything that is not an auth{} entry
432 < * should always be true (i.e. aconf->flags & CONF_FLAGS_NEED_PASSWORD == 0)
432 > * should always be true (i.e. conf->flags & CONF_FLAGS_NEED_PASSWORD == 0)
433   */
434 < struct AccessItem *
435 < find_conf_by_address(const char *name, struct irc_ssaddr *addr, int type,
436 <                     int fam, const char *username, const char *password)
437 < {
438 <  unsigned long hprecv = 0;
439 <  struct AccessItem *hprec = NULL;
440 <  struct AddressRec *arec;
434 > struct MaskItem *
435 > find_conf_by_address(const char *name, const struct irc_ssaddr *addr, unsigned int type,
436 >                     int fam, const char *username, const char *password, int do_match)
437 > {
438 >  unsigned int hprecv = 0;
439 >  dlink_node *node = NULL;
440 >  struct MaskItem *hprec = NULL;
441 >  struct AddressRec *arec = NULL;
442    int b;
443 <
448 <  if (username == NULL)
449 <    username = "";
450 <  if (password == NULL)
451 <    password = "";
443 >  int (*cmpfunc)(const char *, const char *) = do_match ? match : irccmp;
444  
445    if (addr)
446    {
447      /* Check for IPV6 matches... */
456 #ifdef IPV6
448      if (fam == AF_INET6)
449      {
450        for (b = 128; b >= 0; b -= 16)
451        {
452 <        for (arec = atable[hash_ipv6(addr, b)]; arec; arec = arec->next)
453 <          if (arec->type == (type & ~0x1) &&
452 >        DLINK_FOREACH(node, atable[hash_ipv6(addr, b)].head)
453 >        {
454 >          arec = node->data;
455 >
456 >          if ((arec->type == type) &&
457                arec->precedence > hprecv &&
458                arec->masktype == HM_IPV6 &&
459                match_ipv6(addr, &arec->Mask.ipa.addr,
460                           arec->Mask.ipa.bits) &&
461 <              (type & 0x1 || match(arec->username, username)) &&
462 <              (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
463 <               match_conf_password(password, arec->aconf)))
461 >              (!username || !cmpfunc(arec->username, username)) &&
462 >              (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
463 >               match_conf_password(password, arec->conf)))
464            {
465              hprecv = arec->precedence;
466 <            hprec = arec->aconf;
466 >            hprec = arec->conf;
467            }
468 +        }
469        }
470      }
471 <    else
477 < #endif
478 <    if (fam == AF_INET)
471 >    else if (fam == AF_INET)
472      {
473        for (b = 32; b >= 0; b -= 8)
474        {
475 <        for (arec = atable[hash_ipv4(addr, b)]; arec; arec = arec->next)
476 <          if (arec->type == (type & ~0x1) &&
475 >        DLINK_FOREACH(node, atable[hash_ipv4(addr, b)].head)
476 >        {
477 >          arec = node->data;
478 >
479 >          if ((arec->type == type) &&
480                arec->precedence > hprecv &&
481                arec->masktype == HM_IPV4 &&
482                match_ipv4(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    }
495  
496 <  if (name != NULL)
496 >  if (name)
497    {
498      const char *p = name;
499  
500      while (1)
501      {
502 <      for (arec = atable[hash_text(p)]; arec != NULL; arec = arec->next)
503 <        if ((arec->type == (type & ~0x1)) &&
502 >        DLINK_FOREACH(node, atable[hash_text(p)].head)
503 >        {
504 >          arec = node->data;
505 >          if ((arec->type == type) &&
506              arec->precedence > hprecv &&
507              (arec->masktype == HM_HOST) &&
508 <            match(arec->Mask.hostname, name) &&
509 <            (type & 0x1 || match(arec->username, username)) &&
510 <            (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
511 <             match_conf_password(password, arec->aconf)))
508 >            !cmpfunc(arec->Mask.hostname, name) &&
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 <      p = strchr(p, '.');
517 <      if (p == NULL)
516 >      }
517 >
518 >      if ((p = strchr(p, '.')) == NULL)
519          break;
520 <      p++;
520 >      ++p;
521      }
522 <    for (arec = atable[0]; arec; arec = arec->next)
523 <      if (arec->type == (type & ~0x1) &&
522 >
523 >    DLINK_FOREACH(node, atable[0].head)
524 >    {
525 >      arec = node->data;
526 >
527 >      if (arec->type == type &&
528            arec->precedence > hprecv &&
529            arec->masktype == HM_HOST &&
530 <          match(arec->Mask.hostname, name) &&
531 <          (type & 0x1 || match(arec->username, username)) &&
532 <          (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
533 <           match_conf_password(password, arec->aconf)))
530 >          !cmpfunc(arec->Mask.hostname, name) &&
531 >          (!username || !cmpfunc(arec->username, username)) &&
532 >          (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
533 >           match_conf_password(password, arec->conf)))
534        {
535          hprecv = arec->precedence;
536 <        hprec = arec->aconf;
536 >        hprec = arec->conf;
537        }
538 +    }
539    }
540  
541    return hprec;
542   }
543  
544 < /* struct AccessItem* find_address_conf(const char*, const char*,
544 > /* struct MaskItem* find_address_conf(const char*, const char*,
545   *                                     struct irc_ssaddr*, int, char *);
546   * Input: The hostname, username, address, address family.
547 < * Output: The applicable AccessItem.
547 > * Output: The applicable MaskItem.
548   * Side-effects: None
549   */
550 < struct AccessItem *
551 < find_address_conf(const char *host, const char *user,
552 <                  struct irc_ssaddr *ip, int aftype, char *password)
553 < {
554 <  struct AccessItem *iconf, *kconf;
555 <
556 <  /* Find the best I-line... If none, return NULL -A1kmm */
557 <  if ((iconf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
558 <                                    password)) == NULL)
559 <    return(NULL);
560 <
561 <  /* If they are exempt from K-lines, return the best I-line. -A1kmm */
562 <  if (IsConfExemptKline(iconf))
563 <    return(iconf);
550 > struct MaskItem *
551 > find_address_conf(const char *host, const char *user, const struct irc_ssaddr *ip,
552 >                  int aftype, const char *password)
553 > {
554 >  struct MaskItem *authcnf = NULL, *killcnf = NULL;
555 >
556 >  /* Find the best auth{} block... If none, return NULL -A1kmm */
557 >  if ((authcnf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
558 >                                      password, 1)) == NULL)
559 >    return NULL;
560 >
561 >  /* If they are exempt from K-lines, return the best auth{} block. -A1kmm */
562 >  if (IsConfExemptKline(authcnf))
563 >    return authcnf;
564  
565    /* Find the best K-line... -A1kmm */
566 <  kconf = find_conf_by_address(host, ip, CONF_KILL, aftype, user, NULL);
566 >  killcnf = find_conf_by_address(host, ip, CONF_KLINE, aftype, user, NULL, 1);
567  
568 <  /* If they are K-lined, return the K-line. Otherwise, return the
569 <   * I-line. -A1kmm */
570 <  if (kconf != NULL)
571 <    return(kconf);
568 >  /*
569 >   * If they are K-lined, return the K-line. Otherwise, return the
570 >   * auth {} block. -A1kmm
571 >   */
572 >  if (killcnf)
573 >    return killcnf;
574  
575 <  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);
575 >  return authcnf;
576   }
577  
578 < 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;
602 <
603 <  eline = find_conf_by_address(host, ip, CONF_EXEMPTKLINE, aftype,
604 <                               user, NULL);
605 <  if (eline != NULL)
606 <    return(eline);
607 <
608 <  return(find_conf_by_address(host, ip, CONF_KILL, aftype, user, NULL));
609 < }
610 <
611 < /* struct AccessItem* find_dline_conf(struct irc_ssaddr*, int)
578 > /* struct MaskItem* find_dline_conf(struct irc_ssaddr*, int)
579   *
580   * Input:       An address, an address family.
581   * Output:      The best matching D-line or exempt line.
582   * Side effects: None.
583   */
584 < struct AccessItem *
585 < find_dline_conf(struct irc_ssaddr *addr, int aftype)
584 > struct MaskItem *
585 > find_dline_conf(const struct irc_ssaddr *addr, int aftype)
586   {
587 <  struct AccessItem *eline;
587 >  struct MaskItem *eline;
588  
589 <  eline = find_conf_by_address(NULL, addr, CONF_EXEMPTDLINE | 1, aftype,
590 <                               NULL, NULL);
591 <  if (eline != NULL)
592 <    return(eline);
593 <  return(find_conf_by_address(NULL, addr, CONF_DLINE | 1, aftype, NULL, NULL));
589 >  eline = find_conf_by_address(NULL, addr, CONF_EXEMPT, aftype, NULL, NULL, 1);
590 >  if (eline)
591 >    return eline;
592 >
593 >  return find_conf_by_address(NULL, addr, CONF_DLINE, aftype, NULL, NULL, 1);
594   }
595  
596 < /* void add_conf_by_address(int, struct AccessItem *aconf)
597 < * Input:
596 > /* void add_conf_by_address(int, struct MaskItem *aconf)
597 > * Input:
598   * Output: None
599   * Side-effects: Adds this entry to the hash table.
600   */
601 < void
602 < add_conf_by_address(int type, struct AccessItem *aconf)
601 > struct AddressRec *
602 > add_conf_by_address(const unsigned int type, struct MaskItem *conf)
603   {
604 <  const char *address;
605 <  const char *username;
606 <  static unsigned long prec_value = 0xFFFFFFFF;
607 <  int masktype, bits;
608 <  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);
604 >  struct AddressRec *arec = NULL;
605 >  const char *const hostname = conf->host;
606 >  const char *const username = conf->user;
607 >  static unsigned int prec_value = 0xFFFFFFFF;
608 >  int bits = 0;
609  
610 <  if (EmptyString(address))
651 <    address = "/NOMATCH!/";
610 >  assert(type && !EmptyString(hostname));
611  
612 <  arec = MyMalloc(sizeof(struct AddressRec));
613 <  masktype = parse_netmask(address, &arec->Mask.ipa.addr, &bits);
612 >  arec = MyCalloc(sizeof(struct AddressRec));
613 >  arec->masktype = parse_netmask(hostname, &arec->Mask.ipa.addr, &bits);
614    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  }
615    arec->username = username;
616 <  arec->aconf = aconf;
616 >  arec->conf = conf;
617    arec->precedence = prec_value--;
618    arec->type = type;
619 +
620 +  switch (arec->masktype)
621 +  {
622 +    case HM_IPV4:
623 +      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
624 +      bits -= bits % 8;
625 +      dlinkAdd(arec, &arec->node, &atable[hash_ipv4(&arec->Mask.ipa.addr, bits)]);
626 +      break;
627 +    case HM_IPV6:
628 +      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
629 +      bits -= bits % 16;
630 +      dlinkAdd(arec, &arec->node, &atable[hash_ipv6(&arec->Mask.ipa.addr, bits)]);
631 +      break;
632 +    default: /* HM_HOST */
633 +      arec->Mask.hostname = hostname;
634 +      dlinkAdd(arec, &arec->node, &atable[get_mask_hash(hostname)]);
635 +      break;
636 +  }
637 +
638 +  return arec;
639   }
640  
641 < /* void delete_one_address(const char*, struct AccessItem*)
642 < * Input: An address string, the associated AccessItem.
641 > /* void delete_one_address(const char*, struct MaskItem*)
642 > * Input: An address string, the associated MaskItem.
643   * Output: None
644 < * Side effects: Deletes an address record. Frees the AccessItem if there
644 > * Side effects: Deletes an address record. Frees the MaskItem if there
645   *               is nothing referencing it, sets it as illegal otherwise.
646   */
647   void
648 < delete_one_address_conf(const char *address, struct AccessItem *aconf)
648 > delete_one_address_conf(const char *address, struct MaskItem *conf)
649   {
650 <  int masktype, bits;
651 <  unsigned long hv;
652 <  struct AddressRec *arec, *arecl = NULL;
650 >  int bits = 0;
651 >  uint32_t hv = 0;
652 >  dlink_node *node = NULL;
653    struct irc_ssaddr addr;
699  masktype = parse_netmask(address, &addr, &bits);
654  
655 < #ifdef IPV6
702 <  if (masktype == HM_IPV6)
655 >  switch (parse_netmask(address, &addr, &bits))
656    {
657 <    /* We have to do this, since we do not re-hash for every bit -A1kmm. */
658 <    bits -= bits % 16;
659 <    hv = hash_ipv6(&addr, bits);
660 <  }
661 <  else
662 < #endif
663 <  if (masktype == HM_IPV4)
664 <  {
665 <    /* We have to do this, since we do not re-hash for every bit -A1kmm. */
666 <    bits -= bits % 8;
667 <    hv = hash_ipv4(&addr, bits);
657 >    case HM_IPV4:
658 >      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
659 >      bits -= bits % 8;
660 >      hv = hash_ipv4(&addr, bits);
661 >      break;
662 >    case HM_IPV6:
663 >      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
664 >      bits -= bits % 16;
665 >      hv = hash_ipv6(&addr, bits);
666 >      break;
667 >    default: /* HM_HOST */
668 >      hv = get_mask_hash(address);
669 >      break;
670    }
671 <  else
672 <    hv = get_mask_hash(address);
718 <  for (arec = atable[hv]; arec; arec = arec->next)
671 >
672 >  DLINK_FOREACH(node, atable[hv].head)
673    {
674 <    if (arec->aconf == aconf)
674 >    struct AddressRec *arec = node->data;
675 >
676 >    if (arec->conf == conf)
677      {
678 <      if (arecl)
679 <        arecl->next = arec->next;
680 <      else
681 <        atable[hv] = arec->next;
682 <      aconf->status |= CONF_ILLEGAL;
727 <      if (aconf->clients == 0)
728 <        free_access_item(aconf);
678 >      dlinkDelete(&arec->node, &atable[hv]);
679 >
680 >      if (!conf->ref_count)
681 >        conf_free(conf);
682 >
683        MyFree(arec);
684        return;
685      }
732    arecl = arec;
686    }
687   }
688  
# Line 737 | Line 690 | delete_one_address_conf(const char *addr
690   * Input: None
691   * Output: None
692   * Side effects: Clears out all address records in the hash table,
693 < *               frees them, and frees the AccessItems if nothing references
694 < *               them, otherwise sets them as illegal.  
693 > *               frees them, and frees the MaskItems if nothing references
694 > *               them, otherwise sets them as illegal.
695   */
696   void
697   clear_out_address_conf(void)
698   {
699 <  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;
699 >  dlink_node *node = NULL, *node_next = NULL;
700  
701 <      if (arec->aconf->flags & CONF_FLAGS_TEMPORARY)
702 <      {
703 <        last_arec = arec;
704 <      }
705 <      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 <        }
701 >  for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
702 >  {
703 >    DLINK_FOREACH_SAFE(node, node_next, atable[i].head)
704 >    {
705 >      struct AddressRec *arec = node->data;
706  
707 <        arec->aconf->status |= CONF_ILLEGAL;
708 <        if (arec->aconf->clients == 0)
709 <          free_access_item(arec->aconf);
710 <        MyFree(arec);
711 <      }
783 <    }
784 <  }
785 < }
707 >      /*
708 >       * Destroy the ircd.conf items and keep those that are in the databases
709 >       */
710 >      if (IsConfDatabase(arec->conf))
711 >        continue;
712  
713 < /*
714 < * 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);
713 >      dlinkDelete(&arec->node, &atable[i]);
714 >      arec->conf->active = 0;
715  
716 <  return(prefix_of_host);
716 >      if (!arec->conf->ref_count)
717 >        conf_free(arec->conf);
718 >      MyFree(arec);
719 >    }
720 >  }
721   }
722  
723 < /* report_auth()
724 < *
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)
723 > static void
724 > hostmask_send_expiration(const struct AddressRec *const arec)
725   {
726 <  struct AddressRec *arec;
842 <  struct ConfItem *conf;
843 <  struct AccessItem *aconf;
844 <  int i;
726 >  char ban_type = '\0';
727  
728 <  for (i = 0; i < ATABLE_SIZE; i++)
729 <  {
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;
728 >  if (!ConfigGeneral.tkline_expire_notices)
729 >    return;
730  
731 <        conf = unmap_conf_item(aconf);
732 <
733 <        /* We are doing a partial list, based on what matches the u@h of the
734 <         * sender, so prepare the strings for comparing --fl_
735 <         */
736 <        if (ConfigFileEntry.hide_spoof_ips)
737 <          sendto_one(client_p, form_str(RPL_STATSILINE), me.name,
738 <                     client_p->name, 'I',
739 <                     conf->name == NULL ? "*" : conf->name,
866 <                     show_iline_prefix(client_p, aconf, aconf->user),
867 <                     IsConfDoSpoofIp(aconf) ? "255.255.255.255" :
868 <                     aconf->host, aconf->port,
869 <                     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
870 <                    
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 <    }
731 >  switch (arec->type)
732 >  {
733 >    case CONF_KLINE:
734 >      ban_type = 'K';
735 >      break;
736 >    case CONF_DLINE:
737 >      ban_type = 'D';
738 >      break;
739 >    default: break;
740    }
741 +
742 +  sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
743 +                       "Temporary %c-line for [%s@%s] expired", ban_type,
744 +                       (arec->conf->user) ? arec->conf->user : "*",
745 +                       (arec->conf->host) ? arec->conf->host : "*");
746   }
747  
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 */
748   void
749 < report_Klines(struct Client *client_p, int tkline)
749 > hostmask_expire_temporary(void)
750   {
751 <  struct AddressRec *arec = NULL;
894 <  struct AccessItem *aconf = NULL;
895 <  int i;
896 <  const char *p = NULL;
751 >  dlink_node *node = NULL, *node_next = NULL;
752  
753 <  if (tkline)
899 <    p = "k";
900 <  else
901 <    p = "K";
902 <
903 <  for (i = 0; i < ATABLE_SIZE; i++)
753 >  for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
754    {
755 <    for (arec = atable[i]; arec; arec = arec->next)
755 >    DLINK_FOREACH_SAFE(node, node_next, atable[i].head)
756      {
757 <      if (arec->type == CONF_KILL)
757 >      struct AddressRec *arec = node->data;
758 >
759 >      if (!arec->conf->until || arec->conf->until > CurrentTime)
760 >        continue;
761 >
762 >      switch (arec->type)
763        {
764 <        if ((tkline && !((aconf = arec->aconf)->flags & CONF_FLAGS_TEMPORARY)) ||
765 <            (!tkline && ((aconf = arec->aconf)->flags & CONF_FLAGS_TEMPORARY)))
766 <          continue;
767 <
768 <        if (IsOper(client_p))
769 <          sendto_one(client_p, form_str(RPL_STATSKLINE), me.name,
770 <                     client_p->name, p, aconf->host, aconf->user,
771 <                     aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
772 <        else
918 <          sendto_one(client_p, form_str(RPL_STATSKLINE), me.name,
919 <                     client_p->name, p, aconf->host, aconf->user,
920 <                     aconf->reason, "");
764 >        case CONF_KLINE:
765 >        case CONF_DLINE:
766 >          hostmask_send_expiration(arec);
767 >
768 >          dlinkDelete(&arec->node, &atable[i]);
769 >          conf_free(arec->conf);
770 >          MyFree(arec);
771 >          break;
772 >        default: break;
773        }
774      }
775    }

Diff Legend

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