|
|
@ -33,6 +33,7 @@ static const n2n_mac_t null_mac = {0, 0, 0, 0, 0, 0}; |
|
|
|
/* ************************************** */ |
|
|
|
|
|
|
|
SOCKET open_socket (int local_port, int bind_any) { |
|
|
|
|
|
|
|
SOCKET sock_fd; |
|
|
|
struct sockaddr_in local_address; |
|
|
|
int sockopt; |
|
|
@ -68,23 +69,28 @@ static int useSyslog = 0, syslog_opened = 0; |
|
|
|
static FILE *traceFile = NULL; |
|
|
|
|
|
|
|
int getTraceLevel () { |
|
|
|
|
|
|
|
return(traceLevel); |
|
|
|
} |
|
|
|
|
|
|
|
void setTraceLevel (int level) { |
|
|
|
|
|
|
|
traceLevel = level; |
|
|
|
} |
|
|
|
|
|
|
|
void setUseSyslog (int use_syslog) { |
|
|
|
|
|
|
|
useSyslog = use_syslog; |
|
|
|
} |
|
|
|
|
|
|
|
void setTraceFile (FILE *f) { |
|
|
|
|
|
|
|
traceFile = f; |
|
|
|
} |
|
|
|
|
|
|
|
void closeTraceFile () { |
|
|
|
if (traceFile != NULL && traceFile != stdout) { |
|
|
|
|
|
|
|
if((traceFile != NULL) && (traceFile != stdout)) { |
|
|
|
fclose(traceFile); |
|
|
|
} |
|
|
|
#ifndef WIN32 |
|
|
@ -97,10 +103,12 @@ void closeTraceFile() { |
|
|
|
|
|
|
|
#define N2N_TRACE_DATESIZE 32 |
|
|
|
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]; |
|
|
@ -123,12 +131,15 @@ void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...) { |
|
|
|
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); |
|
|
@ -160,6 +181,7 @@ 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 *cp, *retStr; |
|
|
|
uint8_t byteval; |
|
|
|
int n; |
|
|
@ -175,9 +197,10 @@ 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); |
|
|
@ -191,22 +214,31 @@ char* intoa(uint32_t /* host order */ addr, char* buf, uint16_t buf_len) { |
|
|
|
|
|
|
|
/** Convert subnet prefix bit length to host order subnet mask. */ |
|
|
|
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 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; |
|
|
|
} |
|
|
|
|
|
|
@ -214,11 +246,12 @@ uint8_t mask2bitlen(uint32_t mask) { |
|
|
|
/* *********************************************** */ |
|
|
|
|
|
|
|
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", |
|
|
|
mac[0] & 0xFF, mac[1] & 0xFF, mac[2] & 0xFF, |
|
|
|
mac[3] & 0xFF, mac[4] & 0xFF, mac[5] & 0xFF); |
|
|
|
|
|
|
|
return(buf); |
|
|
|
} |
|
|
|
|
|
|
@ -230,6 +263,7 @@ char * macaddr_str(macstr_t buf, |
|
|
|
* hostname resolution is performed. This could take 15 seconds. |
|
|
|
*/ |
|
|
|
int supernode2sock (n2n_sock_t * sn, const n2n_sn_name_t addrIn) { |
|
|
|
|
|
|
|
n2n_sn_name_t addr; |
|
|
|
const char *supernode_host; |
|
|
|
int rv = 0; |
|
|
@ -247,28 +281,24 @@ int supernode2sock(n2n_sock_t * sn, const n2n_sn_name_t addrIn) { |
|
|
|
|
|
|
|
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 |
|
|
|
{ |
|
|
|
} else { |
|
|
|
/* Should only return IPv4 addresses due to aihints. */ |
|
|
|
traceEvent(TRACE_WARNING, "Failed to resolve supernode IPv4 address for %s", supernode_host); |
|
|
|
rv = -1; |
|
|
@ -292,6 +322,7 @@ 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 *scan, *tmp, *peer = NULL; |
|
|
|
|
|
|
|
if(memcmp(mac, null_mac, sizeof(n2n_mac_t)) != 0) { /* not zero MAC */ |
|
|
@ -333,7 +364,6 @@ uint8_t is_multi_broadcast(const uint8_t * dest_mac) { |
|
|
|
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 */ |
|
|
@ -342,6 +372,7 @@ uint8_t is_multi_broadcast(const uint8_t * dest_mac) { |
|
|
|
/* *********************************************** */ |
|
|
|
|
|
|
|
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"); |
|
|
@ -360,13 +391,18 @@ char* msg_type2str(uint16_t msg_type) { |
|
|
|
/* *********************************************** */ |
|
|
|
|
|
|
|
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"); |
|
|
@ -377,6 +413,7 @@ void hexdump(const uint8_t *buf, size_t len) { |
|
|
|
/* *********************************************** */ |
|
|
|
|
|
|
|
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", |
|
|
@ -386,10 +423,13 @@ void print_n2n_version() { |
|
|
|
/* *********************************************** */ |
|
|
|
|
|
|
|
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"); |
|
|
|
|
|
|
@ -403,13 +443,13 @@ 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) |
|
|
|
{ |
|
|
|
time_t purge_before) { |
|
|
|
|
|
|
|
struct peer_info *scan, *tmp; |
|
|
|
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,8 +460,8 @@ 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; |
|
|
|
|
|
|
@ -434,8 +474,8 @@ 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]; |
|
|
@ -444,8 +484,8 @@ static uint8_t hex2byte(const char * s) |
|
|
|
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
|
|
|
@ -455,8 +495,7 @@ extern int str2mac(uint8_t * outmac /* 6 bytes */, const char * s) |
|
|
|
++outmac; |
|
|
|
s += 2; /* don't skip colon yet - helps generalise loop. */ |
|
|
|
|
|
|
|
for(i=1; i<6; ++i) |
|
|
|
{ |
|
|
|
for(i = 1; i < 6; ++i) { |
|
|
|
s += 1; |
|
|
|
*outmac = hex2byte(s); |
|
|
|
++outmac; |
|
|
@ -468,7 +507,10 @@ extern int str2mac(uint8_t * outmac /* 6 bytes */, const char * s) |
|
|
|
|
|
|
|
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) { |
|
|
@ -489,12 +531,14 @@ 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) { |
|
|
|
|
|
|
|
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; |
|
|
|
} |
|
|
|
|
|
|
@ -502,17 +546,26 @@ char *ip_subnet_to_str(dec_ip_bit_str_t buf, const n2n_ip_subnet_t *ipaddr) { |
|
|
|
/* @return 1 if the two sockets are equivalent. */ |
|
|
|
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; |
|
|
|
} |
|
|
|
|
|
|
@ -524,9 +577,11 @@ int sock_equal(const n2n_sock_t * a, |
|
|
|
|
|
|
|
#if defined(WIN32) |
|
|
|
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 |
|
|
@ -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."); |
|
|
|