ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hostmask.c
Revision: 1367
Committed: Tue Apr 24 21:20:54 2012 UTC (13 years, 4 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/hostmask.c
File size: 25125 byte(s)
Log Message:
- Cleanup hostmask.c. Make it use dlink list manipulation routines

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 michael 1367 dlink_list atable[ATABLE_SIZE];
352 adx 30
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 michael 1367 for (; *p; ++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 michael 1367 dlink_node *ptr = NULL;
461 adx 30 struct AccessItem *hprec = NULL;
462     struct AddressRec *arec;
463     int b;
464    
465     if (username == NULL)
466     username = "";
467     if (password == NULL)
468     password = "";
469    
470     if (addr)
471     {
472     /* Check for IPV6 matches... */
473     #ifdef IPV6
474     if (fam == AF_INET6)
475     {
476     for (b = 128; b >= 0; b -= 16)
477     {
478 michael 1367 DLINK_FOREACH(ptr, atable[hash_ipv6(addr, b)].head)
479     {
480     arec = ptr->data;
481    
482 adx 30 if (arec->type == (type & ~0x1) &&
483     arec->precedence > hprecv &&
484     arec->masktype == HM_IPV6 &&
485     match_ipv6(addr, &arec->Mask.ipa.addr,
486     arec->Mask.ipa.bits) &&
487     (type & 0x1 || match(arec->username, username)) &&
488     (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
489     match_conf_password(password, arec->aconf)))
490     {
491     hprecv = arec->precedence;
492     hprec = arec->aconf;
493     }
494 michael 1367 }
495 adx 30 }
496     }
497     else
498     #endif
499     if (fam == AF_INET)
500     {
501     for (b = 32; b >= 0; b -= 8)
502     {
503 michael 1367 DLINK_FOREACH(ptr, atable[hash_ipv4(addr, b)].head)
504     {
505     arec = ptr->data;
506    
507 adx 30 if (arec->type == (type & ~0x1) &&
508     arec->precedence > hprecv &&
509     arec->masktype == HM_IPV4 &&
510     match_ipv4(addr, &arec->Mask.ipa.addr,
511     arec->Mask.ipa.bits) &&
512     (type & 0x1 || match(arec->username, username)) &&
513     (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
514     match_conf_password(password, arec->aconf)))
515     {
516     hprecv = arec->precedence;
517     hprec = arec->aconf;
518     }
519 michael 1367 }
520 adx 30 }
521     }
522     }
523    
524     if (name != NULL)
525     {
526     const char *p = name;
527    
528     while (1)
529     {
530 michael 1367 DLINK_FOREACH(ptr, atable[hash_text(p)].head)
531     {
532     arec = ptr->data;
533     if ((arec->type == (type & ~0x1)) &&
534 adx 30 arec->precedence > hprecv &&
535     (arec->masktype == HM_HOST) &&
536     match(arec->Mask.hostname, name) &&
537     (type & 0x1 || match(arec->username, username)) &&
538     (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
539     match_conf_password(password, arec->aconf)))
540     {
541     hprecv = arec->precedence;
542     hprec = arec->aconf;
543     }
544 michael 1367 }
545 adx 30 p = strchr(p, '.');
546     if (p == NULL)
547     break;
548     p++;
549     }
550 michael 1367
551     DLINK_FOREACH(ptr, atable[0].head)
552     {
553     arec = ptr->data;
554    
555 adx 30 if (arec->type == (type & ~0x1) &&
556     arec->precedence > hprecv &&
557     arec->masktype == HM_HOST &&
558     match(arec->Mask.hostname, name) &&
559     (type & 0x1 || match(arec->username, username)) &&
560     (IsNeedPassword(arec->aconf) || arec->aconf->passwd == NULL ||
561     match_conf_password(password, arec->aconf)))
562     {
563     hprecv = arec->precedence;
564     hprec = arec->aconf;
565     }
566 michael 1367 }
567 adx 30 }
568    
569     return hprec;
570     }
571    
572     /* struct AccessItem* find_address_conf(const char*, const char*,
573     * struct irc_ssaddr*, int, char *);
574     * Input: The hostname, username, address, address family.
575     * Output: The applicable AccessItem.
576     * Side-effects: None
577     */
578     struct AccessItem *
579     find_address_conf(const char *host, const char *user,
580     struct irc_ssaddr *ip, int aftype, char *password)
581     {
582     struct AccessItem *iconf, *kconf;
583    
584     /* Find the best I-line... If none, return NULL -A1kmm */
585     if ((iconf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
586     password)) == NULL)
587 michael 1298 return NULL;
588 adx 30
589     /* If they are exempt from K-lines, return the best I-line. -A1kmm */
590     if (IsConfExemptKline(iconf))
591 michael 1298 return iconf;
592 adx 30
593     /* Find the best K-line... -A1kmm */
594     kconf = find_conf_by_address(host, ip, CONF_KILL, aftype, user, NULL);
595    
596     /* If they are K-lined, return the K-line. Otherwise, return the
597     * I-line. -A1kmm */
598     if (kconf != NULL)
599 michael 1298 return kconf;
600 adx 30
601     kconf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL);
602     if (kconf != NULL && !IsConfExemptGline(iconf))
603 michael 1298 return kconf;
604 adx 30
605 michael 1298 return iconf;
606 adx 30 }
607    
608     struct AccessItem *
609     find_gline_conf(const char *host, const char *user,
610     struct irc_ssaddr *ip, int aftype)
611     {
612     struct AccessItem *eline;
613    
614     eline = find_conf_by_address(host, ip, CONF_EXEMPTKLINE, aftype,
615     user, NULL);
616     if (eline != NULL)
617 michael 1298 return eline;
618 adx 30
619 michael 1298 return find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL);
620 adx 30 }
621    
622     /* find_kline_conf
623     *
624     * inputs - pointer to hostname
625     * - pointer to username
626     * - incoming IP and type (IPv4 vs. IPv6)
627     * outut - pointer to kline conf if found NULL if not
628     * side effects -
629     */
630     struct AccessItem *
631     find_kline_conf(const char *host, const char *user,
632 michael 1298 struct irc_ssaddr *ip, int aftype)
633 adx 30 {
634     struct AccessItem *eline;
635    
636     eline = find_conf_by_address(host, ip, CONF_EXEMPTKLINE, aftype,
637     user, NULL);
638     if (eline != NULL)
639 michael 1298 return eline;
640 adx 30
641 michael 1298 return find_conf_by_address(host, ip, CONF_KILL, aftype, user, NULL);
642 adx 30 }
643    
644     /* struct AccessItem* find_dline_conf(struct irc_ssaddr*, int)
645     *
646     * Input: An address, an address family.
647     * Output: The best matching D-line or exempt line.
648     * Side effects: None.
649     */
650     struct AccessItem *
651     find_dline_conf(struct irc_ssaddr *addr, int aftype)
652     {
653     struct AccessItem *eline;
654    
655     eline = find_conf_by_address(NULL, addr, CONF_EXEMPTDLINE | 1, aftype,
656     NULL, NULL);
657     if (eline != NULL)
658 michael 1298 return eline;
659    
660     return find_conf_by_address(NULL, addr, CONF_DLINE | 1, aftype, NULL, NULL);
661 adx 30 }
662    
663     /* void add_conf_by_address(int, struct AccessItem *aconf)
664     * Input:
665     * Output: None
666     * Side-effects: Adds this entry to the hash table.
667     */
668     void
669 michael 1367 add_conf_by_address(const unsigned int type, struct AccessItem *aconf)
670 adx 30 {
671     const char *address;
672     const char *username;
673 michael 1343 static unsigned int prec_value = 0xFFFFFFFF;
674 michael 1367 int bits = 0;
675 adx 30 struct AddressRec *arec;
676    
677     address = aconf->host;
678     username = aconf->user;
679    
680     assert(type != 0);
681     assert(aconf != NULL);
682    
683     if (EmptyString(address))
684     address = "/NOMATCH!/";
685    
686     arec = MyMalloc(sizeof(struct AddressRec));
687 michael 1367 arec->masktype = parse_netmask(address, &arec->Mask.ipa.addr, &bits);
688 adx 30 arec->Mask.ipa.bits = bits;
689 michael 1367 arec->username = username;
690     arec->aconf = aconf;
691     arec->precedence = prec_value--;
692     arec->type = type;
693 michael 1298
694 michael 1367 switch (arec->masktype)
695     {
696     case HM_IPV4:
697     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
698     bits -= bits % 8;
699     dlinkAdd(arec, &arec->node, &atable[hash_ipv4(&arec->Mask.ipa.addr, bits)]);
700     break;
701 adx 30 #ifdef IPV6
702 michael 1367 case HM_IPV6:
703     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
704     bits -= bits % 16;
705     dlinkAdd(arec, &arec->node, &atable[hash_ipv6(&arec->Mask.ipa.addr, bits)]);
706     break;
707 adx 30 #endif
708 michael 1367 default: /* HM_HOST */
709     arec->Mask.hostname = address;
710     dlinkAdd(arec, &arec->node, &atable[get_mask_hash(address)]);
711     break;
712 adx 30 }
713     }
714    
715     /* void delete_one_address(const char*, struct AccessItem*)
716     * Input: An address string, the associated AccessItem.
717     * Output: None
718     * Side effects: Deletes an address record. Frees the AccessItem if there
719     * is nothing referencing it, sets it as illegal otherwise.
720     */
721     void
722     delete_one_address_conf(const char *address, struct AccessItem *aconf)
723     {
724 michael 1367 int bits = 0;
725     uint32_t hv = 0;
726     dlink_node *ptr = NULL, *ptr_next = NULL;
727 adx 30 struct irc_ssaddr addr;
728 michael 1298
729 michael 1367 switch (parse_netmask(address, &addr, &bits))
730     {
731     case HM_IPV4:
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     break;
736 adx 30 #ifdef IPV6
737 michael 1367 case HM_IPV6:
738     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
739     bits -= bits % 16;
740     hv = hash_ipv6(&addr, bits);
741     break;
742 adx 30 #endif
743 michael 1367 default: /* HM_HOST */
744     hv = get_mask_hash(address);
745     break;
746 adx 30 }
747 michael 1298
748 michael 1367 DLINK_FOREACH_SAFE(ptr, ptr_next, atable[hv].head)
749 adx 30 {
750 michael 1367 struct AddressRec *arec = ptr->data;
751    
752 adx 30 if (arec->aconf == aconf)
753     {
754 michael 1367 dlinkDelete(&arec->node, &atable[hv]);
755 adx 30 aconf->status |= CONF_ILLEGAL;
756 michael 1298
757 michael 1367 if (!aconf->clients)
758 adx 30 free_access_item(aconf);
759 michael 1298
760 adx 30 MyFree(arec);
761     return;
762     }
763     }
764     }
765    
766     /* void clear_out_address_conf(void)
767     * Input: None
768     * Output: None
769     * Side effects: Clears out all address records in the hash table,
770     * frees them, and frees the AccessItems if nothing references
771     * them, otherwise sets them as illegal.
772     */
773     void
774     clear_out_address_conf(void)
775     {
776 michael 1367 unsigned int i = 0;
777     dlink_node *ptr = NULL, *ptr_next = NULL;
778 adx 30
779 michael 1367 for (i = 0; i < ATABLE_SIZE; ++i)
780 adx 30 {
781 michael 1367 ptr = ptr_next = NULL;
782 michael 1298
783 michael 1367 DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
784 adx 30 {
785 michael 1367 struct AddressRec *arec = ptr->data;
786    
787 adx 30 /* We keep the temporary K-lines and destroy the
788     * permanent ones, just to be confusing :) -A1kmm
789     */
790 michael 1367 if (!(arec->aconf->flags & CONF_FLAGS_TEMPORARY))
791 adx 30 {
792 michael 1367 dlinkDelete(&arec->node, &atable[i]);
793 adx 30 /* unlink it from link list - Dianora */
794     arec->aconf->status |= CONF_ILLEGAL;
795 michael 1298
796 michael 1367 if (!arec->aconf->clients)
797 adx 30 free_access_item(arec->aconf);
798     MyFree(arec);
799     }
800     }
801     }
802     }
803    
804     /*
805     * show_iline_prefix()
806     *
807     * inputs - pointer to struct Client requesting output
808     * - pointer to struct AccessItem
809     * - name to which iline prefix will be prefixed to
810     * output - pointer to static string with prefixes listed in ascii form
811     * side effects - NONE
812     */
813     char *
814     show_iline_prefix(struct Client *sptr, struct AccessItem *aconf, const char *name)
815     {
816     static char prefix_of_host[USERLEN + 14];
817 michael 1298 char *prefix_ptr = prefix_of_host;
818 adx 30
819     if (IsNoTilde(aconf))
820     *prefix_ptr++ = '-';
821     if (IsLimitIp(aconf))
822     *prefix_ptr++ = '!';
823     if (IsNeedIdentd(aconf))
824     *prefix_ptr++ = '+';
825     if (!IsNeedPassword(aconf))
826     *prefix_ptr++ = '&';
827     if (IsConfExemptResv(aconf))
828     *prefix_ptr++ = '$';
829     if (IsNoMatchIp(aconf))
830     *prefix_ptr++ = '%';
831     if (IsConfDoSpoofIp(aconf))
832     *prefix_ptr++ = '=';
833     if (MyOper(sptr) && IsConfExemptKline(aconf))
834     *prefix_ptr++ = '^';
835     if (MyOper(sptr) && IsConfExemptGline(aconf))
836     *prefix_ptr++ = '_';
837     if (MyOper(sptr) && IsConfExemptLimits(aconf))
838     *prefix_ptr++ = '>';
839     if (IsConfCanFlood(aconf))
840     *prefix_ptr++ = '|';
841 michael 1298
842 michael 1014 strlcpy(prefix_ptr, name, USERLEN+1);
843 adx 30
844 michael 1298 return prefix_of_host;
845 adx 30 }
846    
847     /* report_auth()
848     *
849     * Inputs: pointer to client to report to
850     * Output: None
851     * Side effects: Reports configured auth{} blocks to client_p
852     */
853     void
854     report_auth(struct Client *client_p)
855     {
856     struct ConfItem *conf;
857     struct AccessItem *aconf;
858 michael 1367 dlink_node *ptr = NULL;
859     unsigned int i;
860 adx 30
861 michael 1367
862     for (i = 0; i < ATABLE_SIZE; ++i)
863 adx 30 {
864 michael 1367 ptr = NULL;
865    
866     DLINK_FOREACH(ptr, atable[i].head)
867 adx 30 {
868 michael 1367 struct AddressRec *arec = ptr->data;
869    
870 adx 30 if (arec->type == CONF_CLIENT)
871     {
872     aconf = arec->aconf;
873    
874     if (!MyOper(client_p) && IsConfDoSpoofIp(aconf))
875     continue;
876    
877     conf = unmap_conf_item(aconf);
878    
879     /* We are doing a partial list, based on what matches the u@h of the
880     * sender, so prepare the strings for comparing --fl_
881     */
882     if (ConfigFileEntry.hide_spoof_ips)
883     sendto_one(client_p, form_str(RPL_STATSILINE), me.name,
884     client_p->name, 'I',
885     conf->name == NULL ? "*" : conf->name,
886     show_iline_prefix(client_p, aconf, aconf->user),
887     IsConfDoSpoofIp(aconf) ? "255.255.255.255" :
888     aconf->host, aconf->port,
889     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
890    
891     else
892     sendto_one(client_p, form_str(RPL_STATSILINE), me.name,
893     client_p->name, 'I',
894     conf->name == NULL ? "*" : conf->name,
895     show_iline_prefix(client_p, aconf, aconf->user),
896     aconf->host, aconf->port,
897     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
898     }
899     }
900     }
901     }
902    
903     /* report_Klines()
904     * Inputs: Client to report to,
905     * type(==0 for perm, !=0 for temporary)
906     * mask
907     * Output: None
908     * Side effects: Reports configured K(or k)-lines to client_p.
909     */
910     void
911     report_Klines(struct Client *client_p, int tkline)
912     {
913     struct AccessItem *aconf = NULL;
914 michael 1367 unsigned int i = 0;
915 adx 30 const char *p = NULL;
916 michael 1367 dlink_node *ptr = NULL;
917 adx 30
918     if (tkline)
919     p = "k";
920     else
921     p = "K";
922    
923 michael 1367 for (i = 0; i < ATABLE_SIZE; ++i)
924 adx 30 {
925 michael 1367 ptr = NULL;
926    
927     DLINK_FOREACH(ptr, atable[i].head)
928 adx 30 {
929 michael 1367 struct AddressRec *arec = ptr->data;
930    
931 adx 30 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