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