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