ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hostmask.c
Revision: 1371
Committed: Wed Apr 25 19:32:21 2012 UTC (13 years, 4 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/hostmask.c
File size: 26638 byte(s)
Log Message:
- "UNKLINE bla@bla.net" may accidentaly remove existing klines such as *@bla.* - Fixed

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

Properties

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