ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hostmask.c
Revision: 3535
Committed: Thu May 15 15:46:25 2014 UTC (11 years, 3 months ago) by michael
Content type: text/x-csrc
File size: 21012 byte(s)
Log Message:
- hostmask.c:delete_one_address_conf(): replaced a DLINK_FOREACH_SAFE with DLINK_FOREACH

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

Properties

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