ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hostmask.c
Revision: 4415
Committed: Thu Aug 7 14:09:36 2014 UTC (11 years ago) by michael
Content type: text/x-csrc
File size: 20861 byte(s)
Log Message:
- Removed ipv6 detection. We now assume all systems that run hybrid have
  ipv6 availability and sockaddr_storage.

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
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
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
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
19 * USA
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 "list.h"
31 #include "conf.h"
32 #include "hostmask.h"
33 #include "send.h"
34 #include "irc_string.h"
35 #include "ircd.h"
36
37
38 #define DigitParse(ch) do { \
39 if (ch >= '0' && ch <= '9') \
40 ch = ch - '0'; \
41 else if (ch >= 'A' && ch <= 'F') \
42 ch = ch - 'A' + 10; \
43 else if (ch >= 'a' && ch <= 'f') \
44 ch = ch - 'a' + 10; \
45 } while (0);
46
47 /* The mask parser/type determination code... */
48
49 /* int try_parse_v6_netmask(const char *, struct irc_ssaddr *, int *);
50 * Input: A possible IPV6 address as a string.
51 * Output: An integer describing whether it is an IPV6 or hostmask,
52 * an address(if it is IPV6), a bitlength(if it is IPV6).
53 * Side effects: None
54 * Comments: Called from parse_netmask
55 */
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 */
60 static int
61 try_parse_v6_netmask(const char *text, struct irc_ssaddr *addr, int *b)
62 {
63 char c;
64 int d[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
65 int dp = 0;
66 int nyble = 4;
67 int finsert = -1;
68 int bits = 128;
69 int deficit = 0;
70 short dc[8];
71 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
72
73 for (const char *p = text; (c = *p); ++p)
74 {
75 if (IsXDigit(c))
76 {
77 if (nyble == 0)
78 return HM_HOST;
79 DigitParse(c);
80 d[dp] |= c << (4 * --nyble);
81 }
82 else if (c == ':')
83 {
84 if (p > text && *(p - 1) == ':')
85 {
86 if (finsert >= 0)
87 return HM_HOST;
88 finsert = dp;
89 }
90 else
91 {
92 /* If there were less than 4 hex digits, e.g. :ABC: shift right
93 * so we don't interpret it as ABC0 -A1kmm */
94 d[dp] = d[dp] >> 4 * nyble;
95 nyble = 4;
96 if (++dp >= 8)
97 return HM_HOST;
98 }
99 }
100 else if (c == '*')
101 {
102 /* * must be last, and * is ambiguous if there is a ::... -A1kmm */
103 if (finsert >= 0 || *(p + 1) || dp == 0 || *(p - 1) != ':')
104 return HM_HOST;
105 bits = dp * 16;
106 }
107 else if (c == '/')
108 {
109 char *after;
110
111 d[dp] = d[dp] >> 4 * nyble;
112 ++dp;
113 bits = strtoul(p + 1, &after, 10);
114
115 if (bits < 0 || *after)
116 return HM_HOST;
117 if (bits > dp * 4 && !(finsert >= 0 && bits <= 128))
118 return HM_HOST;
119 break;
120 }
121 else
122 return HM_HOST;
123 }
124
125 d[dp] = d[dp] >> 4 * nyble;
126
127 if (c == 0)
128 ++dp;
129 if (finsert < 0 && bits == 0)
130 bits = dp * 16;
131
132 /* How many words are missing? -A1kmm */
133 deficit = bits / 16 + ((bits % 16) ? 1 : 0) - dp;
134
135 /* Now fill in the gaps(from ::) in the copied table... -A1kmm */
136 for (dp = 0, nyble = 0; dp < 8; ++dp)
137 {
138 if (nyble == finsert && deficit)
139 {
140 dc[dp] = 0;
141 deficit--;
142 }
143 else
144 dc[dp] = d[nyble++];
145 }
146
147 /* Set unused bits to 0... -A1kmm */
148 if (bits < 128 && (bits % 16 != 0))
149 dc[bits / 16] &= ~((1 << (15 - bits % 16)) - 1);
150 for (dp = bits / 16 + (bits % 16 ? 1 : 0); dp < 8; ++dp)
151 dc[dp] = 0;
152
153 /* And assign... -A1kmm */
154 if (addr)
155 for (dp = 0; dp < 8; ++dp)
156 /* The cast is a kludge to make netbsd work. */
157 ((unsigned short *)&v6->sin6_addr)[dp] = htons(dc[dp]);
158
159 if (b)
160 *b = bits;
161 return HM_IPV6;
162 }
163
164 /* int try_parse_v4_netmask(const char *, struct irc_ssaddr *, int *);
165 * Input: A possible IPV4 address as a string.
166 * Output: An integer describing whether it is an IPV4 or hostmask,
167 * an address(if it is IPV4), a bitlength(if it is IPV4).
168 * Side effects: None
169 * Comments: Called from parse_netmask
170 */
171 static int
172 try_parse_v4_netmask(const char *text, struct irc_ssaddr *addr, int *b)
173 {
174 const char *digits[4];
175 unsigned char addb[4];
176 int n = 0, bits = 0;
177 char c;
178 struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
179
180 digits[n++] = text;
181
182 for (const char *p = text; (c = *p); ++p)
183 {
184 if (c >= '0' && c <= '9') /* empty */
185 ;
186 else if (c == '.')
187 {
188 if (n >= 4)
189 return HM_HOST;
190
191 digits[n++] = p + 1;
192 }
193 else if (c == '*')
194 {
195 if (*(p + 1) || n == 0 || *(p - 1) != '.')
196 return HM_HOST;
197
198 bits = (n - 1) * 8;
199 break;
200 }
201 else if (c == '/')
202 {
203 char *after;
204 bits = strtoul(p + 1, &after, 10);
205
206 if (bits < 0 || *after)
207 return HM_HOST;
208 if (bits > n * 8)
209 return HM_HOST;
210
211 break;
212 }
213 else
214 return HM_HOST;
215 }
216
217 if (n < 4 && bits == 0)
218 bits = n * 8;
219 if (bits)
220 while (n < 4)
221 digits[n++] = "0";
222
223 for (n = 0; n < 4; ++n)
224 addb[n] = strtoul(digits[n], NULL, 10);
225
226 if (bits == 0)
227 bits = 32;
228
229 /* Set unused bits to 0... -A1kmm */
230 if (bits < 32 && bits % 8)
231 addb[bits / 8] &= ~((1 << (8 - bits % 8)) - 1);
232 for (n = bits / 8 + (bits % 8 ? 1 : 0); n < 4; ++n)
233 addb[n] = 0;
234 if (addr)
235 v4->sin_addr.s_addr =
236 htonl(addb[0] << 24 | addb[1] << 16 | addb[2] << 8 | addb[3]);
237 if (b)
238 *b = bits;
239 return HM_IPV4;
240 }
241
242 /* int parse_netmask(const char *, struct irc_ssaddr *, int *);
243 * Input: A hostmask, or an IPV4/6 address.
244 * Output: An integer describing whether it is an IPV4, IPV6 address or a
245 * hostmask, an address(if it is an IP mask),
246 * a bitlength(if it is IP mask).
247 * Side effects: None
248 */
249 int
250 parse_netmask(const char *text, struct irc_ssaddr *addr, int *b)
251 {
252 if (strchr(text, '.'))
253 return try_parse_v4_netmask(text, addr, b);
254 if (strchr(text, ':'))
255 return try_parse_v6_netmask(text, addr, b);
256
257 return HM_HOST;
258 }
259
260 /* The address matching stuff... */
261 /* int match_ipv6(struct irc_ssaddr *, struct irc_ssaddr *, int)
262 * Input: An IP address, an IP mask, the number of bits in the mask.
263 * Output: if match, -1 else 0
264 * Side effects: None
265 */
266 int
267 match_ipv6(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
268 {
269 int i, m, n = bits / 8;
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])
275 return 0;
276
277 if ((m = bits % 8) == 0)
278 return -1;
279 if ((v6->sin6_addr.s6_addr[n] & ~((1 << (8 - m)) - 1)) ==
280 v6mask->sin6_addr.s6_addr[n])
281 return -1;
282 return 0;
283 }
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(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
292 {
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;
299 return -1;
300 }
301
302 /*
303 * mask_addr
304 *
305 * inputs - pointer to the ip to mask
306 * - bitlen
307 * output - NONE
308 * side effects -
309 */
310 void
311 mask_addr(struct irc_ssaddr *ip, int bits)
312 {
313 int mask;
314 struct sockaddr_in6 *v6_base_ip;
315 int i, m, n;
316 struct sockaddr_in *v4_base_ip;
317
318 if (ip->ss.ss_family == AF_INET)
319 {
320 uint32_t tmp = 0;
321 v4_base_ip = (struct sockaddr_in *)ip;
322
323 mask = ~((1 << (32 - bits)) - 1);
324 tmp = ntohl(v4_base_ip->sin_addr.s_addr);
325 v4_base_ip->sin_addr.s_addr = htonl(tmp & mask);
326 }
327 else
328 {
329 n = bits / 8;
330 m = bits % 8;
331 v6_base_ip = (struct sockaddr_in6 *)ip;
332
333 mask = ~((1 << (8 - m)) -1 );
334 v6_base_ip->sin6_addr.s6_addr[n] = v6_base_ip->sin6_addr.s6_addr[n] & mask;
335
336 for (i = n + 1; i < 16; i++)
337 v6_base_ip->sin6_addr.s6_addr[i] = 0;
338 }
339 }
340
341 /* Hashtable stuff...now external as it's used in m_stats.c */
342 dlink_list atable[ATABLE_SIZE];
343
344 void
345 init_host_hash(void)
346 {
347 memset(&atable, 0, sizeof(atable));
348 }
349
350 /* unsigned long hash_ipv4(struct irc_ssaddr*)
351 * Input: An IP address.
352 * Output: A hash value of the IP address.
353 * Side effects: None
354 */
355 static uint32_t
356 hash_ipv4(const struct irc_ssaddr *addr, int bits)
357 {
358 if (bits != 0)
359 {
360 const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
361 uint32_t av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
362
363 return (av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1);
364 }
365
366 return 0;
367 }
368
369 /* unsigned long hash_ipv6(struct irc_ssaddr*)
370 * Input: An IP address.
371 * Output: A hash value of the IP address.
372 * Side effects: None
373 */
374 static uint32_t
375 hash_ipv6(const struct irc_ssaddr *addr, int bits)
376 {
377 uint32_t v = 0, n;
378 const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
379
380 for (n = 0; n < 16; ++n)
381 {
382 if (bits >= 8)
383 {
384 v ^= v6->sin6_addr.s6_addr[n];
385 bits -= 8;
386 }
387 else if (bits)
388 {
389 v ^= v6->sin6_addr.s6_addr[n] & ~((1 << (8 - bits)) - 1);
390 return v & (ATABLE_SIZE - 1);
391 }
392 else
393 return v & (ATABLE_SIZE - 1);
394 }
395
396 return v & (ATABLE_SIZE - 1);
397 }
398
399 /* int hash_text(const char *start)
400 * Input: The start of the text to hash.
401 * Output: The hash of the string between 1 and (TH_MAX-1)
402 * Side-effects: None.
403 */
404 static uint32_t
405 hash_text(const char *start)
406 {
407 uint32_t h = 0;
408
409 for (const char *p = start; *p; ++p)
410 h = (h << 4) - (h + ToLower(*p));
411
412 return h & (ATABLE_SIZE - 1);
413 }
414
415 /* unsigned long get_hash_mask(const char *)
416 * Input: The text to hash.
417 * Output: The hash of the string right of the first '.' past the last
418 * wildcard in the string.
419 * Side-effects: None.
420 */
421 static uint32_t
422 get_mask_hash(const char *text)
423 {
424 const char *hp = "", *p;
425
426 for (p = text + strlen(text) - 1; p >= text; --p)
427 if (IsMWildChar(*p))
428 return hash_text(hp);
429 else if (*p == '.')
430 hp = p + 1;
431 return hash_text(text);
432 }
433
434 /* struct MaskItem *find_conf_by_address(const char *, struct irc_ssaddr *,
435 * int type, int fam, const char *username)
436 * Input: The hostname, the address, the type of mask to find, the address
437 * family, the username.
438 * Output: The matching value with the highest precedence.
439 * Side-effects: None
440 * Note: Setting bit 0 of the type means that the username is ignored.
441 * Warning: IsNeedPassword for everything that is not an auth{} entry
442 * should always be true (i.e. conf->flags & CONF_FLAGS_NEED_PASSWORD == 0)
443 */
444 struct MaskItem *
445 find_conf_by_address(const char *name, struct irc_ssaddr *addr, unsigned int type,
446 int fam, const char *username, const char *password, int do_match)
447 {
448 unsigned int hprecv = 0;
449 dlink_node *ptr = NULL;
450 struct MaskItem *hprec = NULL;
451 struct AddressRec *arec = NULL;
452 int b;
453 int (*cmpfunc)(const char *, const char *) = do_match ? match : irccmp;
454
455 if (addr)
456 {
457 /* Check for IPV6 matches... */
458 if (fam == AF_INET6)
459 {
460 for (b = 128; b >= 0; b -= 16)
461 {
462 DLINK_FOREACH(ptr, atable[hash_ipv6(addr, b)].head)
463 {
464 arec = ptr->data;
465
466 if ((arec->type == type) &&
467 arec->precedence > hprecv &&
468 arec->masktype == HM_IPV6 &&
469 match_ipv6(addr, &arec->Mask.ipa.addr,
470 arec->Mask.ipa.bits) &&
471 (!username || !cmpfunc(arec->username, username)) &&
472 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
473 match_conf_password(password, arec->conf)))
474 {
475 hprecv = arec->precedence;
476 hprec = arec->conf;
477 }
478 }
479 }
480 }
481 else if (fam == AF_INET)
482 {
483 for (b = 32; b >= 0; b -= 8)
484 {
485 DLINK_FOREACH(ptr, atable[hash_ipv4(addr, b)].head)
486 {
487 arec = ptr->data;
488
489 if ((arec->type == type) &&
490 arec->precedence > hprecv &&
491 arec->masktype == HM_IPV4 &&
492 match_ipv4(addr, &arec->Mask.ipa.addr,
493 arec->Mask.ipa.bits) &&
494 (!username || !cmpfunc(arec->username, username)) &&
495 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
496 match_conf_password(password, arec->conf)))
497 {
498 hprecv = arec->precedence;
499 hprec = arec->conf;
500 }
501 }
502 }
503 }
504 }
505
506 if (name)
507 {
508 const char *p = name;
509
510 while (1)
511 {
512 DLINK_FOREACH(ptr, atable[hash_text(p)].head)
513 {
514 arec = ptr->data;
515 if ((arec->type == type) &&
516 arec->precedence > hprecv &&
517 (arec->masktype == HM_HOST) &&
518 !cmpfunc(arec->Mask.hostname, name) &&
519 (!username || !cmpfunc(arec->username, username)) &&
520 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
521 match_conf_password(password, arec->conf)))
522 {
523 hprecv = arec->precedence;
524 hprec = arec->conf;
525 }
526 }
527
528 if ((p = strchr(p, '.')) == NULL)
529 break;
530 ++p;
531 }
532
533 DLINK_FOREACH(ptr, atable[0].head)
534 {
535 arec = ptr->data;
536
537 if (arec->type == type &&
538 arec->precedence > hprecv &&
539 arec->masktype == HM_HOST &&
540 !cmpfunc(arec->Mask.hostname, name) &&
541 (!username || !cmpfunc(arec->username, username)) &&
542 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
543 match_conf_password(password, arec->conf)))
544 {
545 hprecv = arec->precedence;
546 hprec = arec->conf;
547 }
548 }
549 }
550
551 return hprec;
552 }
553
554 /* struct MaskItem* find_address_conf(const char*, const char*,
555 * struct irc_ssaddr*, int, char *);
556 * Input: The hostname, username, address, address family.
557 * Output: The applicable MaskItem.
558 * Side-effects: None
559 */
560 struct MaskItem *
561 find_address_conf(const char *host, const char *user, struct irc_ssaddr *ip,
562 int aftype, const char *password)
563 {
564 struct MaskItem *authcnf = NULL, *killcnf = NULL;
565
566 /* Find the best auth{} block... If none, return NULL -A1kmm */
567 if ((authcnf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
568 password, 1)) == NULL)
569 return NULL;
570
571 /* If they are exempt from K-lines, return the best auth{} block. -A1kmm */
572 if (IsConfExemptKline(authcnf))
573 return authcnf;
574
575 /* Find the best K-line... -A1kmm */
576 killcnf = find_conf_by_address(host, ip, CONF_KLINE, aftype, user, NULL, 1);
577
578 /*
579 * If they are K-lined, return the K-line. Otherwise, return the
580 * auth{} block. -A1kmm
581 */
582 if (killcnf)
583 return killcnf;
584
585 if (IsConfExemptGline(authcnf))
586 return authcnf;
587
588 killcnf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL, 1);
589 if (killcnf)
590 return killcnf;
591
592 return authcnf;
593 }
594
595 /* struct MaskItem* find_dline_conf(struct irc_ssaddr*, int)
596 *
597 * Input: An address, an address family.
598 * Output: The best matching D-line or exempt line.
599 * Side effects: None.
600 */
601 struct MaskItem *
602 find_dline_conf(struct irc_ssaddr *addr, int aftype)
603 {
604 struct MaskItem *eline;
605
606 eline = find_conf_by_address(NULL, addr, CONF_EXEMPT, aftype, NULL, NULL, 1);
607 if (eline)
608 return eline;
609
610 return find_conf_by_address(NULL, addr, CONF_DLINE, aftype, NULL, NULL, 1);
611 }
612
613 /* void add_conf_by_address(int, struct MaskItem *aconf)
614 * Input:
615 * Output: None
616 * Side-effects: Adds this entry to the hash table.
617 */
618 struct AddressRec *
619 add_conf_by_address(const unsigned int type, struct MaskItem *conf)
620 {
621 const char *hostname = conf->host;
622 const char *username = conf->user;
623 static unsigned int prec_value = 0xFFFFFFFF;
624 int bits = 0;
625 struct AddressRec *arec = NULL;
626
627 assert(type && !EmptyString(hostname));
628
629 arec = MyCalloc(sizeof(struct AddressRec));
630 arec->masktype = parse_netmask(hostname, &arec->Mask.ipa.addr, &bits);
631 arec->Mask.ipa.bits = bits;
632 arec->username = username;
633 arec->conf = conf;
634 arec->precedence = prec_value--;
635 arec->type = type;
636
637 switch (arec->masktype)
638 {
639 case HM_IPV4:
640 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
641 bits -= bits % 8;
642 dlinkAdd(arec, &arec->node, &atable[hash_ipv4(&arec->Mask.ipa.addr, bits)]);
643 break;
644 case HM_IPV6:
645 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
646 bits -= bits % 16;
647 dlinkAdd(arec, &arec->node, &atable[hash_ipv6(&arec->Mask.ipa.addr, bits)]);
648 break;
649 default: /* HM_HOST */
650 arec->Mask.hostname = hostname;
651 dlinkAdd(arec, &arec->node, &atable[get_mask_hash(hostname)]);
652 break;
653 }
654
655 return arec;
656 }
657
658 /* void delete_one_address(const char*, struct MaskItem*)
659 * Input: An address string, the associated MaskItem.
660 * Output: None
661 * Side effects: Deletes an address record. Frees the MaskItem if there
662 * is nothing referencing it, sets it as illegal otherwise.
663 */
664 void
665 delete_one_address_conf(const char *address, struct MaskItem *conf)
666 {
667 int bits = 0;
668 uint32_t hv = 0;
669 dlink_node *ptr = NULL;
670 struct irc_ssaddr addr;
671
672 switch (parse_netmask(address, &addr, &bits))
673 {
674 case HM_IPV4:
675 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
676 bits -= bits % 8;
677 hv = hash_ipv4(&addr, bits);
678 break;
679 case HM_IPV6:
680 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
681 bits -= bits % 16;
682 hv = hash_ipv6(&addr, bits);
683 break;
684 default: /* HM_HOST */
685 hv = get_mask_hash(address);
686 break;
687 }
688
689 DLINK_FOREACH(ptr, atable[hv].head)
690 {
691 struct AddressRec *arec = ptr->data;
692
693 if (arec->conf == conf)
694 {
695 dlinkDelete(&arec->node, &atable[hv]);
696
697 if (!conf->ref_count)
698 conf_free(conf);
699
700 MyFree(arec);
701 return;
702 }
703 }
704 }
705
706 /* void clear_out_address_conf(void)
707 * Input: None
708 * Output: None
709 * Side effects: Clears out all address records in the hash table,
710 * frees them, and frees the MaskItems if nothing references
711 * them, otherwise sets them as illegal.
712 */
713 void
714 clear_out_address_conf(void)
715 {
716 dlink_node *ptr = NULL, *ptr_next = NULL;
717
718 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
719 {
720 DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
721 {
722 struct AddressRec *arec = ptr->data;
723
724 /*
725 * We keep the temporary K-lines and destroy the permanent ones,
726 * just to be confusing :) -A1kmm
727 */
728 if (arec->conf->until || IsConfDatabase(arec->conf))
729 continue;
730
731 dlinkDelete(&arec->node, &atable[i]);
732
733 if (!arec->conf->ref_count)
734 conf_free(arec->conf);
735 MyFree(arec);
736 }
737 }
738 }
739
740 static void
741 hostmask_send_expiration(struct AddressRec *arec)
742 {
743 char ban_type = '\0';
744
745 if (!ConfigGeneral.tkline_expire_notices)
746 return;
747
748 switch (arec->type)
749 {
750 case CONF_KLINE:
751 ban_type = 'K';
752 break;
753 case CONF_DLINE:
754 ban_type = 'D';
755 break;
756 case CONF_GLINE:
757 ban_type = 'G';
758 break;
759 default: break;
760 }
761
762 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
763 "Temporary %c-line for [%s@%s] expired", ban_type,
764 (arec->conf->user) ? arec->conf->user : "*",
765 (arec->conf->host) ? arec->conf->host : "*");
766 }
767
768 void
769 hostmask_expire_temporary(void)
770 {
771 dlink_node *ptr = NULL, *ptr_next = NULL;
772
773 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
774 {
775 DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
776 {
777 struct AddressRec *arec = ptr->data;
778
779 if (!arec->conf->until || arec->conf->until > CurrentTime)
780 continue;
781
782 switch (arec->type)
783 {
784 case CONF_KLINE:
785 case CONF_DLINE:
786 case CONF_GLINE:
787 hostmask_send_expiration(arec);
788
789 dlinkDelete(&arec->node, &atable[i]);
790 conf_free(arec->conf);
791 MyFree(arec);
792 break;
793 default: break;
794 }
795 }
796 }
797 }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision