ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hostmask.c
Revision: 9596
Committed: Fri Sep 4 16:51:08 2020 UTC (4 years, 11 months ago) by michael
Content type: text/x-csrc
File size: 20958 byte(s)
Log Message:
- Cleanup ip address matching routine in various places

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 9101 * Copyright (c) 2001-2020 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 8664 } while (false);
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 michael 9030 uint16_t 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     bits = strtoul(p + 1, &after, 10);
114 michael 1298
115 michael 9027 if (bits < 0 || bits > 128 || *after)
116 adx 30 return HM_HOST;
117 michael 9027 /* 16 bits for each hextet, plus 4 for each parsed nyble */
118     if (bits > dp * 16 + (4 - nyble) * 4 && !(finsert >= 0))
119 adx 30 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 7791 {
157     v6->sin6_family = AF_INET6;
158    
159 michael 3215 for (dp = 0; dp < 8; ++dp)
160 adx 30 /* The cast is a kludge to make netbsd work. */
161 michael 9030 ((uint16_t *)&v6->sin6_addr)[dp] = htons(dc[dp]);
162 michael 7791 }
163 michael 1298
164 michael 3215 if (b)
165 adx 30 *b = bits;
166     return HM_IPV6;
167     }
168    
169     /* int try_parse_v4_netmask(const char *, struct irc_ssaddr *, int *);
170     * Input: A possible IPV4 address as a string.
171     * Output: An integer describing whether it is an IPV4 or hostmask,
172     * an address(if it is IPV4), a bitlength(if it is IPV4).
173     * Side effects: None
174     * Comments: Called from parse_netmask
175     */
176     static int
177     try_parse_v4_netmask(const char *text, struct irc_ssaddr *addr, int *b)
178     {
179     const char *digits[4];
180 michael 9046 uint8_t addb[4];
181 adx 30 int n = 0, bits = 0;
182     char c;
183 michael 4874 struct sockaddr_in *const v4 = (struct sockaddr_in *)addr;
184 adx 30
185     digits[n++] = text;
186    
187 michael 3469 for (const char *p = text; (c = *p); ++p)
188 michael 2894 {
189 adx 30 if (c >= '0' && c <= '9') /* empty */
190     ;
191     else if (c == '.')
192     {
193     if (n >= 4)
194     return HM_HOST;
195 michael 1298
196 adx 30 digits[n++] = p + 1;
197     }
198     else if (c == '*')
199     {
200 michael 5976 if (*(p + 1) || n == 1 || *(p - 1) != '.')
201 adx 30 return HM_HOST;
202 michael 1298
203 adx 30 bits = (n - 1) * 8;
204     break;
205     }
206     else if (c == '/')
207     {
208     char *after;
209     bits = strtoul(p + 1, &after, 10);
210 michael 1298
211 michael 1786 if (bits < 0 || *after)
212 adx 30 return HM_HOST;
213     if (bits > n * 8)
214     return HM_HOST;
215 michael 1298
216 adx 30 break;
217     }
218     else
219     return HM_HOST;
220 michael 2894 }
221 adx 30
222     if (n < 4 && bits == 0)
223     bits = n * 8;
224     if (bits)
225     while (n < 4)
226     digits[n++] = "0";
227 michael 1298
228 michael 3215 for (n = 0; n < 4; ++n)
229 adx 30 addb[n] = strtoul(digits[n], NULL, 10);
230 michael 1298
231 adx 30 if (bits == 0)
232     bits = 32;
233 michael 1298
234 adx 30 /* Set unused bits to 0... -A1kmm */
235     if (bits < 32 && bits % 8)
236     addb[bits / 8] &= ~((1 << (8 - bits % 8)) - 1);
237 michael 3215 for (n = bits / 8 + (bits % 8 ? 1 : 0); n < 4; ++n)
238 adx 30 addb[n] = 0;
239     if (addr)
240 michael 7791 {
241     v4->sin_family = AF_INET;
242 adx 30 v4->sin_addr.s_addr =
243 michael 9016 htonl((unsigned int)addb[0] << 24 |
244     (unsigned int)addb[1] << 16 |
245     (unsigned int)addb[2] << 8 |
246     (unsigned int)addb[3]);
247 michael 7791 }
248    
249 michael 3215 if (b)
250 adx 30 *b = bits;
251     return HM_IPV4;
252     }
253    
254     /* int parse_netmask(const char *, struct irc_ssaddr *, int *);
255     * Input: A hostmask, or an IPV4/6 address.
256     * Output: An integer describing whether it is an IPV4, IPV6 address or a
257     * hostmask, an address(if it is an IP mask),
258     * a bitlength(if it is IP mask).
259     * Side effects: None
260     */
261     int
262     parse_netmask(const char *text, struct irc_ssaddr *addr, int *b)
263     {
264 michael 7791 if (addr)
265 michael 8310 memset(addr, 0, sizeof(*addr));
266 michael 7791
267 michael 2814 if (strchr(text, '.'))
268     return try_parse_v4_netmask(text, addr, b);
269 michael 1298 if (strchr(text, ':'))
270 adx 30 return try_parse_v6_netmask(text, addr, b);
271 michael 4415
272 adx 30 return HM_HOST;
273     }
274    
275 michael 9596 bool
276     address_compare(const void *p1, const void *p2, bool exact, bool port, int bits)
277     {
278     const struct irc_ssaddr *const addr = p1;
279     const struct irc_ssaddr *const mask = p2;
280    
281     if (addr->ss.ss_family != mask->ss.ss_family)
282     return false;
283    
284     if (addr->ss.ss_family == AF_INET)
285     {
286     const struct sockaddr_in *const sin1 = (const struct sockaddr_in *)addr;
287     const struct sockaddr_in *const sin2 = (const struct sockaddr_in *)mask;
288    
289     if (port == true && (sin1->sin_port != sin2->sin_port))
290     return false;
291     if (exact == true)
292     return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
293     return match_ipv4(addr, mask, bits);
294     }
295     else if (addr->ss.ss_family == AF_INET6)
296     {
297     const struct sockaddr_in6 *const sin1 = (const struct sockaddr_in6 *)addr;
298     const struct sockaddr_in6 *const sin2 = (const struct sockaddr_in6 *)mask;
299    
300     if (port == true && (sin1->sin6_port != sin2->sin6_port))
301     return false;
302    
303     if (exact == true)
304     return memcmp(sin1->sin6_addr.s6_addr,
305     sin2->sin6_addr.s6_addr, sizeof(struct in6_addr)) == 0;
306     return match_ipv6(addr, mask, bits);
307     }
308    
309     return false;
310     }
311    
312 adx 30 /* The address matching stuff... */
313     /* int match_ipv6(struct irc_ssaddr *, struct irc_ssaddr *, int)
314     * Input: An IP address, an IP mask, the number of bits in the mask.
315     * Output: if match, -1 else 0
316     * Side effects: None
317     */
318 michael 8688 bool
319 michael 1455 match_ipv6(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
320 adx 30 {
321     int i, m, n = bits / 8;
322 michael 4977 const struct sockaddr_in6 *const v6 = (const struct sockaddr_in6 *)addr;
323     const struct sockaddr_in6 *const v6mask = (const struct sockaddr_in6 *)mask;
324 adx 30
325 michael 3215 for (i = 0; i < n; ++i)
326 adx 30 if (v6->sin6_addr.s6_addr[i] != v6mask->sin6_addr.s6_addr[i])
327 michael 8688 return false;
328 michael 3215
329 adx 30 if ((m = bits % 8) == 0)
330 michael 8688 return true;
331 adx 30 if ((v6->sin6_addr.s6_addr[n] & ~((1 << (8 - m)) - 1)) ==
332     v6mask->sin6_addr.s6_addr[n])
333 michael 8688 return true;
334     return false;
335 adx 30 }
336 michael 1372
337 adx 30 /* int match_ipv4(struct irc_ssaddr *, struct irc_ssaddr *, int)
338     * Input: An IP address, an IP mask, the number of bits in the mask.
339     * Output: if match, -1 else 0
340     * Side Effects: None
341     */
342 michael 8688 bool
343 michael 1455 match_ipv4(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
344 adx 30 {
345 michael 4977 const struct sockaddr_in *const v4 = (const struct sockaddr_in *)addr;
346     const struct sockaddr_in *const v4mask = (const struct sockaddr_in *)mask;
347 michael 1298
348 michael 8688 if ((ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1)) ==
349 adx 30 ntohl(v4mask->sin_addr.s_addr))
350 michael 8688 return true;
351     return false;
352 adx 30 }
353    
354     /* unsigned long hash_ipv4(struct irc_ssaddr*)
355     * Input: An IP address.
356     * Output: A hash value of the IP address.
357     * Side effects: None
358     */
359 michael 1343 static uint32_t
360 michael 2898 hash_ipv4(const struct irc_ssaddr *addr, int bits)
361 adx 30 {
362 michael 8437 if (bits)
363 adx 30 {
364 michael 4874 const struct sockaddr_in *const v4 = (const struct sockaddr_in *)addr;
365 michael 1343 uint32_t av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
366 michael 1298
367     return (av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1);
368 adx 30 }
369    
370 michael 1298 return 0;
371 adx 30 }
372    
373     /* unsigned long hash_ipv6(struct irc_ssaddr*)
374     * Input: An IP address.
375     * Output: A hash value of the IP address.
376     * Side effects: None
377     */
378 michael 1343 static uint32_t
379 michael 2898 hash_ipv6(const struct irc_ssaddr *addr, int bits)
380 adx 30 {
381 michael 1343 uint32_t v = 0, n;
382 michael 4874 const struct sockaddr_in6 *const v6 = (const struct sockaddr_in6 *)addr;
383 michael 1298
384 michael 3215 for (n = 0; n < 16; ++n)
385 adx 30 {
386     if (bits >= 8)
387     {
388     v ^= v6->sin6_addr.s6_addr[n];
389     bits -= 8;
390     }
391     else if (bits)
392     {
393     v ^= v6->sin6_addr.s6_addr[n] & ~((1 << (8 - bits)) - 1);
394     return v & (ATABLE_SIZE - 1);
395     }
396     else
397     return v & (ATABLE_SIZE - 1);
398     }
399 michael 4415
400 adx 30 return v & (ATABLE_SIZE - 1);
401     }
402    
403     /* int hash_text(const char *start)
404     * Input: The start of the text to hash.
405     * Output: The hash of the string between 1 and (TH_MAX-1)
406     * Side-effects: None.
407     */
408 michael 1343 static uint32_t
409 adx 30 hash_text(const char *start)
410     {
411 michael 1343 uint32_t h = 0;
412 adx 30
413 michael 3469 for (const char *p = start; *p; ++p)
414 michael 2331 h = (h << 4) - (h + ToLower(*p));
415 michael 1298
416     return h & (ATABLE_SIZE - 1);
417 adx 30 }
418    
419     /* unsigned long get_hash_mask(const char *)
420     * Input: The text to hash.
421     * Output: The hash of the string right of the first '.' past the last
422     * wildcard in the string.
423     * Side-effects: None.
424     */
425 michael 1343 static uint32_t
426 adx 30 get_mask_hash(const char *text)
427     {
428     const char *hp = "", *p;
429    
430 michael 3215 for (p = text + strlen(text) - 1; p >= text; --p)
431 adx 723 if (IsMWildChar(*p))
432 adx 30 return hash_text(hp);
433     else if (*p == '.')
434     hp = p + 1;
435     return hash_text(text);
436     }
437    
438 michael 1632 /* struct MaskItem *find_conf_by_address(const char *, struct irc_ssaddr *,
439 adx 30 * int type, int fam, const char *username)
440     * Input: The hostname, the address, the type of mask to find, the address
441     * family, the username.
442     * Output: The matching value with the highest precedence.
443     * Side-effects: None
444     * Note: Setting bit 0 of the type means that the username is ignored.
445     * Warning: IsNeedPassword for everything that is not an auth{} entry
446 michael 1632 * should always be true (i.e. conf->flags & CONF_FLAGS_NEED_PASSWORD == 0)
447 adx 30 */
448 michael 1632 struct MaskItem *
449 michael 5850 find_conf_by_address(const char *name, const struct irc_ssaddr *addr, unsigned int type,
450 michael 8829 const char *username, const char *password, int do_match)
451 adx 30 {
452 michael 1343 unsigned int hprecv = 0;
453 michael 7914 dlink_node *node;
454 michael 1632 struct MaskItem *hprec = NULL;
455     struct AddressRec *arec = NULL;
456 michael 1371 int (*cmpfunc)(const char *, const char *) = do_match ? match : irccmp;
457 adx 30
458     if (addr)
459     {
460     /* Check for IPV6 matches... */
461 michael 8829 if (addr->ss.ss_family == AF_INET6)
462 adx 30 {
463 michael 7797 for (int b = 128; b >= 0; b -= 16)
464 adx 30 {
465 michael 4815 DLINK_FOREACH(node, atable[hash_ipv6(addr, b)].head)
466 michael 1367 {
467 michael 4815 arec = node->data;
468 michael 1367
469 michael 2995 if ((arec->type == type) &&
470 adx 30 arec->precedence > hprecv &&
471     arec->masktype == HM_IPV6 &&
472     match_ipv6(addr, &arec->Mask.ipa.addr,
473     arec->Mask.ipa.bits) &&
474 michael 2995 (!username || !cmpfunc(arec->username, username)) &&
475 michael 2916 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
476     match_conf_password(password, arec->conf)))
477 adx 30 {
478     hprecv = arec->precedence;
479 michael 1632 hprec = arec->conf;
480 adx 30 }
481 michael 1367 }
482 adx 30 }
483     }
484 michael 8829 else if (addr->ss.ss_family == AF_INET)
485 adx 30 {
486 michael 7797 for (int b = 32; b >= 0; b -= 8)
487 adx 30 {
488 michael 4815 DLINK_FOREACH(node, atable[hash_ipv4(addr, b)].head)
489 michael 1367 {
490 michael 4815 arec = node->data;
491 michael 1367
492 michael 2995 if ((arec->type == type) &&
493 adx 30 arec->precedence > hprecv &&
494     arec->masktype == HM_IPV4 &&
495     match_ipv4(addr, &arec->Mask.ipa.addr,
496     arec->Mask.ipa.bits) &&
497 michael 2995 (!username || !cmpfunc(arec->username, username)) &&
498 michael 2916 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
499     match_conf_password(password, arec->conf)))
500 adx 30 {
501     hprecv = arec->precedence;
502 michael 1632 hprec = arec->conf;
503 adx 30 }
504 michael 1367 }
505 adx 30 }
506     }
507     }
508    
509 michael 3215 if (name)
510 adx 30 {
511     const char *p = name;
512    
513 michael 8664 while (true)
514 adx 30 {
515 michael 4815 DLINK_FOREACH(node, atable[hash_text(p)].head)
516 michael 1367 {
517 michael 4815 arec = node->data;
518 michael 2995 if ((arec->type == type) &&
519 adx 30 arec->precedence > hprecv &&
520     (arec->masktype == HM_HOST) &&
521 michael 1652 !cmpfunc(arec->Mask.hostname, name) &&
522 michael 2995 (!username || !cmpfunc(arec->username, username)) &&
523 michael 1632 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
524     match_conf_password(password, arec->conf)))
525 adx 30 {
526     hprecv = arec->precedence;
527 michael 1632 hprec = arec->conf;
528 adx 30 }
529 michael 1367 }
530 michael 3215
531     if ((p = strchr(p, '.')) == NULL)
532 adx 30 break;
533 michael 3215 ++p;
534 adx 30 }
535 michael 1367
536 michael 4815 DLINK_FOREACH(node, atable[0].head)
537 michael 1367 {
538 michael 4815 arec = node->data;
539 michael 1367
540 michael 2995 if (arec->type == type &&
541 adx 30 arec->precedence > hprecv &&
542     arec->masktype == HM_HOST &&
543 michael 1652 !cmpfunc(arec->Mask.hostname, name) &&
544 michael 2995 (!username || !cmpfunc(arec->username, username)) &&
545 michael 1632 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
546     match_conf_password(password, arec->conf)))
547 adx 30 {
548     hprecv = arec->precedence;
549 michael 1632 hprec = arec->conf;
550 adx 30 }
551 michael 1367 }
552 adx 30 }
553    
554     return hprec;
555     }
556    
557 michael 1632 /* struct MaskItem* find_address_conf(const char*, const char*,
558 adx 30 * struct irc_ssaddr*, int, char *);
559     * Input: The hostname, username, address, address family.
560 michael 1632 * Output: The applicable MaskItem.
561 adx 30 * Side-effects: None
562     */
563 michael 1632 struct MaskItem *
564 michael 8829 find_address_conf(const char *host, const char *user, const struct irc_ssaddr *addr, const char *password)
565 adx 30 {
566 michael 1632 struct MaskItem *authcnf = NULL, *killcnf = NULL;
567 adx 30
568 michael 1426 /* Find the best auth{} block... If none, return NULL -A1kmm */
569 michael 8829 if ((authcnf = find_conf_by_address(host, addr, CONF_CLIENT, user, password, 1)) == NULL)
570 michael 1298 return NULL;
571 adx 30
572 michael 1426 /* If they are exempt from K-lines, return the best auth{} block. -A1kmm */
573 michael 1632 if (IsConfExemptKline(authcnf))
574     return authcnf;
575 adx 30
576     /* Find the best K-line... -A1kmm */
577 michael 8829 killcnf = find_conf_by_address(host, addr, CONF_KLINE, user, NULL, 1);
578 adx 30
579 michael 1426 /*
580     * If they are K-lined, return the K-line. Otherwise, return the
581 michael 5805 * auth {} block. -A1kmm
582 michael 1426 */
583 michael 6411 if (killcnf)
584 michael 1632 return killcnf;
585 adx 30
586 michael 1632 return authcnf;
587 adx 30 }
588    
589 michael 1632 /* struct MaskItem* find_dline_conf(struct irc_ssaddr*, int)
590 adx 30 *
591     * Input: An address, an address family.
592     * Output: The best matching D-line or exempt line.
593     * Side effects: None.
594     */
595 michael 1632 struct MaskItem *
596 michael 8829 find_dline_conf(const struct irc_ssaddr *addr)
597 adx 30 {
598 michael 1632 struct MaskItem *eline;
599 adx 30
600 michael 8829 eline = find_conf_by_address(NULL, addr, CONF_EXEMPT, NULL, NULL, 1);
601 michael 3215 if (eline)
602 michael 1298 return eline;
603    
604 michael 8829 return find_conf_by_address(NULL, addr, CONF_DLINE, NULL, NULL, 1);
605 adx 30 }
606    
607 michael 1632 /* void add_conf_by_address(int, struct MaskItem *aconf)
608 michael 2916 * Input:
609 adx 30 * Output: None
610     * Side-effects: Adds this entry to the hash table.
611     */
612 michael 2811 struct AddressRec *
613 michael 1632 add_conf_by_address(const unsigned int type, struct MaskItem *conf)
614 adx 30 {
615 michael 4977 const char *const hostname = conf->host;
616     const char *const username = conf->user;
617 michael 6868 static unsigned int prec_value = UINT_MAX;
618 michael 1367 int bits = 0;
619 adx 30
620 michael 3003 assert(type && !EmptyString(hostname));
621 adx 30
622 michael 8310 struct AddressRec *arec = xcalloc(sizeof(*arec));
623 michael 3001 arec->masktype = parse_netmask(hostname, &arec->Mask.ipa.addr, &bits);
624 adx 30 arec->Mask.ipa.bits = bits;
625 michael 1367 arec->username = username;
626 michael 1632 arec->conf = conf;
627 michael 1367 arec->precedence = prec_value--;
628     arec->type = type;
629 michael 1298
630 michael 1367 switch (arec->masktype)
631     {
632     case HM_IPV4:
633     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
634     bits -= bits % 8;
635     dlinkAdd(arec, &arec->node, &atable[hash_ipv4(&arec->Mask.ipa.addr, bits)]);
636     break;
637     case HM_IPV6:
638     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
639     bits -= bits % 16;
640     dlinkAdd(arec, &arec->node, &atable[hash_ipv6(&arec->Mask.ipa.addr, bits)]);
641     break;
642     default: /* HM_HOST */
643 michael 3001 arec->Mask.hostname = hostname;
644     dlinkAdd(arec, &arec->node, &atable[get_mask_hash(hostname)]);
645 michael 1367 break;
646 adx 30 }
647 michael 2811
648     return arec;
649 adx 30 }
650    
651 michael 1632 /* void delete_one_address(const char*, struct MaskItem*)
652     * Input: An address string, the associated MaskItem.
653 adx 30 * Output: None
654 michael 1632 * Side effects: Deletes an address record. Frees the MaskItem if there
655 adx 30 * is nothing referencing it, sets it as illegal otherwise.
656     */
657     void
658 michael 1632 delete_one_address_conf(const char *address, struct MaskItem *conf)
659 adx 30 {
660 michael 1367 int bits = 0;
661     uint32_t hv = 0;
662 michael 7914 dlink_node *node;
663 adx 30 struct irc_ssaddr addr;
664 michael 1298
665 michael 1367 switch (parse_netmask(address, &addr, &bits))
666     {
667     case HM_IPV4:
668     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
669     bits -= bits % 8;
670     hv = hash_ipv4(&addr, bits);
671     break;
672     case HM_IPV6:
673     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
674     bits -= bits % 16;
675     hv = hash_ipv6(&addr, bits);
676     break;
677     default: /* HM_HOST */
678     hv = get_mask_hash(address);
679     break;
680 adx 30 }
681 michael 1298
682 michael 4815 DLINK_FOREACH(node, atable[hv].head)
683 adx 30 {
684 michael 4815 struct AddressRec *arec = node->data;
685 michael 1367
686 michael 1632 if (arec->conf == conf)
687 adx 30 {
688 michael 1367 dlinkDelete(&arec->node, &atable[hv]);
689 michael 1298
690 michael 8437 if (conf->ref_count == 0)
691 michael 1632 conf_free(conf);
692 michael 1298
693 michael 7032 xfree(arec);
694 adx 30 return;
695     }
696     }
697     }
698    
699     /* void clear_out_address_conf(void)
700     * Input: None
701     * Output: None
702     * Side effects: Clears out all address records in the hash table,
703 michael 1632 * frees them, and frees the MaskItems if nothing references
704 michael 2916 * them, otherwise sets them as illegal.
705 adx 30 */
706     void
707     clear_out_address_conf(void)
708     {
709 michael 7914 dlink_node *node, *node_next;
710 michael 2916
711 michael 3235 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
712 adx 30 {
713 michael 4815 DLINK_FOREACH_SAFE(node, node_next, atable[i].head)
714 adx 30 {
715 michael 4815 struct AddressRec *arec = node->data;
716 michael 1367
717 michael 1628 /*
718 michael 5846 * Destroy the ircd.conf items and keep those that are in the databases
719 michael 1628 */
720 michael 5846 if (IsConfDatabase(arec->conf))
721 michael 1628 continue;
722 michael 1622
723 michael 1628 dlinkDelete(&arec->node, &atable[i]);
724 michael 8658 arec->conf->active = false;
725 michael 1298
726 michael 8437 if (arec->conf->ref_count == 0)
727 michael 1632 conf_free(arec->conf);
728 michael 7032 xfree(arec);
729 adx 30 }
730     }
731     }
732    
733 michael 1369 static void
734 michael 4977 hostmask_send_expiration(const struct AddressRec *const arec)
735 michael 1369 {
736 michael 6991 char ban_type = '?';
737 michael 1369
738     switch (arec->type)
739     {
740     case CONF_KLINE:
741     ban_type = 'K';
742     break;
743     case CONF_DLINE:
744     ban_type = 'D';
745     break;
746 michael 1644 default: break;
747 michael 1369 }
748 michael 2916
749 michael 8963 sendto_realops_flags(UMODE_EXPIRATION, L_ALL, SEND_NOTICE,
750 michael 1369 "Temporary %c-line for [%s@%s] expired", ban_type,
751 michael 1632 (arec->conf->user) ? arec->conf->user : "*",
752     (arec->conf->host) ? arec->conf->host : "*");
753 michael 1369 }
754    
755     void
756     hostmask_expire_temporary(void)
757     {
758 michael 7914 dlink_node *node, *node_next;
759 michael 1369
760 michael 3235 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
761 michael 1369 {
762 michael 4815 DLINK_FOREACH_SAFE(node, node_next, atable[i].head)
763 michael 1369 {
764 michael 4815 struct AddressRec *arec = node->data;
765 michael 1369
766 michael 8926 if (arec->conf->until == 0 || arec->conf->until > event_base->time.sec_real)
767 michael 1369 continue;
768    
769     switch (arec->type)
770     {
771     case CONF_KLINE:
772     case CONF_DLINE:
773     hostmask_send_expiration(arec);
774    
775     dlinkDelete(&arec->node, &atable[i]);
776 michael 1632 conf_free(arec->conf);
777 michael 7032 xfree(arec);
778 michael 1369 break;
779 michael 1644 default: break;
780 michael 1369 }
781     }
782     }
783     }

Properties

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