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