Line 0
Link Here
|
|
|
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 |
|
21 |
namespace core { |
22 |
|
23 |
int 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 |
|
74 |
int 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 |
|
99 |
int 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 |
|
108 |
int 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 |
|
136 |
IpRange* 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 |
|
148 |
std::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 |
|
162 |
void 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 |
|
170 |
void IpFilter::clear( str_list* list ) { |
171 |
if( list ) |
172 |
list->clear(); |
173 |
} |
174 |
|
175 |
} |