Mercurial > hg > index.fcgi > gift-gnutella > gift-gnutella-0.0.11-1pba
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/gt_ban.c Sat Feb 20 21:18:28 2010 -0800 1.3 @@ -0,0 +1,241 @@ 1.4 +/* 1.5 + * $Id: gt_ban.c,v 1.7 2004/01/29 07:50:25 hipnod Exp $ 1.6 + * 1.7 + * Copyright (C) 2003 giFT project (gift.sourceforge.net) 1.8 + * 1.9 + * This program is free software; you can redistribute it and/or modify it 1.10 + * under the terms of the GNU General Public License as published by the 1.11 + * Free Software Foundation; either version 2, or (at your option) any 1.12 + * later version. 1.13 + * 1.14 + * This program is distributed in the hope that it will be useful, but 1.15 + * WITHOUT ANY WARRANTY; without even the implied warranty of 1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1.17 + * General Public License for more details. 1.18 + */ 1.19 + 1.20 +#include "gt_gnutella.h" 1.21 + 1.22 +#include "gt_conf.h" 1.23 +#include "gt_ban.h" 1.24 + 1.25 +/*****************************************************************************/ 1.26 + 1.27 +/* mask of bits that determines which bucket a ban goes into */ 1.28 +#define INDEX_MASK (0xff000000) 1.29 + 1.30 +/*****************************************************************************/ 1.31 + 1.32 +typedef struct ban_ipv4 1.33 +{ 1.34 + in_addr_t ipv4; 1.35 + uint32_t netmask; 1.36 +} ban_ipv4_t; 1.37 + 1.38 +/*****************************************************************************/ 1.39 + 1.40 +/* ban list organize by the first 8 bits */ 1.41 +static Dataset *ipv4_ban_list; 1.42 + 1.43 +/*****************************************************************************/ 1.44 + 1.45 +static char *net_mask_str (uint32_t netmask) 1.46 +{ 1.47 + static char buf[128]; 1.48 + 1.49 + snprintf (buf, sizeof (buf) - 1, "%d.%d.%d.%d", 1.50 + (netmask & 0xff000000) >> 24, 1.51 + (netmask & 0x00ff0000) >> 16, 1.52 + (netmask & 0x0000ff00) >> 8, 1.53 + (netmask & 0x000000ff)); 1.54 + 1.55 + return buf; 1.56 +} 1.57 + 1.58 +static uint32_t net_mask_bin (char *netmask) 1.59 +{ 1.60 + uint32_t a[4]; 1.61 + 1.62 + if (!netmask) 1.63 + return 0xFFFFffff; 1.64 + 1.65 + if (sscanf (netmask, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]) != 4) 1.66 + return 0xFFFFffff; 1.67 + 1.68 + return (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]; 1.69 +} 1.70 + 1.71 +/*****************************************************************************/ 1.72 + 1.73 +/* 1.74 + * Returns 0 if ban 'b' is contained within ban 'a'. 1.75 + */ 1.76 +static int find_superset_ban (ban_ipv4_t *a, ban_ipv4_t *b) 1.77 +{ 1.78 + uint32_t sig1 = a->ipv4 & a->netmask; 1.79 + uint32_t sig2 = b->ipv4 & b->netmask; 1.80 + 1.81 + /* 1.82 + * If there are no bits in the significant address portions 1.83 + * that contradict within _a_'s netmask, then ban _b_ is a 1.84 + * subset of _a_. 1.85 + */ 1.86 + return ((sig2 ^ sig1) & a->netmask); 1.87 +} 1.88 + 1.89 +static void log_dup (ban_ipv4_t *orig_ban, ban_ipv4_t *b) 1.90 +{ 1.91 + char *ip1, *ip2; 1.92 + char *n1, *n2; 1.93 + 1.94 + if (!orig_ban || !b) 1.95 + return; 1.96 + 1.97 + n1 = STRDUP (net_mask_str (b->netmask)); 1.98 + ip1 = STRDUP (net_ip_str (htonl (b->ipv4))); 1.99 + n2 = net_mask_str (orig_ban->netmask); 1.100 + ip2 = net_ip_str (htonl (orig_ban->ipv4)); 1.101 + 1.102 + if (BAN_DEBUG) 1.103 + GT->dbg (GT, "ban %s/%s is a subset of %s/%s", ip1, n1, ip2, n2); 1.104 + 1.105 + free (ip1); 1.106 + free (n1); 1.107 +} 1.108 + 1.109 +BOOL gt_ban_ipv4_add (in_addr_t address, uint32_t netmask) 1.110 +{ 1.111 + uint32_t prefix; 1.112 + List *list; 1.113 + List *orig; 1.114 + ban_ipv4_t *ban; 1.115 + 1.116 + if (!(ban = MALLOC (sizeof (ban_ipv4_t)))) 1.117 + return FALSE; 1.118 + 1.119 + address = ntohl (address); 1.120 + 1.121 + ban->ipv4 = address; 1.122 + ban->netmask = netmask | INDEX_MASK; /* ensure we have at least 8 bits */ 1.123 + 1.124 + prefix = address & INDEX_MASK; 1.125 + 1.126 + list = dataset_lookup (ipv4_ban_list, &prefix, sizeof (prefix)); 1.127 + 1.128 + if ((orig = list_find_custom (list, ban, (ListForeachFunc)find_superset_ban))) 1.129 + { 1.130 + log_dup (list_nth_data (orig, 0), ban); 1.131 + free (ban); 1.132 + return TRUE; 1.133 + } 1.134 + 1.135 + list = list_prepend (list, ban); 1.136 + 1.137 + if (!dataset_insert (&ipv4_ban_list, &prefix, sizeof (prefix), list, 0)) 1.138 + return FALSE; 1.139 + 1.140 + if (BAN_DEBUG) 1.141 + { 1.142 + GT->dbg (GT, "*!*@%s/%s", net_ip_str (htonl (address)), 1.143 + net_mask_str (netmask)); 1.144 + } 1.145 + 1.146 + return TRUE; 1.147 +} 1.148 + 1.149 +BOOL gt_ban_ipv4_is_banned (in_addr_t address) 1.150 +{ 1.151 + uint32_t prefix; 1.152 + List *list; 1.153 + ban_ipv4_t ban; 1.154 + 1.155 + address = ntohl (address); 1.156 + prefix = address & INDEX_MASK; 1.157 + 1.158 + if (!(list = dataset_lookup (ipv4_ban_list, &prefix, sizeof (prefix)))) 1.159 + return FALSE; 1.160 + 1.161 + ban.ipv4 = address; 1.162 + ban.netmask = 0xFFFFffff; 1.163 + 1.164 + if (list_find_custom (list, &ban, (ListForeachFunc)find_superset_ban)) 1.165 + return TRUE; 1.166 + 1.167 + return FALSE; 1.168 +} 1.169 + 1.170 +/*****************************************************************************/ 1.171 + 1.172 +static BOOL load_hostiles_txt (char *hostiles_filename) 1.173 +{ 1.174 + FILE *f; 1.175 + char *hostiles_path; 1.176 + char *buf = NULL; 1.177 + char *p; 1.178 + 1.179 + hostiles_path = gift_conf_path ("%s/%s", GT->name, hostiles_filename); 1.180 + 1.181 + if (!(f = fopen (hostiles_path, "r"))) 1.182 + return FALSE; 1.183 + 1.184 + while (file_read_line (f, &buf)) 1.185 + { 1.186 + in_addr_t ipv4; 1.187 + uint32_t netmask; 1.188 + char *ipv4_str; 1.189 + char *mask_str; 1.190 + 1.191 + p = buf; 1.192 + 1.193 + /* divide the string into two sides */ 1.194 + ipv4_str = string_sep (&p, "/"); 1.195 + mask_str = p; 1.196 + 1.197 + if (!ipv4_str) 1.198 + continue; 1.199 + 1.200 + netmask = net_mask_bin (mask_str); 1.201 + ipv4 = net_ip (ipv4_str); 1.202 + 1.203 + if (!ipv4 || ipv4 == INADDR_NONE) 1.204 + continue; 1.205 + 1.206 + gt_ban_ipv4_add (ipv4, netmask); 1.207 + } 1.208 + 1.209 + fclose (f); 1.210 + return TRUE; 1.211 +} 1.212 + 1.213 +void gt_ban_init (void) 1.214 +{ 1.215 + ipv4_ban_list = dataset_new (DATASET_HASH); 1.216 + 1.217 + if (!gt_config_load_file ("Gnutella/hostiles.txt", TRUE, FALSE)) 1.218 + GT->warn (GT, "couldn't load \"hostiles.txt\""); 1.219 + 1.220 + load_hostiles_txt ("hostiles.txt"); 1.221 +#ifndef WIN32 1.222 + load_hostiles_txt ("Hostiles.txt"); /* case-sensitivite blah */ 1.223 +#endif 1.224 +} 1.225 + 1.226 +static int free_ban (ban_ipv4_t *ban, void *udata) 1.227 +{ 1.228 + free (ban); 1.229 + return TRUE; 1.230 +} 1.231 + 1.232 +static int cleanup_lists (ds_data_t *data, ds_data_t *value, void *udata) 1.233 +{ 1.234 + List *list = value->data; 1.235 + list_foreach_remove (list, (ListForeachFunc)free_ban, NULL); 1.236 + return DS_CONTINUE | DS_REMOVE; 1.237 +} 1.238 + 1.239 +void gt_ban_cleanup (void) 1.240 +{ 1.241 + dataset_foreach_ex (ipv4_ban_list, DS_FOREACH_EX(cleanup_lists), NULL); 1.242 + dataset_clear (ipv4_ban_list); 1.243 + ipv4_ban_list = NULL; 1.244 +}