ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hostmask.c
Revision: 6429
Committed: Thu Aug 27 10:44:15 2015 UTC (10 years ago) by michael
Content type: text/x-csrc
File size: 20641 byte(s)
Log Message:
- hostmask.h, hostmask.c: use const keyword where appropriate

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

Properties

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