|
@ -1,6 +1,5 @@ |
|
|
/*
|
|
|
/**
|
|
|
* (C) 2007-09 - Luca Deri <deri@ntop.org> |
|
|
* (C) 2007-18 - ntop.org and contributors |
|
|
* Richard Andrews <andrews@ntop.org> |
|
|
|
|
|
* |
|
|
* |
|
|
* This program is free software; you can redistribute it and/or modify |
|
|
* 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 |
|
|
* it under the terms of the GNU General Public License as published by |
|
@ -13,11 +12,7 @@ |
|
|
* GNU General Public License for more details. |
|
|
* GNU General Public License for more details. |
|
|
* |
|
|
* |
|
|
* You should have received a copy of the GNU General Public License |
|
|
* You should have received a copy of the GNU General Public License |
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>
|
|
|
* along with this program; if not see see <http://www.gnu.org/licenses/>
|
|
|
* |
|
|
|
|
|
* Code contributions courtesy of: |
|
|
|
|
|
* Massimo Torquati <torquati@ntop.org> |
|
|
|
|
|
* Matt Gilg |
|
|
|
|
|
* |
|
|
* |
|
|
*/ |
|
|
*/ |
|
|
|
|
|
|
|
@ -57,13 +52,13 @@ SOCKET open_socket(int local_port, int bind_any) { |
|
|
/* fcntl(sock_fd, F_SETFL, O_NONBLOCK); */ |
|
|
/* fcntl(sock_fd, F_SETFL, O_NONBLOCK); */ |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&sockopt, sizeof(sockopt)); |
|
|
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR,(char *)&sockopt, sizeof(sockopt)); |
|
|
|
|
|
|
|
|
memset(&local_address, 0, sizeof(local_address)); |
|
|
memset(&local_address, 0, sizeof(local_address)); |
|
|
local_address.sin_family = AF_INET; |
|
|
local_address.sin_family = AF_INET; |
|
|
local_address.sin_port = htons(local_port); |
|
|
local_address.sin_port = htons(local_port); |
|
|
local_address.sin_addr.s_addr = htonl(bind_any?INADDR_ANY:INADDR_LOOPBACK); |
|
|
local_address.sin_addr.s_addr = htonl(bind_any?INADDR_ANY:INADDR_LOOPBACK); |
|
|
if(bind(sock_fd, (struct sockaddr*) &local_address, sizeof(local_address)) == -1) { |
|
|
if(bind(sock_fd,(struct sockaddr*) &local_address, sizeof(local_address)) == -1) { |
|
|
traceEvent(TRACE_ERROR, "Bind error [%s]\n", strerror(errno)); |
|
|
traceEvent(TRACE_ERROR, "Bind error [%s]\n", strerror(errno)); |
|
|
return(-1); |
|
|
return(-1); |
|
|
} |
|
|
} |
|
@ -93,7 +88,7 @@ void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...) { |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
/* We have two paths - one if we're logging, one if we aren't
|
|
|
/* We have two paths - one if we're logging, one if we aren't
|
|
|
* Note that the no-log case is those systems which don't support it (WIN32), |
|
|
* Note that the no-log case is those systems which don't support it(WIN32), |
|
|
* those without the headers !defined(USE_SYSLOG) |
|
|
* those without the headers !defined(USE_SYSLOG) |
|
|
* those where it's parametrically off... |
|
|
* those where it's parametrically off... |
|
|
*/ |
|
|
*/ |
|
@ -101,7 +96,7 @@ void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...) { |
|
|
memset(buf, 0, sizeof(buf)); |
|
|
memset(buf, 0, sizeof(buf)); |
|
|
strftime(theDate, N2N_TRACE_DATESIZE, "%d/%b/%Y %H:%M:%S", localtime(&theTime)); |
|
|
strftime(theDate, N2N_TRACE_DATESIZE, "%d/%b/%Y %H:%M:%S", localtime(&theTime)); |
|
|
|
|
|
|
|
|
va_start (va_ap, format); |
|
|
va_start(va_ap, format); |
|
|
vsnprintf(buf, sizeof(buf)-1, format, va_ap); |
|
|
vsnprintf(buf, sizeof(buf)-1, format, va_ap); |
|
|
va_end(va_ap); |
|
|
va_end(va_ap); |
|
|
|
|
|
|
|
@ -153,26 +148,26 @@ char* intoa(uint32_t /* host order */ addr, char* buf, uint16_t buf_len) { |
|
|
byteval = addr & 0xff; |
|
|
byteval = addr & 0xff; |
|
|
*--cp = byteval % 10 + '0'; |
|
|
*--cp = byteval % 10 + '0'; |
|
|
byteval /= 10; |
|
|
byteval /= 10; |
|
|
if (byteval > 0) { |
|
|
if(byteval > 0) { |
|
|
*--cp = byteval % 10 + '0'; |
|
|
*--cp = byteval % 10 + '0'; |
|
|
byteval /= 10; |
|
|
byteval /= 10; |
|
|
if (byteval > 0) |
|
|
if(byteval > 0) |
|
|
*--cp = byteval + '0'; |
|
|
*--cp = byteval + '0'; |
|
|
} |
|
|
} |
|
|
*--cp = '.'; |
|
|
*--cp = '.'; |
|
|
addr >>= 8; |
|
|
addr >>= 8; |
|
|
} while (--n > 0); |
|
|
} while(--n > 0); |
|
|
|
|
|
|
|
|
/* Convert the string to lowercase */ |
|
|
/* Convert the string to lowercase */ |
|
|
retStr = (char*)(cp+1); |
|
|
retStr =(char*)(cp+1); |
|
|
|
|
|
|
|
|
return(retStr); |
|
|
return(retStr); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* *********************************************** */ |
|
|
/* *********************************************** */ |
|
|
|
|
|
|
|
|
char * macaddr_str( macstr_t buf, |
|
|
char * macaddr_str(macstr_t buf, |
|
|
const n2n_mac_t mac ) |
|
|
const n2n_mac_t mac) |
|
|
{ |
|
|
{ |
|
|
snprintf(buf, N2N_MACSTR_SIZE, "%02X:%02X:%02X:%02X:%02X:%02X", |
|
|
snprintf(buf, N2N_MACSTR_SIZE, "%02X:%02X:%02X:%02X:%02X:%02X", |
|
|
mac[0] & 0xFF, mac[1] & 0xFF, mac[2] & 0xFF, |
|
|
mac[0] & 0xFF, mac[1] & 0xFF, mac[2] & 0xFF, |
|
@ -184,9 +179,9 @@ char * macaddr_str( macstr_t buf, |
|
|
|
|
|
|
|
|
uint8_t is_multi_broadcast(const uint8_t * dest_mac) { |
|
|
uint8_t is_multi_broadcast(const uint8_t * dest_mac) { |
|
|
|
|
|
|
|
|
int is_broadcast = ( memcmp(broadcast_addr, dest_mac, 6) == 0 ); |
|
|
int is_broadcast =(memcmp(broadcast_addr, dest_mac, 6) == 0); |
|
|
int is_multicast = ( memcmp(multicast_addr, dest_mac, 3) == 0 ); |
|
|
int is_multicast =(memcmp(multicast_addr, dest_mac, 3) == 0); |
|
|
int is_ipv6_multicast = ( memcmp(ipv6_multicast_addr, dest_mac, 2) == 0 ); |
|
|
int is_ipv6_multicast =(memcmp(ipv6_multicast_addr, dest_mac, 2) == 0); |
|
|
|
|
|
|
|
|
return is_broadcast || is_multicast || is_ipv6_multicast; |
|
|
return is_broadcast || is_multicast || is_ipv6_multicast; |
|
|
|
|
|
|
|
@ -219,11 +214,11 @@ void hexdump(const uint8_t * buf, size_t len) |
|
|
{ |
|
|
{ |
|
|
size_t i; |
|
|
size_t i; |
|
|
|
|
|
|
|
|
if ( 0 == len ) { return; } |
|
|
if(0 == len) { return; } |
|
|
|
|
|
|
|
|
for(i=0; i<len; i++) |
|
|
for(i=0; i<len; i++) |
|
|
{ |
|
|
{ |
|
|
if((i > 0) && ((i % 16) == 0)) { printf("\n"); } |
|
|
if((i > 0) &&((i % 16) == 0)) { printf("\n"); } |
|
|
printf("%02X ", buf[i] & 0xFF); |
|
|
printf("%02X ", buf[i] & 0xFF); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -235,12 +230,11 @@ void hexdump(const uint8_t * buf, size_t len) |
|
|
void print_n2n_version() { |
|
|
void print_n2n_version() { |
|
|
printf("Welcome to n2n v.%s for %s\n" |
|
|
printf("Welcome to n2n v.%s for %s\n" |
|
|
"Built on %s\n" |
|
|
"Built on %s\n" |
|
|
"Copyright 2007-09 - http://www.ntop.org\n\n", |
|
|
"Copyright 2007-18 - ntop.org and contributors\n\n", |
|
|
n2n_sw_version, n2n_sw_osName, n2n_sw_buildDate); |
|
|
n2n_sw_version, n2n_sw_osName, n2n_sw_buildDate); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* *********************************************** */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Find the peer entry in list with mac_addr equal to mac.
|
|
|
/** Find the peer entry in list with mac_addr equal to mac.
|
|
|
* |
|
|
* |
|
@ -248,11 +242,11 @@ void print_n2n_version() { |
|
|
* |
|
|
* |
|
|
* @return NULL if not found; otherwise pointer to peer entry. |
|
|
* @return NULL if not found; otherwise pointer to peer entry. |
|
|
*/ |
|
|
*/ |
|
|
struct peer_info * find_peer_by_mac( struct peer_info * list, const n2n_mac_t mac ) |
|
|
struct peer_info * find_peer_by_mac(struct peer_info * list, const n2n_mac_t mac) |
|
|
{ |
|
|
{ |
|
|
while(list != NULL) |
|
|
while(list != NULL) |
|
|
{ |
|
|
{ |
|
|
if( 0 == memcmp(mac, list->mac_addr, 6) ) |
|
|
if(0 == memcmp(mac, list->mac_addr, 6)) |
|
|
{ |
|
|
{ |
|
|
return list; |
|
|
return list; |
|
|
} |
|
|
} |
|
@ -266,11 +260,11 @@ struct peer_info * find_peer_by_mac( struct peer_info * list, const n2n_mac_t ma |
|
|
/** Return the number of elements in the list.
|
|
|
/** Return the number of elements in the list.
|
|
|
* |
|
|
* |
|
|
*/ |
|
|
*/ |
|
|
size_t peer_list_size( const struct peer_info * list ) |
|
|
size_t peer_list_size(const struct peer_info * list) |
|
|
{ |
|
|
{ |
|
|
size_t retval=0; |
|
|
size_t retval=0; |
|
|
|
|
|
|
|
|
while ( list ) |
|
|
while(list) |
|
|
{ |
|
|
{ |
|
|
++retval; |
|
|
++retval; |
|
|
list = list->next; |
|
|
list = list->next; |
|
@ -284,8 +278,8 @@ size_t peer_list_size( const struct peer_info * list ) |
|
|
* The item new is added to the head of the list. New is modified during |
|
|
* The item new is added to the head of the list. New is modified during |
|
|
* insertion. list takes ownership of new. |
|
|
* insertion. list takes ownership of new. |
|
|
*/ |
|
|
*/ |
|
|
void peer_list_add( struct peer_info * * list, |
|
|
void peer_list_add(struct peer_info * * list, |
|
|
struct peer_info * new ) |
|
|
struct peer_info * new) |
|
|
{ |
|
|
{ |
|
|
new->next = *list; |
|
|
new->next = *list; |
|
|
new->last_seen = time(NULL); |
|
|
new->last_seen = time(NULL); |
|
@ -293,7 +287,7 @@ void peer_list_add( struct peer_info * * list, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
size_t purge_expired_registrations( struct peer_info ** peer_list ) { |
|
|
size_t purge_expired_registrations(struct peer_info ** peer_list) { |
|
|
static time_t last_purge = 0; |
|
|
static time_t last_purge = 0; |
|
|
time_t now = time(NULL); |
|
|
time_t now = time(NULL); |
|
|
size_t num_reg = 0; |
|
|
size_t num_reg = 0; |
|
@ -302,7 +296,7 @@ size_t purge_expired_registrations( struct peer_info ** peer_list ) { |
|
|
|
|
|
|
|
|
traceEvent(TRACE_INFO, "Purging old registrations"); |
|
|
traceEvent(TRACE_INFO, "Purging old registrations"); |
|
|
|
|
|
|
|
|
num_reg = purge_peer_list( peer_list, now-REGISTRATION_TIMEOUT ); |
|
|
num_reg = purge_peer_list(peer_list, now-REGISTRATION_TIMEOUT); |
|
|
|
|
|
|
|
|
last_purge = now; |
|
|
last_purge = now; |
|
|
traceEvent(TRACE_INFO, "Remove %ld registrations", num_reg); |
|
|
traceEvent(TRACE_INFO, "Remove %ld registrations", num_reg); |
|
@ -311,8 +305,8 @@ size_t purge_expired_registrations( struct peer_info ** peer_list ) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** Purge old items from the peer_list and return the number of items that were removed. */ |
|
|
/** Purge old items from the peer_list and return the number of items that were removed. */ |
|
|
size_t purge_peer_list( struct peer_info ** peer_list, |
|
|
size_t purge_peer_list(struct peer_info ** peer_list, |
|
|
time_t purge_before ) |
|
|
time_t purge_before) |
|
|
{ |
|
|
{ |
|
|
struct peer_info *scan; |
|
|
struct peer_info *scan; |
|
|
struct peer_info *prev; |
|
|
struct peer_info *prev; |
|
@ -350,7 +344,7 @@ size_t purge_peer_list( struct peer_info ** peer_list, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** Purge all items from the peer_list and return the number of items that were removed. */ |
|
|
/** Purge all items from the peer_list and return the number of items that were removed. */ |
|
|
size_t clear_peer_list( struct peer_info ** peer_list ) |
|
|
size_t clear_peer_list(struct peer_info ** peer_list) |
|
|
{ |
|
|
{ |
|
|
struct peer_info *scan; |
|
|
struct peer_info *scan; |
|
|
struct peer_info *prev; |
|
|
struct peer_info *prev; |
|
@ -379,17 +373,17 @@ size_t clear_peer_list( struct peer_info ** peer_list ) |
|
|
return retval; |
|
|
return retval; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static uint8_t hex2byte( const char * s ) |
|
|
static uint8_t hex2byte(const char * s) |
|
|
{ |
|
|
{ |
|
|
char tmp[3]; |
|
|
char tmp[3]; |
|
|
tmp[0]=s[0]; |
|
|
tmp[0]=s[0]; |
|
|
tmp[1]=s[1]; |
|
|
tmp[1]=s[1]; |
|
|
tmp[2]=0; /* NULL term */ |
|
|
tmp[2]=0; /* NULL term */ |
|
|
|
|
|
|
|
|
return((uint8_t)strtol( tmp, NULL, 16 )); |
|
|
return((uint8_t)strtol(tmp, NULL, 16)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
extern int str2mac( uint8_t * outmac /* 6 bytes */, const char * s ) |
|
|
extern int str2mac(uint8_t * outmac /* 6 bytes */, const char * s) |
|
|
{ |
|
|
{ |
|
|
size_t i; |
|
|
size_t i; |
|
|
|
|
|
|
|
@ -400,7 +394,7 @@ extern int str2mac( uint8_t * outmac /* 6 bytes */, const char * s ) |
|
|
++outmac; |
|
|
++outmac; |
|
|
s+=2; /* don't skip colon yet - helps generalise loop. */ |
|
|
s+=2; /* don't skip colon yet - helps generalise loop. */ |
|
|
|
|
|
|
|
|
for (i=1; i<6; ++i ) |
|
|
for(i=1; i<6; ++i) |
|
|
{ |
|
|
{ |
|
|
s+=1; |
|
|
s+=1; |
|
|
*outmac=hex2byte(s); |
|
|
*outmac=hex2byte(s); |
|
@ -411,42 +405,46 @@ extern int str2mac( uint8_t * outmac /* 6 bytes */, const char * s ) |
|
|
return 0; /* ok */ |
|
|
return 0; /* ok */ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
extern char * sock_to_cstr( n2n_sock_str_t out, |
|
|
extern char * sock_to_cstr(n2n_sock_str_t out, |
|
|
const n2n_sock_t * sock ) |
|
|
const n2n_sock_t * sock) { |
|
|
{ |
|
|
if(NULL == out) { return NULL; } |
|
|
int r; |
|
|
|
|
|
|
|
|
|
|
|
if ( NULL == out ) { return NULL; } |
|
|
|
|
|
memset(out, 0, N2N_SOCKBUF_SIZE); |
|
|
memset(out, 0, N2N_SOCKBUF_SIZE); |
|
|
|
|
|
|
|
|
if ( AF_INET6 == sock->family ) |
|
|
if(AF_INET6 == sock->family) { |
|
|
{ |
|
|
|
|
|
/* INET6 not written yet */ |
|
|
/* INET6 not written yet */ |
|
|
r = snprintf( out, N2N_SOCKBUF_SIZE, "XXXX:%hu", sock->port ); |
|
|
snprintf(out, N2N_SOCKBUF_SIZE, "XXXX:%hu", sock->port); |
|
|
return out; |
|
|
return out; |
|
|
} |
|
|
} else { |
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
const uint8_t * a = sock->addr.v4; |
|
|
const uint8_t * a = sock->addr.v4; |
|
|
r = snprintf( out, N2N_SOCKBUF_SIZE, "%hu.%hu.%hu.%hu:%hu", |
|
|
|
|
|
(a[0] & 0xff), (a[1] & 0xff), (a[2] & 0xff), (a[3] & 0xff), sock->port ); |
|
|
snprintf(out, N2N_SOCKBUF_SIZE, "%hu.%hu.%hu.%hu:%hu", |
|
|
|
|
|
(unsigned short)(a[0] & 0xff), |
|
|
|
|
|
(unsigned short)(a[1] & 0xff), |
|
|
|
|
|
(unsigned short)(a[2] & 0xff), |
|
|
|
|
|
(unsigned short)(a[3] & 0xff), |
|
|
|
|
|
(unsigned short)sock->port); |
|
|
return out; |
|
|
return out; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* @return zero if the two sockets are equivalent. */ |
|
|
/* @return zero if the two sockets are equivalent. */ |
|
|
int sock_equal( const n2n_sock_t * a, |
|
|
int sock_equal(const n2n_sock_t * a, |
|
|
const n2n_sock_t * b ) |
|
|
const n2n_sock_t * b) { |
|
|
{ |
|
|
if(a->port != b->port) { return 1; } |
|
|
if ( a->port != b->port ) { return 1; } |
|
|
if(a->family != b->family) { return 1; } |
|
|
if ( a->family != b->family ) { return 1; } |
|
|
|
|
|
switch (a->family) /* they are the same */ |
|
|
switch(a->family) { |
|
|
{ |
|
|
|
|
|
case AF_INET: |
|
|
case AF_INET: |
|
|
if ( 0 != memcmp( a->addr.v4, b->addr.v4, IPV4_SIZE ) ) { return 1;}; |
|
|
if(0 != memcmp(a->addr.v4, b->addr.v4, IPV4_SIZE)) { |
|
|
|
|
|
return 1; |
|
|
|
|
|
} |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
default: |
|
|
default: |
|
|
if ( 0 != memcmp( a->addr.v6, b->addr.v6, IPV6_SIZE ) ) { return 1;}; |
|
|
if(0 != memcmp(a->addr.v6, b->addr.v6, IPV6_SIZE)) { |
|
|
|
|
|
return 1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|