ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/src/hostmask.c
Revision: 2995
Committed: Tue Feb 18 21:16:17 2014 UTC (10 years, 1 month ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid/trunk/src/hostmask.c
File size: 21261 byte(s)
Log Message:
- hostmask.c: get rid of this (type & ~0x1) hack

File Contents

# User Rev Content
1 adx 30 /*
2 michael 2916 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 adx 30 *
4 michael 2916 * Copyright (c) 2001-2014 ircd-hybrid development team
5 adx 30 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19     * USA
20     */
21    
22 michael 2916 /*! \file hostmask.c
23     * \brief Code to efficiently find IP & hostmask based configs.
24     * \version $Id$
25     */
26    
27 adx 30 #include "stdinc.h"
28     #include "memory.h"
29     #include "ircd_defs.h"
30 michael 1011 #include "list.h"
31 michael 1309 #include "conf.h"
32 adx 30 #include "hostmask.h"
33     #include "send.h"
34     #include "irc_string.h"
35 michael 1369 #include "ircd.h"
36 adx 30
37    
38     #define DigitParse(ch) do { \
39     if (ch >= '0' && ch <= '9') \
40     ch = ch - '0'; \
41     else if (ch >= 'A' && ch <= 'F') \
42     ch = ch - 'A' + 10; \
43     else if (ch >= 'a' && ch <= 'f') \
44     ch = ch - 'a' + 10; \
45 michael 1298 } while (0);
46 adx 30
47     /* The mask parser/type determination code... */
48    
49     /* int try_parse_v6_netmask(const char *, struct irc_ssaddr *, int *);
50     * Input: A possible IPV6 address as a string.
51     * Output: An integer describing whether it is an IPV6 or hostmask,
52     * an address(if it is IPV6), a bitlength(if it is IPV6).
53     * Side effects: None
54     * Comments: Called from parse_netmask
55     */
56 michael 2916 /* Fixed so ::/0 (any IPv6 address) is valid
57 adx 30 Also a bug in DigitParse above.
58     -Gozem 2002-07-19 gozem@linux.nu
59     */
60     #ifdef IPV6
61     static int
62     try_parse_v6_netmask(const char *text, struct irc_ssaddr *addr, int *b)
63     {
64     const char *p;
65     char c;
66     int d[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
67     int dp = 0;
68     int nyble = 4;
69     int finsert = -1;
70     int bits = 128;
71     int deficit = 0;
72     short dc[8];
73 michael 1298 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
74 adx 30
75     for (p = text; (c = *p); p++)
76 michael 2894 {
77 adx 30 if (IsXDigit(c))
78     {
79     if (nyble == 0)
80     return HM_HOST;
81     DigitParse(c);
82     d[dp] |= c << (4 * --nyble);
83     }
84     else if (c == ':')
85     {
86     if (p > text && *(p - 1) == ':')
87     {
88     if (finsert >= 0)
89     return HM_HOST;
90     finsert = dp;
91     }
92     else
93     {
94     /* If there were less than 4 hex digits, e.g. :ABC: shift right
95     * so we don't interpret it as ABC0 -A1kmm */
96     d[dp] = d[dp] >> 4 * nyble;
97     nyble = 4;
98     if (++dp >= 8)
99     return HM_HOST;
100     }
101     }
102     else if (c == '*')
103     {
104     /* * must be last, and * is ambiguous if there is a ::... -A1kmm */
105     if (finsert >= 0 || *(p + 1) || dp == 0 || *(p - 1) != ':')
106     return HM_HOST;
107     bits = dp * 16;
108     }
109     else if (c == '/')
110     {
111     char *after;
112    
113     d[dp] = d[dp] >> 4 * nyble;
114     dp++;
115     bits = strtoul(p + 1, &after, 10);
116 michael 1298
117 adx 30 if (bits < 0 || *after)
118     return HM_HOST;
119     if (bits > dp * 4 && !(finsert >= 0 && bits <= 128))
120     return HM_HOST;
121     break;
122     }
123     else
124     return HM_HOST;
125 michael 2894 }
126 adx 30
127     d[dp] = d[dp] >> 4 * nyble;
128 michael 1298
129 adx 30 if (c == 0)
130     dp++;
131     if (finsert < 0 && bits == 0)
132     bits = dp * 16;
133 michael 1298
134 adx 30 /* How many words are missing? -A1kmm */
135     deficit = bits / 16 + ((bits % 16) ? 1 : 0) - dp;
136 michael 1298
137 adx 30 /* Now fill in the gaps(from ::) in the copied table... -A1kmm */
138     for (dp = 0, nyble = 0; dp < 8; dp++)
139     {
140     if (nyble == finsert && deficit)
141     {
142     dc[dp] = 0;
143     deficit--;
144     }
145     else
146     dc[dp] = d[nyble++];
147     }
148 michael 1298
149 adx 30 /* Set unused bits to 0... -A1kmm */
150     if (bits < 128 && (bits % 16 != 0))
151     dc[bits / 16] &= ~((1 << (15 - bits % 16)) - 1);
152     for (dp = bits / 16 + (bits % 16 ? 1 : 0); dp < 8; dp++)
153     dc[dp] = 0;
154 michael 1298
155 adx 30 /* And assign... -A1kmm */
156     if (addr)
157     for (dp = 0; dp < 8; dp++)
158     /* The cast is a kludge to make netbsd work. */
159     ((unsigned short *)&v6->sin6_addr)[dp] = htons(dc[dp]);
160 michael 1298
161 adx 30 if (b != NULL)
162     *b = bits;
163     return HM_IPV6;
164     }
165     #endif
166    
167     /* int try_parse_v4_netmask(const char *, struct irc_ssaddr *, int *);
168     * Input: A possible IPV4 address as a string.
169     * Output: An integer describing whether it is an IPV4 or hostmask,
170     * an address(if it is IPV4), a bitlength(if it is IPV4).
171     * Side effects: None
172     * Comments: Called from parse_netmask
173     */
174     static int
175     try_parse_v4_netmask(const char *text, struct irc_ssaddr *addr, int *b)
176     {
177     const char *p;
178     const char *digits[4];
179     unsigned char addb[4];
180     int n = 0, bits = 0;
181     char c;
182 michael 1298 struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
183 adx 30
184     digits[n++] = text;
185    
186     for (p = text; (c = *p); p++)
187 michael 2894 {
188 adx 30 if (c >= '0' && c <= '9') /* empty */
189     ;
190     else if (c == '.')
191     {
192     if (n >= 4)
193     return HM_HOST;
194 michael 1298
195 adx 30 digits[n++] = p + 1;
196     }
197     else if (c == '*')
198     {
199     if (*(p + 1) || n == 0 || *(p - 1) != '.')
200     return HM_HOST;
201 michael 1298
202 adx 30 bits = (n - 1) * 8;
203     break;
204     }
205     else if (c == '/')
206     {
207     char *after;
208     bits = strtoul(p + 1, &after, 10);
209 michael 1298
210 michael 1786 if (bits < 0 || *after)
211 adx 30 return HM_HOST;
212     if (bits > n * 8)
213     return HM_HOST;
214 michael 1298
215 adx 30 break;
216     }
217     else
218     return HM_HOST;
219 michael 2894 }
220 adx 30
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 michael 2814 if (strchr(text, '.'))
257     return try_parse_v4_netmask(text, addr, b);
258 adx 30 #ifdef IPV6
259 michael 1298 if (strchr(text, ':'))
260 adx 30 return try_parse_v6_netmask(text, addr, b);
261     #endif
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 michael 1455 match_ipv6(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
274 adx 30 {
275     int i, m, n = bits / 8;
276 michael 1455 const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
277     const struct sockaddr_in6 *v6mask = (const 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 michael 1372
291 adx 30 /* 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 michael 1455 match_ipv4(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
298 adx 30 {
299 michael 1455 const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
300     const struct sockaddr_in *v4mask = (const struct sockaddr_in *)mask;
301 michael 1298
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 michael 2898 hash_ipv4(const struct irc_ssaddr *addr, int bits)
367 adx 30 {
368     if (bits != 0)
369     {
370 michael 2898 const struct sockaddr_in *v4 = (const 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 michael 2898 hash_ipv6(const struct irc_ssaddr *addr, int bits)
387 adx 30 {
388 michael 1343 uint32_t v = 0, n;
389 michael 2898 const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
390 michael 1298
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 michael 2331 h = (h << 4) - (h + 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 michael 1632 /* struct MaskItem *find_conf_by_address(const char *, struct irc_ssaddr *,
447 adx 30 * 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 michael 1632 * should always be true (i.e. conf->flags & CONF_FLAGS_NEED_PASSWORD == 0)
455 adx 30 */
456 michael 1632 struct MaskItem *
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 michael 1632 struct MaskItem *hprec = NULL;
463     struct AddressRec *arec = NULL;
464 adx 30 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 michael 2916 arec = ptr->data;
483 michael 1367
484 michael 2995 if ((arec->type == type) &&
485 adx 30 arec->precedence > hprecv &&
486     arec->masktype == HM_IPV6 &&
487     match_ipv6(addr, &arec->Mask.ipa.addr,
488     arec->Mask.ipa.bits) &&
489 michael 2995 (!username || !cmpfunc(arec->username, username)) &&
490 michael 2916 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
491     match_conf_password(password, arec->conf)))
492 adx 30 {
493     hprecv = arec->precedence;
494 michael 1632 hprec = arec->conf;
495 adx 30 }
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 michael 2995 if ((arec->type == type) &&
510 adx 30 arec->precedence > hprecv &&
511     arec->masktype == HM_IPV4 &&
512     match_ipv4(addr, &arec->Mask.ipa.addr,
513     arec->Mask.ipa.bits) &&
514 michael 2995 (!username || !cmpfunc(arec->username, username)) &&
515 michael 2916 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
516     match_conf_password(password, arec->conf)))
517 adx 30 {
518     hprecv = arec->precedence;
519 michael 1632 hprec = arec->conf;
520 adx 30 }
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 michael 2995 if ((arec->type == type) &&
536 adx 30 arec->precedence > hprecv &&
537     (arec->masktype == HM_HOST) &&
538 michael 1652 !cmpfunc(arec->Mask.hostname, name) &&
539 michael 2995 (!username || !cmpfunc(arec->username, username)) &&
540 michael 1632 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
541     match_conf_password(password, arec->conf)))
542 adx 30 {
543     hprecv = arec->precedence;
544 michael 1632 hprec = arec->conf;
545 adx 30 }
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 michael 2995 if (arec->type == type &&
558 adx 30 arec->precedence > hprecv &&
559     arec->masktype == HM_HOST &&
560 michael 1652 !cmpfunc(arec->Mask.hostname, name) &&
561 michael 2995 (!username || !cmpfunc(arec->username, username)) &&
562 michael 1632 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
563     match_conf_password(password, arec->conf)))
564 adx 30 {
565     hprecv = arec->precedence;
566 michael 1632 hprec = arec->conf;
567 adx 30 }
568 michael 1367 }
569 adx 30 }
570    
571     return hprec;
572     }
573    
574 michael 1632 /* struct MaskItem* find_address_conf(const char*, const char*,
575 adx 30 * struct irc_ssaddr*, int, char *);
576     * Input: The hostname, username, address, address family.
577 michael 1632 * Output: The applicable MaskItem.
578 adx 30 * Side-effects: None
579     */
580 michael 1632 struct MaskItem *
581 adx 30 find_address_conf(const char *host, const char *user,
582     struct irc_ssaddr *ip, int aftype, char *password)
583     {
584 michael 1632 struct MaskItem *authcnf = NULL, *killcnf = NULL;
585 adx 30
586 michael 1426 /* Find the best auth{} block... If none, return NULL -A1kmm */
587 michael 1632 if ((authcnf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
588     password, 1)) == NULL)
589 michael 1298 return NULL;
590 adx 30
591 michael 1426 /* If they are exempt from K-lines, return the best auth{} block. -A1kmm */
592 michael 1632 if (IsConfExemptKline(authcnf))
593     return authcnf;
594 adx 30
595     /* Find the best K-line... -A1kmm */
596 michael 1632 killcnf = find_conf_by_address(host, ip, CONF_KLINE, aftype, user, NULL, 1);
597 adx 30
598 michael 1426 /*
599     * If they are K-lined, return the K-line. Otherwise, return the
600     * auth{} block. -A1kmm
601     */
602 michael 1632 if (killcnf != NULL)
603     return killcnf;
604 adx 30
605 michael 1632 if (IsConfExemptGline(authcnf))
606     return authcnf;
607 adx 30
608 michael 1632 killcnf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL, 1);
609     if (killcnf != NULL)
610     return killcnf;
611    
612     return authcnf;
613 adx 30 }
614    
615 michael 1632 /* struct MaskItem* find_dline_conf(struct irc_ssaddr*, int)
616 adx 30 *
617     * Input: An address, an address family.
618     * Output: The best matching D-line or exempt line.
619     * Side effects: None.
620     */
621 michael 1632 struct MaskItem *
622 adx 30 find_dline_conf(struct irc_ssaddr *addr, int aftype)
623     {
624 michael 1632 struct MaskItem *eline;
625 adx 30
626 michael 2995 eline = find_conf_by_address(NULL, addr, CONF_EXEMPT, aftype, NULL, NULL, 1);
627 adx 30 if (eline != NULL)
628 michael 1298 return eline;
629    
630 michael 2995 return find_conf_by_address(NULL, addr, CONF_DLINE, aftype, NULL, NULL, 1);
631 adx 30 }
632    
633 michael 1632 /* void add_conf_by_address(int, struct MaskItem *aconf)
634 michael 2916 * Input:
635 adx 30 * Output: None
636     * Side-effects: Adds this entry to the hash table.
637     */
638 michael 2811 struct AddressRec *
639 michael 1632 add_conf_by_address(const unsigned int type, struct MaskItem *conf)
640 adx 30 {
641     const char *address;
642     const char *username;
643 michael 1343 static unsigned int prec_value = 0xFFFFFFFF;
644 michael 1367 int bits = 0;
645 adx 30 struct AddressRec *arec;
646    
647 michael 1632 address = conf->host;
648     username = conf->user;
649 adx 30
650 michael 1632 assert(type);
651 adx 30
652     if (EmptyString(address))
653     address = "/NOMATCH!/";
654    
655     arec = MyMalloc(sizeof(struct AddressRec));
656 michael 1367 arec->masktype = parse_netmask(address, &arec->Mask.ipa.addr, &bits);
657 adx 30 arec->Mask.ipa.bits = bits;
658 michael 1367 arec->username = username;
659 michael 1632 arec->conf = conf;
660 michael 1367 arec->precedence = prec_value--;
661     arec->type = type;
662 michael 1298
663 michael 1367 switch (arec->masktype)
664     {
665     case HM_IPV4:
666     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
667     bits -= bits % 8;
668     dlinkAdd(arec, &arec->node, &atable[hash_ipv4(&arec->Mask.ipa.addr, bits)]);
669     break;
670 adx 30 #ifdef IPV6
671 michael 1367 case HM_IPV6:
672     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
673     bits -= bits % 16;
674     dlinkAdd(arec, &arec->node, &atable[hash_ipv6(&arec->Mask.ipa.addr, bits)]);
675     break;
676 adx 30 #endif
677 michael 1367 default: /* HM_HOST */
678     arec->Mask.hostname = address;
679     dlinkAdd(arec, &arec->node, &atable[get_mask_hash(address)]);
680     break;
681 adx 30 }
682 michael 2811
683     return arec;
684 adx 30 }
685    
686 michael 1632 /* void delete_one_address(const char*, struct MaskItem*)
687     * Input: An address string, the associated MaskItem.
688 adx 30 * Output: None
689 michael 1632 * Side effects: Deletes an address record. Frees the MaskItem if there
690 adx 30 * is nothing referencing it, sets it as illegal otherwise.
691     */
692     void
693 michael 1632 delete_one_address_conf(const char *address, struct MaskItem *conf)
694 adx 30 {
695 michael 1367 int bits = 0;
696     uint32_t hv = 0;
697     dlink_node *ptr = NULL, *ptr_next = NULL;
698 adx 30 struct irc_ssaddr addr;
699 michael 1298
700 michael 1367 switch (parse_netmask(address, &addr, &bits))
701     {
702     case HM_IPV4:
703     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
704     bits -= bits % 8;
705     hv = hash_ipv4(&addr, bits);
706     break;
707 adx 30 #ifdef IPV6
708 michael 1367 case HM_IPV6:
709     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
710     bits -= bits % 16;
711     hv = hash_ipv6(&addr, bits);
712     break;
713 adx 30 #endif
714 michael 1367 default: /* HM_HOST */
715     hv = get_mask_hash(address);
716     break;
717 adx 30 }
718 michael 1298
719 michael 1367 DLINK_FOREACH_SAFE(ptr, ptr_next, atable[hv].head)
720 adx 30 {
721 michael 1367 struct AddressRec *arec = ptr->data;
722    
723 michael 1632 if (arec->conf == conf)
724 adx 30 {
725 michael 1367 dlinkDelete(&arec->node, &atable[hv]);
726 michael 1298
727 michael 1644 if (!conf->ref_count)
728 michael 1632 conf_free(conf);
729 michael 1298
730 adx 30 MyFree(arec);
731     return;
732     }
733     }
734     }
735    
736     /* void clear_out_address_conf(void)
737     * Input: None
738     * Output: None
739     * Side effects: Clears out all address records in the hash table,
740 michael 1632 * frees them, and frees the MaskItems if nothing references
741 michael 2916 * them, otherwise sets them as illegal.
742 adx 30 */
743     void
744     clear_out_address_conf(void)
745     {
746 michael 1367 unsigned int i = 0;
747     dlink_node *ptr = NULL, *ptr_next = NULL;
748 michael 2916
749 michael 1367 for (i = 0; i < ATABLE_SIZE; ++i)
750 adx 30 {
751 michael 1367 DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
752 adx 30 {
753 michael 1367 struct AddressRec *arec = ptr->data;
754    
755 michael 1628 /*
756     * We keep the temporary K-lines and destroy the permanent ones,
757     * just to be confusing :) -A1kmm
758     */
759 michael 1649 if (arec->conf->until || IsConfDatabase(arec->conf))
760 michael 1628 continue;
761 michael 1622
762 michael 1628 dlinkDelete(&arec->node, &atable[i]);
763 michael 1298
764 michael 1644 if (!arec->conf->ref_count)
765 michael 1632 conf_free(arec->conf);
766 michael 1628 MyFree(arec);
767 adx 30 }
768     }
769     }
770    
771 michael 1369 static void
772     hostmask_send_expiration(struct AddressRec *arec)
773     {
774     char ban_type = '\0';
775    
776     if (!ConfigFileEntry.tkline_expire_notices)
777     return;
778    
779     switch (arec->type)
780     {
781     case CONF_KLINE:
782     ban_type = 'K';
783     break;
784     case CONF_DLINE:
785     ban_type = 'D';
786     break;
787     case CONF_GLINE:
788     ban_type = 'G';
789     break;
790 michael 1644 default: break;
791 michael 1369 }
792 michael 2916
793 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
794 michael 1369 "Temporary %c-line for [%s@%s] expired", ban_type,
795 michael 1632 (arec->conf->user) ? arec->conf->user : "*",
796     (arec->conf->host) ? arec->conf->host : "*");
797 michael 1369 }
798    
799     void
800     hostmask_expire_temporary(void)
801     {
802     unsigned int i = 0;
803     dlink_node *ptr = NULL, *ptr_next = NULL;
804    
805     for (i = 0; i < ATABLE_SIZE; ++i)
806     {
807     DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
808     {
809     struct AddressRec *arec = ptr->data;
810    
811 michael 1649 if (!arec->conf->until || arec->conf->until > CurrentTime)
812 michael 1369 continue;
813    
814     switch (arec->type)
815     {
816     case CONF_KLINE:
817     case CONF_DLINE:
818     case CONF_GLINE:
819     hostmask_send_expiration(arec);
820    
821     dlinkDelete(&arec->node, &atable[i]);
822 michael 1632 conf_free(arec->conf);
823 michael 1369 MyFree(arec);
824     break;
825 michael 1644 default: break;
826 michael 1369 }
827     }
828     }
829     }

Properties

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