|
@ -1,11 +1,11 @@ |
|
|
/*
|
|
|
/*
|
|
|
* (C) 2007-09 - Luca Deri <deri@ntop.org> |
|
|
*(C) 2007-09 - Luca Deri <deri@ntop.org> |
|
|
* Richard Andrews <andrews@ntop.org> |
|
|
* 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 |
|
|
* the Free Software Foundation; either version 3 of the License, or |
|
|
* the Free Software Foundation; either version 3 of the License, or |
|
|
* (at your option) any later version. |
|
|
*(at your option) any later version. |
|
|
* |
|
|
* |
|
|
* This program is distributed in the hope that it will be useful, |
|
|
* This program is distributed in the hope that it will be useful, |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
@ -32,7 +32,7 @@ |
|
|
# define REGISTRATION_TIMEOUT 120 |
|
|
# define REGISTRATION_TIMEOUT 120 |
|
|
#else /* #if defined(DEBUG) */ |
|
|
#else /* #if defined(DEBUG) */ |
|
|
# define PURGE_REGISTRATION_FREQUENCY 60 |
|
|
# define PURGE_REGISTRATION_FREQUENCY 60 |
|
|
# define REGISTRATION_TIMEOUT (60*20) |
|
|
# define REGISTRATION_TIMEOUT (60*20) |
|
|
#endif /* #if defined(DEBUG) */ |
|
|
#endif /* #if defined(DEBUG) */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -57,13 +57,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); |
|
|
} |
|
|
} |
|
@ -89,11 +89,11 @@ void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...) { |
|
|
char *extra_msg = ""; |
|
|
char *extra_msg = ""; |
|
|
time_t theTime = time(NULL); |
|
|
time_t theTime = time(NULL); |
|
|
#ifdef WIN32 |
|
|
#ifdef WIN32 |
|
|
int i; |
|
|
int i; |
|
|
#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 +101,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); |
|
|
|
|
|
|
|
@ -128,7 +128,7 @@ void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...) { |
|
|
} |
|
|
} |
|
|
#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 [%11s:%4d] %s%s", theDate, &file[i], line, extra_msg, buf); |
|
|
snprintf(out_buf, sizeof(out_buf), "%s [%11s:%4d] %s%s", theDate, &file[i], line, extra_msg, buf); |
|
|
printf("%s\n", out_buf); |
|
|
printf("%s\n", out_buf); |
|
|
fflush(stdout); |
|
|
fflush(stdout); |
|
@ -153,42 +153,42 @@ 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, |
|
|
mac[3] & 0xFF, mac[4] & 0xFF, mac[5] & 0xFF); |
|
|
mac[3] & 0xFF, mac[4] & 0xFF, mac[5] & 0xFF); |
|
|
return(buf); |
|
|
return(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; |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -217,17 +217,17 @@ 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; |
|
|
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); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
printf("\n"); |
|
|
printf("\n"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* *********************************************** */ |
|
|
/* *********************************************** */ |
|
@ -248,11 +248,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 +266,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 +284,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 +293,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 +302,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 +311,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,46 +350,46 @@ 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; |
|
|
size_t retval=0; |
|
|
size_t retval=0; |
|
|
|
|
|
|
|
|
scan = *peer_list; |
|
|
scan = *peer_list; |
|
|
prev = NULL; |
|
|
prev = NULL; |
|
|
while(scan != NULL) |
|
|
while(scan != NULL) |
|
|
{ |
|
|
{ |
|
|
struct peer_info *next = scan->next; |
|
|
struct peer_info *next = scan->next; |
|
|
|
|
|
|
|
|
if(prev == NULL) |
|
|
if(prev == NULL) |
|
|
{ |
|
|
{ |
|
|
*peer_list = next; |
|
|
*peer_list = next; |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
prev->next = next; |
|
|
prev->next = next; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
++retval; |
|
|
++retval; |
|
|
free(scan); |
|
|
free(scan); |
|
|
scan = next; |
|
|
scan = next; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
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 +400,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,45 +411,49 @@ 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 ) |
|
|
{ |
|
|
{ |
|
|
int r; |
|
|
int r; |
|
|
|
|
|
|
|
|
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 ) |
|
|
{ |
|
|
{ |
|
|
/* INET6 not written yet */ |
|
|
/* INET6 not written yet */ |
|
|
r = snprintf( out, N2N_SOCKBUF_SIZE, "XXXX:%hu", sock->port ); |
|
|
r = 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", |
|
|
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 ); |
|
|
(unsigned short)(a[0] & 0xff), |
|
|
return out; |
|
|
(unsigned short)(a[1] & 0xff), |
|
|
|
|
|
(unsigned short)(a[2] & 0xff), |
|
|
|
|
|
(unsigned short)(a[3] & 0xff), |
|
|
|
|
|
(unsigned short)sock->port ); |
|
|
|
|
|
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) /* they are the same */ |
|
|
{ |
|
|
{ |
|
|
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; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|