ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hostmask.c
Revision: 1369
Committed: Wed Apr 25 19:04:19 2012 UTC (11 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/hostmask.c
File size: 26439 byte(s)
Log Message:
- cleanup temporary k/d/g line code

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 "numeric.h"
32 #include "send.h"
33 #include "irc_string.h"
34 #include "ircd.h"
35
36 #ifdef IPV6
37 static int try_parse_v6_netmask(const char *, struct irc_ssaddr *, int *);
38 static uint32_t hash_ipv6(struct irc_ssaddr *, int);
39 #endif
40 static int try_parse_v4_netmask(const char *, struct irc_ssaddr *, int *);
41 static uint32_t hash_ipv4(struct irc_ssaddr *, int);
42
43 #define DigitParse(ch) do { \
44 if (ch >= '0' && ch <= '9') \
45 ch = ch - '0'; \
46 else if (ch >= 'A' && ch <= 'F') \
47 ch = ch - 'A' + 10; \
48 else if (ch >= 'a' && ch <= 'f') \
49 ch = ch - 'a' + 10; \
50 } while (0);
51
52 /* The mask parser/type determination code... */
53
54 /* int try_parse_v6_netmask(const char *, struct irc_ssaddr *, int *);
55 * Input: A possible IPV6 address as a string.
56 * Output: An integer describing whether it is an IPV6 or hostmask,
57 * an address(if it is IPV6), a bitlength(if it is IPV6).
58 * Side effects: None
59 * Comments: Called from parse_netmask
60 */
61 /* Fixed so ::/0 (any IPv6 address) is valid
62 Also a bug in DigitParse above.
63 -Gozem 2002-07-19 gozem@linux.nu
64 */
65 #ifdef IPV6
66 static int
67 try_parse_v6_netmask(const char *text, struct irc_ssaddr *addr, int *b)
68 {
69 const char *p;
70 char c;
71 int d[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
72 int dp = 0;
73 int nyble = 4;
74 int finsert = -1;
75 int bits = 128;
76 int deficit = 0;
77 short dc[8];
78 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
79
80 for (p = text; (c = *p); p++)
81 if (IsXDigit(c))
82 {
83 if (nyble == 0)
84 return HM_HOST;
85 DigitParse(c);
86 d[dp] |= c << (4 * --nyble);
87 }
88 else if (c == ':')
89 {
90 if (p > text && *(p - 1) == ':')
91 {
92 if (finsert >= 0)
93 return HM_HOST;
94 finsert = dp;
95 }
96 else
97 {
98 /* If there were less than 4 hex digits, e.g. :ABC: shift right
99 * so we don't interpret it as ABC0 -A1kmm */
100 d[dp] = d[dp] >> 4 * nyble;
101 nyble = 4;
102 if (++dp >= 8)
103 return HM_HOST;
104 }
105 }
106 else if (c == '*')
107 {
108 /* * must be last, and * is ambiguous if there is a ::... -A1kmm */
109 if (finsert >= 0 || *(p + 1) || dp == 0 || *(p - 1) != ':')
110 return HM_HOST;
111 bits = dp * 16;
112 }
113 else if (c == '/')
114 {
115 char *after;
116
117 d[dp] = d[dp] >> 4 * nyble;
118 dp++;
119 bits = strtoul(p + 1, &after, 10);
120
121 if (bits < 0 || *after)
122 return HM_HOST;
123 if (bits > dp * 4 && !(finsert >= 0 && bits <= 128))
124 return HM_HOST;
125 break;
126 }
127 else
128 return HM_HOST;
129
130 d[dp] = d[dp] >> 4 * nyble;
131
132 if (c == 0)
133 dp++;
134 if (finsert < 0 && bits == 0)
135 bits = dp * 16;
136
137 /* How many words are missing? -A1kmm */
138 deficit = bits / 16 + ((bits % 16) ? 1 : 0) - dp;
139
140 /* Now fill in the gaps(from ::) in the copied table... -A1kmm */
141 for (dp = 0, nyble = 0; dp < 8; dp++)
142 {
143 if (nyble == finsert && deficit)
144 {
145 dc[dp] = 0;
146 deficit--;
147 }
148 else
149 dc[dp] = d[nyble++];
150 }
151
152 /* Set unused bits to 0... -A1kmm */
153 if (bits < 128 && (bits % 16 != 0))
154 dc[bits / 16] &= ~((1 << (15 - bits % 16)) - 1);
155 for (dp = bits / 16 + (bits % 16 ? 1 : 0); dp < 8; dp++)
156 dc[dp] = 0;
157
158 /* And assign... -A1kmm */
159 if (addr)
160 for (dp = 0; dp < 8; dp++)
161 /* The cast is a kludge to make netbsd work. */
162 ((unsigned short *)&v6->sin6_addr)[dp] = htons(dc[dp]);
163
164 if (b != NULL)
165 *b = bits;
166 return HM_IPV6;
167 }
168 #endif
169
170 /* int try_parse_v4_netmask(const char *, struct irc_ssaddr *, int *);
171 * Input: A possible IPV4 address as a string.
172 * Output: An integer describing whether it is an IPV4 or hostmask,
173 * an address(if it is IPV4), a bitlength(if it is IPV4).
174 * Side effects: None
175 * Comments: Called from parse_netmask
176 */
177 static int
178 try_parse_v4_netmask(const char *text, struct irc_ssaddr *addr, int *b)
179 {
180 const char *p;
181 const char *digits[4];
182 unsigned char addb[4];
183 int n = 0, bits = 0;
184 char c;
185 struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
186
187 digits[n++] = text;
188
189 for (p = text; (c = *p); p++)
190 if (c >= '0' && c <= '9') /* empty */
191 ;
192 else if (c == '.')
193 {
194 if (n >= 4)
195 return HM_HOST;
196
197 digits[n++] = p + 1;
198 }
199 else if (c == '*')
200 {
201 if (*(p + 1) || n == 0 || *(p - 1) != '.')
202 return HM_HOST;
203
204 bits = (n - 1) * 8;
205 break;
206 }
207 else if (c == '/')
208 {
209 char *after;
210 bits = strtoul(p + 1, &after, 10);
211
212 if (!bits || *after)
213 return HM_HOST;
214 if (bits > n * 8)
215 return HM_HOST;
216
217 break;
218 }
219 else
220 return HM_HOST;
221
222 if (n < 4 && bits == 0)
223 bits = n * 8;
224 if (bits)
225 while (n < 4)
226 digits[n++] = "0";
227
228 for (n = 0; n < 4; n++)
229 addb[n] = strtoul(digits[n], NULL, 10);
230
231 if (bits == 0)
232 bits = 32;
233
234 /* Set unused bits to 0... -A1kmm */
235 if (bits < 32 && bits % 8)
236 addb[bits / 8] &= ~((1 << (8 - bits % 8)) - 1);
237 for (n = bits / 8 + (bits % 8 ? 1 : 0); n < 4; n++)
238 addb[n] = 0;
239 if (addr)
240 v4->sin_addr.s_addr =
241 htonl(addb[0] << 24 | addb[1] << 16 | addb[2] << 8 | addb[3]);
242 if (b != NULL)
243 *b = bits;
244 return HM_IPV4;
245 }
246
247 /* int parse_netmask(const char *, struct irc_ssaddr *, int *);
248 * Input: A hostmask, or an IPV4/6 address.
249 * Output: An integer describing whether it is an IPV4, IPV6 address or a
250 * hostmask, an address(if it is an IP mask),
251 * a bitlength(if it is IP mask).
252 * Side effects: None
253 */
254 int
255 parse_netmask(const char *text, struct irc_ssaddr *addr, int *b)
256 {
257 #ifdef IPV6
258 if (strchr(text, ':'))
259 return try_parse_v6_netmask(text, addr, b);
260 #endif
261 if (strchr(text, '.'))
262 return try_parse_v4_netmask(text, addr, b);
263 return HM_HOST;
264 }
265
266 /* The address matching stuff... */
267 /* int match_ipv6(struct irc_ssaddr *, struct irc_ssaddr *, int)
268 * Input: An IP address, an IP mask, the number of bits in the mask.
269 * Output: if match, -1 else 0
270 * Side effects: None
271 */
272 #ifdef IPV6
273 int
274 match_ipv6(struct irc_ssaddr *addr, struct irc_ssaddr *mask, int bits)
275 {
276 int i, m, n = bits / 8;
277 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
278 struct sockaddr_in6 *v6mask = (struct sockaddr_in6 *)mask;
279
280 for (i = 0; i < n; i++)
281 if (v6->sin6_addr.s6_addr[i] != v6mask->sin6_addr.s6_addr[i])
282 return 0;
283 if ((m = bits % 8) == 0)
284 return -1;
285 if ((v6->sin6_addr.s6_addr[n] & ~((1 << (8 - m)) - 1)) ==
286 v6mask->sin6_addr.s6_addr[n])
287 return -1;
288 return 0;
289 }
290 #endif
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(struct irc_ssaddr *addr, struct irc_ssaddr *mask, int bits)
298 {
299 struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
300 struct sockaddr_in *v4mask = (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(struct irc_ssaddr *addr, int bits)
367 {
368 if (bits != 0)
369 {
370 struct sockaddr_in *v4 = (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(struct irc_ssaddr *addr, int bits)
387 {
388 uint32_t v = 0, n;
389 struct sockaddr_in6 *v6 = (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 + (unsigned char)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 AccessItem *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. aconf->flags & CONF_FLAGS_NEED_PASSWORD == 0)
455 */
456 struct AccessItem *
457 find_conf_by_address(const char *name, struct irc_ssaddr *addr, unsigned int type,
458 int fam, const char *username, const char *password)
459 {
460 unsigned int hprecv = 0;
461 dlink_node *ptr = NULL;
462 struct AccessItem *hprec = NULL;
463 struct AddressRec *arec;
464 int b;
465
466 if (username == NULL)
467 username = "";
468 if (password == NULL)
469 password = "";
470
471 if (addr)
472 {
473 /* Check for IPV6 matches... */
474 #ifdef IPV6
475 if (fam == AF_INET6)
476 {
477 for (b = 128; b >= 0; b -= 16)
478 {
479 DLINK_FOREACH(ptr, atable[hash_ipv6(addr, b)].head)
480 {
481 arec = ptr->data;
482
483 if (arec->type == (type & ~0x1) &&
484 arec->precedence > hprecv &&
485 arec->masktype == HM_IPV6 &&
486 match_ipv6(addr, &arec->Mask.ipa.addr,
487 arec->Mask.ipa.bits) &&
488 (type & 0x1 || match(arec->username, username)) &&
489 (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
490 match_conf_password(password, arec->aconf)))
491 {
492 hprecv = arec->precedence;
493 hprec = arec->aconf;
494 }
495 }
496 }
497 }
498 else
499 #endif
500 if (fam == AF_INET)
501 {
502 for (b = 32; b >= 0; b -= 8)
503 {
504 DLINK_FOREACH(ptr, atable[hash_ipv4(addr, b)].head)
505 {
506 arec = ptr->data;
507
508 if (arec->type == (type & ~0x1) &&
509 arec->precedence > hprecv &&
510 arec->masktype == HM_IPV4 &&
511 match_ipv4(addr, &arec->Mask.ipa.addr,
512 arec->Mask.ipa.bits) &&
513 (type & 0x1 || match(arec->username, username)) &&
514 (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
515 match_conf_password(password, arec->aconf)))
516 {
517 hprecv = arec->precedence;
518 hprec = arec->aconf;
519 }
520 }
521 }
522 }
523 }
524
525 if (name != NULL)
526 {
527 const char *p = name;
528
529 while (1)
530 {
531 DLINK_FOREACH(ptr, atable[hash_text(p)].head)
532 {
533 arec = ptr->data;
534 if ((arec->type == (type & ~0x1)) &&
535 arec->precedence > hprecv &&
536 (arec->masktype == HM_HOST) &&
537 match(arec->Mask.hostname, name) &&
538 (type & 0x1 || match(arec->username, username)) &&
539 (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
540 match_conf_password(password, arec->aconf)))
541 {
542 hprecv = arec->precedence;
543 hprec = arec->aconf;
544 }
545 }
546 p = strchr(p, '.');
547 if (p == NULL)
548 break;
549 p++;
550 }
551
552 DLINK_FOREACH(ptr, atable[0].head)
553 {
554 arec = ptr->data;
555
556 if (arec->type == (type & ~0x1) &&
557 arec->precedence > hprecv &&
558 arec->masktype == HM_HOST &&
559 match(arec->Mask.hostname, name) &&
560 (type & 0x1 || match(arec->username, username)) &&
561 (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
562 match_conf_password(password, arec->aconf)))
563 {
564 hprecv = arec->precedence;
565 hprec = arec->aconf;
566 }
567 }
568 }
569
570 return hprec;
571 }
572
573 /* struct AccessItem* find_address_conf(const char*, const char*,
574 * struct irc_ssaddr*, int, char *);
575 * Input: The hostname, username, address, address family.
576 * Output: The applicable AccessItem.
577 * Side-effects: None
578 */
579 struct AccessItem *
580 find_address_conf(const char *host, const char *user,
581 struct irc_ssaddr *ip, int aftype, char *password)
582 {
583 struct AccessItem *iconf, *kconf;
584
585 /* Find the best I-line... If none, return NULL -A1kmm */
586 if ((iconf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
587 password)) == NULL)
588 return NULL;
589
590 /* If they are exempt from K-lines, return the best I-line. -A1kmm */
591 if (IsConfExemptKline(iconf))
592 return iconf;
593
594 /* Find the best K-line... -A1kmm */
595 kconf = find_conf_by_address(host, ip, CONF_KLINE, aftype, user, NULL);
596
597 /* If they are K-lined, return the K-line. Otherwise, return the
598 * I-line. -A1kmm */
599 if (kconf != NULL)
600 return kconf;
601
602 kconf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL);
603 if (kconf != NULL && !IsConfExemptGline(iconf))
604 return kconf;
605
606 return iconf;
607 }
608
609 struct AccessItem *
610 find_gline_conf(const char *host, const char *user,
611 struct irc_ssaddr *ip, int aftype)
612 {
613 struct AccessItem *eline;
614
615 eline = find_conf_by_address(host, ip, CONF_EXEMPTKLINE, aftype,
616 user, NULL);
617 if (eline != NULL)
618 return eline;
619
620 return find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL);
621 }
622
623 /* find_kline_conf
624 *
625 * inputs - pointer to hostname
626 * - pointer to username
627 * - incoming IP and type (IPv4 vs. IPv6)
628 * outut - pointer to kline conf if found NULL if not
629 * side effects -
630 */
631 struct AccessItem *
632 find_kline_conf(const char *host, const char *user,
633 struct irc_ssaddr *ip, int aftype)
634 {
635 struct AccessItem *eline;
636
637 eline = find_conf_by_address(host, ip, CONF_EXEMPTKLINE, aftype,
638 user, NULL);
639 if (eline != NULL)
640 return eline;
641
642 return find_conf_by_address(host, ip, CONF_KLINE, aftype, user, NULL);
643 }
644
645 /* struct AccessItem* find_dline_conf(struct irc_ssaddr*, int)
646 *
647 * Input: An address, an address family.
648 * Output: The best matching D-line or exempt line.
649 * Side effects: None.
650 */
651 struct AccessItem *
652 find_dline_conf(struct irc_ssaddr *addr, int aftype)
653 {
654 struct AccessItem *eline;
655
656 eline = find_conf_by_address(NULL, addr, CONF_EXEMPTDLINE | 1, aftype,
657 NULL, NULL);
658 if (eline != NULL)
659 return eline;
660
661 return find_conf_by_address(NULL, addr, CONF_DLINE | 1, aftype, NULL, NULL);
662 }
663
664 /* void add_conf_by_address(int, struct AccessItem *aconf)
665 * Input:
666 * Output: None
667 * Side-effects: Adds this entry to the hash table.
668 */
669 void
670 add_conf_by_address(const unsigned int type, struct AccessItem *aconf)
671 {
672 const char *address;
673 const char *username;
674 static unsigned int prec_value = 0xFFFFFFFF;
675 int bits = 0;
676 struct AddressRec *arec;
677
678 address = aconf->host;
679 username = aconf->user;
680
681 assert(type != 0);
682 assert(aconf != NULL);
683
684 if (EmptyString(address))
685 address = "/NOMATCH!/";
686
687 arec = MyMalloc(sizeof(struct AddressRec));
688 arec->masktype = parse_netmask(address, &arec->Mask.ipa.addr, &bits);
689 arec->Mask.ipa.bits = bits;
690 arec->username = username;
691 arec->aconf = aconf;
692 arec->precedence = prec_value--;
693 arec->type = type;
694
695 switch (arec->masktype)
696 {
697 case HM_IPV4:
698 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
699 bits -= bits % 8;
700 dlinkAdd(arec, &arec->node, &atable[hash_ipv4(&arec->Mask.ipa.addr, bits)]);
701 break;
702 #ifdef IPV6
703 case HM_IPV6:
704 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
705 bits -= bits % 16;
706 dlinkAdd(arec, &arec->node, &atable[hash_ipv6(&arec->Mask.ipa.addr, bits)]);
707 break;
708 #endif
709 default: /* HM_HOST */
710 arec->Mask.hostname = address;
711 dlinkAdd(arec, &arec->node, &atable[get_mask_hash(address)]);
712 break;
713 }
714 }
715
716 /* void delete_one_address(const char*, struct AccessItem*)
717 * Input: An address string, the associated AccessItem.
718 * Output: None
719 * Side effects: Deletes an address record. Frees the AccessItem if there
720 * is nothing referencing it, sets it as illegal otherwise.
721 */
722 void
723 delete_one_address_conf(const char *address, struct AccessItem *aconf)
724 {
725 int bits = 0;
726 uint32_t hv = 0;
727 dlink_node *ptr = NULL, *ptr_next = NULL;
728 struct irc_ssaddr addr;
729
730 switch (parse_netmask(address, &addr, &bits))
731 {
732 case HM_IPV4:
733 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
734 bits -= bits % 8;
735 hv = hash_ipv4(&addr, bits);
736 break;
737 #ifdef IPV6
738 case HM_IPV6:
739 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
740 bits -= bits % 16;
741 hv = hash_ipv6(&addr, bits);
742 break;
743 #endif
744 default: /* HM_HOST */
745 hv = get_mask_hash(address);
746 break;
747 }
748
749 DLINK_FOREACH_SAFE(ptr, ptr_next, atable[hv].head)
750 {
751 struct AddressRec *arec = ptr->data;
752
753 if (arec->aconf == aconf)
754 {
755 dlinkDelete(&arec->node, &atable[hv]);
756 aconf->status |= CONF_ILLEGAL;
757
758 if (!aconf->clients)
759 free_access_item(aconf);
760
761 MyFree(arec);
762 return;
763 }
764 }
765 }
766
767 /* void clear_out_address_conf(void)
768 * Input: None
769 * Output: None
770 * Side effects: Clears out all address records in the hash table,
771 * frees them, and frees the AccessItems if nothing references
772 * them, otherwise sets them as illegal.
773 */
774 void
775 clear_out_address_conf(void)
776 {
777 unsigned int i = 0;
778 dlink_node *ptr = NULL, *ptr_next = NULL;
779
780 for (i = 0; i < ATABLE_SIZE; ++i)
781 {
782 ptr = ptr_next = NULL;
783
784 DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
785 {
786 struct AddressRec *arec = ptr->data;
787
788 /* We keep the temporary K-lines and destroy the
789 * permanent ones, just to be confusing :) -A1kmm
790 */
791 if (!(arec->aconf->flags & CONF_FLAGS_TEMPORARY))
792 {
793 dlinkDelete(&arec->node, &atable[i]);
794 /* unlink it from link list - Dianora */
795 arec->aconf->status |= CONF_ILLEGAL;
796
797 if (!arec->aconf->clients)
798 free_access_item(arec->aconf);
799 MyFree(arec);
800 }
801 }
802 }
803 }
804
805 static void
806 hostmask_send_expiration(struct AddressRec *arec)
807 {
808 char ban_type = '\0';
809
810 if (!ConfigFileEntry.tkline_expire_notices)
811 return;
812
813 switch (arec->type)
814 {
815 case CONF_KLINE:
816 ban_type = 'K';
817 break;
818 case CONF_DLINE:
819 ban_type = 'D';
820 break;
821 case CONF_GLINE:
822 ban_type = 'G';
823 break;
824 }
825
826 sendto_realops_flags(UMODE_ALL, L_ALL,
827 "Temporary %c-line for [%s@%s] expired", ban_type,
828 (arec->aconf->user) ? arec->aconf->user : "*",
829 (arec->aconf->host) ? arec->aconf->host : "*");
830 }
831
832 void
833 hostmask_expire_temporary(void)
834 {
835 unsigned int i = 0;
836 dlink_node *ptr = NULL, *ptr_next = NULL;
837
838 for (i = 0; i < ATABLE_SIZE; ++i)
839 {
840 ptr = ptr_next = NULL;
841
842 DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
843 {
844 struct AddressRec *arec = ptr->data;
845
846 if (!IsConfTemporary(arec->aconf) || arec->aconf->hold > CurrentTime)
847 continue;
848
849 switch (arec->type)
850 {
851 case CONF_KLINE:
852 case CONF_DLINE:
853 case CONF_GLINE:
854 hostmask_send_expiration(arec);
855
856 dlinkDelete(&arec->node, &atable[i]);
857 free_access_item(arec->aconf);
858 MyFree(arec);
859 break;
860 }
861 }
862 }
863 }
864
865 /*
866 * show_iline_prefix()
867 *
868 * inputs - pointer to struct Client requesting output
869 * - pointer to struct AccessItem
870 * - name to which iline prefix will be prefixed to
871 * output - pointer to static string with prefixes listed in ascii form
872 * side effects - NONE
873 */
874 char *
875 show_iline_prefix(struct Client *sptr, struct AccessItem *aconf, const char *name)
876 {
877 static char prefix_of_host[USERLEN + 14];
878 char *prefix_ptr = prefix_of_host;
879
880 if (IsNoTilde(aconf))
881 *prefix_ptr++ = '-';
882 if (IsLimitIp(aconf))
883 *prefix_ptr++ = '!';
884 if (IsNeedIdentd(aconf))
885 *prefix_ptr++ = '+';
886 if (!IsNeedPassword(aconf))
887 *prefix_ptr++ = '&';
888 if (IsConfExemptResv(aconf))
889 *prefix_ptr++ = '$';
890 if (IsNoMatchIp(aconf))
891 *prefix_ptr++ = '%';
892 if (IsConfDoSpoofIp(aconf))
893 *prefix_ptr++ = '=';
894 if (MyOper(sptr) && IsConfExemptKline(aconf))
895 *prefix_ptr++ = '^';
896 if (MyOper(sptr) && IsConfExemptGline(aconf))
897 *prefix_ptr++ = '_';
898 if (MyOper(sptr) && IsConfExemptLimits(aconf))
899 *prefix_ptr++ = '>';
900 if (IsConfCanFlood(aconf))
901 *prefix_ptr++ = '|';
902
903 strlcpy(prefix_ptr, name, USERLEN+1);
904
905 return prefix_of_host;
906 }
907
908 /* report_auth()
909 *
910 * Inputs: pointer to client to report to
911 * Output: None
912 * Side effects: Reports configured auth{} blocks to client_p
913 */
914 void
915 report_auth(struct Client *client_p)
916 {
917 struct ConfItem *conf;
918 struct AccessItem *aconf;
919 dlink_node *ptr = NULL;
920 unsigned int i;
921
922
923 for (i = 0; i < ATABLE_SIZE; ++i)
924 {
925 ptr = NULL;
926
927 DLINK_FOREACH(ptr, atable[i].head)
928 {
929 struct AddressRec *arec = ptr->data;
930
931 if (arec->type == CONF_CLIENT)
932 {
933 aconf = arec->aconf;
934
935 if (!MyOper(client_p) && IsConfDoSpoofIp(aconf))
936 continue;
937
938 conf = unmap_conf_item(aconf);
939
940 /* We are doing a partial list, based on what matches the u@h of the
941 * sender, so prepare the strings for comparing --fl_
942 */
943 if (ConfigFileEntry.hide_spoof_ips)
944 sendto_one(client_p, form_str(RPL_STATSILINE), me.name,
945 client_p->name, 'I',
946 conf->name == NULL ? "*" : conf->name,
947 show_iline_prefix(client_p, aconf, aconf->user),
948 IsConfDoSpoofIp(aconf) ? "255.255.255.255" :
949 aconf->host, aconf->port,
950 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
951
952 else
953 sendto_one(client_p, form_str(RPL_STATSILINE), me.name,
954 client_p->name, 'I',
955 conf->name == NULL ? "*" : conf->name,
956 show_iline_prefix(client_p, aconf, aconf->user),
957 aconf->host, aconf->port,
958 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
959 }
960 }
961 }
962 }
963
964 /* report_Klines()
965 * Inputs: Client to report to,
966 * type(==0 for perm, !=0 for temporary)
967 * mask
968 * Output: None
969 * Side effects: Reports configured K(or k)-lines to client_p.
970 */
971 void
972 report_Klines(struct Client *client_p, int tkline)
973 {
974 struct AccessItem *aconf = NULL;
975 unsigned int i = 0;
976 const char *p = NULL;
977 dlink_node *ptr = NULL;
978
979 if (tkline)
980 p = "k";
981 else
982 p = "K";
983
984 for (i = 0; i < ATABLE_SIZE; ++i)
985 {
986 ptr = NULL;
987
988 DLINK_FOREACH(ptr, atable[i].head)
989 {
990 struct AddressRec *arec = ptr->data;
991
992 if (arec->type == CONF_KLINE)
993 {
994 if ((tkline && !((aconf = arec->aconf)->flags & CONF_FLAGS_TEMPORARY)) ||
995 (!tkline && ((aconf = arec->aconf)->flags & CONF_FLAGS_TEMPORARY)))
996 continue;
997
998 if (HasUMode(client_p, UMODE_OPER))
999 sendto_one(client_p, form_str(RPL_STATSKLINE), me.name,
1000 client_p->name, p, aconf->host, aconf->user,
1001 aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
1002 else
1003 sendto_one(client_p, form_str(RPL_STATSKLINE), me.name,
1004 client_p->name, p, aconf->host, aconf->user,
1005 aconf->reason, "");
1006 }
1007 }
1008 }
1009 }

Properties

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