@ -32,14 +32,15 @@ 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 ;
SOCKET sock_fd ;
struct sockaddr_in local_address ;
struct sockaddr_in local_address ;
int sockopt ;
int sockopt ;
if ( ( sock_fd = socket ( PF_INET , SOCK_DGRAM , 0 ) ) < 0 ) {
if ( ( sock_fd = socket ( PF_INET , SOCK_DGRAM , 0 ) ) < 0 ) {
traceEvent ( TRACE_ERROR , " Unable to create socket [%s][%d] \n " ,
traceEvent ( TRACE_ERROR , " Unable to create socket [%s][%d] \n " ,
strerror ( errno ) , sock_fd ) ;
strerror ( errno ) , sock_fd ) ;
return ( - 1 ) ;
return ( - 1 ) ;
}
}
@ -67,28 +68,33 @@ static int traceLevel = 2 /* NORMAL */;
static int useSyslog = 0 , syslog_opened = 0 ;
static int useSyslog = 0 , syslog_opened = 0 ;
static FILE * traceFile = NULL ;
static FILE * traceFile = NULL ;
int getTraceLevel ( ) {
int getTraceLevel ( ) {
return ( traceLevel ) ;
return ( traceLevel ) ;
}
}
void setTraceLevel ( int level ) {
void setTraceLevel ( int level ) {
traceLevel = level ;
traceLevel = level ;
}
}
void setUseSyslog ( int use_syslog ) {
void setUseSyslog ( int use_syslog ) {
useSyslog = use_syslog ;
useSyslog = use_syslog ;
}
}
void setTraceFile ( FILE * f ) {
void setTraceFile ( FILE * f ) {
traceFile = f ;
traceFile = f ;
}
}
void closeTraceFile ( ) {
void closeTraceFile ( ) {
if ( traceFile ! = NULL & & traceFile ! = stdout ) {
if ( ( traceFile ! = NULL ) & & ( traceFile ! = stdout ) ) {
fclose ( traceFile ) ;
fclose ( traceFile ) ;
}
}
# ifndef WIN32
# ifndef WIN32
if ( useSyslog & & syslog_opened ) {
if ( useSyslog & & syslog_opened ) {
closelog ( ) ;
closelog ( ) ;
syslog_opened = 0 ;
syslog_opened = 0 ;
}
}
@ -96,11 +102,13 @@ void closeTraceFile() {
}
}
# define N2N_TRACE_DATESIZE 32
# 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 ;
va_list va_ap ;
if ( traceFile = = NULL )
if ( traceFile = = NULL ) {
traceFile = stdout ;
traceFile = stdout ;
}
if ( eventTraceLevel < = traceLevel ) {
if ( eventTraceLevel < = traceLevel ) {
char buf [ 1024 ] ;
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 ) ) ;
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 ) ;
if ( eventTraceLevel = = 0 /* TRACE_ERROR */ )
if ( eventTraceLevel = = 0 /* TRACE_ERROR */ ) {
extra_msg = " ERROR: " ;
extra_msg = " ERROR: " ;
else if ( eventTraceLevel = = 1 /* TRACE_WARNING */ )
} else if ( eventTraceLevel = = 1 /* TRACE_WARNING */ ) {
extra_msg = " 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
# ifndef WIN32
if ( useSyslog ) {
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 ) ;
snprintf ( out_buf , sizeof ( out_buf ) , " %s%s " , extra_msg , buf ) ;
syslog ( LOG_INFO , " %s " , out_buf ) ;
syslog ( LOG_INFO , " %s " , out_buf ) ;
} else {
} else {
for ( i = strlen ( file ) - 1 ; i > 0 ; i - - ) if ( file [ i ] = = ' / ' ) { i + + ; break ; } ;
for ( i = strlen ( file ) - 1 ; i > 0 ; i - - ) {
snprintf ( out_buf , sizeof ( out_buf ) , " %s [%s:%d] %s%s " , theDate , & file [ i ] , line , extra_msg , buf ) ;
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 ) ;
fprintf ( traceFile , " %s \n " , out_buf ) ;
fflush ( traceFile ) ;
fflush ( traceFile ) ;
}
}
# else
# else
/* this is the WIN32 code */
/* 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 ) ;
snprintf ( out_buf , sizeof ( out_buf ) , " %s [%s:%d] %s%s " , theDate , & file [ i ] , line , extra_msg , buf ) ;
fprintf ( traceFile , " %s \n " , out_buf ) ;
fprintf ( traceFile , " %s \n " , out_buf ) ;
fflush ( traceFile ) ;
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. */
/* 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 ;
char * cp , * retStr ;
uint8_t byteval ;
uint8_t byteval ;
int n ;
int n ;
@ -175,50 +197,61 @@ char* intoa(uint32_t /* host order */ addr, char* buf, uint16_t buf_len) {
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 ) ;
}
}
/** Convert subnet prefix bit length to host order subnet mask. */
/** 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 ;
uint8_t i ;
for ( i = 1 ; i < = bitlen ; + + i ) {
uint32_t mask = 0 ;
mask | = 1 < < ( 32 - i ) ;
}
for ( i = 1 ; i < = bitlen ; + + i ) {
return mask ;
mask | = 1 < < ( 32 - i ) ;
}
return mask ;
}
}
/** Convert host order subnet mask to subnet prefix bit length. */
/** 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 ) {
uint8_t i , bitlen = 0 ;
if ( ( mask < < i ) & 0x80000000 ) + + bitlen ;
else break ;
for ( i = 0 ; i < 32 ; + + i ) {
}
if ( ( mask < < i ) & 0x80000000 ) {
return bitlen ;
+ + bitlen ;
} else {
break ;
}
}
return bitlen ;
}
}
/* *********************************************** */
/* *********************************************** */
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 ,
mac [ 3 ] & 0xFF , mac [ 4 ] & 0xFF , mac [ 5 ] & 0xFF ) ;
mac [ 3 ] & 0xFF , mac [ 4 ] & 0xFF , mac [ 5 ] & 0xFF ) ;
return ( buf ) ;
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
* REVISIT : This is a really bad idea . The edge will block completely while the
* hostname resolution is performed . This could take 15 seconds .
* 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 ;
n2n_sn_name_t addr ;
const char * supernode_host ;
const char * supernode_host ;
int rv = 0 ;
int rv = 0 ;
@ -245,38 +279,34 @@ int supernode2sock(n2n_sock_t * sn, const n2n_sn_name_t addrIn) {
struct addrinfo * ainfo = NULL ;
struct addrinfo * ainfo = NULL ;
int nameerr ;
int nameerr ;
if ( supernode_port ) {
if ( supernode_port ) {
sn - > port = atoi ( supernode_port ) ;
sn - > port = atoi ( supernode_port ) ;
}
} else {
else
traceEvent ( TRACE_WARNING , " Bad supernode parameter (-l <host:port>) %s %s:%s " ,
traceEvent ( TRACE_WARNING , " Bad supernode parameter (-l <host:port>) %s %s:%s " ,
addr , supernode_host , supernode_port ) ;
addr , supernode_host , supernode_port ) ;
}
nameerr = getaddrinfo ( supernode_host , NULL , & aihints , & ainfo ) ;
nameerr = getaddrinfo ( supernode_host , NULL , & aihints , & ainfo ) ;
if ( 0 = = nameerr )
if ( 0 = = nameerr ) {
{
struct sockaddr_in * saddr ;
struct sockaddr_in * saddr ;
/* ainfo s the head of a linked list if non-NULL. */
/* 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 ;
/* 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 ;
memcpy ( sn - > addr . v4 , & ( saddr - > sin_addr . s_addr ) , IPV4_SIZE ) ;
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 ;
}
freeaddrinfo ( ainfo ) ; /* free everything allocated by getaddrinfo(). */
ainfo = NULL ;
} else {
} else {
/* Should only return IPv4 addresses due to aihints. */
traceEvent ( TRACE_WARNING , " Failed to resolve supernode IPv4 address for %s " , supernode_host ) ;
rv = - 1 ;
}
freeaddrinfo ( ainfo ) ; /* free everything allocated by getaddrinfo(). */
ainfo = NULL ;
} else {
traceEvent ( TRACE_WARNING , " Failed to resolve supernode host %s, %d: %s " , supernode_host , nameerr , gai_strerror ( nameerr ) ) ;
traceEvent ( TRACE_WARNING , " Failed to resolve supernode host %s, %d: %s " , supernode_host , nameerr , gai_strerror ( nameerr ) ) ;
rv = - 2 ;
rv = - 2 ;
}
}
@ -291,49 +321,49 @@ 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 ;
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 ) ;
HASH_FIND_PEER ( * sn_list , mac , peer ) ;
}
}
if ( peer = = NULL ) { /* zero MAC, search by socket */
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 ) {
if ( memcmp ( & ( scan - > sock ) , sock , sizeof ( n2n_sock_t ) ) = = 0 ) {
HASH_DEL ( * sn_list , scan ) ;
HASH_DEL ( * sn_list , scan ) ;
memcpy ( & ( scan - > mac_addr ) , mac , sizeof ( n2n_mac_t ) ) ;
memcpy ( & ( scan - > mac_addr ) , mac , sizeof ( n2n_mac_t ) ) ;
HASH_ADD_PEER ( * sn_list , scan ) ;
HASH_ADD_PEER ( * sn_list , scan ) ;
peer = scan ;
peer = scan ;
break ;
break ;
}
}
}
}
if ( ( peer = = NULL ) & & ( * skip_add = = SN_ADD ) ) {
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 ) {
if ( peer ) {
sn_selection_criterion_default ( & ( peer - > selection_criterion ) ) ;
sn_selection_criterion_default ( & ( peer - > selection_criterion ) ) ;
memcpy ( & ( peer - > sock ) , sock , sizeof ( n2n_sock_t ) ) ;
memcpy ( & ( peer - > sock ) , sock , sizeof ( n2n_sock_t ) ) ;
memcpy ( & ( peer - > mac_addr ) , mac , sizeof ( n2n_mac_t ) ) ;
memcpy ( & ( peer - > mac_addr ) , mac , sizeof ( n2n_mac_t ) ) ;
HASH_ADD_PEER ( * sn_list , peer ) ;
HASH_ADD_PEER ( * sn_list , peer ) ;
* skip_add = SN_ADD_ADDED ;
* skip_add = SN_ADD_ADDED ;
}
}
}
}
}
}
return peer ;
return peer ;
}
}
/* ************************************************ */
/* ************************************************ */
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 ;
}
}
/* http://www.faqs.org/rfcs/rfc908.html */
/* http://www.faqs.org/rfcs/rfc908.html */
@ -341,17 +371,18 @@ 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 ) {
switch ( msg_type ) {
case MSG_TYPE_REGISTER : return ( " MSG_TYPE_REGISTER " ) ;
case MSG_TYPE_REGISTER : return ( " MSG_TYPE_REGISTER " ) ;
case MSG_TYPE_DEREGISTER : return ( " MSG_TYPE_DEREGISTER " ) ;
case MSG_TYPE_DEREGISTER : return ( " MSG_TYPE_DEREGISTER " ) ;
case MSG_TYPE_PACKET : return ( " MSG_TYPE_PACKET " ) ;
case MSG_TYPE_PACKET : return ( " MSG_TYPE_PACKET " ) ;
case MSG_TYPE_REGISTER_ACK : return ( " MSG_TYPE_REGISTER_ACK " ) ;
case MSG_TYPE_REGISTER_ACK : return ( " MSG_TYPE_REGISTER_ACK " ) ;
case MSG_TYPE_REGISTER_SUPER : return ( " MSG_TYPE_REGISTER_SUPER " ) ;
case MSG_TYPE_REGISTER_SUPER : return ( " MSG_TYPE_REGISTER_SUPER " ) ;
case MSG_TYPE_REGISTER_SUPER_ACK : return ( " MSG_TYPE_REGISTER_SUPER_ACK " ) ;
case MSG_TYPE_REGISTER_SUPER_ACK : return ( " MSG_TYPE_REGISTER_SUPER_ACK " ) ;
case MSG_TYPE_REGISTER_SUPER_NAK : return ( " MSG_TYPE_REGISTER_SUPER_NAK " ) ;
case MSG_TYPE_REGISTER_SUPER_NAK : return ( " MSG_TYPE_REGISTER_SUPER_NAK " ) ;
case MSG_TYPE_FEDERATION : return ( " MSG_TYPE_FEDERATION " ) ;
case MSG_TYPE_FEDERATION : return ( " MSG_TYPE_FEDERATION " ) ;
default : return ( " ??? " ) ;
default : return ( " ??? " ) ;
}
}
return ( " ??? " ) ;
return ( " ??? " ) ;
@ -359,41 +390,50 @@ 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 ; }
size_t i ;
printf ( " ----------------------------------------------- \n " ) ;
if ( 0 = = len ) {
for ( i = 0 ; i < len ; i + + ) {
return ;
if ( ( i > 0 ) & & ( ( i % 16 ) = = 0 ) ) { printf ( " \n " ) ; }
}
printf ( " %02X " , buf [ i ] & 0xFF ) ;
}
printf ( " ----------------------------------------------- \n " ) ;
printf ( " \n " ) ;
for ( i = 0 ; i < len ; i + + ) {
printf ( " ----------------------------------------------- \n " ) ;
if ( ( i > 0 ) & & ( ( i % 16 ) = = 0 ) ) {
printf ( " \n " ) ;
}
printf ( " %02X " , buf [ i ] & 0xFF ) ;
}
printf ( " \n " ) ;
printf ( " ----------------------------------------------- \n " ) ;
}
}
/* *********************************************** */
/* *********************************************** */
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-2020 - ntop.org and contributors \n \n " ,
" Copyright 2007-2020 - ntop.org and contributors \n \n " ,
GIT_RELEASE , PACKAGE_OSNAME , PACKAGE_BUILDDATE ) ;
GIT_RELEASE , PACKAGE_OSNAME , PACKAGE_BUILDDATE ) ;
}
}
/* *********************************************** */
/* *********************************************** */
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 ) ;
time_t now = time ( NULL ) ;
size_t num_reg = 0 ;
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 " ) ;
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 ;
( * p_last_purge ) = now ;
traceEvent ( TRACE_DEBUG , " Remove %ld registrations " , num_reg ) ;
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. */
/** 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 , * tmp ;
struct peer_info * scan , * tmp ;
size_t retval = 0 ;
size_t retval = 0 ;
HASH_ITER ( hh , * peer_list , scan , tmp ) {
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 ) ;
HASH_DEL ( * peer_list , scan ) ;
retval + + ;
retval + + ;
free ( scan ) ;
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. */
/** 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 ;
struct peer_info * scan , * tmp ;
size_t retval = 0 ;
size_t retval = 0 ;
HASH_ITER ( hh , * peer_list , scan , tmp ) {
HASH_ITER ( hh , * peer_list , scan , tmp ) {
HASH_DEL ( * peer_list , scan ) ;
HASH_DEL ( * peer_list , scan ) ;
@ -434,41 +474,43 @@ 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 ;
/* break it down as one case for the first "HH", the 5 x through loop for
/* 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 . */
* each " :HH " where HH is a two hex nibbles in ASCII . */
* outmac = hex2byte ( s ) ;
* outmac = hex2byte ( 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 ) ;
+ + outmac ;
+ + outmac ;
s + = 2 ;
s + = 2 ;
}
}
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 ; }
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 ) {
@ -479,41 +521,52 @@ extern char * sock_to_cstr(n2n_sock_str_t out,
const uint8_t * a = sock - > addr . v4 ;
const uint8_t * a = sock - > addr . v4 ;
snprintf ( out , N2N_SOCKBUF_SIZE , " %hu.%hu.%hu.%hu:%hu " ,
snprintf ( out , N2N_SOCKBUF_SIZE , " %hu.%hu.%hu.%hu:%hu " ,
( unsigned short ) ( a [ 0 ] & 0xff ) ,
( unsigned short ) ( a [ 0 ] & 0xff ) ,
( unsigned short ) ( a [ 1 ] & 0xff ) ,
( unsigned short ) ( a [ 1 ] & 0xff ) ,
( unsigned short ) ( a [ 2 ] & 0xff ) ,
( unsigned short ) ( a [ 2 ] & 0xff ) ,
( unsigned short ) ( a [ 3 ] & 0xff ) ,
( unsigned short ) ( a [ 3 ] & 0xff ) ,
( unsigned short ) sock - > port ) ;
( unsigned short ) sock - > port ) ;
return out ;
return 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 ) ,
snprintf ( buf , sizeof ( dec_ip_bit_str_t ) , " %hhu.%hhu.%hhu.%hhu/%hhu " ,
( uint8_t ) ( ( ipaddr - > net_addr > > 16 ) & 0xFF ) ,
( uint8_t ) ( ( ipaddr - > net_addr > > 24 ) & 0xFF ) ,
( uint8_t ) ( ( ipaddr - > net_addr > > 8 ) & 0xFF ) ,
( uint8_t ) ( ( ipaddr - > net_addr > > 16 ) & 0xFF ) ,
( uint8_t ) ( ipaddr - > net_addr & 0xFF ) ,
( uint8_t ) ( ( ipaddr - > net_addr > > 8 ) & 0xFF ) ,
ipaddr - > net_bitlen ) ;
( uint8_t ) ( ipaddr - > net_addr & 0xFF ) ,
return buf ;
ipaddr - > net_bitlen ) ;
return buf ;
}
}
/* @return 1 if the two sockets are equivalent. */
/* @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 ) {
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 ) {
switch ( a - > family ) {
case AF_INET :
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 ) ;
return ( 0 ) ;
break ;
}
default :
break ;
if ( memcmp ( a - > addr . v6 , b - > addr . v6 , IPV6_SIZE ) )
return ( 0 ) ;
default :
break ;
if ( memcmp ( a - > addr . v6 , b - > addr . v6 , IPV6_SIZE ) ) {
return ( 0 ) ;
}
break ;
}
}
/* equal */
/* equal */
@ -523,10 +576,12 @@ int sock_equal(const n2n_sock_t * a,
/* *********************************************** */
/* *********************************************** */
# if defined(WIN32)
# if defined(WIN32)
int gettimeofday ( struct timeval * tp , void * tzp ) {
int gettimeofday ( struct timeval * tp , void * tzp ) {
time_t clock ;
time_t clock ;
struct tm tm ;
struct tm tm ;
SYSTEMTIME wtm ;
SYSTEMTIME wtm ;
GetLocalTime ( & wtm ) ;
GetLocalTime ( & wtm ) ;
tm . tm_year = wtm . wYear - 1900 ;
tm . tm_year = wtm . wYear - 1900 ;
tm . tm_mon = wtm . wMonth - 1 ;
tm . tm_mon = wtm . wMonth - 1 ;
@ -538,6 +593,7 @@ int gettimeofday(struct timeval *tp, void *tzp) {
clock = mktime ( & tm ) ;
clock = mktime ( & tm ) ;
tp - > tv_sec = clock ;
tp - > tv_sec = clock ;
tp - > tv_usec = wtm . wMilliseconds * 1000 ;
tp - > tv_usec = wtm . wMilliseconds * 1000 ;
return ( 0 ) ;
return ( 0 ) ;
}
}
# endif
# endif
@ -567,7 +623,7 @@ uint64_t time_stamp (void) {
// returns an initial time stamp for use with replay protection
// returns an initial time stamp for use with replay protection
uint64_t initial_time_stamp ( void ) {
uint64_t initial_time_stamp ( void ) {
return ( time_stamp ( ) - TIME_STAMP_FRAME ) ;
return ( time_stamp ( ) - TIME_STAMP_FRAME ) ;
}
}
@ -582,8 +638,8 @@ int time_stamp_verify_and_update (uint64_t stamp, uint64_t * previous_stamp, int
// abs()
// abs()
diff = ( diff < 0 ? - diff : diff ) ;
diff = ( diff < 0 ? - diff : diff ) ;
if ( diff > = TIME_STAMP_FRAME ) {
if ( diff > = TIME_STAMP_FRAME ) {
traceEvent ( TRACE_DEBUG , " time_stamp_verify_and_update found a timestamp out of allowed frame. " ) ;
traceEvent ( TRACE_DEBUG , " time_stamp_verify_and_update found a timestamp out of allowed frame. " ) ;
return ( 0 ) ; // failure
return ( 0 ) ; // failure
}
}
// if applicable: is it higher than previous time stamp (including allowed deviation of TIME_STAMP_JITTER)?
// if applicable: is it higher than previous time stamp (including allowed deviation of TIME_STAMP_JITTER)?
@ -593,8 +649,9 @@ int time_stamp_verify_and_update (uint64_t stamp, uint64_t * previous_stamp, int
* previous_stamp = ( * previous_stamp > > 12 ) < < 12 ;
* previous_stamp = ( * previous_stamp > > 12 ) < < 12 ;
diff = stamp - * previous_stamp ;
diff = stamp - * previous_stamp ;
if ( allow_jitter )
if ( allow_jitter ) {
diff + = TIME_STAMP_JITTER ;
diff + = TIME_STAMP_JITTER ;
}
if ( diff < = 0 ) {
if ( diff < = 0 ) {
traceEvent ( TRACE_DEBUG , " time_stamp_verify_and_update found a timestamp too old compared to previous. " ) ;
traceEvent ( TRACE_DEBUG , " time_stamp_verify_and_update found a timestamp too old compared to previous. " ) ;