ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hostmask.c
Revision: 4815
Committed: Sat Nov 1 15:28:42 2014 UTC (10 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 20917 byte(s)
Log Message:
- Renamed variables

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 michael 4565 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 adx 30 * 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     static int
61     try_parse_v6_netmask(const char *text, struct irc_ssaddr *addr, int *b)
62     {
63     char c;
64     int d[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
65     int dp = 0;
66     int nyble = 4;
67     int finsert = -1;
68     int bits = 128;
69     int deficit = 0;
70     short dc[8];
71 michael 1298 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
72 adx 30
73 michael 3469 for (const char *p = text; (c = *p); ++p)
74 michael 2894 {
75 adx 30 if (IsXDigit(c))
76     {
77     if (nyble == 0)
78     return HM_HOST;
79     DigitParse(c);
80     d[dp] |= c << (4 * --nyble);
81     }
82     else if (c == ':')
83     {
84     if (p > text && *(p - 1) == ':')
85     {
86     if (finsert >= 0)
87     return HM_HOST;
88     finsert = dp;
89     }
90     else
91     {
92     /* If there were less than 4 hex digits, e.g. :ABC: shift right
93     * so we don't interpret it as ABC0 -A1kmm */
94     d[dp] = d[dp] >> 4 * nyble;
95     nyble = 4;
96     if (++dp >= 8)
97     return HM_HOST;
98     }
99     }
100     else if (c == '*')
101     {
102     /* * must be last, and * is ambiguous if there is a ::... -A1kmm */
103     if (finsert >= 0 || *(p + 1) || dp == 0 || *(p - 1) != ':')
104     return HM_HOST;
105     bits = dp * 16;
106     }
107     else if (c == '/')
108     {
109     char *after;
110    
111     d[dp] = d[dp] >> 4 * nyble;
112 michael 3215 ++dp;
113 adx 30 bits = strtoul(p + 1, &after, 10);
114 michael 1298
115 adx 30 if (bits < 0 || *after)
116     return HM_HOST;
117     if (bits > dp * 4 && !(finsert >= 0 && bits <= 128))
118     return HM_HOST;
119     break;
120     }
121     else
122     return HM_HOST;
123 michael 2894 }
124 adx 30
125     d[dp] = d[dp] >> 4 * nyble;
126 michael 1298
127 adx 30 if (c == 0)
128 michael 3215 ++dp;
129 adx 30 if (finsert < 0 && bits == 0)
130     bits = dp * 16;
131 michael 1298
132 adx 30 /* How many words are missing? -A1kmm */
133     deficit = bits / 16 + ((bits % 16) ? 1 : 0) - dp;
134 michael 1298
135 adx 30 /* Now fill in the gaps(from ::) in the copied table... -A1kmm */
136 michael 3215 for (dp = 0, nyble = 0; dp < 8; ++dp)
137 adx 30 {
138     if (nyble == finsert && deficit)
139     {
140     dc[dp] = 0;
141     deficit--;
142     }
143     else
144     dc[dp] = d[nyble++];
145     }
146 michael 1298
147 adx 30 /* Set unused bits to 0... -A1kmm */
148     if (bits < 128 && (bits % 16 != 0))
149     dc[bits / 16] &= ~((1 << (15 - bits % 16)) - 1);
150 michael 3215 for (dp = bits / 16 + (bits % 16 ? 1 : 0); dp < 8; ++dp)
151 adx 30 dc[dp] = 0;
152 michael 1298
153 adx 30 /* And assign... -A1kmm */
154     if (addr)
155 michael 3215 for (dp = 0; dp < 8; ++dp)
156 adx 30 /* The cast is a kludge to make netbsd work. */
157     ((unsigned short *)&v6->sin6_addr)[dp] = htons(dc[dp]);
158 michael 1298
159 michael 3215 if (b)
160 adx 30 *b = bits;
161     return HM_IPV6;
162     }
163    
164     /* int try_parse_v4_netmask(const char *, struct irc_ssaddr *, int *);
165     * Input: A possible IPV4 address as a string.
166     * Output: An integer describing whether it is an IPV4 or hostmask,
167     * an address(if it is IPV4), a bitlength(if it is IPV4).
168     * Side effects: None
169     * Comments: Called from parse_netmask
170     */
171     static int
172     try_parse_v4_netmask(const char *text, struct irc_ssaddr *addr, int *b)
173     {
174     const char *digits[4];
175     unsigned char addb[4];
176     int n = 0, bits = 0;
177     char c;
178 michael 1298 struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
179 adx 30
180     digits[n++] = text;
181    
182 michael 3469 for (const char *p = text; (c = *p); ++p)
183 michael 2894 {
184 adx 30 if (c >= '0' && c <= '9') /* empty */
185     ;
186     else if (c == '.')
187     {
188     if (n >= 4)
189     return HM_HOST;
190 michael 1298
191 adx 30 digits[n++] = p + 1;
192     }
193     else if (c == '*')
194     {
195     if (*(p + 1) || n == 0 || *(p - 1) != '.')
196     return HM_HOST;
197 michael 1298
198 adx 30 bits = (n - 1) * 8;
199     break;
200     }
201     else if (c == '/')
202     {
203     char *after;
204     bits = strtoul(p + 1, &after, 10);
205 michael 1298
206 michael 1786 if (bits < 0 || *after)
207 adx 30 return HM_HOST;
208     if (bits > n * 8)
209     return HM_HOST;
210 michael 1298
211 adx 30 break;
212     }
213     else
214     return HM_HOST;
215 michael 2894 }
216 adx 30
217     if (n < 4 && bits == 0)
218     bits = n * 8;
219     if (bits)
220     while (n < 4)
221     digits[n++] = "0";
222 michael 1298
223 michael 3215 for (n = 0; n < 4; ++n)
224 adx 30 addb[n] = strtoul(digits[n], NULL, 10);
225 michael 1298
226 adx 30 if (bits == 0)
227     bits = 32;
228 michael 1298
229 adx 30 /* Set unused bits to 0... -A1kmm */
230     if (bits < 32 && bits % 8)
231     addb[bits / 8] &= ~((1 << (8 - bits % 8)) - 1);
232 michael 3215 for (n = bits / 8 + (bits % 8 ? 1 : 0); n < 4; ++n)
233 adx 30 addb[n] = 0;
234     if (addr)
235     v4->sin_addr.s_addr =
236     htonl(addb[0] << 24 | addb[1] << 16 | addb[2] << 8 | addb[3]);
237 michael 3215 if (b)
238 adx 30 *b = bits;
239     return HM_IPV4;
240     }
241    
242     /* int parse_netmask(const char *, struct irc_ssaddr *, int *);
243     * Input: A hostmask, or an IPV4/6 address.
244     * Output: An integer describing whether it is an IPV4, IPV6 address or a
245     * hostmask, an address(if it is an IP mask),
246     * a bitlength(if it is IP mask).
247     * Side effects: None
248     */
249     int
250     parse_netmask(const char *text, struct irc_ssaddr *addr, int *b)
251     {
252 michael 2814 if (strchr(text, '.'))
253     return try_parse_v4_netmask(text, addr, b);
254 michael 1298 if (strchr(text, ':'))
255 adx 30 return try_parse_v6_netmask(text, addr, b);
256 michael 4415
257 adx 30 return HM_HOST;
258     }
259    
260     /* The address matching stuff... */
261     /* int match_ipv6(struct irc_ssaddr *, struct irc_ssaddr *, int)
262     * Input: An IP address, an IP mask, the number of bits in the mask.
263     * Output: if match, -1 else 0
264     * Side effects: None
265     */
266     int
267 michael 1455 match_ipv6(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
268 adx 30 {
269     int i, m, n = bits / 8;
270 michael 1455 const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
271     const struct sockaddr_in6 *v6mask = (const struct sockaddr_in6 *)mask;
272 adx 30
273 michael 3215 for (i = 0; i < n; ++i)
274 adx 30 if (v6->sin6_addr.s6_addr[i] != v6mask->sin6_addr.s6_addr[i])
275     return 0;
276 michael 3215
277 adx 30 if ((m = bits % 8) == 0)
278     return -1;
279     if ((v6->sin6_addr.s6_addr[n] & ~((1 << (8 - m)) - 1)) ==
280     v6mask->sin6_addr.s6_addr[n])
281     return -1;
282     return 0;
283     }
284 michael 1372
285 adx 30 /* int match_ipv4(struct irc_ssaddr *, struct irc_ssaddr *, int)
286     * Input: An IP address, an IP mask, the number of bits in the mask.
287     * Output: if match, -1 else 0
288     * Side Effects: None
289     */
290     int
291 michael 1455 match_ipv4(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
292 adx 30 {
293 michael 1455 const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
294     const struct sockaddr_in *v4mask = (const struct sockaddr_in *)mask;
295 michael 1298
296 adx 30 if ((ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1)) !=
297     ntohl(v4mask->sin_addr.s_addr))
298     return 0;
299     return -1;
300     }
301    
302     /*
303     * mask_addr
304     *
305     * inputs - pointer to the ip to mask
306     * - bitlen
307     * output - NONE
308     * side effects -
309     */
310     void
311     mask_addr(struct irc_ssaddr *ip, int bits)
312     {
313     int mask;
314     struct sockaddr_in6 *v6_base_ip;
315     int i, m, n;
316     struct sockaddr_in *v4_base_ip;
317    
318 michael 4415 if (ip->ss.ss_family == AF_INET)
319 adx 30 {
320 michael 3770 uint32_t tmp = 0;
321 michael 1298 v4_base_ip = (struct sockaddr_in *)ip;
322    
323 adx 30 mask = ~((1 << (32 - bits)) - 1);
324 michael 3770 tmp = ntohl(v4_base_ip->sin_addr.s_addr);
325     v4_base_ip->sin_addr.s_addr = htonl(tmp & mask);
326 adx 30 }
327     else
328     {
329     n = bits / 8;
330     m = bits % 8;
331 michael 1298 v6_base_ip = (struct sockaddr_in6 *)ip;
332 adx 30
333     mask = ~((1 << (8 - m)) -1 );
334     v6_base_ip->sin6_addr.s6_addr[n] = v6_base_ip->sin6_addr.s6_addr[n] & mask;
335 michael 1298
336 db 300 for (i = n + 1; i < 16; i++)
337     v6_base_ip->sin6_addr.s6_addr[i] = 0;
338 adx 30 }
339     }
340    
341 michael 4298 /* Hashtable stuff...now external as it's used in m_stats.c */
342 michael 1367 dlink_list atable[ATABLE_SIZE];
343 adx 30
344     void
345     init_host_hash(void)
346     {
347     memset(&atable, 0, sizeof(atable));
348     }
349    
350     /* unsigned long hash_ipv4(struct irc_ssaddr*)
351     * Input: An IP address.
352     * Output: A hash value of the IP address.
353     * Side effects: None
354     */
355 michael 1343 static uint32_t
356 michael 2898 hash_ipv4(const struct irc_ssaddr *addr, int bits)
357 adx 30 {
358     if (bits != 0)
359     {
360 michael 2898 const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
361 michael 1343 uint32_t av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
362 michael 1298
363     return (av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1);
364 adx 30 }
365    
366 michael 1298 return 0;
367 adx 30 }
368    
369     /* unsigned long hash_ipv6(struct irc_ssaddr*)
370     * Input: An IP address.
371     * Output: A hash value of the IP address.
372     * Side effects: None
373     */
374 michael 1343 static uint32_t
375 michael 2898 hash_ipv6(const struct irc_ssaddr *addr, int bits)
376 adx 30 {
377 michael 1343 uint32_t v = 0, n;
378 michael 2898 const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
379 michael 1298
380 michael 3215 for (n = 0; n < 16; ++n)
381 adx 30 {
382     if (bits >= 8)
383     {
384     v ^= v6->sin6_addr.s6_addr[n];
385     bits -= 8;
386     }
387     else if (bits)
388     {
389     v ^= v6->sin6_addr.s6_addr[n] & ~((1 << (8 - bits)) - 1);
390     return v & (ATABLE_SIZE - 1);
391     }
392     else
393     return v & (ATABLE_SIZE - 1);
394     }
395 michael 4415
396 adx 30 return v & (ATABLE_SIZE - 1);
397     }
398    
399     /* int hash_text(const char *start)
400     * Input: The start of the text to hash.
401     * Output: The hash of the string between 1 and (TH_MAX-1)
402     * Side-effects: None.
403     */
404 michael 1343 static uint32_t
405 adx 30 hash_text(const char *start)
406     {
407 michael 1343 uint32_t h = 0;
408 adx 30
409 michael 3469 for (const char *p = start; *p; ++p)
410 michael 2331 h = (h << 4) - (h + ToLower(*p));
411 michael 1298
412     return h & (ATABLE_SIZE - 1);
413 adx 30 }
414    
415     /* unsigned long get_hash_mask(const char *)
416     * Input: The text to hash.
417     * Output: The hash of the string right of the first '.' past the last
418     * wildcard in the string.
419     * Side-effects: None.
420     */
421 michael 1343 static uint32_t
422 adx 30 get_mask_hash(const char *text)
423     {
424     const char *hp = "", *p;
425    
426 michael 3215 for (p = text + strlen(text) - 1; p >= text; --p)
427 adx 723 if (IsMWildChar(*p))
428 adx 30 return hash_text(hp);
429     else if (*p == '.')
430     hp = p + 1;
431     return hash_text(text);
432     }
433    
434 michael 1632 /* struct MaskItem *find_conf_by_address(const char *, struct irc_ssaddr *,
435 adx 30 * int type, int fam, const char *username)
436     * Input: The hostname, the address, the type of mask to find, the address
437     * family, the username.
438     * Output: The matching value with the highest precedence.
439     * Side-effects: None
440     * Note: Setting bit 0 of the type means that the username is ignored.
441     * Warning: IsNeedPassword for everything that is not an auth{} entry
442 michael 1632 * should always be true (i.e. conf->flags & CONF_FLAGS_NEED_PASSWORD == 0)
443 adx 30 */
444 michael 1632 struct MaskItem *
445 michael 1369 find_conf_by_address(const char *name, struct irc_ssaddr *addr, unsigned int type,
446 michael 1371 int fam, const char *username, const char *password, int do_match)
447 adx 30 {
448 michael 1343 unsigned int hprecv = 0;
449 michael 4815 dlink_node *node = NULL;
450 michael 1632 struct MaskItem *hprec = NULL;
451     struct AddressRec *arec = NULL;
452 adx 30 int b;
453 michael 1371 int (*cmpfunc)(const char *, const char *) = do_match ? match : irccmp;
454 adx 30
455     if (addr)
456     {
457     /* Check for IPV6 matches... */
458     if (fam == AF_INET6)
459     {
460     for (b = 128; b >= 0; b -= 16)
461     {
462 michael 4815 DLINK_FOREACH(node, atable[hash_ipv6(addr, b)].head)
463 michael 1367 {
464 michael 4815 arec = node->data;
465 michael 1367
466 michael 2995 if ((arec->type == type) &&
467 adx 30 arec->precedence > hprecv &&
468     arec->masktype == HM_IPV6 &&
469     match_ipv6(addr, &arec->Mask.ipa.addr,
470     arec->Mask.ipa.bits) &&
471 michael 2995 (!username || !cmpfunc(arec->username, username)) &&
472 michael 2916 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
473     match_conf_password(password, arec->conf)))
474 adx 30 {
475     hprecv = arec->precedence;
476 michael 1632 hprec = arec->conf;
477 adx 30 }
478 michael 1367 }
479 adx 30 }
480     }
481 michael 4415 else if (fam == AF_INET)
482 adx 30 {
483     for (b = 32; b >= 0; b -= 8)
484     {
485 michael 4815 DLINK_FOREACH(node, atable[hash_ipv4(addr, b)].head)
486 michael 1367 {
487 michael 4815 arec = node->data;
488 michael 1367
489 michael 2995 if ((arec->type == type) &&
490 adx 30 arec->precedence > hprecv &&
491     arec->masktype == HM_IPV4 &&
492     match_ipv4(addr, &arec->Mask.ipa.addr,
493     arec->Mask.ipa.bits) &&
494 michael 2995 (!username || !cmpfunc(arec->username, username)) &&
495 michael 2916 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
496     match_conf_password(password, arec->conf)))
497 adx 30 {
498     hprecv = arec->precedence;
499 michael 1632 hprec = arec->conf;
500 adx 30 }
501 michael 1367 }
502 adx 30 }
503     }
504     }
505    
506 michael 3215 if (name)
507 adx 30 {
508     const char *p = name;
509    
510     while (1)
511     {
512 michael 4815 DLINK_FOREACH(node, atable[hash_text(p)].head)
513 michael 1367 {
514 michael 4815 arec = node->data;
515 michael 2995 if ((arec->type == type) &&
516 adx 30 arec->precedence > hprecv &&
517     (arec->masktype == HM_HOST) &&
518 michael 1652 !cmpfunc(arec->Mask.hostname, name) &&
519 michael 2995 (!username || !cmpfunc(arec->username, username)) &&
520 michael 1632 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
521     match_conf_password(password, arec->conf)))
522 adx 30 {
523     hprecv = arec->precedence;
524 michael 1632 hprec = arec->conf;
525 adx 30 }
526 michael 1367 }
527 michael 3215
528     if ((p = strchr(p, '.')) == NULL)
529 adx 30 break;
530 michael 3215 ++p;
531 adx 30 }
532 michael 1367
533 michael 4815 DLINK_FOREACH(node, atable[0].head)
534 michael 1367 {
535 michael 4815 arec = node->data;
536 michael 1367
537 michael 2995 if (arec->type == type &&
538 adx 30 arec->precedence > hprecv &&
539     arec->masktype == HM_HOST &&
540 michael 1652 !cmpfunc(arec->Mask.hostname, name) &&
541 michael 2995 (!username || !cmpfunc(arec->username, username)) &&
542 michael 1632 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
543     match_conf_password(password, arec->conf)))
544 adx 30 {
545     hprecv = arec->precedence;
546 michael 1632 hprec = arec->conf;
547 adx 30 }
548 michael 1367 }
549 adx 30 }
550    
551     return hprec;
552     }
553    
554 michael 1632 /* struct MaskItem* find_address_conf(const char*, const char*,
555 adx 30 * struct irc_ssaddr*, int, char *);
556     * Input: The hostname, username, address, address family.
557 michael 1632 * Output: The applicable MaskItem.
558 adx 30 * Side-effects: None
559     */
560 michael 1632 struct MaskItem *
561 michael 3553 find_address_conf(const char *host, const char *user, struct irc_ssaddr *ip,
562     int aftype, const char *password)
563 adx 30 {
564 michael 1632 struct MaskItem *authcnf = NULL, *killcnf = NULL;
565 adx 30
566 michael 1426 /* Find the best auth{} block... If none, return NULL -A1kmm */
567 michael 1632 if ((authcnf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
568     password, 1)) == NULL)
569 michael 1298 return NULL;
570 adx 30
571 michael 1426 /* If they are exempt from K-lines, return the best auth{} block. -A1kmm */
572 michael 1632 if (IsConfExemptKline(authcnf))
573     return authcnf;
574 adx 30
575     /* Find the best K-line... -A1kmm */
576 michael 1632 killcnf = find_conf_by_address(host, ip, CONF_KLINE, aftype, user, NULL, 1);
577 adx 30
578 michael 1426 /*
579     * If they are K-lined, return the K-line. Otherwise, return the
580     * auth{} block. -A1kmm
581     */
582 michael 3215 if (killcnf)
583 michael 1632 return killcnf;
584 adx 30
585 michael 1632 if (IsConfExemptGline(authcnf))
586     return authcnf;
587 adx 30
588 michael 1632 killcnf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL, 1);
589 michael 3215 if (killcnf)
590 michael 1632 return killcnf;
591    
592     return authcnf;
593 adx 30 }
594    
595 michael 1632 /* struct MaskItem* find_dline_conf(struct irc_ssaddr*, int)
596 adx 30 *
597     * Input: An address, an address family.
598     * Output: The best matching D-line or exempt line.
599     * Side effects: None.
600     */
601 michael 1632 struct MaskItem *
602 adx 30 find_dline_conf(struct irc_ssaddr *addr, int aftype)
603     {
604 michael 1632 struct MaskItem *eline;
605 adx 30
606 michael 2995 eline = find_conf_by_address(NULL, addr, CONF_EXEMPT, aftype, NULL, NULL, 1);
607 michael 3215 if (eline)
608 michael 1298 return eline;
609    
610 michael 2995 return find_conf_by_address(NULL, addr, CONF_DLINE, aftype, NULL, NULL, 1);
611 adx 30 }
612    
613 michael 1632 /* void add_conf_by_address(int, struct MaskItem *aconf)
614 michael 2916 * Input:
615 adx 30 * Output: None
616     * Side-effects: Adds this entry to the hash table.
617     */
618 michael 2811 struct AddressRec *
619 michael 1632 add_conf_by_address(const unsigned int type, struct MaskItem *conf)
620 adx 30 {
621 michael 3001 const char *hostname = conf->host;
622     const char *username = conf->user;
623 michael 1343 static unsigned int prec_value = 0xFFFFFFFF;
624 michael 1367 int bits = 0;
625 michael 3001 struct AddressRec *arec = NULL;
626 adx 30
627 michael 3003 assert(type && !EmptyString(hostname));
628 adx 30
629 michael 3504 arec = MyCalloc(sizeof(struct AddressRec));
630 michael 3001 arec->masktype = parse_netmask(hostname, &arec->Mask.ipa.addr, &bits);
631 adx 30 arec->Mask.ipa.bits = bits;
632 michael 1367 arec->username = username;
633 michael 1632 arec->conf = conf;
634 michael 1367 arec->precedence = prec_value--;
635     arec->type = type;
636 michael 1298
637 michael 1367 switch (arec->masktype)
638     {
639     case HM_IPV4:
640     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
641     bits -= bits % 8;
642     dlinkAdd(arec, &arec->node, &atable[hash_ipv4(&arec->Mask.ipa.addr, bits)]);
643     break;
644     case HM_IPV6:
645     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
646     bits -= bits % 16;
647     dlinkAdd(arec, &arec->node, &atable[hash_ipv6(&arec->Mask.ipa.addr, bits)]);
648     break;
649     default: /* HM_HOST */
650 michael 3001 arec->Mask.hostname = hostname;
651     dlinkAdd(arec, &arec->node, &atable[get_mask_hash(hostname)]);
652 michael 1367 break;
653 adx 30 }
654 michael 2811
655     return arec;
656 adx 30 }
657    
658 michael 1632 /* void delete_one_address(const char*, struct MaskItem*)
659     * Input: An address string, the associated MaskItem.
660 adx 30 * Output: None
661 michael 1632 * Side effects: Deletes an address record. Frees the MaskItem if there
662 adx 30 * is nothing referencing it, sets it as illegal otherwise.
663     */
664     void
665 michael 1632 delete_one_address_conf(const char *address, struct MaskItem *conf)
666 adx 30 {
667 michael 1367 int bits = 0;
668     uint32_t hv = 0;
669 michael 4815 dlink_node *node = NULL;
670 adx 30 struct irc_ssaddr addr;
671 michael 1298
672 michael 1367 switch (parse_netmask(address, &addr, &bits))
673     {
674     case HM_IPV4:
675     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
676     bits -= bits % 8;
677     hv = hash_ipv4(&addr, bits);
678     break;
679     case HM_IPV6:
680     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
681     bits -= bits % 16;
682     hv = hash_ipv6(&addr, bits);
683     break;
684     default: /* HM_HOST */
685     hv = get_mask_hash(address);
686     break;
687 adx 30 }
688 michael 1298
689 michael 4815 DLINK_FOREACH(node, atable[hv].head)
690 adx 30 {
691 michael 4815 struct AddressRec *arec = node->data;
692 michael 1367
693 michael 1632 if (arec->conf == conf)
694 adx 30 {
695 michael 1367 dlinkDelete(&arec->node, &atable[hv]);
696 michael 1298
697 michael 1644 if (!conf->ref_count)
698 michael 1632 conf_free(conf);
699 michael 1298
700 adx 30 MyFree(arec);
701     return;
702     }
703     }
704     }
705    
706     /* void clear_out_address_conf(void)
707     * Input: None
708     * Output: None
709     * Side effects: Clears out all address records in the hash table,
710 michael 1632 * frees them, and frees the MaskItems if nothing references
711 michael 2916 * them, otherwise sets them as illegal.
712 adx 30 */
713     void
714     clear_out_address_conf(void)
715     {
716 michael 4815 dlink_node *node = NULL, *node_next = NULL;
717 michael 2916
718 michael 3235 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
719 adx 30 {
720 michael 4815 DLINK_FOREACH_SAFE(node, node_next, atable[i].head)
721 adx 30 {
722 michael 4815 struct AddressRec *arec = node->data;
723 michael 1367
724 michael 1628 /*
725     * We keep the temporary K-lines and destroy the permanent ones,
726     * just to be confusing :) -A1kmm
727     */
728 michael 1649 if (arec->conf->until || IsConfDatabase(arec->conf))
729 michael 1628 continue;
730 michael 1622
731 michael 1628 dlinkDelete(&arec->node, &atable[i]);
732 michael 4523 arec->conf->active = 0;
733 michael 1298
734 michael 1644 if (!arec->conf->ref_count)
735 michael 1632 conf_free(arec->conf);
736 michael 1628 MyFree(arec);
737 adx 30 }
738     }
739     }
740    
741 michael 1369 static void
742     hostmask_send_expiration(struct AddressRec *arec)
743     {
744     char ban_type = '\0';
745    
746 michael 4340 if (!ConfigGeneral.tkline_expire_notices)
747 michael 1369 return;
748    
749     switch (arec->type)
750     {
751     case CONF_KLINE:
752     ban_type = 'K';
753     break;
754     case CONF_DLINE:
755     ban_type = 'D';
756     break;
757     case CONF_GLINE:
758     ban_type = 'G';
759     break;
760 michael 1644 default: break;
761 michael 1369 }
762 michael 2916
763 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
764 michael 1369 "Temporary %c-line for [%s@%s] expired", ban_type,
765 michael 1632 (arec->conf->user) ? arec->conf->user : "*",
766     (arec->conf->host) ? arec->conf->host : "*");
767 michael 1369 }
768    
769     void
770     hostmask_expire_temporary(void)
771     {
772 michael 4815 dlink_node *node = NULL, *node_next = NULL;
773 michael 1369
774 michael 3235 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
775 michael 1369 {
776 michael 4815 DLINK_FOREACH_SAFE(node, node_next, atable[i].head)
777 michael 1369 {
778 michael 4815 struct AddressRec *arec = node->data;
779 michael 1369
780 michael 1649 if (!arec->conf->until || arec->conf->until > CurrentTime)
781 michael 1369 continue;
782    
783     switch (arec->type)
784     {
785     case CONF_KLINE:
786     case CONF_DLINE:
787     case CONF_GLINE:
788     hostmask_send_expiration(arec);
789    
790     dlinkDelete(&arec->node, &atable[i]);
791 michael 1632 conf_free(arec->conf);
792 michael 1369 MyFree(arec);
793     break;
794 michael 1644 default: break;
795 michael 1369 }
796     }
797     }
798     }

Properties

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