ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/hostmask.c
Revision: 69
Committed: Tue Oct 4 16:09:51 2005 UTC (19 years, 10 months ago) by adx
Content type: text/x-csrc
File size: 25053 byte(s)
Log Message:
- splitted ircd/libio, all headers connected with libio sources have been
  moved for internal use only. To use libio interface, include "libio.h"
  (which is already done in "stdinc.h")


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 "ircd_defs.h"
27 #include "s_conf.h"
28 #include "hostmask.h"
29 #include "numeric.h"
30 #include "send.h"
31
32 #ifdef IPV6
33 static int try_parse_v6_netmask(const char *, struct irc_ssaddr *, int *);
34 static unsigned long hash_ipv6(struct irc_ssaddr *, int);
35 #endif
36 static int try_parse_v4_netmask(const char *, struct irc_ssaddr *, int *);
37 static unsigned long hash_ipv4(struct irc_ssaddr *, int);
38
39 #define DigitParse(ch) do { \
40 if (ch >= '0' && ch <= '9') \
41 ch = ch - '0'; \
42 else if (ch >= 'A' && ch <= 'F') \
43 ch = ch - 'A' + 10; \
44 else if (ch >= 'a' && ch <= 'f') \
45 ch = ch - 'a' + 10; \
46 } while(0);
47
48 /* The mask parser/type determination code... */
49
50 /* int try_parse_v6_netmask(const char *, struct irc_ssaddr *, int *);
51 * Input: A possible IPV6 address as a string.
52 * Output: An integer describing whether it is an IPV6 or hostmask,
53 * an address(if it is IPV6), a bitlength(if it is IPV6).
54 * Side effects: None
55 * Comments: Called from parse_netmask
56 */
57 /* Fixed so ::/0 (any IPv6 address) is valid
58 Also a bug in DigitParse above.
59 -Gozem 2002-07-19 gozem@linux.nu
60 */
61 #ifdef IPV6
62 static int
63 try_parse_v6_netmask(const char *text, struct irc_ssaddr *addr, int *b)
64 {
65 const char *p;
66 char c;
67 int d[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
68 int dp = 0;
69 int nyble = 4;
70 int finsert = -1;
71 int bits = 128;
72 int deficit = 0;
73 short dc[8];
74 struct sockaddr_in6 *v6 = (struct sockaddr_in6*) addr;
75
76 for (p = text; (c = *p); p++)
77 if (IsXDigit(c))
78 {
79 if (nyble == 0)
80 return HM_HOST;
81 DigitParse(c);
82 d[dp] |= c << (4 * --nyble);
83 }
84 else if (c == ':')
85 {
86 if (p > text && *(p - 1) == ':')
87 {
88 if (finsert >= 0)
89 return HM_HOST;
90 finsert = dp;
91 }
92 else
93 {
94 /* If there were less than 4 hex digits, e.g. :ABC: shift right
95 * so we don't interpret it as ABC0 -A1kmm */
96 d[dp] = d[dp] >> 4 * nyble;
97 nyble = 4;
98 if (++dp >= 8)
99 return HM_HOST;
100 }
101 }
102 else if (c == '*')
103 {
104 /* * must be last, and * is ambiguous if there is a ::... -A1kmm */
105 if (finsert >= 0 || *(p + 1) || dp == 0 || *(p - 1) != ':')
106 return HM_HOST;
107 bits = dp * 16;
108 }
109 else if (c == '/')
110 {
111 char *after;
112
113 d[dp] = d[dp] >> 4 * nyble;
114 dp++;
115 bits = strtoul(p + 1, &after, 10);
116 if (bits < 0 || *after)
117 return HM_HOST;
118 if (bits > dp * 4 && !(finsert >= 0 && bits <= 128))
119 return HM_HOST;
120 break;
121 }
122 else
123 return HM_HOST;
124
125 d[dp] = d[dp] >> 4 * nyble;
126 if (c == 0)
127 dp++;
128 if (finsert < 0 && bits == 0)
129 bits = dp * 16;
130 /* How many words are missing? -A1kmm */
131 deficit = bits / 16 + ((bits % 16) ? 1 : 0) - dp;
132 /* Now fill in the gaps(from ::) in the copied table... -A1kmm */
133 for (dp = 0, nyble = 0; dp < 8; dp++)
134 {
135 if (nyble == finsert && deficit)
136 {
137 dc[dp] = 0;
138 deficit--;
139 }
140 else
141 dc[dp] = d[nyble++];
142 }
143 /* Set unused bits to 0... -A1kmm */
144 if (bits < 128 && (bits % 16 != 0))
145 dc[bits / 16] &= ~((1 << (15 - bits % 16)) - 1);
146 for (dp = bits / 16 + (bits % 16 ? 1 : 0); dp < 8; dp++)
147 dc[dp] = 0;
148 /* And assign... -A1kmm */
149 if (addr)
150 for (dp = 0; dp < 8; dp++)
151 /* The cast is a kludge to make netbsd work. */
152 ((unsigned short *)&v6->sin6_addr)[dp] = htons(dc[dp]);
153 if (b != NULL)
154 *b = bits;
155 return HM_IPV6;
156 }
157 #endif
158
159 /* int try_parse_v4_netmask(const char *, struct irc_ssaddr *, int *);
160 * Input: A possible IPV4 address as a string.
161 * Output: An integer describing whether it is an IPV4 or hostmask,
162 * an address(if it is IPV4), a bitlength(if it is IPV4).
163 * Side effects: None
164 * Comments: Called from parse_netmask
165 */
166 static int
167 try_parse_v4_netmask(const char *text, struct irc_ssaddr *addr, int *b)
168 {
169 const char *p;
170 const char *digits[4];
171 unsigned char addb[4];
172 int n = 0, bits = 0;
173 char c;
174 struct sockaddr_in *v4 = (struct sockaddr_in*) addr;
175
176 digits[n++] = text;
177
178 for (p = text; (c = *p); p++)
179 if (c >= '0' && c <= '9') /* empty */
180 ;
181 else if (c == '.')
182 {
183 if (n >= 4)
184 return HM_HOST;
185 digits[n++] = p + 1;
186 }
187 else if (c == '*')
188 {
189 if (*(p + 1) || n == 0 || *(p - 1) != '.')
190 return HM_HOST;
191 bits = (n - 1) * 8;
192 break;
193 }
194 else if (c == '/')
195 {
196 char *after;
197 bits = strtoul(p + 1, &after, 10);
198 if (!bits || *after)
199 return HM_HOST;
200 if (bits > n * 8)
201 return HM_HOST;
202 break;
203 }
204 else
205 return HM_HOST;
206
207 if (n < 4 && bits == 0)
208 bits = n * 8;
209 if (bits)
210 while (n < 4)
211 digits[n++] = "0";
212 for (n = 0; n < 4; n++)
213 addb[n] = strtoul(digits[n], NULL, 10);
214 if (bits == 0)
215 bits = 32;
216 /* Set unused bits to 0... -A1kmm */
217 if (bits < 32 && bits % 8)
218 addb[bits / 8] &= ~((1 << (8 - bits % 8)) - 1);
219 for (n = bits / 8 + (bits % 8 ? 1 : 0); n < 4; n++)
220 addb[n] = 0;
221 if (addr)
222 v4->sin_addr.s_addr =
223 htonl(addb[0] << 24 | addb[1] << 16 | addb[2] << 8 | addb[3]);
224 if (b != NULL)
225 *b = bits;
226 return HM_IPV4;
227 }
228
229 /* int parse_netmask(const char *, struct irc_ssaddr *, int *);
230 * Input: A hostmask, or an IPV4/6 address.
231 * Output: An integer describing whether it is an IPV4, IPV6 address or a
232 * hostmask, an address(if it is an IP mask),
233 * a bitlength(if it is IP mask).
234 * Side effects: None
235 */
236 int
237 parse_netmask(const char *text, struct irc_ssaddr *addr, int *b)
238 {
239 #ifdef IPV6
240 if (strchr(text, ':'))
241 return try_parse_v6_netmask(text, addr, b);
242 #endif
243 if (strchr(text, '.'))
244 return try_parse_v4_netmask(text, addr, b);
245 return HM_HOST;
246 }
247
248 /* The address matching stuff... */
249 /* int match_ipv6(struct irc_ssaddr *, struct irc_ssaddr *, int)
250 * Input: An IP address, an IP mask, the number of bits in the mask.
251 * Output: if match, -1 else 0
252 * Side effects: None
253 */
254 #ifdef IPV6
255 int
256 match_ipv6(struct irc_ssaddr *addr, struct irc_ssaddr *mask, int bits)
257 {
258 int i, m, n = bits / 8;
259 struct sockaddr_in6 *v6 = (struct sockaddr_in6*)addr;
260 struct sockaddr_in6 *v6mask = (struct sockaddr_in6*)mask;
261
262 for (i = 0; i < n; i++)
263 if (v6->sin6_addr.s6_addr[i] != v6mask->sin6_addr.s6_addr[i])
264 return 0;
265 if ((m = bits % 8) == 0)
266 return -1;
267 if ((v6->sin6_addr.s6_addr[n] & ~((1 << (8 - m)) - 1)) ==
268 v6mask->sin6_addr.s6_addr[n])
269 return -1;
270 return 0;
271 }
272 #endif
273 /* int match_ipv4(struct irc_ssaddr *, struct irc_ssaddr *, int)
274 * Input: An IP address, an IP mask, the number of bits in the mask.
275 * Output: if match, -1 else 0
276 * Side Effects: None
277 */
278 int
279 match_ipv4(struct irc_ssaddr *addr, struct irc_ssaddr *mask, int bits)
280 {
281 struct sockaddr_in *v4 = (struct sockaddr_in*) addr;
282 struct sockaddr_in *v4mask = (struct sockaddr_in*) mask;
283 if ((ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1)) !=
284 ntohl(v4mask->sin_addr.s_addr))
285 return 0;
286 return -1;
287 }
288
289 /*
290 * mask_addr
291 *
292 * inputs - pointer to the ip to mask
293 * - bitlen
294 * output - NONE
295 * side effects -
296 */
297 void
298 mask_addr(struct irc_ssaddr *ip, int bits)
299 {
300 int mask;
301 #ifdef IPV6
302 struct sockaddr_in6 *v6_base_ip;
303 int i, m, n;
304 #endif
305 struct sockaddr_in *v4_base_ip;
306
307 #ifdef IPV6
308 if (ip->ss.ss_family != AF_INET6)
309 #endif
310 {
311 v4_base_ip = (struct sockaddr_in*)ip;
312 mask = ~((1 << (32 - bits)) - 1);
313 v4_base_ip->sin_addr.s_addr =
314 htonl(ntohl(v4_base_ip->sin_addr.s_addr) & mask);
315 }
316 #ifdef IPV6
317 else
318 {
319 n = bits / 8;
320 m = bits % 8;
321 v6_base_ip = (struct sockaddr_in6*)ip;
322
323 mask = ~((1 << (8 - m)) -1 );
324 v6_base_ip->sin6_addr.s6_addr[n] = v6_base_ip->sin6_addr.s6_addr[n] & mask;
325 for (i = n + 1; n < 16; i++)
326 v6_base_ip->sin6_addr.s6_addr[n] = 0;
327 }
328 #endif
329 }
330
331 /* Hashtable stuff...now external as its used in m_stats.c */
332 struct AddressRec *atable[ATABLE_SIZE];
333
334 void
335 init_host_hash(void)
336 {
337 memset(&atable, 0, sizeof(atable));
338 }
339
340 /* unsigned long hash_ipv4(struct irc_ssaddr*)
341 * Input: An IP address.
342 * Output: A hash value of the IP address.
343 * Side effects: None
344 */
345 static unsigned long
346 hash_ipv4(struct irc_ssaddr *addr, int bits)
347 {
348 if (bits != 0)
349 {
350 struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
351 unsigned long av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
352 return((av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1));
353 }
354
355 return(0);
356 }
357
358 /* unsigned long hash_ipv6(struct irc_ssaddr*)
359 * Input: An IP address.
360 * Output: A hash value of the IP address.
361 * Side effects: None
362 */
363 #ifdef IPV6
364 static unsigned long
365 hash_ipv6(struct irc_ssaddr *addr, int bits)
366 {
367 unsigned long v = 0, n;
368 struct sockaddr_in6 *v6 = (struct sockaddr_in6*) addr;
369
370 for (n = 0; n < 16; n++)
371 {
372 if (bits >= 8)
373 {
374 v ^= v6->sin6_addr.s6_addr[n];
375 bits -= 8;
376 }
377 else if (bits)
378 {
379 v ^= v6->sin6_addr.s6_addr[n] & ~((1 << (8 - bits)) - 1);
380 return v & (ATABLE_SIZE - 1);
381 }
382 else
383 return v & (ATABLE_SIZE - 1);
384 }
385 return v & (ATABLE_SIZE - 1);
386 }
387 #endif
388
389 /* int hash_text(const char *start)
390 * Input: The start of the text to hash.
391 * Output: The hash of the string between 1 and (TH_MAX-1)
392 * Side-effects: None.
393 */
394 static int
395 hash_text(const char *start)
396 {
397 const char *p = start;
398 unsigned long h = 0;
399
400 while (*p)
401 {
402 h = (h << 4) - (h + (unsigned char)ToLower(*p++));
403 }
404 return (h & (ATABLE_SIZE - 1));
405 }
406
407 /* unsigned long get_hash_mask(const char *)
408 * Input: The text to hash.
409 * Output: The hash of the string right of the first '.' past the last
410 * wildcard in the string.
411 * Side-effects: None.
412 */
413 static unsigned long
414 get_mask_hash(const char *text)
415 {
416 const char *hp = "", *p;
417
418 for (p = text + strlen(text) - 1; p >= text; p--)
419 if (*p == '*' || *p == '?')
420 return hash_text(hp);
421 else if (*p == '.')
422 hp = p + 1;
423 return hash_text(text);
424 }
425
426 /* struct AccessItem *find_conf_by_address(const char *, struct irc_ssaddr *,
427 * int type, int fam, const char *username)
428 * Input: The hostname, the address, the type of mask to find, the address
429 * family, the username.
430 * Output: The matching value with the highest precedence.
431 * Side-effects: None
432 * Note: Setting bit 0 of the type means that the username is ignored.
433 * Warning: IsNeedPassword for everything that is not an auth{} entry
434 * should always be true (i.e. aconf->flags & CONF_FLAGS_NEED_PASSWORD == 0)
435 */
436 struct AccessItem *
437 find_conf_by_address(const char *name, struct irc_ssaddr *addr, int type,
438 int fam, const char *username, const char *password)
439 {
440 unsigned long hprecv = 0;
441 struct AccessItem *hprec = NULL;
442 struct AddressRec *arec;
443 int b;
444
445 if (username == NULL)
446 username = "";
447 if (password == NULL)
448 password = "";
449
450 if (addr)
451 {
452 /* Check for IPV6 matches... */
453 #ifdef IPV6
454 if (fam == AF_INET6)
455 {
456 for (b = 128; b >= 0; b -= 16)
457 {
458 for (arec = atable[hash_ipv6(addr, b)]; arec; arec = arec->next)
459 if (arec->type == (type & ~0x1) &&
460 arec->precedence > hprecv &&
461 arec->masktype == HM_IPV6 &&
462 match_ipv6(addr, &arec->Mask.ipa.addr,
463 arec->Mask.ipa.bits) &&
464 (type & 0x1 || match(arec->username, username)) &&
465 (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
466 match_conf_password(password, arec->aconf)))
467 {
468 hprecv = arec->precedence;
469 hprec = arec->aconf;
470 }
471 }
472 }
473 else
474 #endif
475 if (fam == AF_INET)
476 {
477 for (b = 32; b >= 0; b -= 8)
478 {
479 for (arec = atable[hash_ipv4(addr, b)]; arec; arec = arec->next)
480 if (arec->type == (type & ~0x1) &&
481 arec->precedence > hprecv &&
482 arec->masktype == HM_IPV4 &&
483 match_ipv4(addr, &arec->Mask.ipa.addr,
484 arec->Mask.ipa.bits) &&
485 (type & 0x1 || match(arec->username, username)) &&
486 (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
487 match_conf_password(password, arec->aconf)))
488 {
489 hprecv = arec->precedence;
490 hprec = arec->aconf;
491 }
492 }
493 }
494 }
495
496 if (name != NULL)
497 {
498 const char *p = name;
499
500 while (1)
501 {
502 for (arec = atable[hash_text(p)]; arec != NULL; arec = arec->next)
503 if ((arec->type == (type & ~0x1)) &&
504 arec->precedence > hprecv &&
505 (arec->masktype == HM_HOST) &&
506 match(arec->Mask.hostname, name) &&
507 (type & 0x1 || match(arec->username, username)) &&
508 (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
509 match_conf_password(password, arec->aconf)))
510 {
511 hprecv = arec->precedence;
512 hprec = arec->aconf;
513 }
514 p = strchr(p, '.');
515 if (p == NULL)
516 break;
517 p++;
518 }
519 for (arec = atable[0]; arec; arec = arec->next)
520 if (arec->type == (type & ~0x1) &&
521 arec->precedence > hprecv &&
522 arec->masktype == HM_HOST &&
523 match(arec->Mask.hostname, name) &&
524 (type & 0x1 || match(arec->username, username)) &&
525 (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
526 match_conf_password(password, arec->aconf)))
527 {
528 hprecv = arec->precedence;
529 hprec = arec->aconf;
530 }
531 }
532
533 return hprec;
534 }
535
536 /* struct AccessItem* find_address_conf(const char*, const char*,
537 * struct irc_ssaddr*, int, char *);
538 * Input: The hostname, username, address, address family.
539 * Output: The applicable AccessItem.
540 * Side-effects: None
541 */
542 struct AccessItem *
543 find_address_conf(const char *host, const char *user,
544 struct irc_ssaddr *ip, int aftype, char *password)
545 {
546 struct AccessItem *iconf, *kconf;
547
548 /* Find the best I-line... If none, return NULL -A1kmm */
549 if ((iconf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
550 password)) == NULL)
551 return(NULL);
552
553 /* If they are exempt from K-lines, return the best I-line. -A1kmm */
554 if (IsConfExemptKline(iconf))
555 return(iconf);
556
557 /* Find the best K-line... -A1kmm */
558 kconf = find_conf_by_address(host, ip, CONF_KILL, aftype, user, NULL);
559
560 /* If they are K-lined, return the K-line. Otherwise, return the
561 * I-line. -A1kmm */
562 if (kconf != NULL)
563 return(kconf);
564
565 kconf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL);
566 if (kconf != NULL && !IsConfExemptGline(iconf))
567 return(kconf);
568
569 return(iconf);
570 }
571
572 struct AccessItem *
573 find_gline_conf(const char *host, const char *user,
574 struct irc_ssaddr *ip, int aftype)
575 {
576 struct AccessItem *eline;
577
578 eline = find_conf_by_address(host, ip, CONF_EXEMPTKLINE, aftype,
579 user, NULL);
580 if (eline != NULL)
581 return(eline);
582
583 return(find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL));
584 }
585
586 /* find_kline_conf
587 *
588 * inputs - pointer to hostname
589 * - pointer to username
590 * - incoming IP and type (IPv4 vs. IPv6)
591 * outut - pointer to kline conf if found NULL if not
592 * side effects -
593 */
594 struct AccessItem *
595 find_kline_conf(const char *host, const char *user,
596 struct irc_ssaddr *ip, int aftype)
597 {
598 struct AccessItem *eline;
599
600 eline = find_conf_by_address(host, ip, CONF_EXEMPTKLINE, aftype,
601 user, NULL);
602 if (eline != NULL)
603 return(eline);
604
605 return(find_conf_by_address(host, ip, CONF_KILL, aftype, user, NULL));
606 }
607
608 /* struct AccessItem* find_dline_conf(struct irc_ssaddr*, int)
609 *
610 * Input: An address, an address family.
611 * Output: The best matching D-line or exempt line.
612 * Side effects: None.
613 */
614 struct AccessItem *
615 find_dline_conf(struct irc_ssaddr *addr, int aftype)
616 {
617 struct AccessItem *eline;
618
619 eline = find_conf_by_address(NULL, addr, CONF_EXEMPTDLINE | 1, aftype,
620 NULL, NULL);
621 if (eline != NULL)
622 return(eline);
623 return(find_conf_by_address(NULL, addr, CONF_DLINE | 1, aftype, NULL, NULL));
624 }
625
626 /* void add_conf_by_address(int, struct AccessItem *aconf)
627 * Input:
628 * Output: None
629 * Side-effects: Adds this entry to the hash table.
630 */
631 void
632 add_conf_by_address(int type, struct AccessItem *aconf)
633 {
634 const char *address;
635 const char *username;
636 static unsigned long prec_value = 0xFFFFFFFF;
637 int masktype, bits;
638 unsigned long hv;
639 struct AddressRec *arec;
640
641 address = aconf->host;
642 username = aconf->user;
643
644 assert(type != 0);
645 assert(aconf != NULL);
646
647 if (EmptyString(address))
648 address = "/NOMATCH!/";
649
650 arec = MyMalloc(sizeof(struct AddressRec));
651 masktype = parse_netmask(address, &arec->Mask.ipa.addr, &bits);
652 arec->Mask.ipa.bits = bits;
653 arec->masktype = masktype;
654 #ifdef IPV6
655 if (masktype == HM_IPV6)
656 {
657 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
658 bits -= bits % 16;
659 arec->next = atable[(hv = hash_ipv6(&arec->Mask.ipa.addr, bits))];
660 atable[hv] = arec;
661 }
662 else
663 #endif
664 if (masktype == HM_IPV4)
665 {
666 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
667 bits -= bits % 8;
668 arec->next = atable[(hv = hash_ipv4(&arec->Mask.ipa.addr, bits))];
669 atable[hv] = arec;
670 }
671 else
672 {
673 arec->Mask.hostname = address;
674 arec->next = atable[(hv = get_mask_hash(address))];
675 atable[hv] = arec;
676 }
677 arec->username = username;
678 arec->aconf = aconf;
679 arec->precedence = prec_value--;
680 arec->type = type;
681 }
682
683 /* void delete_one_address(const char*, struct AccessItem*)
684 * Input: An address string, the associated AccessItem.
685 * Output: None
686 * Side effects: Deletes an address record. Frees the AccessItem if there
687 * is nothing referencing it, sets it as illegal otherwise.
688 */
689 void
690 delete_one_address_conf(const char *address, struct AccessItem *aconf)
691 {
692 int masktype, bits;
693 unsigned long hv;
694 struct AddressRec *arec, *arecl = NULL;
695 struct irc_ssaddr addr;
696 masktype = parse_netmask(address, &addr, &bits);
697
698 #ifdef IPV6
699 if (masktype == HM_IPV6)
700 {
701 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
702 bits -= bits % 16;
703 hv = hash_ipv6(&addr, bits);
704 }
705 else
706 #endif
707 if (masktype == HM_IPV4)
708 {
709 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
710 bits -= bits % 8;
711 hv = hash_ipv4(&addr, bits);
712 }
713 else
714 hv = get_mask_hash(address);
715 for (arec = atable[hv]; arec; arec = arec->next)
716 {
717 if (arec->aconf == aconf)
718 {
719 if (arecl)
720 arecl->next = arec->next;
721 else
722 atable[hv] = arec->next;
723 aconf->status |= CONF_ILLEGAL;
724 if (aconf->clients == 0)
725 free_access_item(aconf);
726 MyFree(arec);
727 return;
728 }
729 arecl = arec;
730 }
731 }
732
733 /* void clear_out_address_conf(void)
734 * Input: None
735 * Output: None
736 * Side effects: Clears out all address records in the hash table,
737 * frees them, and frees the AccessItems if nothing references
738 * them, otherwise sets them as illegal.
739 */
740 void
741 clear_out_address_conf(void)
742 {
743 int i;
744 struct AddressRec *arec;
745 struct AddressRec *last_arec;
746 struct AddressRec *next_arec;
747
748 for (i = 0; i < ATABLE_SIZE; i++)
749 {
750 last_arec = NULL;
751 for (arec = atable[i]; arec; arec = next_arec)
752 {
753 /* We keep the temporary K-lines and destroy the
754 * permanent ones, just to be confusing :) -A1kmm
755 */
756 next_arec = arec->next;
757
758 if (arec->aconf->flags & CONF_FLAGS_TEMPORARY)
759 {
760 last_arec = arec;
761 }
762 else
763 {
764 /* unlink it from link list - Dianora */
765
766 if (last_arec == NULL)
767 {
768 atable[i] = next_arec;
769 }
770 else
771 {
772 last_arec->next = next_arec;
773 }
774
775 arec->aconf->status |= CONF_ILLEGAL;
776 if (arec->aconf->clients == 0)
777 free_access_item(arec->aconf);
778 MyFree(arec);
779 }
780 }
781 }
782 }
783
784 /*
785 * show_iline_prefix()
786 *
787 * inputs - pointer to struct Client requesting output
788 * - pointer to struct AccessItem
789 * - name to which iline prefix will be prefixed to
790 * output - pointer to static string with prefixes listed in ascii form
791 * side effects - NONE
792 */
793 char *
794 show_iline_prefix(struct Client *sptr, struct AccessItem *aconf, const char *name)
795 {
796 static char prefix_of_host[USERLEN + 14];
797 char *prefix_ptr;
798
799 prefix_ptr = prefix_of_host;
800 if (IsNoTilde(aconf))
801 *prefix_ptr++ = '-';
802 if (IsLimitIp(aconf))
803 *prefix_ptr++ = '!';
804 if (IsNeedIdentd(aconf))
805 *prefix_ptr++ = '+';
806 if (!IsNeedPassword(aconf))
807 *prefix_ptr++ = '&';
808 if (IsConfExemptResv(aconf))
809 *prefix_ptr++ = '$';
810 if (IsNoMatchIp(aconf))
811 *prefix_ptr++ = '%';
812 if (IsConfDoSpoofIp(aconf))
813 *prefix_ptr++ = '=';
814 if (MyOper(sptr) && IsConfExemptKline(aconf))
815 *prefix_ptr++ = '^';
816 if (MyOper(sptr) && IsConfExemptGline(aconf))
817 *prefix_ptr++ = '_';
818 if (MyOper(sptr) && IsConfExemptLimits(aconf))
819 *prefix_ptr++ = '>';
820 if (MyOper(sptr) && IsConfIdlelined(aconf))
821 *prefix_ptr++ = '<';
822 if (IsConfCanFlood(aconf))
823 *prefix_ptr++ = '|';
824 strlcpy(prefix_ptr, name, USERLEN);
825
826 return(prefix_of_host);
827 }
828
829 /* report_auth()
830 *
831 * Inputs: pointer to client to report to
832 * Output: None
833 * Side effects: Reports configured auth{} blocks to client_p
834 */
835 void
836 report_auth(struct Client *client_p)
837 {
838 struct AddressRec *arec;
839 struct ConfItem *conf;
840 struct AccessItem *aconf;
841 int i;
842
843 for (i = 0; i < ATABLE_SIZE; i++)
844 {
845 for (arec = atable[i]; arec; arec = arec->next)
846 {
847 if (arec->type == CONF_CLIENT)
848 {
849 aconf = arec->aconf;
850
851 if (!MyOper(client_p) && IsConfDoSpoofIp(aconf))
852 continue;
853
854 conf = unmap_conf_item(aconf);
855
856 /* We are doing a partial list, based on what matches the u@h of the
857 * sender, so prepare the strings for comparing --fl_
858 */
859 if (ConfigFileEntry.hide_spoof_ips)
860 sendto_one(client_p, form_str(RPL_STATSILINE), me.name,
861 client_p->name, 'I',
862 conf->name == NULL ? "*" : conf->name,
863 show_iline_prefix(client_p, aconf, aconf->user),
864 IsConfDoSpoofIp(aconf) ? "255.255.255.255" :
865 aconf->host, aconf->port,
866 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
867
868 else
869 sendto_one(client_p, form_str(RPL_STATSILINE), me.name,
870 client_p->name, 'I',
871 conf->name == NULL ? "*" : conf->name,
872 show_iline_prefix(client_p, aconf, aconf->user),
873 aconf->host, aconf->port,
874 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
875 }
876 }
877 }
878 }
879
880 /* report_Klines()
881 * Inputs: Client to report to,
882 * type(==0 for perm, !=0 for temporary)
883 * mask
884 * Output: None
885 * Side effects: Reports configured K(or k)-lines to client_p.
886 */
887 void
888 report_Klines(struct Client *client_p, int tkline)
889 {
890 struct AddressRec *arec = NULL;
891 struct AccessItem *aconf = NULL;
892 int i;
893 const char *p = NULL;
894
895 if (tkline)
896 p = "k";
897 else
898 p = "K";
899
900 for (i = 0; i < ATABLE_SIZE; i++)
901 {
902 for (arec = atable[i]; arec; arec = arec->next)
903 {
904 if (arec->type == CONF_KILL)
905 {
906 if ((tkline && !((aconf = arec->aconf)->flags & CONF_FLAGS_TEMPORARY)) ||
907 (!tkline && ((aconf = arec->aconf)->flags & CONF_FLAGS_TEMPORARY)))
908 continue;
909
910 if (IsOper(client_p))
911 sendto_one(client_p, form_str(RPL_STATSKLINE), me.name,
912 client_p->name, p, aconf->host, aconf->user,
913 aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
914 else
915 sendto_one(client_p, form_str(RPL_STATSKLINE), me.name,
916 client_p->name, p, aconf->host, aconf->user,
917 aconf->reason, "");
918 }
919 }
920 }
921 }

Properties

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