ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/src/hostmask.c
Revision: 1343
Committed: Sat Apr 7 18:46:29 2012 UTC (12 years ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/hostmask.c
File size: 25054 byte(s)
Log Message:
- hostmask.c, rng_mt.c: avoid use of long int types

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

Properties

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