view src/gt_ban.c @ 0:d39e1d0d75b6

initial add
author paulo@hit-nxdomain.opendns.com
date Sat, 20 Feb 2010 21:18:28 -0800
parents
children
line source
1 /*
2 * $Id: gt_ban.c,v 1.7 2004/01/29 07:50:25 hipnod Exp $
3 *
4 * Copyright (C) 2003 giFT project (gift.sourceforge.net)
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 */
17 #include "gt_gnutella.h"
19 #include "gt_conf.h"
20 #include "gt_ban.h"
22 /*****************************************************************************/
24 /* mask of bits that determines which bucket a ban goes into */
25 #define INDEX_MASK (0xff000000)
27 /*****************************************************************************/
29 typedef struct ban_ipv4
30 {
31 in_addr_t ipv4;
32 uint32_t netmask;
33 } ban_ipv4_t;
35 /*****************************************************************************/
37 /* ban list organize by the first 8 bits */
38 static Dataset *ipv4_ban_list;
40 /*****************************************************************************/
42 static char *net_mask_str (uint32_t netmask)
43 {
44 static char buf[128];
46 snprintf (buf, sizeof (buf) - 1, "%d.%d.%d.%d",
47 (netmask & 0xff000000) >> 24,
48 (netmask & 0x00ff0000) >> 16,
49 (netmask & 0x0000ff00) >> 8,
50 (netmask & 0x000000ff));
52 return buf;
53 }
55 static uint32_t net_mask_bin (char *netmask)
56 {
57 uint32_t a[4];
59 if (!netmask)
60 return 0xFFFFffff;
62 if (sscanf (netmask, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]) != 4)
63 return 0xFFFFffff;
65 return (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3];
66 }
68 /*****************************************************************************/
70 /*
71 * Returns 0 if ban 'b' is contained within ban 'a'.
72 */
73 static int find_superset_ban (ban_ipv4_t *a, ban_ipv4_t *b)
74 {
75 uint32_t sig1 = a->ipv4 & a->netmask;
76 uint32_t sig2 = b->ipv4 & b->netmask;
78 /*
79 * If there are no bits in the significant address portions
80 * that contradict within _a_'s netmask, then ban _b_ is a
81 * subset of _a_.
82 */
83 return ((sig2 ^ sig1) & a->netmask);
84 }
86 static void log_dup (ban_ipv4_t *orig_ban, ban_ipv4_t *b)
87 {
88 char *ip1, *ip2;
89 char *n1, *n2;
91 if (!orig_ban || !b)
92 return;
94 n1 = STRDUP (net_mask_str (b->netmask));
95 ip1 = STRDUP (net_ip_str (htonl (b->ipv4)));
96 n2 = net_mask_str (orig_ban->netmask);
97 ip2 = net_ip_str (htonl (orig_ban->ipv4));
99 if (BAN_DEBUG)
100 GT->dbg (GT, "ban %s/%s is a subset of %s/%s", ip1, n1, ip2, n2);
102 free (ip1);
103 free (n1);
104 }
106 BOOL gt_ban_ipv4_add (in_addr_t address, uint32_t netmask)
107 {
108 uint32_t prefix;
109 List *list;
110 List *orig;
111 ban_ipv4_t *ban;
113 if (!(ban = MALLOC (sizeof (ban_ipv4_t))))
114 return FALSE;
116 address = ntohl (address);
118 ban->ipv4 = address;
119 ban->netmask = netmask | INDEX_MASK; /* ensure we have at least 8 bits */
121 prefix = address & INDEX_MASK;
123 list = dataset_lookup (ipv4_ban_list, &prefix, sizeof (prefix));
125 if ((orig = list_find_custom (list, ban, (ListForeachFunc)find_superset_ban)))
126 {
127 log_dup (list_nth_data (orig, 0), ban);
128 free (ban);
129 return TRUE;
130 }
132 list = list_prepend (list, ban);
134 if (!dataset_insert (&ipv4_ban_list, &prefix, sizeof (prefix), list, 0))
135 return FALSE;
137 if (BAN_DEBUG)
138 {
139 GT->dbg (GT, "*!*@%s/%s", net_ip_str (htonl (address)),
140 net_mask_str (netmask));
141 }
143 return TRUE;
144 }
146 BOOL gt_ban_ipv4_is_banned (in_addr_t address)
147 {
148 uint32_t prefix;
149 List *list;
150 ban_ipv4_t ban;
152 address = ntohl (address);
153 prefix = address & INDEX_MASK;
155 if (!(list = dataset_lookup (ipv4_ban_list, &prefix, sizeof (prefix))))
156 return FALSE;
158 ban.ipv4 = address;
159 ban.netmask = 0xFFFFffff;
161 if (list_find_custom (list, &ban, (ListForeachFunc)find_superset_ban))
162 return TRUE;
164 return FALSE;
165 }
167 /*****************************************************************************/
169 static BOOL load_hostiles_txt (char *hostiles_filename)
170 {
171 FILE *f;
172 char *hostiles_path;
173 char *buf = NULL;
174 char *p;
176 hostiles_path = gift_conf_path ("%s/%s", GT->name, hostiles_filename);
178 if (!(f = fopen (hostiles_path, "r")))
179 return FALSE;
181 while (file_read_line (f, &buf))
182 {
183 in_addr_t ipv4;
184 uint32_t netmask;
185 char *ipv4_str;
186 char *mask_str;
188 p = buf;
190 /* divide the string into two sides */
191 ipv4_str = string_sep (&p, "/");
192 mask_str = p;
194 if (!ipv4_str)
195 continue;
197 netmask = net_mask_bin (mask_str);
198 ipv4 = net_ip (ipv4_str);
200 if (!ipv4 || ipv4 == INADDR_NONE)
201 continue;
203 gt_ban_ipv4_add (ipv4, netmask);
204 }
206 fclose (f);
207 return TRUE;
208 }
210 void gt_ban_init (void)
211 {
212 ipv4_ban_list = dataset_new (DATASET_HASH);
214 if (!gt_config_load_file ("Gnutella/hostiles.txt", TRUE, FALSE))
215 GT->warn (GT, "couldn't load \"hostiles.txt\"");
217 load_hostiles_txt ("hostiles.txt");
218 #ifndef WIN32
219 load_hostiles_txt ("Hostiles.txt"); /* case-sensitivite blah */
220 #endif
221 }
223 static int free_ban (ban_ipv4_t *ban, void *udata)
224 {
225 free (ban);
226 return TRUE;
227 }
229 static int cleanup_lists (ds_data_t *data, ds_data_t *value, void *udata)
230 {
231 List *list = value->data;
232 list_foreach_remove (list, (ListForeachFunc)free_ban, NULL);
233 return DS_CONTINUE | DS_REMOVE;
234 }
236 void gt_ban_cleanup (void)
237 {
238 dataset_foreach_ex (ipv4_ban_list, DS_FOREACH_EX(cleanup_lists), NULL);
239 dataset_clear (ipv4_ban_list);
240 ipv4_ban_list = NULL;
241 }