ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/hostmask.c
Revision: 1298
Committed: Tue Feb 28 18:51:13 2012 UTC (12 years, 1 month ago) by michael
Content type: text/x-csrc
File size: 25103 byte(s)
Log Message:
- fixed style in some places

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

Properties

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