ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hostmask.c
Revision: 3535
Committed: Thu May 15 15:46:25 2014 UTC (11 years, 3 months ago) by michael
Content type: text/x-csrc
File size: 21012 byte(s)
Log Message:
- hostmask.c:delete_one_address_conf(): replaced a DLINK_FOREACH_SAFE with DLINK_FOREACH

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

Properties

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