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 723 by adx, Sun Jul 16 19:41:33 2006 UTC vs.
ircd-hybrid/trunk/src/hostmask.c (file contents), Revision 1649 by michael, Sat Nov 10 19:27:13 2012 UTC

# Line 25 | Line 25
25   #include "stdinc.h"
26   #include "memory.h"
27   #include "ircd_defs.h"
28 < #include "tools.h"
29 < #include "s_conf.h"
28 > #include "list.h"
29 > #include "conf.h"
30   #include "hostmask.h"
31 – #include "numeric.h"
31   #include "send.h"
32   #include "irc_string.h"
33 + #include "ircd.h"
34  
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);
35  
36   #define DigitParse(ch) do { \
37                         if (ch >= '0' && ch <= '9') \
# Line 46 | Line 40 | static unsigned long hash_ipv4(struct ir
40                           ch = ch - 'A' + 10; \
41                         else if (ch >= 'a' && ch <= 'f') \
42                           ch = ch - 'a' + 10; \
43 <                       } while(0);
43 >                       } while (0);
44  
45   /* The mask parser/type determination code... */
46  
# Line 74 | Line 68 | try_parse_v6_netmask(const char *text, s
68    int bits = 128;
69    int deficit = 0;
70    short dc[8];
71 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6*) addr;
71 >  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
72  
73    for (p = text; (c = *p); p++)
74      if (IsXDigit(c))
# Line 116 | Line 110 | try_parse_v6_netmask(const char *text, s
110        d[dp] = d[dp] >> 4 * nyble;
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 126 | Line 121 | try_parse_v6_netmask(const char *text, s
121        return HM_HOST;
122  
123    d[dp] = d[dp] >> 4 * nyble;
124 +
125    if (c == 0)
126      dp++;
127    if (finsert < 0 && bits == 0)
128      bits = dp * 16;
129 +
130    /* How many words are missing? -A1kmm */
131    deficit = bits / 16 + ((bits % 16) ? 1 : 0) - dp;
132 +
133    /* Now fill in the gaps(from ::) in the copied table... -A1kmm */
134    for (dp = 0, nyble = 0; dp < 8; dp++)
135    {
# Line 143 | Line 141 | try_parse_v6_netmask(const char *text, s
141      else
142        dc[dp] = d[nyble++];
143    }
144 +
145    /* Set unused bits to 0... -A1kmm */
146    if (bits < 128 && (bits % 16 != 0))
147      dc[bits / 16] &= ~((1 << (15 - bits % 16)) - 1);
148    for (dp = bits / 16 + (bits % 16 ? 1 : 0); dp < 8; dp++)
149      dc[dp] = 0;
150 +
151    /* And assign... -A1kmm */
152    if (addr)
153      for (dp = 0; dp < 8; dp++)
154        /* The cast is a kludge to make netbsd work. */
155        ((unsigned short *)&v6->sin6_addr)[dp] = htons(dc[dp]);
156 +
157    if (b != NULL)
158      *b = bits;
159    return HM_IPV6;
# Line 174 | Line 175 | try_parse_v4_netmask(const char *text, s
175    unsigned char addb[4];
176    int n = 0, bits = 0;
177    char c;
178 <  struct sockaddr_in *v4 = (struct sockaddr_in*) addr;
178 >  struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
179  
180    digits[n++] = text;
181  
# Line 185 | Line 186 | try_parse_v4_netmask(const char *text, s
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) != '.')
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 +
205        if (!bits || *after)
206          return HM_HOST;
207        if (bits > n * 8)
208          return HM_HOST;
209 +
210        break;
211      }
212      else
# Line 212 | Line 217 | try_parse_v4_netmask(const char *text, s
217    if (bits)
218      while (n < 4)
219        digits[n++] = "0";
220 +
221    for (n = 0; n < 4; n++)
222      addb[n] = strtoul(digits[n], NULL, 10);
223 +
224    if (bits == 0)
225      bits = 32;
226 +
227    /* Set unused bits to 0... -A1kmm */
228    if (bits < 32 && bits % 8)
229      addb[bits / 8] &= ~((1 << (8 - bits % 8)) - 1);
# Line 240 | Line 248 | int
248   parse_netmask(const char *text, struct irc_ssaddr *addr, int *b)
249   {
250   #ifdef IPV6
251 <    if (strchr(text, ':'))
251 >  if (strchr(text, ':'))
252      return try_parse_v6_netmask(text, addr, b);
253   #endif
254    if (strchr(text, '.'))
# Line 256 | Line 264 | parse_netmask(const char *text, struct i
264   */
265   #ifdef IPV6
266   int
267 < match_ipv6(struct irc_ssaddr *addr, struct irc_ssaddr *mask, int bits)
267 > match_ipv6(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
268   {
269    int i, m, n = bits / 8;
270 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6*)addr;
271 <  struct sockaddr_in6 *v6mask = (struct sockaddr_in6*)mask;
270 >  const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
271 >  const struct sockaddr_in6 *v6mask = (const struct sockaddr_in6 *)mask;
272  
273    for (i = 0; i < n; i++)
274      if (v6->sin6_addr.s6_addr[i] != v6mask->sin6_addr.s6_addr[i])
# Line 273 | Line 281 | match_ipv6(struct irc_ssaddr *addr, stru
281    return 0;
282   }
283   #endif
284 +
285   /* int match_ipv4(struct irc_ssaddr *, struct irc_ssaddr *, int)
286   * Input: An IP address, an IP mask, the number of bits in the mask.
287   * Output: if match, -1 else 0
288   * Side Effects: None
289   */
290   int
291 < match_ipv4(struct irc_ssaddr *addr, struct irc_ssaddr *mask, int bits)
291 > match_ipv4(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
292   {
293 <  struct sockaddr_in *v4 = (struct sockaddr_in*) addr;
294 <  struct sockaddr_in *v4mask = (struct sockaddr_in*) mask;
293 >  const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
294 >  const struct sockaddr_in *v4mask = (const struct sockaddr_in *)mask;
295 >
296    if ((ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1)) !=
297        ntohl(v4mask->sin_addr.s_addr))
298      return 0;
# Line 311 | Line 321 | mask_addr(struct irc_ssaddr *ip, int bit
321    if (ip->ss.ss_family != AF_INET6)
322   #endif
323    {
324 <    v4_base_ip = (struct sockaddr_in*)ip;
324 >    v4_base_ip = (struct sockaddr_in *)ip;
325 >
326      mask = ~((1 << (32 - bits)) - 1);
327 <    v4_base_ip->sin_addr.s_addr =
317 <      htonl(ntohl(v4_base_ip->sin_addr.s_addr) & mask);
327 >    v4_base_ip->sin_addr.s_addr = htonl(ntohl(v4_base_ip->sin_addr.s_addr) & mask);
328    }
329   #ifdef IPV6
330    else
331    {
332      n = bits / 8;
333      m = bits % 8;
334 <    v6_base_ip = (struct sockaddr_in6*)ip;
334 >    v6_base_ip = (struct sockaddr_in6 *)ip;
335  
336      mask = ~((1 << (8 - m)) -1 );
337      v6_base_ip->sin6_addr.s6_addr[n] = v6_base_ip->sin6_addr.s6_addr[n] & mask;
338 +
339      for (i = n + 1; i < 16; i++)
340        v6_base_ip->sin6_addr.s6_addr[i] = 0;
341    }
# Line 332 | Line 343 | mask_addr(struct irc_ssaddr *ip, int bit
343   }
344  
345   /* Hashtable stuff...now external as its used in m_stats.c */
346 < struct AddressRec *atable[ATABLE_SIZE];
346 > dlink_list atable[ATABLE_SIZE];
347  
348   void
349   init_host_hash(void)
# Line 345 | Line 356 | init_host_hash(void)
356   * Output: A hash value of the IP address.
357   * Side effects: None
358   */
359 < static unsigned long
359 > static uint32_t
360   hash_ipv4(struct irc_ssaddr *addr, int bits)
361   {
362    if (bits != 0)
363    {
364      struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
365 <    unsigned long av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
366 <    return((av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1));
365 >    uint32_t av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
366 >
367 >    return (av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1);
368    }
369  
370 <  return(0);
370 >  return 0;
371   }
372  
373   /* unsigned long hash_ipv6(struct irc_ssaddr*)
# Line 364 | Line 376 | hash_ipv4(struct irc_ssaddr *addr, int b
376   * Side effects: None
377   */
378   #ifdef IPV6
379 < static unsigned long
379 > static uint32_t
380   hash_ipv6(struct irc_ssaddr *addr, int bits)
381   {
382 <  unsigned long v = 0, n;
383 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6*) addr;
384 <  
382 >  uint32_t v = 0, n;
383 >  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
384 >
385    for (n = 0; n < 16; n++)
386    {
387      if (bits >= 8)
# Line 394 | Line 406 | hash_ipv6(struct irc_ssaddr *addr, int b
406   * Output: The hash of the string between 1 and (TH_MAX-1)
407   * Side-effects: None.
408   */
409 < static int
409 > static uint32_t
410   hash_text(const char *start)
411   {
412    const char *p = start;
413 <  unsigned long h = 0;
413 >  uint32_t h = 0;
414  
415 <  while (*p)
416 <  {
417 <    h = (h << 4) - (h + (unsigned char)ToLower(*p++));
418 <  }
407 <  return (h & (ATABLE_SIZE - 1));
415 >  for (; *p; ++p)
416 >    h = (h << 4) - (h + (unsigned char)ToLower(*p));
417 >
418 >  return h & (ATABLE_SIZE - 1);
419   }
420  
421   /* unsigned long get_hash_mask(const char *)
# Line 413 | Line 424 | hash_text(const char *start)
424   *         wildcard in the string.
425   * Side-effects: None.
426   */
427 < static unsigned long
427 > static uint32_t
428   get_mask_hash(const char *text)
429   {
430    const char *hp = "", *p;
# Line 426 | Line 437 | get_mask_hash(const char *text)
437    return hash_text(text);
438   }
439  
440 < /* struct AccessItem *find_conf_by_address(const char *, struct irc_ssaddr *,
440 > /* struct MaskItem *find_conf_by_address(const char *, struct irc_ssaddr *,
441   *                                         int type, int fam, const char *username)
442   * Input: The hostname, the address, the type of mask to find, the address
443   *        family, the username.
# Line 434 | Line 445 | get_mask_hash(const char *text)
445   * Side-effects: None
446   * Note: Setting bit 0 of the type means that the username is ignored.
447   * Warning: IsNeedPassword for everything that is not an auth{} entry
448 < * should always be true (i.e. aconf->flags & CONF_FLAGS_NEED_PASSWORD == 0)
448 > * should always be true (i.e. conf->flags & CONF_FLAGS_NEED_PASSWORD == 0)
449   */
450 < struct AccessItem *
451 < find_conf_by_address(const char *name, struct irc_ssaddr *addr, int type,
452 <                     int fam, const char *username, const char *password)
453 < {
454 <  unsigned long hprecv = 0;
455 <  struct AccessItem *hprec = NULL;
456 <  struct AddressRec *arec;
450 > struct MaskItem *
451 > find_conf_by_address(const char *name, struct irc_ssaddr *addr, unsigned int type,
452 >                     int fam, const char *username, const char *password, int do_match)
453 > {
454 >  unsigned int hprecv = 0;
455 >  dlink_node *ptr = NULL;
456 >  struct MaskItem *hprec = NULL;
457 >  struct AddressRec *arec = NULL;
458    int b;
459 +  int (*cmpfunc)(const char *, const char *) = do_match ? match : irccmp;
460  
461    if (username == NULL)
462      username = "";
# Line 458 | Line 471 | find_conf_by_address(const char *name, s
471      {
472        for (b = 128; b >= 0; b -= 16)
473        {
474 <        for (arec = atable[hash_ipv6(addr, b)]; arec; arec = arec->next)
474 >        DLINK_FOREACH(ptr, atable[hash_ipv6(addr, b)].head)
475 >        {
476 >          arec = ptr->data;
477 >
478            if (arec->type == (type & ~0x1) &&
479                arec->precedence > hprecv &&
480                arec->masktype == HM_IPV6 &&
481                match_ipv6(addr, &arec->Mask.ipa.addr,
482                           arec->Mask.ipa.bits) &&
483 <              (type & 0x1 || match(arec->username, username)) &&
484 <              (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
485 <               match_conf_password(password, arec->aconf)))
483 >              (type & 0x1 || cmpfunc(arec->username, username) == do_match) &&
484 >              (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
485 >               match_conf_password(password, arec->conf)))
486            {
487              hprecv = arec->precedence;
488 <            hprec = arec->aconf;
488 >            hprec = arec->conf;
489            }
490 +        }
491        }
492      }
493      else
# Line 479 | Line 496 | find_conf_by_address(const char *name, s
496      {
497        for (b = 32; b >= 0; b -= 8)
498        {
499 <        for (arec = atable[hash_ipv4(addr, b)]; arec; arec = arec->next)
499 >        DLINK_FOREACH(ptr, atable[hash_ipv4(addr, b)].head)
500 >        {
501 >          arec = ptr->data;
502 >
503            if (arec->type == (type & ~0x1) &&
504                arec->precedence > hprecv &&
505                arec->masktype == HM_IPV4 &&
506                match_ipv4(addr, &arec->Mask.ipa.addr,
507                           arec->Mask.ipa.bits) &&
508 <              (type & 0x1 || match(arec->username, username)) &&
509 <              (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
510 <               match_conf_password(password, arec->aconf)))
508 >              (type & 0x1 || cmpfunc(arec->username, username) == do_match) &&
509 >              (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
510 >               match_conf_password(password, arec->conf)))
511            {
512              hprecv = arec->precedence;
513 <            hprec = arec->aconf;
513 >            hprec = arec->conf;
514            }
515 +        }
516        }
517      }
518    }
# Line 502 | Line 523 | find_conf_by_address(const char *name, s
523  
524      while (1)
525      {
526 <      for (arec = atable[hash_text(p)]; arec != NULL; arec = arec->next)
527 <        if ((arec->type == (type & ~0x1)) &&
526 >        DLINK_FOREACH(ptr, atable[hash_text(p)].head)
527 >        {
528 >          arec = ptr->data;
529 >          if ((arec->type == (type & ~0x1)) &&
530              arec->precedence > hprecv &&
531              (arec->masktype == HM_HOST) &&
532 <            match(arec->Mask.hostname, name) &&
533 <            (type & 0x1 || match(arec->username, username)) &&
534 <            (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
535 <             match_conf_password(password, arec->aconf)))
532 >            cmpfunc(arec->Mask.hostname, name) == do_match &&
533 >            (type & 0x1 || cmpfunc(arec->username, username) == do_match) &&
534 >            (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
535 >             match_conf_password(password, arec->conf)))
536          {
537            hprecv = arec->precedence;
538 <          hprec = arec->aconf;
538 >          hprec = arec->conf;
539          }
540 +      }
541        p = strchr(p, '.');
542        if (p == NULL)
543          break;
544        p++;
545      }
546 <    for (arec = atable[0]; arec; arec = arec->next)
546 >
547 >    DLINK_FOREACH(ptr, atable[0].head)
548 >    {
549 >      arec = ptr->data;
550 >
551        if (arec->type == (type & ~0x1) &&
552            arec->precedence > hprecv &&
553            arec->masktype == HM_HOST &&
554 <          match(arec->Mask.hostname, name) &&
555 <          (type & 0x1 || match(arec->username, username)) &&
556 <          (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
557 <           match_conf_password(password, arec->aconf)))
554 >          cmpfunc(arec->Mask.hostname, name) == do_match &&
555 >          (type & 0x1 || cmpfunc(arec->username, username) == do_match) &&
556 >          (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
557 >           match_conf_password(password, arec->conf)))
558        {
559          hprecv = arec->precedence;
560 <        hprec = arec->aconf;
560 >        hprec = arec->conf;
561        }
562 +    }
563    }
564  
565    return hprec;
566   }
567  
568 < /* struct AccessItem* find_address_conf(const char*, const char*,
568 > /* struct MaskItem* find_address_conf(const char*, const char*,
569   *                                     struct irc_ssaddr*, int, char *);
570   * Input: The hostname, username, address, address family.
571 < * Output: The applicable AccessItem.
571 > * Output: The applicable MaskItem.
572   * Side-effects: None
573   */
574 < struct AccessItem *
574 > struct MaskItem *
575   find_address_conf(const char *host, const char *user,
576                    struct irc_ssaddr *ip, int aftype, char *password)
577   {
578 <  struct AccessItem *iconf, *kconf;
578 >  struct MaskItem *authcnf = NULL, *killcnf = NULL;
579  
580 <  /* Find the best I-line... If none, return NULL -A1kmm */
581 <  if ((iconf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
582 <                                    password)) == NULL)
583 <    return(NULL);
584 <
585 <  /* If they are exempt from K-lines, return the best I-line. -A1kmm */
586 <  if (IsConfExemptKline(iconf))
587 <    return(iconf);
580 >  /* Find the best auth{} block... If none, return NULL -A1kmm */
581 >  if ((authcnf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
582 >                                      password, 1)) == NULL)
583 >    return NULL;
584 >
585 >  /* If they are exempt from K-lines, return the best auth{} block. -A1kmm */
586 >  if (IsConfExemptKline(authcnf))
587 >    return authcnf;
588  
589    /* Find the best K-line... -A1kmm */
590 <  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 < }
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);
590 >  killcnf = find_conf_by_address(host, ip, CONF_KLINE, aftype, user, NULL, 1);
591  
592 <  return(find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL));
593 < }
592 >  /*
593 >   * If they are K-lined, return the K-line. Otherwise, return the
594 >   * auth{} block. -A1kmm
595 >   */
596 >  if (killcnf != NULL)
597 >    return killcnf;
598  
599 < /* find_kline_conf
600 < *
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;
599 >  if (IsConfExemptGline(authcnf))
600 >    return authcnf;
601  
602 <  eline = find_conf_by_address(host, ip, CONF_EXEMPTKLINE, aftype,
603 <                               user, NULL);
604 <  if (eline != NULL)
606 <    return(eline);
602 >  killcnf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL, 1);
603 >  if (killcnf != NULL)
604 >    return killcnf;
605  
606 <  return(find_conf_by_address(host, ip, CONF_KILL, aftype, user, NULL));
606 >  return authcnf;
607   }
608  
609 < /* struct AccessItem* find_dline_conf(struct irc_ssaddr*, int)
609 > /* struct MaskItem* find_dline_conf(struct irc_ssaddr*, int)
610   *
611   * Input:       An address, an address family.
612   * Output:      The best matching D-line or exempt line.
613   * Side effects: None.
614   */
615 < struct AccessItem *
615 > struct MaskItem *
616   find_dline_conf(struct irc_ssaddr *addr, int aftype)
617   {
618 <  struct AccessItem *eline;
618 >  struct MaskItem *eline;
619  
620 <  eline = find_conf_by_address(NULL, addr, CONF_EXEMPTDLINE | 1, aftype,
621 <                               NULL, NULL);
620 >  eline = find_conf_by_address(NULL, addr, CONF_EXEMPT | 1, aftype,
621 >                               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 | 1, aftype, NULL, NULL, 1);
626   }
627  
628 < /* void add_conf_by_address(int, struct AccessItem *aconf)
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)
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;
641 <  unsigned long hv;
638 >  static unsigned int prec_value = 0xFFFFFFFF;
639 >  int bits = 0;
640    struct AddressRec *arec;
641  
642 <  address = aconf->host;
643 <  username = aconf->user;
642 >  address = conf->host;
643 >  username = conf->user;
644  
645 <  assert(type != 0);
648 <  assert(aconf != NULL);
645 >  assert(type);
646  
647    if (EmptyString(address))
648      address = "/NOMATCH!/";
649  
650    arec = MyMalloc(sizeof(struct AddressRec));
651 <  masktype = parse_netmask(address, &arec->Mask.ipa.addr, &bits);
651 >  arec->masktype = parse_netmask(address, &arec->Mask.ipa.addr, &bits);
652    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 –  }
653    arec->username = username;
654 <  arec->aconf = aconf;
654 >  arec->conf = conf;
655    arec->precedence = prec_value--;
656    arec->type = type;
657 +
658 +  switch (arec->masktype)
659 +  {
660 +    case HM_IPV4:
661 +      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
662 +      bits -= bits % 8;
663 +      dlinkAdd(arec, &arec->node, &atable[hash_ipv4(&arec->Mask.ipa.addr, bits)]);
664 +      break;
665 + #ifdef IPV6
666 +    case HM_IPV6:
667 +      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
668 +      bits -= bits % 16;
669 +      dlinkAdd(arec, &arec->node, &atable[hash_ipv6(&arec->Mask.ipa.addr, bits)]);
670 +      break;
671 + #endif
672 +    default: /* HM_HOST */
673 +      arec->Mask.hostname = address;
674 +      dlinkAdd(arec, &arec->node, &atable[get_mask_hash(address)]);
675 +      break;
676 +  }
677   }
678  
679 < /* void delete_one_address(const char*, struct AccessItem*)
680 < * Input: An address string, the associated AccessItem.
679 > /* void delete_one_address(const char*, struct MaskItem*)
680 > * Input: An address string, the associated MaskItem.
681   * Output: None
682 < * Side effects: Deletes an address record. Frees the AccessItem if there
682 > * Side effects: Deletes an address record. Frees the MaskItem if there
683   *               is nothing referencing it, sets it as illegal otherwise.
684   */
685   void
686 < delete_one_address_conf(const char *address, struct AccessItem *aconf)
686 > delete_one_address_conf(const char *address, struct MaskItem *conf)
687   {
688 <  int masktype, bits;
689 <  unsigned long hv;
690 <  struct AddressRec *arec, *arecl = NULL;
688 >  int bits = 0;
689 >  uint32_t hv = 0;
690 >  dlink_node *ptr = NULL, *ptr_next = NULL;
691    struct irc_ssaddr addr;
699 –  masktype = parse_netmask(address, &addr, &bits);
692  
693 < #ifdef IPV6
702 <  if (masktype == HM_IPV6)
693 >  switch (parse_netmask(address, &addr, &bits))
694    {
695 <    /* We have to do this, since we do not re-hash for every bit -A1kmm. */
696 <    bits -= bits % 16;
697 <    hv = hash_ipv6(&addr, bits);
698 <  }
699 <  else
695 >    case HM_IPV4:
696 >      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
697 >      bits -= bits % 8;
698 >      hv = hash_ipv4(&addr, bits);
699 >      break;
700 > #ifdef IPV6
701 >    case HM_IPV6:
702 >      /* We have to do this, since we do not re-hash for every bit -A1kmm. */
703 >      bits -= bits % 16;
704 >      hv = hash_ipv6(&addr, bits);
705 >      break;
706   #endif
707 <  if (masktype == HM_IPV4)
708 <  {
709 <    /* 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);
707 >    default: /* HM_HOST */
708 >      hv = get_mask_hash(address);
709 >      break;
710    }
711 <  else
712 <    hv = get_mask_hash(address);
718 <  for (arec = atable[hv]; arec; arec = arec->next)
711 >
712 >  DLINK_FOREACH_SAFE(ptr, ptr_next, atable[hv].head)
713    {
714 <    if (arec->aconf == aconf)
714 >    struct AddressRec *arec = ptr->data;
715 >
716 >    if (arec->conf == conf)
717      {
718 <      if (arecl)
719 <        arecl->next = arec->next;
720 <      else
721 <        atable[hv] = arec->next;
722 <      aconf->status |= CONF_ILLEGAL;
727 <      if (aconf->clients == 0)
728 <        free_access_item(aconf);
718 >      dlinkDelete(&arec->node, &atable[hv]);
719 >
720 >      if (!conf->ref_count)
721 >        conf_free(conf);
722 >
723        MyFree(arec);
724        return;
725      }
732 –    arecl = arec;
726    }
727   }
728  
# Line 737 | Line 730 | delete_one_address_conf(const char *addr
730   * Input: None
731   * Output: None
732   * Side effects: Clears out all address records in the hash table,
733 < *               frees them, and frees the AccessItems if nothing references
733 > *               frees them, and frees the MaskItems if nothing references
734   *               them, otherwise sets them as illegal.  
735   */
736   void
737   clear_out_address_conf(void)
738   {
739 <  int i;
740 <  struct AddressRec *arec;
748 <  struct AddressRec *last_arec;
749 <  struct AddressRec *next_arec;
739 >  unsigned int i = 0;
740 >  dlink_node *ptr = NULL, *ptr_next = NULL;
741  
742 <  for (i = 0; i < ATABLE_SIZE; i++)
742 >  for (i = 0; i < ATABLE_SIZE; ++i)
743    {
744 <    last_arec = NULL;
754 <    for (arec = atable[i]; arec; arec = next_arec)
744 >    DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
745      {
746 <      /* We keep the temporary K-lines and destroy the
757 <       * permanent ones, just to be confusing :) -A1kmm
758 <       */  
759 <      next_arec = arec->next;
746 >      struct AddressRec *arec = ptr->data;
747  
748 <      if (arec->aconf->flags & CONF_FLAGS_TEMPORARY)
749 <      {
750 <        last_arec = arec;
751 <      }
752 <      else  
753 <      {
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 <        }
748 >      /*
749 >       * We keep the temporary K-lines and destroy the permanent ones,
750 >       * just to be confusing :) -A1kmm
751 >       */
752 >      if (arec->conf->until || IsConfDatabase(arec->conf))
753 >        continue;
754  
755 <        arec->aconf->status |= CONF_ILLEGAL;
756 <        if (arec->aconf->clients == 0)
757 <          free_access_item(arec->aconf);
758 <        MyFree(arec);
759 <      }
755 >      dlinkDelete(&arec->node, &atable[i]);
756 >
757 >      if (!arec->conf->ref_count)
758 >        conf_free(arec->conf);
759 >      MyFree(arec);
760      }
761    }
762   }
763  
764 < /*
765 < * 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);
828 <
829 <  return(prefix_of_host);
830 < }
831 <
832 < /* report_auth()
833 < *
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)
764 > static void
765 > hostmask_send_expiration(struct AddressRec *arec)
766   {
767 <  struct AddressRec *arec;
842 <  struct ConfItem *conf;
843 <  struct AccessItem *aconf;
844 <  int i;
845 <
846 <  for (i = 0; i < ATABLE_SIZE; i++)
847 <  {
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;
767 >  char ban_type = '\0';
768  
769 <        conf = unmap_conf_item(aconf);
769 >  if (!ConfigFileEntry.tkline_expire_notices)
770 >    return;
771  
772 <        /* We are doing a partial list, based on what matches the u@h of the
773 <         * sender, so prepare the strings for comparing --fl_
774 <         */
775 <        if (ConfigFileEntry.hide_spoof_ips)
776 <          sendto_one(client_p, form_str(RPL_STATSILINE), me.name,
777 <                     client_p->name, 'I',
778 <                     conf->name == NULL ? "*" : conf->name,
779 <                     show_iline_prefix(client_p, aconf, aconf->user),
780 <                     IsConfDoSpoofIp(aconf) ? "255.255.255.255" :
781 <                     aconf->host, aconf->port,
782 <                     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
783 <                    
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 <    }
772 >  switch (arec->type)
773 >  {
774 >    case CONF_KLINE:
775 >      ban_type = 'K';
776 >      break;
777 >    case CONF_DLINE:
778 >      ban_type = 'D';
779 >      break;
780 >    case CONF_GLINE:
781 >      ban_type = 'G';
782 >      break;
783 >    default: break;
784    }
785 +  
786 +  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
787 +                       "Temporary %c-line for [%s@%s] expired", ban_type,
788 +                       (arec->conf->user) ? arec->conf->user : "*",
789 +                       (arec->conf->host) ? arec->conf->host : "*");
790   }
791  
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 – */
792   void
793 < report_Klines(struct Client *client_p, int tkline)
793 > hostmask_expire_temporary(void)
794   {
795 <  struct AddressRec *arec = NULL;
796 <  struct AccessItem *aconf = NULL;
895 <  int i;
896 <  const char *p = NULL;
795 >  unsigned int i = 0;
796 >  dlink_node *ptr = NULL, *ptr_next = NULL;
797  
798 <  if (tkline)
899 <    p = "k";
900 <  else
901 <    p = "K";
902 <
903 <  for (i = 0; i < ATABLE_SIZE; i++)
798 >  for (i = 0; i < ATABLE_SIZE; ++i)
799    {
800 <    for (arec = atable[i]; arec; arec = arec->next)
800 >    DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
801      {
802 <      if (arec->type == CONF_KILL)
802 >      struct AddressRec *arec = ptr->data;
803 >
804 >      if (!arec->conf->until || arec->conf->until > CurrentTime)
805 >        continue;
806 >
807 >      switch (arec->type)
808        {
809 <        if ((tkline && !((aconf = arec->aconf)->flags & CONF_FLAGS_TEMPORARY)) ||
810 <            (!tkline && ((aconf = arec->aconf)->flags & CONF_FLAGS_TEMPORARY)))
811 <          continue;
812 <
813 <        if (IsOper(client_p))
814 <          sendto_one(client_p, form_str(RPL_STATSKLINE), me.name,
815 <                     client_p->name, p, aconf->host, aconf->user,
816 <                     aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
817 <        else
818 <          sendto_one(client_p, form_str(RPL_STATSKLINE), me.name,
919 <                     client_p->name, p, aconf->host, aconf->user,
920 <                     aconf->reason, "");
809 >        case CONF_KLINE:
810 >        case CONF_DLINE:
811 >        case CONF_GLINE:
812 >          hostmask_send_expiration(arec);
813 >
814 >          dlinkDelete(&arec->node, &atable[i]);
815 >          conf_free(arec->conf);
816 >          MyFree(arec);
817 >          break;
818 >        default: break;
819        }
820      }
821    }

Diff Legend

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