00001
00002
00003 #include <stdlib.h>
00004 #include <unistd.h>
00005 #include <assert.h>
00006 #include <sys/time.h>
00007
00008 #include "util.h"
00009 #include "net_util.h"
00010 #include "md5.h"
00011 #include "Anon.h"
00012 #include "Val.h"
00013 #include "NetVar.h"
00014
00015
00016 AnonymizeIPAddr* ip_anonymizer[NUM_ADDR_ANONYMIZATION_METHODS] = {0};
00017
00018 static uint32 rand32()
00019 {
00020 return ((random() & 0xffff) << 16) | (random() & 0xffff);
00021 }
00022
00023
00024 int bi_ffs(uint32 value)
00025 {
00026 int add = 0;
00027 static uint8 bvals[] = { 0, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1 };
00028
00029 if ( (value & 0xFFFF0000) == 0 )
00030 {
00031 if ( value == 0 )
00032
00033 return 0;
00034
00035 add += 16;
00036 }
00037
00038 else
00039 value >>= 16;
00040
00041 if ( (value & 0xFF00) == 0 )
00042 add += 8;
00043 else
00044 value >>= 8;
00045
00046 if ( (value & 0xF0) == 0 )
00047 add += 4;
00048 else
00049 value >>= 4;
00050
00051 return add + bvals[value & 0xf];
00052 }
00053
00054 #define first_n_bit_mask(n) (~(0xFFFFFFFFU >> n))
00055
00056 ipaddr32_t AnonymizeIPAddr::Anonymize(ipaddr32_t addr)
00057 {
00058 map<ipaddr32_t, ipaddr32_t>::iterator p = mapping.find(addr);
00059 if ( p != mapping.end() )
00060 return p->second;
00061 else
00062 {
00063 ipaddr32_t new_addr = anonymize(addr);
00064 mapping[addr] = new_addr;
00065
00066 return new_addr;
00067 }
00068 }
00069
00070 int AnonymizeIPAddr::PreserveNet(ipaddr32_t input)
00071 {
00072 switch ( addr_to_class(ntohl(input)) ) {
00073 case 'A':
00074 return PreservePrefix(input, 8);
00075 case 'B':
00076 return PreservePrefix(input, 16);
00077 case 'C':
00078 return PreservePrefix(input, 24);
00079 default:
00080 return 0;
00081 }
00082 }
00083
00084 ipaddr32_t AnonymizeIPAddr_Seq::anonymize(ipaddr32_t )
00085 {
00086 return htonl(seq++);
00087 }
00088
00089 ipaddr32_t AnonymizeIPAddr_RandomMD5::anonymize(ipaddr32_t input)
00090 {
00091 uint8 digest[16];
00092 ipaddr32_t output = 0;
00093
00094 hmac_md5(sizeof(input), (u_char*)(&input), digest);
00095
00096 for ( int i = 0; i < 4; ++i )
00097 output = (output << 8) | digest[i];
00098
00099 return output;
00100 }
00101
00102 ipaddr32_t AnonymizeIPAddr_PrefixMD5::anonymize(ipaddr32_t input)
00103 {
00104 uint8 digest[16];
00105 ipaddr32_t prefix_mask = 0xffffffff;
00106 ipaddr32_t output = input;
00107
00108 for ( int i = 0; i < 32; ++i )
00109 {
00110 prefix.len = 32 - i;
00111 prefix.prefix = input & prefix_mask;
00112
00113 hmac_md5(sizeof(prefix), (u_char*)(&prefix), digest);
00114
00115 ipaddr32_t bit_mask = (digest[0] & 1) << i;
00116 output ^= bit_mask;
00117 }
00118
00119 return output;
00120 }
00121
00122 AnonymizeIPAddr_A50::~AnonymizeIPAddr_A50()
00123 {
00124 for ( unsigned int i = 0; i < blocks.size(); ++i )
00125 delete [] blocks[i];
00126
00127 blocks.clear();
00128 }
00129
00130 void AnonymizeIPAddr_A50::init()
00131 {
00132 root = next_free_node = 0;
00133
00134
00135 memset(&special_nodes[0], 0, sizeof(special_nodes));
00136 special_nodes[0].input = special_nodes[0].output = 0;
00137 special_nodes[1].input = special_nodes[1].output = 0xFFFFFFFF;
00138
00139 before_anonymization = 1;
00140 }
00141
00142 int AnonymizeIPAddr_A50::PreservePrefix(ipaddr32_t input, int num_bits)
00143 {
00144 DEBUG_MSG(fmt("%s/%d\n", dotted_addr(input), num_bits));
00145
00146 if ( ! before_anonymization )
00147 {
00148 run_time("prefix perservation specified after anonymization begun");
00149 return 0;
00150 }
00151
00152 input = ntohl(input);
00153
00154
00155 input = input & first_n_bit_mask(num_bits);
00156
00157 Node* n = find_node(input);
00158
00159
00160 if ( num_bits == 32 )
00161 n->output = input;
00162
00163 else if ( num_bits > 0 )
00164 {
00165 assert((0xFFFFFFFFU >> 1) == 0x7FFFFFFFU);
00166 uint32 suffix_mask = (0xFFFFFFFFU >> num_bits);
00167 uint32 prefix_mask = ~suffix_mask;
00168 n->output = (input & prefix_mask) | (rand32() & suffix_mask);
00169 }
00170
00171 return 1;
00172 }
00173
00174 ipaddr32_t AnonymizeIPAddr_A50::anonymize(ipaddr32_t a)
00175 {
00176 before_anonymization = 0;
00177 new_mapping = 0;
00178
00179 if ( Node* n = find_node(ntohl(a)) )
00180 {
00181 ipaddr32_t output = htonl(n->output);
00182 return output;
00183 }
00184 else
00185 return 0;
00186 }
00187
00188 AnonymizeIPAddr_A50::Node* AnonymizeIPAddr_A50::new_node_block()
00189 {
00190 assert(! next_free_node);
00191
00192 int block_size = 1024;
00193 Node* block = new Node[block_size];
00194 if ( ! block )
00195 internal_error("out of memory!");
00196
00197 blocks.push_back(block);
00198
00199 for ( int i = 1; i < block_size - 1; ++i )
00200 block[i].child[0] = &block[i+1];
00201
00202 block[block_size - 1].child[0] = 0;
00203 next_free_node = &block[1];
00204
00205 return &block[0];
00206 }
00207
00208 inline AnonymizeIPAddr_A50::Node* AnonymizeIPAddr_A50::new_node()
00209 {
00210 new_mapping = 1;
00211
00212 if ( next_free_node )
00213 {
00214 Node* n = next_free_node;
00215 next_free_node = n->child[0];
00216 return n;
00217 }
00218 else
00219 return new_node_block();
00220 }
00221
00222 inline void AnonymizeIPAddr_A50::free_node(Node *n)
00223 {
00224 n->child[0] = next_free_node;
00225 next_free_node = n;
00226 }
00227
00228 ipaddr32_t AnonymizeIPAddr_A50::make_output(ipaddr32_t old_output, int swivel) const
00229 {
00230
00231 if ( swivel == 32 )
00232 return old_output ^ 1;
00233 else
00234 {
00235
00236 ipaddr32_t known_part =
00237 ((old_output >> (32 - swivel)) ^ 1) << (32 - swivel);
00238
00239
00240 return known_part | ((rand32() & 0x7FFFFFFF) >> swivel);
00241 }
00242 }
00243
00244 AnonymizeIPAddr_A50::Node* AnonymizeIPAddr_A50::make_peer(ipaddr32_t a, Node* n)
00245 {
00246 if ( a == 0 || a == 0xFFFFFFFFU )
00247 internal_error("0.0.0.0 and 255.255.255.255 should never get into the tree");
00248
00249
00250
00251
00252
00253 Node* down[2];
00254
00255 if ( ! (down[0] = new_node()) )
00256 return 0;
00257
00258 if ( ! (down[1] = new_node()) )
00259 {
00260 free_node(down[0]);
00261 return 0;
00262 }
00263
00264
00265 int swivel = bi_ffs(a ^ n->input);
00266
00267
00268 int bitvalue = (a >> (32 - swivel)) & 1;
00269
00270 down[bitvalue]->input = a;
00271 down[bitvalue]->output = make_output(n->output, swivel);
00272 down[bitvalue]->child[0] = down[bitvalue]->child[1] = 0;
00273
00274 *down[1 - bitvalue] = *n;
00275
00276 n->input = down[1]->input;
00277 n->output = down[1]->output;
00278 n->child[0] = down[0];
00279 n->child[1] = down[1];
00280
00281 return down[bitvalue];
00282 }
00283
00284 AnonymizeIPAddr_A50::Node* AnonymizeIPAddr_A50::find_node(ipaddr32_t a)
00285 {
00286
00287
00288 if ( a == 0 || a == 0xFFFFFFFFU )
00289 return &special_nodes[a & 1];
00290
00291 if ( ! root )
00292 {
00293 root = new_node();
00294 root->input = a;
00295 root->output = rand32();
00296 root->child[0] = root->child[1] = 0;
00297
00298 return root;
00299 }
00300
00301
00302 Node* n = root;
00303 while ( n )
00304 {
00305 if ( n->input == a )
00306 return n;
00307
00308 if ( ! n->child[0] )
00309 n = make_peer(a, n);
00310
00311 else
00312 {
00313
00314
00315 int swivel =
00316 bi_ffs(n->child[0]->input ^ n->child[1]->input);
00317
00318 if ( bi_ffs(a ^ n->input) < swivel )
00319
00320 n = make_peer(a, n);
00321
00322 else if ( a & (1 << (32 - swivel)) )
00323 n = n->child[1];
00324
00325 else
00326 n = n->child[0];
00327 }
00328 }
00329
00330 internal_error("out of memory!");
00331 return 0;
00332 }
00333
00334 void init_ip_addr_anonymizers()
00335 {
00336 ip_anonymizer[KEEP_ORIG_ADDR] = 0;
00337 ip_anonymizer[SEQUENTIALLY_NUMBERED] = new AnonymizeIPAddr_Seq();
00338 ip_anonymizer[RANDOM_MD5] = new AnonymizeIPAddr_RandomMD5();
00339 ip_anonymizer[PREFIX_PRESERVING_A50] = new AnonymizeIPAddr_A50();
00340 ip_anonymizer[PREFIX_PRESERVING_MD5] = new AnonymizeIPAddr_PrefixMD5();
00341 }
00342
00343 ipaddr32_t anonymize_ip(ipaddr32_t ip, enum ip_addr_anonymization_class_t cl)
00344 {
00345 TableVal* preserve_addr = 0;
00346 AddrVal addr(ip);
00347
00348 int method = -1;
00349
00350 switch ( cl ) {
00351 case ORIG_ADDR:
00352 preserve_addr = preserve_orig_addr;
00353 method = orig_addr_anonymization;
00354 break;
00355
00356 case RESP_ADDR:
00357 preserve_addr = preserve_resp_addr;
00358 method = resp_addr_anonymization;
00359 break;
00360
00361 default:
00362 preserve_addr = preserve_other_addr;
00363 method = other_addr_anonymization;
00364 break;
00365 }
00366
00367 ipaddr32_t new_ip = 0;
00368
00369 if ( preserve_addr && preserve_addr->Lookup(&addr) )
00370 new_ip = ip;
00371
00372 else if ( method >= 0 && method < NUM_ADDR_ANONYMIZATION_METHODS )
00373 {
00374 if ( method == KEEP_ORIG_ADDR )
00375 new_ip = ip;
00376
00377 else if ( ! ip_anonymizer[method] )
00378 internal_error("IP anonymizer not initialized");
00379
00380 else
00381 new_ip = ip_anonymizer[method]->Anonymize(ip);
00382 }
00383
00384 else
00385 internal_error("invalid IP anonymization method");
00386
00387 #ifdef LOG_ANONYMIZATION_MAPPING
00388 log_anonymization_mapping(ip, new_ip);
00389 #endif
00390 return new_ip;
00391 }
00392
00393 #ifdef LOG_ANONYMIZATION_MAPPING
00394
00395 #include "NetVar.h"
00396 #include "Event.h"
00397
00398 void log_anonymization_mapping(ipaddr32_t input, ipaddr32_t output)
00399 {
00400 if ( anonymization_mapping )
00401 {
00402 val_list* vl = new val_list;
00403 vl->append(new AddrVal(input));
00404 vl->append(new AddrVal(output));
00405 mgr.QueueEvent(anonymization_mapping, vl);
00406 }
00407 }
00408
00409 #endif