]> jfr.im git - solanum.git/blame - ircd/hostmask.c
Refactor check_one_kline a tiny bit
[solanum.git] / ircd / hostmask.c
CommitLineData
212380e3
AC
1/*
2 * charybdis: an advanced internet relay chat daemon (ircd).
3 * hostmask.c: Code to efficiently find IP & hostmask based configs.
4 *
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
05ee179e 8 * Copyright (C) 2005-2008 charybdis development team
212380e3
AC
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 * USA
212380e3
AC
24 */
25
26#include "stdinc.h"
212380e3
AC
27#include "ircd_defs.h"
28#include "s_conf.h"
29#include "hostmask.h"
30#include "numeric.h"
31#include "send.h"
4562c604 32#include "match.h"
212380e3 33
212380e3 34static unsigned long hash_ipv6(struct sockaddr *, int);
212380e3
AC
35static unsigned long hash_ipv4(struct sockaddr *, int);
36
37
e7046ee5 38/* int parse_netmask(const char *, struct rb_sockaddr_storage *, int *);
212380e3
AC
39 * Input: A hostmask, or an IPV4/6 address.
40 * Output: An integer describing whether it is an IPV4, IPV6 address or a
41 * hostmask, an address(if it is an IP mask),
42 * a bitlength(if it is IP mask).
43 * Side effects: None
44 */
45int
29c92cf9 46parse_netmask(const char *text, struct rb_sockaddr_storage *naddr, int *nb)
212380e3
AC
47{
48 char *ip = LOCAL_COPY(text);
49 char *ptr;
e7046ee5 50 struct rb_sockaddr_storage *addr, xaddr;
212380e3
AC
51 int *b, xb;
52 if(nb == NULL)
53 b = &xb;
54 else
55 b = nb;
55abcbb2 56
212380e3 57 if(naddr == NULL)
29c92cf9 58 addr = &xaddr;
212380e3 59 else
29c92cf9 60 addr = naddr;
17e4b48b
JT
61
62 if(strpbrk(ip, "*?") != NULL)
63 {
64 return HM_HOST;
65 }
212380e3 66 if(strchr(ip, ':'))
55abcbb2 67 {
212380e3
AC
68 if((ptr = strchr(ip, '/')))
69 {
70 *ptr = '\0';
71 ptr++;
72 *b = atoi(ptr);
73 if(*b > 128)
74 *b = 128;
4e4a5fcc
JT
75 else if(*b < 0)
76 return HM_HOST;
212380e3
AC
77 } else
78 *b = 128;
17809d2d 79 if(rb_inet_pton_sock(ip, addr) > 0)
212380e3
AC
80 return HM_IPV6;
81 else
82 return HM_HOST;
83 } else
212380e3
AC
84 if(strchr(text, '.'))
85 {
86 if((ptr = strchr(ip, '/')))
87 {
88 *ptr = '\0';
89 ptr++;
90 *b = atoi(ptr);
91 if(*b > 32)
92 *b = 32;
4e4a5fcc
JT
93 else if(*b < 0)
94 return HM_HOST;
212380e3
AC
95 } else
96 *b = 32;
17809d2d 97 if(rb_inet_pton_sock(ip, addr) > 0)
212380e3
AC
98 return HM_IPV4;
99 else
100 return HM_HOST;
101 }
102 return HM_HOST;
103}
104
105/* Hashtable stuff...now external as its used in m_stats.c */
106struct AddressRec *atable[ATABLE_SIZE];
107
108void
109init_host_hash(void)
110{
111 memset(&atable, 0, sizeof(atable));
112}
113
e7046ee5 114/* unsigned long hash_ipv4(struct rb_sockaddr_storage*)
212380e3
AC
115 * Input: An IP address.
116 * Output: A hash value of the IP address.
117 * Side effects: None
118 */
119static unsigned long
120hash_ipv4(struct sockaddr *saddr, int bits)
121{
29c92cf9 122 struct sockaddr_in *addr = (struct sockaddr_in *)(void *)saddr;
55abcbb2 123
212380e3
AC
124 if(bits != 0)
125 {
126 unsigned long av = ntohl(addr->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
127 return (av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1);
128 }
129
130 return 0;
131}
132
e7046ee5 133/* unsigned long hash_ipv6(struct rb_sockaddr_storage*)
212380e3
AC
134 * Input: An IP address.
135 * Output: A hash value of the IP address.
136 * Side effects: None
137 */
212380e3
AC
138static unsigned long
139hash_ipv6(struct sockaddr *saddr, int bits)
140{
29c92cf9 141 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)(void *)saddr;
212380e3
AC
142 unsigned long v = 0, n;
143 for (n = 0; n < 16; n++)
144 {
145 if(bits >= 8)
146 {
147 v ^= addr->sin6_addr.s6_addr[n];
148 bits -= 8;
149 }
150 else if(bits)
151 {
152 v ^= addr->sin6_addr.s6_addr[n] & ~((1 << (8 - bits)) - 1);
153 return v & (ATABLE_SIZE - 1);
154 }
155 else
156 return v & (ATABLE_SIZE - 1);
157 }
158 return v & (ATABLE_SIZE - 1);
159}
212380e3
AC
160
161/* int hash_text(const char *start)
162 * Input: The start of the text to hash.
163 * Output: The hash of the string between 1 and (TH_MAX-1)
164 * Side-effects: None.
165 */
166static int
167hash_text(const char *start)
168{
169 const char *p = start;
170 unsigned long h = 0;
171
172 while(*p)
173 {
7e6b5384 174 h = (h << 4) - (h + (unsigned char) irctolower(*p++));
212380e3
AC
175 }
176
177 return (h & (ATABLE_SIZE - 1));
178}
179
180/* unsigned long get_hash_mask(const char *)
181 * Input: The text to hash.
182 * Output: The hash of the string right of the first '.' past the last
183 * wildcard in the string.
184 * Side-effects: None.
185 */
186static unsigned long
187get_mask_hash(const char *text)
188{
189 const char *hp = "", *p;
190
191 for (p = text + strlen(text) - 1; p >= text; p--)
192 if(*p == '*' || *p == '?')
193 return hash_text(hp);
194 else if(*p == '.')
195 hp = p + 1;
196 return hash_text(text);
197}
198
e7046ee5 199/* struct ConfItem* find_conf_by_address(const char*, struct rb_sockaddr_storage*,
212380e3 200 * int type, int fam, const char *username)
b18dba6d
SA
201 *
202 * This process needs to be kept in sync with check_one_kline().
203 *
212380e3
AC
204 * Input: The hostname, the address, the type of mask to find, the address
205 * family, the username.
206 * Output: The matching value with the highest precedence.
207 * Side-effects: None
208 * Note: Setting bit 0 of the type means that the username is ignored.
209 */
210struct ConfItem *
211find_conf_by_address(const char *name, const char *sockhost,
212 const char *orighost,
55abcbb2 213 struct sockaddr *addr, int type, int fam,
40c1fd47 214 const char *username, const char *auth_user)
212380e3
AC
215{
216 unsigned long hprecv = 0;
217 struct ConfItem *hprec = NULL;
218 struct AddressRec *arec;
219 int b;
220
221 if(username == NULL)
222 username = "";
223
224 if(addr)
225 {
226 /* Check for IPV6 matches... */
212380e3
AC
227 if(fam == AF_INET6)
228 {
229
230 for (b = 128; b >= 0; b -= 16)
231 {
232 for (arec = atable[hash_ipv6(addr, b)]; arec; arec = arec->next)
233 if(arec->type == (type & ~0x1) &&
234 arec->masktype == HM_IPV6 &&
235 comp_with_mask_sock(addr, (struct sockaddr *)&arec->Mask.ipa.addr,
55abcbb2
KB
236 arec->Mask.ipa.bits) &&
237 (type & 0x1 || match(arec-> username, username)) &&
238 (type != CONF_CLIENT || !arec->auth_user ||
239 (auth_user && match(arec->auth_user, auth_user))) &&
240 arec->precedence > hprecv)
212380e3
AC
241 {
242 hprecv = arec->precedence;
243 hprec = arec->aconf;
244 }
245 }
246 }
247 else
212380e3
AC
248 if(fam == AF_INET)
249 {
250 for (b = 32; b >= 0; b -= 8)
251 {
252 for (arec = atable[hash_ipv4(addr, b)]; arec; arec = arec->next)
253 if(arec->type == (type & ~0x1) &&
254 arec->masktype == HM_IPV4 &&
212380e3 255 comp_with_mask_sock(addr, (struct sockaddr *)&arec->Mask.ipa.addr,
55abcbb2
KB
256 arec->Mask.ipa.bits) &&
257 (type & 0x1 || match(arec->username, username)) &&
258 (type != CONF_CLIENT || !arec->auth_user ||
259 (auth_user && match(arec->auth_user, auth_user))) &&
260 arec->precedence > hprecv)
212380e3
AC
261 {
262 hprecv = arec->precedence;
263 hprec = arec->aconf;
264 }
265 }
266 }
267 }
268
269 if(orighost != NULL)
270 {
271 const char *p;
272
273 for (p = orighost; p != NULL;)
274 {
275 for (arec = atable[hash_text(p)]; arec; arec = arec->next)
55abcbb2 276
212380e3
AC
277 if((arec->type == (type & ~0x1)) &&
278 (arec->masktype == HM_HOST) &&
279 arec->precedence > hprecv &&
280 match(arec->Mask.hostname, orighost) &&
55abcbb2
KB
281 (type != CONF_CLIENT || !arec->auth_user ||
282 (auth_user && match(arec->auth_user, auth_user))) &&
212380e3
AC
283 (type & 0x1 || match(arec->username, username)))
284 {
285 hprecv = arec->precedence;
286 hprec = arec->aconf;
287 }
288 p = strchr(p, '.');
289 if(p != NULL)
290 p++;
291 else
292 break;
293 }
294 for (arec = atable[0]; arec; arec = arec->next)
295 {
296 if(arec->type == (type & ~0x1) &&
297 arec->masktype == HM_HOST &&
55abcbb2 298 arec->precedence > hprecv &&
212380e3
AC
299 (match(arec->Mask.hostname, orighost) ||
300 (sockhost && match(arec->Mask.hostname, sockhost))) &&
55abcbb2
KB
301 (type != CONF_CLIENT || !arec->auth_user ||
302 (auth_user && match(arec->auth_user, auth_user))) &&
212380e3
AC
303 (type & 0x1 || match(arec->username, username)))
304 {
305 hprecv = arec->precedence;
306 hprec = arec->aconf;
307 }
308 }
309 }
310
311 if(name != NULL)
312 {
313 const char *p;
314 /* And yes - we have to check p after strchr and p after increment for
315 * NULL -kre */
316 for (p = name; p != NULL;)
317 {
318 for (arec = atable[hash_text(p)]; arec; arec = arec->next)
319 if((arec->type == (type & ~0x1)) &&
320 (arec->masktype == HM_HOST) &&
321 arec->precedence > hprecv &&
322 match(arec->Mask.hostname, name) &&
55abcbb2
KB
323 (type != CONF_CLIENT || !arec->auth_user ||
324 (auth_user && match(arec->auth_user, auth_user))) &&
212380e3
AC
325 (type & 0x1 || match(arec->username, username)))
326 {
327 hprecv = arec->precedence;
328 hprec = arec->aconf;
329 }
330 p = strchr(p, '.');
331 if(p != NULL)
332 p++;
333 else
334 break;
335 }
336 for (arec = atable[0]; arec; arec = arec->next)
337 {
338 if(arec->type == (type & ~0x1) &&
339 arec->masktype == HM_HOST &&
55abcbb2 340 arec->precedence > hprecv &&
212380e3
AC
341 (match(arec->Mask.hostname, name) ||
342 (sockhost && match(arec->Mask.hostname, sockhost))) &&
55abcbb2
KB
343 (type != CONF_CLIENT || !arec->auth_user ||
344 (auth_user && match(arec->auth_user, auth_user))) &&
212380e3
AC
345 (type & 0x1 || match(arec->username, username)))
346 {
347 hprecv = arec->precedence;
348 hprec = arec->aconf;
349 }
350 }
351 }
352 return hprec;
353}
354
355/* struct ConfItem* find_address_conf(const char*, const char*,
e7046ee5 356 * struct rb_sockaddr_storage*, int);
212380e3
AC
357 * Input: The hostname, username, address, address family.
358 * Output: The applicable ConfItem.
359 * Side-effects: None
360 */
361struct ConfItem *
55abcbb2 362find_address_conf(const char *host, const char *sockhost, const char *user,
40c1fd47 363 const char *notildeuser, struct sockaddr *ip, int aftype, char *auth_user)
212380e3
AC
364{
365 struct ConfItem *iconf, *kconf;
366 const char *vuser;
d006b551 367 struct sockaddr_in ip4;
212380e3
AC
368
369 /* Find the best I-line... If none, return NULL -A1kmm */
40c1fd47 370 if(!(iconf = find_conf_by_address(host, sockhost, NULL, ip, CONF_CLIENT, aftype, user, auth_user)))
212380e3
AC
371 return NULL;
372 /* Find what their visible username will be.
373 * Note that the username without tilde may contain one char more.
374 * -- jilles */
375 vuser = IsNoTilde(iconf) ? notildeuser : user;
376
377 /* If they are exempt from K-lines, return the best I-line. -A1kmm */
378 if(IsConfExemptKline(iconf))
379 return iconf;
380
381 /* Find the best K-line... -A1kmm */
40c1fd47 382 kconf = find_conf_by_address(host, sockhost, NULL, ip, CONF_KILL, aftype, user, NULL);
212380e3
AC
383
384 /* If they are K-lined, return the K-line */
385 if(kconf)
386 return kconf;
387
388 /* if theres a spoof, check it against klines.. */
389 if(IsConfDoSpoofIp(iconf))
390 {
27f616dd 391 char *p = strchr(iconf->info.name, '@');
212380e3
AC
392
393 /* note, we dont need to pass sockhost here, as its
394 * guaranteed to not match by whats above.. --anfl
395 */
396 if(p)
397 {
398 *p = '\0';
27f616dd 399 kconf = find_conf_by_address(p+1, NULL, NULL, ip, CONF_KILL, aftype, iconf->info.name, NULL);
212380e3
AC
400 *p = '@';
401 }
402 else
27f616dd 403 kconf = find_conf_by_address(iconf->info.name, NULL, NULL, ip, CONF_KILL, aftype, vuser, NULL);
212380e3
AC
404
405 if(kconf)
406 return kconf;
407 }
408
409 /* if no_tilde, check the username without tilde against klines too
410 * -- jilles */
411 if(user != vuser)
412 {
40c1fd47 413 kconf = find_conf_by_address(host, sockhost, NULL, ip, CONF_KILL, aftype, vuser, NULL);
212380e3
AC
414 if(kconf)
415 return kconf;
416 }
417
6387b5ad 418 if(ip != NULL && ip->sa_family == AF_INET6 &&
4eafa9e6 419 rb_ipv4_from_ipv6((const struct sockaddr_in6 *)(const void *)ip, &ip4))
d006b551
JT
420 {
421 kconf = find_conf_by_address(NULL, NULL, NULL, (struct sockaddr *)&ip4, CONF_KILL, AF_INET, vuser, NULL);
422 if(kconf)
423 return kconf;
424 }
d006b551 425
212380e3
AC
426 return iconf;
427}
428
e7046ee5 429/* struct ConfItem* find_dline(struct rb_sockaddr_storage*, int)
54ac8b60
VY
430 * Input: An address, an address family.
431 * Output: The best matching D-line or exempt line.
432 * Side effects: None.
433 */
434struct ConfItem *
435find_dline(struct sockaddr *addr, int aftype)
436{
d006b551 437 struct ConfItem *aconf;
d006b551 438 struct sockaddr_in addr2;
d006b551
JT
439
440 aconf = find_conf_by_address(NULL, NULL, NULL, addr, CONF_EXEMPTDLINE | 1, aftype, NULL, NULL);
441 if(aconf)
442 return aconf;
443 aconf = find_conf_by_address(NULL, NULL, NULL, addr, CONF_DLINE | 1, aftype, NULL, NULL);
444 if(aconf)
445 return aconf;
d006b551 446 if(addr->sa_family == AF_INET6 &&
4eafa9e6 447 rb_ipv4_from_ipv6((const struct sockaddr_in6 *)(const void *)addr, &addr2))
d006b551
JT
448 {
449 aconf = find_conf_by_address(NULL, NULL, NULL, (struct sockaddr *)&addr2, CONF_DLINE | 1, AF_INET, NULL, NULL);
450 if(aconf)
451 return aconf;
452 }
d006b551 453 return NULL;
54ac8b60
VY
454}
455
6f3a09ff 456/* void find_exact_conf_by_address(const char*, int, const char *)
55abcbb2 457 * Input:
4e0f14a0
JT
458 * Output: ConfItem if found
459 * Side-effects: None
460 */
461struct ConfItem *
462find_exact_conf_by_address(const char *address, int type, const char *username)
463{
464 int masktype, bits;
465 unsigned long hv;
466 struct AddressRec *arec;
e7046ee5 467 struct rb_sockaddr_storage addr;
4e0f14a0
JT
468
469 if(address == NULL)
470 address = "/NOMATCH!/";
29c92cf9 471 masktype = parse_netmask(address, &addr, &bits);
4e0f14a0
JT
472 if(masktype == HM_IPV6)
473 {
474 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
475 hv = hash_ipv6((struct sockaddr *)&addr, bits - bits % 16);
476 }
de293496 477 else if(masktype == HM_IPV4)
4e0f14a0
JT
478 {
479 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
480 hv = hash_ipv4((struct sockaddr *)&addr, bits - bits % 8);
481 }
482 else
483 {
484 hv = get_mask_hash(address);
485 }
486 for (arec = atable[hv]; arec; arec = arec->next)
487 {
488 if (arec->type == type &&
489 arec->masktype == masktype &&
6f3a09ff 490 (arec->username == NULL || username == NULL ? arec->username == username : !irccmp(arec->username, username)))
4e0f14a0
JT
491 {
492 if (masktype == HM_HOST)
493 {
494 if (!irccmp(arec->Mask.hostname, address))
495 return arec->aconf;
496 }
497 else
498 {
499 if (arec->Mask.ipa.bits == bits &&
500 comp_with_mask_sock((struct sockaddr *)&arec->Mask.ipa.addr, (struct sockaddr *)&addr, bits))
501 return arec->aconf;
502 }
503 }
504 }
505 return NULL;
506}
507
212380e3
AC
508/* void add_conf_by_address(const char*, int, const char *,
509 * struct ConfItem *aconf)
55abcbb2 510 * Input:
212380e3
AC
511 * Output: None
512 * Side-effects: Adds this entry to the hash table.
513 */
514void
40c1fd47 515add_conf_by_address(const char *address, int type, const char *username, const char *auth_user, struct ConfItem *aconf)
212380e3
AC
516{
517 static unsigned long prec_value = 0xFFFFFFFF;
ab5fc9c0 518 int bits;
212380e3
AC
519 unsigned long hv;
520 struct AddressRec *arec;
521
522 if(address == NULL)
523 address = "/NOMATCH!/";
eddc2ab6 524 arec = rb_malloc(sizeof(struct AddressRec));
ab5fc9c0 525 arec->masktype = parse_netmask(address, &arec->Mask.ipa.addr, &bits);
ab5fc9c0 526 if(arec->masktype == HM_IPV6)
212380e3 527 {
ab5fc9c0 528 arec->Mask.ipa.bits = bits;
212380e3
AC
529 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
530 bits -= bits % 16;
531 arec->next = atable[(hv = hash_ipv6((struct sockaddr *)&arec->Mask.ipa.addr, bits))];
532 atable[hv] = arec;
533 }
de293496 534 else if(arec->masktype == HM_IPV4)
212380e3 535 {
ab5fc9c0 536 arec->Mask.ipa.bits = bits;
212380e3
AC
537 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
538 bits -= bits % 8;
539 arec->next = atable[(hv = hash_ipv4((struct sockaddr *)&arec->Mask.ipa.addr, bits))];
540 atable[hv] = arec;
541 }
542 else
543 {
544 arec->Mask.hostname = address;
545 arec->next = atable[(hv = get_mask_hash(address))];
546 atable[hv] = arec;
547 }
548 arec->username = username;
40c1fd47 549 arec->auth_user = auth_user;
212380e3
AC
550 arec->aconf = aconf;
551 arec->precedence = prec_value--;
552 arec->type = type;
553}
554
555/* void delete_one_address(const char*, struct ConfItem*)
556 * Input: An address string, the associated ConfItem.
557 * Output: None
558 * Side effects: Deletes an address record. Frees the ConfItem if there
559 * is nothing referencing it, sets it as illegal otherwise.
560 */
561void
562delete_one_address_conf(const char *address, struct ConfItem *aconf)
563{
564 int masktype, bits;
565 unsigned long hv;
566 struct AddressRec *arec, *arecl = NULL;
e7046ee5 567 struct rb_sockaddr_storage addr;
29c92cf9 568 masktype = parse_netmask(address, &addr, &bits);
212380e3
AC
569 if(masktype == HM_IPV6)
570 {
571 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
572 bits -= bits % 16;
573 hv = hash_ipv6((struct sockaddr *)&addr, bits);
574 }
de293496 575 else if(masktype == HM_IPV4)
212380e3
AC
576 {
577 /* We have to do this, since we do not re-hash for every bit -A1kmm. */
578 bits -= bits % 8;
579 hv = hash_ipv4((struct sockaddr *)&addr, bits);
580 }
581 else
582 hv = get_mask_hash(address);
583 for (arec = atable[hv]; arec; arec = arec->next)
584 {
585 if(arec->aconf == aconf)
586 {
587 if(arecl)
588 arecl->next = arec->next;
589 else
590 atable[hv] = arec->next;
591 aconf->status |= CONF_ILLEGAL;
592 if(!aconf->clients)
593 free_conf(aconf);
637c4932 594 rb_free(arec);
212380e3
AC
595 return;
596 }
597 arecl = arec;
598 }
599}
600
601/* void clear_out_address_conf(void)
602 * Input: None
603 * Output: None
604 * Side effects: Clears out all address records in the hash table,
605 * frees them, and frees the ConfItems if nothing references
606 * them, otherwise sets them as illegal.
607 */
608void
609clear_out_address_conf(void)
610{
611 int i;
612 struct AddressRec **store_next;
613 struct AddressRec *arec, *arecn;
614
615 for (i = 0; i < ATABLE_SIZE; i++)
616 {
617 store_next = &atable[i];
618 for (arec = atable[i]; arec; arec = arecn)
619 {
620 arecn = arec->next;
621 /* We keep the temporary K-lines and destroy the
622 * permanent ones, just to be confusing :) -A1kmm */
623 if(arec->aconf->flags & CONF_FLAGS_TEMPORARY ||
624 (arec->type != CONF_CLIENT && arec->type != CONF_EXEMPTDLINE))
625 {
626 *store_next = arec;
627 store_next = &arec->next;
628 }
629 else
630 {
631 arec->aconf->status |= CONF_ILLEGAL;
632 if(!arec->aconf->clients)
633 free_conf(arec->aconf);
637c4932 634 rb_free(arec);
212380e3
AC
635 }
636 }
637 *store_next = NULL;
638 }
639}
640
641void
642clear_out_address_conf_bans(void)
643{
644 int i;
645 struct AddressRec **store_next;
646 struct AddressRec *arec, *arecn;
647
648 for (i = 0; i < ATABLE_SIZE; i++)
649 {
650 store_next = &atable[i];
651 for (arec = atable[i]; arec; arec = arecn)
652 {
653 arecn = arec->next;
654 /* We keep the temporary K-lines and destroy the
655 * permanent ones, just to be confusing :) -A1kmm */
656 if(arec->aconf->flags & CONF_FLAGS_TEMPORARY ||
657 (arec->type == CONF_CLIENT || arec->type == CONF_EXEMPTDLINE))
658 {
659 *store_next = arec;
660 store_next = &arec->next;
661 }
662 else
663 {
664 arec->aconf->status |= CONF_ILLEGAL;
665 if(!arec->aconf->clients)
666 free_conf(arec->aconf);
637c4932 667 rb_free(arec);
212380e3
AC
668 }
669 }
670 *store_next = NULL;
671 }
672}
673
674
675/*
676 * show_iline_prefix()
677 *
678 * inputs - pointer to struct Client requesting output
55abcbb2 679 * - pointer to struct ConfItem
212380e3
AC
680 * - name to which iline prefix will be prefixed to
681 * output - pointer to static string with prefixes listed in ascii form
682 * side effects - NONE
683 */
684char *
685show_iline_prefix(struct Client *sptr, struct ConfItem *aconf, char *name)
686{
687 static char prefix_of_host[USERLEN + 15];
688 char *prefix_ptr;
689
690 prefix_ptr = prefix_of_host;
691 if(IsNoTilde(aconf))
692 *prefix_ptr++ = '-';
212380e3
AC
693 if(IsNeedIdentd(aconf))
694 *prefix_ptr++ = '+';
212380e3
AC
695 if(IsConfDoSpoofIp(aconf))
696 *prefix_ptr++ = '=';
c4f13a64
JT
697 if(IsOper(sptr) && IsConfExemptFlood(aconf))
698 *prefix_ptr++ = '|';
c4f13a64
JT
699 if(IsOper(sptr) && IsConfExemptDNSBL(aconf) && !IsConfExemptKline(aconf))
700 *prefix_ptr++ = '$';
a63a1eab 701 if(IsOper(sptr) && IsConfExemptKline(aconf))
212380e3 702 *prefix_ptr++ = '^';
a63a1eab 703 if(IsOper(sptr) && IsConfExemptLimits(aconf))
212380e3 704 *prefix_ptr++ = '>';
212380e3
AC
705 *prefix_ptr = '\0';
706 strncpy(prefix_ptr, name, USERLEN);
707 return (prefix_of_host);
708}
709
710/* report_auth()
711 *
712 * Inputs: pointer to client to report to
713 * Output: None
714 * Side effects: Reports configured auth{} blocks to client_p
715 */
716void
717report_auth(struct Client *client_p)
718{
29c92cf9
JB
719 char *name, *host, *user, *classname;
720 const char *pass;
212380e3
AC
721 struct AddressRec *arec;
722 struct ConfItem *aconf;
723 int i, port;
724
725 for (i = 0; i < ATABLE_SIZE; i++)
726 for (arec = atable[i]; arec; arec = arec->next)
727 if(arec->type == CONF_CLIENT)
728 {
729 aconf = arec->aconf;
730
a63a1eab 731 if(!IsOper(client_p) && IsConfDoSpoofIp(aconf))
212380e3
AC
732 continue;
733
734 get_printable_conf(aconf, &name, &host, &pass, &user, &port,
735 &classname);
55abcbb2 736
40c1fd47
VY
737 if(!EmptyString(aconf->spasswd))
738 pass = aconf->spasswd;
212380e3 739
55abcbb2 740 sendto_one_numeric(client_p, RPL_STATSILINE,
212380e3 741 form_str(RPL_STATSILINE),
40c1fd47 742 name, pass, show_iline_prefix(client_p, aconf, user),
212380e3
AC
743 show_ip_conf(aconf, client_p) ? host : "255.255.255.255",
744 port, classname);
745 }
746}
747