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