ntopng/src/AddressTree.cpp
2017-01-20 16:50:56 +01:00

214 lines
5.6 KiB
C++

/*
*
* (C) 2013-17 - ntop.org
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "ntop_includes.h"
#include "../third-party/patricia/patricia.c"
/* **************************************** */
AddressTree::AddressTree() { init(); }
/* **************************************** */
static void free_ptree_data(void *data) { ; }
/* **************************************** */
void AddressTree::init() {
numAddresses = 0;
ptree_v4 = New_Patricia(32), ptree_v6 = New_Patricia(128), macs = NULL;
}
/* **************************************** */
AddressTree::~AddressTree() {
cleanup();
}
/* ******************************************* */
bool AddressTree::addAddress(char *_what, const int16_t user_data) {
u_int32_t _mac[6];
int16_t id = (user_data == -1) ? numAddresses : user_data;
if(sscanf(_what, "%02X:%02X:%02X:%02X:%02X:%02X",
&_mac[0], &_mac[1], &_mac[2],
&_mac[3], &_mac[4], &_mac[5]) == 6) {
int16_t v;
u_int8_t mac[6];
for(int i=0; i<6; i++) mac[i] = (u_int8_t)_mac[i];
if((v = findMac(mac)) == -1) {
/* Not found: let's add it */
MacKey_t *s;
if((s = (MacKey_t*)malloc(sizeof(MacKey_t))) != NULL) {
memcpy(s->mac, mac, 6), s->value = id;
HASH_ADD(hh, macs, mac, 6, s);
} else
return(false);
}
} else {
patricia_node_t *node = Utils::ptree_add_rule(strchr(_what, '.') ? ptree_v4 : ptree_v6, _what);
if(node)
node->user_data = id;
}
numAddresses++;
return(true);
}
/* ******************************************* */
/* Format: 131.114.21.0/24,10.0.0.0/255.0.0.0 */
bool AddressTree::addAddresses(char *rule, const int16_t user_data) {
char *tmp, *net = strtok_r(rule, ",", &tmp);
while(net != NULL) {
if(!addAddress(net, user_data))
return false;
net = strtok_r(NULL, ",", &tmp);
}
return true;
}
/* ******************************************* */
int16_t AddressTree::findAddress(int family, void *addr) {
patricia_tree_t *p;
int bits;
patricia_node_t *node;
if(family == AF_INET)
p = ptree_v4, bits = 32;
else if(family == AF_INET6)
p = ptree_v6, bits = 128;
else
return(-1);
node = Utils::ptree_match(p, family, addr, bits);
if(node == NULL)
return(-1);
else
return(node->user_data);
}
/* ******************************************* */
int16_t AddressTree::findMac(u_int8_t addr[]) {
MacKey_t *s = NULL;
HASH_FIND(hh, macs, addr, 6, s);
return(s ? s->value : -1);
}
/* **************************************************** */
static void address_tree_dump_funct(prefix_t *prefix, void *data, void *user_data) {
char address[64], ret[64], *a;
if(!prefix) return;
switch(prefix->family) {
case AF_INET:
a = Utils::intoaV4(ntohl(prefix->add.sin.s_addr), address, sizeof(address));
snprintf(ret, sizeof(ret), "%s/%d", a, prefix->bitlen);
break;
case AF_INET6:
a = Utils::intoaV6(*((struct ndpi_in6_addr*)&prefix->add.sin6), prefix->bitlen, address, sizeof(address));
snprintf(ret, sizeof(ret), "%s/%d", a, prefix->bitlen);
break;
}
if(user_data)
lua_push_str_table_entry((lua_State*)user_data, ret, (char*)"");
else
ntop->getTrace()->traceEvent(TRACE_NORMAL, "[AddressTree] %s", ret);
}
/* **************************************************** */
void AddressTree::getAddresses(lua_State* vm) {
if(ptree_v4->head) patricia_walk_inorder(ptree_v4->head, address_tree_dump_funct, vm);
if(ptree_v6->head) patricia_walk_inorder(ptree_v6->head, address_tree_dump_funct, vm);
if(macs) {
MacKey_t *current, *tmp;
HASH_ITER(hh, macs, current, tmp) {
char key[32], val[8];
snprintf(key, sizeof(key), "%02X:%02X:%02X:%02X:%02X:%02X",
current->mac[0], current->mac[1], current->mac[2],
current->mac[3], current->mac[4], current->mac[5]);
snprintf(val, sizeof(val), "%u", current->value);
lua_push_str_table_entry(vm, key, val);
}
}
}
/* **************************************************** */
void AddressTree::dump() {
if(ptree_v4->head) patricia_walk_inorder(ptree_v4->head, address_tree_dump_funct, NULL);
if(ptree_v6->head) patricia_walk_inorder(ptree_v6->head, address_tree_dump_funct, NULL);
if(macs) {
MacKey_t *current, *tmp;
HASH_ITER(hh, macs, current, tmp) {
char key[32];
snprintf(key, sizeof(key), "%02X:%02X:%02X:%02X:%02X:%02X",
current->mac[0], current->mac[1], current->mac[2],
current->mac[3], current->mac[4], current->mac[5]);
ntop->getTrace()->traceEvent(TRACE_NORMAL, "[AddressTree] %s", key);
}
}
}
/* **************************************************** */
void AddressTree::cleanup() {
if(ptree_v4) Destroy_Patricia(ptree_v4, free_ptree_data);
if(ptree_v6) Destroy_Patricia(ptree_v6, free_ptree_data);
if(macs) {
MacKey_t *current, *tmp;
HASH_ITER(hh, macs, current, tmp) {
HASH_DEL(macs, current); /* delete it */
free(current); /* free it */
}
}
}