ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hostmask.c
Revision: 7668
Committed: Wed Jul 20 17:09:49 2016 UTC (9 years, 1 month ago) by michael
Content type: text/x-csrc
File size: 20536 byte(s)
Log Message:
- Fixed svn properties

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 7006 * Copyright (c) 2001-2016 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     static int
60     try_parse_v6_netmask(const char *text, struct irc_ssaddr *addr, int *b)
61     {
62     char c;
63     int d[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
64     int dp = 0;
65     int nyble = 4;
66     int finsert = -1;
67     int bits = 128;
68     int deficit = 0;
69     short dc[8];
70 michael 4874 struct sockaddr_in6 *const v6 = (struct sockaddr_in6 *)addr;
71 adx 30
72 michael 3469 for (const char *p = text; (c = *p); ++p)
73 michael 2894 {
74 adx 30 if (IsXDigit(c))
75     {
76     if (nyble == 0)
77     return HM_HOST;
78     DigitParse(c);
79     d[dp] |= c << (4 * --nyble);
80     }
81     else if (c == ':')
82     {
83     if (p > text && *(p - 1) == ':')
84     {
85     if (finsert >= 0)
86     return HM_HOST;
87     finsert = dp;
88     }
89     else
90     {
91 michael 6580 /*
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     */
95 adx 30 d[dp] = d[dp] >> 4 * nyble;
96     nyble = 4;
97 michael 6580
98 adx 30 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 michael 3215 ++dp;
115 adx 30 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 michael 3215 ++dp;
131 adx 30 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 michael 3215 for (dp = 0, nyble = 0; dp < 8; ++dp)
139 adx 30 {
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 michael 3215 for (dp = bits / 16 + (bits % 16 ? 1 : 0); dp < 8; ++dp)
153 adx 30 dc[dp] = 0;
154 michael 1298
155 adx 30 /* And assign... -A1kmm */
156     if (addr)
157 michael 3215 for (dp = 0; dp < 8; ++dp)
158 adx 30 /* The cast is a kludge to make netbsd work. */
159     ((unsigned short *)&v6->sin6_addr)[dp] = htons(dc[dp]);
160 michael 1298
161 michael 3215 if (b)
162 adx 30 *b = bits;
163     return HM_IPV6;
164     }
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 4874 struct sockaddr_in *const 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 michael 5976 if (*(p + 1) || n == 1 || *(p - 1) != '.')
198 adx 30 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 michael 1298 if (strchr(text, ':'))
257 adx 30 return try_parse_v6_netmask(text, addr, b);
258 michael 4415
259 adx 30 return HM_HOST;
260     }
261    
262     /* The address matching stuff... */
263     /* int match_ipv6(struct irc_ssaddr *, struct irc_ssaddr *, int)
264     * Input: An IP address, an IP mask, the number of bits in the mask.
265     * Output: if match, -1 else 0
266     * Side effects: None
267     */
268     int
269 michael 1455 match_ipv6(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
270 adx 30 {
271     int i, m, n = bits / 8;
272 michael 4977 const struct sockaddr_in6 *const v6 = (const struct sockaddr_in6 *)addr;
273     const struct sockaddr_in6 *const v6mask = (const struct sockaddr_in6 *)mask;
274 adx 30
275 michael 3215 for (i = 0; i < n; ++i)
276 adx 30 if (v6->sin6_addr.s6_addr[i] != v6mask->sin6_addr.s6_addr[i])
277     return 0;
278 michael 3215
279 adx 30 if ((m = bits % 8) == 0)
280     return -1;
281     if ((v6->sin6_addr.s6_addr[n] & ~((1 << (8 - m)) - 1)) ==
282     v6mask->sin6_addr.s6_addr[n])
283     return -1;
284     return 0;
285     }
286 michael 1372
287 adx 30 /* int match_ipv4(struct irc_ssaddr *, struct irc_ssaddr *, int)
288     * Input: An IP address, an IP mask, the number of bits in the mask.
289     * Output: if match, -1 else 0
290     * Side Effects: None
291     */
292     int
293 michael 1455 match_ipv4(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
294 adx 30 {
295 michael 4977 const struct sockaddr_in *const v4 = (const struct sockaddr_in *)addr;
296     const struct sockaddr_in *const v4mask = (const struct sockaddr_in *)mask;
297 michael 1298
298 adx 30 if ((ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1)) !=
299     ntohl(v4mask->sin_addr.s_addr))
300     return 0;
301     return -1;
302     }
303    
304     /*
305     * mask_addr
306     *
307     * inputs - pointer to the ip to mask
308     * - bitlen
309     * output - NONE
310     * side effects -
311     */
312     void
313     mask_addr(struct irc_ssaddr *ip, int bits)
314     {
315     int mask;
316     struct sockaddr_in6 *v6_base_ip;
317     int i, m, n;
318     struct sockaddr_in *v4_base_ip;
319    
320 michael 4415 if (ip->ss.ss_family == AF_INET)
321 adx 30 {
322 michael 3770 uint32_t tmp = 0;
323 michael 1298 v4_base_ip = (struct sockaddr_in *)ip;
324    
325 adx 30 mask = ~((1 << (32 - bits)) - 1);
326 michael 3770 tmp = ntohl(v4_base_ip->sin_addr.s_addr);
327     v4_base_ip->sin_addr.s_addr = htonl(tmp & mask);
328 adx 30 }
329     else
330     {
331     n = bits / 8;
332     m = bits % 8;
333 michael 1298 v6_base_ip = (struct sockaddr_in6 *)ip;
334 adx 30
335 michael 4915 mask = ~((1 << (8 - m)) - 1);
336 adx 30 v6_base_ip->sin6_addr.s6_addr[n] = v6_base_ip->sin6_addr.s6_addr[n] & mask;
337 michael 1298
338 db 300 for (i = n + 1; i < 16; i++)
339     v6_base_ip->sin6_addr.s6_addr[i] = 0;
340 adx 30 }
341     }
342    
343     /* unsigned long hash_ipv4(struct irc_ssaddr*)
344     * Input: An IP address.
345     * Output: A hash value of the IP address.
346     * Side effects: None
347     */
348 michael 1343 static uint32_t
349 michael 2898 hash_ipv4(const struct irc_ssaddr *addr, int bits)
350 adx 30 {
351     if (bits != 0)
352     {
353 michael 4874 const struct sockaddr_in *const v4 = (const struct sockaddr_in *)addr;
354 michael 1343 uint32_t av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
355 michael 1298
356     return (av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1);
357 adx 30 }
358    
359 michael 1298 return 0;
360 adx 30 }
361    
362     /* unsigned long hash_ipv6(struct irc_ssaddr*)
363     * Input: An IP address.
364     * Output: A hash value of the IP address.
365     * Side effects: None
366     */
367 michael 1343 static uint32_t
368 michael 2898 hash_ipv6(const struct irc_ssaddr *addr, int bits)
369 adx 30 {
370 michael 1343 uint32_t v = 0, n;
371 michael 4874 const struct sockaddr_in6 *const v6 = (const struct sockaddr_in6 *)addr;
372 michael 1298
373 michael 3215 for (n = 0; n < 16; ++n)
374 adx 30 {
375     if (bits >= 8)
376     {
377     v ^= v6->sin6_addr.s6_addr[n];
378     bits -= 8;
379     }
380     else if (bits)
381     {
382     v ^= v6->sin6_addr.s6_addr[n] & ~((1 << (8 - bits)) - 1);
383     return v & (ATABLE_SIZE - 1);
384     }
385     else
386     return v & (ATABLE_SIZE - 1);
387     }
388 michael 4415
389 adx 30 return v & (ATABLE_SIZE - 1);
390     }
391    
392     /* int hash_text(const char *start)
393     * Input: The start of the text to hash.
394     * Output: The hash of the string between 1 and (TH_MAX-1)
395     * Side-effects: None.
396     */
397 michael 1343 static uint32_t
398 adx 30 hash_text(const char *start)
399     {
400 michael 1343 uint32_t h = 0;
401 adx 30
402 michael 3469 for (const char *p = start; *p; ++p)
403 michael 2331 h = (h << 4) - (h + ToLower(*p));
404 michael 1298
405     return h & (ATABLE_SIZE - 1);
406 adx 30 }
407    
408     /* unsigned long get_hash_mask(const char *)
409     * Input: The text to hash.
410     * Output: The hash of the string right of the first '.' past the last
411     * wildcard in the string.
412     * Side-effects: None.
413     */
414 michael 1343 static uint32_t
415 adx 30 get_mask_hash(const char *text)
416     {
417     const char *hp = "", *p;
418    
419 michael 3215 for (p = text + strlen(text) - 1; p >= text; --p)
420 adx 723 if (IsMWildChar(*p))
421 adx 30 return hash_text(hp);
422     else if (*p == '.')
423     hp = p + 1;
424     return hash_text(text);
425     }
426    
427 michael 1632 /* struct MaskItem *find_conf_by_address(const char *, struct irc_ssaddr *,
428 adx 30 * int type, int fam, const char *username)
429     * Input: The hostname, the address, the type of mask to find, the address
430     * family, the username.
431     * Output: The matching value with the highest precedence.
432     * Side-effects: None
433     * Note: Setting bit 0 of the type means that the username is ignored.
434     * Warning: IsNeedPassword for everything that is not an auth{} entry
435 michael 1632 * should always be true (i.e. conf->flags & CONF_FLAGS_NEED_PASSWORD == 0)
436 adx 30 */
437 michael 1632 struct MaskItem *
438 michael 5850 find_conf_by_address(const char *name, const struct irc_ssaddr *addr, unsigned int type,
439 michael 1371 int fam, const char *username, const char *password, int do_match)
440 adx 30 {
441 michael 1343 unsigned int hprecv = 0;
442 michael 4815 dlink_node *node = NULL;
443 michael 1632 struct MaskItem *hprec = NULL;
444     struct AddressRec *arec = NULL;
445 adx 30 int b;
446 michael 1371 int (*cmpfunc)(const char *, const char *) = do_match ? match : irccmp;
447 adx 30
448     if (addr)
449     {
450     /* Check for IPV6 matches... */
451     if (fam == AF_INET6)
452     {
453     for (b = 128; b >= 0; b -= 16)
454     {
455 michael 4815 DLINK_FOREACH(node, atable[hash_ipv6(addr, b)].head)
456 michael 1367 {
457 michael 4815 arec = node->data;
458 michael 1367
459 michael 2995 if ((arec->type == type) &&
460 adx 30 arec->precedence > hprecv &&
461     arec->masktype == HM_IPV6 &&
462     match_ipv6(addr, &arec->Mask.ipa.addr,
463     arec->Mask.ipa.bits) &&
464 michael 2995 (!username || !cmpfunc(arec->username, username)) &&
465 michael 2916 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
466     match_conf_password(password, arec->conf)))
467 adx 30 {
468     hprecv = arec->precedence;
469 michael 1632 hprec = arec->conf;
470 adx 30 }
471 michael 1367 }
472 adx 30 }
473     }
474 michael 4415 else if (fam == AF_INET)
475 adx 30 {
476     for (b = 32; b >= 0; b -= 8)
477     {
478 michael 4815 DLINK_FOREACH(node, atable[hash_ipv4(addr, b)].head)
479 michael 1367 {
480 michael 4815 arec = node->data;
481 michael 1367
482 michael 2995 if ((arec->type == type) &&
483 adx 30 arec->precedence > hprecv &&
484     arec->masktype == HM_IPV4 &&
485     match_ipv4(addr, &arec->Mask.ipa.addr,
486     arec->Mask.ipa.bits) &&
487 michael 2995 (!username || !cmpfunc(arec->username, username)) &&
488 michael 2916 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
489     match_conf_password(password, arec->conf)))
490 adx 30 {
491     hprecv = arec->precedence;
492 michael 1632 hprec = arec->conf;
493 adx 30 }
494 michael 1367 }
495 adx 30 }
496     }
497     }
498    
499 michael 3215 if (name)
500 adx 30 {
501     const char *p = name;
502    
503     while (1)
504     {
505 michael 4815 DLINK_FOREACH(node, atable[hash_text(p)].head)
506 michael 1367 {
507 michael 4815 arec = node->data;
508 michael 2995 if ((arec->type == type) &&
509 adx 30 arec->precedence > hprecv &&
510     (arec->masktype == HM_HOST) &&
511 michael 1652 !cmpfunc(arec->Mask.hostname, name) &&
512 michael 2995 (!username || !cmpfunc(arec->username, username)) &&
513 michael 1632 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
514     match_conf_password(password, arec->conf)))
515 adx 30 {
516     hprecv = arec->precedence;
517 michael 1632 hprec = arec->conf;
518 adx 30 }
519 michael 1367 }
520 michael 3215
521     if ((p = strchr(p, '.')) == NULL)
522 adx 30 break;
523 michael 3215 ++p;
524 adx 30 }
525 michael 1367
526 michael 4815 DLINK_FOREACH(node, atable[0].head)
527 michael 1367 {
528 michael 4815 arec = node->data;
529 michael 1367
530 michael 2995 if (arec->type == type &&
531 adx 30 arec->precedence > hprecv &&
532     arec->masktype == HM_HOST &&
533 michael 1652 !cmpfunc(arec->Mask.hostname, name) &&
534 michael 2995 (!username || !cmpfunc(arec->username, username)) &&
535 michael 1632 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
536     match_conf_password(password, arec->conf)))
537 adx 30 {
538     hprecv = arec->precedence;
539 michael 1632 hprec = arec->conf;
540 adx 30 }
541 michael 1367 }
542 adx 30 }
543    
544     return hprec;
545     }
546    
547 michael 1632 /* struct MaskItem* find_address_conf(const char*, const char*,
548 adx 30 * struct irc_ssaddr*, int, char *);
549     * Input: The hostname, username, address, address family.
550 michael 1632 * Output: The applicable MaskItem.
551 adx 30 * Side-effects: None
552     */
553 michael 1632 struct MaskItem *
554 michael 6429 find_address_conf(const char *host, const char *user, const struct irc_ssaddr *ip,
555 michael 3553 int aftype, const char *password)
556 adx 30 {
557 michael 1632 struct MaskItem *authcnf = NULL, *killcnf = NULL;
558 adx 30
559 michael 1426 /* Find the best auth{} block... If none, return NULL -A1kmm */
560 michael 1632 if ((authcnf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
561     password, 1)) == NULL)
562 michael 1298 return NULL;
563 adx 30
564 michael 1426 /* If they are exempt from K-lines, return the best auth{} block. -A1kmm */
565 michael 1632 if (IsConfExemptKline(authcnf))
566     return authcnf;
567 adx 30
568     /* Find the best K-line... -A1kmm */
569 michael 1632 killcnf = find_conf_by_address(host, ip, CONF_KLINE, aftype, user, NULL, 1);
570 adx 30
571 michael 1426 /*
572     * If they are K-lined, return the K-line. Otherwise, return the
573 michael 5805 * auth {} block. -A1kmm
574 michael 1426 */
575 michael 6411 if (killcnf)
576 michael 1632 return killcnf;
577 adx 30
578 michael 1632 return authcnf;
579 adx 30 }
580    
581 michael 1632 /* struct MaskItem* find_dline_conf(struct irc_ssaddr*, int)
582 adx 30 *
583     * Input: An address, an address family.
584     * Output: The best matching D-line or exempt line.
585     * Side effects: None.
586     */
587 michael 1632 struct MaskItem *
588 michael 6429 find_dline_conf(const struct irc_ssaddr *addr, int aftype)
589 adx 30 {
590 michael 1632 struct MaskItem *eline;
591 adx 30
592 michael 2995 eline = find_conf_by_address(NULL, addr, CONF_EXEMPT, aftype, NULL, NULL, 1);
593 michael 3215 if (eline)
594 michael 1298 return eline;
595    
596 michael 6411 return find_conf_by_address(NULL, addr, CONF_DLINE, aftype, NULL, NULL, 1);
597 adx 30 }
598    
599 michael 1632 /* void add_conf_by_address(int, struct MaskItem *aconf)
600 michael 2916 * Input:
601 adx 30 * Output: None
602     * Side-effects: Adds this entry to the hash table.
603     */
604 michael 2811 struct AddressRec *
605 michael 1632 add_conf_by_address(const unsigned int type, struct MaskItem *conf)
606 adx 30 {
607 michael 4977 struct AddressRec *arec = NULL;
608     const char *const hostname = conf->host;
609     const char *const username = conf->user;
610 michael 6868 static unsigned int prec_value = UINT_MAX;
611 michael 1367 int bits = 0;
612 adx 30
613 michael 3003 assert(type && !EmptyString(hostname));
614 adx 30
615 michael 7032 arec = xcalloc(sizeof(struct AddressRec));
616 michael 3001 arec->masktype = parse_netmask(hostname, &arec->Mask.ipa.addr, &bits);
617 adx 30 arec->Mask.ipa.bits = bits;
618 michael 1367 arec->username = username;
619 michael 1632 arec->conf = conf;
620 michael 1367 arec->precedence = prec_value--;
621     arec->type = type;
622 michael 1298
623 michael 1367 switch (arec->masktype)
624     {
625     case HM_IPV4:
626     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
627     bits -= bits % 8;
628     dlinkAdd(arec, &arec->node, &atable[hash_ipv4(&arec->Mask.ipa.addr, bits)]);
629     break;
630     case HM_IPV6:
631     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
632     bits -= bits % 16;
633     dlinkAdd(arec, &arec->node, &atable[hash_ipv6(&arec->Mask.ipa.addr, bits)]);
634     break;
635     default: /* HM_HOST */
636 michael 3001 arec->Mask.hostname = hostname;
637     dlinkAdd(arec, &arec->node, &atable[get_mask_hash(hostname)]);
638 michael 1367 break;
639 adx 30 }
640 michael 2811
641     return arec;
642 adx 30 }
643    
644 michael 1632 /* void delete_one_address(const char*, struct MaskItem*)
645     * Input: An address string, the associated MaskItem.
646 adx 30 * Output: None
647 michael 1632 * Side effects: Deletes an address record. Frees the MaskItem if there
648 adx 30 * is nothing referencing it, sets it as illegal otherwise.
649     */
650     void
651 michael 1632 delete_one_address_conf(const char *address, struct MaskItem *conf)
652 adx 30 {
653 michael 1367 int bits = 0;
654     uint32_t hv = 0;
655 michael 4815 dlink_node *node = NULL;
656 adx 30 struct irc_ssaddr addr;
657 michael 1298
658 michael 1367 switch (parse_netmask(address, &addr, &bits))
659     {
660     case HM_IPV4:
661     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
662     bits -= bits % 8;
663     hv = hash_ipv4(&addr, bits);
664     break;
665     case HM_IPV6:
666     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
667     bits -= bits % 16;
668     hv = hash_ipv6(&addr, bits);
669     break;
670     default: /* HM_HOST */
671     hv = get_mask_hash(address);
672     break;
673 adx 30 }
674 michael 1298
675 michael 4815 DLINK_FOREACH(node, atable[hv].head)
676 adx 30 {
677 michael 4815 struct AddressRec *arec = node->data;
678 michael 1367
679 michael 1632 if (arec->conf == conf)
680 adx 30 {
681 michael 1367 dlinkDelete(&arec->node, &atable[hv]);
682 michael 1298
683 michael 1644 if (!conf->ref_count)
684 michael 1632 conf_free(conf);
685 michael 1298
686 michael 7032 xfree(arec);
687 adx 30 return;
688     }
689     }
690     }
691    
692     /* void clear_out_address_conf(void)
693     * Input: None
694     * Output: None
695     * Side effects: Clears out all address records in the hash table,
696 michael 1632 * frees them, and frees the MaskItems if nothing references
697 michael 2916 * them, otherwise sets them as illegal.
698 adx 30 */
699     void
700     clear_out_address_conf(void)
701     {
702 michael 4815 dlink_node *node = NULL, *node_next = NULL;
703 michael 2916
704 michael 3235 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
705 adx 30 {
706 michael 4815 DLINK_FOREACH_SAFE(node, node_next, atable[i].head)
707 adx 30 {
708 michael 4815 struct AddressRec *arec = node->data;
709 michael 1367
710 michael 1628 /*
711 michael 5846 * Destroy the ircd.conf items and keep those that are in the databases
712 michael 1628 */
713 michael 5846 if (IsConfDatabase(arec->conf))
714 michael 1628 continue;
715 michael 1622
716 michael 1628 dlinkDelete(&arec->node, &atable[i]);
717 michael 4523 arec->conf->active = 0;
718 michael 1298
719 michael 1644 if (!arec->conf->ref_count)
720 michael 1632 conf_free(arec->conf);
721 michael 7032 xfree(arec);
722 adx 30 }
723     }
724     }
725    
726 michael 1369 static void
727 michael 4977 hostmask_send_expiration(const struct AddressRec *const arec)
728 michael 1369 {
729 michael 6991 char ban_type = '?';
730 michael 1369
731 michael 4340 if (!ConfigGeneral.tkline_expire_notices)
732 michael 1369 return;
733    
734     switch (arec->type)
735     {
736     case CONF_KLINE:
737     ban_type = 'K';
738     break;
739     case CONF_DLINE:
740     ban_type = 'D';
741     break;
742 michael 1644 default: break;
743 michael 1369 }
744 michael 2916
745 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
746 michael 1369 "Temporary %c-line for [%s@%s] expired", ban_type,
747 michael 1632 (arec->conf->user) ? arec->conf->user : "*",
748     (arec->conf->host) ? arec->conf->host : "*");
749 michael 1369 }
750    
751     void
752     hostmask_expire_temporary(void)
753     {
754 michael 4815 dlink_node *node = NULL, *node_next = NULL;
755 michael 1369
756 michael 3235 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
757 michael 1369 {
758 michael 4815 DLINK_FOREACH_SAFE(node, node_next, atable[i].head)
759 michael 1369 {
760 michael 4815 struct AddressRec *arec = node->data;
761 michael 1369
762 michael 1649 if (!arec->conf->until || arec->conf->until > CurrentTime)
763 michael 1369 continue;
764    
765     switch (arec->type)
766     {
767     case CONF_KLINE:
768     case CONF_DLINE:
769     hostmask_send_expiration(arec);
770    
771     dlinkDelete(&arec->node, &atable[i]);
772 michael 1632 conf_free(arec->conf);
773 michael 7032 xfree(arec);
774 michael 1369 break;
775 michael 1644 default: break;
776 michael 1369 }
777     }
778     }
779     }

Properties

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