ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hostmask.c
Revision: 3003
Committed: Wed Feb 19 10:05:57 2014 UTC (12 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 21174 byte(s)
Log Message:
- hostmask.c:add_conf_by_address(): fixed assert statement

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

Properties

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