Mercurial > hg > index.fcgi > gift-gnutella > gift-gnutella-0.0.11-1pba
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:ca8dcb803862 |
---|---|
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 */ | |
16 | |
17 #include "gt_gnutella.h" | |
18 | |
19 #include "gt_conf.h" | |
20 #include "gt_ban.h" | |
21 | |
22 /*****************************************************************************/ | |
23 | |
24 /* mask of bits that determines which bucket a ban goes into */ | |
25 #define INDEX_MASK (0xff000000) | |
26 | |
27 /*****************************************************************************/ | |
28 | |
29 typedef struct ban_ipv4 | |
30 { | |
31 in_addr_t ipv4; | |
32 uint32_t netmask; | |
33 } ban_ipv4_t; | |
34 | |
35 /*****************************************************************************/ | |
36 | |
37 /* ban list organize by the first 8 bits */ | |
38 static Dataset *ipv4_ban_list; | |
39 | |
40 /*****************************************************************************/ | |
41 | |
42 static char *net_mask_str (uint32_t netmask) | |
43 { | |
44 static char buf[128]; | |
45 | |
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)); | |
51 | |
52 return buf; | |
53 } | |
54 | |
55 static uint32_t net_mask_bin (char *netmask) | |
56 { | |
57 uint32_t a[4]; | |
58 | |
59 if (!netmask) | |
60 return 0xFFFFffff; | |
61 | |
62 if (sscanf (netmask, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]) != 4) | |
63 return 0xFFFFffff; | |
64 | |
65 return (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]; | |
66 } | |
67 | |
68 /*****************************************************************************/ | |
69 | |
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; | |
77 | |
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 } | |
85 | |
86 static void log_dup (ban_ipv4_t *orig_ban, ban_ipv4_t *b) | |
87 { | |
88 char *ip1, *ip2; | |
89 char *n1, *n2; | |
90 | |
91 if (!orig_ban || !b) | |
92 return; | |
93 | |
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)); | |
98 | |
99 if (BAN_DEBUG) | |
100 GT->dbg (GT, "ban %s/%s is a subset of %s/%s", ip1, n1, ip2, n2); | |
101 | |
102 free (ip1); | |
103 free (n1); | |
104 } | |
105 | |
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; | |
112 | |
113 if (!(ban = MALLOC (sizeof (ban_ipv4_t)))) | |
114 return FALSE; | |
115 | |
116 address = ntohl (address); | |
117 | |
118 ban->ipv4 = address; | |
119 ban->netmask = netmask | INDEX_MASK; /* ensure we have at least 8 bits */ | |
120 | |
121 prefix = address & INDEX_MASK; | |
122 | |
123 list = dataset_lookup (ipv4_ban_list, &prefix, sizeof (prefix)); | |
124 | |
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 } | |
131 | |
132 list = list_prepend (list, ban); | |
133 | |
134 if (!dataset_insert (&ipv4_ban_list, &prefix, sizeof (prefix), list, 0)) | |
135 return FALSE; | |
136 | |
137 if (BAN_DEBUG) | |
138 { | |
139 GT->dbg (GT, "*!*@%s/%s", net_ip_str (htonl (address)), | |
140 net_mask_str (netmask)); | |
141 } | |
142 | |
143 return TRUE; | |
144 } | |
145 | |
146 BOOL gt_ban_ipv4_is_banned (in_addr_t address) | |
147 { | |
148 uint32_t prefix; | |
149 List *list; | |
150 ban_ipv4_t ban; | |
151 | |
152 address = ntohl (address); | |
153 prefix = address & INDEX_MASK; | |
154 | |
155 if (!(list = dataset_lookup (ipv4_ban_list, &prefix, sizeof (prefix)))) | |
156 return FALSE; | |
157 | |
158 ban.ipv4 = address; | |
159 ban.netmask = 0xFFFFffff; | |
160 | |
161 if (list_find_custom (list, &ban, (ListForeachFunc)find_superset_ban)) | |
162 return TRUE; | |
163 | |
164 return FALSE; | |
165 } | |
166 | |
167 /*****************************************************************************/ | |
168 | |
169 static BOOL load_hostiles_txt (char *hostiles_filename) | |
170 { | |
171 FILE *f; | |
172 char *hostiles_path; | |
173 char *buf = NULL; | |
174 char *p; | |
175 | |
176 hostiles_path = gift_conf_path ("%s/%s", GT->name, hostiles_filename); | |
177 | |
178 if (!(f = fopen (hostiles_path, "r"))) | |
179 return FALSE; | |
180 | |
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; | |
187 | |
188 p = buf; | |
189 | |
190 /* divide the string into two sides */ | |
191 ipv4_str = string_sep (&p, "/"); | |
192 mask_str = p; | |
193 | |
194 if (!ipv4_str) | |
195 continue; | |
196 | |
197 netmask = net_mask_bin (mask_str); | |
198 ipv4 = net_ip (ipv4_str); | |
199 | |
200 if (!ipv4 || ipv4 == INADDR_NONE) | |
201 continue; | |
202 | |
203 gt_ban_ipv4_add (ipv4, netmask); | |
204 } | |
205 | |
206 fclose (f); | |
207 return TRUE; | |
208 } | |
209 | |
210 void gt_ban_init (void) | |
211 { | |
212 ipv4_ban_list = dataset_new (DATASET_HASH); | |
213 | |
214 if (!gt_config_load_file ("Gnutella/hostiles.txt", TRUE, FALSE)) | |
215 GT->warn (GT, "couldn't load \"hostiles.txt\""); | |
216 | |
217 load_hostiles_txt ("hostiles.txt"); | |
218 #ifndef WIN32 | |
219 load_hostiles_txt ("Hostiles.txt"); /* case-sensitivite blah */ | |
220 #endif | |
221 } | |
222 | |
223 static int free_ban (ban_ipv4_t *ban, void *udata) | |
224 { | |
225 free (ban); | |
226 return TRUE; | |
227 } | |
228 | |
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 } | |
235 | |
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 } |