ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hostmask.c
Revision: 2894
Committed: Tue Jan 21 19:11:13 2014 UTC (11 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 21258 byte(s)
Log Message:
- hostmask.c: style cleanups

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * hostmask.c: Code to efficiently find IP & hostmask based configs.
4     *
5     * Copyright (C) 2005 by the past and present ircd coders, and others.
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20     * USA
21     *
22 knight 31 * $Id$
23 adx 30 */
24    
25     #include "stdinc.h"
26     #include "memory.h"
27     #include "ircd_defs.h"
28 michael 1011 #include "list.h"
29 michael 1309 #include "conf.h"
30 adx 30 #include "hostmask.h"
31     #include "send.h"
32     #include "irc_string.h"
33 michael 1369 #include "ircd.h"
34 adx 30
35    
36     #define DigitParse(ch) do { \
37     if (ch >= '0' && ch <= '9') \
38     ch = ch - '0'; \
39     else if (ch >= 'A' && ch <= 'F') \
40     ch = ch - 'A' + 10; \
41     else if (ch >= 'a' && ch <= 'f') \
42     ch = ch - 'a' + 10; \
43 michael 1298 } while (0);
44 adx 30
45     /* The mask parser/type determination code... */
46    
47     /* int try_parse_v6_netmask(const char *, struct irc_ssaddr *, int *);
48     * Input: A possible IPV6 address as a string.
49     * Output: An integer describing whether it is an IPV6 or hostmask,
50     * an address(if it is IPV6), a bitlength(if it is IPV6).
51     * Side effects: None
52     * Comments: Called from parse_netmask
53     */
54     /* Fixed so ::/0 (any IPv6 address) is valid
55     Also a bug in DigitParse above.
56     -Gozem 2002-07-19 gozem@linux.nu
57     */
58     #ifdef IPV6
59     static int
60     try_parse_v6_netmask(const char *text, struct irc_ssaddr *addr, int *b)
61     {
62     const char *p;
63     char c;
64     int d[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
65     int dp = 0;
66     int nyble = 4;
67     int finsert = -1;
68     int bits = 128;
69     int deficit = 0;
70     short dc[8];
71 michael 1298 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
72 adx 30
73     for (p = text; (c = *p); p++)
74 michael 2894 {
75 adx 30 if (IsXDigit(c))
76     {
77     if (nyble == 0)
78     return HM_HOST;
79     DigitParse(c);
80     d[dp] |= c << (4 * --nyble);
81     }
82     else if (c == ':')
83     {
84     if (p > text && *(p - 1) == ':')
85     {
86     if (finsert >= 0)
87     return HM_HOST;
88     finsert = dp;
89     }
90     else
91     {
92     /* If there were less than 4 hex digits, e.g. :ABC: shift right
93     * so we don't interpret it as ABC0 -A1kmm */
94     d[dp] = d[dp] >> 4 * nyble;
95     nyble = 4;
96     if (++dp >= 8)
97     return HM_HOST;
98     }
99     }
100     else if (c == '*')
101     {
102     /* * must be last, and * is ambiguous if there is a ::... -A1kmm */
103     if (finsert >= 0 || *(p + 1) || dp == 0 || *(p - 1) != ':')
104     return HM_HOST;
105     bits = dp * 16;
106     }
107     else if (c == '/')
108     {
109     char *after;
110    
111     d[dp] = d[dp] >> 4 * nyble;
112     dp++;
113     bits = strtoul(p + 1, &after, 10);
114 michael 1298
115 adx 30 if (bits < 0 || *after)
116     return HM_HOST;
117     if (bits > dp * 4 && !(finsert >= 0 && bits <= 128))
118     return HM_HOST;
119     break;
120     }
121     else
122     return HM_HOST;
123 michael 2894 }
124 adx 30
125     d[dp] = d[dp] >> 4 * nyble;
126 michael 1298
127 adx 30 if (c == 0)
128     dp++;
129     if (finsert < 0 && bits == 0)
130     bits = dp * 16;
131 michael 1298
132 adx 30 /* How many words are missing? -A1kmm */
133     deficit = bits / 16 + ((bits % 16) ? 1 : 0) - dp;
134 michael 1298
135 adx 30 /* Now fill in the gaps(from ::) in the copied table... -A1kmm */
136     for (dp = 0, nyble = 0; dp < 8; dp++)
137     {
138     if (nyble == finsert && deficit)
139     {
140     dc[dp] = 0;
141     deficit--;
142     }
143     else
144     dc[dp] = d[nyble++];
145     }
146 michael 1298
147 adx 30 /* Set unused bits to 0... -A1kmm */
148     if (bits < 128 && (bits % 16 != 0))
149     dc[bits / 16] &= ~((1 << (15 - bits % 16)) - 1);
150     for (dp = bits / 16 + (bits % 16 ? 1 : 0); dp < 8; dp++)
151     dc[dp] = 0;
152 michael 1298
153 adx 30 /* And assign... -A1kmm */
154     if (addr)
155     for (dp = 0; dp < 8; dp++)
156     /* The cast is a kludge to make netbsd work. */
157     ((unsigned short *)&v6->sin6_addr)[dp] = htons(dc[dp]);
158 michael 1298
159 adx 30 if (b != NULL)
160     *b = bits;
161     return HM_IPV6;
162     }
163     #endif
164    
165     /* int try_parse_v4_netmask(const char *, struct irc_ssaddr *, int *);
166     * Input: A possible IPV4 address as a string.
167     * Output: An integer describing whether it is an IPV4 or hostmask,
168     * an address(if it is IPV4), a bitlength(if it is IPV4).
169     * Side effects: None
170     * Comments: Called from parse_netmask
171     */
172     static int
173     try_parse_v4_netmask(const char *text, struct irc_ssaddr *addr, int *b)
174     {
175     const char *p;
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     for (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 adx 30 for (n = 0; n < 4; n++)
226     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     for (n = bits / 8 + (bits % 8 ? 1 : 0); n < 4; n++)
235     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     if (b != NULL)
240     *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     for (i = 0; i < n; i++)
278     if (v6->sin6_addr.s6_addr[i] != v6mask->sin6_addr.s6_addr[i])
279     return 0;
280     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     #endif
288 michael 1372
289 adx 30 /* int match_ipv4(struct irc_ssaddr *, struct irc_ssaddr *, int)
290     * Input: An IP address, an IP mask, the number of bits in the mask.
291     * Output: if match, -1 else 0
292     * Side Effects: None
293     */
294     int
295 michael 1455 match_ipv4(const struct irc_ssaddr *addr, const struct irc_ssaddr *mask, int bits)
296 adx 30 {
297 michael 1455 const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
298     const struct sockaddr_in *v4mask = (const struct sockaddr_in *)mask;
299 michael 1298
300 adx 30 if ((ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1)) !=
301     ntohl(v4mask->sin_addr.s_addr))
302     return 0;
303     return -1;
304     }
305    
306     /*
307     * mask_addr
308     *
309     * inputs - pointer to the ip to mask
310     * - bitlen
311     * output - NONE
312     * side effects -
313     */
314     void
315     mask_addr(struct irc_ssaddr *ip, int bits)
316     {
317     int mask;
318     #ifdef IPV6
319     struct sockaddr_in6 *v6_base_ip;
320     int i, m, n;
321     #endif
322     struct sockaddr_in *v4_base_ip;
323    
324     #ifdef IPV6
325     if (ip->ss.ss_family != AF_INET6)
326     #endif
327     {
328 michael 1298 v4_base_ip = (struct sockaddr_in *)ip;
329    
330 adx 30 mask = ~((1 << (32 - bits)) - 1);
331 michael 1298 v4_base_ip->sin_addr.s_addr = htonl(ntohl(v4_base_ip->sin_addr.s_addr) & mask);
332 adx 30 }
333     #ifdef IPV6
334     else
335     {
336     n = bits / 8;
337     m = bits % 8;
338 michael 1298 v6_base_ip = (struct sockaddr_in6 *)ip;
339 adx 30
340     mask = ~((1 << (8 - m)) -1 );
341     v6_base_ip->sin6_addr.s6_addr[n] = v6_base_ip->sin6_addr.s6_addr[n] & mask;
342 michael 1298
343 db 300 for (i = n + 1; i < 16; i++)
344     v6_base_ip->sin6_addr.s6_addr[i] = 0;
345 adx 30 }
346     #endif
347     }
348    
349     /* Hashtable stuff...now external as its used in m_stats.c */
350 michael 1367 dlink_list atable[ATABLE_SIZE];
351 adx 30
352     void
353     init_host_hash(void)
354     {
355     memset(&atable, 0, sizeof(atable));
356     }
357    
358     /* unsigned long hash_ipv4(struct irc_ssaddr*)
359     * Input: An IP address.
360     * Output: A hash value of the IP address.
361     * Side effects: None
362     */
363 michael 1343 static uint32_t
364 adx 30 hash_ipv4(struct irc_ssaddr *addr, int bits)
365     {
366     if (bits != 0)
367     {
368     struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
369 michael 1343 uint32_t av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
370 michael 1298
371     return (av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1);
372 adx 30 }
373    
374 michael 1298 return 0;
375 adx 30 }
376    
377     /* unsigned long hash_ipv6(struct irc_ssaddr*)
378     * Input: An IP address.
379     * Output: A hash value of the IP address.
380     * Side effects: None
381     */
382     #ifdef IPV6
383 michael 1343 static uint32_t
384 adx 30 hash_ipv6(struct irc_ssaddr *addr, int bits)
385     {
386 michael 1343 uint32_t v = 0, n;
387 michael 1298 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
388    
389 adx 30 for (n = 0; n < 16; n++)
390     {
391     if (bits >= 8)
392     {
393     v ^= v6->sin6_addr.s6_addr[n];
394     bits -= 8;
395     }
396     else if (bits)
397     {
398     v ^= v6->sin6_addr.s6_addr[n] & ~((1 << (8 - bits)) - 1);
399     return v & (ATABLE_SIZE - 1);
400     }
401     else
402     return v & (ATABLE_SIZE - 1);
403     }
404     return v & (ATABLE_SIZE - 1);
405     }
406     #endif
407    
408     /* int hash_text(const char *start)
409     * Input: The start of the text to hash.
410     * Output: The hash of the string between 1 and (TH_MAX-1)
411     * Side-effects: None.
412     */
413 michael 1343 static uint32_t
414 adx 30 hash_text(const char *start)
415     {
416     const char *p = start;
417 michael 1343 uint32_t h = 0;
418 adx 30
419 michael 1367 for (; *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     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 (username == NULL)
466     username = "";
467     if (password == NULL)
468     password = "";
469    
470     if (addr)
471     {
472     /* Check for IPV6 matches... */
473     #ifdef IPV6
474     if (fam == AF_INET6)
475     {
476     for (b = 128; b >= 0; b -= 16)
477     {
478 michael 1367 DLINK_FOREACH(ptr, atable[hash_ipv6(addr, b)].head)
479     {
480     arec = ptr->data;
481    
482 adx 30 if (arec->type == (type & ~0x1) &&
483     arec->precedence > hprecv &&
484     arec->masktype == HM_IPV6 &&
485     match_ipv6(addr, &arec->Mask.ipa.addr,
486     arec->Mask.ipa.bits) &&
487 michael 1652 (type & 0x1 || !cmpfunc(arec->username, username)) &&
488 michael 1632 (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     else
498     #endif
499     if (fam == AF_INET)
500     {
501     for (b = 32; b >= 0; b -= 8)
502     {
503 michael 1367 DLINK_FOREACH(ptr, atable[hash_ipv4(addr, b)].head)
504     {
505     arec = ptr->data;
506    
507 adx 30 if (arec->type == (type & ~0x1) &&
508     arec->precedence > hprecv &&
509     arec->masktype == HM_IPV4 &&
510     match_ipv4(addr, &arec->Mask.ipa.addr,
511     arec->Mask.ipa.bits) &&
512 michael 1652 (type & 0x1 || !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 adx 30 }
521     }
522     }
523    
524     if (name != NULL)
525     {
526     const char *p = name;
527    
528     while (1)
529     {
530 michael 1367 DLINK_FOREACH(ptr, atable[hash_text(p)].head)
531     {
532     arec = ptr->data;
533     if ((arec->type == (type & ~0x1)) &&
534 adx 30 arec->precedence > hprecv &&
535     (arec->masktype == HM_HOST) &&
536 michael 1652 !cmpfunc(arec->Mask.hostname, name) &&
537     (type & 0x1 || !cmpfunc(arec->username, username)) &&
538 michael 1632 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
539     match_conf_password(password, arec->conf)))
540 adx 30 {
541     hprecv = arec->precedence;
542 michael 1632 hprec = arec->conf;
543 adx 30 }
544 michael 1367 }
545 adx 30 p = strchr(p, '.');
546     if (p == NULL)
547     break;
548     p++;
549     }
550 michael 1367
551     DLINK_FOREACH(ptr, atable[0].head)
552     {
553     arec = ptr->data;
554    
555 adx 30 if (arec->type == (type & ~0x1) &&
556     arec->precedence > hprecv &&
557     arec->masktype == HM_HOST &&
558 michael 1652 !cmpfunc(arec->Mask.hostname, name) &&
559 michael 1655 (type & 0x1 || !cmpfunc(arec->username, username)) &&
560 michael 1632 (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL ||
561     match_conf_password(password, arec->conf)))
562 adx 30 {
563     hprecv = arec->precedence;
564 michael 1632 hprec = arec->conf;
565 adx 30 }
566 michael 1367 }
567 adx 30 }
568    
569     return hprec;
570     }
571    
572 michael 1632 /* struct MaskItem* find_address_conf(const char*, const char*,
573 adx 30 * struct irc_ssaddr*, int, char *);
574     * Input: The hostname, username, address, address family.
575 michael 1632 * Output: The applicable MaskItem.
576 adx 30 * Side-effects: None
577     */
578 michael 1632 struct MaskItem *
579 adx 30 find_address_conf(const char *host, const char *user,
580     struct irc_ssaddr *ip, int aftype, char *password)
581     {
582 michael 1632 struct MaskItem *authcnf = NULL, *killcnf = NULL;
583 adx 30
584 michael 1426 /* Find the best auth{} block... If none, return NULL -A1kmm */
585 michael 1632 if ((authcnf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user,
586     password, 1)) == NULL)
587 michael 1298 return NULL;
588 adx 30
589 michael 1426 /* If they are exempt from K-lines, return the best auth{} block. -A1kmm */
590 michael 1632 if (IsConfExemptKline(authcnf))
591     return authcnf;
592 adx 30
593     /* Find the best K-line... -A1kmm */
594 michael 1632 killcnf = find_conf_by_address(host, ip, CONF_KLINE, aftype, user, NULL, 1);
595 adx 30
596 michael 1426 /*
597     * If they are K-lined, return the K-line. Otherwise, return the
598     * auth{} block. -A1kmm
599     */
600 michael 1632 if (killcnf != NULL)
601     return killcnf;
602 adx 30
603 michael 1632 if (IsConfExemptGline(authcnf))
604     return authcnf;
605 adx 30
606 michael 1632 killcnf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL, 1);
607     if (killcnf != NULL)
608     return killcnf;
609    
610     return authcnf;
611 adx 30 }
612    
613 michael 1632 /* struct MaskItem* find_dline_conf(struct irc_ssaddr*, int)
614 adx 30 *
615     * Input: An address, an address family.
616     * Output: The best matching D-line or exempt line.
617     * Side effects: None.
618     */
619 michael 1632 struct MaskItem *
620 adx 30 find_dline_conf(struct irc_ssaddr *addr, int aftype)
621     {
622 michael 1632 struct MaskItem *eline;
623 adx 30
624 michael 1632 eline = find_conf_by_address(NULL, addr, CONF_EXEMPT | 1, aftype,
625 michael 1371 NULL, NULL, 1);
626 adx 30 if (eline != NULL)
627 michael 1298 return eline;
628    
629 michael 1371 return find_conf_by_address(NULL, addr, CONF_DLINE | 1, aftype, NULL, NULL, 1);
630 adx 30 }
631    
632 michael 1632 /* void add_conf_by_address(int, struct MaskItem *aconf)
633 adx 30 * Input:
634     * Output: None
635     * Side-effects: Adds this entry to the hash table.
636     */
637 michael 2811 struct AddressRec *
638 michael 1632 add_conf_by_address(const unsigned int type, struct MaskItem *conf)
639 adx 30 {
640     const char *address;
641     const char *username;
642 michael 1343 static unsigned int prec_value = 0xFFFFFFFF;
643 michael 1367 int bits = 0;
644 adx 30 struct AddressRec *arec;
645    
646 michael 1632 address = conf->host;
647     username = conf->user;
648 adx 30
649 michael 1632 assert(type);
650 adx 30
651     if (EmptyString(address))
652     address = "/NOMATCH!/";
653    
654     arec = MyMalloc(sizeof(struct AddressRec));
655 michael 1367 arec->masktype = parse_netmask(address, &arec->Mask.ipa.addr, &bits);
656 adx 30 arec->Mask.ipa.bits = bits;
657 michael 1367 arec->username = username;
658 michael 1632 arec->conf = conf;
659 michael 1367 arec->precedence = prec_value--;
660     arec->type = type;
661 michael 1298
662 michael 1367 switch (arec->masktype)
663     {
664     case HM_IPV4:
665     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
666     bits -= bits % 8;
667     dlinkAdd(arec, &arec->node, &atable[hash_ipv4(&arec->Mask.ipa.addr, bits)]);
668     break;
669 adx 30 #ifdef IPV6
670 michael 1367 case HM_IPV6:
671     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
672     bits -= bits % 16;
673     dlinkAdd(arec, &arec->node, &atable[hash_ipv6(&arec->Mask.ipa.addr, bits)]);
674     break;
675 adx 30 #endif
676 michael 1367 default: /* HM_HOST */
677     arec->Mask.hostname = address;
678     dlinkAdd(arec, &arec->node, &atable[get_mask_hash(address)]);
679     break;
680 adx 30 }
681 michael 2811
682     return arec;
683 adx 30 }
684    
685 michael 1632 /* void delete_one_address(const char*, struct MaskItem*)
686     * Input: An address string, the associated MaskItem.
687 adx 30 * Output: None
688 michael 1632 * Side effects: Deletes an address record. Frees the MaskItem if there
689 adx 30 * is nothing referencing it, sets it as illegal otherwise.
690     */
691     void
692 michael 1632 delete_one_address_conf(const char *address, struct MaskItem *conf)
693 adx 30 {
694 michael 1367 int bits = 0;
695     uint32_t hv = 0;
696     dlink_node *ptr = NULL, *ptr_next = NULL;
697 adx 30 struct irc_ssaddr addr;
698 michael 1298
699 michael 1367 switch (parse_netmask(address, &addr, &bits))
700     {
701     case HM_IPV4:
702     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
703     bits -= bits % 8;
704     hv = hash_ipv4(&addr, bits);
705     break;
706 adx 30 #ifdef IPV6
707 michael 1367 case HM_IPV6:
708     /* We have to do this, since we do not re-hash for every bit -A1kmm. */
709     bits -= bits % 16;
710     hv = hash_ipv6(&addr, bits);
711     break;
712 adx 30 #endif
713 michael 1367 default: /* HM_HOST */
714     hv = get_mask_hash(address);
715     break;
716 adx 30 }
717 michael 1298
718 michael 1367 DLINK_FOREACH_SAFE(ptr, ptr_next, atable[hv].head)
719 adx 30 {
720 michael 1367 struct AddressRec *arec = ptr->data;
721    
722 michael 1632 if (arec->conf == conf)
723 adx 30 {
724 michael 1367 dlinkDelete(&arec->node, &atable[hv]);
725 michael 1298
726 michael 1644 if (!conf->ref_count)
727 michael 1632 conf_free(conf);
728 michael 1298
729 adx 30 MyFree(arec);
730     return;
731     }
732     }
733     }
734    
735     /* void clear_out_address_conf(void)
736     * Input: None
737     * Output: None
738     * Side effects: Clears out all address records in the hash table,
739 michael 1632 * frees them, and frees the MaskItems if nothing references
740 adx 30 * them, otherwise sets them as illegal.
741     */
742     void
743     clear_out_address_conf(void)
744     {
745 michael 1367 unsigned int i = 0;
746     dlink_node *ptr = NULL, *ptr_next = NULL;
747 adx 30
748 michael 1367 for (i = 0; i < ATABLE_SIZE; ++i)
749 adx 30 {
750 michael 1367 DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
751 adx 30 {
752 michael 1367 struct AddressRec *arec = ptr->data;
753    
754 michael 1628 /*
755     * We keep the temporary K-lines and destroy the permanent ones,
756     * just to be confusing :) -A1kmm
757     */
758 michael 1649 if (arec->conf->until || IsConfDatabase(arec->conf))
759 michael 1628 continue;
760 michael 1622
761 michael 1628 dlinkDelete(&arec->node, &atable[i]);
762 michael 1298
763 michael 1644 if (!arec->conf->ref_count)
764 michael 1632 conf_free(arec->conf);
765 michael 1628 MyFree(arec);
766 adx 30 }
767     }
768     }
769    
770 michael 1369 static void
771     hostmask_send_expiration(struct AddressRec *arec)
772     {
773     char ban_type = '\0';
774    
775     if (!ConfigFileEntry.tkline_expire_notices)
776     return;
777    
778     switch (arec->type)
779     {
780     case CONF_KLINE:
781     ban_type = 'K';
782     break;
783     case CONF_DLINE:
784     ban_type = 'D';
785     break;
786     case CONF_GLINE:
787     ban_type = 'G';
788     break;
789 michael 1644 default: break;
790 michael 1369 }
791    
792 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
793 michael 1369 "Temporary %c-line for [%s@%s] expired", ban_type,
794 michael 1632 (arec->conf->user) ? arec->conf->user : "*",
795     (arec->conf->host) ? arec->conf->host : "*");
796 michael 1369 }
797    
798     void
799     hostmask_expire_temporary(void)
800     {
801     unsigned int i = 0;
802     dlink_node *ptr = NULL, *ptr_next = NULL;
803    
804     for (i = 0; i < ATABLE_SIZE; ++i)
805     {
806     DLINK_FOREACH_SAFE(ptr, ptr_next, atable[i].head)
807     {
808     struct AddressRec *arec = ptr->data;
809    
810 michael 1649 if (!arec->conf->until || arec->conf->until > CurrentTime)
811 michael 1369 continue;
812    
813     switch (arec->type)
814     {
815     case CONF_KLINE:
816     case CONF_DLINE:
817     case CONF_GLINE:
818     hostmask_send_expiration(arec);
819    
820     dlinkDelete(&arec->node, &atable[i]);
821 michael 1632 conf_free(arec->conf);
822 michael 1369 MyFree(arec);
823     break;
824 michael 1644 default: break;
825 michael 1369 }
826     }
827     }
828     }

Properties

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