ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hostmask.c
Revision: 2898
Committed: Wed Jan 22 18:41:24 2014 UTC (11 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 21294 byte(s)
Log Message:
- hostmask.c: constification

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * hostmask.c: Code to efficiently find IP & hostmask based configs.
4 *
5 * Copyright (C) 2005 by the past and present ircd coders, and others.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 *
22 * $Id$
23 */
24
25 #include "stdinc.h"
26 #include "memory.h"
27 #include "ircd_defs.h"
28 #include "list.h"
29 #include "conf.h"
30 #include "hostmask.h"
31 #include "send.h"
32 #include "irc_string.h"
33 #include "ircd.h"
34
35
36 #define DigitParse(ch) do { \
37 if (ch >= '0' && ch <= '9') \
38 ch = ch - '0'; \
39 else if (ch >= 'A' && ch <= 'F') \
40 ch = ch - 'A' + 10; \
41 else if (ch >= 'a' && ch <= 'f') \
42 ch = ch - 'a' + 10; \
43 } while (0);
44
45 /* The mask parser/type determination code... */
46
47 /* int try_parse_v6_netmask(const char *, struct irc_ssaddr *, int *);
48 * Input: A possible IPV6 address as a string.
49 * Output: An integer describing whether it is an IPV6 or hostmask,
50 * an address(if it is IPV6), a bitlength(if it is IPV6).
51 * Side effects: None
52 * Comments: Called from parse_netmask
53 */
54 /* Fixed so ::/0 (any IPv6 address) is valid
55 Also a bug in DigitParse above.
56 -Gozem 2002-07-19 gozem@linux.nu
57 */
58 #ifdef IPV6
59 static int
60 try_parse_v6_netmask(const char *text, struct irc_ssaddr *addr, int *b)
61 {
62 const char *p;
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 (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 != NULL)
160 *b = bits;
161 return HM_IPV6;
162 }
163 #endif
164
165 /* int try_parse_v4_netmask(const char *, struct irc_ssaddr *, int *);
166 * Input: A possible IPV4 address as a string.
167 * Output: An integer describing whether it is an IPV4 or hostmask,
168 * an address(if it is IPV4), a bitlength(if it is IPV4).
169 * Side effects: None
170 * Comments: Called from parse_netmask
171 */
172 static int
173 try_parse_v4_netmask(const char *text, struct irc_ssaddr *addr, int *b)
174 {
175 const char *p;
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 (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 != NULL)
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 if ((m = bits % 8) == 0)
281 return -1;
282 if ((v6->sin6_addr.s6_addr[n] & ~((1 << (8 - m)) - 1)) ==
283 v6mask->sin6_addr.s6_addr[n])
284 return -1;
285 return 0;
286 }
287 #endif
288
289 /* int match_ipv4(struct irc_ssaddr *, struct irc_ssaddr *, int)
290 * Input: An IP address, an IP mask, the number of bits in the mask.
291 * Output: if match, -1 else 0
292 * Side Effects: None
293 */
294 int
295 match_ipv4(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
296 {
297 const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
298 const struct sockaddr_in *v4mask = (const struct sockaddr_in *)mask;
299
300 if ((ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1)) !=
301 ntohl(v4mask->sin_addr.s_addr))
302 return 0;
303 return -1;
304 }
305
306 /*
307 * mask_addr
308 *
309 * inputs - pointer to the ip to mask
310 * - bitlen
311 * output - NONE
312 * side effects -
313 */
314 void
315 mask_addr(struct irc_ssaddr *ip, int bits)
316 {
317 int mask;
318 #ifdef IPV6
319 struct sockaddr_in6 *v6_base_ip;
320 int i, m, n;
321 #endif
322 struct sockaddr_in *v4_base_ip;
323
324 #ifdef IPV6
325 if (ip->ss.ss_family != AF_INET6)
326 #endif
327 {
328 v4_base_ip = (struct sockaddr_in *)ip;
329
330 mask = ~((1 << (32 - bits)) - 1);
331 v4_base_ip->sin_addr.s_addr = htonl(ntohl(v4_base_ip->sin_addr.s_addr) & mask);
332 }
333 #ifdef IPV6
334 else
335 {
336 n = bits / 8;
337 m = bits % 8;
338 v6_base_ip = (struct sockaddr_in6 *)ip;
339
340 mask = ~((1 << (8 - m)) -1 );
341 v6_base_ip->sin6_addr.s6_addr[n] = v6_base_ip->sin6_addr.s6_addr[n] & mask;
342
343 for (i = n + 1; i < 16; i++)
344 v6_base_ip->sin6_addr.s6_addr[i] = 0;
345 }
346 #endif
347 }
348
349 /* Hashtable stuff...now external as its used in m_stats.c */
350 dlink_list atable[ATABLE_SIZE];
351
352 void
353 init_host_hash(void)
354 {
355 memset(&atable, 0, sizeof(atable));
356 }
357
358 /* unsigned long hash_ipv4(struct irc_ssaddr*)
359 * Input: An IP address.
360 * Output: A hash value of the IP address.
361 * Side effects: None
362 */
363 static uint32_t
364 hash_ipv4(const struct irc_ssaddr *addr, int bits)
365 {
366 if (bits != 0)
367 {
368 const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
369 uint32_t av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
370
371 return (av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1);
372 }
373
374 return 0;
375 }
376
377 /* unsigned long hash_ipv6(struct irc_ssaddr*)
378 * Input: An IP address.
379 * Output: A hash value of the IP address.
380 * Side effects: None
381 */
382 #ifdef IPV6
383 static uint32_t
384 hash_ipv6(const struct irc_ssaddr *addr, int bits)
385 {
386 uint32_t v = 0, n;
387 const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
388
389 for (n = 0; n < 16; n++)
390 {
391 if (bits >= 8)
392 {
393 v ^= v6->sin6_addr.s6_addr[n];
394 bits -= 8;
395 }
396 else if (bits)
397 {
398 v ^= v6->sin6_addr.s6_addr[n] & ~((1 << (8 - bits)) - 1);
399 return v & (ATABLE_SIZE - 1);
400 }
401 else
402 return v & (ATABLE_SIZE - 1);
403 }
404 return v & (ATABLE_SIZE - 1);
405 }
406 #endif
407
408 /* int hash_text(const char *start)
409 * Input: The start of the text to hash.
410 * Output: The hash of the string between 1 and (TH_MAX-1)
411 * Side-effects: None.
412 */
413 static uint32_t
414 hash_text(const char *start)
415 {
416 const char *p = start;
417 uint32_t h = 0;
418
419 for (; *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 (username == NULL)
466 username = "";
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 & ~0x1) &&
483 arec->precedence > hprecv &&
484 arec->masktype == HM_IPV6 &&
485 match_ipv6(addr, &arec->Mask.ipa.addr,
486 arec->Mask.ipa.bits) &&
487 (type & 0x1 || !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 & ~0x1) &&
508 arec->precedence > hprecv &&
509 arec->masktype == HM_IPV4 &&
510 match_ipv4(addr, &arec->Mask.ipa.addr,
511 arec->Mask.ipa.bits) &&
512 (type & 0x1 || !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 & ~0x1)) &&
534 arec->precedence > hprecv &&
535 (arec->masktype == HM_HOST) &&
536 !cmpfunc(arec->Mask.hostname, name) &&
537 (type & 0x1 || !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 & ~0x1) &&
556 arec->precedence > hprecv &&
557 arec->masktype == HM_HOST &&
558 !cmpfunc(arec->Mask.hostname, name) &&
559 (type & 0x1 || !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 | 1, aftype,
625 NULL, NULL, 1);
626 if (eline != NULL)
627 return eline;
628
629 return find_conf_by_address(NULL, addr, CONF_DLINE | 1, aftype, NULL, NULL, 1);
630 }
631
632 /* void add_conf_by_address(int, struct MaskItem *aconf)
633 * Input:
634 * Output: None
635 * Side-effects: Adds this entry to the hash table.
636 */
637 struct AddressRec *
638 add_conf_by_address(const unsigned int type, struct MaskItem *conf)
639 {
640 const char *address;
641 const char *username;
642 static unsigned int prec_value = 0xFFFFFFFF;
643 int bits = 0;
644 struct AddressRec *arec;
645
646 address = conf->host;
647 username = conf->user;
648
649 assert(type);
650
651 if (EmptyString(address))
652 address = "/NOMATCH!/";
653
654 arec = MyMalloc(sizeof(struct AddressRec));
655 arec->masktype = parse_netmask(address, &arec->Mask.ipa.addr, &bits);
656 arec->Mask.ipa.bits = bits;
657 arec->username = username;
658 arec->conf = conf;
659 arec->precedence = prec_value--;
660 arec->type = type;
661
662 switch (arec->masktype)
663 {
664 case HM_IPV4:
665 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
666 bits -= bits % 8;
667 dlinkAdd(arec, &arec->node, &atable[hash_ipv4(&arec->Mask.ipa.addr, bits)]);
668 break;
669 #ifdef IPV6
670 case HM_IPV6:
671 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
672 bits -= bits % 16;
673 dlinkAdd(arec, &arec->node, &atable[hash_ipv6(&arec->Mask.ipa.addr, bits)]);
674 break;
675 #endif
676 default: /* HM_HOST */
677 arec->Mask.hostname = address;
678 dlinkAdd(arec, &arec->node, &atable[get_mask_hash(address)]);
679 break;
680 }
681
682 return arec;
683 }
684
685 /* void delete_one_address(const char*, struct MaskItem*)
686 * Input: An address string, the associated MaskItem.
687 * Output: None
688 * Side effects: Deletes an address record. Frees the MaskItem if there
689 * is nothing referencing it, sets it as illegal otherwise.
690 */
691 void
692 delete_one_address_conf(const char *address, struct MaskItem *conf)
693 {
694 int bits = 0;
695 uint32_t hv = 0;
696 dlink_node *ptr = NULL, *ptr_next = NULL;
697 struct irc_ssaddr addr;
698
699 switch (parse_netmask(address, &addr, &bits))
700 {
701 case HM_IPV4:
702 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
703 bits -= bits % 8;
704 hv = hash_ipv4(&addr, bits);
705 break;
706 #ifdef IPV6
707 case HM_IPV6:
708 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
709 bits -= bits % 16;
710 hv = hash_ipv6(&addr, bits);
711 break;
712 #endif
713 default: /* HM_HOST */
714 hv = get_mask_hash(address);
715 break;
716 }
717
718 DLINK_FOREACH_SAFE(ptr, ptr_next, atable[hv].head)
719 {
720 struct AddressRec *arec = ptr->data;
721
722 if (arec->conf == conf)
723 {
724 dlinkDelete(&arec->node, &atable[hv]);
725
726 if (!conf->ref_count)
727 conf_free(conf);
728
729 MyFree(arec);
730 return;
731 }
732 }
733 }
734
735 /* void clear_out_address_conf(void)
736 * Input: None
737 * Output: None
738 * Side effects: Clears out all address records in the hash table,
739 * frees them, and frees the MaskItems if nothing references
740 * them, otherwise sets them as illegal.
741 */
742 void
743 clear_out_address_conf(void)
744 {
745 unsigned int i = 0;
746 dlink_node *ptr = NULL, *ptr_next = NULL;
747
748 for (i = 0; i < ATABLE_SIZE; ++i)
749 {
750 DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
751 {
752 struct AddressRec *arec = ptr->data;
753
754 /*
755 * We keep the temporary K-lines and destroy the permanent ones,
756 * just to be confusing :) -A1kmm
757 */
758 if (arec->conf->until || IsConfDatabase(arec->conf))
759 continue;
760
761 dlinkDelete(&arec->node, &atable[i]);
762
763 if (!arec->conf->ref_count)
764 conf_free(arec->conf);
765 MyFree(arec);
766 }
767 }
768 }
769
770 static void
771 hostmask_send_expiration(struct AddressRec *arec)
772 {
773 char ban_type = '\0';
774
775 if (!ConfigFileEntry.tkline_expire_notices)
776 return;
777
778 switch (arec->type)
779 {
780 case CONF_KLINE:
781 ban_type = 'K';
782 break;
783 case CONF_DLINE:
784 ban_type = 'D';
785 break;
786 case CONF_GLINE:
787 ban_type = 'G';
788 break;
789 default: break;
790 }
791
792 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
793 "Temporary %c-line for [%s@%s] expired", ban_type,
794 (arec->conf->user) ? arec->conf->user : "*",
795 (arec->conf->host) ? arec->conf->host : "*");
796 }
797
798 void
799 hostmask_expire_temporary(void)
800 {
801 unsigned int i = 0;
802 dlink_node *ptr = NULL, *ptr_next = NULL;
803
804 for (i = 0; i < ATABLE_SIZE; ++i)
805 {
806 DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
807 {
808 struct AddressRec *arec = ptr->data;
809
810 if (!arec->conf->until || arec->conf->until > CurrentTime)
811 continue;
812
813 switch (arec->type)
814 {
815 case CONF_KLINE:
816 case CONF_DLINE:
817 case CONF_GLINE:
818 hostmask_send_expiration(arec);
819
820 dlinkDelete(&arec->node, &atable[i]);
821 conf_free(arec->conf);
822 MyFree(arec);
823 break;
824 default: break;
825 }
826 }
827 }
828 }

Properties

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