Ticket #239: rtorrent-0.8.6-ip_filter_no_boost-fast.patch

File rtorrent-0.8.6-ip_filter_no_boost-fast.patch, 28.7 KB (added by denis@fateyev.com, 2 years ago)

ip_filter feature for rtorrent 0.8.6 (diff)

  • src/command_network.cc

    Based on 'rtorrent-0.8.5-ip_filter_no_boost-fast.patch' by Richard Monk and 'yb'
    Adapted for rtorrent-0.8.6 by Denis Fateyev <denis@fateyev.com>
    
    See http://libtorrent.rakshasa.no/ticket/239 for more details.
    
    a b  
    3636 
    3737#include "config.h" 
    3838 
     39#include <string> 
     40#include <sstream> 
     41#include <list> 
     42#include <unistd.h> 
     43 
    3944#include <functional> 
    4045#include <cstdio> 
    4146#include <rak/address_info.h> 
     
    6267#include "control.h" 
    6368#include "command_helpers.h" 
    6469 
     70#include "utils/pattern.h"  
     71#include "core/ip_filter.h" 
     72 
     73 
    6574torrent::Object 
    6675apply_throttle(bool up, const torrent::Object& rawArgs) { 
    6776  const torrent::Object::list_type& args = rawArgs.as_list(); 
     
    209218} 
    210219 
    211220torrent::Object 
     221apply_ip_filter(const torrent::Object& rawArgs) { 
     222  const torrent::Object::list_type& args = rawArgs.as_list(); 
     223 
     224  std::list<std::string> files; 
     225 
     226  for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) { 
     227    std::string file( itr->as_string() ); 
     228    utils::trim( file ); 
     229    if( access(file.c_str(),F_OK | R_OK) )  
     230      throw torrent::input_error("IpFilter file '" + file + "' does not exist or not readable. Filter could not be loaded"); 
     231    files.push_back( file ); 
     232  } 
     233 
     234  std::stringstream logMsg;  
     235  if( files.empty() ) { 
     236    logMsg << "IpFilter is empty"; 
     237    control->core()->push_log( logMsg.str().c_str() ); 
     238  } 
     239  else { 
     240    core::IpFilter* f = new core::IpFilter(); 
     241    logMsg << "IpFilter is initialized with files: "; 
     242    int entries = 0; 
     243    clock_t time_start = clock(); 
     244    for( std::list<std::string>::iterator itr = files.begin(); itr != files.end(); itr++) { 
     245      std::cout << "Loading IP filters from '" << *itr << "'..."; 
     246      std::cout.flush(); 
     247      if( itr != files.begin() ) 
     248        logMsg << ", "; 
     249      logMsg << *itr; 
     250      int merges = f->add_from_file( *itr ); 
     251      if( merges < 0 ) { 
     252        std::cout << "error" << std::endl; 
     253        std::cout.flush(); 
     254        throw torrent::input_error("IpFilter could not load file '" + *itr + "'"); 
     255      } 
     256      std::cout << "done. Loaded " << (f->size()-entries) << " ranges. " << merges << " ranges were merged." << std::endl; 
     257      std::cout.flush(); 
     258      entries = f->size(); 
     259    } 
     260    control->core()->push_log( logMsg.str().c_str() ); 
     261    std::stringstream logMsg2("IpFilter loaded with ");  
     262    logMsg2 << f->size() << " ranges total. " << f->get_merges() << " ranges were merged."; 
     263    control->core()->push_log( logMsg2.str().c_str() ); 
     264    std::cout << logMsg2.str() << std::endl; 
     265    std::cout << "IP_Filters loaded in " << (double)(clock()-time_start)/CLOCKS_PER_SEC << " seconds" << std::endl; 
     266    std::cout.flush(); 
     267    control->core()->set_ip_filter( f ); 
     268  } 
     269 
     270  return torrent::Object(); 
     271} 
     272 
     273torrent::Object 
    212274apply_tos(const torrent::Object& rawArg) { 
    213275  rpc::Command::value_type value; 
    214276  torrent::ConnectionManager* cm = torrent::connection_manager(); 
     
    492554 
    493555  ADD_VARIABLE_BOOL("peer_exchange", true); 
    494556 
     557  ADD_COMMAND_VOID("reload_ip_filter",          rak::make_mem_fun(control->core(), &core::Manager::reload_ip_filter)); 
     558  ADD_COMMAND_LIST("ip_filter",                 rak::ptr_fn(&apply_ip_filter)); 
     559 
    495560  // Not really network stuff: 
    496561  ADD_VARIABLE_BOOL("handshake_log", false); 
    497562  ADD_VARIABLE_STRING("tracker_dump", ""); 
  • src/core/Makefile.am

    a b  
    3636        view.cc \ 
    3737        view.h \ 
    3838        view_manager.cc \ 
    39         view_manager.h 
     39        view_manager.h \ 
     40        ip_address.cc \ 
     41        ip_address.h \ 
     42        ip_filter.cc \ 
     43        ip_filter.h \ 
     44        ip_range.cc \ 
     45        ip_range.h \ 
     46        printable.h \ 
     47        regex_namespace.h \ 
     48        ip_filter_statics.cc 
    4049 
    4150INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir) 
  • src/core/Makefile.in

    a b  
    6060        manager.$(OBJEXT) poll_manager.$(OBJEXT) \ 
    6161        poll_manager_epoll.$(OBJEXT) poll_manager_kqueue.$(OBJEXT) \ 
    6262        poll_manager_select.$(OBJEXT) view.$(OBJEXT) \ 
    63         view_manager.$(OBJEXT) 
     63        view_manager.$(OBJEXT) \ 
     64        ip_address.$(OBJEXT) \ 
     65        ip_filter.$(OBJEXT) \ 
     66        ip_range.$(OBJEXT) \ 
     67        ip_filter_statics.$(OBJEXT)  
    6468libsub_core_a_OBJECTS = $(am_libsub_core_a_OBJECTS) 
    6569DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) 
    6670depcomp = $(SHELL) $(top_srcdir)/depcomp 
     
    247251        view.cc \ 
    248252        view.h \ 
    249253        view_manager.cc \ 
    250         view_manager.h 
     254        view_manager.h \ 
     255        ip_address.cc \ 
     256        ip_address.h \ 
     257        ip_filter.cc \ 
     258        ip_filter.h \ 
     259        ip_range.cc \ 
     260        ip_range.h \ 
     261        printable.h \ 
     262        regex_namespace.h \ 
     263        ip_filter_statics.cc 
    251264 
    252265INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir) 
    253266all: all-am 
     
    314327@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poll_manager_select.Po@am__quote@ 
    315328@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/view.Po@am__quote@ 
    316329@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/view_manager.Po@am__quote@ 
     330@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ip_address.Po@am__quote@ 
     331@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ip_range.Po@am__quote@ 
     332@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ip_filter_statics.Po@am__quote@ 
    317333 
    318334.cc.o: 
    319335@am__fastdepCXX_TRUE@   $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< 
  • src/core/ip_address.cc

    a b  
     1#include <cstdlib> 
     2#include <string> 
     3#include <arpa/inet.h> 
     4 
     5#include "ip_address.h" 
     6#include "utils/pattern.h" 
     7 
     8namespace core { 
     9 
     10std::pair<bool,uint32_t> IpAddress::to_int( const std::string& address ) { 
     11        uint32_t a; 
     12        int r = inet_pton( AF_INET, address.c_str(), &a); 
     13        if( r ) 
     14                a = ntohl( a ); 
     15        return std::pair<bool,uint32_t>( (r!=0), a ); 
     16} 
     17 
     18std::string IpAddress::to_string() const { 
     19        char buf[128] = ""; 
     20        uint32_t a = htonl( m_address ); 
     21        inet_ntop( AF_INET, &a, buf, sizeof(buf) ); 
     22        return std::string( buf ); 
     23} 
     24 
     25} 
  • src/core/ip_address.h

    a b  
     1#ifndef IPADDRESS_H 
     2#define IPADDRESS_H 
     3 
     4#include <inttypes.h>  
     5#include <string> 
     6 
     7#include "printable.h" 
     8#include "utils/pattern.h" 
     9#include "regex_namespace.h" 
     10 
     11namespace core { 
     12 
     13class IpAddress : public Printable { 
     14        friend class IpRange; 
     15         
     16        private: // constants 
     17                static const std::string        PATTERN_IP_EXPRESSION; 
     18                static const std::string        PATTERN_IP_BYTES_EXPRESSION; 
     19                static const regex::Pattern     PATTERN_IP_BYTES; 
     20 
     21                static const int                GRP_IP_FIRST_BYTE; 
     22                static const int                GRP_IP_BYTES_COUNT; 
     23 
     24        private: // fields 
     25                uint32_t                        m_address; 
     26         
     27        private: // static methods 
     28         
     29        private: // dynamic methods 
     30                IpAddress() : m_address(0) {} 
     31         
     32                void copy( const IpAddress& addr ) { m_address = addr.m_address;} 
     33         
     34        public: // static methods 
     35                static std::pair<bool,uint32_t> to_int( const std::string& strAddress ); 
     36                static IpAddress* parse( const std::string& strAddress ) { 
     37                        std::pair<bool,uint32_t> result = to_int( strAddress ); 
     38                        return ( !result.first ) ? NULL : new IpAddress( result.second ); 
     39                } 
     40         
     41        public: // dynamic methods 
     42                IpAddress( uint32_t address ) : m_address(address) {} 
     43                IpAddress( const IpAddress& addr ) { copy( addr ); } 
     44                IpAddress& operator= ( const IpAddress& addr ) { copy( addr ); return *this; }  
     45 
     46                operator uint32_t() const { return m_address; } 
     47 
     48                bool operator>= ( const IpAddress& ip ) const { return (m_address >=    ip.m_address); } 
     49                bool operator<= ( const IpAddress& ip ) const { return (m_address <=    ip.m_address); } 
     50                bool operator<  ( const IpAddress& ip ) const { return (m_address <     ip.m_address); } 
     51                bool operator>  ( const IpAddress& ip ) const { return (m_address >     ip.m_address); } 
     52                bool operator== ( const IpAddress& ip ) const { return (m_address ==    ip.m_address); } 
     53                bool operator!= ( const IpAddress& ip ) const { return (m_address !=    ip.m_address); } 
     54 
     55                bool operator>= ( uint32_t ip ) const { return (m_address >= ip); } 
     56                bool operator<= ( uint32_t ip ) const { return (m_address <= ip); } 
     57                bool operator<  ( uint32_t ip ) const { return (m_address <  ip); } 
     58                bool operator>  ( uint32_t ip ) const { return (m_address >  ip); } 
     59                bool operator== ( uint32_t ip ) const { return (m_address == ip); } 
     60                bool operator!= ( uint32_t ip ) const { return (m_address != ip); } 
     61 
     62                std::string to_string() const; 
     63        }; 
     64} 
     65#endif 
  • src/core/ip_filter.cc

    a b  
     1#include <sstream> 
     2#include <string> 
     3#include <map> 
     4#include <list> 
     5#include <fstream> 
     6#include <stdio.h> 
     7#include <stdlib.h> 
     8 
     9#include "ip_filter.h" 
     10 
     11namespace core { 
     12 
     13int IpFilter::merge_and_insert( range_map* rs, IpRange* r ) { 
     14        if( !r || !r->get_from() ) 
     15                return 0; 
     16 
     17        std::pair<const IpAddress,IpRange::ptr> p( *r->get_from(), IpRange::ptr(r) ); 
     18        std::pair<range_itr,bool> duo = rs->insert( p ); 
     19 
     20        range_itr idx = duo.first; 
     21        bool wasInserted = duo.second; 
     22        IpRange* curr = NULL; 
     23        int mergeCount = 0; 
     24 
     25        if( !wasInserted ) { // exactly the same start address already exists 
     26                curr = idx->second; 
     27                if( *curr->get_to() < *r->get_to() ) 
     28                        curr->set_to( r->get_to() ); 
     29                delete r; 
     30                r = curr; 
     31                mergeCount++; 
     32        } 
     33        else { 
     34                if( idx != rs->begin() ) { 
     35                        --idx; 
     36                curr = idx->second; // previous 
     37                if( *r->get_from() <= *curr->get_to() ) 
     38                        r = curr; 
     39                else 
     40                        ++idx; 
     41                } 
     42        } 
     43 
     44        if( idx != rs->end() ) 
     45                ++idx; 
     46 
     47        while( idx != rs->end() ) { 
     48                curr = idx->second; 
     49                if( *r->get_to() < *curr->get_from() ) 
     50                        break; 
     51 
     52                std::string d = r->get_description(); 
     53                d += " / " + curr->get_description(); 
     54                r->set_description( d ); 
     55                if( *r->get_to() < *curr->get_to() ) 
     56                        r->set_to( curr->get_to() ); 
     57                rs->erase( idx++ ); 
     58                delete curr; 
     59                mergeCount++; 
     60        } 
     61        return mergeCount; 
     62} 
     63 
     64int IpFilter::add_from_file( const std::string& fileName, range_map* rs, str_list* files ) { 
     65        FILE *f = fopen(fileName.c_str(),"r"); 
     66        int mergeCount = 0; 
     67        if (f==0) return -1; 
     68        char *line = (char *)malloc(64); 
     69        size_t sz=64; 
     70        int charsread = 0; 
     71        int linesread=0; 
     72        while( (charsread=getline(&line,&sz,f)) >=0 ) { 
     73                if( (line[0] == '#' ) || ( charsread <= 1 ) )  
     74                        continue; 
     75                 
     76                IpRange* ir = IpRange::parse( line, charsread ); 
     77                if( !ir || !ir->get_from() || !ir->get_to() ) 
     78                        continue; 
     79 
     80                mergeCount += merge_and_insert( rs, ir ); 
     81        } 
     82        free(line); 
     83        files->push_back( std::string(fileName) ); 
     84        fclose(f); 
     85        m_merges += mergeCount; 
     86        return mergeCount; 
     87} 
     88 
     89int IpFilter::add_from_file( const std::string& fileName ) { 
     90        if( !m_ranges ) 
     91                m_ranges = new range_map(); 
     92        if( !m_loadedFiles ) 
     93                m_loadedFiles = new std::list<std::string>(); 
     94 
     95        return add_from_file( fileName, m_ranges, m_loadedFiles ); 
     96} 
     97 
     98int IpFilter::reload() { 
     99        if( !m_loadedFiles || m_loadedFiles->empty() ) 
     100                return 0; 
     101 
     102        range_map* rs = new range_map(); 
     103        str_list* files = new str_list(); 
     104        int mergeCount = 0; 
     105        for( str_list::const_iterator it = m_loadedFiles->begin(), end = m_loadedFiles->end(); it != end; it++ ) 
     106                mergeCount += add_from_file( *it, rs, files ); 
     107 
     108        range_map* rsOld = m_ranges; 
     109        m_ranges = rs; 
     110        if( rsOld ) { 
     111                clear( rsOld ); 
     112                delete rsOld; 
     113        } 
     114 
     115        str_list* filesOld = m_loadedFiles; 
     116        m_loadedFiles = files; 
     117        if( filesOld ) { 
     118                clear( filesOld ); 
     119                delete filesOld; 
     120        } 
     121 
     122        m_merges = mergeCount; 
     123        return mergeCount; 
     124} 
     125 
     126IpRange* IpFilter::find_range( uint32_t ip ) const { 
     127        if( (ip >= 0) && m_ranges && !m_ranges->empty() ) { 
     128                range_itr idx = m_ranges->upper_bound( ip ); 
     129                if( idx != m_ranges->begin() ) 
     130                        --idx; 
     131                IpRange* curr = idx->second; 
     132                if( curr->includes( ip ) ) 
     133                        return curr; 
     134        } 
     135        return NULL; 
     136} 
     137 
     138std::string IpFilter::to_string() const { 
     139        std::stringstream result; 
     140        if( !m_ranges ) 
     141                result << "NULL" << std::endl; 
     142        else { 
     143                for( range_map::const_iterator it = m_ranges->begin() ; it != m_ranges->end(); it++ ) { 
     144                        const IpAddress a = it->first; 
     145                        IpRange* ir = it->second; 
     146                        result << a << ": " << *ir << std::endl; 
     147                } 
     148        } 
     149        return result.str(); 
     150} 
     151 
     152void IpFilter::clear( range_map* map ) { 
     153        if( map ) { 
     154                for( range_itr i = map->begin(), j = map->end(); i != j; i++ ) 
     155                        delete i->second; 
     156                map->clear(); 
     157        } 
     158} 
     159 
     160void IpFilter::clear( str_list* list ) { 
     161        if( list ) 
     162                list->clear(); 
     163} 
     164 
     165} 
  • src/core/ip_filter.h

    a b  
     1#ifndef IPFILTER_H 
     2#define IPFILTER_H 
     3 
     4#include <string> 
     5#include <map> 
     6#include <list> 
     7 
     8#include "printable.h" 
     9#include "ip_address.h" 
     10#include "ip_range.h" 
     11 
     12namespace core { 
     13 
     14typedef std::map<const IpAddress,IpRange::ptr>  range_map; 
     15typedef range_map::iterator                     range_itr; 
     16typedef std::list<std::string>                  str_list; 
     17 
     18class IpFilter : public Printable { 
     19        private: // fields 
     20                int m_merges; 
     21                range_map* m_ranges; 
     22                str_list* m_loadedFiles; 
     23 
     24        private: // static methods 
     25                static void clear( range_map* map ); 
     26                static void clear( str_list* list ); 
     27 
     28        private: // dynamic methods 
     29                void init_members(void) { // to avoid long constructor lines for every ctor 
     30                        m_ranges = NULL; 
     31                        m_loadedFiles = NULL; 
     32                        m_merges = 0; 
     33                } 
     34                int merge_and_insert( range_map* rs, IpRange* r ); 
     35                int add_from_file( const std::string& fileName, range_map* rs, str_list* files ); 
     36 
     37        public: // static methods 
     38 
     39        public: // dynamic methods 
     40                IpFilter() { init_members(); } 
     41                ~IpFilter() { 
     42                        clear(); 
     43                        if( m_ranges ) delete m_ranges; 
     44                        if( m_loadedFiles ) delete m_loadedFiles; 
     45                        m_ranges = NULL; 
     46                        m_loadedFiles = NULL; 
     47                } 
     48                IpFilter( std::string* files, int size ) { 
     49                        init_members(); 
     50                        for( int i = 0; i < size; i++, files++ ) 
     51                                add_from_file( *files ); 
     52                } 
     53                IpFilter( str_list& files ) { 
     54                        init_members(); 
     55                        for( str_list::const_iterator i = files.begin(), last = files.end(); i != last; i++ ) 
     56                                add_from_file( *i ); 
     57                } 
     58                IpFilter( IpFilter& f ) { 
     59                        init_members(); 
     60                        m_ranges = new range_map( *f.m_ranges ); 
     61                        m_loadedFiles = new str_list( *f.m_loadedFiles ); 
     62                } 
     63 
     64                int reload(); 
     65                int add_from_file( const std::string& fileName ); 
     66                int add_from_file( char* fileName ) { std::string s( fileName ); return add_from_file(s); } 
     67                void clear() { clear( m_ranges ); clear( m_loadedFiles ); } 
     68 
     69                IpRange* find_range( uint32_t ip ) const; 
     70 
     71                bool is_filtered( uint32_t ip ) const { return (find_range( ip ) != NULL); } 
     72                bool is_filtered( std::string ip ) const {  
     73                        static std::pair<bool,uint32_t> ipInt = IpAddress::to_int( ip ); 
     74                        return (!ipInt.first ? false : is_filtered( ipInt.second ));  
     75                } 
     76 
     77                std::string to_string() const; 
     78 
     79                int size(void) { return ( m_ranges ? m_ranges->size() : 0 ); } 
     80                int get_merges(void) { return m_merges; } 
     81                void set_files( str_list& files) { m_loadedFiles = new str_list( files ); } 
     82}; 
     83 
     84} 
     85#endif 
  • src/core/ip_filter_statics.cc

    a b  
     1#include "ip_address.h" 
     2#include "ip_range.h" 
     3#include "utils/pattern.h" 
     4 
     5namespace core { 
     6 
     7const std::string               IpAddress::PATTERN_IP_EXPRESSION                = "(([0-9]{1,3}\\.){3}[0-9]{1,3})"; 
     8const std::string               IpAddress::PATTERN_IP_BYTES_EXPRESSION          = "([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})"; 
     9const regex::Pattern            IpAddress::PATTERN_IP_BYTES                     = PATTERN_IP_BYTES_EXPRESSION; 
     10 
     11const int                       IpAddress::GRP_IP_FIRST_BYTE                    = 1; 
     12const int                       IpAddress::GRP_IP_BYTES_COUNT                   = 4; 
     13 
     14const std::string               IpRange::PATTERN_RANGE_EXPRESSION               = "[[:space:]]*(.*)[[:space:]]*:[[:space:]]*" + IpAddress::PATTERN_IP_EXPRESSION + "[[:space:]]*-[[:space:]]*" + IpAddress::PATTERN_IP_EXPRESSION + "[[:space:]]*"; 
     15const regex::Pattern            IpRange::PATTERN_RANGE                          = PATTERN_RANGE_EXPRESSION; 
     16 
     17const int                       IpRange::GRP_DESCRIPTION                        = 1; 
     18const int                       IpRange::GRP_FIRST_IP                           = 2; 
     19const int                       IpRange::GRP_SECOND_IP                          = 4; 
     20 
     21} 
  • src/core/ip_range.cc

    a b  
     1#include <sstream> 
     2#include <string> 
     3 
     4#include "ip_range.h" 
     5#include "utils/pattern.h" 
     6#include "regex_namespace.h" 
     7 
     8namespace core { 
     9 
     10IpRange* IpRange::parse( const std::string& s ) { 
     11        regex::Match m = PATTERN_RANGE.match( s ); 
     12                 
     13        if( !m.matches() ) { 
     14                std::cout << "!! range format is invalid: '" << s << "'" << std::endl; 
     15                return NULL; 
     16        } 
     17 
     18        std::string     description     = m.group( GRP_DESCRIPTION ); 
     19        std::string     ip1             = m.group( GRP_FIRST_IP ); 
     20        std::string     ip2             = m.group( GRP_SECOND_IP ); 
     21        IpAddress*      from            = IpAddress::parse( ip1 ); 
     22        IpAddress*      to              = IpAddress::parse( ip2 ); 
     23 
     24        if( !from ) { 
     25                std::cout << "!! from is invalid: description='" << description << ", ip1=" << ip1 << ", ip2=" << ip2 << std::endl; 
     26                return NULL; 
     27        } 
     28        if( !to ) { 
     29                std::cout << "!! to is invalid: description='" << description << ", ip1=" << ip1 << ", ip2=" << ip2 << std::endl; 
     30                return NULL; 
     31        } 
     32 
     33//      if( !from || !to || (*to < *from) ) 
     34//              return NULL; 
     35 
     36        IpRange* r = new IpRange(); 
     37 
     38        r->m_description        = description; 
     39        r->m_from               = from; 
     40        r->m_to                 = to; 
     41 
     42        if( to && from && (*to < *from) ) { 
     43                std::cout << "!! to < from: " << r->to_string() << std::endl; 
     44                delete r; 
     45                return NULL; 
     46        } 
     47 
     48        return r; 
     49} 
     50 
     51//fast version 
     52IpRange* IpRange::parse( const char *s, const int size ){ 
     53        static char description[256]; 
     54        static char ip1[24], ip2[24]; 
     55        int pos=0, post=0, enddesc=size-1; 
     56        while (enddesc>0 && s[enddesc]!=':') enddesc--; //find last ':' in the line 
     57        while((pos<enddesc) && (unsigned char)s[pos]<=' ') pos++; // strip from start 
     58        while ((pos<enddesc)){ 
     59          if (post<255) description[post++]=s[pos]; 
     60          pos++; 
     61        }  
     62        description[post]=0; 
     63        if (s[pos]==':') pos++; 
     64          post=0; 
     65          while ((pos<size) && s[pos]!='-'){ 
     66            if (post<23) ip1[post++]=s[pos]; 
     67            pos++; 
     68          }  
     69          ip1[post]=0; 
     70          if (s[pos]=='-'){ 
     71            pos++; 
     72            post=0; 
     73                while ((pos<size) && s[pos]>' '){ 
     74              if (post<23) ip2[post++]=s[pos]; 
     75              pos++; 
     76                } 
     77                ip2[post]=0; 
     78          } else ip2[0]=0; 
     79 
     80        IpAddress*      from            = IpAddress::parse(ip1); 
     81        IpAddress*      to            = IpAddress::parse(ip2); 
     82 
     83        if( !from ) { 
     84                std::cout << "!! from is invalid: description='" << description << ", ip1=" << ip1 << ", ip2=" << ip2 << std::endl; 
     85                return NULL; 
     86        } 
     87        if( !to ) { 
     88                std::cout << "!! to is invalid: description='" << description << ", ip1=" << ip1 << ", ip2=" << ip2 << std::endl; 
     89                return NULL; 
     90        } 
     91 
     92        IpRange* r = new IpRange(); 
     93        r->m_description        = description; 
     94        r->m_from               = from; 
     95        r->m_to                 = to; 
     96 
     97        if( (*to < *from) ) { 
     98                std::cout << "!! to < from: " << r->to_string() << std::endl; 
     99                delete r; 
     100                return NULL; 
     101        } 
     102         
     103        return r; 
     104} 
     105 
     106std::string IpRange::to_string() const { 
     107        std::stringstream result; 
     108        result << m_description << ": [" << m_from->to_string() << " - " << m_to->to_string() << ']'; 
     109        return result.str(); 
     110} 
     111 
     112} 
  • src/core/ip_range.h

    a b  
     1#ifndef IPRANGE_H 
     2#define IPRANGE_H 
     3 
     4#include <string> 
     5 
     6#include "printable.h" 
     7#include "ip_address.h" 
     8#include "utils/pattern.h" 
     9#include "regex_namespace.h" 
     10 
     11namespace core { 
     12 
     13class IpRange : public Printable { 
     14        public: // constants 
     15                static const std::string        PATTERN_RANGE_EXPRESSION; 
     16                static const regex::Pattern     PATTERN_RANGE; 
     17 
     18                static const int                        GRP_DESCRIPTION; 
     19                static const int                        GRP_FIRST_IP; 
     20                static const int                        GRP_SECOND_IP; 
     21 
     22        private: // fields 
     23                std::string                                     m_description; 
     24                const IpAddress*                        m_from; 
     25                const IpAddress*                        m_to; 
     26 
     27        private: // dynamic methods 
     28                IpRange() : m_description(), m_from(NULL), m_to(NULL) {} 
     29         
     30        public: // static methods 
     31                typedef IpRange* ptr; 
     32                static IpRange* parse( const std::string& s ); 
     33                static IpRange* parse( const char *s, const int size ); 
     34         
     35        public: // dynamic methods 
     36                IpRange( IpRange& rng ) { copy(rng); } 
     37                IpRange& operator= ( IpRange& rng ) { copy(rng); return *this; } 
     38         
     39                void copy( IpRange& rng ) { 
     40                        m_description = rng.m_description; 
     41                        m_from = (!rng.m_from) ? NULL : new IpAddress( *rng.m_from ); 
     42                        m_to = (!rng.m_to) ? NULL : new IpAddress( *rng.m_to ); 
     43                } 
     44         
     45                const std::string&      get_description ( void ) const  { return m_description; } 
     46                const IpAddress*        get_from        ( void ) const  { return m_from; } 
     47                const IpAddress*        get_to          ( void ) const  { return m_to; } 
     48                 
     49                void    set_description ( const std::string&    description )   { m_description = description; } 
     50                void    set_from        ( const IpAddress*      from )          { if( m_from ) delete m_from; m_from = new IpAddress( *from ); } 
     51                void    set_to          ( const IpAddress*      to )            { if( m_to ) delete m_to; m_to = new IpAddress( *to ); } 
     52                 
     53                bool    includes( const IpAddress& ip ) const { return includes((uint32_t)ip); } 
     54                bool    includes( uint32_t ip ) const { return (*m_from <= ip) && (*m_to >= ip); } 
     55                 
     56                ~IpRange() { 
     57                        delete m_from; 
     58                        m_from = NULL; 
     59                        delete m_to; 
     60                        m_to = NULL; 
     61                } 
     62 
     63        std::string to_string() const; 
     64}; 
     65 
     66} 
     67#endif 
  • src/core/manager.cc

    a b  
    3939#include <cstdio> 
    4040#include <cstring> 
    4141#include <fstream> 
     42#include <sstream> 
    4243#include <unistd.h> 
    4344#include <sys/select.h> 
    4445#include <rak/address_info.h> 
     
    151152  } 
    152153} 
    153154 
     155uint32_t 
     156Manager::filter_ip(const sockaddr* sa) { 
     157  IpRange* r = NULL; 
     158  // if something's wrong with filter or address it's gonna be allowed 
     159  if( m_ipFilter && sa ) { 
     160    const rak::socket_address* socketAddress = rak::socket_address::cast_from(sa); 
     161    if( socketAddress->is_valid() && (socketAddress->family() == rak::socket_address::af_inet) ) 
     162      r = m_ipFilter->find_range( socketAddress->sa_inet()->address_h() ); 
     163    if( r ) 
     164      m_logComplete.push_front("Address '" + socketAddress->address_str() + "' is rejected by IP filter range '" + r->to_string()); 
     165    else 
     166    if( rpc::call_command_value("get_handshake_log") ) 
     167      m_logComplete.push_front("IP Filter allowed connection with '" + socketAddress->address_str() + "'"); 
     168  } 
     169  return (r==NULL); 
     170} 
     171 
     172 
    154173void 
    155174Manager::push_log(const char* msg) { 
    156175  m_logImportant.push_front(msg); 
     
    158158} 
    159159 
    160160Manager::Manager() : 
    161   m_hashingView(NULL) 
     161  m_hashingView(NULL), 
     162  m_ipFilter(NULL) 
    162163//   m_pollManager(NULL) { 
    163164{ 
    164165  m_downloadStore   = new DownloadStore(); 
     
    180199  delete m_downloadStore; 
    181200  delete m_httpQueue; 
    182201  delete m_fileStatusCache; 
     202 
     203  set_ip_filter( NULL ); 
    183204} 
    184205 
    185206void 
     
    259280  CurlStack::global_init(); 
    260281 
    261282  torrent::connection_manager()->set_signal_handshake_log(sigc::mem_fun(this, &Manager::handshake_log)); 
     283  torrent::connection_manager()->set_filter(sigc::mem_fun(this, &Manager::filter_ip)); 
    262284} 
    263285 
    264286void 
     
    593615  } 
    594616} 
    595617 
     618void Manager::reload_ip_filter(void) { 
     619  if( m_ipFilter ) { 
     620    push_log("Reloading IP filter"); 
     621    m_ipFilter->reload(); 
     622    std::stringstream logMsg("IpFilter reloaded with ");  
     623    logMsg << m_ipFilter->size() << " ranges total. " << m_ipFilter->get_merges() << " ranges were merged."; 
     624    push_log( logMsg.str().c_str() ); 
     625} 
     626} 
    596627} 
  • src/core/manager.h

    a b  
    4747#include "range_map.h" 
    4848#include "log.h" 
    4949 
     50#include "ip_filter.h" 
     51 
    5052namespace torrent { 
    5153  class Bencode; 
    5254} 
     
    120122 
    121123  void                handshake_log(const sockaddr* sa, int msg, int err, const torrent::HashString* hash); 
    122124 
     125  uint32_t            filter_ip(const sockaddr* sa); 
     126 
     127  void                set_ip_filter( IpFilter* ipFilter ) { 
     128                        IpFilter* old = m_ipFilter; 
     129                        m_ipFilter = ipFilter; 
     130                        if( old ) delete old; 
     131                      } 
     132  void                reload_ip_filter(void); 
     133 
    123134  static const int create_start    = 0x1; 
    124135  static const int create_tied     = 0x2; 
    125136  static const int create_quiet    = 0x4; 
     
    156167  PollManager*        m_pollManager; 
    157168  Log                 m_logImportant; 
    158169  Log                 m_logComplete; 
     170 
     171  IpFilter*           m_ipFilter; 
    159172}; 
    160173 
    161174// Meh, cleanup. 
  • src/core/printable.h

    a b  
     1#ifndef PRINTABLE_H 
     2#define PRINTABLE_H 
     3 
     4#include <iostream> 
     5 
     6class Printable { 
     7        public: 
     8                virtual std::string to_string() const = 0; 
     9}; 
     10 
     11template<typename _CharT,class _Traits> inline std::basic_ostream<_CharT,_Traits>& 
     12        operator<<( std::basic_ostream<_CharT,_Traits>& out, const Printable& val) { 
     13        return out << val.to_string(); 
     14} 
     15 
     16#endif 
  • src/core/regex_namespace.h

    a b  
     1#ifndef REGEXNAMESPACE_H 
     2#define REGEXNAMESPACE_H 
     3 
     4namespace regex = utils; 
     5 
     6#endif 
  • src/utils/Makefile.am

    a b  
    99        lockfile.cc \ 
    1010        lockfile.h \ 
    1111        socket_fd.cc \ 
    12         socket_fd.h 
     12        socket_fd.h \ 
     13        pattern.cc \ 
     14        pattern.h 
    1315 
    1416INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir) 
  • src/utils/Makefile.in

    a b  
    5555libsub_utils_a_LIBADD = 
    5656am_libsub_utils_a_OBJECTS = directory.$(OBJEXT) \ 
    5757        file_status_cache.$(OBJEXT) lockfile.$(OBJEXT) \ 
    58         socket_fd.$(OBJEXT) 
     58        socket_fd.$(OBJEXT) pattern.$(OBJEXT) 
    5959libsub_utils_a_OBJECTS = $(am_libsub_utils_a_OBJECTS) 
    6060DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) 
    6161depcomp = $(SHELL) $(top_srcdir)/depcomp 
     
    215215        lockfile.cc \ 
    216216        lockfile.h \ 
    217217        socket_fd.cc \ 
    218         socket_fd.h 
     218        socket_fd.h \ 
     219        pattern.cc \ 
     220        pattern.h 
    219221 
    220222INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir) 
    221223all: all-am 
     
    269271@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_status_cache.Po@am__quote@ 
    270272@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lockfile.Po@am__quote@ 
    271273@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_fd.Po@am__quote@ 
     274@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pattern.@am__quote@ 
    272275 
    273276.cc.o: 
    274277@am__fastdepCXX_TRUE@   $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< 
  • src/utils/pattern.cc

    a b  
     1#include <string> 
     2#include <sys/types.h> 
     3#include <ctype.h> 
     4#include <regex.h> 
     5 
     6#include "pattern.h" 
     7 
     8namespace utils { 
     9 
     10int Pattern::countGroups( const std::string& str ) { 
     11        int count1 = 0; 
     12        int count2 = 0; 
     13 
     14        for( size_t index = -1; (index = str.find( '(', index+1 )) != std::string::npos;  ) 
     15                count1++; 
     16        for( size_t index = -1; (index = str.find( ')', index+1 )) != std::string::npos;  ) 
     17                count2++; 
     18 
     19        return (count1 < count2) ? count1 : count2; 
     20} 
     21 
     22Pattern::Pattern( const std::string& pattern, Flags flags ) :   lastResult(-1), 
     23                                                                preg(NULL) { 
     24        int regFlags = REG_EXTENDED | REG_ICASE | REG_NEWLINE; 
     25        if( !(flags & CASE_SENSITIVE) ) 
     26                regFlags ^= REG_ICASE; 
     27        if( (flags & DOT_MATCH_NEWLINE) ) 
     28                regFlags ^= REG_NEWLINE; 
     29 
     30        preg = new regex_t; 
     31        numGroups = countGroups( pattern ) + 1; 
     32 
     33        lastResult = regcomp( preg, pattern.c_str(), regFlags ); 
     34} 
     35 
     36Pattern::~Pattern() { 
     37        regfree( preg ); 
     38        delete( preg ); 
     39} 
     40 
     41std::string Pattern::getLastError() const { 
     42        char errBuf[1024]; 
     43        regerror( lastResult, preg, errBuf, sizeof(errBuf) ); 
     44        return std::string(errBuf); 
     45} 
     46 
     47Match Pattern::match( const std::string& expression ) const { 
     48 
     49        regmatch_t* pmatch = new regmatch_t[numGroups]; 
     50        int res = regexec( preg, expression.c_str(), numGroups, pmatch, 0 ); 
     51        return Match( expression, numGroups, pmatch, res, getLastError() ); 
     52} 
     53 
     54Match::Match( const std::string& expr, int ngroups, regmatch_t* groups, int result, const std::string& message ) :  
     55        expression( expr ),  
     56        nmatch( ngroups ),  
     57        pmatch( groups ), 
     58        matchResult( result ), 
     59        matchMessage( message ) { 
     60} 
     61 
     62std::string Match::group( int i ) { 
     63        if( (i >= nmatch) || (pmatch[i].rm_so < 0) ) 
     64                return ""; 
     65 
     66        return expression.substr( pmatch[i].rm_so, pmatch[i].rm_eo - pmatch[i].rm_so ); 
     67} 
     68 
     69std::string& trim( std::string& str ) { 
     70        std::string::iterator it; 
     71        for( it = str.begin(); (it < str.end()) && ( isspace(*it) || (*it == 0) ) ; it++ ); 
     72        str.erase( str.begin(), it ); 
     73        for( it = str.end()-1; (it >= str.begin()) && ( isspace(*it) || (*it == 0) ) ; it-- ); 
     74        str.erase( ++it, str.end() ); 
     75        return str; 
     76} 
     77 
     78} 
     79 
  • src/utils/pattern.h

    a b  
     1#ifndef PATTERN_H 
     2#define PATTERN_H 
     3 
     4#include <string> 
     5#include <sys/types.h> 
     6#include <ctype.h> 
     7#include <regex.h> 
     8 
     9namespace utils { 
     10 
     11class Match { 
     12        public: 
     13                Match( const std::string& expr, int ngroups, regmatch_t* pmatch, int matchResult, const std::string& matchMessage ); 
     14                ~Match() { delete[] pmatch; } 
     15                std::string group( int i ); 
     16                bool found() { return (matchResult == 0); } 
     17                bool matches() { return found(); } 
     18                std::string& getMatchMessage() { return matchMessage; } 
     19 
     20        private: 
     21                std::string     expression; 
     22                int             nmatch; 
     23                regmatch_t*     pmatch; 
     24                int             matchResult; 
     25                std::string     matchMessage; 
     26}; 
     27 
     28class Pattern { 
     29        public: 
     30                enum Flags { 
     31                        DEFAULT = 0,            // REG_EXTENDED | REG_ICASE | REG_NEWLINE 
     32                        CASE_SENSITIVE, 
     33                        DOT_MATCH_NEWLINE 
     34                }; 
     35 
     36        public: 
     37                Pattern( const std::string& pattern, Flags f = Pattern::DEFAULT ); 
     38                ~Pattern(); 
     39                bool isSuccess() { return (lastResult == 0); } 
     40                std::string getLastError() const; 
     41                Match match( const std::string& expression ) const; 
     42 
     43        private: 
     44                int countGroups( const std::string& str ); 
     45 
     46        private: 
     47                regex_t*        preg; 
     48                int             lastResult; 
     49                int             numGroups; 
     50}; 
     51 
     52 
     53std::string& trim( std::string& str ); 
     54 
     55} 
     56 
     57// end of ifdef PATTERN_H 
     58#endif 
     59