/[svn]/ircd-hybrid/branches/8.2.x/src/hostmask.c
ViewVC logotype

Contents of /ircd-hybrid/branches/8.2.x/src/hostmask.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6581 - (show annotations)
Mon Oct 19 19:52:30 2015 UTC (3 years, 8 months ago) by michael
File MIME type: text/x-chdr
File size: 20543 byte(s)
- hostmask.c: style correction

1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 2001-2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
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 /* Hashtable stuff...now external as it's used in m_stats.c */
48 dlink_list atable[ATABLE_SIZE];
49
50 /* The mask parser/type determination code... */
51
52 /* int try_parse_v6_netmask(const char *, struct irc_ssaddr *, int *);
53 * Input: A possible IPV6 address as a string.
54 * Output: An integer describing whether it is an IPV6 or hostmask,
55 * an address(if it is IPV6), a bitlength(if it is IPV6).
56 * Side effects: None
57 * Comments: Called from parse_netmask
58 */
59 static int
60 try_parse_v6_netmask(const char *text, struct irc_ssaddr *addr, int *b)
61 {
62 char c;
63 int d[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
64 int dp = 0;
65 int nyble = 4;
66 int finsert = -1;
67 int bits = 128;
68 int deficit = 0;
69 short dc[8];
70 struct sockaddr_in6 *const v6 = (struct sockaddr_in6 *)addr;
71
72 for (const char *p = text; (c = *p); ++p)
73 {
74 if (IsXDigit(c))
75 {
76 if (nyble == 0)
77 return HM_HOST;
78 DigitParse(c);
79 d[dp] |= c << (4 * --nyble);
80 }
81 else if (c == ':')
82 {
83 if (p > text && *(p - 1) == ':')
84 {
85 if (finsert >= 0)
86 return HM_HOST;
87 finsert = dp;
88 }
89 else
90 {
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 */
95 d[dp] = d[dp] >> 4 * nyble;
96 nyble = 4;
97
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)
162 *b = bits;
163 return HM_IPV6;
164 }
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 *const 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 == 1 || *(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 if (strchr(text, ':'))
257 return try_parse_v6_netmask(text, addr, b);
258
259 return HM_HOST;
260 }
261
262 /* The address matching stuff... */
263 /* int match_ipv6(struct irc_ssaddr *, struct irc_ssaddr *, int)
264 * Input: An IP address, an IP mask, the number of bits in the mask.
265 * Output: if match, -1 else 0
266 * Side effects: None
267 */
268 int
269 match_ipv6(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
270 {
271 int i, m, n = bits / 8;
272 const struct sockaddr_in6 *const v6 = (const struct sockaddr_in6 *)addr;
273 const struct sockaddr_in6 *const v6mask = (const struct sockaddr_in6 *)mask;
274
275 for (i = 0; i < n; ++i)
276 if (v6->sin6_addr.s6_addr[i] != v6mask->sin6_addr.s6_addr[i])
277 return 0;
278
279 if ((m = bits % 8) == 0)
280 return -1;
281 if ((v6->sin6_addr.s6_addr[n] & ~((1 << (8 - m)) - 1)) ==
282 v6mask->sin6_addr.s6_addr[n])
283 return -1;
284 return 0;
285 }
286
287 /* int match_ipv4(struct irc_ssaddr *, struct irc_ssaddr *, int)
288 * Input: An IP address, an IP mask, the number of bits in the mask.
289 * Output: if match, -1 else 0
290 * Side Effects: None
291 */
292 int
293 match_ipv4(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
294 {
295 const struct sockaddr_in *const v4 = (const struct sockaddr_in *)addr;
296 const struct sockaddr_in *const v4mask = (const struct sockaddr_in *)mask;
297
298 if ((ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1)) !=
299 ntohl(v4mask->sin_addr.s_addr))
300 return 0;
301 return -1;
302 }
303
304 /*
305 * mask_addr
306 *
307 * inputs - pointer to the ip to mask
308 * - bitlen
309 * output - NONE
310 * side effects -
311 */
312 void
313 mask_addr(struct irc_ssaddr *ip, int bits)
314 {
315 int mask;
316 struct sockaddr_in6 *v6_base_ip;
317 int i, m, n;
318 struct sockaddr_in *v4_base_ip;
319
320 if (ip->ss.ss_family == AF_INET)
321 {
322 uint32_t tmp = 0;
323 v4_base_ip = (struct sockaddr_in *)ip;
324
325 mask = ~((1 << (32 - bits)) - 1);
326 tmp = ntohl(v4_base_ip->sin_addr.s_addr);
327 v4_base_ip->sin_addr.s_addr = htonl(tmp & mask);
328 }
329 else
330 {
331 n = bits / 8;
332 m = bits % 8;
333 v6_base_ip = (struct sockaddr_in6 *)ip;
334
335 mask = ~((1 << (8 - m)) - 1);
336 v6_base_ip->sin6_addr.s6_addr[n] = v6_base_ip->sin6_addr.s6_addr[n] & mask;
337
338 for (i = n + 1; i < 16; i++)
339 v6_base_ip->sin6_addr.s6_addr[i] = 0;
340 }
341 }
342
343 /* unsigned long hash_ipv4(struct irc_ssaddr*)
344 * Input: An IP address.
345 * Output: A hash value of the IP address.
346 * Side effects: None
347 */
348 static uint32_t
349 hash_ipv4(const struct irc_ssaddr *addr, int bits)
350 {
351 if (bits != 0)
352 {
353 const struct sockaddr_in *const v4 = (const struct sockaddr_in *)addr;
354 uint32_t av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
355
356 return (av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1);
357 }
358
359 return 0;
360 }
361
362 /* unsigned long hash_ipv6(struct irc_ssaddr*)
363 * Input: An IP address.
364 * Output: A hash value of the IP address.
365 * Side effects: None
366 */
367 static uint32_t
368 hash_ipv6(const struct irc_ssaddr *addr, int bits)
369 {
370 uint32_t v = 0, n;
371 const struct sockaddr_in6 *const v6 = (const struct sockaddr_in6 *)addr;
372
373 for (n = 0; n < 16; ++n)
374 {
375 if (bits >= 8)
376 {
377 v ^= v6->sin6_addr.s6_addr[n];
378 bits -= 8;
379 }
380 else if (bits)
381 {
382 v ^= v6->sin6_addr.s6_addr[n] & ~((1 << (8 - bits)) - 1);
383 return v & (ATABLE_SIZE - 1);
384 }
385 else
386 return v & (ATABLE_SIZE - 1);
387 }
388
389 return v & (ATABLE_SIZE - 1);
390 }
391
392 /* int hash_text(const char *start)
393 * Input: The start of the text to hash.
394 * Output: The hash of the string between 1 and (TH_MAX-1)
395 * Side-effects: None.
396 */
397 static uint32_t
398 hash_text(const char *start)
399 {
400 uint32_t h = 0;
401
402 for (const char *p = start; *p; ++p)
403 h = (h << 4) - (h + ToLower(*p));
404
405 return h & (ATABLE_SIZE - 1);
406 }
407
408 /* unsigned long get_hash_mask(const char *)
409 * Input: The text to hash.
410 * Output: The hash of the string right of the first '.' past the last
411 * wildcard in the string.
412 * Side-effects: None.
413 */
414 static uint32_t
415 get_mask_hash(const char *text)
416 {
417 const char *hp = "", *p;
418
419 for (p = text + strlen(text) - 1; p >= text; --p)
420 if (IsMWildChar(*p))
421 return hash_text(hp);
422 else if (*p == '.')
423 hp = p + 1;
424 return hash_text(text);
425 }
426
427 /* struct MaskItem *find_conf_by_address(const char *, struct irc_ssaddr *,
428 * int type, int fam, const char *username)
429 * Input: The hostname, the address, the type of mask to find, the address
430 * family, the username.
431 * Output: The matching value with the highest precedence.
432 * Side-effects: None
433 * Note: Setting bit 0 of the type means that the username is ignored.
434 * Warning: IsNeedPassword for everything that is not an auth{} entry
435 * should always be true (i.e. conf->flags & CONF_FLAGS_NEED_PASSWORD == 0)
436 */
437 struct MaskItem *
438 find_conf_by_address(const char *name, const struct irc_ssaddr *addr, unsigned int type,
439 int fam, const char *username, const char *password, int do_match)
440 {
441 unsigned int hprecv = 0;
442 dlink_node *node = NULL;
443 struct MaskItem *hprec = NULL;
444 struct AddressRec *arec = NULL;
445 int b;
446 int (*cmpfunc)(const char *, const char *) = do_match ? match : irccmp;
447
448 if (addr)
449 {
450 /* Check for IPV6 matches... */
451 if (fam == AF_INET6)
452 {
453 for (b = 128; b >= 0; b -= 16)
454 {
455 DLINK_FOREACH(node, atable[hash_ipv6(addr, b)].head)
456 {
457 arec = node->data;
458
459 if ((arec->type == type) &&
460 arec->precedence > hprecv &&
461 arec->masktype == HM_IPV6 &&
462 match_ipv6(addr, &arec->Mask.ipa.addr,
463 arec->Mask.ipa.bits) &&
464 (!username || !cmpfunc(arec->username, username)) &&
465 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
466 match_conf_password(password, arec->conf)))
467 {
468 hprecv = arec->precedence;
469 hprec = arec->conf;
470 }
471 }
472 }
473 }
474 else if (fam == AF_INET)
475 {
476 for (b = 32; b >= 0; b -= 8)
477 {
478 DLINK_FOREACH(node, atable[hash_ipv4(addr, b)].head)
479 {
480 arec = node->data;
481
482 if ((arec->type == type) &&
483 arec->precedence > hprecv &&
484 arec->masktype == HM_IPV4 &&
485 match_ipv4(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 }
498
499 if (name)
500 {
501 const char *p = name;
502
503 while (1)
504 {
505 DLINK_FOREACH(node, atable[hash_text(p)].head)
506 {
507 arec = node->data;
508 if ((arec->type == type) &&
509 arec->precedence > hprecv &&
510 (arec->masktype == HM_HOST) &&
511 !cmpfunc(arec->Mask.hostname, name) &&
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 if ((p = strchr(p, '.')) == NULL)
522 break;
523 ++p;
524 }
525
526 DLINK_FOREACH(node, atable[0].head)
527 {
528 arec = node->data;
529
530 if (arec->type == type &&
531 arec->precedence > hprecv &&
532 arec->masktype == HM_HOST &&
533 !cmpfunc(arec->Mask.hostname, name) &&
534 (!username || !cmpfunc(arec->username, username)) &&
535 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
536 match_conf_password(password, arec->conf)))
537 {
538 hprecv = arec->precedence;
539 hprec = arec->conf;
540 }
541 }
542 }
543
544 return hprec;
545 }
546
547 /* struct MaskItem* find_address_conf(const char*, const char*,
548 * struct irc_ssaddr*, int, char *);
549 * Input: The hostname, username, address, address family.
550 * Output: The applicable MaskItem.
551 * Side-effects: None
552 */
553 struct MaskItem *
554 find_address_conf(const char *host, const char *user, const struct irc_ssaddr *ip,
555 int aftype, const char *password)
556 {
557 struct MaskItem *authcnf = NULL, *killcnf = NULL;
558
559 /* Find the best auth{} block... If none, return NULL -A1kmm */
560 if ((authcnf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
561 password, 1)) == NULL)
562 return NULL;
563
564 /* If they are exempt from K-lines, return the best auth{} block. -A1kmm */
565 if (IsConfExemptKline(authcnf))
566 return authcnf;
567
568 /* Find the best K-line... -A1kmm */
569 killcnf = find_conf_by_address(host, ip, CONF_KLINE, aftype, user, NULL, 1);
570
571 /*
572 * If they are K-lined, return the K-line. Otherwise, return the
573 * auth {} block. -A1kmm
574 */
575 if (killcnf)
576 return killcnf;
577
578 return authcnf;
579 }
580
581 /* struct MaskItem* find_dline_conf(struct irc_ssaddr*, int)
582 *
583 * Input: An address, an address family.
584 * Output: The best matching D-line or exempt line.
585 * Side effects: None.
586 */
587 struct MaskItem *
588 find_dline_conf(const struct irc_ssaddr *addr, int aftype)
589 {
590 struct MaskItem *eline;
591
592 eline = find_conf_by_address(NULL, addr, CONF_EXEMPT, aftype, NULL, NULL, 1);
593 if (eline)
594 return eline;
595
596 return find_conf_by_address(NULL, addr, CONF_DLINE, aftype, NULL, NULL, 1);
597 }
598
599 /* void add_conf_by_address(int, struct MaskItem *aconf)
600 * Input:
601 * Output: None
602 * Side-effects: Adds this entry to the hash table.
603 */
604 struct AddressRec *
605 add_conf_by_address(const unsigned int type, struct MaskItem *conf)
606 {
607 struct AddressRec *arec = NULL;
608 const char *const hostname = conf->host;
609 const char *const username = conf->user;
610 static unsigned int prec_value = 0xFFFFFFFF;
611 int bits = 0;
612
613 assert(type && !EmptyString(hostname));
614
615 arec = MyCalloc(sizeof(struct AddressRec));
616 arec->masktype = parse_netmask(hostname, &arec->Mask.ipa.addr, &bits);
617 arec->Mask.ipa.bits = bits;
618 arec->username = username;
619 arec->conf = conf;
620 arec->precedence = prec_value--;
621 arec->type = type;
622
623 switch (arec->masktype)
624 {
625 case HM_IPV4:
626 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
627 bits -= bits % 8;
628 dlinkAdd(arec, &arec->node, &atable[hash_ipv4(&arec->Mask.ipa.addr, bits)]);
629 break;
630 case HM_IPV6:
631 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
632 bits -= bits % 16;
633 dlinkAdd(arec, &arec->node, &atable[hash_ipv6(&arec->Mask.ipa.addr, bits)]);
634 break;
635 default: /* HM_HOST */
636 arec->Mask.hostname = hostname;
637 dlinkAdd(arec, &arec->node, &atable[get_mask_hash(hostname)]);
638 break;
639 }
640
641 return arec;
642 }
643
644 /* void delete_one_address(const char*, struct MaskItem*)
645 * Input: An address string, the associated MaskItem.
646 * Output: None
647 * Side effects: Deletes an address record. Frees the MaskItem if there
648 * is nothing referencing it, sets it as illegal otherwise.
649 */
650 void
651 delete_one_address_conf(const char *address, struct MaskItem *conf)
652 {
653 int bits = 0;
654 uint32_t hv = 0;
655 dlink_node *node = NULL;
656 struct irc_ssaddr addr;
657
658 switch (parse_netmask(address, &addr, &bits))
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 hv = hash_ipv4(&addr, bits);
664 break;
665 case HM_IPV6:
666 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
667 bits -= bits % 16;
668 hv = hash_ipv6(&addr, bits);
669 break;
670 default: /* HM_HOST */
671 hv = get_mask_hash(address);
672 break;
673 }
674
675 DLINK_FOREACH(node, atable[hv].head)
676 {
677 struct AddressRec *arec = node->data;
678
679 if (arec->conf == conf)
680 {
681 dlinkDelete(&arec->node, &atable[hv]);
682
683 if (!conf->ref_count)
684 conf_free(conf);
685
686 MyFree(arec);
687 return;
688 }
689 }
690 }
691
692 /* void clear_out_address_conf(void)
693 * Input: None
694 * Output: None
695 * Side effects: Clears out all address records in the hash table,
696 * frees them, and frees the MaskItems if nothing references
697 * them, otherwise sets them as illegal.
698 */
699 void
700 clear_out_address_conf(void)
701 {
702 dlink_node *node = NULL, *node_next = NULL;
703
704 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
705 {
706 DLINK_FOREACH_SAFE(node, node_next, atable[i].head)
707 {
708 struct AddressRec *arec = node->data;
709
710 /*
711 * Destroy the ircd.conf items and keep those that are in the databases
712 */
713 if (IsConfDatabase(arec->conf))
714 continue;
715
716 dlinkDelete(&arec->node, &atable[i]);
717 arec->conf->active = 0;
718
719 if (!arec->conf->ref_count)
720 conf_free(arec->conf);
721 MyFree(arec);
722 }
723 }
724 }
725
726 static void
727 hostmask_send_expiration(const struct AddressRec *const arec)
728 {
729 char ban_type = '\0';
730
731 if (!ConfigGeneral.tkline_expire_notices)
732 return;
733
734 switch (arec->type)
735 {
736 case CONF_KLINE:
737 ban_type = 'K';
738 break;
739 case CONF_DLINE:
740 ban_type = 'D';
741 break;
742 default: break;
743 }
744
745 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
746 "Temporary %c-line for [%s@%s] expired", ban_type,
747 (arec->conf->user) ? arec->conf->user : "*",
748 (arec->conf->host) ? arec->conf->host : "*");
749 }
750
751 void
752 hostmask_expire_temporary(void)
753 {
754 dlink_node *node = NULL, *node_next = NULL;
755
756 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
757 {
758 DLINK_FOREACH_SAFE(node, node_next, atable[i].head)
759 {
760 struct AddressRec *arec = node->data;
761
762 if (!arec->conf->until || arec->conf->until > CurrentTime)
763 continue;
764
765 switch (arec->type)
766 {
767 case CONF_KLINE:
768 case CONF_DLINE:
769 hostmask_send_expiration(arec);
770
771 dlinkDelete(&arec->node, &atable[i]);
772 conf_free(arec->conf);
773 MyFree(arec);
774 break;
775 default: break;
776 }
777 }
778 }
779 }

Properties

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

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.26