ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/hostmask.c
Revision: 300
Committed: Mon Dec 5 23:13:58 2005 UTC (18 years, 3 months ago) by db
Content type: text/x-csrc
File size: 25116 byte(s)
Log Message:
- fixed infinite loop spotted and fixed by
  *runedude* Jeremy Sayres and my email is runedude@runedude.net


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

Properties

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