ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hostmask.c
Revision: 1367
Committed: Tue Apr 24 21:20:54 2012 UTC (13 years, 4 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/hostmask.c
File size: 25125 byte(s)
Log Message:
- Cleanup hostmask.c. Make it use dlink list manipulation routines

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
35 #ifdef IPV6
36 static int try_parse_v6_netmask(const char *, struct irc_ssaddr *, int *);
37 static uint32_t hash_ipv6(struct irc_ssaddr *, int);
38 #endif
39 static int try_parse_v4_netmask(const char *, struct irc_ssaddr *, int *);
40 static uint32_t 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 dlink_list 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 uint32_t
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 uint32_t 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 uint32_t
385 hash_ipv6(struct irc_ssaddr *addr, int bits)
386 {
387 uint32_t 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 uint32_t
415 hash_text(const char *start)
416 {
417 const char *p = start;
418 uint32_t h = 0;
419
420 for (; *p; ++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 uint32_t
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 int hprecv = 0;
460 dlink_node *ptr = NULL;
461 struct AccessItem *hprec = NULL;
462 struct AddressRec *arec;
463 int b;
464
465 if (username == NULL)
466 username = "";
467 if (password == NULL)
468 password = "";
469
470 if (addr)
471 {
472 /* Check for IPV6 matches... */
473 #ifdef IPV6
474 if (fam == AF_INET6)
475 {
476 for (b = 128; b >= 0; b -= 16)
477 {
478 DLINK_FOREACH(ptr, atable[hash_ipv6(addr, b)].head)
479 {
480 arec = ptr->data;
481
482 if (arec->type == (type & ~0x1) &&
483 arec->precedence > hprecv &&
484 arec->masktype == HM_IPV6 &&
485 match_ipv6(addr, &arec->Mask.ipa.addr,
486 arec->Mask.ipa.bits) &&
487 (type & 0x1 || match(arec->username, username)) &&
488 (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
489 match_conf_password(password, arec->aconf)))
490 {
491 hprecv = arec->precedence;
492 hprec = arec->aconf;
493 }
494 }
495 }
496 }
497 else
498 #endif
499 if (fam == AF_INET)
500 {
501 for (b = 32; b >= 0; b -= 8)
502 {
503 DLINK_FOREACH(ptr, atable[hash_ipv4(addr, b)].head)
504 {
505 arec = ptr->data;
506
507 if (arec->type == (type & ~0x1) &&
508 arec->precedence > hprecv &&
509 arec->masktype == HM_IPV4 &&
510 match_ipv4(addr, &arec->Mask.ipa.addr,
511 arec->Mask.ipa.bits) &&
512 (type & 0x1 || match(arec->username, username)) &&
513 (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
514 match_conf_password(password, arec->aconf)))
515 {
516 hprecv = arec->precedence;
517 hprec = arec->aconf;
518 }
519 }
520 }
521 }
522 }
523
524 if (name != NULL)
525 {
526 const char *p = name;
527
528 while (1)
529 {
530 DLINK_FOREACH(ptr, atable[hash_text(p)].head)
531 {
532 arec = ptr->data;
533 if ((arec->type == (type & ~0x1)) &&
534 arec->precedence > hprecv &&
535 (arec->masktype == HM_HOST) &&
536 match(arec->Mask.hostname, name) &&
537 (type & 0x1 || match(arec->username, username)) &&
538 (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
539 match_conf_password(password, arec->aconf)))
540 {
541 hprecv = arec->precedence;
542 hprec = arec->aconf;
543 }
544 }
545 p = strchr(p, '.');
546 if (p == NULL)
547 break;
548 p++;
549 }
550
551 DLINK_FOREACH(ptr, atable[0].head)
552 {
553 arec = ptr->data;
554
555 if (arec->type == (type & ~0x1) &&
556 arec->precedence > hprecv &&
557 arec->masktype == HM_HOST &&
558 match(arec->Mask.hostname, name) &&
559 (type & 0x1 || match(arec->username, username)) &&
560 (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
561 match_conf_password(password, arec->aconf)))
562 {
563 hprecv = arec->precedence;
564 hprec = arec->aconf;
565 }
566 }
567 }
568
569 return hprec;
570 }
571
572 /* struct AccessItem* find_address_conf(const char*, const char*,
573 * struct irc_ssaddr*, int, char *);
574 * Input: The hostname, username, address, address family.
575 * Output: The applicable AccessItem.
576 * Side-effects: None
577 */
578 struct AccessItem *
579 find_address_conf(const char *host, const char *user,
580 struct irc_ssaddr *ip, int aftype, char *password)
581 {
582 struct AccessItem *iconf, *kconf;
583
584 /* Find the best I-line... If none, return NULL -A1kmm */
585 if ((iconf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
586 password)) == NULL)
587 return NULL;
588
589 /* If they are exempt from K-lines, return the best I-line. -A1kmm */
590 if (IsConfExemptKline(iconf))
591 return iconf;
592
593 /* Find the best K-line... -A1kmm */
594 kconf = find_conf_by_address(host, ip, CONF_KILL, aftype, user, NULL);
595
596 /* If they are K-lined, return the K-line. Otherwise, return the
597 * I-line. -A1kmm */
598 if (kconf != NULL)
599 return kconf;
600
601 kconf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL);
602 if (kconf != NULL && !IsConfExemptGline(iconf))
603 return kconf;
604
605 return iconf;
606 }
607
608 struct AccessItem *
609 find_gline_conf(const char *host, const char *user,
610 struct irc_ssaddr *ip, int aftype)
611 {
612 struct AccessItem *eline;
613
614 eline = find_conf_by_address(host, ip, CONF_EXEMPTKLINE, aftype,
615 user, NULL);
616 if (eline != NULL)
617 return eline;
618
619 return find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL);
620 }
621
622 /* find_kline_conf
623 *
624 * inputs - pointer to hostname
625 * - pointer to username
626 * - incoming IP and type (IPv4 vs. IPv6)
627 * outut - pointer to kline conf if found NULL if not
628 * side effects -
629 */
630 struct AccessItem *
631 find_kline_conf(const char *host, const char *user,
632 struct irc_ssaddr *ip, int aftype)
633 {
634 struct AccessItem *eline;
635
636 eline = find_conf_by_address(host, ip, CONF_EXEMPTKLINE, aftype,
637 user, NULL);
638 if (eline != NULL)
639 return eline;
640
641 return find_conf_by_address(host, ip, CONF_KILL, aftype, user, NULL);
642 }
643
644 /* struct AccessItem* find_dline_conf(struct irc_ssaddr*, int)
645 *
646 * Input: An address, an address family.
647 * Output: The best matching D-line or exempt line.
648 * Side effects: None.
649 */
650 struct AccessItem *
651 find_dline_conf(struct irc_ssaddr *addr, int aftype)
652 {
653 struct AccessItem *eline;
654
655 eline = find_conf_by_address(NULL, addr, CONF_EXEMPTDLINE | 1, aftype,
656 NULL, NULL);
657 if (eline != NULL)
658 return eline;
659
660 return find_conf_by_address(NULL, addr, CONF_DLINE | 1, aftype, NULL, NULL);
661 }
662
663 /* void add_conf_by_address(int, struct AccessItem *aconf)
664 * Input:
665 * Output: None
666 * Side-effects: Adds this entry to the hash table.
667 */
668 void
669 add_conf_by_address(const unsigned int type, struct AccessItem *aconf)
670 {
671 const char *address;
672 const char *username;
673 static unsigned int prec_value = 0xFFFFFFFF;
674 int bits = 0;
675 struct AddressRec *arec;
676
677 address = aconf->host;
678 username = aconf->user;
679
680 assert(type != 0);
681 assert(aconf != NULL);
682
683 if (EmptyString(address))
684 address = "/NOMATCH!/";
685
686 arec = MyMalloc(sizeof(struct AddressRec));
687 arec->masktype = parse_netmask(address, &arec->Mask.ipa.addr, &bits);
688 arec->Mask.ipa.bits = bits;
689 arec->username = username;
690 arec->aconf = aconf;
691 arec->precedence = prec_value--;
692 arec->type = type;
693
694 switch (arec->masktype)
695 {
696 case HM_IPV4:
697 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
698 bits -= bits % 8;
699 dlinkAdd(arec, &arec->node, &atable[hash_ipv4(&arec->Mask.ipa.addr, bits)]);
700 break;
701 #ifdef IPV6
702 case HM_IPV6:
703 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
704 bits -= bits % 16;
705 dlinkAdd(arec, &arec->node, &atable[hash_ipv6(&arec->Mask.ipa.addr, bits)]);
706 break;
707 #endif
708 default: /* HM_HOST */
709 arec->Mask.hostname = address;
710 dlinkAdd(arec, &arec->node, &atable[get_mask_hash(address)]);
711 break;
712 }
713 }
714
715 /* void delete_one_address(const char*, struct AccessItem*)
716 * Input: An address string, the associated AccessItem.
717 * Output: None
718 * Side effects: Deletes an address record. Frees the AccessItem if there
719 * is nothing referencing it, sets it as illegal otherwise.
720 */
721 void
722 delete_one_address_conf(const char *address, struct AccessItem *aconf)
723 {
724 int bits = 0;
725 uint32_t hv = 0;
726 dlink_node *ptr = NULL, *ptr_next = NULL;
727 struct irc_ssaddr addr;
728
729 switch (parse_netmask(address, &addr, &bits))
730 {
731 case HM_IPV4:
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 break;
736 #ifdef IPV6
737 case HM_IPV6:
738 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
739 bits -= bits % 16;
740 hv = hash_ipv6(&addr, bits);
741 break;
742 #endif
743 default: /* HM_HOST */
744 hv = get_mask_hash(address);
745 break;
746 }
747
748 DLINK_FOREACH_SAFE(ptr, ptr_next, atable[hv].head)
749 {
750 struct AddressRec *arec = ptr->data;
751
752 if (arec->aconf == aconf)
753 {
754 dlinkDelete(&arec->node, &atable[hv]);
755 aconf->status |= CONF_ILLEGAL;
756
757 if (!aconf->clients)
758 free_access_item(aconf);
759
760 MyFree(arec);
761 return;
762 }
763 }
764 }
765
766 /* void clear_out_address_conf(void)
767 * Input: None
768 * Output: None
769 * Side effects: Clears out all address records in the hash table,
770 * frees them, and frees the AccessItems if nothing references
771 * them, otherwise sets them as illegal.
772 */
773 void
774 clear_out_address_conf(void)
775 {
776 unsigned int i = 0;
777 dlink_node *ptr = NULL, *ptr_next = NULL;
778
779 for (i = 0; i < ATABLE_SIZE; ++i)
780 {
781 ptr = ptr_next = NULL;
782
783 DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
784 {
785 struct AddressRec *arec = ptr->data;
786
787 /* We keep the temporary K-lines and destroy the
788 * permanent ones, just to be confusing :) -A1kmm
789 */
790 if (!(arec->aconf->flags & CONF_FLAGS_TEMPORARY))
791 {
792 dlinkDelete(&arec->node, &atable[i]);
793 /* unlink it from link list - Dianora */
794 arec->aconf->status |= CONF_ILLEGAL;
795
796 if (!arec->aconf->clients)
797 free_access_item(arec->aconf);
798 MyFree(arec);
799 }
800 }
801 }
802 }
803
804 /*
805 * show_iline_prefix()
806 *
807 * inputs - pointer to struct Client requesting output
808 * - pointer to struct AccessItem
809 * - name to which iline prefix will be prefixed to
810 * output - pointer to static string with prefixes listed in ascii form
811 * side effects - NONE
812 */
813 char *
814 show_iline_prefix(struct Client *sptr, struct AccessItem *aconf, const char *name)
815 {
816 static char prefix_of_host[USERLEN + 14];
817 char *prefix_ptr = prefix_of_host;
818
819 if (IsNoTilde(aconf))
820 *prefix_ptr++ = '-';
821 if (IsLimitIp(aconf))
822 *prefix_ptr++ = '!';
823 if (IsNeedIdentd(aconf))
824 *prefix_ptr++ = '+';
825 if (!IsNeedPassword(aconf))
826 *prefix_ptr++ = '&';
827 if (IsConfExemptResv(aconf))
828 *prefix_ptr++ = '$';
829 if (IsNoMatchIp(aconf))
830 *prefix_ptr++ = '%';
831 if (IsConfDoSpoofIp(aconf))
832 *prefix_ptr++ = '=';
833 if (MyOper(sptr) && IsConfExemptKline(aconf))
834 *prefix_ptr++ = '^';
835 if (MyOper(sptr) && IsConfExemptGline(aconf))
836 *prefix_ptr++ = '_';
837 if (MyOper(sptr) && IsConfExemptLimits(aconf))
838 *prefix_ptr++ = '>';
839 if (IsConfCanFlood(aconf))
840 *prefix_ptr++ = '|';
841
842 strlcpy(prefix_ptr, name, USERLEN+1);
843
844 return prefix_of_host;
845 }
846
847 /* report_auth()
848 *
849 * Inputs: pointer to client to report to
850 * Output: None
851 * Side effects: Reports configured auth{} blocks to client_p
852 */
853 void
854 report_auth(struct Client *client_p)
855 {
856 struct ConfItem *conf;
857 struct AccessItem *aconf;
858 dlink_node *ptr = NULL;
859 unsigned int i;
860
861
862 for (i = 0; i < ATABLE_SIZE; ++i)
863 {
864 ptr = NULL;
865
866 DLINK_FOREACH(ptr, atable[i].head)
867 {
868 struct AddressRec *arec = ptr->data;
869
870 if (arec->type == CONF_CLIENT)
871 {
872 aconf = arec->aconf;
873
874 if (!MyOper(client_p) && IsConfDoSpoofIp(aconf))
875 continue;
876
877 conf = unmap_conf_item(aconf);
878
879 /* We are doing a partial list, based on what matches the u@h of the
880 * sender, so prepare the strings for comparing --fl_
881 */
882 if (ConfigFileEntry.hide_spoof_ips)
883 sendto_one(client_p, form_str(RPL_STATSILINE), me.name,
884 client_p->name, 'I',
885 conf->name == NULL ? "*" : conf->name,
886 show_iline_prefix(client_p, aconf, aconf->user),
887 IsConfDoSpoofIp(aconf) ? "255.255.255.255" :
888 aconf->host, aconf->port,
889 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
890
891 else
892 sendto_one(client_p, form_str(RPL_STATSILINE), me.name,
893 client_p->name, 'I',
894 conf->name == NULL ? "*" : conf->name,
895 show_iline_prefix(client_p, aconf, aconf->user),
896 aconf->host, aconf->port,
897 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
898 }
899 }
900 }
901 }
902
903 /* report_Klines()
904 * Inputs: Client to report to,
905 * type(==0 for perm, !=0 for temporary)
906 * mask
907 * Output: None
908 * Side effects: Reports configured K(or k)-lines to client_p.
909 */
910 void
911 report_Klines(struct Client *client_p, int tkline)
912 {
913 struct AccessItem *aconf = NULL;
914 unsigned int i = 0;
915 const char *p = NULL;
916 dlink_node *ptr = NULL;
917
918 if (tkline)
919 p = "k";
920 else
921 p = "K";
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_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