diff options
author | Michele Calgaro <[email protected]> | 2025-03-02 18:37:22 +0900 |
---|---|---|
committer | Michele Calgaro <[email protected]> | 2025-03-06 12:31:12 +0900 |
commit | 44ef0bd5fe47a43e47aec5f7981b6c1d728dd9a8 (patch) | |
tree | 2b29e921a9bccea53444ed9bbed06a25a5fe20cc /src/plugins/ipfilter/antip2p.cpp | |
parent | d1f24dae035c506d945ca13f2be398aa0a4de8cc (diff) | |
download | ktorrent-master.tar.gz ktorrent-master.zip |
Signed-off-by: Michele Calgaro <[email protected]>
Diffstat (limited to 'src/plugins/ipfilter/antip2p.cpp')
-rw-r--r-- | src/plugins/ipfilter/antip2p.cpp | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/src/plugins/ipfilter/antip2p.cpp b/src/plugins/ipfilter/antip2p.cpp new file mode 100644 index 0000000..2f9fb55 --- /dev/null +++ b/src/plugins/ipfilter/antip2p.cpp @@ -0,0 +1,237 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * [email protected] * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "antip2p.h" + +#include <torrent/globals.h> +#include <util/log.h> +#include <util/constants.h> +#include <util/mmapfile.h> + +#include <tdeglobal.h> +#include <tdestandarddirs.h> + +#include <tqstring.h> +#include <tqvaluelist.h> + +using namespace bt; + +namespace kt +{ + + bool IPBlock::operator < (const IPBlock & b) const + { + if (ip2 < b.ip1) // a range is before b range + return true; + else if (b.ip2 < ip1) // b range is before a range + return false; + else + return ip1 < b.ip1;// a and b intersect + } + + Uint32 AntiP2P::toUint32(const TQString& ip) + { + bool test; + Uint32 ret = ip.section('.',0,0).toULongLong(&test); + ret <<= 8; + ret |= ip.section('.',1,1).toULong(&test); + ret <<= 8; + ret |= ip.section('.',2,2).toULong(&test); + ret <<= 8; + ret |= ip.section('.',3,3).toULong(&test); + + return ret; + } + + TQString fromUint32(Uint32 ip) + { + Uint32 tmp = ip; + TQString out; + + tmp = ip; + tmp &= 0x000000FF; + out.prepend(TQString("%1").arg(tmp)); + ip >>= 8; + tmp = ip; + tmp &= 0x000000FF; + out.prepend(TQString("%1.").arg(tmp)); + ip >>= 8; + tmp = ip; + tmp &= 0x000000FF; + out.prepend(TQString("%1.").arg(tmp)); + ip >>= 8; + tmp = ip; + tmp &= 0x000000FF; + out.prepend(TQString("%1.").arg(tmp)); + + return out; + } + + AntiP2P::AntiP2P() + { + header_loaded = false; + load(); + } + + AntiP2P::~AntiP2P() + { + if(file) + delete file; + + Out(SYS_IPF|LOG_ALL) << "Anti-P2P filter unloaded." << endl; + } + + void AntiP2P::load() + { + file = new MMapFile(); + if(! file->open(TDEGlobal::dirs()->saveLocation("data","ktorrent") + "level1.dat", MMapFile::READ) ) + { + Out(SYS_IPF|LOG_NOTICE) << "Anti-p2p file not loaded." << endl; + file = 0; + return; + } + Out(SYS_IPF|LOG_ALL) << "Loading Anti-P2P filter..." << endl; + } + + void AntiP2P::loadHeader() + { + if(!file) + return; + + Uint32 nrElements = file->getSize() / sizeof(IPBlock); + uint blocksize = nrElements < 100 ? 10 : 100; // number of entries that each HeaderBlock holds. If total number is < 100, than this value is 10. + HeaderBlock hb; + + for(Uint64 i = 0; i < file->getSize() ; i+= sizeof(IPBlock)*(blocksize) ) + { + IPBlock ipb; + hb.offset = i; + file->seek(MMapFile::BEGIN, i); + file->read(&ipb, sizeof(IPBlock)); + hb.ip1 = ipb.ip1; + if ( i + (blocksize-1)*sizeof(IPBlock) > file->getSize() ) //last entry + { + file->seek(MMapFile::BEGIN, file->getSize() - sizeof(IPBlock)); + file->read(&ipb, sizeof(IPBlock)); + hb.ip2 = ipb.ip2; + hb.nrEntries = nrElements % blocksize; + + blocks.push_back(hb); + break; + } + file->seek(MMapFile::BEGIN, i + (blocksize-1)*sizeof(IPBlock)); + file->read(&ipb, sizeof(IPBlock)); + hb.ip2 = ipb.ip2; + hb.nrEntries = blocksize; + blocks.push_back(hb); + } + + Out(SYS_IPF|LOG_NOTICE) << "AntiP2P header loaded." << endl; + header_loaded = true; + } + + bool AntiP2P::exists() + { + return file != 0; + } + + bool AntiP2P::isBlockedIP(const TQString& ip ) + { + Uint32 test = toUint32(ip); + return isBlockedIP(test); + } + + int AntiP2P::searchHeader(Uint32& ip, int start, int end) + { + if (end == 0) + return -1; //empty list + + if (end == 1) + { + if (blocks[start].ip1 <= ip && blocks[start].ip2 >= ip) //then our IP is somewhere in between + { + if (blocks[start].ip1 == ip || blocks[start].ip2 == ip) + return -2; //Return -2 to signal that this IP matches either IP from header. No need to search mmaped file in that case. + else + return start; //else return block index + } + else + return -1; //not found + } + else + { + int i = start + end/2; + if (blocks[i].ip1 <= ip) + return searchHeader(ip, i, end - end/2); + else + return searchHeader(ip, start, end/2); + } + } + + bool AntiP2P::isBlockedIP( Uint32& ip ) + { + if (!header_loaded) + { + Out(SYS_IPF|LOG_IMPORTANT) << "Tried to check if IP was blocked, but no AntiP2P header was loaded." << endl; + return false; + } + + int in_header = searchHeader(ip, 0, blocks.count()); + switch (in_header) + { + case -1: + return false; //ip is not blocked + case -2: + return true; //ip is blocked (we're really lucky to find it in header already) + default: + //search mmapped file + HeaderBlock to_be_searched = blocks[in_header]; + Uint8* fptr = (Uint8*) file->getDataPointer(); + fptr += to_be_searched.offset; + IPBlock* file_blocks = (IPBlock*) fptr; + return searchFile(file_blocks, ip, 0, to_be_searched.nrEntries); + break; + } + return false; + } + + bool AntiP2P::searchFile(IPBlock* file_blocks, Uint32& ip, int start, int end) + { + if (end == 0) + return false; //empty list, so not found + + if (end == 1) + { + if (file_blocks[start].ip1 <= ip && file_blocks[start].ip2 >= ip) //we have a match! + return true; + else + return false; //IP is not found. + } + + else + { + int i = start + end/2; + if (file_blocks[i].ip1 <= ip) + return searchFile(file_blocks, ip, i, end - end/2); + else + return searchFile(file_blocks, ip, start, end/2); + } + } +} |