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 +}