edge_utils.c (n2n-3.0) | : | edge_utils.c (n2n-3.1.1) | ||
---|---|---|---|---|
/** | /** | |||
* (C) 2007-21 - ntop.org and contributors | * (C) 2007-22 - ntop.org and contributors | |||
* | * | |||
* 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 | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* 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 see <http://www.gnu.org/licenses/> | * along with this program; if not see see <http://www.gnu.org/licenses/> | |||
* | * | |||
*/ | */ | |||
#include "n2n.h" | #include "n2n.h" | |||
#include "network_traffic_filter.h" | #include "network_traffic_filter.h" | |||
#include "edge_utils_win32.h" | #include "edge_utils_win32.h" | |||
/* heap allocation for compression as per lzo example doc */ | ||||
#define HEAP_ALLOC(var,size) lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lz | ||||
o_align_t) - 1)) / sizeof(lzo_align_t) ] | ||||
static HEAP_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS); | ||||
/* ************************************** */ | /* ************************************** */ | |||
int resolve_create_thread (n2n_resolve_parameter_t **param, struct peer_info *sn _list); | int resolve_create_thread (n2n_resolve_parameter_t **param, struct peer_info *sn _list); | |||
int resolve_check (n2n_resolve_parameter_t *param, uint8_t resolution_request, t ime_t now); | int resolve_check (n2n_resolve_parameter_t *param, uint8_t resolution_request, t ime_t now); | |||
int resolve_cancel_thread (n2n_resolve_parameter_t *param); | int resolve_cancel_thread (n2n_resolve_parameter_t *param); | |||
#ifdef HAVE_PORT_FORWARDING | ||||
int port_map_create_thread (n2n_port_map_parameter_t **param, uint16_t mgmt_port | ||||
); | ||||
int port_map_cancel_thread (n2n_port_map_parameter_t *param); | ||||
#endif | ||||
static const char * supernode_ip (const n2n_edge_t * eee); | static const char * supernode_ip (const n2n_edge_t * eee); | |||
static void send_register (n2n_edge_t *eee, const n2n_sock_t *remote_peer, const n2n_mac_t peer_mac, n2n_cookie_t cookie); | static void send_register (n2n_edge_t *eee, const n2n_sock_t *remote_peer, const n2n_mac_t peer_mac, n2n_cookie_t cookie); | |||
static void check_peer_registration_needed (n2n_edge_t *eee, | static void check_peer_registration_needed (n2n_edge_t *eee, | |||
uint8_t from_supernode, | uint8_t from_supernode, | |||
uint8_t via_multicast, | uint8_t via_multicast, | |||
const n2n_mac_t mac, | const n2n_mac_t mac, | |||
const n2n_cookie_t cookie, | const n2n_cookie_t cookie, | |||
const n2n_ip_subnet_t *dev_addr, | const n2n_ip_subnet_t *dev_addr, | |||
const n2n_desc_t *dev_desc, | const n2n_desc_t *dev_desc, | |||
skipping to change at line 327 | skipping to change at line 328 | |||
memcpy(&eee->conf.preferred_sock, &local_sock, sizeof(n2n_sock_t )); | memcpy(&eee->conf.preferred_sock, &local_sock, sizeof(n2n_sock_t )); | |||
traceEvent(TRACE_INFO, "determined local socket [%s]", | traceEvent(TRACE_INFO, "determined local socket [%s]", | |||
sock_to_cstr(sockbuf, &local_sock)); | sock_to_cstr(sockbuf, &local_sock)); | |||
} | } | |||
} | } | |||
if(eee->cb.sock_opened) | if(eee->cb.sock_opened) | |||
eee->cb.sock_opened(eee); | eee->cb.sock_opened(eee); | |||
} | } | |||
#ifdef HAVE_PORT_FORWARDING | ||||
if(eee->conf.port_forwarding) | ||||
// REVISIT: replace with mgmt port notification to listener for mgmt por | ||||
t | ||||
// subscription support | ||||
n2n_chg_port_mapping(eee, eee->conf.preferred_sock.port); | ||||
#endif // HAVE_PORT_FORWARDING | ||||
return 0; | return 0; | |||
} | } | |||
// always closes the socket | // always closes the socket | |||
void supernode_disconnect (n2n_edge_t *eee) { | void supernode_disconnect (n2n_edge_t *eee) { | |||
if(eee->sock >= 0) { | if(eee->sock >= 0) { | |||
closesocket(eee->sock); | closesocket(eee->sock); | |||
eee->sock = -1; | eee->sock = -1; | |||
} | } | |||
skipping to change at line 375 | skipping to change at line 382 | |||
eee->start_time = time(NULL); | eee->start_time = time(NULL); | |||
eee->known_peers = NULL; | eee->known_peers = NULL; | |||
eee->pending_peers = NULL; | eee->pending_peers = NULL; | |||
reset_sup_attempts(eee); | reset_sup_attempts(eee); | |||
sn_selection_criterion_common_data_default(eee); | sn_selection_criterion_common_data_default(eee); | |||
pearson_hash_init(); | pearson_hash_init(); | |||
if(eee->conf.compression == N2N_COMPRESSION_ID_LZO) | // always initialize compression transforms so we can at least decompress | |||
if(lzo_init() != LZO_E_OK) { | rc = n2n_transop_lzo_init(&eee->conf, &eee->transop_lzo); | |||
traceEvent(TRACE_ERROR, "LZO compression error"); | if(rc) goto edge_init_error; /* error message is printed in lzo_init */ | |||
goto edge_init_error; | #ifdef HAVE_ZSTD | |||
} | rc = n2n_transop_zstd_init(&eee->conf, &eee->transop_zstd); | |||
#ifdef N2N_HAVE_ZSTD | if(rc) goto edge_init_error; /* error message is printed in zstd_init */ | |||
// zstd does not require initialization. if it were required, this would be | ||||
a good place | ||||
#endif | #endif | |||
traceEvent(TRACE_NORMAL, "number of supernodes in the list: %d\n", HASH_COUN T(eee->conf.supernodes)); | traceEvent(TRACE_NORMAL, "number of supernodes in the list: %d\n", HASH_COUN T(eee->conf.supernodes)); | |||
HASH_ITER(hh, eee->conf.supernodes, scan, tmp) { | HASH_ITER(hh, eee->conf.supernodes, scan, tmp) { | |||
traceEvent(TRACE_NORMAL, "supernode %u => %s\n", i, (scan->ip_addr)); | traceEvent(TRACE_NORMAL, "supernode %u => %s\n", i, (scan->ip_addr)); | |||
i++; | i++; | |||
} | } | |||
/* Set active transop */ | /* Set active transop */ | |||
switch(transop_id) { | switch(transop_id) { | |||
skipping to change at line 477 | skipping to change at line 483 | |||
eee->udp_multicast_sock = -1; | eee->udp_multicast_sock = -1; | |||
#endif | #endif | |||
if(edge_init_sockets(eee) < 0) { | if(edge_init_sockets(eee) < 0) { | |||
traceEvent(TRACE_ERROR, "socket setup failed"); | traceEvent(TRACE_ERROR, "socket setup failed"); | |||
goto edge_init_error; | goto edge_init_error; | |||
} | } | |||
if(resolve_create_thread(&(eee->resolve_parameter), eee->conf.supernodes) == 0) { | if(resolve_create_thread(&(eee->resolve_parameter), eee->conf.supernodes) == 0) { | |||
traceEvent(TRACE_NORMAL, "successfully created resolver thread"); | traceEvent(TRACE_NORMAL, "successfully created resolver thread"); | |||
} | } | |||
#ifdef HAVE_PORT_FORWARDING | ||||
if(eee->conf.port_forwarding) | ||||
if(port_map_create_thread(&eee->port_map_parameter, eee->conf.mgmt_port) | ||||
== 0) { | ||||
traceEvent(TRACE_NORMAL, "successfully created port mapping thread") | ||||
; | ||||
} | ||||
#endif // HAVE_MINIUPNP || HAVE_NATPMP | ||||
eee->network_traffic_filter = create_network_traffic_filter(); | eee->network_traffic_filter = create_network_traffic_filter(); | |||
network_traffic_filter_add_rule(eee->network_traffic_filter, eee->conf.netwo rk_traffic_filter_rules); | network_traffic_filter_add_rule(eee->network_traffic_filter, eee->conf.netwo rk_traffic_filter_rules); | |||
//edge_init_success: | //edge_init_success: | |||
*rv = 0; | *rv = 0; | |||
return(eee); | return(eee); | |||
edge_init_error: | edge_init_error: | |||
if(eee) | if(eee) | |||
free(eee); | free(eee); | |||
skipping to change at line 786 | skipping to change at line 797 | |||
if(scan) | if(scan) | |||
scan->last_cookie = N2N_NO_REG_COOKIE; | scan->last_cookie = N2N_NO_REG_COOKIE; | |||
} | } | |||
if(scan) { | if(scan) { | |||
HASH_DEL(eee->pending_peers, scan); | HASH_DEL(eee->pending_peers, scan); | |||
scan_tmp = find_peer_by_sock(peer, eee->known_peers); | scan_tmp = find_peer_by_sock(peer, eee->known_peers); | |||
if(scan_tmp != NULL) { | if(scan_tmp != NULL) { | |||
HASH_DEL(eee->known_peers, scan_tmp); | HASH_DEL(eee->known_peers, scan_tmp); | |||
mgmt_event_post(N2N_EVENT_PEER,N2N_EVENT_PEER_DEL_P2P,scan); | ||||
free(scan); | free(scan); | |||
scan = scan_tmp; | scan = scan_tmp; | |||
memcpy(scan->mac_addr, mac, sizeof(n2n_mac_t)); | memcpy(scan->mac_addr, mac, sizeof(n2n_mac_t)); | |||
// in case of MAC change, reset cookie to allow immediate re-registr ation | // in case of MAC change, reset cookie to allow immediate re-registr ation | |||
scan->last_cookie = N2N_NO_REG_COOKIE; | scan->last_cookie = N2N_NO_REG_COOKIE; | |||
} else { | } else { | |||
// update sock but ... | // update sock but ... | |||
// ... ignore ACKs's (and their socks) from lower ranked inbound way s for a while | // ... ignore ACKs's (and their socks) from lower ranked inbound way s for a while | |||
if(((now - scan->last_seen) > REGISTRATION_TIMEOUT / 4) | if(((now - scan->last_seen) > REGISTRATION_TIMEOUT / 4) | |||
||(cookie > scan->last_cookie)) { | ||(cookie > scan->last_cookie)) { | |||
scan->sock = *peer; | scan->sock = *peer; | |||
scan->last_cookie = cookie; | scan->last_cookie = cookie; | |||
} | } | |||
} | } | |||
HASH_ADD_PEER(eee->known_peers, scan); | HASH_ADD_PEER(eee->known_peers, scan); | |||
scan->last_p2p = now; | scan->last_p2p = now; | |||
mgmt_event_post(N2N_EVENT_PEER,N2N_EVENT_PEER_ADD_P2P,scan); | ||||
traceEvent(TRACE_DEBUG, "p2p connection established: %s [%s]", | traceEvent(TRACE_DEBUG, "p2p connection established: %s [%s]", | |||
macaddr_str(mac_buf, mac), | macaddr_str(mac_buf, mac), | |||
sock_to_cstr(sockbuf, peer)); | sock_to_cstr(sockbuf, peer)); | |||
traceEvent(TRACE_DEBUG, "new peer %s [%s]", | traceEvent(TRACE_DEBUG, "new peer %s [%s]", | |||
macaddr_str(mac_buf, scan->mac_addr), | macaddr_str(mac_buf, scan->mac_addr), | |||
sock_to_cstr(sockbuf, &(scan->sock))); | sock_to_cstr(sockbuf, &(scan->sock))); | |||
traceEvent(TRACE_DEBUG, "pending peers list size=%u", | traceEvent(TRACE_DEBUG, "pending peers list size=%u", | |||
skipping to change at line 963 | skipping to change at line 976 | |||
if(!sock_equal(&(scan->sock), peer)) { | if(!sock_equal(&(scan->sock), peer)) { | |||
if(!from_supernode) { | if(!from_supernode) { | |||
/* This is a P2P packet */ | /* This is a P2P packet */ | |||
traceEvent(TRACE_NORMAL, "peer %s changed [%s] -> [%s]", | traceEvent(TRACE_NORMAL, "peer %s changed [%s] -> [%s]", | |||
macaddr_str(mac_buf, scan->mac_addr), | macaddr_str(mac_buf, scan->mac_addr), | |||
sock_to_cstr(sockbuf1, &(scan->sock)), | sock_to_cstr(sockbuf1, &(scan->sock)), | |||
sock_to_cstr(sockbuf2, peer)); | sock_to_cstr(sockbuf2, peer)); | |||
/* The peer has changed public socket. It can no longer be assumed t o be reachable. */ | /* The peer has changed public socket. It can no longer be assumed t o be reachable. */ | |||
HASH_DEL(eee->known_peers, scan); | HASH_DEL(eee->known_peers, scan); | |||
mgmt_event_post(N2N_EVENT_PEER,N2N_EVENT_PEER_DEL_P2P,scan); | ||||
free(scan); | free(scan); | |||
register_with_new_peer(eee, from_supernode, via_multicast, mac, dev_ addr, dev_desc, peer); | register_with_new_peer(eee, from_supernode, via_multicast, mac, dev_ addr, dev_desc, peer); | |||
} else { | } else { | |||
/* Don't worry about what the supernode reports, it could be seeing a different socket. */ | /* Don't worry about what the supernode reports, it could be seeing a different socket. */ | |||
} | } | |||
} else | } else | |||
scan->last_seen = when; | scan->last_seen = when; | |||
} | } | |||
skipping to change at line 1519 | skipping to change at line 1533 | |||
} | } | |||
check_join_multicast_group(eee); | check_join_multicast_group(eee); | |||
if(0 == eee->sup_attempts) { | if(0 == eee->sup_attempts) { | |||
/* Give up on that supernode and try the next one. */ | /* Give up on that supernode and try the next one. */ | |||
sn_selection_criterion_bad(&(eee->curr_sn->selection_criterion)); | sn_selection_criterion_bad(&(eee->curr_sn->selection_criterion)); | |||
sn_selection_sort(&(eee->conf.supernodes)); | sn_selection_sort(&(eee->conf.supernodes)); | |||
eee->curr_sn = eee->conf.supernodes; | eee->curr_sn = eee->conf.supernodes; | |||
traceEvent(TRACE_WARNING, "supernode not responding, now trying [%s]", s upernode_ip(eee)); | traceEvent(TRACE_WARNING, "supernode not responding, now trying [%s]", s upernode_ip(eee)); | |||
supernode_connect(eee); | ||||
reset_sup_attempts(eee); | reset_sup_attempts(eee); | |||
// trigger out-of-schedule DNS resolution | // trigger out-of-schedule DNS resolution | |||
eee->resolution_request = 1; | eee->resolution_request = 1; | |||
// in some multi-NATed scenarios communication gets stuck on losing conn ection to supernode | // in some multi-NATed scenarios communication gets stuck on losing conn ection to supernode | |||
// closing and re-opening the socket allows for re-establishing communic ation | // closing and re-opening the socket allows for re-establishing communic ation | |||
// this can only be done, if working on some unprivileged port and/or ha ving sufficent | // this can only be done, if working on some unprivileged port and/or ha ving sufficent | |||
// privileges. as we are not able to check for sufficent privileges here , we only do it | // privileges. as we are not able to check for sufficent privileges here , we only do it | |||
// if port is sufficently high or unset. uncovered: privileged port and sufficent privileges | // if port is sufficently high or unset. uncovered: privileged port and sufficent privileges | |||
if((eee->conf.local_port == 0) || (eee->conf.local_port > 1024)) { | if((eee->conf.local_port == 0) || (eee->conf.local_port > 1024)) { | |||
skipping to change at line 1547 | skipping to change at line 1560 | |||
if(!cnt) { | if(!cnt) { | |||
// ... and then count the connection retries | // ... and then count the connection retries | |||
(eee->close_socket_counter)++; | (eee->close_socket_counter)++; | |||
if(eee->close_socket_counter >= N2N_CLOSE_SOCKET_COUNTER_MAX) { | if(eee->close_socket_counter >= N2N_CLOSE_SOCKET_COUNTER_MAX) { | |||
eee->close_socket_counter = 0; | eee->close_socket_counter = 0; | |||
supernode_disconnect(eee); | supernode_disconnect(eee); | |||
traceEvent(TRACE_DEBUG, "disconnected supernode"); | traceEvent(TRACE_DEBUG, "disconnected supernode"); | |||
} | } | |||
} | } | |||
supernode_connect(eee); | ||||
traceEvent(TRACE_DEBUG, "reconnected to supernode"); | traceEvent(TRACE_DEBUG, "reconnected to supernode"); | |||
} | } | |||
supernode_connect(eee); | ||||
} else { | } else { | |||
--(eee->sup_attempts); | --(eee->sup_attempts); | |||
} | } | |||
#ifndef HAVE_PTHREAD | #ifndef HAVE_PTHREAD | |||
if(supernode2sock(&(eee->curr_sn->sock), eee->curr_sn->ip_addr) == 0) { | if(supernode2sock(&(eee->curr_sn->sock), eee->curr_sn->ip_addr) == 0) { | |||
#endif | #endif | |||
traceEvent(TRACE_INFO, "registering with supernode [%s][number of supern odes %d][attempts left %u]", | traceEvent(TRACE_INFO, "registering with supernode [%s][number of supern odes %d][attempts left %u]", | |||
supernode_ip(eee), HASH_COUNT(eee->conf.supernodes), (unsigne d int)eee->sup_attempts); | supernode_ip(eee), HASH_COUNT(eee->conf.supernodes), (unsigne d int)eee->sup_attempts); | |||
skipping to change at line 1627 | skipping to change at line 1640 | |||
++(eee->stats.rx_sup); | ++(eee->stats.rx_sup); | |||
eee->last_sup = now; | eee->last_sup = now; | |||
} else { | } else { | |||
++(eee->stats.rx_p2p); | ++(eee->stats.rx_p2p); | |||
eee->last_p2p=now; | eee->last_p2p=now; | |||
} | } | |||
/* Handle transform. */ | /* Handle transform. */ | |||
{ | { | |||
uint8_t decodebuf[N2N_PKT_BUF_SIZE]; | uint8_t decode_buf[N2N_PKT_BUF_SIZE]; | |||
uint8_t deflate_buf[N2N_PKT_BUF_SIZE]; | ||||
size_t eth_size; | size_t eth_size; | |||
n2n_transform_t rx_transop_id; | n2n_transform_t rx_transop_id; | |||
uint8_t rx_compression_id; | uint8_t rx_compression_id; | |||
rx_transop_id = (n2n_transform_t)pkt->transform; | rx_transop_id = (n2n_transform_t)pkt->transform; | |||
rx_compression_id = pkt->compression; | rx_compression_id = pkt->compression; | |||
if(rx_transop_id == eee->conf.transop_id) { | if(rx_transop_id == eee->conf.transop_id) { | |||
uint8_t is_multicast; | uint8_t is_multicast; | |||
eth_payload = decodebuf; | // decrypt | |||
eh = (ether_hdr_t*)eth_payload; | eth_payload = decode_buf; | |||
eth_size = eee->transop.rev(&eee->transop, | eth_size = eee->transop.rev(&eee->transop, | |||
eth_payload, N2N_PKT_BUF_SIZE, | eth_payload, N2N_PKT_BUF_SIZE, | |||
payload, psize, pkt->srcMac); | payload, psize, pkt->srcMac); | |||
++(eee->transop.rx_cnt); /* stats */ | ++(eee->transop.rx_cnt); /* stats */ | |||
/* decompress if necessary */ | /* decompress if necessary */ | |||
uint8_t * deflation_buffer = 0; | size_t deflate_len; | |||
lzo_uint deflated_len; | ||||
switch(rx_compression_id) { | switch(rx_compression_id) { | |||
case N2N_COMPRESSION_ID_NONE: | case N2N_COMPRESSION_ID_NONE: | |||
break; // continue afterwards | break; // continue afterwards | |||
case N2N_COMPRESSION_ID_LZO: | case N2N_COMPRESSION_ID_LZO: | |||
deflation_buffer = malloc(N2N_PKT_BUF_SIZE); | deflate_len = eee->transop_lzo.rev(&eee->transop_lzo, | |||
lzo1x_decompress(eth_payload, eth_size, deflation_buffer, &d | deflate_buf, N2N_PKT_BUF_ | |||
eflated_len, NULL); | SIZE, | |||
decode_buf, eth_size, pkt | ||||
->srcMac); | ||||
break; | break; | |||
#ifdef N2N_HAVE_ZSTD | ||||
#ifdef HAVE_ZSTD | ||||
case N2N_COMPRESSION_ID_ZSTD: | case N2N_COMPRESSION_ID_ZSTD: | |||
deflated_len = N2N_PKT_BUF_SIZE; | deflate_len = eee->transop_zstd.rev(&eee->transop_zstd, | |||
deflation_buffer = malloc(deflated_len); | deflate_buf, N2N_PKT_BUF | |||
deflated_len = ZSTD_decompress(deflation_buffer, deflated_le | _SIZE, | |||
n, eth_payload, eth_size); | decode_buf, eth_size, pk | |||
if(ZSTD_isError(deflated_len)) { | t->srcMac); | |||
traceEvent(TRACE_WARNING, "payload decompression failed | ||||
with zstd error '%s'.", | ||||
ZSTD_getErrorName(deflated_len)); | ||||
free(deflation_buffer); | ||||
return(-1); // cannot help it | ||||
} | ||||
break; | break; | |||
#endif | #endif | |||
default: | default: | |||
traceEvent(TRACE_WARNING, "payload decompression failed: rec eived packet indicating unsupported %s compression.", | traceEvent(TRACE_WARNING, "payload decompression failed: rec eived packet indicating unsupported %s compression.", | |||
compression_str(rx_compression_id)); | compression_str(rx_compression_id)); | |||
return(-1); // cannot handle it | return(-1); // cannot handle it | |||
} | } | |||
if(rx_compression_id != N2N_COMPRESSION_ID_NONE) { | if(rx_compression_id != N2N_COMPRESSION_ID_NONE) { | |||
traceEvent(TRACE_DEBUG, "payload decompression %s: deflated %u b ytes to %u bytes", | traceEvent(TRACE_DEBUG, "payload decompression %s: deflated %u b ytes to %u bytes", | |||
compression_str(rx_compression_id), eth_size, (int)de | compression_str(rx_compression_id), eth_ | |||
flated_len); | size, (int)deflate_len); | |||
memcpy(eth_payload,deflation_buffer, deflated_len ); | eth_payload = deflate_buf; | |||
eth_size = deflated_len; | eth_size = deflate_len; | |||
free(deflation_buffer); | ||||
} | } | |||
eh = (ether_hdr_t*)eth_payload; | ||||
is_multicast = (is_ip6_discovery(eth_payload, eth_size) || is_ethMul ticast(eth_payload, eth_size)); | is_multicast = (is_ip6_discovery(eth_payload, eth_size) || is_ethMul ticast(eth_payload, eth_size)); | |||
if(eee->conf.drop_multicast && is_multicast) { | if(eee->conf.drop_multicast && is_multicast) { | |||
traceEvent(TRACE_INFO, "dropping RX multicast"); | traceEvent(TRACE_INFO, "dropping RX multicast"); | |||
return(-1); | return(-1); | |||
} else if((!eee->conf.allow_routing) && (!is_multicast)) { | } else if((!eee->conf.allow_routing) && (!is_multicast)) { | |||
/* Check if it is a routed packet */ | /* Check if it is a routed packet */ | |||
if((ntohs(eh->type) == 0x0800) && (eth_size >= ETH_FRAMESIZE + I P4_MIN_SIZE)) { | if((ntohs(eh->type) == 0x0800) && (eth_size >= ETH_FRAMESIZE + I P4_MIN_SIZE)) { | |||
uint32_t *dst = (uint32_t*)ð_payload[ETH_FRAMESIZE + IP4_ DSTOFFSET]; | uint32_t *dst = (uint32_t*)ð_payload[ETH_FRAMESIZE + IP4_ DSTOFFSET]; | |||
uint8_t *dst_mac = (uint8_t*)eth_payload; | uint8_t *dst_mac = (uint8_t*)eth_payload; | |||
/* Note: all elements of the_ip are in network order */ | /* Note: all elements of the_ip are in network order */ | |||
if(!memcmp(dst_mac, broadcast_mac, N2N_MAC_SIZE)) | if(!memcmp(dst_mac, broadcast_mac, N2N_MAC_SIZE)) | |||
traceEvent(TRACE_DEBUG, "RX broadcast packet destined to [%s]", | traceEvent(TRACE_DEBUG, "RX broadcast packet destined to [%s]", | |||
intoa(ntohl(*dst), ip_buf, sizeof(ip_buf))); | intoa(ntohl(*dst), ip_buf, sizeof(ip_buf))); | |||
else if((*dst != eee->device.ip_addr)) { | else if((*dst != eee->device.ip_addr)) { | |||
/* This is a packet that needs to be routed */ | /* This is a packet that needs to be routed */ | |||
traceEvent(TRACE_INFO, "discarding routed packet destine d to [%s]", | traceEvent(TRACE_INFO, "discarding routed packet destine d to [%s]", | |||
skipping to change at line 1785 | skipping to change at line 1796 | |||
} | } | |||
} | } | |||
fclose(fd); | fclose(fd); | |||
return buf; | return buf; | |||
} | } | |||
#endif | #endif | |||
#endif | #endif | |||
/** Read a datagram from the management UDP socket and take appropriate | ||||
* action. */ | ||||
static void readFromMgmtSocket (n2n_edge_t *eee) { | ||||
char udp_buf[N2N_PKT_BUF_SIZE]; /* Compete UDP packet */ | ||||
ssize_t recvlen; | ||||
/* ssize_t sendlen; */ | ||||
struct sockaddr_in sender_sock; | ||||
socklen_t i; | ||||
size_t msg_len; | ||||
time_t now; | ||||
struct peer_info *peer, *tmpPeer; | ||||
macstr_t mac_buf; | ||||
char time_buf[10]; /* 9 digits + 1 terminating zero */ | ||||
char uptime_buf[11]; /* 10 digits + 1 terminating zero */ | ||||
/* dec_ip_bit_str_t ip_bit_str = {'\0'}; */ | ||||
/* dec_ip_str_t ip_str = {'\0'}; */ | ||||
in_addr_t net; | ||||
n2n_sock_str_t sockbuf; | ||||
uint32_t num_pending_peers = 0; | ||||
uint32_t num_known_peers = 0; | ||||
uint32_t num = 0; | ||||
selection_criterion_str_t sel_buf; | ||||
now = time(NULL); | ||||
i = sizeof(sender_sock); | ||||
recvlen = recvfrom(eee->udp_mgmt_sock, udp_buf, N2N_PKT_BUF_SIZE, 0/*flags*/ | ||||
, | ||||
(struct sockaddr *) &sender_sock, (socklen_t *) &i); | ||||
if(recvlen < 0) { | ||||
traceEvent(TRACE_WARNING, "mgmt recvfrom failed: %d - %s", errno, strerr | ||||
or(errno)); | ||||
return; /* failed to receive data from UDP */ | ||||
} | ||||
/* avoid parsing any uninitialized junk from the stack */ | ||||
udp_buf[recvlen] = 0; | ||||
if((0 == memcmp(udp_buf, "help", 4)) || (0 == memcmp(udp_buf, "?", 1))) { | ||||
msg_len = 0; | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - ms | ||||
g_len), | ||||
"Help for edge management console:\n" | ||||
"\tstop | Gracefully exit edge\n" | ||||
"\thelp | This help message\n" | ||||
"\t+verb | Increase verbosity of logging\n" | ||||
"\t-verb | Decrease verbosity of logging\n" | ||||
"\tr ... | start query with JSON reply\n" | ||||
"\tw ... | start update with JSON reply\n" | ||||
"\t<enter> | Display statistics\n\n"); | ||||
sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, | ||||
(struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); | ||||
return; | ||||
} | ||||
if(0 == memcmp(udp_buf, "stop", 4)) { | ||||
traceEvent(TRACE_NORMAL, "stop command received"); | ||||
*eee->keep_running = 0; | ||||
return; | ||||
} | ||||
if(0 == memcmp(udp_buf, "+verb", 5)) { | ||||
msg_len = 0; | ||||
setTraceLevel(getTraceLevel() + 1); | ||||
traceEvent(TRACE_NORMAL, "+verb traceLevel=%u", (unsigned int) getTraceL | ||||
evel()); | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - ms | ||||
g_len), | ||||
"> +OK traceLevel=%u\n", (unsigned int) getTraceLeve | ||||
l()); | ||||
sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, | ||||
(struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); | ||||
return; | ||||
} | ||||
if(0 == memcmp(udp_buf, "-verb", 5)) { | ||||
msg_len = 0; | ||||
if(getTraceLevel() > 0) { | ||||
setTraceLevel(getTraceLevel() - 1); | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE | ||||
- msg_len), | ||||
"> -OK traceLevel=%u\n", getTraceLevel()); | ||||
} else { | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE | ||||
- msg_len), | ||||
"> -NOK traceLevel=%u\n", getTraceLevel()); | ||||
} | ||||
traceEvent(TRACE_NORMAL, "-verb traceLevel=%u", (unsigned int) getTraceL | ||||
evel()); | ||||
sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, | ||||
(struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); | ||||
return; | ||||
} | ||||
if((udp_buf[0] == 'r' || udp_buf[0] == 'w') && (udp_buf[1] == ' ')) { | ||||
/* this is a JSON request */ | ||||
handleMgmtJson(eee, udp_buf, sender_sock); | ||||
return; | ||||
} | ||||
traceEvent(TRACE_DEBUG, "mgmt status requested"); | ||||
msg_len = 0; | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_le | ||||
n), | ||||
"COMMUNITY '%s'\n\n", | ||||
(eee->conf.header_encryption == HEADER_ENCRYPTION_NONE) | ||||
? (char*)eee->conf.community_name : "-- header encrypted --"); | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_le | ||||
n), | ||||
" ### | TAP | MAC | EDGE | ||||
| HINT | LAST SEEN | UPTIME\n"); | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_le | ||||
n), | ||||
"======================================================= | ||||
======================================================\n"); | ||||
// dump nodes with forwarding through supernodes | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_le | ||||
n), | ||||
"SUPERNODE FORWARD\n"); | ||||
num = 0; | ||||
HASH_ITER(hh, eee->pending_peers, peer, tmpPeer) { | ||||
++num_pending_peers; | ||||
net = htonl(peer->dev_addr.net_addr); | ||||
snprintf(time_buf, sizeof(time_buf), "%9u", (unsigned int)(now - peer->l | ||||
ast_seen)); | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - ms | ||||
g_len), | ||||
"%4u | %-15s | %-17s | %-21s | %-15s | %9s |\n", | ||||
++num, | ||||
(peer->dev_addr.net_addr == 0) ? "" : inet_ntoa(*(st | ||||
ruct in_addr *) &net), | ||||
(is_null_mac(peer->mac_addr)) ? "" : macaddr_str(mac | ||||
_buf, peer->mac_addr), | ||||
sock_to_cstr(sockbuf, &(peer->sock)), | ||||
peer->dev_desc, | ||||
(peer->last_seen) ? time_buf : ""); | ||||
sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, | ||||
(struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); | ||||
msg_len = 0; | ||||
} | ||||
// dump peer-to-peer nodes | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_le | ||||
n), | ||||
"------------------------------------------------------- | ||||
------------------------------------------------------\n"); | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_le | ||||
n), | ||||
"PEER TO PEER\n"); | ||||
num = 0; | ||||
HASH_ITER(hh, eee->known_peers, peer, tmpPeer) { | ||||
++num_known_peers; | ||||
net = htonl(peer->dev_addr.net_addr); | ||||
snprintf(time_buf, sizeof(time_buf), "%9u", (unsigned int)(now - peer->l | ||||
ast_seen)); | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - ms | ||||
g_len), | ||||
"%4u | %-15s | %-17s | %-21s | %-15s | %9s |\n", | ||||
++num, | ||||
(peer->dev_addr.net_addr == 0) ? "" : inet_ntoa(*(st | ||||
ruct in_addr *) &net), | ||||
(is_null_mac(peer->mac_addr)) ? "" : macaddr_str(mac | ||||
_buf, peer->mac_addr), | ||||
sock_to_cstr(sockbuf, &(peer->sock)), | ||||
peer->dev_desc, | ||||
(peer->last_seen) ? time_buf : ""); | ||||
sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, | ||||
(struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); | ||||
msg_len = 0; | ||||
} | ||||
// dump supernodes | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_le | ||||
n), | ||||
"------------------------------------------------------- | ||||
------------------------------------------------------\n"); | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_le | ||||
n), | ||||
"SUPERNODES\n"); | ||||
HASH_ITER(hh, eee->conf.supernodes, peer, tmpPeer) { | ||||
net = htonl(peer->dev_addr.net_addr); | ||||
snprintf(time_buf, sizeof(time_buf), "%9u", (unsigned int)(now - peer->l | ||||
ast_seen)); | ||||
snprintf(uptime_buf, sizeof(uptime_buf), "%10u", (unsigned int)(peer->up | ||||
time)); | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - ms | ||||
g_len), | ||||
"%-19s %1s%1s | %-17s | %-21s | %-15s | %9s | %10s\n | ||||
", | ||||
peer->version, | ||||
(peer->purgeable == SN_UNPURGEABLE) ? "l" : "", | ||||
(peer == eee->curr_sn) ? (eee->sn_wait ? "." : "*" ) | ||||
: "", | ||||
is_null_mac(peer->mac_addr) ? "" : macaddr_str(mac_b | ||||
uf, peer->mac_addr), | ||||
sock_to_cstr(sockbuf, &(peer->sock)), | ||||
sn_selection_criterion_str(eee, sel_buf, peer), | ||||
(peer->last_seen) ? time_buf : "", | ||||
(peer->uptime) ? uptime_buf : ""); | ||||
sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0, | ||||
(struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); | ||||
msg_len = 0; | ||||
} | ||||
// further stats | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_le | ||||
n), | ||||
"======================================================= | ||||
======================================================\n"); | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_le | ||||
n), | ||||
"uptime %lu | ", | ||||
time(NULL) - eee->start_time); | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_le | ||||
n), | ||||
"pend_peers %u | ", | ||||
num_pending_peers); | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_le | ||||
n), | ||||
"known_peers %u | ", | ||||
num_known_peers); | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_le | ||||
n), | ||||
"transop %u,%u\n", | ||||
(unsigned int) eee->transop.tx_cnt, | ||||
(unsigned int) eee->transop.rx_cnt); | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_le | ||||
n), | ||||
"super %u,%u | ", | ||||
(unsigned int) eee->stats.tx_sup, | ||||
(unsigned int) eee->stats.rx_sup); | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_le | ||||
n), | ||||
"p2p %u,%u\n", | ||||
(unsigned int) eee->stats.tx_p2p, | ||||
(unsigned int) eee->stats.rx_p2p); | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_le | ||||
n), | ||||
"last_super %ld sec ago | ", | ||||
(now - eee->last_sup)); | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_le | ||||
n), | ||||
"last_p2p %ld sec ago\n", | ||||
(now - eee->last_p2p)); | ||||
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_le | ||||
n), | ||||
"\nType \"help\" to see more commands.\n\n"); | ||||
/* sendlen = */ sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, | ||||
(struct sockaddr *) &sender_sock, sizeof(struct socka | ||||
ddr_in)); | ||||
} | ||||
/* ************************************** */ | /* ************************************** */ | |||
static int check_query_peer_info (n2n_edge_t *eee, time_t now, n2n_mac_t mac) { | static int check_query_peer_info (n2n_edge_t *eee, time_t now, n2n_mac_t mac) { | |||
struct peer_info *scan; | struct peer_info *scan; | |||
HASH_FIND_PEER(eee->pending_peers, mac, scan); | HASH_FIND_PEER(eee->pending_peers, mac, scan); | |||
if(!scan) { | if(!scan) { | |||
scan = calloc(1, sizeof(struct peer_info)); | scan = calloc(1, sizeof(struct peer_info)); | |||
skipping to change at line 2074 | skipping to change at line 1855 | |||
macaddr_str(mac_buf, mac_address)); | macaddr_str(mac_buf, mac_address)); | |||
HASH_FIND_PEER(eee->known_peers, mac_address, scan); | HASH_FIND_PEER(eee->known_peers, mac_address, scan); | |||
if(scan && (scan->last_seen > 0)) { | if(scan && (scan->last_seen > 0)) { | |||
if((now - scan->last_p2p) >= (scan->timeout / 2)) { | if((now - scan->last_p2p) >= (scan->timeout / 2)) { | |||
/* Too much time passed since we saw the peer, need to register agai n | /* Too much time passed since we saw the peer, need to register agai n | |||
* since the peer address may have changed. */ | * since the peer address may have changed. */ | |||
traceEvent(TRACE_DEBUG, "refreshing idle known peer"); | traceEvent(TRACE_DEBUG, "refreshing idle known peer"); | |||
HASH_DEL(eee->known_peers, scan); | HASH_DEL(eee->known_peers, scan); | |||
mgmt_event_post(N2N_EVENT_PEER,N2N_EVENT_PEER_DEL_P2P,scan); | ||||
free(scan); | free(scan); | |||
/* NOTE: registration will be performed upon the receival of the nex t response packet */ | /* NOTE: registration will be performed upon the receival of the nex t response packet */ | |||
} else { | } else { | |||
/* Valid known peer found */ | /* Valid known peer found */ | |||
memcpy(destination, &scan->sock, sizeof(n2n_sock_t)); | memcpy(destination, &scan->sock, sizeof(n2n_sock_t)); | |||
retval = 1; | retval = 1; | |||
} | } | |||
} | } | |||
if(retval == 0) { | if(retval == 0) { | |||
skipping to change at line 2154 | skipping to change at line 1936 | |||
/* ************************************** */ | /* ************************************** */ | |||
/** A layer-2 packet was received at the tunnel and needs to be sent via UDP. */ | /** A layer-2 packet was received at the tunnel and needs to be sent via UDP. */ | |||
void edge_send_packet2net (n2n_edge_t * eee, | void edge_send_packet2net (n2n_edge_t * eee, | |||
uint8_t *tap_pkt, size_t len) { | uint8_t *tap_pkt, size_t len) { | |||
ipstr_t ip_buf; | ipstr_t ip_buf; | |||
n2n_mac_t destMac; | n2n_mac_t destMac; | |||
n2n_common_t cmn; | n2n_common_t cmn; | |||
n2n_PACKET_t pkt; | n2n_PACKET_t pkt; | |||
uint8_t *enc_src = tap_pkt; | ||||
size_t enc_len = len; | ||||
uint8_t compression_buf[N2N_PKT_BUF_SIZE]; | ||||
uint8_t pktbuf[N2N_PKT_BUF_SIZE]; | uint8_t pktbuf[N2N_PKT_BUF_SIZE]; | |||
size_t idx = 0; | size_t idx = 0; | |||
n2n_transform_t tx_transop_idx = eee->transop.transform_id; | n2n_transform_t tx_transop_idx = eee->transop.transform_id; | |||
ether_hdr_t eh; | ether_hdr_t eh; | |||
/* tap_pkt is not aligned so we have to copy to aligned memory */ | /* tap_pkt is not aligned so we have to copy to aligned memory */ | |||
memcpy(&eh, tap_pkt, sizeof(ether_hdr_t)); | memcpy(&eh, tap_pkt, sizeof(ether_hdr_t)); | |||
/* Discard IP packets that are not originated by this hosts */ | /* Discard IP packets that are not originated by this hosts */ | |||
if(!(eee->conf.allow_routing)) { | if(!(eee->conf.allow_routing)) { | |||
skipping to change at line 2203 | skipping to change at line 1988 | |||
memset(&pkt, 0, sizeof(pkt)); | memset(&pkt, 0, sizeof(pkt)); | |||
memcpy(pkt.srcMac, eee->device.mac_addr, N2N_MAC_SIZE); | memcpy(pkt.srcMac, eee->device.mac_addr, N2N_MAC_SIZE); | |||
memcpy(pkt.dstMac, destMac, N2N_MAC_SIZE); | memcpy(pkt.dstMac, destMac, N2N_MAC_SIZE); | |||
pkt.transform = tx_transop_idx; | pkt.transform = tx_transop_idx; | |||
// compression needs to be tried before encode_PACKET is called for compress ion indication gets encoded there | // compression needs to be tried before encode_PACKET is called for compress ion indication gets encoded there | |||
pkt.compression = N2N_COMPRESSION_ID_NONE; | pkt.compression = N2N_COMPRESSION_ID_NONE; | |||
if(eee->conf.compression) { | if(eee->conf.compression) { | |||
uint8_t * compression_buffer = NULL; | ||||
int32_t compression_len; | int32_t compression_len; | |||
switch(eee->conf.compression) { | switch(eee->conf.compression) { | |||
case N2N_COMPRESSION_ID_LZO: | case N2N_COMPRESSION_ID_LZO: | |||
compression_buffer = malloc(len + len / 16 + 64 + 3); | compression_len = eee->transop_lzo.fwd(&eee->transop_lzo, | |||
if(lzo1x_1_compress(tap_pkt, len, compression_buffer, (lzo_uint* | compression_buf, sizeof(c | |||
)&compression_len, wrkmem) == LZO_E_OK) { | ompression_buf), | |||
if(compression_len < len) { | tap_pkt, len, | |||
pkt.compression = N2N_COMPRESSION_ID_LZO; | pkt.dstMac); | |||
} | ||||
if((compression_len > 0) && (compression_len < len)) { | ||||
pkt.compression = N2N_COMPRESSION_ID_LZO; | ||||
} | } | |||
break; | break; | |||
#ifdef N2N_HAVE_ZSTD | ||||
#ifdef HAVE_ZSTD | ||||
case N2N_COMPRESSION_ID_ZSTD: | case N2N_COMPRESSION_ID_ZSTD: | |||
compression_len = N2N_PKT_BUF_SIZE + 128; | compression_len = eee->transop_zstd.fwd(&eee->transop_zstd, | |||
compression_buffer = malloc(compression_len); // leaves enough | compression_buf, sizeof( | |||
room, for exact size call compression_len = ZSTD_compressBound (len); (slower) | compression_buf), | |||
compression_len = (int32_t)ZSTD_compress(compression_buffer, com | tap_pkt, len, | |||
pression_len, tap_pkt, len, ZSTD_COMPRESSION_LEVEL); | pkt.dstMac); | |||
if(!ZSTD_isError(compression_len)) { | ||||
if(compression_len < len) { | if((compression_len > 0) && (compression_len < len)) { | |||
pkt.compression = N2N_COMPRESSION_ID_ZSTD; | pkt.compression = N2N_COMPRESSION_ID_ZSTD; | |||
} | ||||
} else { | ||||
traceEvent(TRACE_ERROR, "payload compression failed with zst | ||||
d error '%s'.", | ||||
ZSTD_getErrorName(compression_len)); | ||||
free(compression_buffer); | ||||
// continue with unset without pkt.compression --> will send | ||||
uncompressed | ||||
} | } | |||
break; | break; | |||
#endif | #endif | |||
default: | default: | |||
break; | break; | |||
} | } | |||
if(pkt.compression != N2N_COMPRESSION_ID_NONE) { | if(pkt.compression != N2N_COMPRESSION_ID_NONE) { | |||
traceEvent(TRACE_DEBUG, "payload compression [%s]: compressed %u byt es to %u bytes\n", | traceEvent(TRACE_DEBUG, "payload compression [%s]: compressed %u byt es to %u bytes\n", | |||
compression_str(pkt.compression), len, compression_len); | compression_str(pkt.compression), len, compression_len); | |||
enc_src = compression_buf; | ||||
memcpy(tap_pkt, compression_buffer, compression_len); | enc_len = compression_len; | |||
len = compression_len; | ||||
} | ||||
if(compression_buffer) { | ||||
free(compression_buffer); | ||||
} | } | |||
} | } | |||
idx = 0; | idx = 0; | |||
encode_PACKET(pktbuf, &idx, &cmn, &pkt); | encode_PACKET(pktbuf, &idx, &cmn, &pkt); | |||
uint16_t headerIdx = idx; | uint16_t headerIdx = idx; | |||
idx += eee->transop.fwd(&eee->transop, | idx += eee->transop.fwd(&eee->transop, | |||
pktbuf + idx, N2N_PKT_BUF_SIZE - idx, | pktbuf + idx, N2N_PKT_BUF_SIZE - idx, | |||
tap_pkt, len, pkt.dstMac); | enc_src, enc_len, pkt.dstMac); | |||
traceEvent(TRACE_DEBUG, "encode PACKET of %u bytes, %u bytes data, %u bytes overhead, transform %u", | traceEvent(TRACE_DEBUG, "encode PACKET of %u bytes, %u bytes data, %u bytes overhead, transform %u", | |||
(u_int)idx, (u_int)len, (u_int)(idx - len), tx_transop_idx); | (u_int)idx, (u_int)len, (u_int)(idx - len), tx_transop_idx); | |||
if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) | if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) | |||
// in case of user-password auth, also encrypt the iv of payload assumin g ChaCha20 and SPECK having the same iv size | // in case of user-password auth, also encrypt the iv of payload assumin g ChaCha20 and SPECK having the same iv size | |||
packet_header_encrypt(pktbuf, headerIdx + (NULL != eee->conf.shared_secr et) * min(idx - headerIdx, N2N_SPECK_IVEC_SIZE), idx, | packet_header_encrypt(pktbuf, headerIdx + (NULL != eee->conf.shared_secr et) * min(idx - headerIdx, N2N_SPECK_IVEC_SIZE), idx, | |||
eee->conf.header_encryption_ctx_dynamic, eee->conf .header_iv_ctx_dynamic, | eee->conf.header_encryption_ctx_dynamic, eee->conf .header_iv_ctx_dynamic, | |||
time_stamp()); | time_stamp()); | |||
skipping to change at line 2480 | skipping to change at line 2258 | |||
return; | return; | |||
} | } | |||
} | } | |||
if(!eee->last_sup) { | if(!eee->last_sup) { | |||
// drop packets received before first registration with supe rnode | // drop packets received before first registration with supe rnode | |||
traceEvent(TRACE_DEBUG, "dropped PACKET recevied before firs t registration with supernode"); | traceEvent(TRACE_DEBUG, "dropped PACKET recevied before firs t registration with supernode"); | |||
return; | return; | |||
} | } | |||
if(is_valid_peer_sock(&pkt.sock)) | ||||
orig_sender = &(pkt.sock); | ||||
if(!from_supernode) { | if(!from_supernode) { | |||
/* This is a P2P packet from the peer. We purge a pending | /* This is a P2P packet from the peer. We purge a pending | |||
* registration towards the possibly nat-ted peer address as we now have | * registration towards the possibly nat-ted peer address as we now have | |||
* a valid channel. We still use check_peer_registration_nee ded in | * a valid channel. We still use check_peer_registration_nee ded in | |||
* handle_PACKET to double check this. | * handle_PACKET to double check this. | |||
*/ | */ | |||
traceEvent(TRACE_DEBUG, "[p2p] from %s", | traceEvent(TRACE_DEBUG, "[p2p] from %s", | |||
macaddr_str(mac_buf1, pkt.srcMac)); | macaddr_str(mac_buf1, pkt.srcMac)); | |||
find_and_remove_peer(&eee->pending_peers, pkt.srcMac); | find_and_remove_peer(&eee->pending_peers, pkt.srcMac); | |||
} else { | } else { | |||
/* [PsP] : edge Peer->Supernode->edge Peer */ | /* [PsP] : edge Peer->Supernode->edge Peer */ | |||
if(is_valid_peer_sock(&pkt.sock)) | ||||
orig_sender = &(pkt.sock); | ||||
traceEvent(TRACE_DEBUG, "[pSp] from %s via [%s]", | traceEvent(TRACE_DEBUG, "[pSp] from %s via [%s]", | |||
macaddr_str(mac_buf1, pkt.srcMac), | macaddr_str(mac_buf1, pkt.srcMac), | |||
sock_to_cstr(sockbuf1, &sender)); | sock_to_cstr(sockbuf1, &sender)); | |||
} | } | |||
/* Update the sender in peer table entry */ | /* Update the sender in peer table entry */ | |||
check_peer_registration_needed(eee, from_supernode, via_multicas t, | check_peer_registration_needed(eee, from_supernode, via_multicas t, | |||
pkt.srcMac, | pkt.srcMac, | |||
// REVISIT: also consider PORT_RE G_COOKIEs when implemented | // REVISIT: also consider PORT_RE G_COOKIEs when implemented | |||
from_supernode ? N2N_FORWARDED_RE G_COOKIE : N2N_REGULAR_REG_COOKIE, | from_supernode ? N2N_FORWARDED_RE G_COOKIE : N2N_REGULAR_REG_COOKIE, | |||
skipping to change at line 2805 | skipping to change at line 2584 | |||
scan = add_sn_to_list_by_mac_or_sock(&(eee->conf.supernodes) , &sender, pi.srcMac, &skip_add); | scan = add_sn_to_list_by_mac_or_sock(&(eee->conf.supernodes) , &sender, pi.srcMac, &skip_add); | |||
if(scan != NULL) { | if(scan != NULL) { | |||
eee->sn_pong = 1; | eee->sn_pong = 1; | |||
scan->last_seen = now; | scan->last_seen = now; | |||
scan->uptime = pi.uptime; | scan->uptime = pi.uptime; | |||
memcpy(scan->version, pi.version, sizeof(n2n_version_t)) ; | memcpy(scan->version, pi.version, sizeof(n2n_version_t)) ; | |||
/* The data type depends on the actual selection strateg y that has been chosen. */ | /* The data type depends on the actual selection strateg y that has been chosen. */ | |||
SN_SELECTION_CRITERION_DATA_TYPE sn_sel_tmp = pi.load; | SN_SELECTION_CRITERION_DATA_TYPE sn_sel_tmp = pi.load; | |||
sn_selection_criterion_calculate(eee, scan, &sn_sel_tmp) ; | sn_selection_criterion_calculate(eee, scan, &sn_sel_tmp) ; | |||
traceEvent(TRACE_INFO, "Rx PONG from supernode %s", | traceEvent(TRACE_INFO, "Rx PONG from supernode %s versio | |||
macaddr_str(mac_buf1, pi.srcMac)); | n '%s'", | |||
macaddr_str(mac_buf1, pi.srcMac), | ||||
pi.version); | ||||
break; | break; | |||
} | } | |||
} else { | } else { | |||
// regular PEER_INFO | // regular PEER_INFO | |||
HASH_FIND_PEER(eee->pending_peers, pi.mac, scan); | HASH_FIND_PEER(eee->pending_peers, pi.mac, scan); | |||
if(!scan) | if(!scan) | |||
// just in case the remote edge has been upgraded by the REG/ACK mechanism in the meantime | // just in case the remote edge has been upgraded by the REG/ACK mechanism in the meantime | |||
HASH_FIND_PEER(eee->known_peers, pi.mac, scan); | HASH_FIND_PEER(eee->known_peers, pi.mac, scan); | |||
skipping to change at line 3150 | skipping to change at line 2930 | |||
eee->cb.main_loop_period(eee, now); | eee->cb.main_loop_period(eee, now); | |||
} /* while */ | } /* while */ | |||
send_unregister_super(eee); | send_unregister_super(eee); | |||
#ifdef WIN32 | #ifdef WIN32 | |||
WaitForSingleObject(tun_read_thread, INFINITE); | WaitForSingleObject(tun_read_thread, INFINITE); | |||
#endif | #endif | |||
closesocket(eee->sock); | supernode_disconnect(eee); | |||
return(0); | return 0; | |||
} | } | |||
/* ************************************** */ | /* ************************************** */ | |||
/** Deinitialise the edge and deallocate any owned memory. */ | /** Deinitialise the edge and deallocate any owned memory. */ | |||
void edge_term (n2n_edge_t * eee) { | void edge_term (n2n_edge_t * eee) { | |||
resolve_cancel_thread(eee->resolve_parameter); | resolve_cancel_thread(eee->resolve_parameter); | |||
#ifdef HAVE_PORT_FORWARDING | ||||
if(eee->conf.port_forwarding) | ||||
port_map_cancel_thread(eee->port_map_parameter); | ||||
#endif // HAVE_MINIUPNP || HAVE_NATPMP | ||||
if(eee->sock >= 0) | if(eee->sock >= 0) | |||
closesocket(eee->sock); | closesocket(eee->sock); | |||
if(eee->udp_mgmt_sock >= 0) | if(eee->udp_mgmt_sock >= 0) | |||
closesocket(eee->udp_mgmt_sock); | closesocket(eee->udp_mgmt_sock); | |||
#ifndef SKIP_MULTICAST_PEERS_DISCOVERY | #ifndef SKIP_MULTICAST_PEERS_DISCOVERY | |||
if(eee->udp_multicast_sock >= 0) | if(eee->udp_multicast_sock >= 0) | |||
closesocket(eee->udp_multicast_sock); | closesocket(eee->udp_multicast_sock); | |||
#endif | #endif | |||
clear_peer_list(&eee->pending_peers); | clear_peer_list(&eee->pending_peers); | |||
clear_peer_list(&eee->known_peers); | clear_peer_list(&eee->known_peers); | |||
eee->transop.deinit(&eee->transop); | eee->transop.deinit(&eee->transop); | |||
eee->transop_lzo.deinit(&eee->transop_lzo); | ||||
#ifdef HAVE_ZSTD | ||||
eee->transop_zstd.deinit(&eee->transop_zstd); | ||||
#endif | ||||
edge_cleanup_routes(eee); | edge_cleanup_routes(eee); | |||
destroy_network_traffic_filter(eee->network_traffic_filter); | destroy_network_traffic_filter(eee->network_traffic_filter); | |||
closeTraceFile(); | closeTraceFile(); | |||
free(eee); | free(eee); | |||
} | } | |||
skipping to change at line 3679 | skipping to change at line 3466 | |||
generate_private_key(*(conf->shared_secret), getenv("N2N_PASSWORD")) ; | generate_private_key(*(conf->shared_secret), getenv("N2N_PASSWORD")) ; | |||
} | } | |||
tmp_string = calloc(1, strlen(N2N_MGMT_PASSWORD) + 1); | tmp_string = calloc(1, strlen(N2N_MGMT_PASSWORD) + 1); | |||
if(tmp_string) { | if(tmp_string) { | |||
strncpy((char*)tmp_string, N2N_MGMT_PASSWORD, strlen(N2N_MGMT_PASSWORD) + 1); | strncpy((char*)tmp_string, N2N_MGMT_PASSWORD, strlen(N2N_MGMT_PASSWORD) + 1); | |||
conf->mgmt_password_hash = pearson_hash_64((uint8_t*)tmp_string, strlen( N2N_MGMT_PASSWORD)); | conf->mgmt_password_hash = pearson_hash_64((uint8_t*)tmp_string, strlen( N2N_MGMT_PASSWORD)); | |||
free(tmp_string); | free(tmp_string); | |||
} | } | |||
#if defined(HAVE_MINIUPNP) || defined(HAVE_NATPMP) | ||||
conf->port_forwarding = 1; | ||||
#endif // HAVE_MINIUPNP || HAVE_NATPMP | ||||
conf->sn_selection_strategy = SN_SELECTION_STRATEGY_LOAD; | conf->sn_selection_strategy = SN_SELECTION_STRATEGY_LOAD; | |||
conf->metric = 0; | conf->metric = 0; | |||
} | } | |||
/* ************************************** */ | /* ************************************** */ | |||
void edge_term_conf (n2n_edge_conf_t *conf) { | void edge_term_conf (n2n_edge_conf_t *conf) { | |||
if(conf->routes) free(conf->routes); | if(conf->routes) free(conf->routes); | |||
if(conf->encrypt_key) free(conf->encrypt_key); | if(conf->encrypt_key) free(conf->encrypt_key); | |||
End of changes. 39 change blocks. | ||||
360 lines changed or deleted | 104 lines changed or added |