ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hostmask.c
Revision: 1376
Committed: Sun Apr 29 17:08:42 2012 UTC (13 years, 4 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/hostmask.c
File size: 22292 byte(s)
Log Message:
- minor cleanups to s_gline, hostmask.c and m_stats.c.
  remove useless NULL assignment of dlink_node pointers.
  the DLINK_FOREACH macros already take care of this.

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

Properties

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