ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/hostmask.c
Revision: 723
Committed: Sun Jul 16 19:41:33 2006 UTC (17 years, 8 months ago) by adx
Content type: text/x-csrc
File size: 25109 byte(s)
Log Message:
+ fixed a bug where auths/klines/glines with digit wildcards (#)
  were not handled correctly

File Contents

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

Properties

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