Ticket #239: fixed-rtorrent-0.8.7-ip_filter_no_boost-fast-bsd2.patch

File fixed-rtorrent-0.8.7-ip_filter_no_boost-fast-bsd2.patch, 32.3 KB (added by jcuzella@lyraphase.com, 17 months ago)

A working patch for version 0.8.7

  • configure.ac

    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>
    Adapted for rtorrent-0.8.7 by James Cuzella <james.cuzella@lyraphase.com>
    Rev.2 (BSD/MacOSX support provided)
    
    See http://libtorrent.rakshasa.no/ticket/239 for more details.
    
    a b  
    44AM_CONFIG_HEADER(config.h) 
    55AM_PATH_CPPUNIT(1.9.6) 
    66 
     7AC_CHECK_FUNCS(getline) 
    78AC_PROG_CXX 
    89AC_PROG_LIBTOOL 
    910 
  • src/command_network.cc

    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> 
     
    6166#include "control.h" 
    6267#include "command_helpers.h" 
    6368 
     69#include "utils/pattern.h"  
     70#include "core/ip_filter.h" 
     71 
     72 
    6473torrent::Object 
    6574apply_throttle(const torrent::Object::list_type& args, bool up) { 
    6675  torrent::Object::list_const_iterator argItr = args.begin(); 
     
    202211  return torrent::Object(); 
    203212} 
    204213 
     214 torrent::Object 
     215apply_ip_filter(const torrent::Object::list_type& args) { 
     216 
     217  std::list<std::string> files; 
     218 
     219  for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) { 
     220    std::string file( itr->as_string() ); 
     221    utils::trim( file ); 
     222    if( access(file.c_str(),F_OK | R_OK) )  
     223      throw torrent::input_error("IpFilter file '" + file + "' does not exist or not readable. Filter could not be loaded"); 
     224    files.push_back( file ); 
     225  } 
     226 
     227  std::stringstream logMsg;  
     228  if( files.empty() ) { 
     229    logMsg << "IpFilter is empty"; 
     230    control->core()->push_log( logMsg.str().c_str() ); 
     231  } 
     232  else { 
     233    core::IpFilter* f = new core::IpFilter(); 
     234    logMsg << "IpFilter is initialized with files: "; 
     235    int entries = 0; 
     236    clock_t time_start = clock(); 
     237    for( std::list<std::string>::iterator itr = files.begin(); itr != files.end(); itr++) { 
     238      std::cout << "Loading IP filters from '" << *itr << "'..."; 
     239      std::cout.flush(); 
     240      if( itr != files.begin() ) 
     241        logMsg << ", "; 
     242      logMsg << *itr; 
     243      int merges = f->add_from_file( *itr ); 
     244      if( merges < 0 ) { 
     245        std::cout << "error" << std::endl; 
     246        std::cout.flush(); 
     247        throw torrent::input_error("IpFilter could not load file '" + *itr + "'"); 
     248      } 
     249      std::cout << "done. Loaded " << (f->size()-entries) << " ranges. " << merges << " ranges were merged." << std::endl; 
     250      std::cout.flush(); 
     251      entries = f->size(); 
     252    } 
     253    control->core()->push_log( logMsg.str().c_str() ); 
     254    std::stringstream logMsg2("IpFilter loaded with ");  
     255    logMsg2 << f->size() << " ranges total. " << f->get_merges() << " ranges were merged."; 
     256    control->core()->push_log( logMsg2.str().c_str() ); 
     257    std::cout << logMsg2.str() << std::endl; 
     258    std::cout << "IP_Filters loaded in " << (double)(clock()-time_start)/CLOCKS_PER_SEC << " seconds" << std::endl; 
     259    std::cout.flush(); 
     260    control->core()->set_ip_filter( f ); 
     261  } 
     262 
     263  return torrent::Object(); 
     264} 
     265 
    205266torrent::Object 
    206267apply_tos(const torrent::Object::string_type& arg) { 
    207268  rpc::command_base::value_type value; 
     
    417478  torrent::FileManager* fileManager = torrent::file_manager(); 
    418479  core::CurlStack* httpStack = control->core()->http_stack(); 
    419480 
     481  CMD2_ANY_V       ("reload_ip_filter", std::tr1::bind(&core::Manager::reload_ip_filter, control->core())); 
     482  CMD2_ANY_LIST    ("ip_filter",        std::tr1::bind(&apply_ip_filter, std::tr1::placeholders::_2)); 
     483 
     484   
    420485  CMD2_VAR_BOOL    ("log.handshake", false); 
    421486  CMD2_VAR_STRING  ("log.tracker",   ""); 
    422487 
  • src/core/getline.cc

    a b  
     1#include <string> 
     2#include <stdio.h> 
     3#include <stdlib.h> 
     4#include <sys/types.h> 
     5#include <sys/stat.h> 
     6#include <limits.h> 
     7#include <errno.h> 
     8 
     9namespace core { 
     10 
     11/* getline.c ---  Implementation of replacement getline function. 
     12   Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005 Free 
     13   Software Foundation, Inc. 
     14 
     15/* Ported from glibc by Simon Josefsson. */ 
     16 
     17#ifndef SIZE_MAX 
     18# define SIZE_MAX ((size_t) -1) 
     19#endif 
     20#ifndef SSIZE_MAX 
     21# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) 
     22#endif 
     23#if !HAVE_FLOCKFILE 
     24# undef flockfile 
     25# define flockfile(x) ((void) 0) 
     26#endif 
     27#if !HAVE_FUNLOCKFILE 
     28# undef funlockfile 
     29# define funlockfile(x) ((void) 0) 
     30#endif 
     31 
     32/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and 
     33   NUL-terminate it).  *LINEPTR is a pointer returned from malloc (or 
     34   NULL), pointing to *N characters of space.  It is realloc'ed as 
     35   necessary.  Returns the number of characters read (not including 
     36   the null terminator), or -1 on error or EOF.  */ 
     37 
     38ssize_t getline (char **lineptr, size_t *n, FILE *fp) 
     39{ 
     40  ssize_t result; 
     41  size_t cur_len = 0; 
     42 
     43  if (lineptr == NULL || n == NULL || fp == NULL) 
     44    { 
     45      errno = EINVAL; 
     46      return -1; 
     47    } 
     48 
     49  flockfile (fp); 
     50 
     51  if (*lineptr == NULL || *n == 0) 
     52    { 
     53      *n = 120; 
     54      *lineptr = (char *) malloc (*n); 
     55      if (*lineptr == NULL) 
     56{ 
     57  result = -1; 
     58  goto unlock_return; 
     59} 
     60    } 
     61 
     62  for (;;) 
     63    { 
     64      int i; 
     65 
     66      i = getc (fp); 
     67      if (i == EOF) 
     68{ 
     69  result = -1; 
     70  break; 
     71} 
     72 
     73      /* Make enough space for len+1 (for final NUL) bytes.  */ 
     74      if (cur_len + 1 >= *n) 
     75{ 
     76  size_t needed_max = 
     77    SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX; 
     78  size_t needed = 2 * *n + 1;   /* Be generous. */ 
     79  char *new_lineptr; 
     80 
     81  if (needed_max < needed) 
     82    needed = needed_max; 
     83  if (cur_len + 1 >= needed) 
     84    { 
     85      result = -1; 
     86      goto unlock_return; 
     87    } 
     88 
     89  new_lineptr = (char *) realloc (*lineptr, needed); 
     90  if (new_lineptr == NULL) 
     91    { 
     92      result = -1; 
     93 
     94 
     95 
     96      goto unlock_return; 
     97    } 
     98 
     99  *lineptr = new_lineptr; 
     100  *n = needed; 
     101} 
     102 
     103      (*lineptr)[cur_len] = i; 
     104      cur_len++; 
     105 
     106      if (i == '\n') 
     107break; 
     108    } 
     109  (*lineptr)[cur_len] = '\0'; 
     110  result = cur_len ? cur_len : result; 
     111 
     112 unlock_return: 
     113  funlockfile (fp); 
     114  return result; 
     115} 
     116 
     117} 
  • src/core/getline.h

    a b  
     1#include <string> 
     2#include <stdio.h> 
     3#include <stdlib.h> 
     4#include <sys/types.h> 
     5#include <sys/stat.h> 
     6#include <limits.h> 
     7#include <errno.h> 
     8 
     9namespace core { 
     10 
     11/* getline.c ---  Implementation of replacement getline function. 
     12   Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005 Free 
     13   Software Foundation, Inc. 
     14 
     15/* Ported from glibc by Simon Josefsson. */ 
     16 
     17/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and 
     18   NUL-terminate it).  *LINEPTR is a pointer returned from malloc (or 
     19   NULL), pointing to *N characters of space.  It is realloc'ed as 
     20   necessary.  Returns the number of characters read (not including 
     21   the null terminator), or -1 on error or EOF.  */ 
     22 
     23ssize_t getline (char **lineptr, size_t *n, FILE *fp); 
     24 
     25} 
  • 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#ifdef HAVE_CONFIG_H 
     10#include <config.h> 
     11#endif 
     12 
     13#ifndef __linux__ 
     14#ifndef HAVE_GETLINE 
     15#include "getline.h" 
     16#endif 
     17#endif 
     18 
     19#include "ip_filter.h" 
     20 
     21namespace core { 
     22 
     23int IpFilter::merge_and_insert( range_map* rs, IpRange* r ) { 
     24        if( !r || !r->get_from() ) 
     25                return 0; 
     26 
     27        std::pair<const IpAddress,IpRange::ptr> p( *r->get_from(), IpRange::ptr(r) ); 
     28        std::pair<range_itr,bool> duo = rs->insert( p ); 
     29 
     30        range_itr idx = duo.first; 
     31        bool wasInserted = duo.second; 
     32        IpRange* curr = NULL; 
     33        int mergeCount = 0; 
     34 
     35        if( !wasInserted ) { // exactly the same start address already exists 
     36                curr = idx->second; 
     37                if( *curr->get_to() < *r->get_to() ) 
     38                        curr->set_to( r->get_to() ); 
     39                delete r; 
     40                r = curr; 
     41                mergeCount++; 
     42        } 
     43        else { 
     44                if( idx != rs->begin() ) { 
     45                        --idx; 
     46                curr = idx->second; // previous 
     47                if( *r->get_from() <= *curr->get_to() ) 
     48                        r = curr; 
     49                else 
     50                        ++idx; 
     51                } 
     52        } 
     53 
     54        if( idx != rs->end() ) 
     55                ++idx; 
     56 
     57        while( idx != rs->end() ) { 
     58                curr = idx->second; 
     59                if( *r->get_to() < *curr->get_from() ) 
     60                        break; 
     61 
     62                std::string d = r->get_description(); 
     63                d += " / " + curr->get_description(); 
     64                r->set_description( d ); 
     65                if( *r->get_to() < *curr->get_to() ) 
     66                        r->set_to( curr->get_to() ); 
     67                rs->erase( idx++ ); 
     68                delete curr; 
     69                mergeCount++; 
     70        } 
     71        return mergeCount; 
     72} 
     73 
     74int IpFilter::add_from_file( const std::string& fileName, range_map* rs, str_list* files ) { 
     75        FILE *f = fopen(fileName.c_str(),"r"); 
     76        int mergeCount = 0; 
     77        if (f==0) return -1; 
     78        char *line = (char *)malloc(64); 
     79        size_t sz=64; 
     80        int charsread = 0; 
     81        int linesread=0; 
     82        while( (charsread=getline(&line,&sz,f)) >=0 ) { 
     83                if( (line[0] == '#' ) || ( charsread <= 1 ) )  
     84                        continue; 
     85                 
     86                IpRange* ir = IpRange::parse( line, charsread ); 
     87                if( !ir || !ir->get_from() || !ir->get_to() ) 
     88                        continue; 
     89 
     90                mergeCount += merge_and_insert( rs, ir ); 
     91        } 
     92        free(line); 
     93        files->push_back( std::string(fileName) ); 
     94        fclose(f); 
     95        m_merges += mergeCount; 
     96        return mergeCount; 
     97} 
     98 
     99int IpFilter::add_from_file( const std::string& fileName ) { 
     100        if( !m_ranges ) 
     101                m_ranges = new range_map(); 
     102        if( !m_loadedFiles ) 
     103                m_loadedFiles = new std::list<std::string>(); 
     104 
     105        return add_from_file( fileName, m_ranges, m_loadedFiles ); 
     106} 
     107 
     108int IpFilter::reload() { 
     109        if( !m_loadedFiles || m_loadedFiles->empty() ) 
     110                return 0; 
     111 
     112        range_map* rs = new range_map(); 
     113        str_list* files = new str_list(); 
     114        int mergeCount = 0; 
     115        for( str_list::const_iterator it = m_loadedFiles->begin(), end = m_loadedFiles->end(); it != end; it++ ) 
     116                mergeCount += add_from_file( *it, rs, files ); 
     117 
     118        range_map* rsOld = m_ranges; 
     119        m_ranges = rs; 
     120        if( rsOld ) { 
     121                clear( rsOld ); 
     122                delete rsOld; 
     123        } 
     124 
     125        str_list* filesOld = m_loadedFiles; 
     126        m_loadedFiles = files; 
     127        if( filesOld ) { 
     128                clear( filesOld ); 
     129                delete filesOld; 
     130        } 
     131 
     132        m_merges = mergeCount; 
     133        return mergeCount; 
     134} 
     135 
     136IpRange* IpFilter::find_range( uint32_t ip ) const { 
     137        if( (ip >= 0) && m_ranges && !m_ranges->empty() ) { 
     138                range_itr idx = m_ranges->upper_bound( ip ); 
     139                if( idx != m_ranges->begin() ) 
     140                        --idx; 
     141                IpRange* curr = idx->second; 
     142                if( curr->includes( ip ) ) 
     143                        return curr; 
     144        } 
     145        return NULL; 
     146} 
     147 
     148std::string IpFilter::to_string() const { 
     149        std::stringstream result; 
     150        if( !m_ranges ) 
     151                result << "NULL" << std::endl; 
     152        else { 
     153                for( range_map::const_iterator it = m_ranges->begin() ; it != m_ranges->end(); it++ ) { 
     154                        const IpAddress a = it->first; 
     155                        IpRange* ir = it->second; 
     156                        result << a << ": " << *ir << std::endl; 
     157                } 
     158        } 
     159        return result.str(); 
     160} 
     161 
     162void IpFilter::clear( range_map* map ) { 
     163        if( map ) { 
     164                for( range_itr i = map->begin(), j = map->end(); i != j; i++ ) 
     165                        delete i->second; 
     166                map->clear(); 
     167        } 
     168} 
     169 
     170void IpFilter::clear( str_list* list ) { 
     171        if( list ) 
     172                list->clear(); 
     173} 
     174 
     175} 
  • 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/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 \ 
     49        getline.h \ 
     50        getline.cc 
    4051 
    4152INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir) 
  • src/core/Makefile.in

    a b  
    6363        manager.$(OBJEXT) poll_manager.$(OBJEXT) \ 
    6464        poll_manager_epoll.$(OBJEXT) poll_manager_kqueue.$(OBJEXT) \ 
    6565        poll_manager_select.$(OBJEXT) view.$(OBJEXT) \ 
    66         view_manager.$(OBJEXT) 
     66        view_manager.$(OBJEXT) \ 
     67        ip_address.$(OBJEXT) \ 
     68        ip_filter.$(OBJEXT) \ 
     69        ip_range.$(OBJEXT) \ 
     70        ip_filter_statics.$(OBJEXT) \ 
     71        getline.$(OBJEXT) 
    6772libsub_core_a_OBJECTS = $(am_libsub_core_a_OBJECTS) 
    6873DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) 
    6974depcomp = $(SHELL) $(top_srcdir)/depcomp 
     
    256261        view.cc \ 
    257262        view.h \ 
    258263        view_manager.cc \ 
    259         view_manager.h 
     264        view_manager.h \ 
     265        ip_address.cc \ 
     266        ip_address.h \ 
     267        ip_filter.cc \ 
     268        ip_filter.h \ 
     269        ip_range.cc \ 
     270        ip_range.h \ 
     271        printable.h \ 
     272        regex_namespace.h \ 
     273        ip_filter_statics.cc \ 
     274        getline.cc \ 
     275        getline.h 
    260276 
    261277INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir) 
    262278all: all-am 
     
    324340@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poll_manager_select.Po@am__quote@ 
    325341@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/view.Po@am__quote@ 
    326342@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/view_manager.Po@am__quote@ 
     343@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ip_address.Po@am__quote@ 
     344@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ip_range.Po@am__quote@ 
     345@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ip_filter_statics.Po@am__quote@   
     346@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getline.Po@am__quote@ 
    327347 
    328348.cc.o: 
    329349@am__fastdepCXX_TRUE@   $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< 
  • src/core/manager.cc

    a b  
    153153  } 
    154154} 
    155155 
     156uint32_t 
     157Manager::filter_ip(const sockaddr* sa) { 
     158  IpRange* r = NULL; 
     159  // if something's wrong with filter or address it's gonna be allowed 
     160  if( m_ipFilter && sa ) { 
     161    const rak::socket_address* socketAddress = rak::socket_address::cast_from(sa); 
     162    if( socketAddress->is_valid() && (socketAddress->family() == rak::socket_address::af_inet) ) 
     163      r = m_ipFilter->find_range( socketAddress->sa_inet()->address_h() ); 
     164    if( r ) 
     165      m_logComplete.push_front("Address '" + socketAddress->address_str() + "' is rejected by IP filter range '" + r->to_string()); 
     166    else 
     167    if( rpc::call_command_value("get_handshake_log") ) 
     168      m_logComplete.push_front("IP Filter allowed connection with '" + socketAddress->address_str() + "'"); 
     169  } 
     170  return (r==NULL); 
     171} 
     172 
     173 
    156174void 
    157175Manager::push_log(const char* msg) { 
    158176  m_logImportant.push_front(msg); 
     
    160178} 
    161179 
    162180Manager::Manager() : 
    163   m_hashingView(NULL) 
     181  m_hashingView(NULL), 
     182  m_ipFilter(NULL) 
    164183//   m_pollManager(NULL) { 
    165184{ 
    166185  m_downloadStore   = new DownloadStore(); 
     
    181200  delete m_downloadStore; 
    182201  delete m_httpQueue; 
    183202  delete m_fileStatusCache; 
     203 
     204  set_ip_filter( NULL ); 
    184205} 
    185206 
    186207void 
     
    226247  CurlStack::global_init(); 
    227248 
    228249  torrent::connection_manager()->set_signal_handshake_log(sigc::mem_fun(this, &Manager::handshake_log)); 
     250  torrent::connection_manager()->set_filter(sigc::mem_fun(this, &Manager::filter_ip)); 
    229251} 
    230252 
    231253void 
     
    585607  } 
    586608} 
    587609 
     610void Manager::reload_ip_filter(void) { 
     611  if( m_ipFilter ) { 
     612    push_log("Reloading IP filter"); 
     613    m_ipFilter->reload(); 
     614    std::stringstream logMsg("IpFilter reloaded with ");  
     615    logMsg << m_ipFilter->size() << " ranges total. " << m_ipFilter->get_merges() << " ranges were merged."; 
     616    push_log( logMsg.str().c_str() ); 
     617  } 
     618} 
     619 
    588620} 
  • 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} 
     
    118120 
    119121  void                handshake_log(const sockaddr* sa, int msg, int err, const torrent::HashString* hash); 
    120122 
     123  uint32_t            filter_ip(const sockaddr* sa); 
     124 
     125  void                set_ip_filter( IpFilter* ipFilter ) { 
     126                        IpFilter* old = m_ipFilter; 
     127                        m_ipFilter = ipFilter; 
     128                        if( old ) delete old; 
     129                      } 
     130  void                reload_ip_filter(void); 
     131 
    121132  static const int create_start    = 0x1; 
    122133  static const int create_tied     = 0x2; 
    123134  static const int create_quiet    = 0x4; 
     
    154165 
    155166  Log                 m_logImportant; 
    156167  Log                 m_logComplete; 
     168 
     169  IpFilter*           m_ipFilter; 
    157170}; 
    158171 
    159172// 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  
    5858libsub_utils_a_LIBADD = 
    5959am_libsub_utils_a_OBJECTS = directory.$(OBJEXT) \ 
    6060        file_status_cache.$(OBJEXT) lockfile.$(OBJEXT) \ 
    61         socket_fd.$(OBJEXT) 
     61        socket_fd.$(OBJEXT) pattern.$(OBJEXT) 
    6262libsub_utils_a_OBJECTS = $(am_libsub_utils_a_OBJECTS) 
    6363DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) 
    6464depcomp = $(SHELL) $(top_srcdir)/depcomp 
     
    224224        lockfile.cc \ 
    225225        lockfile.h \ 
    226226        socket_fd.cc \ 
    227         socket_fd.h 
     227        socket_fd.h \ 
     228        pattern.cc \ 
     229        pattern.h 
    228230 
    229231INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir) 
    230232all: all-am 
     
    279281@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_status_cache.Po@am__quote@ 
    280282@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lockfile.Po@am__quote@ 
    281283@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_fd.Po@am__quote@ 
     284@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pattern.Po@am__quote@ 
    282285 
    283286.cc.o: 
    284287@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