@ -32,7 +32,8 @@ static const n2n_mac_t null_mac = {0, 0, 0, 0, 0, 0};
/* ************************************** */
SOCKET open_socket ( int local_port , int bind_any ) {
SOCKET open_socket ( int local_port , int bind_any ) {
SOCKET sock_fd ;
struct sockaddr_in local_address ;
int sockopt ;
@ -67,28 +68,33 @@ static int traceLevel = 2 /* NORMAL */;
static int useSyslog = 0 , syslog_opened = 0 ;
static FILE * traceFile = NULL ;
int getTraceLevel ( ) {
int getTraceLevel ( ) {
return ( traceLevel ) ;
}
void setTraceLevel ( int level ) {
void setTraceLevel ( int level ) {
traceLevel = level ;
}
void setUseSyslog ( int use_syslog ) {
useSyslog = use_syslog ;
void setUseSyslog ( int use_syslog ) {
useSyslog = use_syslog ;
}
void setTraceFile ( FILE * f ) {
void setTraceFile ( FILE * f ) {
traceFile = f ;
}
void closeTraceFile ( ) {
if ( traceFile ! = NULL & & traceFile ! = stdout ) {
void closeTraceFile ( ) {
if ( ( traceFile ! = NULL ) & & ( traceFile ! = stdout ) ) {
fclose ( traceFile ) ;
}
# ifndef WIN32
if ( useSyslog & & syslog_opened ) {
if ( useSyslog & & syslog_opened ) {
closelog ( ) ;
syslog_opened = 0 ;
}
@ -96,11 +102,13 @@ void closeTraceFile() {
}
# define N2N_TRACE_DATESIZE 32
void traceEvent ( int eventTraceLevel , char * file , int line , char * format , . . . ) {
void traceEvent ( int eventTraceLevel , char * file , int line , char * format , . . . ) {
va_list va_ap ;
if ( traceFile = = NULL )
if ( traceFile = = NULL ) {
traceFile = stdout ;
}
if ( eventTraceLevel < = traceLevel ) {
char buf [ 1024 ] ;
@ -120,15 +128,18 @@ void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...) {
strftime ( theDate , N2N_TRACE_DATESIZE , " %d/%b/%Y %H:%M:%S " , localtime ( & theTime ) ) ;
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 ) ;
if ( eventTraceLevel = = 0 /* TRACE_ERROR */ )
if ( eventTraceLevel = = 0 /* TRACE_ERROR */ ) {
extra_msg = " ERROR: " ;
else if ( eventTraceLevel = = 1 /* TRACE_WARNING */ )
} else if ( eventTraceLevel = = 1 /* TRACE_WARNING */ ) {
extra_msg = " WARNING: " ;
}
while ( buf [ strlen ( buf ) - 1 ] = = ' \n ' ) buf [ strlen ( buf ) - 1 ] = ' \0 ' ;
while ( buf [ strlen ( buf ) - 1 ] = = ' \n ' ) {
buf [ strlen ( buf ) - 1 ] = ' \0 ' ;
}
# ifndef WIN32
if ( useSyslog ) {
@ -140,14 +151,24 @@ void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...) {
snprintf ( out_buf , sizeof ( out_buf ) , " %s%s " , extra_msg , buf ) ;
syslog ( LOG_INFO , " %s " , out_buf ) ;
} else {
for ( i = strlen ( file ) - 1 ; i > 0 ; i - - ) if ( file [ i ] = = ' / ' ) { i + + ; break ; } ;
for ( i = strlen ( file ) - 1 ; i > 0 ; i - - ) {
if ( file [ i ] = = ' / ' ) {
i + + ;
break ;
}
}
snprintf ( out_buf , sizeof ( out_buf ) , " %s [%s:%d] %s%s " , theDate , & file [ i ] , line , extra_msg , buf ) ;
fprintf ( traceFile , " %s \n " , out_buf ) ;
fflush ( traceFile ) ;
}
# else
/* this is the WIN32 code */
for ( i = strlen ( file ) - 1 ; i > 0 ; i - - ) if ( file [ i ] = = ' \\ ' ) { i + + ; break ; } ;
for ( i = strlen ( file ) - 1 ; i > 0 ; i - - ) {
if ( file [ i ] = = ' \\ ' ) {
i + + ;
break ;
}
}
snprintf ( out_buf , sizeof ( out_buf ) , " %s [%s:%d] %s%s " , theDate , & file [ i ] , line , extra_msg , buf ) ;
fprintf ( traceFile , " %s \n " , out_buf ) ;
fflush ( traceFile ) ;
@ -159,7 +180,8 @@ void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...) {
/* *********************************************** */
/* addr should be in network order. Things are so much simpler that way. */
char * intoa ( uint32_t /* host order */ addr , char * buf , uint16_t buf_len ) {
char * intoa ( uint32_t /* host order */ addr , char * buf , uint16_t buf_len ) {
char * cp , * retStr ;
uint8_t byteval ;
int n ;
@ -175,50 +197,61 @@ char* intoa(uint32_t /* host order */ addr, char* buf, uint16_t buf_len) {
if ( byteval > 0 ) {
* - - cp = byteval % 10 + ' 0 ' ;
byteval / = 10 ;
if ( byteval > 0 )
if ( byteval > 0 ) {
* - - cp = byteval + ' 0 ' ;
}
}
* - - cp = ' . ' ;
addr > > = 8 ;
} while ( - - n > 0 ) ;
/* Convert the string to lowercase */
retStr = ( char * ) ( cp + 1 ) ;
retStr = ( char * ) ( cp + 1 ) ;
return ( retStr ) ;
}
/** Convert subnet prefix bit length to host order subnet mask. */
uint32_t bitlen2mask ( uint8_t bitlen ) {
uint32_t bitlen2mask ( uint8_t bitlen ) {
uint8_t i ;
uint32_t mask = 0 ;
for ( i = 1 ; i < = bitlen ; + + i ) {
mask | = 1 < < ( 32 - i ) ;
}
return mask ;
}
/** Convert host order subnet mask to subnet prefix bit length. */
uint8_t mask2bitlen ( uint32_t mask ) {
uint8_t mask2bitlen ( uint32_t mask ) {
uint8_t i , bitlen = 0 ;
for ( i = 0 ; i < 32 ; + + i ) {
if ( ( mask < < i ) & 0x80000000 ) + + bitlen ;
else break ;
if ( ( mask < < i ) & 0x80000000 ) {
+ + bitlen ;
} else {
break ;
}
}
return bitlen ;
}
/* *********************************************** */
char * macaddr_str ( macstr_t buf ,
const n2n_mac_t mac )
{
char * macaddr_str ( macstr_t buf ,
const n2n_mac_t mac ) {
snprintf ( buf , N2N_MACSTR_SIZE , " %02X:%02X:%02X:%02X:%02X:%02X " ,
mac [ 0 ] & 0xFF , mac [ 1 ] & 0xFF , mac [ 2 ] & 0xFF ,
mac [ 3 ] & 0xFF , mac [ 4 ] & 0xFF , mac [ 5 ] & 0xFF ) ;
return ( buf ) ;
}
@ -229,7 +262,8 @@ char * macaddr_str(macstr_t buf,
* REVISIT : This is a really bad idea . The edge will block completely while the
* hostname resolution is performed . This could take 15 seconds .
*/
int supernode2sock ( n2n_sock_t * sn , const n2n_sn_name_t addrIn ) {
int supernode2sock ( n2n_sock_t * sn , const n2n_sn_name_t addrIn ) {
n2n_sn_name_t addr ;
const char * supernode_host ;
int rv = 0 ;
@ -245,30 +279,26 @@ int supernode2sock(n2n_sock_t * sn, const n2n_sn_name_t addrIn) {
struct addrinfo * ainfo = NULL ;
int nameerr ;
if ( supernode_port ) {
if ( supernode_port ) {
sn - > port = atoi ( supernode_port ) ;
}
else
} else {
traceEvent ( TRACE_WARNING , " Bad supernode parameter (-l <host:port>) %s %s:%s " ,
addr , supernode_host , supernode_port ) ;
}
nameerr = getaddrinfo ( supernode_host , NULL , & aihints , & ainfo ) ;
if ( 0 = = nameerr )
{
if ( 0 = = nameerr ) {
struct sockaddr_in * saddr ;
/* ainfo s the head of a linked list if non-NULL. */
if ( ainfo & & ( PF_INET = = ainfo - > ai_family ) )
{
if ( ainfo & & ( PF_INET = = ainfo - > ai_family ) ) {
/* It is definitely and IPv4 address -> sockaddr_in */
saddr = ( struct sockaddr_in * ) ainfo - > ai_addr ;
memcpy ( sn - > addr . v4 , & ( saddr - > sin_addr . s_addr ) , IPV4_SIZE ) ;
sn - > family = AF_INET ;
}
else
{
sn - > family = AF_INET ;
} else {
/* Should only return IPv4 addresses due to aihints. */
traceEvent ( TRACE_WARNING , " Failed to resolve supernode IPv4 address for %s " , supernode_host ) ;
rv = - 1 ;
@ -291,15 +321,16 @@ int supernode2sock(n2n_sock_t * sn, const n2n_sn_name_t addrIn) {
/* ************************************** */
struct peer_info * add_sn_to_list_by_mac_or_sock ( struct peer_info * * sn_list , n2n_sock_t * sock , n2n_mac_t * mac , int * skip_add ) {
struct peer_info * add_sn_to_list_by_mac_or_sock ( struct peer_info * * sn_list , n2n_sock_t * sock , n2n_mac_t * mac , int * skip_add ) {
struct peer_info * scan , * tmp , * peer = NULL ;
if ( memcmp ( mac , null_mac , sizeof ( n2n_mac_t ) ) ! = 0 ) { /* not zero MAC */
if ( memcmp ( mac , null_mac , sizeof ( n2n_mac_t ) ) ! = 0 ) { /* not zero MAC */
HASH_FIND_PEER ( * sn_list , mac , peer ) ;
}
if ( peer = = NULL ) { /* zero MAC, search by socket */
HASH_ITER ( hh , * sn_list , scan , tmp ) {
HASH_ITER ( hh , * sn_list , scan , tmp ) {
if ( memcmp ( & ( scan - > sock ) , sock , sizeof ( n2n_sock_t ) ) = = 0 ) {
HASH_DEL ( * sn_list , scan ) ;
memcpy ( & ( scan - > mac_addr ) , mac , sizeof ( n2n_mac_t ) ) ;
@ -310,11 +341,11 @@ struct peer_info* add_sn_to_list_by_mac_or_sock(struct peer_info **sn_list, n2n_
}
if ( ( peer = = NULL ) & & ( * skip_add = = SN_ADD ) ) {
peer = ( struct peer_info * ) calloc ( 1 , sizeof ( struct peer_info ) ) ;
peer = ( struct peer_info * ) calloc ( 1 , sizeof ( struct peer_info ) ) ;
if ( peer ) {
sn_selection_criterion_default ( & ( peer - > selection_criterion ) ) ;
memcpy ( & ( peer - > sock ) , sock , sizeof ( n2n_sock_t ) ) ;
memcpy ( & ( peer - > mac_addr ) , mac , sizeof ( n2n_mac_t ) ) ;
memcpy ( & ( peer - > sock ) , sock , sizeof ( n2n_sock_t ) ) ;
memcpy ( & ( peer - > mac_addr ) , mac , sizeof ( n2n_mac_t ) ) ;
HASH_ADD_PEER ( * sn_list , peer ) ;
* skip_add = SN_ADD_ADDED ;
}
@ -326,14 +357,13 @@ struct peer_info* add_sn_to_list_by_mac_or_sock(struct peer_info **sn_list, n2n_
/* ************************************************ */
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_multicast = ( memcmp ( multicast_addr , dest_mac , 3 ) = = 0 ) ;
int is_ipv6_multicast = ( memcmp ( ipv6_multicast_addr , dest_mac , 2 ) = = 0 ) ;
int is_broadcast = ( memcmp ( broadcast_addr , dest_mac , 6 ) = = 0 ) ;
int is_multicast = ( memcmp ( multicast_addr , dest_mac , 3 ) = = 0 ) ;
int is_ipv6_multicast = ( memcmp ( ipv6_multicast_addr , dest_mac , 2 ) = = 0 ) ;
return is_broadcast | | is_multicast | | is_ipv6_multicast ;
}
/* http://www.faqs.org/rfcs/rfc908.html */
@ -341,7 +371,8 @@ uint8_t is_multi_broadcast(const uint8_t * dest_mac) {
/* *********************************************** */
char * msg_type2str ( uint16_t msg_type ) {
char * msg_type2str ( uint16_t msg_type ) {
switch ( msg_type ) {
case MSG_TYPE_REGISTER : return ( " MSG_TYPE_REGISTER " ) ;
case MSG_TYPE_DEREGISTER : return ( " MSG_TYPE_DEREGISTER " ) ;
@ -359,14 +390,19 @@ char* msg_type2str(uint16_t msg_type) {
/* *********************************************** */
void hexdump ( const uint8_t * buf , size_t len ) {
void hexdump ( const uint8_t * buf , size_t len ) {
size_t i ;
if ( 0 = = len ) { return ; }
if ( 0 = = len ) {
return ;
}
printf ( " ----------------------------------------------- \n " ) ;
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 ( " \n " ) ;
@ -376,7 +412,8 @@ 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 "
" Built on %s \n "
" Copyright 2007-2020 - ntop.org and contributors \n \n " ,
@ -385,15 +422,18 @@ void print_n2n_version() {
/* *********************************************** */
size_t purge_expired_registrations ( struct peer_info * * peer_list , time_t * p_last_purge , int timeout ) {
size_t purge_expired_registrations ( struct peer_info * * peer_list , time_t * p_last_purge , int timeout ) {
time_t now = time ( NULL ) ;
size_t num_reg = 0 ;
if ( ( now - ( * p_last_purge ) ) < timeout ) return 0 ;
if ( ( now - ( * p_last_purge ) ) < timeout ) {
return 0 ;
}
traceEvent ( TRACE_DEBUG , " Purging old registrations " ) ;
num_reg = purge_peer_list ( peer_list , now - REGISTRATION_TIMEOUT ) ;
num_reg = purge_peer_list ( peer_list , now - REGISTRATION_TIMEOUT ) ;
( * p_last_purge ) = now ;
traceEvent ( TRACE_DEBUG , " Remove %ld registrations " , num_reg ) ;
@ -402,14 +442,14 @@ size_t purge_expired_registrations(struct peer_info ** peer_list, time_t* p_last
}
/** 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 ,
time_t purge_before )
{
size_t purge_peer_list ( struct peer_info * * peer_list ,
time_t purge_before ) {
struct peer_info * scan , * tmp ;
size_t retval = 0 ;
size_t retval = 0 ;
HASH_ITER ( hh , * peer_list , scan , tmp ) {
if ( scan - > purgeable = = SN_PURGEABLE & & scan - > last_seen < purge_before ) {
if ( ( scan - > purgeable = = SN_PURGEABLE ) & & ( scan - > last_seen < purge_before ) ) {
HASH_DEL ( * peer_list , scan ) ;
retval + + ;
free ( scan ) ;
@ -420,10 +460,10 @@ 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. */
size_t clear_peer_list ( struct peer_info * * peer_list )
{
size_t clear_peer_list ( struct peer_info * * peer_list ) {
struct peer_info * scan , * tmp ;
size_t retval = 0 ;
size_t retval = 0 ;
HASH_ITER ( hh , * peer_list , scan , tmp ) {
HASH_DEL ( * peer_list , scan ) ;
@ -434,41 +474,43 @@ size_t clear_peer_list(struct peer_info ** peer_list)
return retval ;
}
static uint8_t hex2byte ( const char * s )
{
static uint8_t hex2byte ( const char * s ) {
char tmp [ 3 ] ;
tmp [ 0 ] = s [ 0 ] ;
tmp [ 1 ] = s [ 1 ] ;
tmp [ 2 ] = 0 ; /* NULL term */
tmp [ 0 ] = s [ 0 ] ;
tmp [ 1 ] = s [ 1 ] ;
tmp [ 2 ] = 0 ; /* NULL term */
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 ;
/* break it down as one case for the first "HH", the 5 x through loop for
* each " :HH " where HH is a two hex nibbles in ASCII . */
* outmac = hex2byte ( s ) ;
* outmac = hex2byte ( s ) ;
+ + 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 )
{
s + = 1 ;
* outmac = hex2byte ( s ) ;
for ( i = 1 ; i < 6 ; + + i ) {
s + = 1 ;
* outmac = hex2byte ( s ) ;
+ + outmac ;
s + = 2 ;
s + = 2 ;
}
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 ) {
if ( NULL = = out ) { return NULL ; }
if ( NULL = = out ) {
return NULL ;
}
memset ( out , 0 , N2N_SOCKBUF_SIZE ) ;
if ( AF_INET6 = = sock - > family ) {
@ -488,31 +530,42 @@ extern char * sock_to_cstr(n2n_sock_str_t out,
}
}
char * ip_subnet_to_str ( dec_ip_bit_str_t buf , const n2n_ip_subnet_t * ipaddr ) {
char * ip_subnet_to_str ( dec_ip_bit_str_t buf , const n2n_ip_subnet_t * ipaddr ) {
snprintf ( buf , sizeof ( dec_ip_bit_str_t ) , " %hhu.%hhu.%hhu.%hhu/%hhu " ,
( uint8_t ) ( ( ipaddr - > net_addr > > 24 ) & 0xFF ) ,
( uint8_t ) ( ( ipaddr - > net_addr > > 16 ) & 0xFF ) ,
( uint8_t ) ( ( ipaddr - > net_addr > > 8 ) & 0xFF ) ,
( uint8_t ) ( ipaddr - > net_addr & 0xFF ) ,
ipaddr - > net_bitlen ) ;
return buf ;
}
/* @return 1 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 ) {
if ( a - > port ! = b - > port ) { return ( 0 ) ; }
if ( a - > family ! = b - > family ) { return ( 0 ) ; }
if ( a - > port ! = b - > port ) {
return ( 0 ) ;
}
if ( a - > family ! = b - > family ) {
return ( 0 ) ;
}
switch ( a - > family ) {
case AF_INET :
if ( memcmp ( a - > addr . v4 , b - > addr . v4 , IPV4_SIZE ) )
if ( memcmp ( a - > addr . v4 , b - > addr . v4 , IPV4_SIZE ) ) {
return ( 0 ) ;
}
break ;
default :
if ( memcmp ( a - > addr . v6 , b - > addr . v6 , IPV6_SIZE ) )
if ( memcmp ( a - > addr . v6 , b - > addr . v6 , IPV6_SIZE ) ) {
return ( 0 ) ;
}
break ;
}
@ -523,10 +576,12 @@ int sock_equal(const n2n_sock_t * a,
/* *********************************************** */
# if defined(WIN32)
int gettimeofday ( struct timeval * tp , void * tzp ) {
int gettimeofday ( struct timeval * tp , void * tzp ) {
time_t clock ;
struct tm tm ;
SYSTEMTIME wtm ;
GetLocalTime ( & wtm ) ;
tm . tm_year = wtm . wYear - 1900 ;
tm . tm_mon = wtm . wMonth - 1 ;
@ -538,6 +593,7 @@ int gettimeofday(struct timeval *tp, void *tzp) {
clock = mktime ( & tm ) ;
tp - > tv_sec = clock ;
tp - > tv_usec = wtm . wMilliseconds * 1000 ;
return ( 0 ) ;
}
# endif
@ -567,7 +623,7 @@ uint64_t time_stamp (void) {
// returns an initial time stamp for use with replay protection
uint64_t initial_time_stamp ( void ) {
return ( time_stamp ( ) - TIME_STAMP_FRAME ) ;
return ( time_stamp ( ) - TIME_STAMP_FRAME ) ;
}
@ -593,8 +649,9 @@ int time_stamp_verify_and_update (uint64_t stamp, uint64_t * previous_stamp, int
* previous_stamp = ( * previous_stamp > > 12 ) < < 12 ;
diff = stamp - * previous_stamp ;
if ( allow_jitter )
if ( allow_jitter ) {
diff + = TIME_STAMP_JITTER ;
}
if ( diff < = 0 ) {
traceEvent ( TRACE_DEBUG , " time_stamp_verify_and_update found a timestamp too old compared to previous. " ) ;