From 368cee035c185b0fd10c0b1b80c5b4a57540cc3b Mon Sep 17 00:00:00 2001 From: Dushara Jayasinghe Date: Tue, 29 Aug 2017 09:45:19 +1000 Subject: [PATCH 01/10] Fix Segmentation fault on Linux amd64 The version defines which were passed to version.c were incorrectly constructed in the CMakeLists.txt file causing a seg fault when invoking edge -h --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c9ad81c..97ea344 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ if(NOT DEFINED N2N_OPTION_AES) set(N2N_OPTION_AES ON) endif(NOT DEFINED N2N_OPTION_AES) -add_definitions(-DN2N_VERSION='\"${N2N_VERSION}\"' -DN2N_OSNAME='\"${N2N_OSNAME}\"') +add_definitions(-DN2N_VERSION="${N2N_VERSION}" -DN2N_OSNAME="${N2N_OSNAME}") if(N2N_OPTION_AES) add_definitions(-DN2N_HAVE_AES) From eb8923e6d02acdece28c7a6403b57eb84d919ff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Lajos=20Kis?= Date: Sun, 3 Dec 2017 12:27:40 +0100 Subject: [PATCH 02/10] fix mk_tar.sh manifest list --- scripts/mk_tar.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_tar.sh b/scripts/mk_tar.sh index 0e84331..7c4e3e7 100755 --- a/scripts/mk_tar.sh +++ b/scripts/mk_tar.sh @@ -28,7 +28,7 @@ PKG_AND_VERSION="${PACKAGE}-${PKG_VERSION}" TEMPDIR="tmp" SOURCE_MANIFEST=" -README +README.md edge.c lzoconf.h lzodefs.h From 05db916ca24ea1b0bf4a7669297b6dde11f7cda9 Mon Sep 17 00:00:00 2001 From: John Niang <1340692778@qq.com> Date: Tue, 3 Apr 2018 23:44:19 +0800 Subject: [PATCH 03/10] Modify README in the source_manifest to README.md --- scripts/mk_tar.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_tar.sh b/scripts/mk_tar.sh index 0e84331..7c4e3e7 100755 --- a/scripts/mk_tar.sh +++ b/scripts/mk_tar.sh @@ -28,7 +28,7 @@ PKG_AND_VERSION="${PACKAGE}-${PKG_VERSION}" TEMPDIR="tmp" SOURCE_MANIFEST=" -README +README.md edge.c lzoconf.h lzodefs.h From 415f6b0a72c4583565b12d138bd4bc40ae053ce9 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Wed, 6 Jun 2018 09:26:08 +0200 Subject: [PATCH 04/10] Minor code cleanup Fixed compilation issue on OSX --- edge.c | 2284 ++++++++++++++++++++++++----------------------- n2n.c | 170 ++-- n2n.h | 12 - tuntap_linux.c | 4 +- tuntap_netbsd.c | 31 +- tuntap_osx.c | 6 +- 6 files changed, 1272 insertions(+), 1235 deletions(-) diff --git a/edge.c b/edge.c index b2407b9..7a4d563 100644 --- a/edge.c +++ b/edge.c @@ -86,53 +86,53 @@ typedef char n2n_sn_name_t[N2N_EDGE_SN_HOST_SIZE]; /** Main structure type for edge. */ struct n2n_edge { - int daemon; /**< Non-zero if edge should detach and run in the background. */ - uint8_t re_resolve_supernode_ip; + int daemon; /**< Non-zero if edge should detach and run in the background. */ + uint8_t re_resolve_supernode_ip; - n2n_sock_t supernode; + n2n_sock_t supernode; - size_t sn_idx; /**< Currently active supernode. */ - size_t sn_num; /**< Number of supernode addresses defined. */ - n2n_sn_name_t sn_ip_array[N2N_EDGE_NUM_SUPERNODES]; - int sn_wait; /**< Whether we are waiting for a supernode response. */ + size_t sn_idx; /**< Currently active supernode. */ + size_t sn_num; /**< Number of supernode addresses defined. */ + n2n_sn_name_t sn_ip_array[N2N_EDGE_NUM_SUPERNODES]; + int sn_wait; /**< Whether we are waiting for a supernode response. */ - n2n_community_t community_name; /**< The community. 16 full octets. */ - char keyschedule[N2N_PATHNAME_MAXLEN]; - int null_transop; /**< Only allowed if no key sources defined. */ + n2n_community_t community_name; /**< The community. 16 full octets. */ + char keyschedule[N2N_PATHNAME_MAXLEN]; + int null_transop; /**< Only allowed if no key sources defined. */ - int udp_sock; - int udp_mgmt_sock; /**< socket for status info. */ + int udp_sock; + int udp_mgmt_sock; /**< socket for status info. */ - tuntap_dev device; /**< All about the TUNTAP device */ - int dyn_ip_mode; /**< Interface IP address is dynamically allocated, eg. DHCP. */ - int allow_routing; /**< Accept packet no to interface address. */ - int drop_multicast; /**< Multicast ethernet addresses. */ + tuntap_dev device; /**< All about the TUNTAP device */ + int dyn_ip_mode; /**< Interface IP address is dynamically allocated, eg. DHCP. */ + int allow_routing; /**< Accept packet no to interface address. */ + int drop_multicast; /**< Multicast ethernet addresses. */ - n2n_trans_op_t transop[N2N_MAX_TRANSFORMS]; /* one for each transform at fixed positions */ - size_t tx_transop_idx; /**< The transop to use when encoding. */ + n2n_trans_op_t transop[N2N_MAX_TRANSFORMS]; /* one for each transform at fixed positions */ + size_t tx_transop_idx; /**< The transop to use when encoding. */ - struct peer_info * known_peers; /**< Edges we are connected to. */ - struct peer_info * pending_peers; /**< Edges we have tried to register with. */ - time_t last_register_req; /**< Check if time to re-register with super*/ - size_t register_lifetime; /**< Time distance after last_register_req at which to re-register. */ - time_t last_p2p; /**< Last time p2p traffic was received. */ - time_t last_sup; /**< Last time a packet arrived from supernode. */ - size_t sup_attempts; /**< Number of remaining attempts to this supernode. */ - n2n_cookie_t last_cookie; /**< Cookie sent in last REGISTER_SUPER. */ + struct peer_info * known_peers; /**< Edges we are connected to. */ + struct peer_info * pending_peers; /**< Edges we have tried to register with. */ + time_t last_register_req; /**< Check if time to re-register with super*/ + size_t register_lifetime; /**< Time distance after last_register_req at which to re-register. */ + time_t last_p2p; /**< Last time p2p traffic was received. */ + time_t last_sup; /**< Last time a packet arrived from supernode. */ + size_t sup_attempts; /**< Number of remaining attempts to this supernode. */ + n2n_cookie_t last_cookie; /**< Cookie sent in last REGISTER_SUPER. */ - time_t start_time; /**< For calculating uptime */ + time_t start_time; /**< For calculating uptime */ - /* Statistics */ - size_t tx_p2p; - size_t rx_p2p; - size_t tx_sup; - size_t rx_sup; + /* Statistics */ + size_t tx_p2p; + size_t rx_p2p; + size_t tx_sup; + size_t rx_sup; }; /** Return the IP address of the current supernode in the ring. */ -static const char * supernode_ip( const n2n_edge_t * eee ) +static const char * supernode_ip(const n2n_edge_t * eee) { - return (eee->sn_ip_array)[eee->sn_idx]; + return (eee->sn_ip_array)[eee->sn_idx]; } @@ -152,7 +152,7 @@ static int readConfFile(const char * filename, char * const linebuffer) { buffer = (char *)malloc(MAX_CONFFILE_LINE_LENGTH); if (!buffer) { - traceEvent( TRACE_ERROR, "Unable to allocate memory"); + traceEvent(TRACE_ERROR, "Unable to allocate memory"); return -1; } @@ -224,7 +224,7 @@ static char ** buildargv(int * effectiveargc, char * const linebuffer) { *effectiveargc = 0; buffer = (char *)calloc(1, strlen(linebuffer)+2); if (!buffer) { - traceEvent( TRACE_ERROR, "Unable to allocate memory"); + traceEvent(TRACE_ERROR, "Unable to allocate memory"); return NULL; } strncpy(buffer, linebuffer,strlen(linebuffer)); @@ -232,7 +232,7 @@ static char ** buildargv(int * effectiveargc, char * const linebuffer) { maxargc = INITIAL_MAXARGC; argv = (char **)malloc(maxargc * sizeof(char*)); if (argv == NULL) { - traceEvent( TRACE_ERROR, "Unable to allocate memory"); + traceEvent(TRACE_ERROR, "Unable to allocate memory"); return NULL; } buff = buffer; @@ -274,50 +274,50 @@ static char ** buildargv(int * effectiveargc, char * const linebuffer) { static int edge_init(n2n_edge_t * eee) { #ifdef WIN32 - initWin32(); + initWin32(); #endif - memset(eee, 0, sizeof(n2n_edge_t)); - eee->start_time = time(NULL); + memset(eee, 0, sizeof(n2n_edge_t)); + eee->start_time = time(NULL); - transop_null_init( &(eee->transop[N2N_TRANSOP_NULL_IDX]) ); - transop_twofish_init( &(eee->transop[N2N_TRANSOP_TF_IDX] ) ); - transop_aes_init( &(eee->transop[N2N_TRANSOP_AESCBC_IDX] ) ); + transop_null_init( &(eee->transop[N2N_TRANSOP_NULL_IDX])); + transop_twofish_init(&(eee->transop[N2N_TRANSOP_TF_IDX] )); + transop_aes_init(&(eee->transop[N2N_TRANSOP_AESCBC_IDX] )); - eee->tx_transop_idx = N2N_TRANSOP_NULL_IDX; /* No guarantee the others have been setup */ + eee->tx_transop_idx = N2N_TRANSOP_NULL_IDX; /* No guarantee the others have been setup */ - eee->daemon = 1; /* By default run in daemon mode. */ - eee->re_resolve_supernode_ip = 0; - /* keyschedule set to NULLs by memset */ - /* community_name set to NULLs by memset */ - eee->null_transop = 0; - eee->udp_sock = -1; - eee->udp_mgmt_sock = -1; - eee->dyn_ip_mode = 0; - eee->allow_routing = 0; - eee->drop_multicast = 1; - eee->known_peers = NULL; - eee->pending_peers = NULL; - eee->last_register_req = 0; - eee->register_lifetime = REGISTER_SUPER_INTERVAL_DFL; - eee->last_p2p = 0; - eee->last_sup = 0; - eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; + eee->daemon = 1; /* By default run in daemon mode. */ + eee->re_resolve_supernode_ip = 0; + /* keyschedule set to NULLs by memset */ + /* community_name set to NULLs by memset */ + eee->null_transop = 0; + eee->udp_sock = -1; + eee->udp_mgmt_sock = -1; + eee->dyn_ip_mode = 0; + eee->allow_routing = 0; + eee->drop_multicast = 1; + eee->known_peers = NULL; + eee->pending_peers = NULL; + eee->last_register_req = 0; + eee->register_lifetime = REGISTER_SUPER_INTERVAL_DFL; + eee->last_p2p = 0; + eee->last_sup = 0; + eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; - if(lzo_init() != LZO_E_OK) + if(lzo_init() != LZO_E_OK) { - traceEvent(TRACE_ERROR, "LZO compression error"); - return(-1); + traceEvent(TRACE_ERROR, "LZO compression error"); + return(-1); } - return(0); + return(0); } /* Called in main() after options are parsed. */ -static int edge_init_twofish( n2n_edge_t * eee, uint8_t *encrypt_pwd, uint32_t encrypt_pwd_len ) +static int edge_init_twofish(n2n_edge_t * eee, uint8_t *encrypt_pwd, uint32_t encrypt_pwd_len) { - return transop_twofish_setup( &(eee->transop[N2N_TRANSOP_TF_IDX]), 0, encrypt_pwd, encrypt_pwd_len ); + return transop_twofish_setup(&(eee->transop[N2N_TRANSOP_TF_IDX]), 0, encrypt_pwd, encrypt_pwd_len); } @@ -325,56 +325,56 @@ static int edge_init_twofish( n2n_edge_t * eee, uint8_t *encrypt_pwd, uint32_t e * * @return - index into the transop array, or -1 on failure. */ -static int transop_enum_to_index( n2n_transform_t id ) +static int transop_enum_to_index(n2n_transform_t id) { - switch (id) + switch (id) { case N2N_TRANSFORM_ID_TWOFISH: - return N2N_TRANSOP_TF_IDX; - break; + return N2N_TRANSOP_TF_IDX; + break; case N2N_TRANSFORM_ID_NULL: - return N2N_TRANSOP_NULL_IDX; - break; + return N2N_TRANSOP_NULL_IDX; + break; case N2N_TRANSFORM_ID_AESCBC: - return N2N_TRANSOP_AESCBC_IDX; - break; + return N2N_TRANSOP_AESCBC_IDX; + break; default: - return -1; + return -1; } } /** Called periodically to roll keys and do any periodic maintenance in the * tranform operations state machines. */ -static int n2n_tick_transop( n2n_edge_t * eee, time_t now ) +static int n2n_tick_transop(n2n_edge_t * eee, time_t now) { - n2n_tostat_t tst; - size_t trop = eee->tx_transop_idx; + n2n_tostat_t tst; + size_t trop = eee->tx_transop_idx; - /* Tests are done in order that most preferred transform is last and causes - * tx_transop_idx to be left at most preferred valid transform. */ - tst = (eee->transop[N2N_TRANSOP_NULL_IDX].tick)( &(eee->transop[N2N_TRANSOP_NULL_IDX]), now ); - tst = (eee->transop[N2N_TRANSOP_AESCBC_IDX].tick)( &(eee->transop[N2N_TRANSOP_AESCBC_IDX]), now ); - if ( tst.can_tx ) + /* Tests are done in order that most preferred transform is last and causes + * tx_transop_idx to be left at most preferred valid transform. */ + tst = (eee->transop[N2N_TRANSOP_NULL_IDX].tick)(&(eee->transop[N2N_TRANSOP_NULL_IDX]), now); + tst = (eee->transop[N2N_TRANSOP_AESCBC_IDX].tick)(&(eee->transop[N2N_TRANSOP_AESCBC_IDX]), now); + if(tst.can_tx) { - traceEvent( TRACE_DEBUG, "can_tx AESCBC (idx=%u)", (unsigned int)N2N_TRANSOP_AESCBC_IDX ); - trop = N2N_TRANSOP_AESCBC_IDX; + traceEvent(TRACE_DEBUG, "can_tx AESCBC (idx=%u)", (unsigned int)N2N_TRANSOP_AESCBC_IDX); + trop = N2N_TRANSOP_AESCBC_IDX; } - tst = (eee->transop[N2N_TRANSOP_TF_IDX].tick)( &(eee->transop[N2N_TRANSOP_TF_IDX]), now ); - if ( tst.can_tx ) + tst = (eee->transop[N2N_TRANSOP_TF_IDX].tick)(&(eee->transop[N2N_TRANSOP_TF_IDX]), now); + if(tst.can_tx) { - traceEvent( TRACE_DEBUG, "can_tx TF (idx=%u)", (unsigned int)N2N_TRANSOP_TF_IDX ); - trop = N2N_TRANSOP_TF_IDX; + traceEvent(TRACE_DEBUG, "can_tx TF (idx=%u)", (unsigned int)N2N_TRANSOP_TF_IDX); + trop = N2N_TRANSOP_TF_IDX; } - if ( trop != eee->tx_transop_idx ) + if(trop != eee->tx_transop_idx) { - eee->tx_transop_idx = trop; - traceEvent( TRACE_NORMAL, "Chose new tx_transop_idx=%u", (unsigned int)(eee->tx_transop_idx) ); + eee->tx_transop_idx = trop; + traceEvent(TRACE_NORMAL, "Chose new tx_transop_idx=%u", (unsigned int)(eee->tx_transop_idx)); } - return 0; + return 0; } @@ -385,85 +385,85 @@ static int n2n_tick_transop( n2n_edge_t * eee, time_t now ) * encoding can be passed to the correct trans_op. The trans_op internal table * will then determine the best SA for that trans_op from the key schedule to * use for encoding. */ -static int edge_init_keyschedule( n2n_edge_t * eee ) +static int edge_init_keyschedule(n2n_edge_t * eee) { #define N2N_NUM_CIPHERSPECS 32 - int retval = -1; - ssize_t numSpecs=0; - n2n_cipherspec_t specs[N2N_NUM_CIPHERSPECS]; - size_t i; - time_t now = time(NULL); + int retval = -1; + ssize_t numSpecs=0; + n2n_cipherspec_t specs[N2N_NUM_CIPHERSPECS]; + size_t i; + time_t now = time(NULL); - numSpecs = n2n_read_keyfile( specs, N2N_NUM_CIPHERSPECS, eee->keyschedule ); + numSpecs = n2n_read_keyfile(specs, N2N_NUM_CIPHERSPECS, eee->keyschedule); - if ( numSpecs > 0 ) + if(numSpecs > 0) { - traceEvent( TRACE_NORMAL, "keyfile = %s read -> %d specs.\n", optarg, (signed int)numSpecs); + traceEvent(TRACE_NORMAL, "keyfile = %s read -> %d specs.\n", optarg, (signed int)numSpecs); - for ( i=0; i < (size_t)numSpecs; ++i ) + for (i=0; i < (size_t)numSpecs; ++i) { - int idx; + int idx; - idx = transop_enum_to_index( specs[i].t ); + idx = transop_enum_to_index(specs[i].t); - switch (idx) + switch (idx) { case N2N_TRANSOP_TF_IDX: case N2N_TRANSOP_AESCBC_IDX: - { - retval = (eee->transop[idx].addspec)( &(eee->transop[idx]), - &(specs[i]) ); + { + retval = (eee->transop[idx].addspec)(&(eee->transop[idx]), + &(specs[i])); break; - } + } default: - retval = -1; + retval = -1; } - if (0 != retval) + if (0 != retval) { - traceEvent( TRACE_ERROR, "keyschedule failed to add spec[%u] to transop[%d].\n", - (unsigned int)i, idx); + traceEvent(TRACE_ERROR, "keyschedule failed to add spec[%u] to transop[%d].\n", + (unsigned int)i, idx); - return retval; + return retval; } } - n2n_tick_transop( eee, now ); + n2n_tick_transop(eee, now); } - else + else { - traceEvent( TRACE_ERROR, "Failed to process '%s'", eee->keyschedule ); + traceEvent(TRACE_ERROR, "Failed to process '%s'", eee->keyschedule); } - return retval; + return retval; } /** Deinitialise the edge and deallocate any owned memory. */ static void edge_deinit(n2n_edge_t * eee) { - if ( eee->udp_sock >=0 ) + if(eee->udp_sock >=0) { - closesocket( eee->udp_sock ); + closesocket(eee->udp_sock); } - if ( eee->udp_mgmt_sock >= 0 ) + if(eee->udp_mgmt_sock >= 0) { - closesocket(eee->udp_mgmt_sock); + closesocket(eee->udp_mgmt_sock); } - clear_peer_list( &(eee->pending_peers) ); - clear_peer_list( &(eee->known_peers) ); + clear_peer_list(&(eee->pending_peers)); + clear_peer_list(&(eee->known_peers)); - (eee->transop[N2N_TRANSOP_TF_IDX].deinit)(&eee->transop[N2N_TRANSOP_TF_IDX]); - (eee->transop[N2N_TRANSOP_NULL_IDX].deinit)(&eee->transop[N2N_TRANSOP_NULL_IDX]); + (eee->transop[N2N_TRANSOP_TF_IDX].deinit)(&eee->transop[N2N_TRANSOP_TF_IDX]); + (eee->transop[N2N_TRANSOP_NULL_IDX].deinit)(&eee->transop[N2N_TRANSOP_NULL_IDX]); } -static void readFromIPSocket( n2n_edge_t * eee ); +static void readFromIPSocket(n2n_edge_t * eee); -static void readFromMgmtSocket( n2n_edge_t * eee, int * keep_running ); +static void readFromMgmtSocket(n2n_edge_t * eee, int * keep_running); static void help() { print_n2n_version(); @@ -476,13 +476,13 @@ static void help() { "-c " "[-k | -K ] " "[-s ] " -#if defined(N2N_HAVE_SETUID) +#ifndef WIN32 "[-u -g ]" -#endif /* #ifndef N2N_HAVE_SETUID */ +#endif /* #ifndef WIN32 */ -#if defined(N2N_HAVE_DAEMON) +#ifndef WIN32 "[-f]" -#endif /* #if defined(N2N_HAVE_DAEMON) */ +#endif /* #ifndef WIN32 */ "[-m ]" "\n" "-l " @@ -506,9 +506,9 @@ static void help() { printf("-u | User ID (numeric) to use when privileges are dropped.\n"); printf("-g | Group ID (numeric) to use when privileges are dropped.\n"); #endif /* ifndef WIN32 */ -#ifdef N2N_HAVE_DAEMON +#ifndef WIN32 printf("-f | Do not fork and run as a daemon; rather run in foreground.\n"); -#endif /* #ifdef N2N_HAVE_DAEMON */ +#endif /* #ifndef WIN32 */ printf("-m | Fix MAC address for the TAP interface (otherwise it may be random)\n" " : eg. -m 01:02:03:04:05:06\n"); printf("-M | Specify n2n MTU of edge interface (default %d).\n", DEFAULT_MTU); @@ -518,146 +518,146 @@ static void help() { printf("-t | Management UDP Port (for multiple edges on a machine).\n"); printf("\nEnvironment variables:\n"); - printf(" N2N_KEY | Encryption key (ASCII). Not with -K or -k.\n" ); + printf(" N2N_KEY | Encryption key (ASCII). Not with -K or -k.\n"); exit(0); } /** Send a datagram to a socket defined by a n2n_sock_t */ -static ssize_t sendto_sock( int fd, const void * buf, size_t len, const n2n_sock_t * dest ) +static ssize_t sendto_sock(int fd, const void * buf, size_t len, const n2n_sock_t * dest) { - struct sockaddr_in peer_addr; - ssize_t sent; + struct sockaddr_in peer_addr; + ssize_t sent; - fill_sockaddr( (struct sockaddr *) &peer_addr, - sizeof(peer_addr), - dest ); + fill_sockaddr((struct sockaddr *) &peer_addr, + sizeof(peer_addr), + dest); - sent = sendto( fd, buf, len, 0/*flags*/, - (struct sockaddr *)&peer_addr, sizeof(struct sockaddr_in) ); - if ( sent < 0 ) + sent = sendto(fd, buf, len, 0/*flags*/, + (struct sockaddr *)&peer_addr, sizeof(struct sockaddr_in)); + if(sent < 0) { - char * c = strerror(errno); - traceEvent( TRACE_ERROR, "sendto failed (%d) %s", errno, c ); + char * c = strerror(errno); + traceEvent(TRACE_ERROR, "sendto failed (%d) %s", errno, c); } - else + else { - traceEvent( TRACE_DEBUG, "sendto sent=%d to ", (signed int)sent ); + traceEvent(TRACE_DEBUG, "sendto sent=%d to ", (signed int)sent); } - return sent; + return sent; } /** Send a REGISTER packet to another edge. */ -static void send_register( n2n_edge_t * eee, - const n2n_sock_t * remote_peer) +static void send_register(n2n_edge_t * eee, + const n2n_sock_t * remote_peer) { - uint8_t pktbuf[N2N_PKT_BUF_SIZE]; - size_t idx; - ssize_t sent; - n2n_common_t cmn; - n2n_REGISTER_t reg; - n2n_sock_str_t sockbuf; + uint8_t pktbuf[N2N_PKT_BUF_SIZE]; + size_t idx; + ssize_t sent; + n2n_common_t cmn; + n2n_REGISTER_t reg; + n2n_sock_str_t sockbuf; - memset(&cmn, 0, sizeof(cmn) ); - memset(®, 0, sizeof(reg) ); - cmn.ttl=N2N_DEFAULT_TTL; - cmn.pc = n2n_register; - cmn.flags = 0; - memcpy( cmn.community, eee->community_name, N2N_COMMUNITY_SIZE ); + memset(&cmn, 0, sizeof(cmn)); + memset(®, 0, sizeof(reg)); + cmn.ttl=N2N_DEFAULT_TTL; + cmn.pc = n2n_register; + cmn.flags = 0; + memcpy(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE); - idx=0; - encode_uint32( reg.cookie, &idx, 123456789 ); - idx=0; - encode_mac( reg.srcMac, &idx, eee->device.mac_addr ); + idx=0; + encode_uint32(reg.cookie, &idx, 123456789); + idx=0; + encode_mac(reg.srcMac, &idx, eee->device.mac_addr); - idx=0; - encode_REGISTER( pktbuf, &idx, &cmn, ® ); + idx=0; + encode_REGISTER(pktbuf, &idx, &cmn, ®); - traceEvent( TRACE_INFO, "send REGISTER %s", - sock_to_cstr( sockbuf, remote_peer ) ); + traceEvent(TRACE_INFO, "send REGISTER %s", + sock_to_cstr(sockbuf, remote_peer)); - sent = sendto_sock( eee->udp_sock, pktbuf, idx, remote_peer ); + sent = sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer); } /** Send a REGISTER_SUPER packet to the current supernode. */ -static void send_register_super( n2n_edge_t * eee, - const n2n_sock_t * supernode) +static void send_register_super(n2n_edge_t * eee, + const n2n_sock_t * supernode) { - uint8_t pktbuf[N2N_PKT_BUF_SIZE]; - size_t idx; - ssize_t sent; - n2n_common_t cmn; - n2n_REGISTER_SUPER_t reg; - n2n_sock_str_t sockbuf; + uint8_t pktbuf[N2N_PKT_BUF_SIZE]; + size_t idx; + ssize_t sent; + n2n_common_t cmn; + n2n_REGISTER_SUPER_t reg; + n2n_sock_str_t sockbuf; - memset(&cmn, 0, sizeof(cmn) ); - memset(®, 0, sizeof(reg) ); - cmn.ttl=N2N_DEFAULT_TTL; - cmn.pc = n2n_register_super; - cmn.flags = 0; - memcpy( cmn.community, eee->community_name, N2N_COMMUNITY_SIZE ); + memset(&cmn, 0, sizeof(cmn)); + memset(®, 0, sizeof(reg)); + cmn.ttl=N2N_DEFAULT_TTL; + cmn.pc = n2n_register_super; + cmn.flags = 0; + memcpy(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE); - for( idx=0; idx < N2N_COOKIE_SIZE; ++idx ) + for(idx=0; idx < N2N_COOKIE_SIZE; ++idx) { - eee->last_cookie[idx] = rand() % 0xff; + eee->last_cookie[idx] = rand() % 0xff; } - memcpy( reg.cookie, eee->last_cookie, N2N_COOKIE_SIZE ); - reg.auth.scheme=0; /* No auth yet */ + memcpy(reg.cookie, eee->last_cookie, N2N_COOKIE_SIZE); + reg.auth.scheme=0; /* No auth yet */ - idx=0; - encode_mac( reg.edgeMac, &idx, eee->device.mac_addr ); + idx=0; + encode_mac(reg.edgeMac, &idx, eee->device.mac_addr); - idx=0; - encode_REGISTER_SUPER( pktbuf, &idx, &cmn, ® ); + idx=0; + encode_REGISTER_SUPER(pktbuf, &idx, &cmn, ®); - traceEvent( TRACE_INFO, "send REGISTER_SUPER to %s", - sock_to_cstr( sockbuf, supernode ) ); + traceEvent(TRACE_INFO, "send REGISTER_SUPER to %s", + sock_to_cstr(sockbuf, supernode)); - sent = sendto_sock( eee->udp_sock, pktbuf, idx, supernode ); + sent = sendto_sock(eee->udp_sock, pktbuf, idx, supernode); } /** Send a REGISTER_ACK packet to a peer edge. */ -static void send_register_ack( n2n_edge_t * eee, - const n2n_sock_t * remote_peer, - const n2n_REGISTER_t * reg ) +static void send_register_ack(n2n_edge_t * eee, + const n2n_sock_t * remote_peer, + const n2n_REGISTER_t * reg) { - uint8_t pktbuf[N2N_PKT_BUF_SIZE]; - size_t idx; - ssize_t sent; - n2n_common_t cmn; - n2n_REGISTER_ACK_t ack; - n2n_sock_str_t sockbuf; + uint8_t pktbuf[N2N_PKT_BUF_SIZE]; + size_t idx; + ssize_t sent; + n2n_common_t cmn; + n2n_REGISTER_ACK_t ack; + n2n_sock_str_t sockbuf; - memset(&cmn, 0, sizeof(cmn) ); - memset(&ack, 0, sizeof(reg) ); - cmn.ttl=N2N_DEFAULT_TTL; - cmn.pc = n2n_register_ack; - cmn.flags = 0; - memcpy( cmn.community, eee->community_name, N2N_COMMUNITY_SIZE ); + memset(&cmn, 0, sizeof(cmn)); + memset(&ack, 0, sizeof(reg)); + cmn.ttl=N2N_DEFAULT_TTL; + cmn.pc = n2n_register_ack; + cmn.flags = 0; + memcpy(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE); - memset( &ack, 0, sizeof(ack) ); - memcpy( ack.cookie, reg->cookie, N2N_COOKIE_SIZE ); - memcpy( ack.srcMac, eee->device.mac_addr, N2N_MAC_SIZE ); - memcpy( ack.dstMac, reg->srcMac, N2N_MAC_SIZE ); + memset(&ack, 0, sizeof(ack)); + memcpy(ack.cookie, reg->cookie, N2N_COOKIE_SIZE); + memcpy(ack.srcMac, eee->device.mac_addr, N2N_MAC_SIZE); + memcpy(ack.dstMac, reg->srcMac, N2N_MAC_SIZE); - idx=0; - encode_REGISTER_ACK( pktbuf, &idx, &cmn, &ack ); + idx=0; + encode_REGISTER_ACK(pktbuf, &idx, &cmn, &ack); - traceEvent( TRACE_INFO, "send REGISTER_ACK %s", - sock_to_cstr( sockbuf, remote_peer ) ); + traceEvent(TRACE_INFO, "send REGISTER_ACK %s", + sock_to_cstr(sockbuf, remote_peer)); - sent = sendto_sock( eee->udp_sock, pktbuf, idx, remote_peer ); + sent = sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer); } @@ -669,27 +669,27 @@ static void send_register_ack( n2n_edge_t * eee, static void send_deregister(n2n_edge_t * eee, n2n_sock_t * remote_peer) { - /* Marshall and send message */ + /* Marshall and send message */ } -static int is_empty_ip_address( const n2n_sock_t * sock ); +static int is_empty_ip_address(const n2n_sock_t * sock); static void update_peer_address(n2n_edge_t * eee, uint8_t from_supernode, const n2n_mac_t mac, const n2n_sock_t * peer, time_t when); -void check_peer( n2n_edge_t * eee, - uint8_t from_supernode, - const n2n_mac_t mac, - const n2n_sock_t * peer ); -void try_send_register( n2n_edge_t * eee, - uint8_t from_supernode, - const n2n_mac_t mac, - const n2n_sock_t * peer ); -void set_peer_operational( n2n_edge_t * eee, - const n2n_mac_t mac, - const n2n_sock_t * peer ); +void check_peer(n2n_edge_t * eee, + uint8_t from_supernode, + const n2n_mac_t mac, + const n2n_sock_t * peer); +void try_send_register(n2n_edge_t * eee, + uint8_t from_supernode, + const n2n_mac_t mac, + const n2n_sock_t * peer); +void set_peer_operational(n2n_edge_t * eee, + const n2n_mac_t mac, + const n2n_sock_t * peer); @@ -706,62 +706,62 @@ void set_peer_operational( n2n_edge_t * eee, * * Called from the main loop when Rx a packet for our device mac. */ -void try_send_register( n2n_edge_t * eee, - uint8_t from_supernode, - const n2n_mac_t mac, - const n2n_sock_t * peer ) +void try_send_register(n2n_edge_t * eee, + uint8_t from_supernode, + const n2n_mac_t mac, + const n2n_sock_t * peer) { - /* REVISIT: purge of pending_peers not yet done. */ - struct peer_info * scan = find_peer_by_mac( eee->pending_peers, mac ); - macstr_t mac_buf; - n2n_sock_str_t sockbuf; + /* REVISIT: purge of pending_peers not yet done. */ + struct peer_info * scan = find_peer_by_mac(eee->pending_peers, mac); + macstr_t mac_buf; + n2n_sock_str_t sockbuf; - if ( NULL == scan ) + if(NULL == scan) { - scan = calloc( 1, sizeof( struct peer_info ) ); + scan = calloc(1, sizeof(struct peer_info)); - memcpy(scan->mac_addr, mac, N2N_MAC_SIZE); - scan->sock = *peer; - scan->last_seen = time(NULL); /* Don't change this it marks the pending peer for removal. */ + memcpy(scan->mac_addr, mac, N2N_MAC_SIZE); + scan->sock = *peer; + scan->last_seen = time(NULL); /* Don't change this it marks the pending peer for removal. */ - peer_list_add( &(eee->pending_peers), scan ); + peer_list_add(&(eee->pending_peers), scan); - traceEvent( TRACE_DEBUG, "=== new pending %s -> %s", - macaddr_str( mac_buf, scan->mac_addr ), - sock_to_cstr( sockbuf, &(scan->sock) ) ); + traceEvent(TRACE_DEBUG, "=== new pending %s -> %s", + macaddr_str(mac_buf, scan->mac_addr), + sock_to_cstr(sockbuf, &(scan->sock))); - traceEvent( TRACE_INFO, "Pending peers list size=%u", - (unsigned int)peer_list_size( eee->pending_peers ) ); + traceEvent(TRACE_INFO, "Pending peers list size=%u", + (unsigned int)peer_list_size(eee->pending_peers)); - /* trace Sending REGISTER */ + /* trace Sending REGISTER */ - send_register(eee, &(scan->sock) ); + send_register(eee, &(scan->sock)); - /* pending_peers now owns scan. */ + /* pending_peers now owns scan. */ } - else + else { } } /** Update the last_seen time for this peer, or get registered. */ -void check_peer( n2n_edge_t * eee, - uint8_t from_supernode, - const n2n_mac_t mac, - const n2n_sock_t * peer ) +void check_peer(n2n_edge_t * eee, + uint8_t from_supernode, + const n2n_mac_t mac, + const n2n_sock_t * peer) { - struct peer_info * scan = find_peer_by_mac( eee->known_peers, mac ); + struct peer_info * scan = find_peer_by_mac(eee->known_peers, mac); - if ( NULL == scan ) + if(NULL == scan) { - /* Not in known_peers - start the REGISTER process. */ - try_send_register( eee, from_supernode, mac, peer ); + /* Not in known_peers - start the REGISTER process. */ + try_send_register(eee, from_supernode, mac, peer); } - else + else { - /* Already in known_peers. */ - update_peer_address( eee, from_supernode, mac, peer, time(NULL) ); + /* Already in known_peers. */ + update_peer_address(eee, from_supernode, mac, peer, time(NULL)); } } @@ -772,101 +772,101 @@ void check_peer( n2n_edge_t * eee, * * Called by main loop when Rx a REGISTER_ACK. */ -void set_peer_operational( n2n_edge_t * eee, - const n2n_mac_t mac, - const n2n_sock_t * peer ) +void set_peer_operational(n2n_edge_t * eee, + const n2n_mac_t mac, + const n2n_sock_t * peer) { - struct peer_info * prev = NULL; - struct peer_info * scan; - macstr_t mac_buf; - n2n_sock_str_t sockbuf; + struct peer_info * prev = NULL; + struct peer_info * scan; + macstr_t mac_buf; + n2n_sock_str_t sockbuf; - traceEvent( TRACE_INFO, "set_peer_operational: %s -> %s", - macaddr_str( mac_buf, mac), - sock_to_cstr( sockbuf, peer ) ); + traceEvent(TRACE_INFO, "set_peer_operational: %s -> %s", + macaddr_str(mac_buf, mac), + sock_to_cstr(sockbuf, peer)); - scan=eee->pending_peers; + scan=eee->pending_peers; - while ( NULL != scan ) + while (NULL != scan) { - if ( 0 == memcmp( scan->mac_addr, mac, N2N_MAC_SIZE ) ) + if(0 == memcmp(scan->mac_addr, mac, N2N_MAC_SIZE)) { - break; /* found. */ + break; /* found. */ } - prev = scan; - scan = scan->next; + prev = scan; + scan = scan->next; } - if ( scan ) + if(scan) { - /* Remove scan from pending_peers. */ - if ( prev ) + /* Remove scan from pending_peers. */ + if(prev) { - prev->next = scan->next; + prev->next = scan->next; } - else + else { - eee->pending_peers = scan->next; + eee->pending_peers = scan->next; } - /* Add scan to known_peers. */ - scan->next = eee->known_peers; - eee->known_peers = scan; + /* Add scan to known_peers. */ + scan->next = eee->known_peers; + eee->known_peers = scan; - scan->sock = *peer; + scan->sock = *peer; - traceEvent( TRACE_DEBUG, "=== new peer %s -> %s", - macaddr_str( mac_buf, scan->mac_addr), - sock_to_cstr( sockbuf, &(scan->sock) ) ); + traceEvent(TRACE_DEBUG, "=== new peer %s -> %s", + macaddr_str(mac_buf, scan->mac_addr), + sock_to_cstr(sockbuf, &(scan->sock))); - traceEvent( TRACE_INFO, "Pending peers list size=%u", - (unsigned int)peer_list_size( eee->pending_peers ) ); + traceEvent(TRACE_INFO, "Pending peers list size=%u", + (unsigned int)peer_list_size(eee->pending_peers)); - traceEvent( TRACE_INFO, "Operational peers list size=%u", - (unsigned int)peer_list_size( eee->known_peers ) ); + traceEvent(TRACE_INFO, "Operational peers list size=%u", + (unsigned int)peer_list_size(eee->known_peers)); - scan->last_seen = time(NULL); + scan->last_seen = time(NULL); } - else + else { - traceEvent( TRACE_DEBUG, "Failed to find sender in pending_peers." ); + traceEvent(TRACE_DEBUG, "Failed to find sender in pending_peers."); } } n2n_mac_t broadcast_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; -static int is_empty_ip_address( const n2n_sock_t * sock ) +static int is_empty_ip_address(const n2n_sock_t * sock) { - const uint8_t * ptr=NULL; - size_t len=0; - size_t i; + const uint8_t * ptr=NULL; + size_t len=0; + size_t i; - if ( AF_INET6 == sock->family ) + if(AF_INET6 == sock->family) { - ptr = sock->addr.v6; - len = 16; + ptr = sock->addr.v6; + len = 16; } - else + else { - ptr = sock->addr.v4; - len = 4; + ptr = sock->addr.v4; + len = 4; } - for (i=0; iknown_peers; - struct peer_info *prev = NULL; /* use to remove bad registrations. */ - n2n_sock_str_t sockbuf1; - n2n_sock_str_t sockbuf2; /* don't clobber sockbuf1 if writing two addresses to trace */ - macstr_t mac_buf; + struct peer_info *scan = eee->known_peers; + struct peer_info *prev = NULL; /* use to remove bad registrations. */ + n2n_sock_str_t sockbuf1; + n2n_sock_str_t sockbuf2; /* don't clobber sockbuf1 if writing two addresses to trace */ + macstr_t mac_buf; - if ( is_empty_ip_address( peer ) ) + if(is_empty_ip_address(peer)) { - /* Not to be registered. */ - return; + /* Not to be registered. */ + return; } - if ( 0 == memcmp( mac, broadcast_mac, N2N_MAC_SIZE ) ) + if(0 == memcmp(mac, broadcast_mac, N2N_MAC_SIZE)) { - /* Not to be registered. */ - return; + /* Not to be registered. */ + return; } - while(scan != NULL) + while(scan != NULL) { - if(memcmp(mac, scan->mac_addr, N2N_MAC_SIZE) == 0) + if(memcmp(mac, scan->mac_addr, N2N_MAC_SIZE) == 0) { - break; + break; } - prev = scan; - scan = scan->next; + prev = scan; + scan = scan->next; } - if ( NULL == scan ) + if(NULL == scan) { - /* Not in known_peers. */ - return; + /* Not in known_peers. */ + return; } - if ( 0 != sock_equal( &(scan->sock), peer)) + if(0 != sock_equal(&(scan->sock), peer)) { - if ( 0 == from_supernode ) + if(0 == from_supernode) { - traceEvent( TRACE_NORMAL, "Peer changed %s: %s -> %s", - macaddr_str( mac_buf, scan->mac_addr ), - sock_to_cstr(sockbuf1, &(scan->sock)), - sock_to_cstr(sockbuf2, peer) ); + traceEvent(TRACE_NORMAL, "Peer changed %s: %s -> %s", + macaddr_str(mac_buf, scan->mac_addr), + sock_to_cstr(sockbuf1, &(scan->sock)), + sock_to_cstr(sockbuf2, peer)); - /* The peer has changed public socket. It can no longer be assumed to be reachable. */ - /* Remove the peer. */ - if ( NULL == prev ) + /* The peer has changed public socket. It can no longer be assumed to be reachable. */ + /* Remove the peer. */ + if(NULL == prev) { - /* scan was head of list */ - eee->known_peers = scan->next; + /* scan was head of list */ + eee->known_peers = scan->next; } - else + else { - prev->next = scan->next; + prev->next = scan->next; } - free(scan); + free(scan); - try_send_register( eee, from_supernode, mac, peer ); + try_send_register(eee, from_supernode, mac, 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 { - /* Found and unchanged. */ - scan->last_seen = when; + /* Found and unchanged. */ + scan->last_seen = when; } } @@ -1013,55 +1013,55 @@ static void send_grat_arps(n2n_edge_t * eee,) { * * This is frequently called by the main loop. */ -static void update_supernode_reg( n2n_edge_t * eee, time_t nowTime ) +static void update_supernode_reg(n2n_edge_t * eee, time_t nowTime) { - if ( eee->sn_wait && ( nowTime > (eee->last_register_req + (eee->register_lifetime/10) ) ) ) + if(eee->sn_wait && (nowTime > (eee->last_register_req + (eee->register_lifetime/10)))) { - /* fall through */ - traceEvent( TRACE_DEBUG, "update_supernode_reg: doing fast retry." ); + /* fall through */ + traceEvent(TRACE_DEBUG, "update_supernode_reg: doing fast retry."); } - else if ( nowTime < (eee->last_register_req + eee->register_lifetime)) + else if(nowTime < (eee->last_register_req + eee->register_lifetime)) { - return; /* Too early */ + return; /* Too early */ } - if ( 0 == eee->sup_attempts ) + if(0 == eee->sup_attempts) { - /* Give up on that supernode and try the next one. */ - ++(eee->sn_idx); + /* Give up on that supernode and try the next one. */ + ++(eee->sn_idx); - if (eee->sn_idx >= eee->sn_num) + if (eee->sn_idx >= eee->sn_num) { - /* Got to end of list, go back to the start. Also works for list of one entry. */ - eee->sn_idx=0; + /* Got to end of list, go back to the start. Also works for list of one entry. */ + eee->sn_idx=0; } - traceEvent(TRACE_WARNING, "Supernode not responding - moving to %u of %u", - (unsigned int)eee->sn_idx, (unsigned int)eee->sn_num ); + traceEvent(TRACE_WARNING, "Supernode not responding - moving to %u of %u", + (unsigned int)eee->sn_idx, (unsigned int)eee->sn_num); - eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; + eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; } - else + else { - --(eee->sup_attempts); + --(eee->sup_attempts); } - if(eee->re_resolve_supernode_ip || (eee->sn_num > 1) ) + if(eee->re_resolve_supernode_ip || (eee->sn_num > 1)) { - supernode2addr(&(eee->supernode), eee->sn_ip_array[eee->sn_idx] ); + supernode2addr(&(eee->supernode), eee->sn_ip_array[eee->sn_idx]); } - traceEvent(TRACE_DEBUG, "Registering with supernode (%s) (attempts left %u)", - supernode_ip(eee), (unsigned int)eee->sup_attempts); + traceEvent(TRACE_DEBUG, "Registering with supernode (%s) (attempts left %u)", + supernode_ip(eee), (unsigned int)eee->sup_attempts); - send_register_super( eee, &(eee->supernode) ); + send_register_super(eee, &(eee->supernode)); - eee->sn_wait=1; + eee->sn_wait=1; - /* REVISIT: turn-on gratuitous ARP with config option. */ - /* send_grat_arps(sock_fd, is_udp_sock); */ + /* REVISIT: turn-on gratuitous ARP with config option. */ + /* send_grat_arps(sock_fd, is_udp_sock); */ - eee->last_register_req = nowTime; + eee->last_register_req = nowTime; } @@ -1071,41 +1071,41 @@ static int find_peer_destination(n2n_edge_t * eee, n2n_mac_t mac_address, n2n_sock_t * destination) { - const struct peer_info *scan = eee->known_peers; - macstr_t mac_buf; - n2n_sock_str_t sockbuf; - int retval=0; + const struct peer_info *scan = eee->known_peers; + macstr_t mac_buf; + n2n_sock_str_t sockbuf; + int retval=0; - traceEvent(TRACE_DEBUG, "Searching destination peer for MAC %02X:%02X:%02X:%02X:%02X:%02X", - mac_address[0] & 0xFF, mac_address[1] & 0xFF, mac_address[2] & 0xFF, - mac_address[3] & 0xFF, mac_address[4] & 0xFF, mac_address[5] & 0xFF); + traceEvent(TRACE_DEBUG, "Searching destination peer for MAC %02X:%02X:%02X:%02X:%02X:%02X", + mac_address[0] & 0xFF, mac_address[1] & 0xFF, mac_address[2] & 0xFF, + mac_address[3] & 0xFF, mac_address[4] & 0xFF, mac_address[5] & 0xFF); - while(scan != NULL) { - traceEvent(TRACE_DEBUG, "Evaluating peer [MAC=%02X:%02X:%02X:%02X:%02X:%02X]", - scan->mac_addr[0] & 0xFF, scan->mac_addr[1] & 0xFF, scan->mac_addr[2] & 0xFF, - scan->mac_addr[3] & 0xFF, scan->mac_addr[4] & 0xFF, scan->mac_addr[5] & 0xFF - ); + while(scan != NULL) { + traceEvent(TRACE_DEBUG, "Evaluating peer [MAC=%02X:%02X:%02X:%02X:%02X:%02X]", + scan->mac_addr[0] & 0xFF, scan->mac_addr[1] & 0xFF, scan->mac_addr[2] & 0xFF, + scan->mac_addr[3] & 0xFF, scan->mac_addr[4] & 0xFF, scan->mac_addr[5] & 0xFF + ); - if((scan->last_seen > 0) && - (memcmp(mac_address, scan->mac_addr, N2N_MAC_SIZE) == 0)) - { - memcpy(destination, &scan->sock, sizeof(n2n_sock_t)); - retval=1; - break; - } - scan = scan->next; - } + if((scan->last_seen > 0) && + (memcmp(mac_address, scan->mac_addr, N2N_MAC_SIZE) == 0)) + { + memcpy(destination, &scan->sock, sizeof(n2n_sock_t)); + retval=1; + break; + } + scan = scan->next; + } - if ( 0 == retval ) + if(0 == retval) { - memcpy(destination, &(eee->supernode), sizeof(struct sockaddr_in)); + memcpy(destination, &(eee->supernode), sizeof(struct sockaddr_in)); } - traceEvent(TRACE_DEBUG, "find_peer_address (%s) -> [%s]", - macaddr_str( mac_buf, mac_address ), - sock_to_cstr( sockbuf, destination ) ); + traceEvent(TRACE_DEBUG, "find_peer_address (%s) -> [%s]", + macaddr_str(mac_buf, mac_address), + sock_to_cstr(sockbuf, destination)); - return retval; + return retval; } @@ -1129,34 +1129,34 @@ static const struct option long_options[] = { /** Send an ecapsulated ethernet PACKET to a destination edge or broadcast MAC * address. */ -static int send_PACKET( n2n_edge_t * eee, - n2n_mac_t dstMac, - const uint8_t * pktbuf, - size_t pktlen ) +static int send_PACKET(n2n_edge_t * eee, + n2n_mac_t dstMac, + const uint8_t * pktbuf, + size_t pktlen) { - int dest; - ssize_t s; - n2n_sock_str_t sockbuf; - n2n_sock_t destination; + int dest; + ssize_t s; + n2n_sock_str_t sockbuf; + n2n_sock_t destination; - /* hexdump( pktbuf, pktlen ); */ + /* hexdump(pktbuf, pktlen); */ - dest = find_peer_destination(eee, dstMac, &destination); + dest = find_peer_destination(eee, dstMac, &destination); - if ( dest ) + if(dest) { - ++(eee->tx_p2p); + ++(eee->tx_p2p); } - else + else { - ++(eee->tx_sup); + ++(eee->tx_sup); } - traceEvent( TRACE_INFO, "send_PACKET to %s", sock_to_cstr( sockbuf, &destination ) ); + traceEvent(TRACE_INFO, "send_PACKET to %s", sock_to_cstr(sockbuf, &destination)); - s = sendto_sock( eee->udp_sock, pktbuf, pktlen, &destination ); + s = sendto_sock(eee->udp_sock, pktbuf, pktlen, &destination); - return 0; + return 0; } @@ -1168,14 +1168,14 @@ static int send_PACKET( n2n_edge_t * eee, * the case where all SAs are expired an arbitrary transform will be chosen for * Tx. It will fail having no valid SAs but one must be selected. */ -static size_t edge_choose_tx_transop( const n2n_edge_t * eee ) +static size_t edge_choose_tx_transop(const n2n_edge_t * eee) { - if ( eee->null_transop) + if(eee->null_transop) { - return N2N_TRANSOP_NULL_IDX; + return N2N_TRANSOP_NULL_IDX; } - return eee->tx_transop_idx; + return eee->tx_transop_idx; } @@ -1183,121 +1183,121 @@ static size_t edge_choose_tx_transop( const n2n_edge_t * eee ) static void send_packet2net(n2n_edge_t * eee, uint8_t *tap_pkt, size_t len) { - ipstr_t ip_buf; - n2n_mac_t destMac; + ipstr_t ip_buf; + n2n_mac_t destMac; - n2n_common_t cmn; - n2n_PACKET_t pkt; + n2n_common_t cmn; + n2n_PACKET_t pkt; - uint8_t pktbuf[N2N_PKT_BUF_SIZE]; - size_t idx=0; - size_t tx_transop_idx=0; + uint8_t pktbuf[N2N_PKT_BUF_SIZE]; + size_t idx=0; + size_t tx_transop_idx=0; - ether_hdr_t eh; + ether_hdr_t eh; - /* tap_pkt is not aligned so we have to copy to aligned memory */ - memcpy( &eh, tap_pkt, sizeof(ether_hdr_t) ); + /* tap_pkt is not aligned so we have to copy to aligned memory */ + memcpy(&eh, tap_pkt, sizeof(ether_hdr_t)); - /* Discard IP packets that are not originated by this hosts */ - if(!(eee->allow_routing)) { - if(ntohs(eh.type) == 0x0800) { - /* This is an IP packet from the local source address - not forwarded. */ + /* Discard IP packets that are not originated by this hosts */ + if(!(eee->allow_routing)) { + if(ntohs(eh.type) == 0x0800) { + /* This is an IP packet from the local source address - not forwarded. */ #define ETH_FRAMESIZE 14 #define IP4_SRCOFFSET 12 - uint32_t *dst = (uint32_t*)&tap_pkt[ETH_FRAMESIZE + IP4_SRCOFFSET]; + uint32_t *dst = (uint32_t*)&tap_pkt[ETH_FRAMESIZE + IP4_SRCOFFSET]; - /* Note: all elements of the_ip are in network order */ - if( *dst != eee->device.ip_addr) { - /* This is a packet that needs to be routed */ - traceEvent(TRACE_INFO, "Discarding routed packet [%s]", - intoa(ntohl(*dst), ip_buf, sizeof(ip_buf))); - return; - } else { - /* This packet is originated by us */ - /* traceEvent(TRACE_INFO, "Sending non-routed packet"); */ - } - } + /* Note: all elements of the_ip are in network order */ + if(*dst != eee->device.ip_addr) { + /* This is a packet that needs to be routed */ + traceEvent(TRACE_INFO, "Discarding routed packet [%s]", + intoa(ntohl(*dst), ip_buf, sizeof(ip_buf))); + return; + } else { + /* This packet is originated by us */ + /* traceEvent(TRACE_INFO, "Sending non-routed packet"); */ + } } + } - /* Optionally compress then apply transforms, eg encryption. */ + /* Optionally compress then apply transforms, eg encryption. */ - /* Once processed, send to destination in PACKET */ + /* Once processed, send to destination in PACKET */ - memcpy( destMac, tap_pkt, N2N_MAC_SIZE ); /* dest MAC is first in ethernet header */ + memcpy(destMac, tap_pkt, N2N_MAC_SIZE); /* dest MAC is first in ethernet header */ - memset( &cmn, 0, sizeof(cmn) ); - cmn.ttl = N2N_DEFAULT_TTL; - cmn.pc = n2n_packet; - cmn.flags=0; /* no options, not from supernode, no socket */ - memcpy( cmn.community, eee->community_name, N2N_COMMUNITY_SIZE ); + memset(&cmn, 0, sizeof(cmn)); + cmn.ttl = N2N_DEFAULT_TTL; + cmn.pc = n2n_packet; + cmn.flags=0; /* no options, not from supernode, no socket */ + memcpy(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE); - memset( &pkt, 0, sizeof(pkt) ); - memcpy( pkt.srcMac, eee->device.mac_addr, N2N_MAC_SIZE); - memcpy( pkt.dstMac, destMac, N2N_MAC_SIZE); + memset(&pkt, 0, sizeof(pkt)); + memcpy(pkt.srcMac, eee->device.mac_addr, N2N_MAC_SIZE); + memcpy(pkt.dstMac, destMac, N2N_MAC_SIZE); - tx_transop_idx = edge_choose_tx_transop( eee ); + tx_transop_idx = edge_choose_tx_transop(eee); - pkt.sock.family=0; /* do not encode sock */ - pkt.transform = eee->transop[tx_transop_idx].transform_id; + pkt.sock.family=0; /* do not encode sock */ + pkt.transform = eee->transop[tx_transop_idx].transform_id; - idx=0; - encode_PACKET( pktbuf, &idx, &cmn, &pkt ); - traceEvent( TRACE_DEBUG, "encoded PACKET header of size=%u transform %u (idx=%u)", - (unsigned int)idx, (unsigned int)pkt.transform, (unsigned int)tx_transop_idx ); + idx=0; + encode_PACKET(pktbuf, &idx, &cmn, &pkt); + traceEvent(TRACE_DEBUG, "encoded PACKET header of size=%u transform %u (idx=%u)", + (unsigned int)idx, (unsigned int)pkt.transform, (unsigned int)tx_transop_idx); - idx += eee->transop[tx_transop_idx].fwd( &(eee->transop[tx_transop_idx]), - pktbuf+idx, N2N_PKT_BUF_SIZE-idx, - tap_pkt, len ); - ++(eee->transop[tx_transop_idx].tx_cnt); /* stats */ + idx += eee->transop[tx_transop_idx].fwd(&(eee->transop[tx_transop_idx]), + pktbuf+idx, N2N_PKT_BUF_SIZE-idx, + tap_pkt, len); + ++(eee->transop[tx_transop_idx].tx_cnt); /* stats */ - send_PACKET( eee, destMac, pktbuf, idx ); /* to peer or supernode */ + send_PACKET(eee, destMac, pktbuf, idx); /* to peer or supernode */ } /** Destination MAC 33:33:0:00:00:00 - 33:33:FF:FF:FF:FF is reserved for IPv6 * neighbour discovery. */ -static int is_ip6_discovery( const void * buf, size_t bufsize ) +static int is_ip6_discovery(const void * buf, size_t bufsize) { - int retval = 0; + int retval = 0; - if ( bufsize >= sizeof(ether_hdr_t) ) + if(bufsize >= sizeof(ether_hdr_t)) { - /* copy to aligned memory */ - ether_hdr_t eh; - memcpy( &eh, buf, sizeof(ether_hdr_t) ); + /* copy to aligned memory */ + ether_hdr_t eh; + memcpy(&eh, buf, sizeof(ether_hdr_t)); - if ( (0x33 == eh.dhost[0]) && - (0x33 == eh.dhost[1]) ) + if((0x33 == eh.dhost[0]) && + (0x33 == eh.dhost[1])) { - retval = 1; /* This is an IPv6 multicast packet [RFC2464]. */ + retval = 1; /* This is an IPv6 multicast packet [RFC2464]. */ } } - return retval; + return retval; } /** Destination 01:00:5E:00:00:00 - 01:00:5E:7F:FF:FF is multicast ethernet. */ -static int is_ethMulticast( const void * buf, size_t bufsize ) +static int is_ethMulticast(const void * buf, size_t bufsize) { - int retval = 0; + int retval = 0; - /* Match 01:00:5E:00:00:00 - 01:00:5E:7F:FF:FF */ - if ( bufsize >= sizeof(ether_hdr_t) ) + /* Match 01:00:5E:00:00:00 - 01:00:5E:7F:FF:FF */ + if(bufsize >= sizeof(ether_hdr_t)) { - /* copy to aligned memory */ - ether_hdr_t eh; - memcpy( &eh, buf, sizeof(ether_hdr_t) ); + /* copy to aligned memory */ + ether_hdr_t eh; + memcpy(&eh, buf, sizeof(ether_hdr_t)); - if ( (0x01 == eh.dhost[0]) && - (0x00 == eh.dhost[1]) && - (0x5E == eh.dhost[2]) && - (0 == (0x80 & eh.dhost[3])) ) + if((0x01 == eh.dhost[0]) && + (0x00 == eh.dhost[1]) && + (0x5E == eh.dhost[2]) && + (0 == (0x80 & eh.dhost[3]))) { - retval = 1; /* This is an ethernet multicast packet [RFC1112]. */ + retval = 1; /* This is an ethernet multicast packet [RFC1112]. */ } } - return retval; + return retval; } @@ -1305,37 +1305,37 @@ static int is_ethMulticast( const void * buf, size_t bufsize ) /** Read a single packet from the TAP interface, process it and write out the * corresponding packet to the cooked socket. */ -static void readFromTAPSocket( n2n_edge_t * eee ) +static void readFromTAPSocket(n2n_edge_t * eee) { - /* tun -> remote */ - uint8_t eth_pkt[N2N_PKT_BUF_SIZE]; - macstr_t mac_buf; - ssize_t len; + /* tun -> remote */ + uint8_t eth_pkt[N2N_PKT_BUF_SIZE]; + macstr_t mac_buf; + ssize_t len; - len = tuntap_read( &(eee->device), eth_pkt, N2N_PKT_BUF_SIZE ); + len = tuntap_read(&(eee->device), eth_pkt, N2N_PKT_BUF_SIZE); - if( (len <= 0) || (len > N2N_PKT_BUF_SIZE) ) + if((len <= 0) || (len > N2N_PKT_BUF_SIZE)) { - traceEvent(TRACE_WARNING, "read()=%d [%d/%s]", - (signed int)len, errno, strerror(errno)); + traceEvent(TRACE_WARNING, "read()=%d [%d/%s]", + (signed int)len, errno, strerror(errno)); } - else + else { - const uint8_t * mac = eth_pkt; - traceEvent(TRACE_INFO, "### Rx TAP packet (%4d) for %s", - (signed int)len, macaddr_str(mac_buf, mac) ); + const uint8_t * mac = eth_pkt; + traceEvent(TRACE_INFO, "### Rx TAP packet (%4d) for %s", + (signed int)len, macaddr_str(mac_buf, mac)); - if ( eee->drop_multicast && - ( is_ip6_discovery( eth_pkt, len ) || - is_ethMulticast( eth_pkt, len) - ) - ) + if(eee->drop_multicast && + (is_ip6_discovery(eth_pkt, len) || + is_ethMulticast(eth_pkt, len) + ) + ) { - traceEvent(TRACE_DEBUG, "Dropping multicast"); + traceEvent(TRACE_DEBUG, "Dropping multicast"); } - else + else { - send_packet2net(eee, eth_pkt, len); + send_packet2net(eee, eth_pkt, len); } } } @@ -1344,422 +1344,422 @@ static void readFromTAPSocket( n2n_edge_t * eee ) /** A PACKET has arrived containing an encapsulated ethernet datagram - usually * encrypted. */ -static int handle_PACKET( n2n_edge_t * eee, - const n2n_common_t * cmn, - const n2n_PACKET_t * pkt, - const n2n_sock_t * orig_sender, - uint8_t * payload, - size_t psize ) +static int handle_PACKET(n2n_edge_t * eee, + const n2n_common_t * cmn, + const n2n_PACKET_t * pkt, + const n2n_sock_t * orig_sender, + uint8_t * payload, + size_t psize) { - ssize_t data_sent_len; - uint8_t from_supernode; - uint8_t * eth_payload=NULL; - int retval = -1; - time_t now; + ssize_t data_sent_len; + uint8_t from_supernode; + uint8_t * eth_payload=NULL; + int retval = -1; + time_t now; - now = time(NULL); + now = time(NULL); - traceEvent( TRACE_DEBUG, "handle_PACKET size %u transform %u", - (unsigned int)psize, (unsigned int)pkt->transform ); - /* hexdump( payload, psize ); */ + traceEvent(TRACE_DEBUG, "handle_PACKET size %u transform %u", + (unsigned int)psize, (unsigned int)pkt->transform); + /* hexdump(payload, psize); */ - from_supernode= cmn->flags & N2N_FLAGS_FROM_SUPERNODE; + from_supernode= cmn->flags & N2N_FLAGS_FROM_SUPERNODE; - if ( from_supernode ) + if(from_supernode) { - ++(eee->rx_sup); - eee->last_sup=now; + ++(eee->rx_sup); + eee->last_sup=now; } + else + { + ++(eee->rx_p2p); + eee->last_p2p=now; + } + + /* Update the sender in peer table entry */ + check_peer(eee, from_supernode, pkt->srcMac, orig_sender); + + /* Handle transform. */ + { + uint8_t decodebuf[N2N_PKT_BUF_SIZE]; + size_t eth_size; + int rx_transop_idx; + + rx_transop_idx = transop_enum_to_index(pkt->transform); + + if(rx_transop_idx >=0) + { + eth_payload = decodebuf; + eth_size = eee->transop[rx_transop_idx].rev(&(eee->transop[rx_transop_idx]), + eth_payload, N2N_PKT_BUF_SIZE, + payload, psize); + ++(eee->transop[rx_transop_idx].rx_cnt); /* stats */ + + /* Write ethernet packet to tap device. */ + traceEvent(TRACE_INFO, "sending to TAP %u", (unsigned int)eth_size); + data_sent_len = tuntap_write(&(eee->device), eth_payload, eth_size); + + if (data_sent_len == eth_size) + { + retval = 0; + } + } else - { - ++(eee->rx_p2p); - eee->last_p2p=now; - } + { + traceEvent(TRACE_ERROR, "handle_PACKET dropped unknown transform enum %u", + (unsigned int)pkt->transform); + } + } - /* Update the sender in peer table entry */ - check_peer( eee, from_supernode, pkt->srcMac, orig_sender ); - - /* Handle transform. */ - { - uint8_t decodebuf[N2N_PKT_BUF_SIZE]; - size_t eth_size; - size_t rx_transop_idx=0; - - rx_transop_idx = transop_enum_to_index(pkt->transform); - - if ( rx_transop_idx >=0 ) - { - eth_payload = decodebuf; - eth_size = eee->transop[rx_transop_idx].rev( &(eee->transop[rx_transop_idx]), - eth_payload, N2N_PKT_BUF_SIZE, - payload, psize ); - ++(eee->transop[rx_transop_idx].rx_cnt); /* stats */ - - /* Write ethernet packet to tap device. */ - traceEvent( TRACE_INFO, "sending to TAP %u", (unsigned int)eth_size ); - data_sent_len = tuntap_write(&(eee->device), eth_payload, eth_size); - - if (data_sent_len == eth_size) - { - retval = 0; - } - } - else - { - traceEvent( TRACE_ERROR, "handle_PACKET dropped unknown transform enum %u", - (unsigned int)pkt->transform ); - } - } - - return retval; + return retval; } /** Read a datagram from the management UDP socket and take appropriate * action. */ -static void readFromMgmtSocket( n2n_edge_t * eee, int * keep_running ) +static void readFromMgmtSocket(n2n_edge_t * eee, int * keep_running) { - uint8_t 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; + uint8_t 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; - 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); + 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 ) + if(recvlen < 0) { - traceEvent(TRACE_ERROR, "mgmt recvfrom failed with %s", strerror(errno) ); + traceEvent(TRACE_ERROR, "mgmt recvfrom failed with %s", strerror(errno)); - return; /* failed to receive data from UDP */ + return; /* failed to receive data from UDP */ } - if ( recvlen >= 4 ) + if(recvlen >= 4) { - if ( 0 == memcmp( udp_buf, "stop", 4 ) ) + if(0 == memcmp(udp_buf, "stop", 4)) { - traceEvent( TRACE_ERROR, "stop command received." ); - *keep_running = 0; - return; + traceEvent(TRACE_ERROR, "stop command received."); + *keep_running = 0; + return; } - if ( 0 == memcmp( udp_buf, "help", 4 ) ) + if(0 == memcmp(udp_buf, "help", 4)) { - msg_len=0; - ++traceLevel; + msg_len=0; + ++traceLevel; - msg_len += snprintf( (char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "Help for edge management console:\n" - " stop Gracefully exit edge\n" - " help This help message\n" - " +verb Increase verbosity of logging\n" - " -verb Decrease verbosity of logging\n" - " reload Re-read the keyschedule\n" - " Display statistics\n\n"); + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "Help for edge management console:\n" + " stop Gracefully exit edge\n" + " help This help message\n" + " +verb Increase verbosity of logging\n" + " -verb Decrease verbosity of logging\n" + " reload Re-read the keyschedule\n" + " Display statistics\n\n"); - sendto( eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, - (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in) ); + sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, + (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); - return; + return; } } - if ( recvlen >= 5 ) + if(recvlen >= 5) { - if ( 0 == memcmp( udp_buf, "+verb", 5 ) ) + if(0 == memcmp(udp_buf, "+verb", 5)) { - msg_len=0; - ++traceLevel; + msg_len=0; + ++traceLevel; - traceEvent( TRACE_ERROR, "+verb traceLevel=%u", (unsigned int)traceLevel ); - msg_len += snprintf( (char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "> +OK traceLevel=%u\n", (unsigned int)traceLevel ); + traceEvent(TRACE_ERROR, "+verb traceLevel=%u", (unsigned int)traceLevel); + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "> +OK traceLevel=%u\n", (unsigned int)traceLevel); - sendto( eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, - (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in) ); + sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, + (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); - return; + return; } - if ( 0 == memcmp( udp_buf, "-verb", 5 ) ) + if(0 == memcmp(udp_buf, "-verb", 5)) { - msg_len=0; + msg_len=0; - if ( traceLevel > 0 ) + if(traceLevel > 0) { - --traceLevel; - msg_len += snprintf( (char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "> -OK traceLevel=%u\n", traceLevel ); + --traceLevel; + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "> -OK traceLevel=%u\n", traceLevel); } - else + else { - msg_len += snprintf( (char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "> -NOK traceLevel=%u\n", traceLevel ); + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "> -NOK traceLevel=%u\n", traceLevel); } - traceEvent( TRACE_ERROR, "-verb traceLevel=%u", (unsigned int)traceLevel ); + traceEvent(TRACE_ERROR, "-verb traceLevel=%u", (unsigned int)traceLevel); - sendto( eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, - (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in) ); - return; + sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, + (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); + return; } } - if ( recvlen >= 6 ) + if(recvlen >= 6) { - if ( 0 == memcmp( udp_buf, "reload", 6 ) ) + if(0 == memcmp(udp_buf, "reload", 6)) { - if ( strlen( eee->keyschedule ) > 0 ) + if(strlen(eee->keyschedule) > 0) { - if ( edge_init_keyschedule(eee) == 0 ) + if(edge_init_keyschedule(eee) == 0) { - msg_len=0; - msg_len += snprintf( (char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "> OK\n" ); - sendto( eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, - (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in) ); + msg_len=0; + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "> OK\n"); + sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, + (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); } - return; + return; } } } - traceEvent(TRACE_DEBUG, "mgmt status rq" ); + traceEvent(TRACE_DEBUG, "mgmt status rq"); - msg_len=0; - msg_len += snprintf( (char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "Statistics for edge\n" ); + msg_len=0; + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "Statistics for edge\n"); - msg_len += snprintf( (char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "uptime %lu\n", - time(NULL) - eee->start_time ); + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "uptime %lu\n", + time(NULL) - eee->start_time); - msg_len += snprintf( (char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "paths super:%u,%u p2p:%u,%u\n", - (unsigned int)eee->tx_sup, - (unsigned int)eee->rx_sup, - (unsigned int)eee->tx_p2p, - (unsigned int)eee->rx_p2p ); + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "paths super:%u,%u p2p:%u,%u\n", + (unsigned int)eee->tx_sup, + (unsigned int)eee->rx_sup, + (unsigned int)eee->tx_p2p, + (unsigned int)eee->rx_p2p); - msg_len += snprintf( (char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "trans:null |%6u|%6u|\n" - "trans:tf |%6u|%6u|\n" - "trans:aes |%6u|%6u|\n", - (unsigned int)eee->transop[N2N_TRANSOP_NULL_IDX].tx_cnt, - (unsigned int)eee->transop[N2N_TRANSOP_NULL_IDX].rx_cnt, - (unsigned int)eee->transop[N2N_TRANSOP_TF_IDX].tx_cnt, - (unsigned int)eee->transop[N2N_TRANSOP_TF_IDX].rx_cnt, - (unsigned int)eee->transop[N2N_TRANSOP_AESCBC_IDX].tx_cnt, - (unsigned int)eee->transop[N2N_TRANSOP_AESCBC_IDX].rx_cnt ); + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "trans:null |%6u|%6u|\n" + "trans:tf |%6u|%6u|\n" + "trans:aes |%6u|%6u|\n", + (unsigned int)eee->transop[N2N_TRANSOP_NULL_IDX].tx_cnt, + (unsigned int)eee->transop[N2N_TRANSOP_NULL_IDX].rx_cnt, + (unsigned int)eee->transop[N2N_TRANSOP_TF_IDX].tx_cnt, + (unsigned int)eee->transop[N2N_TRANSOP_TF_IDX].rx_cnt, + (unsigned int)eee->transop[N2N_TRANSOP_AESCBC_IDX].tx_cnt, + (unsigned int)eee->transop[N2N_TRANSOP_AESCBC_IDX].rx_cnt); - msg_len += snprintf( (char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "peers pend:%u full:%u\n", - (unsigned int)peer_list_size( eee->pending_peers ), - (unsigned int)peer_list_size( eee->known_peers ) ); + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "peers pend:%u full:%u\n", + (unsigned int)peer_list_size(eee->pending_peers), + (unsigned int)peer_list_size(eee->known_peers)); - msg_len += snprintf( (char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "last super:%lu(%ld sec ago) p2p:%lu(%ld sec ago)\n", - eee->last_sup, (now-eee->last_sup), eee->last_p2p, (now-eee->last_p2p) ); + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "last super:%lu(%ld sec ago) p2p:%lu(%ld sec ago)\n", + eee->last_sup, (now-eee->last_sup), eee->last_p2p, (now-eee->last_p2p)); - traceEvent(TRACE_DEBUG, "mgmt status sending: %s", udp_buf ); + traceEvent(TRACE_DEBUG, "mgmt status sending: %s", udp_buf); - sendlen = sendto( eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, - (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in) ); + sendlen = sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, + (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); } /** Read a datagram from the main UDP socket to the internet. */ -static void readFromIPSocket( n2n_edge_t * eee ) +static void readFromIPSocket(n2n_edge_t * eee) { - n2n_common_t cmn; /* common fields in the packet header */ + n2n_common_t cmn; /* common fields in the packet header */ - n2n_sock_str_t sockbuf1; - n2n_sock_str_t sockbuf2; /* don't clobber sockbuf1 if writing two addresses to trace */ - macstr_t mac_buf1; - macstr_t mac_buf2; + n2n_sock_str_t sockbuf1; + n2n_sock_str_t sockbuf2; /* don't clobber sockbuf1 if writing two addresses to trace */ + macstr_t mac_buf1; + macstr_t mac_buf2; - uint8_t udp_buf[N2N_PKT_BUF_SIZE]; /* Compete UDP packet */ - ssize_t recvlen; - size_t rem; - size_t idx; - size_t msg_type; - uint8_t from_supernode; - struct sockaddr_in sender_sock; - n2n_sock_t sender; - n2n_sock_t * orig_sender=NULL; - time_t now=0; + uint8_t udp_buf[N2N_PKT_BUF_SIZE]; /* Compete UDP packet */ + ssize_t recvlen; + size_t rem; + size_t idx; + size_t msg_type; + uint8_t from_supernode; + struct sockaddr_in sender_sock; + n2n_sock_t sender; + n2n_sock_t * orig_sender=NULL; + time_t now=0; - size_t i; + size_t i; - i = sizeof(sender_sock); - recvlen=recvfrom(eee->udp_sock, udp_buf, N2N_PKT_BUF_SIZE, 0/*flags*/, - (struct sockaddr *)&sender_sock, (socklen_t*)&i); + i = sizeof(sender_sock); + recvlen=recvfrom(eee->udp_sock, udp_buf, N2N_PKT_BUF_SIZE, 0/*flags*/, + (struct sockaddr *)&sender_sock, (socklen_t*)&i); - if ( recvlen < 0 ) + if(recvlen < 0) { - traceEvent(TRACE_ERROR, "recvfrom failed with %s", strerror(errno) ); + traceEvent(TRACE_ERROR, "recvfrom failed with %s", strerror(errno)); - return; /* failed to receive data from UDP */ + return; /* failed to receive data from UDP */ } - /* REVISIT: when UDP/IPv6 is supported we will need a flag to indicate which - * IP transport version the packet arrived on. May need to UDP sockets. */ - sender.family = AF_INET; /* udp_sock was opened PF_INET v4 */ - sender.port = ntohs(sender_sock.sin_port); - memcpy( &(sender.addr.v4), &(sender_sock.sin_addr.s_addr), IPV4_SIZE ); + /* REVISIT: when UDP/IPv6 is supported we will need a flag to indicate which + * IP transport version the packet arrived on. May need to UDP sockets. */ + sender.family = AF_INET; /* udp_sock was opened PF_INET v4 */ + sender.port = ntohs(sender_sock.sin_port); + memcpy(&(sender.addr.v4), &(sender_sock.sin_addr.s_addr), IPV4_SIZE); - /* The packet may not have an orig_sender socket spec. So default to last - * hop as sender. */ - orig_sender=&sender; + /* The packet may not have an orig_sender socket spec. So default to last + * hop as sender. */ + orig_sender=&sender; - traceEvent(TRACE_INFO, "### Rx N2N UDP (%d) from %s", - (signed int)recvlen, sock_to_cstr(sockbuf1, &sender) ); + traceEvent(TRACE_INFO, "### Rx N2N UDP (%d) from %s", + (signed int)recvlen, sock_to_cstr(sockbuf1, &sender)); - /* hexdump( udp_buf, recvlen ); */ + /* hexdump(udp_buf, recvlen); */ - rem = recvlen; /* Counts down bytes of packet to protect against buffer overruns. */ - idx = 0; /* marches through packet header as parts are decoded. */ - if ( decode_common(&cmn, udp_buf, &rem, &idx) < 0 ) + rem = recvlen; /* Counts down bytes of packet to protect against buffer overruns. */ + idx = 0; /* marches through packet header as parts are decoded. */ + if(decode_common(&cmn, udp_buf, &rem, &idx) < 0) { - traceEvent( TRACE_ERROR, "Failed to decode common section in N2N_UDP" ); - return; /* failed to decode packet */ + traceEvent(TRACE_ERROR, "Failed to decode common section in N2N_UDP"); + return; /* failed to decode packet */ } - now = time(NULL); + now = time(NULL); - msg_type = cmn.pc; /* packet code */ - from_supernode= cmn.flags & N2N_FLAGS_FROM_SUPERNODE; + msg_type = cmn.pc; /* packet code */ + from_supernode= cmn.flags & N2N_FLAGS_FROM_SUPERNODE; - if( 0 == memcmp(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE) ) + if(0 == memcmp(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE)) { - if( msg_type == MSG_TYPE_PACKET) + if(msg_type == MSG_TYPE_PACKET) { - /* process PACKET - most frequent so first in list. */ - n2n_PACKET_t pkt; + /* process PACKET - most frequent so first in list. */ + n2n_PACKET_t pkt; - decode_PACKET( &pkt, &cmn, udp_buf, &rem, &idx ); + decode_PACKET(&pkt, &cmn, udp_buf, &rem, &idx); - if ( pkt.sock.family ) + if(pkt.sock.family) { - orig_sender = &(pkt.sock); + orig_sender = &(pkt.sock); } - traceEvent(TRACE_INFO, "Rx PACKET from %s (%s)", - sock_to_cstr(sockbuf1, &sender), - sock_to_cstr(sockbuf2, orig_sender) ); + traceEvent(TRACE_INFO, "Rx PACKET from %s (%s)", + sock_to_cstr(sockbuf1, &sender), + sock_to_cstr(sockbuf2, orig_sender)); - handle_PACKET( eee, &cmn, &pkt, orig_sender, udp_buf+idx, recvlen-idx ); + handle_PACKET(eee, &cmn, &pkt, orig_sender, udp_buf+idx, recvlen-idx); } - else if(msg_type == MSG_TYPE_REGISTER) + else if(msg_type == MSG_TYPE_REGISTER) { - /* Another edge is registering with us */ - n2n_REGISTER_t reg; + /* Another edge is registering with us */ + n2n_REGISTER_t reg; - decode_REGISTER( ®, &cmn, udp_buf, &rem, &idx ); + decode_REGISTER(®, &cmn, udp_buf, &rem, &idx); - if ( reg.sock.family ) + if(reg.sock.family) { - orig_sender = &(reg.sock); + orig_sender = &(reg.sock); } - traceEvent(TRACE_INFO, "Rx REGISTER src=%s dst=%s from peer %s (%s)", - macaddr_str( mac_buf1, reg.srcMac ), - macaddr_str( mac_buf2, reg.dstMac ), - sock_to_cstr(sockbuf1, &sender), - sock_to_cstr(sockbuf2, orig_sender) ); + traceEvent(TRACE_INFO, "Rx REGISTER src=%s dst=%s from peer %s (%s)", + macaddr_str(mac_buf1, reg.srcMac), + macaddr_str(mac_buf2, reg.dstMac), + sock_to_cstr(sockbuf1, &sender), + sock_to_cstr(sockbuf2, orig_sender)); - if ( 0 == memcmp(reg.dstMac, (eee->device.mac_addr), 6) ) + if(0 == memcmp(reg.dstMac, (eee->device.mac_addr), 6)) { - check_peer( eee, from_supernode, reg.srcMac, orig_sender ); + check_peer(eee, from_supernode, reg.srcMac, orig_sender); } - send_register_ack(eee, orig_sender, ®); + send_register_ack(eee, orig_sender, ®); } - else if(msg_type == MSG_TYPE_REGISTER_ACK) + else if(msg_type == MSG_TYPE_REGISTER_ACK) { - /* Peer edge is acknowledging our register request */ - n2n_REGISTER_ACK_t ra; + /* Peer edge is acknowledging our register request */ + n2n_REGISTER_ACK_t ra; - decode_REGISTER_ACK( &ra, &cmn, udp_buf, &rem, &idx ); + decode_REGISTER_ACK(&ra, &cmn, udp_buf, &rem, &idx); - if ( ra.sock.family ) + if(ra.sock.family) { - orig_sender = &(ra.sock); + orig_sender = &(ra.sock); } - traceEvent(TRACE_INFO, "Rx REGISTER_ACK src=%s dst=%s from peer %s (%s)", - macaddr_str( mac_buf1, ra.srcMac ), - macaddr_str( mac_buf2, ra.dstMac ), - sock_to_cstr(sockbuf1, &sender), - sock_to_cstr(sockbuf2, orig_sender) ); + traceEvent(TRACE_INFO, "Rx REGISTER_ACK src=%s dst=%s from peer %s (%s)", + macaddr_str(mac_buf1, ra.srcMac), + macaddr_str(mac_buf2, ra.dstMac), + sock_to_cstr(sockbuf1, &sender), + sock_to_cstr(sockbuf2, orig_sender)); - /* Move from pending_peers to known_peers; ignore if not in pending. */ - set_peer_operational( eee, ra.srcMac, &sender ); + /* Move from pending_peers to known_peers; ignore if not in pending. */ + set_peer_operational(eee, ra.srcMac, &sender); } - else if(msg_type == MSG_TYPE_REGISTER_SUPER_ACK) + else if(msg_type == MSG_TYPE_REGISTER_SUPER_ACK) { - n2n_REGISTER_SUPER_ACK_t ra; + n2n_REGISTER_SUPER_ACK_t ra; - if ( eee->sn_wait ) + if(eee->sn_wait) { - decode_REGISTER_SUPER_ACK( &ra, &cmn, udp_buf, &rem, &idx ); + decode_REGISTER_SUPER_ACK(&ra, &cmn, udp_buf, &rem, &idx); - if ( ra.sock.family ) + if(ra.sock.family) { - orig_sender = &(ra.sock); + orig_sender = &(ra.sock); } - traceEvent(TRACE_NORMAL, "Rx REGISTER_SUPER_ACK myMAC=%s [%s] (external %s). Attempts %u", - macaddr_str( mac_buf1, ra.edgeMac ), - sock_to_cstr(sockbuf1, &sender), - sock_to_cstr(sockbuf2, orig_sender), - (unsigned int)eee->sup_attempts ); + traceEvent(TRACE_NORMAL, "Rx REGISTER_SUPER_ACK myMAC=%s [%s] (external %s). Attempts %u", + macaddr_str(mac_buf1, ra.edgeMac), + sock_to_cstr(sockbuf1, &sender), + sock_to_cstr(sockbuf2, orig_sender), + (unsigned int)eee->sup_attempts); - if ( 0 == memcmp( ra.cookie, eee->last_cookie, N2N_COOKIE_SIZE ) ) + if(0 == memcmp(ra.cookie, eee->last_cookie, N2N_COOKIE_SIZE)) { - if ( ra.num_sn > 0 ) + if(ra.num_sn > 0) { - traceEvent(TRACE_NORMAL, "Rx REGISTER_SUPER_ACK backup supernode at %s", - sock_to_cstr(sockbuf1, &(ra.sn_bak) ) ); + traceEvent(TRACE_NORMAL, "Rx REGISTER_SUPER_ACK backup supernode at %s", + sock_to_cstr(sockbuf1, &(ra.sn_bak))); } - eee->last_sup = now; - eee->sn_wait=0; - eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; /* refresh because we got a response */ + eee->last_sup = now; + eee->sn_wait=0; + eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; /* refresh because we got a response */ - /* REVISIT: store sn_back */ - eee->register_lifetime = ra.lifetime; - eee->register_lifetime = MAX( eee->register_lifetime, REGISTER_SUPER_INTERVAL_MIN ); - eee->register_lifetime = MIN( eee->register_lifetime, REGISTER_SUPER_INTERVAL_MAX ); + /* REVISIT: store sn_back */ + eee->register_lifetime = ra.lifetime; + eee->register_lifetime = MAX(eee->register_lifetime, REGISTER_SUPER_INTERVAL_MIN); + eee->register_lifetime = MIN(eee->register_lifetime, REGISTER_SUPER_INTERVAL_MAX); } - else + else { - traceEvent( TRACE_WARNING, "Rx REGISTER_SUPER_ACK with wrong or old cookie." ); + traceEvent(TRACE_WARNING, "Rx REGISTER_SUPER_ACK with wrong or old cookie."); } } - else + else { - traceEvent( TRACE_WARNING, "Rx REGISTER_SUPER_ACK with no outstanding REGISTER_SUPER." ); + traceEvent(TRACE_WARNING, "Rx REGISTER_SUPER_ACK with no outstanding REGISTER_SUPER."); } } - else + else { - /* Not a known message type */ - traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored", (signed int)msg_type); - return; + /* Not a known message type */ + traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored", (signed int)msg_type); + return; } } /* if (community match) */ - else + else { - traceEvent(TRACE_WARNING, "Received packet with invalid community"); + traceEvent(TRACE_WARNING, "Received packet with invalid community"); } } @@ -1768,16 +1768,16 @@ static void readFromIPSocket( n2n_edge_t * eee ) #ifdef WIN32 -static DWORD tunReadThread(LPVOID lpArg ) +static DWORD tunReadThread(LPVOID lpArg) { - n2n_edge_t *eee = (n2n_edge_t*)lpArg; + n2n_edge_t *eee = (n2n_edge_t*)lpArg; - while(1) + while(1) { - readFromTAPSocket(eee); + readFromTAPSocket(eee); } - return((DWORD)NULL); + return((DWORD)NULL); } @@ -1785,15 +1785,15 @@ static DWORD tunReadThread(LPVOID lpArg ) * file descriptors. */ static void startTunReadThread(n2n_edge_t *eee) { - HANDLE hThread; - DWORD dwThreadId; + HANDLE hThread; + DWORD dwThreadId; - hThread = CreateThread(NULL, /* security attributes */ - 0, /* use default stack size */ - (LPTHREAD_START_ROUTINE)tunReadThread, /* thread function */ - (void*)eee, /* argument to thread function */ - 0, /* thread creation flags */ - &dwThreadId); /* thread id out */ + hThread = CreateThread(NULL, /* security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE)tunReadThread, /* thread function */ + (void*)eee, /* argument to thread function */ + 0, /* thread creation flags */ + &dwThreadId); /* thread id out */ } #endif @@ -1806,59 +1806,59 @@ static void startTunReadThread(n2n_edge_t *eee) */ static void supernode2addr(n2n_sock_t * sn, const n2n_sn_name_t addrIn) { - n2n_sn_name_t addr; - const char *supernode_host; + n2n_sn_name_t addr; + const char *supernode_host; - memcpy( addr, addrIn, N2N_EDGE_SN_HOST_SIZE ); + memcpy(addr, addrIn, N2N_EDGE_SN_HOST_SIZE); - supernode_host = strtok(addr, ":"); + supernode_host = strtok(addr, ":"); - if(supernode_host) + if(supernode_host) { - in_addr_t sn_addr; - char *supernode_port = strtok(NULL, ":"); - const struct addrinfo aihints = {0, PF_INET, 0, 0, 0, NULL, NULL, NULL}; - struct addrinfo * ainfo = NULL; - int nameerr; + in_addr_t sn_addr; + char *supernode_port = strtok(NULL, ":"); + const struct addrinfo aihints = {0, PF_INET, 0, 0, 0, NULL, NULL, NULL}; + struct addrinfo * ainfo = NULL; + int nameerr; - if ( supernode_port ) - sn->port = atoi(supernode_port); - else - traceEvent(TRACE_WARNING, "Bad supernode parameter (-l ) %s %s:%s", - addr, supernode_host, supernode_port); + if(supernode_port) + sn->port = atoi(supernode_port); + else + traceEvent(TRACE_WARNING, "Bad supernode parameter (-l ) %s %s:%s", + 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. */ - if ( ainfo && (PF_INET == ainfo->ai_family) ) + /* ainfo s the head of a linked list if non-NULL. */ + 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 + else { - /* Should only return IPv4 addresses due to aihints. */ - traceEvent(TRACE_WARNING, "Failed to resolve supernode IPv4 address for %s", supernode_host); + /* Should only return IPv4 addresses due to aihints. */ + traceEvent(TRACE_WARNING, "Failed to resolve supernode IPv4 address for %s", supernode_host); } - freeaddrinfo(ainfo); /* free everything allocated by getaddrinfo(). */ - ainfo = NULL; + freeaddrinfo(ainfo); /* free everything allocated by getaddrinfo(). */ + ainfo = NULL; } else { - traceEvent(TRACE_WARNING, "Failed to resolve supernode host %s, assuming numeric", supernode_host); - sn_addr = inet_addr(supernode_host); /* uint32_t */ - memcpy( sn->addr.v4, &(sn_addr), IPV4_SIZE ); - sn->family=AF_INET; - } + traceEvent(TRACE_WARNING, "Failed to resolve supernode host %s, assuming numeric", supernode_host); + sn_addr = inet_addr(supernode_host); /* uint32_t */ + memcpy(sn->addr.v4, &(sn_addr), IPV4_SIZE); + sn->family=AF_INET; + } } else - traceEvent(TRACE_WARNING, "Wrong supernode parameter (-l )"); + traceEvent(TRACE_WARNING, "Wrong supernode parameter (-l )"); } /* ***************************************************** */ @@ -1880,533 +1880,577 @@ static void supernode2addr(n2n_sock_t * sn, const n2n_sn_name_t addrIn) * * return 0 on success and -1 on error */ -static int scan_address( char * ip_addr, size_t addr_size, - char * ip_mode, size_t mode_size, - const char * s ) +static int scan_address(char * ip_addr, size_t addr_size, + char * ip_mode, size_t mode_size, + const char * s) { - int retval = -1; - char * p; + int retval = -1; + char * p; - if ( ( NULL == s ) || ( NULL == ip_addr) ) + if((NULL == s) || (NULL == ip_addr)) { - return -1; + return -1; } - memset(ip_addr, 0, addr_size); + memset(ip_addr, 0, addr_size); - p = strpbrk(s, ":"); + p = strpbrk(s, ":"); - if ( p ) + if(p) { - /* colon is present */ - if ( ip_mode ) + /* colon is present */ + if(ip_mode) { - size_t end=0; + size_t end=0; - memset(ip_mode, 0, mode_size); - end = MIN( p-s, (ssize_t)(mode_size-1) ); /* ensure NULL term */ - strncpy( ip_mode, s, end ); - strncpy( ip_addr, p+1, addr_size-1 ); /* ensure NULL term */ - retval = 0; + memset(ip_mode, 0, mode_size); + end = MIN(p-s, (ssize_t)(mode_size-1)); /* ensure NULL term */ + strncpy(ip_mode, s, end); + strncpy(ip_addr, p+1, addr_size-1); /* ensure NULL term */ + retval = 0; } } - else + else { - /* colon is not present */ - strncpy( ip_addr, s, addr_size ); + /* colon is not present */ + strncpy(ip_addr, s, addr_size); } - return retval; + return retval; } -static int run_loop(n2n_edge_t * eee ); +static int run_loop(n2n_edge_t * eee); #define N2N_NETMASK_STR_SIZE 16 /* dotted decimal 12 numbers + 3 dots */ #define N2N_MACNAMSIZ 18 /* AA:BB:CC:DD:EE:FF + NULL*/ #define N2N_IF_MODE_SIZE 16 /* static | dhcp */ +/* *************************************************** */ + +void daemonize() { +#ifndef WIN32 + int childpid; + + traceEvent(TRACE_NORMAL, "Parent process is exiting (this is normal)"); + + signal(SIGPIPE, SIG_IGN); + signal(SIGHUP, SIG_IGN); + signal(SIGCHLD, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + + if((childpid = fork()) < 0) + traceEvent(TRACE_ERROR, "Occurred while daemonizing (errno=%d)", + errno); + else { + if(!childpid) { /* child */ + int rc; + + //traceEvent(TRACE_NORMAL, "Bye bye: I'm becoming a daemon..."); + rc = chdir("/"); + if(rc != 0) + traceEvent(TRACE_ERROR, "Error while moving to / directory"); + + setsid(); /* detach from the terminal */ + + fclose(stdin); + fclose(stdout); + /* fclose(stderr); */ + + /* + * clear any inherited file mode creation mask + */ + //umask(0); + + /* + * Use line buffered stdout + */ + /* setlinebuf (stdout); */ + setvbuf(stdout, (char *)NULL, _IOLBF, 0); + } else /* father */ + exit(0); + } +#endif +} + +/* *************************************************** */ + /** Entry point to program from kernel. */ int main(int argc, char* argv[]) { - int opt; - int local_port = 0 /* any port */; - int mgmt_port = N2N_EDGE_MGMT_PORT; /* 5644 by default */ - char tuntap_dev_name[N2N_IFNAMSIZ] = "edge0"; - char ip_mode[N2N_IF_MODE_SIZE]="static"; - char ip_addr[N2N_NETMASK_STR_SIZE] = ""; - char netmask[N2N_NETMASK_STR_SIZE]="255.255.255.0"; - int mtu = DEFAULT_MTU; - int got_s = 0; + int opt; + int local_port = 0 /* any port */; + int mgmt_port = N2N_EDGE_MGMT_PORT; /* 5644 by default */ + char tuntap_dev_name[N2N_IFNAMSIZ] = "edge0"; + char ip_mode[N2N_IF_MODE_SIZE]="static"; + char ip_addr[N2N_NETMASK_STR_SIZE] = ""; + char netmask[N2N_NETMASK_STR_SIZE]="255.255.255.0"; + int mtu = DEFAULT_MTU; + int got_s = 0; #ifndef WIN32 - uid_t userid=0; /* root is the only guaranteed ID */ - gid_t groupid=0; /* root is the only guaranteed ID */ + uid_t userid=0; /* root is the only guaranteed ID */ + gid_t groupid=0; /* root is the only guaranteed ID */ #endif - char device_mac[N2N_MACNAMSIZ]=""; - char * encrypt_key=NULL; + char device_mac[N2N_MACNAMSIZ]=""; + char * encrypt_key=NULL; - int i, effectiveargc=0; - char ** effectiveargv=NULL; - char * linebuffer = NULL; + int i, effectiveargc=0; + char ** effectiveargv=NULL; + char * linebuffer = NULL; - n2n_edge_t eee; /* single instance for this program */ + n2n_edge_t eee; /* single instance for this program */ - if (-1 == edge_init(&eee) ) + if (-1 == edge_init(&eee)) { - traceEvent( TRACE_ERROR, "Failed in edge_init" ); - exit(1); + traceEvent(TRACE_ERROR, "Failed in edge_init"); + exit(1); } - if( getenv( "N2N_KEY" )) + if(getenv("N2N_KEY")) { - encrypt_key = strdup( getenv( "N2N_KEY" )); + encrypt_key = strdup(getenv("N2N_KEY")); } #ifdef WIN32 - tuntap_dev_name[0] = '\0'; + tuntap_dev_name[0] = '\0'; #endif - memset(&(eee.supernode), 0, sizeof(eee.supernode)); - eee.supernode.family = AF_INET; + memset(&(eee.supernode), 0, sizeof(eee.supernode)); + eee.supernode.family = AF_INET; - linebuffer = (char *)malloc(MAX_CMDLINE_BUFFER_LENGTH); - if (!linebuffer) + linebuffer = (char *)malloc(MAX_CMDLINE_BUFFER_LENGTH); + if (!linebuffer) { - traceEvent( TRACE_ERROR, "Unable to allocate memory"); - exit(1); + traceEvent(TRACE_ERROR, "Unable to allocate memory"); + exit(1); } - snprintf(linebuffer, MAX_CMDLINE_BUFFER_LENGTH, "%s",argv[0]); + snprintf(linebuffer, MAX_CMDLINE_BUFFER_LENGTH, "%s",argv[0]); #ifdef WIN32 - for(i=0; i < (int)strlen(linebuffer); i++) - if(linebuffer[i] == '\\') linebuffer[i] = '/'; + for(i=0; i < (int)strlen(linebuffer); i++) + if(linebuffer[i] == '\\') linebuffer[i] = '/'; #endif - for(i=1;i 0 ) - { + { + if (strlen(eee.keyschedule) > 0) + { fprintf(stderr, "Error: -K and -k options are mutually exclusive.\n"); exit(1); - } else { - traceEvent(TRACE_DEBUG, "encrypt_key = '%s'\n", encrypt_key); - encrypt_key = strdup(optarg); + } else { + traceEvent(TRACE_DEBUG, "encrypt_key = '%s'\n", encrypt_key); + encrypt_key = strdup(optarg); } break; - } + } case 'r': /* enable packet routing across n2n endpoints */ - { + { eee.allow_routing = 1; break; - } + } case 'l': /* supernode-list */ - { - if ( eee.sn_num < N2N_EDGE_NUM_SUPERNODES ) - { - strncpy( (eee.sn_ip_array[eee.sn_num]), optarg, N2N_EDGE_SN_HOST_SIZE); - traceEvent(TRACE_DEBUG, "Adding supernode[%u] = %s\n", (unsigned int)eee.sn_num, (eee.sn_ip_array[eee.sn_num]) ); + { + if(eee.sn_num < N2N_EDGE_NUM_SUPERNODES) + { + strncpy((eee.sn_ip_array[eee.sn_num]), optarg, N2N_EDGE_SN_HOST_SIZE); + traceEvent(TRACE_DEBUG, "Adding supernode[%u] = %s\n", (unsigned int)eee.sn_num, (eee.sn_ip_array[eee.sn_num])); ++eee.sn_num; - } + } else - { - fprintf(stderr, "Too many supernodes!\n" ); + { + fprintf(stderr, "Too many supernodes!\n"); exit(1); - } + } break; - } + } #if defined(N2N_CAN_NAME_IFACE) case 'd': /* TUNTAP name */ - { + { strncpy(tuntap_dev_name, optarg, N2N_IFNAMSIZ); break; - } + } #endif case 'b': - { + { eee.re_resolve_supernode_ip = 1; break; - } + } case 'p': - { + { local_port = atoi(optarg); break; - } + } case 't': - { + { mgmt_port = atoi(optarg); break; - } + } case 's': /* Subnet Mask */ - { + { if (0 != got_s) - { + { traceEvent(TRACE_WARNING, "Multiple subnet masks supplied."); - } + } strncpy(netmask, optarg, N2N_NETMASK_STR_SIZE); got_s = 1; break; - } + } case 'h': /* help */ - { + { help(); break; - } + } case 'v': /* verbose */ - { + { ++traceLevel; /* do 2 -v flags to increase verbosity to DEBUG level*/ break; - } + } } /* end switch */ } -#ifdef N2N_HAVE_DAEMON - if ( eee.daemon ) +#ifndef WIN32 + if(eee.daemon) { - useSyslog=1; /* traceEvent output now goes to syslog. */ - if ( -1 == daemon( 0, 0 ) ) - { - traceEvent( TRACE_ERROR, "Failed to become daemon." ); - exit(-5); - } + useSyslog = 1; /* traceEvent output now goes to syslog. */ + daemonize(); } -#endif /* #ifdef N2N_HAVE_DAEMON */ +#endif /* #ifndef WIN32 */ - traceEvent( TRACE_NORMAL, "Starting n2n edge %s %s", n2n_sw_version, n2n_sw_buildDate ); + traceEvent(TRACE_NORMAL, "Starting n2n edge %s %s", n2n_sw_version, n2n_sw_buildDate); - for (i=0; i< N2N_EDGE_NUM_SUPERNODES; ++i ) + for (i=0; i< N2N_EDGE_NUM_SUPERNODES; ++i) { - traceEvent( TRACE_NORMAL, "supernode %u => %s\n", i, (eee.sn_ip_array[i]) ); + traceEvent(TRACE_NORMAL, "supernode %u => %s\n", i, (eee.sn_ip_array[i])); } - supernode2addr( &(eee.supernode), eee.sn_ip_array[eee.sn_idx] ); + supernode2addr(&(eee.supernode), eee.sn_ip_array[eee.sn_idx]); - for ( i=0; i 0) - traceEvent(TRACE_NORMAL, "Binding to local port %d", (signed int)local_port); - - if ( encrypt_key ) { - if(edge_init_twofish( &eee, (uint8_t *)(encrypt_key), strlen(encrypt_key) ) < 0) { - fprintf(stderr, "Error: twofish setup failed.\n" ); - return(-1); - } - } else if ( strlen(eee.keyschedule) > 0 ) { - if (edge_init_keyschedule( &eee ) != 0 ) { - fprintf(stderr, "Error: keyschedule setup failed.\n" ); - return(-1); - } + if(local_port > 0) + traceEvent(TRACE_NORMAL, "Binding to local port %d", (signed int)local_port); + if(encrypt_key) { + if(edge_init_twofish(&eee, (uint8_t *)(encrypt_key), strlen(encrypt_key)) < 0) { + fprintf(stderr, "Error: twofish setup failed.\n"); + return(-1); } - /* else run in NULL mode */ + } else if(strlen(eee.keyschedule) > 0) { + if (edge_init_keyschedule(&eee) != 0) { + fprintf(stderr, "Error: keyschedule setup failed.\n"); + return(-1); + } + + } + /* else run in NULL mode */ - eee.udp_sock = open_socket(local_port, 1 /*bind ANY*/ ); - if(eee.udp_sock < 0) + eee.udp_sock = open_socket(local_port, 1 /*bind ANY*/); + if(eee.udp_sock < 0) { - traceEvent( TRACE_ERROR, "Failed to bind main UDP port %u", (signed int)local_port ); - return(-1); + traceEvent(TRACE_ERROR, "Failed to bind main UDP port %u", (signed int)local_port); + return(-1); } - eee.udp_mgmt_sock = open_socket(mgmt_port, 0 /* bind LOOPBACK*/ ); + eee.udp_mgmt_sock = open_socket(mgmt_port, 0 /* bind LOOPBACK*/); - if(eee.udp_mgmt_sock < 0) + if(eee.udp_mgmt_sock < 0) { - traceEvent( TRACE_ERROR, "Failed to bind management UDP port %u", (unsigned int)N2N_EDGE_MGMT_PORT ); - return(-1); + traceEvent(TRACE_ERROR, "Failed to bind management UDP port %u", (unsigned int)N2N_EDGE_MGMT_PORT); + return(-1); } - traceEvent(TRACE_NORMAL, "edge started"); + traceEvent(TRACE_NORMAL, "edge started"); - update_supernode_reg(&eee, time(NULL) ); + update_supernode_reg(&eee, time(NULL)); - return run_loop(&eee); + return run_loop(&eee); } -static int run_loop(n2n_edge_t * eee ) +static int run_loop(n2n_edge_t * eee) { - int keep_running=1; - size_t numPurged; - time_t lastIfaceCheck=0; - time_t lastTransop=0; + int keep_running=1; + size_t numPurged; + time_t lastIfaceCheck=0; + time_t lastTransop=0; #ifdef WIN32 - startTunReadThread(eee); + startTunReadThread(eee); #endif - /* Main loop - * - * select() is used to wait for input on either the TAP fd or the UDP/TCP - * socket. When input is present the data is read and processed by either - * readFromIPSocket() or readFromTAPSocket() - */ + /* Main loop + * + * select() is used to wait for input on either the TAP fd or the UDP/TCP + * socket. When input is present the data is read and processed by either + * readFromIPSocket() or readFromTAPSocket() + */ - while(keep_running) + while(keep_running) { - int rc, max_sock = 0; - fd_set socket_mask; - struct timeval wait_time; - time_t nowTime; + int rc, max_sock = 0; + fd_set socket_mask; + struct timeval wait_time; + time_t nowTime; - FD_ZERO(&socket_mask); - FD_SET(eee->udp_sock, &socket_mask); - FD_SET(eee->udp_mgmt_sock, &socket_mask); - max_sock = max( eee->udp_sock, eee->udp_mgmt_sock ); + FD_ZERO(&socket_mask); + FD_SET(eee->udp_sock, &socket_mask); + FD_SET(eee->udp_mgmt_sock, &socket_mask); + max_sock = max(eee->udp_sock, eee->udp_mgmt_sock); #ifndef WIN32 - FD_SET(eee->device.fd, &socket_mask); - max_sock = max( max_sock, eee->device.fd ); + FD_SET(eee->device.fd, &socket_mask); + max_sock = max(max_sock, eee->device.fd); #endif - wait_time.tv_sec = SOCKET_TIMEOUT_INTERVAL_SECS; wait_time.tv_usec = 0; + wait_time.tv_sec = SOCKET_TIMEOUT_INTERVAL_SECS; wait_time.tv_usec = 0; - rc = select(max_sock+1, &socket_mask, NULL, NULL, &wait_time); - nowTime=time(NULL); + rc = select(max_sock+1, &socket_mask, NULL, NULL, &wait_time); + nowTime=time(NULL); - /* Make sure ciphers are updated before the packet is treated. */ - if ( ( nowTime - lastTransop ) > TRANSOP_TICK_INTERVAL ) + /* Make sure ciphers are updated before the packet is treated. */ + if((nowTime - lastTransop) > TRANSOP_TICK_INTERVAL) { - lastTransop = nowTime; + lastTransop = nowTime; - n2n_tick_transop( eee, nowTime ); + n2n_tick_transop(eee, nowTime); } - if(rc > 0) + if(rc > 0) { - /* Any or all of the FDs could have input; check them all. */ + /* Any or all of the FDs could have input; check them all. */ - if(FD_ISSET(eee->udp_sock, &socket_mask)) + if(FD_ISSET(eee->udp_sock, &socket_mask)) { - /* Read a cooked socket from the internet socket. Writes on the TAP - * socket. */ - readFromIPSocket(eee); + /* Read a cooked socket from the internet socket. Writes on the TAP + * socket. */ + readFromIPSocket(eee); } - if(FD_ISSET(eee->udp_mgmt_sock, &socket_mask)) + if(FD_ISSET(eee->udp_mgmt_sock, &socket_mask)) { - /* Read a cooked socket from the internet socket. Writes on the TAP - * socket. */ - readFromMgmtSocket(eee, &keep_running); + /* Read a cooked socket from the internet socket. Writes on the TAP + * socket. */ + readFromMgmtSocket(eee, &keep_running); } #ifndef WIN32 - if(FD_ISSET(eee->device.fd, &socket_mask)) + if(FD_ISSET(eee->device.fd, &socket_mask)) { - /* Read an ethernet frame from the TAP socket. Write on the IP - * socket. */ - readFromTAPSocket(eee); + /* Read an ethernet frame from the TAP socket. Write on the IP + * socket. */ + readFromTAPSocket(eee); } #endif } - /* Finished processing select data. */ + /* Finished processing select data. */ - update_supernode_reg(eee, nowTime); + update_supernode_reg(eee, nowTime); - numPurged = purge_expired_registrations( &(eee->known_peers) ); - numPurged += purge_expired_registrations( &(eee->pending_peers) ); - if ( numPurged > 0 ) + numPurged = purge_expired_registrations(&(eee->known_peers)); + numPurged += purge_expired_registrations(&(eee->pending_peers)); + if(numPurged > 0) { - traceEvent( TRACE_NORMAL, "Peer removed: pending=%u, operational=%u", - (unsigned int)peer_list_size( eee->pending_peers ), - (unsigned int)peer_list_size( eee->known_peers ) ); + traceEvent(TRACE_NORMAL, "Peer removed: pending=%u, operational=%u", + (unsigned int)peer_list_size(eee->pending_peers), + (unsigned int)peer_list_size(eee->known_peers)); } - if ( eee->dyn_ip_mode && - (( nowTime - lastIfaceCheck ) > IFACE_UPDATE_INTERVAL ) ) + if(eee->dyn_ip_mode && + ((nowTime - lastIfaceCheck) > IFACE_UPDATE_INTERVAL)) { - traceEvent(TRACE_NORMAL, "Re-checking dynamic IP address."); - tuntap_get_address( &(eee->device) ); - lastIfaceCheck = nowTime; + traceEvent(TRACE_NORMAL, "Re-checking dynamic IP address."); + tuntap_get_address(&(eee->device)); + lastIfaceCheck = nowTime; } } /* while */ - send_deregister( eee, &(eee->supernode)); + send_deregister(eee, &(eee->supernode)); - closesocket(eee->udp_sock); - tuntap_close(&(eee->device)); + closesocket(eee->udp_sock); + tuntap_close(&(eee->device)); - edge_deinit( eee ); + edge_deinit(eee); - return(0); + return(0); } diff --git a/n2n.c b/n2n.c index b2c84f9..b6bae37 100644 --- a/n2n.c +++ b/n2n.c @@ -1,11 +1,11 @@ /* - * (C) 2007-09 - Luca Deri + *(C) 2007-09 - Luca Deri * Richard Andrews * * 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 * 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, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -32,7 +32,7 @@ # define REGISTRATION_TIMEOUT 120 #else /* #if defined(DEBUG) */ # define PURGE_REGISTRATION_FREQUENCY 60 -# define REGISTRATION_TIMEOUT (60*20) +# define REGISTRATION_TIMEOUT (60*20) #endif /* #if defined(DEBUG) */ @@ -57,13 +57,13 @@ SOCKET open_socket(int local_port, int bind_any) { /* fcntl(sock_fd, F_SETFL, O_NONBLOCK); */ #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)); local_address.sin_family = AF_INET; local_address.sin_port = htons(local_port); 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)); return(-1); } @@ -89,11 +89,11 @@ void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...) { char *extra_msg = ""; time_t theTime = time(NULL); #ifdef WIN32 - int i; + int i; #endif /* 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 where it's parametrically off... */ @@ -101,7 +101,7 @@ void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...) { memset(buf, 0, sizeof(buf)); 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); va_end(va_ap); @@ -128,7 +128,7 @@ void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...) { } #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 [%11s:%4d] %s%s", theDate, &file[i], line, extra_msg, buf); printf("%s\n", out_buf); fflush(stdout); @@ -153,42 +153,42 @@ char* intoa(uint32_t /* host order */ addr, char* buf, uint16_t buf_len) { byteval = addr & 0xff; *--cp = byteval % 10 + '0'; byteval /= 10; - if (byteval > 0) { + if(byteval > 0) { *--cp = byteval % 10 + '0'; byteval /= 10; - if (byteval > 0) + if(byteval > 0) *--cp = byteval + '0'; } *--cp = '.'; addr >>= 8; - } while (--n > 0); + } while(--n > 0); /* Convert the string to lowercase */ - retStr = (char*)(cp+1); + retStr =(char*)(cp+1); return(retStr); } /* *********************************************** */ -char * macaddr_str( macstr_t buf, - const n2n_mac_t mac ) +char * macaddr_str(macstr_t buf, + const n2n_mac_t mac ) { - snprintf(buf, N2N_MACSTR_SIZE, "%02X:%02X:%02X:%02X:%02X:%02X", - mac[0] & 0xFF, mac[1] & 0xFF, mac[2] & 0xFF, - mac[3] & 0xFF, mac[4] & 0xFF, mac[5] & 0xFF); - return(buf); + 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); } /* *********************************************** */ uint8_t is_multi_broadcast(const uint8_t * dest_mac) { - int is_broadcast = ( memcmp(broadcast_addr, dest_mac, 6) == 0 ); - int is_multicast = ( memcmp(multicast_addr, dest_mac, 3) == 0 ); - int is_ipv6_multicast = ( memcmp(ipv6_multicast_addr, dest_mac, 2) == 0 ); + int is_broadcast =(memcmp(broadcast_addr, dest_mac, 6) == 0 ); + int is_multicast =(memcmp(multicast_addr, dest_mac, 3) == 0 ); + int is_ipv6_multicast =(memcmp(ipv6_multicast_addr, dest_mac, 2) == 0 ); - return is_broadcast || is_multicast || is_ipv6_multicast; + 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) { - size_t i; + size_t i; - if ( 0 == len ) { return; } + if(0 == len ) { return; } - for(i=0; i 0) && ((i % 16) == 0)) { printf("\n"); } - printf("%02X ", buf[i] & 0xFF); + if((i > 0) &&((i % 16) == 0)) { printf("\n"); } + 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. */ -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) { - if( 0 == memcmp(mac, list->mac_addr, 6) ) + if(0 == memcmp(mac, list->mac_addr, 6) ) { 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. * */ -size_t peer_list_size( const struct peer_info * list ) +size_t peer_list_size(const struct peer_info * list ) { size_t retval=0; - while ( list ) + while(list ) { ++retval; 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 * insertion. list takes ownership of new. */ -void peer_list_add( struct peer_info * * list, - struct peer_info * new ) +void peer_list_add(struct peer_info * * list, + struct peer_info * new ) { new->next = *list; 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; time_t now = time(NULL); 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"); - num_reg = purge_peer_list( peer_list, now-REGISTRATION_TIMEOUT ); + num_reg = purge_peer_list(peer_list, now-REGISTRATION_TIMEOUT ); last_purge = now; 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. */ -size_t purge_peer_list( struct peer_info ** peer_list, - time_t purge_before ) +size_t purge_peer_list(struct peer_info ** peer_list, + time_t purge_before ) { struct peer_info *scan; 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. */ -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 *prev; - size_t retval=0; + struct peer_info *scan; + struct peer_info *prev; + size_t retval=0; - scan = *peer_list; - prev = NULL; - while(scan != NULL) + scan = *peer_list; + prev = 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; - free(scan); - scan = next; + ++retval; + free(scan); + scan = next; } - return retval; + return retval; } -static uint8_t hex2byte( const char * s ) +static uint8_t hex2byte(const char * s ) { char tmp[3]; tmp[0]=s[0]; tmp[1]=s[1]; tmp[2]=0; /* NULL term */ - 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; @@ -400,7 +400,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); @@ -411,45 +411,49 @@ extern int str2mac( uint8_t * outmac /* 6 bytes */, const char * s ) return 0; /* ok */ } -extern char * sock_to_cstr( n2n_sock_str_t out, - const n2n_sock_t * sock ) +extern char * sock_to_cstr(n2n_sock_str_t out, + const n2n_sock_t * sock ) { - int r; + int r; - if ( NULL == out ) { return NULL; } - memset(out, 0, N2N_SOCKBUF_SIZE); + if(NULL == out ) { return NULL; } + memset(out, 0, N2N_SOCKBUF_SIZE); - if ( AF_INET6 == sock->family ) + if(AF_INET6 == sock->family ) { - /* INET6 not written yet */ - r = snprintf( out, N2N_SOCKBUF_SIZE, "XXXX:%hu", sock->port ); - return out; + /* INET6 not written yet */ + r = snprintf(out, N2N_SOCKBUF_SIZE, "XXXX:%hu", sock->port ); + return out; } - else + else { - const uint8_t * a = sock->addr.v4; - 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 ); - return out; + const uint8_t * a = sock->addr.v4; + r = snprintf(out, N2N_SOCKBUF_SIZE, "%hu.%hu.%hu.%hu:%hu", + (unsigned short)(a[0] & 0xff), + (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. */ -int sock_equal( const n2n_sock_t * a, - const n2n_sock_t * b ) +int sock_equal(const n2n_sock_t * a, + const n2n_sock_t * b ) { - if ( a->port != b->port ) { return 1; } - if ( a->family != b->family ) { return 1; } - switch (a->family) /* they are the same */ + if(a->port != b->port ) { return 1; } + if(a->family != b->family ) { return 1; } + switch(a->family) /* they are the same */ { case AF_INET: - if ( 0 != memcmp( a->addr.v4, b->addr.v4, IPV4_SIZE ) ) { return 1;}; - break; + if(0 != memcmp(a->addr.v4, b->addr.v4, IPV4_SIZE ) ) { return 1;}; + break; default: - if ( 0 != memcmp( a->addr.v6, b->addr.v6, IPV6_SIZE ) ) { return 1;}; - break; + if(0 != memcmp(a->addr.v6, b->addr.v6, IPV6_SIZE ) ) { return 1;}; + break; } - return 0; + return 0; } diff --git a/n2n.h b/n2n.h index 4801bf7..a004e7f 100644 --- a/n2n.h +++ b/n2n.h @@ -36,14 +36,7 @@ tunctl -u UID -t tunX */ -#if defined(__APPLE__) && defined(__MACH__) -#define _DARWIN_ -#endif - -/* Some capability defaults which can be reset for particular platforms. */ -#define N2N_HAVE_DAEMON 1 -#define N2N_HAVE_SETUID 1 /* #define N2N_CAN_NAME_IFACE */ /* Moved here to define _CRT_SECURE_NO_WARNINGS before all the including takes place */ @@ -99,11 +92,6 @@ struct ether_hdr typedef struct ether_hdr ether_hdr_t; -#ifdef __sun__ -#include /* MIN() and MAX() declared here */ -#undef N2N_HAVE_DAEMON -#endif /* #ifdef __sun__ */ - #include #include #include diff --git a/tuntap_linux.c b/tuntap_linux.c index 66b3dd8..ae535e1 100644 --- a/tuntap_linux.c +++ b/tuntap_linux.c @@ -30,8 +30,10 @@ static void read_mac(char *ifname, n2n_mac_t mac_addr) { _sock=socket(PF_INET, SOCK_DGRAM, 0); strcpy(ifr.ifr_name, ifname); res = ioctl(_sock,SIOCGIFHWADDR,&ifr); - if (res<0) { + + if(res < 0) { perror ("Get hw addr"); + traceEvent(TRACE_ERROR, "Unable to read interfce %s MAC", ifname); } else memcpy(mac_addr, ifr.ifr_ifru.ifru_hwaddr.sa_data, 6); diff --git a/tuntap_netbsd.c b/tuntap_netbsd.c index 011f7df..bca6e3e 100644 --- a/tuntap_netbsd.c +++ b/tuntap_netbsd.c @@ -39,7 +39,7 @@ int tuntap_open(tuntap_dev *device /* ignored */, char tap_device[N2N_NETBSD_TAPDEVICE_SIZE]; struct ifreq req; - if (dev) { + if(dev) { snprintf(tap_device, sizeof(tap_device), "/dev/%s", dev); device->fd = open(tap_device, O_RDWR); snprintf(tap_device, sizeof(tap_device), "%s", dev); @@ -47,7 +47,7 @@ int tuntap_open(tuntap_dev *device /* ignored */, else { device->fd = open("/dev/tap", O_RDWR); if(device->fd >= 0) { - if (ioctl(device->fd, TAPGIFNAME, &req) == -1) { + if(ioctl(device->fd, TAPGIFNAME, &req) == -1) { traceEvent(TRACE_ERROR, "Unable to obtain name of tap device (%s)", strerror(errno)); close(device->fd); return(-1); @@ -62,46 +62,45 @@ int tuntap_open(tuntap_dev *device /* ignored */, traceEvent(TRACE_ERROR, "Unable to open tap device (%s)", strerror(errno)); return(-1); } else { - char buf[256]; + char cmd[256]; FILE *fd; traceEvent(TRACE_NORMAL, "Succesfully open %s", tap_device); device->ip_addr = inet_addr(device_ip); - if ( device_mac && device_mac[0] != '\0' ) - { + if( device_mac && device_mac[0] != '\0') { /* Set the hw address before bringing the if up. */ - snprintf(buf, sizeof(buf), "ifconfig %s link %s active", + snprintf(cmd, sizeof(cmd), "ifconfig %s link %s active", tap_device, device_mac); - system(buf); + system(cmd); } - snprintf(buf, sizeof(buf), "ifconfig %s %s netmask %s mtu %d up", + snprintf(cmd, sizeof(cmd), "ifconfig %s %s netmask %s mtu %d up", tap_device, device_ip, device_mask, mtu); - system(buf); + system(cmd); traceEvent(TRACE_NORMAL, "Interface %s up and running (%s/%s)", tap_device, device_ip, device_mask); - /* Read MAC address */ + /* Read MAC address */ + snprintf(cmd, sizeof(cmd), "ifconfig %s |grep address|cut -c 11-28", tap_device); + /* traceEvent(TRACE_INFO, "%s", cmd); */ - snprintf(buf, sizeof(buf), "ifconfig %s |grep address|cut -c 11-28", tap_device); - /* traceEvent(TRACE_INFO, "%s", buf); */ - - fd = popen(buf, "r"); + fd = popen(cmd, "r"); if(fd < 0) { tun_close(device); return(-1); } else { int a, b, c, d, e, f; - + char buf[256]; + buf[0] = 0; fgets(buf, sizeof(buf), fd); pclose(fd); if(buf[0] == '\0') { - traceEvent(TRACE_ERROR, "Unable to read %s interface MAC address", tap_device); + traceEvent(TRACE_ERROR, "Unable to read %s interface MAC address [%s]", tap_device, cmd); exit(0); } diff --git a/tuntap_osx.c b/tuntap_osx.c index 6b37b1f..c6df8e4 100644 --- a/tuntap_osx.c +++ b/tuntap_osx.c @@ -17,7 +17,7 @@ #include "n2n.h" -#ifdef _DARWIN_ +#ifdef __APPLE__ void tun_close(tuntap_dev *device); @@ -77,7 +77,7 @@ int tuntap_open(tuntap_dev *device /* ignored */, fd = popen(buf, "r"); if(fd < 0) { - tun_close(device); + tuntap_close(device); return(-1); } else { int a, b, c, d, e, f; @@ -129,4 +129,4 @@ void tuntap_get_address(struct tuntap_dev *tuntap) { } -#endif /* _DARWIN_ */ +#endif /* __APPLE__ */ From 7b07636281bec9dfc0dd8e965e456510a36b0631 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Wed, 6 Jun 2018 09:57:31 +0200 Subject: [PATCH 05/10] Refreshed copyright and added contributors list --- README.md | 2 +- benchmark.c | 18 ++++++++++++++++++ contributors.txt | 8 ++++++++ edge.c | 9 +-------- n2n.c | 18 ++++++------------ n2n.h | 11 +++-------- n2n_keyfile.c | 19 ++++++++++++++++--- n2n_keyfile.h | 18 +++++++++++++++++- n2n_transforms.h | 18 +++++++++++++++++- n2n_wire.h | 19 +++++++++++++++---- sn.c | 22 ++++++++++++++++------ test.c | 18 ++++++++++++++++++ transform_aes.c | 19 ++++++++++++++++--- transform_null.c | 18 +++++++++++++++++- transform_tf.c | 18 +++++++++++++++++- tuntap_freebsd.c | 5 +++-- tuntap_linux.c | 9 +++++---- tuntap_netbsd.c | 6 +++--- tuntap_osx.c | 5 +++-- wire.c | 18 +++++++++++++++++- 20 files changed, 217 insertions(+), 61 deletions(-) create mode 100644 contributors.txt diff --git a/README.md b/README.md index a057b52..4e4a58c 100644 --- a/README.md +++ b/README.md @@ -116,4 +116,4 @@ NULL (-O3) 10659 (C) 2007-2010 - Luca Deri and Richard Andrews -(C) 2016 - ntop +(C) 2018 - ntop diff --git a/benchmark.c b/benchmark.c index f6802ce..a631c61 100644 --- a/benchmark.c +++ b/benchmark.c @@ -1,3 +1,21 @@ +/* + * (C) 2007-18 - ntop.org and contributors + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see + * + */ + #include "n2n_wire.h" #include "n2n_transforms.h" #include "n2n.h" diff --git a/contributors.txt b/contributors.txt new file mode 100644 index 0000000..0b19fb6 --- /dev/null +++ b/contributors.txt @@ -0,0 +1,8 @@ +Code contributions courtesy of: + * Richard Andrews + * Don Bindner + * Sylwester Sosnowski + * Wilfried "Wonka" Klaebe + * Lukasz Taczuk + * Alaric Snell-Pym + * Babak Farrokhi [FreeBSD port] diff --git a/edge.c b/edge.c index 7a4d563..c8f2813 100644 --- a/edge.c +++ b/edge.c @@ -1,6 +1,5 @@ /** - * (C) 2007-09 - Luca Deri - * Richard Andrews + * (C) 2007-18 - ntop.org and contributors * * 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 @@ -15,12 +14,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not see see * - * Code contributions courtesy of: - * Don Bindner - * Sylwester Sosnowski - * Wilfried "Wonka" Klaebe - * Lukasz Taczuk - * */ #include "n2n.h" diff --git a/n2n.c b/n2n.c index b6bae37..ece937d 100644 --- a/n2n.c +++ b/n2n.c @@ -1,11 +1,10 @@ -/* - *(C) 2007-09 - Luca Deri - * Richard Andrews +/** + * (C) 2007-18 - ntop.org and contributors * * 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 * 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, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -13,11 +12,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, see - * - * Code contributions courtesy of: - * Massimo Torquati - * Matt Gilg + * along with this program; if not see see * */ @@ -235,12 +230,11 @@ 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-09 - http://www.ntop.org\n\n", + "Copyright 2007-18 - ntop.org and contributors\n\n", n2n_sw_version, n2n_sw_osName, n2n_sw_buildDate); } - - +/* *********************************************** */ /** Find the peer entry in list with mac_addr equal to mac. * diff --git a/n2n.h b/n2n.h index a004e7f..8f80720 100644 --- a/n2n.h +++ b/n2n.h @@ -1,6 +1,5 @@ -/* - * (C) 2007-09 - Luca Deri - * Richard Andrews +/** + * (C) 2007-18 - ntop.org and contributors * * 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 @@ -13,11 +12,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, see - * - * Code contributions courtesy of: - * Babak Farrokhi [FreeBSD port] - * Lukasz Taczuk + * along with this program; if not see see * */ diff --git a/n2n_keyfile.c b/n2n_keyfile.c index 56de3a1..eda6c83 100644 --- a/n2n_keyfile.c +++ b/n2n_keyfile.c @@ -1,6 +1,19 @@ -/* (c) 2009 Richard Andrews */ -/* Contributions from: - * - Jozef Kralik +/** + * (C) 2007-18 - ntop.org and contributors + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * */ #include "n2n.h" diff --git a/n2n_keyfile.h b/n2n_keyfile.h index 6068df1..05cdf60 100644 --- a/n2n_keyfile.h +++ b/n2n_keyfile.h @@ -1,4 +1,20 @@ -/* (c) 2009 Richard Andrews */ +/** + * (C) 2007-18 - ntop.org and contributors + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + */ /** Key files * diff --git a/n2n_transforms.h b/n2n_transforms.h index effbc50..6702dae 100644 --- a/n2n_transforms.h +++ b/n2n_transforms.h @@ -1,4 +1,20 @@ -/* (c) 2009 Richard Andrews */ +/** + * (C) 2007-18 - ntop.org and contributors + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + */ #if !defined(N2N_TRANSFORMS_H_) #define N2N_TRANSFORMS_H_ diff --git a/n2n_wire.h b/n2n_wire.h index 8a3dfdf..88fa0ea 100644 --- a/n2n_wire.h +++ b/n2n_wire.h @@ -1,8 +1,19 @@ -/* (c) 2009 Richard Andrews +/** + * (C) 2007-18 - ntop.org and contributors + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see * - * Contributions by: - * Luca Deri - * Lukasz Taczuk */ #if !defined( N2N_WIRE_H_ ) diff --git a/sn.c b/sn.c index 7df4729..9138a37 100644 --- a/sn.c +++ b/sn.c @@ -1,12 +1,22 @@ -/* Supernode for n2n-2.x */ - -/* (c) 2009 Richard Andrews +/** + * (C) 2007-18 - ntop.org and contributors + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see * - * Contributions by: - * Lukasz Taczuk - * Struan Bartlett */ +/* Supernode for n2n-2.x */ #include "n2n.h" diff --git a/test.c b/test.c index 97ec91b..ab89e45 100644 --- a/test.c +++ b/test.c @@ -1,3 +1,21 @@ +/** + * (C) 2007-18 - ntop.org and contributors + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + */ + #include "n2n.h" #include "n2n_keyfile.h" #include diff --git a/transform_aes.c b/transform_aes.c index a8c4969..718cb4e 100644 --- a/transform_aes.c +++ b/transform_aes.c @@ -1,6 +1,19 @@ -/* (c) 2009 Richard Andrews */ -/* Contributions from: - * - Jozef Kralik +/** + * (C) 2007-18 - ntop.org and contributors + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * */ #include "n2n.h" diff --git a/transform_null.c b/transform_null.c index b486989..78a7185 100644 --- a/transform_null.c +++ b/transform_null.c @@ -1,4 +1,20 @@ -/* (c) 2009 Richard Andrews */ +/** + * (C) 2007-18 - ntop.org and contributors + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + */ #include "n2n.h" #include "n2n_transforms.h" diff --git a/transform_tf.c b/transform_tf.c index 1ae5bc5..944a55a 100644 --- a/transform_tf.c +++ b/transform_tf.c @@ -1,4 +1,20 @@ -/* (c) 2009 Richard Andrews */ +/** + * (C) 2007-18 - ntop.org and contributors + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + */ #include "n2n.h" #include "n2n_transforms.h" diff --git a/tuntap_freebsd.c b/tuntap_freebsd.c index 7d9096a..fc06f74 100644 --- a/tuntap_freebsd.c +++ b/tuntap_freebsd.c @@ -1,5 +1,5 @@ -/* - * (C) 2007-09 - Luca Deri +/** + * (C) 2007-18 - ntop.org and contributors * * 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 @@ -13,6 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not see see + * */ #include "n2n.h" diff --git a/tuntap_linux.c b/tuntap_linux.c index ae535e1..27ce05c 100644 --- a/tuntap_linux.c +++ b/tuntap_linux.c @@ -1,5 +1,5 @@ -/* - * (C) 2007-09 - Luca Deri +/** + * (C) 2007-18 - ntop.org and contributors * * 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 @@ -12,8 +12,9 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, see -*/ + * along with this program; if not see see + * + */ #include "n2n.h" diff --git a/tuntap_netbsd.c b/tuntap_netbsd.c index bca6e3e..2d948d9 100644 --- a/tuntap_netbsd.c +++ b/tuntap_netbsd.c @@ -1,6 +1,5 @@ -/* - * (C) 2007-09 - Luca Deri - * (C) 2009 - Alaric Snell-Pym +/** + * (C) 2007-18 - ntop.org and contributors * * 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 @@ -14,6 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not see see + * */ #include "n2n.h" diff --git a/tuntap_osx.c b/tuntap_osx.c index c6df8e4..ee06ef8 100644 --- a/tuntap_osx.c +++ b/tuntap_osx.c @@ -1,5 +1,5 @@ -/* - * (C) 2007-09 - Luca Deri +/** + * (C) 2007-18 - ntop.org and contributors * * 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 @@ -13,6 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not see see + * */ #include "n2n.h" diff --git a/wire.c b/wire.c index 6490c9d..228b426 100644 --- a/wire.c +++ b/wire.c @@ -1,4 +1,20 @@ -/* (c) 2009 Richard Andrews */ +/** + * (C) 2007-18 - ntop.org and contributors + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + */ /** Routines for encoding and decoding n2n packets on the wire. * From 89a612a3aead3360d92c0ae9b3afaf2a141bee52 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Wed, 6 Jun 2018 09:58:58 +0200 Subject: [PATCH 06/10] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4e4a58c..c3cbc5d 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,6 @@ AES (-O3) 12532 TF (-O3) 14046 NULL (-O3) 10659 -(C) 2007-2010 - Luca Deri and Richard Andrews +----------------- -(C) 2018 - ntop +(C) 2007-18 - ntop.org and contributors From 1daf46275ef11c5011a5e94bc02267dea59ab690 Mon Sep 17 00:00:00 2001 From: Luca Date: Wed, 6 Jun 2018 18:37:24 +0200 Subject: [PATCH 07/10] Added instructions for using n2n on MacOS --- HACKING => doc/HACKING | 0 NEW_FEATURES.txt => doc/NEW_FEATURES.txt | 0 doc/n2n_on_MacOS.txt | 19 +++++++++++++++++++ 3 files changed, 19 insertions(+) rename HACKING => doc/HACKING (100%) rename NEW_FEATURES.txt => doc/NEW_FEATURES.txt (100%) create mode 100644 doc/n2n_on_MacOS.txt diff --git a/HACKING b/doc/HACKING similarity index 100% rename from HACKING rename to doc/HACKING diff --git a/NEW_FEATURES.txt b/doc/NEW_FEATURES.txt similarity index 100% rename from NEW_FEATURES.txt rename to doc/NEW_FEATURES.txt diff --git a/doc/n2n_on_MacOS.txt b/doc/n2n_on_MacOS.txt new file mode 100644 index 0000000..38a03bb --- /dev/null +++ b/doc/n2n_on_MacOS.txt @@ -0,0 +1,19 @@ + +Using n2n on MacOS +------------------ + +In order to use n2n on MacOS you need to first install support for the tap interface. +if you are a brew (https://brew.sh) user you can do it in a couple of steps + +- brew tap homebrew/cask +- brew cask install tuntap + +Note that in the latest OS versions (for instance MacOS High Sierra), you may need to +need to enable their kernel extension in + + System Preferences → Security & Privacy → General + +For more information refer to vendor documentation or the Apple Technical Note: + + https://developer.apple.com/library/content/technotes/tn2459/_index.html + From 41401a131f0ce9eea70bb7e90458adce39b5f998 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Thu, 7 Jun 2018 21:45:33 +0200 Subject: [PATCH 08/10] Minor code cleanup --- edge.c | 42 +++++++++------------- n2n.c | 96 +++++++++++++++++++++++++------------------------- tuntap_linux.c | 65 ++++++++++++++++++++-------------- 3 files changed, 103 insertions(+), 100 deletions(-) diff --git a/edge.c b/edge.c index c8f2813..d68b568 100644 --- a/edge.c +++ b/edge.c @@ -549,7 +549,7 @@ static void send_register(n2n_edge_t * eee, { uint8_t pktbuf[N2N_PKT_BUF_SIZE]; size_t idx; - ssize_t sent; + /* ssize_t sent; */ n2n_common_t cmn; n2n_REGISTER_t reg; n2n_sock_str_t sockbuf; @@ -572,19 +572,16 @@ static void send_register(n2n_edge_t * eee, traceEvent(TRACE_INFO, "send REGISTER %s", sock_to_cstr(sockbuf, remote_peer)); - - sent = sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer); - + /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer); } /** Send a REGISTER_SUPER packet to the current supernode. */ static void send_register_super(n2n_edge_t * eee, - const n2n_sock_t * supernode) -{ + const n2n_sock_t * supernode) { uint8_t pktbuf[N2N_PKT_BUF_SIZE]; size_t idx; - ssize_t sent; + /* ssize_t sent; */ n2n_common_t cmn; n2n_REGISTER_SUPER_t reg; n2n_sock_str_t sockbuf; @@ -614,19 +611,17 @@ static void send_register_super(n2n_edge_t * eee, sock_to_cstr(sockbuf, supernode)); - sent = sendto_sock(eee->udp_sock, pktbuf, idx, supernode); - + /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, supernode); } /** Send a REGISTER_ACK packet to a peer edge. */ static void send_register_ack(n2n_edge_t * eee, const n2n_sock_t * remote_peer, - const n2n_REGISTER_t * reg) -{ + const n2n_REGISTER_t * reg) { uint8_t pktbuf[N2N_PKT_BUF_SIZE]; size_t idx; - ssize_t sent; + /* ssize_t sent; */ n2n_common_t cmn; n2n_REGISTER_ACK_t ack; n2n_sock_str_t sockbuf; @@ -650,7 +645,7 @@ static void send_register_ack(n2n_edge_t * eee, sock_to_cstr(sockbuf, remote_peer)); - sent = sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer); + /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer); } @@ -1128,7 +1123,7 @@ static int send_PACKET(n2n_edge_t * eee, size_t pktlen) { int dest; - ssize_t s; + /*ssize_t s; */ n2n_sock_str_t sockbuf; n2n_sock_t destination; @@ -1137,17 +1132,13 @@ static int send_PACKET(n2n_edge_t * eee, dest = find_peer_destination(eee, dstMac, &destination); if(dest) - { - ++(eee->tx_p2p); - } + ++(eee->tx_p2p); else - { - ++(eee->tx_sup); - } + ++(eee->tx_sup); traceEvent(TRACE_INFO, "send_PACKET to %s", sock_to_cstr(sockbuf, &destination)); - s = sendto_sock(eee->udp_sock, pktbuf, pktlen, &destination); + /* s = */ sendto_sock(eee->udp_sock, pktbuf, pktlen, &destination); return 0; } @@ -1414,7 +1405,7 @@ static void readFromMgmtSocket(n2n_edge_t * eee, int * keep_running) { uint8_t udp_buf[N2N_PKT_BUF_SIZE]; /* Compete UDP packet */ ssize_t recvlen; - ssize_t sendlen; + /* ssize_t sendlen; */ struct sockaddr_in sender_sock; socklen_t i; size_t msg_len; @@ -1563,9 +1554,8 @@ static void readFromMgmtSocket(n2n_edge_t * eee, int * keep_running) traceEvent(TRACE_DEBUG, "mgmt status sending: %s", udp_buf); - sendlen = sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, - (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); - + /* sendlen = */ sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, + (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); } @@ -1920,7 +1910,7 @@ static int run_loop(n2n_edge_t * eee); /* *************************************************** */ -void daemonize() { +static void daemonize() { #ifndef WIN32 int childpid; diff --git a/n2n.c b/n2n.c index ece937d..d5c293c 100644 --- a/n2n.c +++ b/n2n.c @@ -167,7 +167,7 @@ char* intoa(uint32_t /* host order */ addr, char* buf, uint16_t buf_len) { /* *********************************************** */ 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, @@ -179,9 +179,9 @@ char * macaddr_str(macstr_t buf, uint8_t is_multi_broadcast(const uint8_t * dest_mac) { - int is_broadcast =(memcmp(broadcast_addr, dest_mac, 6) == 0 ); - int is_multicast =(memcmp(multicast_addr, dest_mac, 3) == 0 ); - int is_ipv6_multicast =(memcmp(ipv6_multicast_addr, dest_mac, 2) == 0 ); + int is_broadcast =(memcmp(broadcast_addr, dest_mac, 6) == 0); + int is_multicast =(memcmp(multicast_addr, dest_mac, 3) == 0); + int is_ipv6_multicast =(memcmp(ipv6_multicast_addr, dest_mac, 2) == 0); return is_broadcast || is_multicast || is_ipv6_multicast; @@ -214,7 +214,7 @@ void hexdump(const uint8_t * buf, size_t len) { size_t i; - if(0 == len ) { return; } + if(0 == len) { return; } for(i=0; imac_addr, 6) ) + if(0 == memcmp(mac, list->mac_addr, 6)) { return list; } @@ -260,11 +260,11 @@ struct peer_info * find_peer_by_mac(struct peer_info * list, const n2n_mac_t mac /** 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; - while(list ) + while(list) { ++retval; list = list->next; @@ -279,7 +279,7 @@ size_t peer_list_size(const struct peer_info * list ) * insertion. list takes ownership of new. */ void peer_list_add(struct peer_info * * list, - struct peer_info * new ) + struct peer_info * new) { new->next = *list; new->last_seen = time(NULL); @@ -287,7 +287,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; time_t now = time(NULL); size_t num_reg = 0; @@ -296,7 +296,7 @@ size_t purge_expired_registrations(struct peer_info ** peer_list ) { 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; traceEvent(TRACE_INFO, "Remove %ld registrations", num_reg); @@ -306,7 +306,7 @@ 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. */ 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 *prev; @@ -344,7 +344,7 @@ 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; struct peer_info *prev; @@ -373,17 +373,17 @@ size_t clear_peer_list(struct peer_info ** peer_list ) return retval; } -static uint8_t hex2byte(const char * s ) +static uint8_t hex2byte(const char * s) { char tmp[3]; tmp[0]=s[0]; tmp[1]=s[1]; tmp[2]=0; /* NULL term */ - 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; @@ -394,7 +394,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); @@ -406,45 +406,45 @@ 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 ) -{ - int r; - - if(NULL == out ) { return NULL; } + const n2n_sock_t * sock) { + if(NULL == out) { return NULL; } memset(out, 0, N2N_SOCKBUF_SIZE); - if(AF_INET6 == sock->family ) - { - /* INET6 not written yet */ - r = snprintf(out, N2N_SOCKBUF_SIZE, "XXXX:%hu", sock->port ); - return out; - } - else - { - const uint8_t * a = sock->addr.v4; - r = snprintf(out, N2N_SOCKBUF_SIZE, "%hu.%hu.%hu.%hu:%hu", - (unsigned short)(a[0] & 0xff), - (unsigned short)(a[1] & 0xff), - (unsigned short)(a[2] & 0xff), - (unsigned short)(a[3] & 0xff), - (unsigned short)sock->port ); - return out; - } + if(AF_INET6 == sock->family) { + /* INET6 not written yet */ + snprintf(out, N2N_SOCKBUF_SIZE, "XXXX:%hu", sock->port); + return out; + } else { + const uint8_t * a = sock->addr.v4; + + snprintf(out, N2N_SOCKBUF_SIZE, "%hu.%hu.%hu.%hu:%hu", + (unsigned short)(a[0] & 0xff), + (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. */ int sock_equal(const n2n_sock_t * a, - const n2n_sock_t * b ) -{ - if(a->port != b->port ) { return 1; } - if(a->family != b->family ) { return 1; } - switch(a->family) /* they are the same */ - { + const n2n_sock_t * b) { + if(a->port != b->port) { return 1; } + if(a->family != b->family) { return 1; } + + switch(a->family) { 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; + 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; } diff --git a/tuntap_linux.c b/tuntap_linux.c index 27ce05c..c98d208 100644 --- a/tuntap_linux.c +++ b/tuntap_linux.c @@ -20,6 +20,8 @@ #ifdef __linux__ +/* *************************************************** */ + static void read_mac(char *ifname, n2n_mac_t mac_addr) { int _sock, res; struct ifreq ifr; @@ -95,24 +97,24 @@ int tuntap_open(tuntap_dev *device, strncpy(device->dev_name, ifr.ifr_name, MIN(IFNAMSIZ, N2N_IFNAMSIZ) ); if ( device_mac && device_mac[0] != '\0' ) - { + { /* Set the hw address before bringing the if up. */ snprintf(buf, sizeof(buf), "/sbin/ifconfig %s hw ether %s", ifr.ifr_name, device_mac ); system(buf); traceEvent(TRACE_INFO, "Setting MAC: %s", buf); - } + } if ( 0 == strncmp( "dhcp", address_mode, 5 ) ) - { + { snprintf(buf, sizeof(buf), "/sbin/ifconfig %s %s mtu %d up", ifr.ifr_name, device_ip, mtu); - } + } else - { + { snprintf(buf, sizeof(buf), "/sbin/ifconfig %s %s netmask %s mtu %d up", ifr.ifr_name, device_ip, device_mask, mtu); - } + } system(buf); traceEvent(TRACE_INFO, "Bringing up: %s", buf); @@ -123,45 +125,56 @@ int tuntap_open(tuntap_dev *device, return(device->fd); } +/* *************************************************** */ + int tuntap_read(struct tuntap_dev *tuntap, unsigned char *buf, int len) { return(read(tuntap->fd, buf, len)); } +/* *************************************************** */ + int tuntap_write(struct tuntap_dev *tuntap, unsigned char *buf, int len) { return(write(tuntap->fd, buf, len)); } +/* *************************************************** */ + void tuntap_close(struct tuntap_dev *tuntap) { close(tuntap->fd); } +/* *************************************************** */ + /* Fill out the ip_addr value from the interface. Called to pick up dynamic * address changes. */ -void tuntap_get_address(struct tuntap_dev *tuntap) -{ - FILE * fp=NULL; - ssize_t nread=0; - char buf[N2N_LINUX_SYSTEMCMD_SIZE]; +void tuntap_get_address(struct tuntap_dev *tuntap) { + FILE * fp=NULL; + ssize_t nread=0; + char buf[N2N_LINUX_SYSTEMCMD_SIZE]; + + /* Would rather have a more direct way to get the inet address but a netlink + * socket is overkill and probably less portable than ifconfig and sed. */ - /* Would rather have a more direct way to get the inet address but a netlink - * socket is overkill and probably less portable than ifconfig and sed. */ + /* If the interface has no address (0.0.0.0) there will be no inet addr + * line and the returned string will be empty. */ + snprintf( buf, sizeof(buf), + "/sbin/ifconfig %s | /bin/sed -e '/inet addr:/!d' -e 's/^.*inet addr://' -e 's/ .*$//'", + tuntap->dev_name); + fp = popen(buf, "r"); - /* If the interface has no address (0.0.0.0) there will be no inet addr - * line and the returned string will be empty. */ - snprintf( buf, sizeof(buf), "/sbin/ifconfig %s | /bin/sed -e '/inet addr:/!d' -e 's/^.*inet addr://' -e 's/ .*$//'", - tuntap->dev_name ); - fp=popen(buf, "r"); - if (fp ) - { - memset(buf,0,N2N_LINUX_SYSTEMCMD_SIZE); /* make sure buf is NULL terminated. */ - nread=fread(buf, 1, 15, fp); - fclose(fp); - fp=NULL; + if (fp) { + memset(buf, 0, N2N_LINUX_SYSTEMCMD_SIZE); /* make sure buf is NULL terminated. */ + nread = fread(buf, N2N_LINUX_SYSTEMCMD_SIZE-1, 1, fp); + fclose(fp); + fp = NULL; - traceEvent(TRACE_INFO, "ifconfig address = %s", buf); + traceEvent(TRACE_INFO, "ifconfig address = %s", buf); - tuntap->ip_addr = inet_addr(buf); + if(nread > 0) { + buf[nread] = '\0'; + tuntap->ip_addr = inet_addr(buf); } + } } From 85ac185781dfac1360dec6151bd5bc7d34d16d62 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Fri, 8 Jun 2018 00:17:42 +0200 Subject: [PATCH 09/10] Code rework --- Makefile | 4 +- edge.c | 2098 ++++++---------------------------------------- egde_utils.c | 1563 ++++++++++++++++++++++++++++++++++ n2n.h | 130 ++- n2n_transforms.h | 28 +- 5 files changed, 1931 insertions(+), 1892 deletions(-) create mode 100644 egde_utils.c diff --git a/Makefile b/Makefile index b670978..2e8266d 100644 --- a/Makefile +++ b/Makefile @@ -45,8 +45,10 @@ MAN8DIR=$(MANDIR)/man8 N2N_LIB=n2n.a N2N_OBJS=n2n.o n2n_keyfile.o wire.o minilzo.o twofish.o \ + egde_utils.o \ transform_null.o transform_tf.o transform_aes.o \ - tuntap_freebsd.o tuntap_netbsd.o tuntap_linux.o tuntap_osx.o version.o + tuntap_freebsd.o tuntap_netbsd.o tuntap_linux.o \ + tuntap_osx.o version.o LIBS_EDGE+=$(LIBS_EDGE_OPT) LIBS_SN= diff --git a/edge.c b/edge.c index d68b568..02c15c0 100644 --- a/edge.c +++ b/edge.c @@ -17,123 +17,22 @@ */ #include "n2n.h" -#include "n2n_transforms.h" -#include -#include -#include "minilzo.h" -#if defined(DEBUG) -#define SOCKET_TIMEOUT_INTERVAL_SECS 5 -#define REGISTER_SUPER_INTERVAL_DFL 20 /* sec */ -#else /* #if defined(DEBUG) */ -#define SOCKET_TIMEOUT_INTERVAL_SECS 10 -#define REGISTER_SUPER_INTERVAL_DFL 60 /* sec */ -#endif /* #if defined(DEBUG) */ +#define N2N_NETMASK_STR_SIZE 16 /* dotted decimal 12 numbers + 3 dots */ +#define N2N_MACNAMSIZ 18 /* AA:BB:CC:DD:EE:FF + NULL*/ +#define N2N_IF_MODE_SIZE 16 /* static | dhcp */ -#define REGISTER_SUPER_INTERVAL_MIN 20 /* sec */ -#define REGISTER_SUPER_INTERVAL_MAX 3600 /* sec */ - -#define IFACE_UPDATE_INTERVAL (30) /* sec. How long it usually takes to get an IP lease. */ -#define TRANSOP_TICK_INTERVAL (10) /* sec */ +/* *************************************************** */ /** maximum length of command line arguments */ #define MAX_CMDLINE_BUFFER_LENGTH 4096 /** maximum length of a line in the configuration file */ -#define MAX_CONFFILE_LINE_LENGTH 1024 - -#define N2N_PATHNAME_MAXLEN 256 -#define N2N_MAX_TRANSFORMS 16 -#define N2N_EDGE_MGMT_PORT 5644 - -/** Positions in the transop array where various transforms are stored. - * - * Used by transop_enum_to_index(). See also the transform enumerations in - * n2n_transforms.h */ -#define N2N_TRANSOP_NULL_IDX 0 -#define N2N_TRANSOP_TF_IDX 1 -#define N2N_TRANSOP_AESCBC_IDX 2 -/* etc. */ - - - -/* Work-memory needed for compression. Allocate memory in units - * of `lzo_align_t' (instead of `char') to make sure it is properly aligned. - */ - -/* #define HEAP_ALLOC(var,size) \ */ -/* lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] */ - -/* static HEAP_ALLOC(wrkmem,LZO1X_1_MEM_COMPRESS); */ +#define MAX_CONFFILE_LINE_LENGTH 1024 /* ******************************************************* */ -#define N2N_EDGE_SN_HOST_SIZE 48 - -typedef char n2n_sn_name_t[N2N_EDGE_SN_HOST_SIZE]; - -#define N2N_EDGE_NUM_SUPERNODES 2 -#define N2N_EDGE_SUP_ATTEMPTS 3 /* Number of failed attmpts before moving on to next supernode. */ - - /** Main structure type for edge. */ -struct n2n_edge -{ - int daemon; /**< Non-zero if edge should detach and run in the background. */ - uint8_t re_resolve_supernode_ip; - - n2n_sock_t supernode; - - size_t sn_idx; /**< Currently active supernode. */ - size_t sn_num; /**< Number of supernode addresses defined. */ - n2n_sn_name_t sn_ip_array[N2N_EDGE_NUM_SUPERNODES]; - int sn_wait; /**< Whether we are waiting for a supernode response. */ - - n2n_community_t community_name; /**< The community. 16 full octets. */ - char keyschedule[N2N_PATHNAME_MAXLEN]; - int null_transop; /**< Only allowed if no key sources defined. */ - - int udp_sock; - int udp_mgmt_sock; /**< socket for status info. */ - - tuntap_dev device; /**< All about the TUNTAP device */ - int dyn_ip_mode; /**< Interface IP address is dynamically allocated, eg. DHCP. */ - int allow_routing; /**< Accept packet no to interface address. */ - int drop_multicast; /**< Multicast ethernet addresses. */ - - n2n_trans_op_t transop[N2N_MAX_TRANSFORMS]; /* one for each transform at fixed positions */ - size_t tx_transop_idx; /**< The transop to use when encoding. */ - - struct peer_info * known_peers; /**< Edges we are connected to. */ - struct peer_info * pending_peers; /**< Edges we have tried to register with. */ - time_t last_register_req; /**< Check if time to re-register with super*/ - size_t register_lifetime; /**< Time distance after last_register_req at which to re-register. */ - time_t last_p2p; /**< Last time p2p traffic was received. */ - time_t last_sup; /**< Last time a packet arrived from supernode. */ - size_t sup_attempts; /**< Number of remaining attempts to this supernode. */ - n2n_cookie_t last_cookie; /**< Cookie sent in last REGISTER_SUPER. */ - - time_t start_time; /**< For calculating uptime */ - - /* Statistics */ - size_t tx_p2p; - size_t rx_p2p; - size_t tx_sup; - size_t rx_sup; -}; - -/** Return the IP address of the current supernode in the ring. */ -static const char * supernode_ip(const n2n_edge_t * eee) -{ - return (eee->sn_ip_array)[eee->sn_idx]; -} - - -static void supernode2addr(n2n_sock_t * sn, const n2n_sn_name_t addr); - -static void send_packet2net(n2n_edge_t * eee, - uint8_t *decrypted_msg, size_t len); - /* ************************************** */ @@ -144,13 +43,13 @@ static int readConfFile(const char * filename, char * const linebuffer) { char * buffer = NULL; buffer = (char *)malloc(MAX_CONFFILE_LINE_LENGTH); - if (!buffer) { + if(!buffer) { traceEvent(TRACE_ERROR, "Unable to allocate memory"); return -1; } - if (stat(filename, &stats)) { - if (errno == ENOENT) + if(stat(filename, &stats)) { + if(errno == ENOENT) traceEvent(TRACE_ERROR, "parameter file %s not found/unable to access\n", filename); else traceEvent(TRACE_ERROR, "cannot stat file %s, errno=%d\n",filename, errno); @@ -159,7 +58,7 @@ static int readConfFile(const char * filename, char * const linebuffer) { } fd = fopen(filename, "rb"); - if (!fd) { + if(!fd) { traceEvent(TRACE_ERROR, "Unable to open parameter file '%s' (%d)...\n",filename,errno); free(buffer); return -1; @@ -169,28 +68,28 @@ static int readConfFile(const char * filename, char * const linebuffer) { /* strip out comments */ p = strchr(buffer, '#'); - if (p) *p ='\0'; + if(p) *p ='\0'; /* remove \n */ p = strchr(buffer, '\n'); - if (p) *p ='\0'; + if(p) *p ='\0'; /* strip out heading spaces */ p = buffer; while(*p == ' ' && *p != '\0') ++p; - if (p != buffer) strncpy(buffer,p,strlen(p)+1); + if(p != buffer) strncpy(buffer,p,strlen(p)+1); /* strip out trailing spaces */ while(strlen(buffer) && buffer[strlen(buffer)-1]==' ') buffer[strlen(buffer)-1]= '\0'; /* check for nested @file option */ - if (strchr(buffer, '@')) { + if(strchr(buffer, '@')) { traceEvent(TRACE_ERROR, "@file in file nesting is not supported\n"); free(buffer); return -1; } - if ((strlen(linebuffer)+strlen(buffer)+2)< MAX_CMDLINE_BUFFER_LENGTH) { + if((strlen(linebuffer)+strlen(buffer)+2)< MAX_CMDLINE_BUFFER_LENGTH) { strncat(linebuffer, " ", 1); strncat(linebuffer, buffer, strlen(buffer)); } else { @@ -206,6 +105,8 @@ static int readConfFile(const char * filename, char * const linebuffer) { return 0; } +/* ************************************** */ + /* Create the argv vector */ static char ** buildargv(int * effectiveargc, char * const linebuffer) { const int INITIAL_MAXARGC = 16; /* Number of args + NULL in initial argv */ @@ -216,7 +117,7 @@ static char ** buildargv(int * effectiveargc, char * const linebuffer) { *effectiveargc = 0; buffer = (char *)calloc(1, strlen(linebuffer)+2); - if (!buffer) { + if(!buffer) { traceEvent(TRACE_ERROR, "Unable to allocate memory"); return NULL; } @@ -224,22 +125,24 @@ static char ** buildargv(int * effectiveargc, char * const linebuffer) { maxargc = INITIAL_MAXARGC; argv = (char **)malloc(maxargc * sizeof(char*)); - if (argv == NULL) { + if(argv == NULL) { traceEvent(TRACE_ERROR, "Unable to allocate memory"); return NULL; } + buff = buffer; + while(buff) { char * p = strchr(buff,' '); - if (p) { + if(p) { *p='\0'; argv[argc++] = strdup(buff); while(*++p == ' ' && *p != '\0'); buff=p; - if (argc >= maxargc) { + if(argc >= maxargc) { maxargc *= 2; argv = (char **)realloc(argv, maxargc * sizeof(char*)); - if (argv == NULL) { + if(argv == NULL) { traceEvent(TRACE_ERROR, "Unable to re-allocate memory"); free(buffer); return NULL; @@ -252,212 +155,12 @@ static char ** buildargv(int * effectiveargc, char * const linebuffer) { } free(buffer); *effectiveargc = argc; + return argv; } - - /* ************************************** */ - -/** Initialise an edge to defaults. - * - * This also initialises the NULL transform operation opstruct. - */ -static int edge_init(n2n_edge_t * eee) -{ -#ifdef WIN32 - initWin32(); -#endif - memset(eee, 0, sizeof(n2n_edge_t)); - eee->start_time = time(NULL); - - transop_null_init( &(eee->transop[N2N_TRANSOP_NULL_IDX])); - transop_twofish_init(&(eee->transop[N2N_TRANSOP_TF_IDX] )); - transop_aes_init(&(eee->transop[N2N_TRANSOP_AESCBC_IDX] )); - - eee->tx_transop_idx = N2N_TRANSOP_NULL_IDX; /* No guarantee the others have been setup */ - - eee->daemon = 1; /* By default run in daemon mode. */ - eee->re_resolve_supernode_ip = 0; - /* keyschedule set to NULLs by memset */ - /* community_name set to NULLs by memset */ - eee->null_transop = 0; - eee->udp_sock = -1; - eee->udp_mgmt_sock = -1; - eee->dyn_ip_mode = 0; - eee->allow_routing = 0; - eee->drop_multicast = 1; - eee->known_peers = NULL; - eee->pending_peers = NULL; - eee->last_register_req = 0; - eee->register_lifetime = REGISTER_SUPER_INTERVAL_DFL; - eee->last_p2p = 0; - eee->last_sup = 0; - eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; - - if(lzo_init() != LZO_E_OK) - { - traceEvent(TRACE_ERROR, "LZO compression error"); - return(-1); - } - - return(0); -} - - - -/* Called in main() after options are parsed. */ -static int edge_init_twofish(n2n_edge_t * eee, uint8_t *encrypt_pwd, uint32_t encrypt_pwd_len) -{ - return transop_twofish_setup(&(eee->transop[N2N_TRANSOP_TF_IDX]), 0, encrypt_pwd, encrypt_pwd_len); -} - - -/** Find the transop op-struct for the transform enumeration required. - * - * @return - index into the transop array, or -1 on failure. - */ -static int transop_enum_to_index(n2n_transform_t id) -{ - switch (id) - { - case N2N_TRANSFORM_ID_TWOFISH: - return N2N_TRANSOP_TF_IDX; - break; - case N2N_TRANSFORM_ID_NULL: - return N2N_TRANSOP_NULL_IDX; - break; - case N2N_TRANSFORM_ID_AESCBC: - return N2N_TRANSOP_AESCBC_IDX; - break; - default: - return -1; - } -} - - -/** Called periodically to roll keys and do any periodic maintenance in the - * tranform operations state machines. */ -static int n2n_tick_transop(n2n_edge_t * eee, time_t now) -{ - n2n_tostat_t tst; - size_t trop = eee->tx_transop_idx; - - /* Tests are done in order that most preferred transform is last and causes - * tx_transop_idx to be left at most preferred valid transform. */ - tst = (eee->transop[N2N_TRANSOP_NULL_IDX].tick)(&(eee->transop[N2N_TRANSOP_NULL_IDX]), now); - tst = (eee->transop[N2N_TRANSOP_AESCBC_IDX].tick)(&(eee->transop[N2N_TRANSOP_AESCBC_IDX]), now); - if(tst.can_tx) - { - traceEvent(TRACE_DEBUG, "can_tx AESCBC (idx=%u)", (unsigned int)N2N_TRANSOP_AESCBC_IDX); - trop = N2N_TRANSOP_AESCBC_IDX; - } - - tst = (eee->transop[N2N_TRANSOP_TF_IDX].tick)(&(eee->transop[N2N_TRANSOP_TF_IDX]), now); - if(tst.can_tx) - { - traceEvent(TRACE_DEBUG, "can_tx TF (idx=%u)", (unsigned int)N2N_TRANSOP_TF_IDX); - trop = N2N_TRANSOP_TF_IDX; - } - - if(trop != eee->tx_transop_idx) - { - eee->tx_transop_idx = trop; - traceEvent(TRACE_NORMAL, "Chose new tx_transop_idx=%u", (unsigned int)(eee->tx_transop_idx)); - } - - return 0; -} - - - -/** Read in a key-schedule file, parse the lines and pass each line to the - * appropriate trans_op for parsing of key-data and adding key-schedule - * entries. The lookup table of time->trans_op is constructed such that - * encoding can be passed to the correct trans_op. The trans_op internal table - * will then determine the best SA for that trans_op from the key schedule to - * use for encoding. */ -static int edge_init_keyschedule(n2n_edge_t * eee) -{ - -#define N2N_NUM_CIPHERSPECS 32 - - int retval = -1; - ssize_t numSpecs=0; - n2n_cipherspec_t specs[N2N_NUM_CIPHERSPECS]; - size_t i; - time_t now = time(NULL); - - numSpecs = n2n_read_keyfile(specs, N2N_NUM_CIPHERSPECS, eee->keyschedule); - - if(numSpecs > 0) - { - traceEvent(TRACE_NORMAL, "keyfile = %s read -> %d specs.\n", optarg, (signed int)numSpecs); - - for (i=0; i < (size_t)numSpecs; ++i) - { - int idx; - - idx = transop_enum_to_index(specs[i].t); - - switch (idx) - { - case N2N_TRANSOP_TF_IDX: - case N2N_TRANSOP_AESCBC_IDX: - { - retval = (eee->transop[idx].addspec)(&(eee->transop[idx]), - &(specs[i])); - break; - } - default: - retval = -1; - } - - if (0 != retval) - { - traceEvent(TRACE_ERROR, "keyschedule failed to add spec[%u] to transop[%d].\n", - (unsigned int)i, idx); - - return retval; - } - } - - n2n_tick_transop(eee, now); - } - else - { - traceEvent(TRACE_ERROR, "Failed to process '%s'", eee->keyschedule); - } - - return retval; -} - - -/** Deinitialise the edge and deallocate any owned memory. */ -static void edge_deinit(n2n_edge_t * eee) -{ - if(eee->udp_sock >=0) - { - closesocket(eee->udp_sock); - } - - if(eee->udp_mgmt_sock >= 0) - { - closesocket(eee->udp_mgmt_sock); - } - - clear_peer_list(&(eee->pending_peers)); - clear_peer_list(&(eee->known_peers)); - - (eee->transop[N2N_TRANSOP_TF_IDX].deinit)(&eee->transop[N2N_TRANSOP_TF_IDX]); - (eee->transop[N2N_TRANSOP_NULL_IDX].deinit)(&eee->transop[N2N_TRANSOP_NULL_IDX]); -} - -static void readFromIPSocket(n2n_edge_t * eee); - -static void readFromMgmtSocket(n2n_edge_t * eee, int * keep_running); - static void help() { print_n2n_version(); @@ -467,7 +170,8 @@ static void help() { #endif /* #if defined(N2N_CAN_NAME_IFACE) */ "-a [static:|dhcp:] " "-c " - "[-k | -K ] " + "[-k | -K ]\n" + " " "[-s ] " #ifndef WIN32 "[-u -g ]" @@ -477,8 +181,8 @@ static void help() { "[-f]" #endif /* #ifndef WIN32 */ "[-m ]" - "\n" - "-l " + "-l \n" + " " "[-p ] [-M ] " "[-r] [-E] [-v] [-t ] [-b] [-h]\n\n"); @@ -516,170 +220,7 @@ static void help() { exit(0); } - -/** Send a datagram to a socket defined by a n2n_sock_t */ -static ssize_t sendto_sock(int fd, const void * buf, size_t len, const n2n_sock_t * dest) -{ - struct sockaddr_in peer_addr; - ssize_t sent; - - fill_sockaddr((struct sockaddr *) &peer_addr, - sizeof(peer_addr), - dest); - - sent = sendto(fd, buf, len, 0/*flags*/, - (struct sockaddr *)&peer_addr, sizeof(struct sockaddr_in)); - if(sent < 0) - { - char * c = strerror(errno); - traceEvent(TRACE_ERROR, "sendto failed (%d) %s", errno, c); - } - else - { - traceEvent(TRACE_DEBUG, "sendto sent=%d to ", (signed int)sent); - } - - return sent; -} - - -/** Send a REGISTER packet to another edge. */ -static void send_register(n2n_edge_t * eee, - const n2n_sock_t * remote_peer) -{ - uint8_t pktbuf[N2N_PKT_BUF_SIZE]; - size_t idx; - /* ssize_t sent; */ - n2n_common_t cmn; - n2n_REGISTER_t reg; - n2n_sock_str_t sockbuf; - - memset(&cmn, 0, sizeof(cmn)); - memset(®, 0, sizeof(reg)); - cmn.ttl=N2N_DEFAULT_TTL; - cmn.pc = n2n_register; - cmn.flags = 0; - memcpy(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE); - - idx=0; - encode_uint32(reg.cookie, &idx, 123456789); - idx=0; - encode_mac(reg.srcMac, &idx, eee->device.mac_addr); - - idx=0; - encode_REGISTER(pktbuf, &idx, &cmn, ®); - - traceEvent(TRACE_INFO, "send REGISTER %s", - sock_to_cstr(sockbuf, remote_peer)); - - /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer); -} - - -/** Send a REGISTER_SUPER packet to the current supernode. */ -static void send_register_super(n2n_edge_t * eee, - const n2n_sock_t * supernode) { - uint8_t pktbuf[N2N_PKT_BUF_SIZE]; - size_t idx; - /* ssize_t sent; */ - n2n_common_t cmn; - n2n_REGISTER_SUPER_t reg; - n2n_sock_str_t sockbuf; - - memset(&cmn, 0, sizeof(cmn)); - memset(®, 0, sizeof(reg)); - cmn.ttl=N2N_DEFAULT_TTL; - cmn.pc = n2n_register_super; - cmn.flags = 0; - memcpy(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE); - - for(idx=0; idx < N2N_COOKIE_SIZE; ++idx) - { - eee->last_cookie[idx] = rand() % 0xff; - } - - memcpy(reg.cookie, eee->last_cookie, N2N_COOKIE_SIZE); - reg.auth.scheme=0; /* No auth yet */ - - idx=0; - encode_mac(reg.edgeMac, &idx, eee->device.mac_addr); - - idx=0; - encode_REGISTER_SUPER(pktbuf, &idx, &cmn, ®); - - traceEvent(TRACE_INFO, "send REGISTER_SUPER to %s", - sock_to_cstr(sockbuf, supernode)); - - - /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, supernode); -} - - -/** Send a REGISTER_ACK packet to a peer edge. */ -static void send_register_ack(n2n_edge_t * eee, - const n2n_sock_t * remote_peer, - const n2n_REGISTER_t * reg) { - uint8_t pktbuf[N2N_PKT_BUF_SIZE]; - size_t idx; - /* ssize_t sent; */ - n2n_common_t cmn; - n2n_REGISTER_ACK_t ack; - n2n_sock_str_t sockbuf; - - memset(&cmn, 0, sizeof(cmn)); - memset(&ack, 0, sizeof(reg)); - cmn.ttl=N2N_DEFAULT_TTL; - cmn.pc = n2n_register_ack; - cmn.flags = 0; - memcpy(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE); - - memset(&ack, 0, sizeof(ack)); - memcpy(ack.cookie, reg->cookie, N2N_COOKIE_SIZE); - memcpy(ack.srcMac, eee->device.mac_addr, N2N_MAC_SIZE); - memcpy(ack.dstMac, reg->srcMac, N2N_MAC_SIZE); - - idx=0; - encode_REGISTER_ACK(pktbuf, &idx, &cmn, &ack); - - traceEvent(TRACE_INFO, "send REGISTER_ACK %s", - sock_to_cstr(sockbuf, remote_peer)); - - - /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer); -} - - -/** NOT IMPLEMENTED - * - * This would send a DEREGISTER packet to a peer edge or supernode to indicate - * the edge is going away. - */ -static void send_deregister(n2n_edge_t * eee, - n2n_sock_t * remote_peer) -{ - /* Marshall and send message */ -} - - -static int is_empty_ip_address(const n2n_sock_t * sock); -static void update_peer_address(n2n_edge_t * eee, - uint8_t from_supernode, - const n2n_mac_t mac, - const n2n_sock_t * peer, - time_t when); -void check_peer(n2n_edge_t * eee, - uint8_t from_supernode, - const n2n_mac_t mac, - const n2n_sock_t * peer); -void try_send_register(n2n_edge_t * eee, - uint8_t from_supernode, - const n2n_mac_t mac, - const n2n_sock_t * peer); -void set_peer_operational(n2n_edge_t * eee, - const n2n_mac_t mac, - const n2n_sock_t * peer); - - +/* ************************************** */ /** Start the registration process. * @@ -726,229 +267,14 @@ void try_send_register(n2n_edge_t * eee, send_register(eee, &(scan->sock)); /* pending_peers now owns scan. */ - } - else - { - } + } else { + } } - -/** Update the last_seen time for this peer, or get registered. */ -void check_peer(n2n_edge_t * eee, - uint8_t from_supernode, - const n2n_mac_t mac, - const n2n_sock_t * peer) -{ - struct peer_info * scan = find_peer_by_mac(eee->known_peers, mac); - - if(NULL == scan) - { - /* Not in known_peers - start the REGISTER process. */ - try_send_register(eee, from_supernode, mac, peer); - } - else - { - /* Already in known_peers. */ - update_peer_address(eee, from_supernode, mac, peer, time(NULL)); - } -} - - -/* Move the peer from the pending_peers list to the known_peers lists. - * - * peer must be a pointer to an element of the pending_peers list. - * - * Called by main loop when Rx a REGISTER_ACK. - */ -void set_peer_operational(n2n_edge_t * eee, - const n2n_mac_t mac, - const n2n_sock_t * peer) -{ - struct peer_info * prev = NULL; - struct peer_info * scan; - macstr_t mac_buf; - n2n_sock_str_t sockbuf; - - traceEvent(TRACE_INFO, "set_peer_operational: %s -> %s", - macaddr_str(mac_buf, mac), - sock_to_cstr(sockbuf, peer)); - - scan=eee->pending_peers; - - while (NULL != scan) - { - if(0 == memcmp(scan->mac_addr, mac, N2N_MAC_SIZE)) - { - break; /* found. */ - } - - prev = scan; - scan = scan->next; - } - - if(scan) - { - - - /* Remove scan from pending_peers. */ - if(prev) - { - prev->next = scan->next; - } - else - { - eee->pending_peers = scan->next; - } - - /* Add scan to known_peers. */ - scan->next = eee->known_peers; - eee->known_peers = scan; - - scan->sock = *peer; - - traceEvent(TRACE_DEBUG, "=== new peer %s -> %s", - macaddr_str(mac_buf, scan->mac_addr), - sock_to_cstr(sockbuf, &(scan->sock))); - - traceEvent(TRACE_INFO, "Pending peers list size=%u", - (unsigned int)peer_list_size(eee->pending_peers)); - - traceEvent(TRACE_INFO, "Operational peers list size=%u", - (unsigned int)peer_list_size(eee->known_peers)); - - - scan->last_seen = time(NULL); - } - else - { - traceEvent(TRACE_DEBUG, "Failed to find sender in pending_peers."); - } -} - - -n2n_mac_t broadcast_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - -static int is_empty_ip_address(const n2n_sock_t * sock) -{ - const uint8_t * ptr=NULL; - size_t len=0; - size_t i; - - if(AF_INET6 == sock->family) - { - ptr = sock->addr.v6; - len = 16; - } - else - { - ptr = sock->addr.v4; - len = 4; - } - - for (i=0; iknown_peers; - struct peer_info *prev = NULL; /* use to remove bad registrations. */ - n2n_sock_str_t sockbuf1; - n2n_sock_str_t sockbuf2; /* don't clobber sockbuf1 if writing two addresses to trace */ - macstr_t mac_buf; - - if(is_empty_ip_address(peer)) - { - /* Not to be registered. */ - return; - } - - if(0 == memcmp(mac, broadcast_mac, N2N_MAC_SIZE)) - { - /* Not to be registered. */ - return; - } - - - while(scan != NULL) - { - if(memcmp(mac, scan->mac_addr, N2N_MAC_SIZE) == 0) - { - break; - } - - prev = scan; - scan = scan->next; - } - - if(NULL == scan) - { - /* Not in known_peers. */ - return; - } - - if(0 != sock_equal(&(scan->sock), peer)) - { - if(0 == from_supernode) - { - traceEvent(TRACE_NORMAL, "Peer changed %s: %s -> %s", - macaddr_str(mac_buf, scan->mac_addr), - sock_to_cstr(sockbuf1, &(scan->sock)), - sock_to_cstr(sockbuf2, peer)); - - /* The peer has changed public socket. It can no longer be assumed to be reachable. */ - /* Remove the peer. */ - if(NULL == prev) - { - /* scan was head of list */ - eee->known_peers = scan->next; - } - else - { - prev->next = scan->next; - } - free(scan); - - try_send_register(eee, from_supernode, mac, peer); - } - else - { - /* Don't worry about what the supernode reports, it could be seeing a different socket. */ - } - } - else - { - /* Found and unchanged. */ - scan->last_seen = when; - } -} - - +/* ************************************** */ #if defined(DUMMY_ID_00001) /* Disabled waiting for config option to enable it */ - - static char gratuitous_arp[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Dest mac */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Src mac */ @@ -964,6 +290,7 @@ static char gratuitous_arp[] = { 0x00, 0x00, 0x00, 0x00 /* Target IP */ }; +/* ************************************** */ /** Build a gratuitous ARP packet for a /24 layer 3 (IP) network. */ static int build_gratuitous_arp(char *buffer, uint16_t buffer_len) { @@ -981,6 +308,8 @@ static int build_gratuitous_arp(char *buffer, uint16_t buffer_len) { return(sizeof(gratuitous_arp)); } +/* ************************************** */ + /** Called from update_supernode_reg to periodically send gratuitous ARP * broadcasts. */ static void send_grat_arps(n2n_edge_t * eee,) { @@ -992,113 +321,9 @@ static void send_grat_arps(n2n_edge_t * eee,) { send_packet2net(eee, buffer, len); send_packet2net(eee, buffer, len); /* Two is better than one :-) */ } + #endif /* #if defined(DUMMY_ID_00001) */ - - - -/** @brief Check to see if we should re-register with the supernode. - * - * This is frequently called by the main loop. - */ -static void update_supernode_reg(n2n_edge_t * eee, time_t nowTime) -{ - if(eee->sn_wait && (nowTime > (eee->last_register_req + (eee->register_lifetime/10)))) - { - /* fall through */ - traceEvent(TRACE_DEBUG, "update_supernode_reg: doing fast retry."); - } - else if(nowTime < (eee->last_register_req + eee->register_lifetime)) - { - return; /* Too early */ - } - - if(0 == eee->sup_attempts) - { - /* Give up on that supernode and try the next one. */ - ++(eee->sn_idx); - - if (eee->sn_idx >= eee->sn_num) - { - /* Got to end of list, go back to the start. Also works for list of one entry. */ - eee->sn_idx=0; - } - - traceEvent(TRACE_WARNING, "Supernode not responding - moving to %u of %u", - (unsigned int)eee->sn_idx, (unsigned int)eee->sn_num); - - eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; - } - else - { - --(eee->sup_attempts); - } - - if(eee->re_resolve_supernode_ip || (eee->sn_num > 1)) - { - supernode2addr(&(eee->supernode), eee->sn_ip_array[eee->sn_idx]); - } - - traceEvent(TRACE_DEBUG, "Registering with supernode (%s) (attempts left %u)", - supernode_ip(eee), (unsigned int)eee->sup_attempts); - - send_register_super(eee, &(eee->supernode)); - - eee->sn_wait=1; - - /* REVISIT: turn-on gratuitous ARP with config option. */ - /* send_grat_arps(sock_fd, is_udp_sock); */ - - eee->last_register_req = nowTime; -} - - - -/* @return 1 if destination is a peer, 0 if destination is supernode */ -static int find_peer_destination(n2n_edge_t * eee, - n2n_mac_t mac_address, - n2n_sock_t * destination) -{ - const struct peer_info *scan = eee->known_peers; - macstr_t mac_buf; - n2n_sock_str_t sockbuf; - int retval=0; - - traceEvent(TRACE_DEBUG, "Searching destination peer for MAC %02X:%02X:%02X:%02X:%02X:%02X", - mac_address[0] & 0xFF, mac_address[1] & 0xFF, mac_address[2] & 0xFF, - mac_address[3] & 0xFF, mac_address[4] & 0xFF, mac_address[5] & 0xFF); - - while(scan != NULL) { - traceEvent(TRACE_DEBUG, "Evaluating peer [MAC=%02X:%02X:%02X:%02X:%02X:%02X]", - scan->mac_addr[0] & 0xFF, scan->mac_addr[1] & 0xFF, scan->mac_addr[2] & 0xFF, - scan->mac_addr[3] & 0xFF, scan->mac_addr[4] & 0xFF, scan->mac_addr[5] & 0xFF - ); - - if((scan->last_seen > 0) && - (memcmp(mac_address, scan->mac_addr, N2N_MAC_SIZE) == 0)) - { - memcpy(destination, &scan->sock, sizeof(n2n_sock_t)); - retval=1; - break; - } - scan = scan->next; - } - - if(0 == retval) - { - memcpy(destination, &(eee->supernode), sizeof(struct sockaddr_in)); - } - - traceEvent(TRACE_DEBUG, "find_peer_address (%s) -> [%s]", - macaddr_str(mac_buf, mac_address), - sock_to_cstr(sockbuf, destination)); - - return retval; -} - - - - /* *********************************************** */ static const struct option long_options[] = { @@ -1114,739 +339,6 @@ static const struct option long_options[] = { /* ***************************************************** */ - -/** Send an ecapsulated ethernet PACKET to a destination edge or broadcast MAC - * address. */ -static int send_PACKET(n2n_edge_t * eee, - n2n_mac_t dstMac, - const uint8_t * pktbuf, - size_t pktlen) -{ - int dest; - /*ssize_t s; */ - n2n_sock_str_t sockbuf; - n2n_sock_t destination; - - /* hexdump(pktbuf, pktlen); */ - - dest = find_peer_destination(eee, dstMac, &destination); - - if(dest) - ++(eee->tx_p2p); - else - ++(eee->tx_sup); - - traceEvent(TRACE_INFO, "send_PACKET to %s", sock_to_cstr(sockbuf, &destination)); - - /* s = */ sendto_sock(eee->udp_sock, pktbuf, pktlen, &destination); - - return 0; -} - - -/* Choose the transop for Tx. This should be based on the newest valid - * cipherspec in the key schedule. - * - * Never fall back to NULL tranform unless no key sources were specified. It is - * better to render edge inoperative than to expose user data in the clear. In - * the case where all SAs are expired an arbitrary transform will be chosen for - * Tx. It will fail having no valid SAs but one must be selected. - */ -static size_t edge_choose_tx_transop(const n2n_edge_t * eee) -{ - if(eee->null_transop) - { - return N2N_TRANSOP_NULL_IDX; - } - - return eee->tx_transop_idx; -} - - -/** A layer-2 packet was received at the tunnel and needs to be sent via UDP. */ -static void send_packet2net(n2n_edge_t * eee, - uint8_t *tap_pkt, size_t len) -{ - ipstr_t ip_buf; - n2n_mac_t destMac; - - n2n_common_t cmn; - n2n_PACKET_t pkt; - - uint8_t pktbuf[N2N_PKT_BUF_SIZE]; - size_t idx=0; - size_t tx_transop_idx=0; - - ether_hdr_t eh; - - /* tap_pkt is not aligned so we have to copy to aligned memory */ - memcpy(&eh, tap_pkt, sizeof(ether_hdr_t)); - - /* Discard IP packets that are not originated by this hosts */ - if(!(eee->allow_routing)) { - if(ntohs(eh.type) == 0x0800) { - /* This is an IP packet from the local source address - not forwarded. */ -#define ETH_FRAMESIZE 14 -#define IP4_SRCOFFSET 12 - uint32_t *dst = (uint32_t*)&tap_pkt[ETH_FRAMESIZE + IP4_SRCOFFSET]; - - /* Note: all elements of the_ip are in network order */ - if(*dst != eee->device.ip_addr) { - /* This is a packet that needs to be routed */ - traceEvent(TRACE_INFO, "Discarding routed packet [%s]", - intoa(ntohl(*dst), ip_buf, sizeof(ip_buf))); - return; - } else { - /* This packet is originated by us */ - /* traceEvent(TRACE_INFO, "Sending non-routed packet"); */ - } - } - } - - /* Optionally compress then apply transforms, eg encryption. */ - - /* Once processed, send to destination in PACKET */ - - memcpy(destMac, tap_pkt, N2N_MAC_SIZE); /* dest MAC is first in ethernet header */ - - memset(&cmn, 0, sizeof(cmn)); - cmn.ttl = N2N_DEFAULT_TTL; - cmn.pc = n2n_packet; - cmn.flags=0; /* no options, not from supernode, no socket */ - memcpy(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE); - - memset(&pkt, 0, sizeof(pkt)); - memcpy(pkt.srcMac, eee->device.mac_addr, N2N_MAC_SIZE); - memcpy(pkt.dstMac, destMac, N2N_MAC_SIZE); - - tx_transop_idx = edge_choose_tx_transop(eee); - - pkt.sock.family=0; /* do not encode sock */ - pkt.transform = eee->transop[tx_transop_idx].transform_id; - - idx=0; - encode_PACKET(pktbuf, &idx, &cmn, &pkt); - traceEvent(TRACE_DEBUG, "encoded PACKET header of size=%u transform %u (idx=%u)", - (unsigned int)idx, (unsigned int)pkt.transform, (unsigned int)tx_transop_idx); - - idx += eee->transop[tx_transop_idx].fwd(&(eee->transop[tx_transop_idx]), - pktbuf+idx, N2N_PKT_BUF_SIZE-idx, - tap_pkt, len); - ++(eee->transop[tx_transop_idx].tx_cnt); /* stats */ - - send_PACKET(eee, destMac, pktbuf, idx); /* to peer or supernode */ -} - - -/** Destination MAC 33:33:0:00:00:00 - 33:33:FF:FF:FF:FF is reserved for IPv6 - * neighbour discovery. - */ -static int is_ip6_discovery(const void * buf, size_t bufsize) -{ - int retval = 0; - - if(bufsize >= sizeof(ether_hdr_t)) - { - /* copy to aligned memory */ - ether_hdr_t eh; - memcpy(&eh, buf, sizeof(ether_hdr_t)); - - if((0x33 == eh.dhost[0]) && - (0x33 == eh.dhost[1])) - { - retval = 1; /* This is an IPv6 multicast packet [RFC2464]. */ - } - } - return retval; -} - -/** Destination 01:00:5E:00:00:00 - 01:00:5E:7F:FF:FF is multicast ethernet. - */ -static int is_ethMulticast(const void * buf, size_t bufsize) -{ - int retval = 0; - - /* Match 01:00:5E:00:00:00 - 01:00:5E:7F:FF:FF */ - if(bufsize >= sizeof(ether_hdr_t)) - { - /* copy to aligned memory */ - ether_hdr_t eh; - memcpy(&eh, buf, sizeof(ether_hdr_t)); - - if((0x01 == eh.dhost[0]) && - (0x00 == eh.dhost[1]) && - (0x5E == eh.dhost[2]) && - (0 == (0x80 & eh.dhost[3]))) - { - retval = 1; /* This is an ethernet multicast packet [RFC1112]. */ - } - } - return retval; -} - - - -/** Read a single packet from the TAP interface, process it and write out the - * corresponding packet to the cooked socket. - */ -static void readFromTAPSocket(n2n_edge_t * eee) -{ - /* tun -> remote */ - uint8_t eth_pkt[N2N_PKT_BUF_SIZE]; - macstr_t mac_buf; - ssize_t len; - - len = tuntap_read(&(eee->device), eth_pkt, N2N_PKT_BUF_SIZE); - - if((len <= 0) || (len > N2N_PKT_BUF_SIZE)) - { - traceEvent(TRACE_WARNING, "read()=%d [%d/%s]", - (signed int)len, errno, strerror(errno)); - } - else - { - const uint8_t * mac = eth_pkt; - traceEvent(TRACE_INFO, "### Rx TAP packet (%4d) for %s", - (signed int)len, macaddr_str(mac_buf, mac)); - - if(eee->drop_multicast && - (is_ip6_discovery(eth_pkt, len) || - is_ethMulticast(eth_pkt, len) - ) - ) - { - traceEvent(TRACE_DEBUG, "Dropping multicast"); - } - else - { - send_packet2net(eee, eth_pkt, len); - } - } -} - - - -/** A PACKET has arrived containing an encapsulated ethernet datagram - usually - * encrypted. */ -static int handle_PACKET(n2n_edge_t * eee, - const n2n_common_t * cmn, - const n2n_PACKET_t * pkt, - const n2n_sock_t * orig_sender, - uint8_t * payload, - size_t psize) -{ - ssize_t data_sent_len; - uint8_t from_supernode; - uint8_t * eth_payload=NULL; - int retval = -1; - time_t now; - - now = time(NULL); - - traceEvent(TRACE_DEBUG, "handle_PACKET size %u transform %u", - (unsigned int)psize, (unsigned int)pkt->transform); - /* hexdump(payload, psize); */ - - from_supernode= cmn->flags & N2N_FLAGS_FROM_SUPERNODE; - - if(from_supernode) - { - ++(eee->rx_sup); - eee->last_sup=now; - } - else - { - ++(eee->rx_p2p); - eee->last_p2p=now; - } - - /* Update the sender in peer table entry */ - check_peer(eee, from_supernode, pkt->srcMac, orig_sender); - - /* Handle transform. */ - { - uint8_t decodebuf[N2N_PKT_BUF_SIZE]; - size_t eth_size; - int rx_transop_idx; - - rx_transop_idx = transop_enum_to_index(pkt->transform); - - if(rx_transop_idx >=0) - { - eth_payload = decodebuf; - eth_size = eee->transop[rx_transop_idx].rev(&(eee->transop[rx_transop_idx]), - eth_payload, N2N_PKT_BUF_SIZE, - payload, psize); - ++(eee->transop[rx_transop_idx].rx_cnt); /* stats */ - - /* Write ethernet packet to tap device. */ - traceEvent(TRACE_INFO, "sending to TAP %u", (unsigned int)eth_size); - data_sent_len = tuntap_write(&(eee->device), eth_payload, eth_size); - - if (data_sent_len == eth_size) - { - retval = 0; - } - } - else - { - traceEvent(TRACE_ERROR, "handle_PACKET dropped unknown transform enum %u", - (unsigned int)pkt->transform); - } - } - - return retval; -} - - -/** Read a datagram from the management UDP socket and take appropriate - * action. */ -static void readFromMgmtSocket(n2n_edge_t * eee, int * keep_running) -{ - uint8_t 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; - - 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_ERROR, "mgmt recvfrom failed with %s", strerror(errno)); - - return; /* failed to receive data from UDP */ - } - - if(recvlen >= 4) - { - if(0 == memcmp(udp_buf, "stop", 4)) - { - traceEvent(TRACE_ERROR, "stop command received."); - *keep_running = 0; - return; - } - - if(0 == memcmp(udp_buf, "help", 4)) - { - msg_len=0; - ++traceLevel; - - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "Help for edge management console:\n" - " stop Gracefully exit edge\n" - " help This help message\n" - " +verb Increase verbosity of logging\n" - " -verb Decrease verbosity of logging\n" - " reload Re-read the keyschedule\n" - " 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(recvlen >= 5) - { - if(0 == memcmp(udp_buf, "+verb", 5)) - { - msg_len=0; - ++traceLevel; - - traceEvent(TRACE_ERROR, "+verb traceLevel=%u", (unsigned int)traceLevel); - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "> +OK traceLevel=%u\n", (unsigned int)traceLevel); - - 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(traceLevel > 0) - { - --traceLevel; - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "> -OK traceLevel=%u\n", traceLevel); - } - else - { - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "> -NOK traceLevel=%u\n", traceLevel); - } - - traceEvent(TRACE_ERROR, "-verb traceLevel=%u", (unsigned int)traceLevel); - - sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, - (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); - return; - } - } - - if(recvlen >= 6) - { - if(0 == memcmp(udp_buf, "reload", 6)) - { - if(strlen(eee->keyschedule) > 0) - { - if(edge_init_keyschedule(eee) == 0) - { - msg_len=0; - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "> OK\n"); - sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, - (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); - } - return; - } - } - } - - traceEvent(TRACE_DEBUG, "mgmt status rq"); - - msg_len=0; - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "Statistics for edge\n"); - - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "uptime %lu\n", - time(NULL) - eee->start_time); - - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "paths super:%u,%u p2p:%u,%u\n", - (unsigned int)eee->tx_sup, - (unsigned int)eee->rx_sup, - (unsigned int)eee->tx_p2p, - (unsigned int)eee->rx_p2p); - - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "trans:null |%6u|%6u|\n" - "trans:tf |%6u|%6u|\n" - "trans:aes |%6u|%6u|\n", - (unsigned int)eee->transop[N2N_TRANSOP_NULL_IDX].tx_cnt, - (unsigned int)eee->transop[N2N_TRANSOP_NULL_IDX].rx_cnt, - (unsigned int)eee->transop[N2N_TRANSOP_TF_IDX].tx_cnt, - (unsigned int)eee->transop[N2N_TRANSOP_TF_IDX].rx_cnt, - (unsigned int)eee->transop[N2N_TRANSOP_AESCBC_IDX].tx_cnt, - (unsigned int)eee->transop[N2N_TRANSOP_AESCBC_IDX].rx_cnt); - - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "peers pend:%u full:%u\n", - (unsigned int)peer_list_size(eee->pending_peers), - (unsigned int)peer_list_size(eee->known_peers)); - - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "last super:%lu(%ld sec ago) p2p:%lu(%ld sec ago)\n", - eee->last_sup, (now-eee->last_sup), eee->last_p2p, (now-eee->last_p2p)); - - traceEvent(TRACE_DEBUG, "mgmt status sending: %s", udp_buf); - - - /* sendlen = */ sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, - (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); -} - - -/** Read a datagram from the main UDP socket to the internet. */ -static void readFromIPSocket(n2n_edge_t * eee) -{ - n2n_common_t cmn; /* common fields in the packet header */ - - n2n_sock_str_t sockbuf1; - n2n_sock_str_t sockbuf2; /* don't clobber sockbuf1 if writing two addresses to trace */ - macstr_t mac_buf1; - macstr_t mac_buf2; - - uint8_t udp_buf[N2N_PKT_BUF_SIZE]; /* Compete UDP packet */ - ssize_t recvlen; - size_t rem; - size_t idx; - size_t msg_type; - uint8_t from_supernode; - struct sockaddr_in sender_sock; - n2n_sock_t sender; - n2n_sock_t * orig_sender=NULL; - time_t now=0; - - size_t i; - - i = sizeof(sender_sock); - recvlen=recvfrom(eee->udp_sock, udp_buf, N2N_PKT_BUF_SIZE, 0/*flags*/, - (struct sockaddr *)&sender_sock, (socklen_t*)&i); - - if(recvlen < 0) - { - traceEvent(TRACE_ERROR, "recvfrom failed with %s", strerror(errno)); - - return; /* failed to receive data from UDP */ - } - - /* REVISIT: when UDP/IPv6 is supported we will need a flag to indicate which - * IP transport version the packet arrived on. May need to UDP sockets. */ - sender.family = AF_INET; /* udp_sock was opened PF_INET v4 */ - sender.port = ntohs(sender_sock.sin_port); - memcpy(&(sender.addr.v4), &(sender_sock.sin_addr.s_addr), IPV4_SIZE); - - /* The packet may not have an orig_sender socket spec. So default to last - * hop as sender. */ - orig_sender=&sender; - - traceEvent(TRACE_INFO, "### Rx N2N UDP (%d) from %s", - (signed int)recvlen, sock_to_cstr(sockbuf1, &sender)); - - /* hexdump(udp_buf, recvlen); */ - - rem = recvlen; /* Counts down bytes of packet to protect against buffer overruns. */ - idx = 0; /* marches through packet header as parts are decoded. */ - if(decode_common(&cmn, udp_buf, &rem, &idx) < 0) - { - traceEvent(TRACE_ERROR, "Failed to decode common section in N2N_UDP"); - return; /* failed to decode packet */ - } - - now = time(NULL); - - msg_type = cmn.pc; /* packet code */ - from_supernode= cmn.flags & N2N_FLAGS_FROM_SUPERNODE; - - if(0 == memcmp(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE)) - { - if(msg_type == MSG_TYPE_PACKET) - { - /* process PACKET - most frequent so first in list. */ - n2n_PACKET_t pkt; - - decode_PACKET(&pkt, &cmn, udp_buf, &rem, &idx); - - if(pkt.sock.family) - { - orig_sender = &(pkt.sock); - } - - traceEvent(TRACE_INFO, "Rx PACKET from %s (%s)", - sock_to_cstr(sockbuf1, &sender), - sock_to_cstr(sockbuf2, orig_sender)); - - handle_PACKET(eee, &cmn, &pkt, orig_sender, udp_buf+idx, recvlen-idx); - } - else if(msg_type == MSG_TYPE_REGISTER) - { - /* Another edge is registering with us */ - n2n_REGISTER_t reg; - - decode_REGISTER(®, &cmn, udp_buf, &rem, &idx); - - if(reg.sock.family) - { - orig_sender = &(reg.sock); - } - - traceEvent(TRACE_INFO, "Rx REGISTER src=%s dst=%s from peer %s (%s)", - macaddr_str(mac_buf1, reg.srcMac), - macaddr_str(mac_buf2, reg.dstMac), - sock_to_cstr(sockbuf1, &sender), - sock_to_cstr(sockbuf2, orig_sender)); - - if(0 == memcmp(reg.dstMac, (eee->device.mac_addr), 6)) - { - check_peer(eee, from_supernode, reg.srcMac, orig_sender); - } - - send_register_ack(eee, orig_sender, ®); - } - else if(msg_type == MSG_TYPE_REGISTER_ACK) - { - /* Peer edge is acknowledging our register request */ - n2n_REGISTER_ACK_t ra; - - decode_REGISTER_ACK(&ra, &cmn, udp_buf, &rem, &idx); - - if(ra.sock.family) - { - orig_sender = &(ra.sock); - } - - traceEvent(TRACE_INFO, "Rx REGISTER_ACK src=%s dst=%s from peer %s (%s)", - macaddr_str(mac_buf1, ra.srcMac), - macaddr_str(mac_buf2, ra.dstMac), - sock_to_cstr(sockbuf1, &sender), - sock_to_cstr(sockbuf2, orig_sender)); - - /* Move from pending_peers to known_peers; ignore if not in pending. */ - set_peer_operational(eee, ra.srcMac, &sender); - } - else if(msg_type == MSG_TYPE_REGISTER_SUPER_ACK) - { - n2n_REGISTER_SUPER_ACK_t ra; - - if(eee->sn_wait) - { - decode_REGISTER_SUPER_ACK(&ra, &cmn, udp_buf, &rem, &idx); - - if(ra.sock.family) - { - orig_sender = &(ra.sock); - } - - traceEvent(TRACE_NORMAL, "Rx REGISTER_SUPER_ACK myMAC=%s [%s] (external %s). Attempts %u", - macaddr_str(mac_buf1, ra.edgeMac), - sock_to_cstr(sockbuf1, &sender), - sock_to_cstr(sockbuf2, orig_sender), - (unsigned int)eee->sup_attempts); - - if(0 == memcmp(ra.cookie, eee->last_cookie, N2N_COOKIE_SIZE)) - { - if(ra.num_sn > 0) - { - traceEvent(TRACE_NORMAL, "Rx REGISTER_SUPER_ACK backup supernode at %s", - sock_to_cstr(sockbuf1, &(ra.sn_bak))); - } - - eee->last_sup = now; - eee->sn_wait=0; - eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; /* refresh because we got a response */ - - /* REVISIT: store sn_back */ - eee->register_lifetime = ra.lifetime; - eee->register_lifetime = MAX(eee->register_lifetime, REGISTER_SUPER_INTERVAL_MIN); - eee->register_lifetime = MIN(eee->register_lifetime, REGISTER_SUPER_INTERVAL_MAX); - } - else - { - traceEvent(TRACE_WARNING, "Rx REGISTER_SUPER_ACK with wrong or old cookie."); - } - } - else - { - traceEvent(TRACE_WARNING, "Rx REGISTER_SUPER_ACK with no outstanding REGISTER_SUPER."); - } - } - else - { - /* Not a known message type */ - traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored", (signed int)msg_type); - return; - } - } /* if (community match) */ - else - { - traceEvent(TRACE_WARNING, "Received packet with invalid community"); - } - -} - -/* ***************************************************** */ - - -#ifdef WIN32 -static DWORD tunReadThread(LPVOID lpArg) -{ - n2n_edge_t *eee = (n2n_edge_t*)lpArg; - - while(1) - { - readFromTAPSocket(eee); - } - - return((DWORD)NULL); -} - - -/** Start a second thread in Windows because TUNTAP interfaces do not expose - * file descriptors. */ -static void startTunReadThread(n2n_edge_t *eee) -{ - HANDLE hThread; - DWORD dwThreadId; - - hThread = CreateThread(NULL, /* security attributes */ - 0, /* use default stack size */ - (LPTHREAD_START_ROUTINE)tunReadThread, /* thread function */ - (void*)eee, /* argument to thread function */ - 0, /* thread creation flags */ - &dwThreadId); /* thread id out */ -} -#endif - -/* ***************************************************** */ - -/** Resolve the supernode IP address. - * - * REVISIT: This is a really bad idea. The edge will block completely while the - * hostname resolution is performed. This could take 15 seconds. - */ -static void supernode2addr(n2n_sock_t * sn, const n2n_sn_name_t addrIn) -{ - n2n_sn_name_t addr; - const char *supernode_host; - - memcpy(addr, addrIn, N2N_EDGE_SN_HOST_SIZE); - - supernode_host = strtok(addr, ":"); - - if(supernode_host) - { - in_addr_t sn_addr; - char *supernode_port = strtok(NULL, ":"); - const struct addrinfo aihints = {0, PF_INET, 0, 0, 0, NULL, NULL, NULL}; - struct addrinfo * ainfo = NULL; - int nameerr; - - if(supernode_port) - sn->port = atoi(supernode_port); - else - traceEvent(TRACE_WARNING, "Bad supernode parameter (-l ) %s %s:%s", - addr, supernode_host, supernode_port); - - nameerr = getaddrinfo(supernode_host, NULL, &aihints, &ainfo); - - 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)) - { - /* 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 - { - /* Should only return IPv4 addresses due to aihints. */ - traceEvent(TRACE_WARNING, "Failed to resolve supernode IPv4 address for %s", supernode_host); - } - - freeaddrinfo(ainfo); /* free everything allocated by getaddrinfo(). */ - ainfo = NULL; - } else { - traceEvent(TRACE_WARNING, "Failed to resolve supernode host %s, assuming numeric", supernode_host); - sn_addr = inet_addr(supernode_host); /* uint32_t */ - memcpy(sn->addr.v4, &(sn_addr), IPV4_SIZE); - sn->family=AF_INET; - } - - } else - traceEvent(TRACE_WARNING, "Wrong supernode parameter (-l )"); -} - -/* ***************************************************** */ - - /** Find the address and IP mode for the tuntap device. * * s is one of these forms: @@ -1865,8 +357,7 @@ static void supernode2addr(n2n_sock_t * sn, const n2n_sn_name_t addrIn) */ static int scan_address(char * ip_addr, size_t addr_size, char * ip_mode, size_t mode_size, - const char * s) -{ + const char * s) { int retval = -1; char * p; @@ -1902,13 +393,7 @@ static int scan_address(char * ip_addr, size_t addr_size, return retval; } -static int run_loop(n2n_edge_t * eee); - -#define N2N_NETMASK_STR_SIZE 16 /* dotted decimal 12 numbers + 3 dots */ -#define N2N_MACNAMSIZ 18 /* AA:BB:CC:DD:EE:FF + NULL*/ -#define N2N_IF_MODE_SIZE 16 /* static | dhcp */ - -/* *************************************************** */ +/* ************************************** */ static void daemonize() { #ifndef WIN32 @@ -1958,33 +443,32 @@ static void daemonize() { /* *************************************************** */ /** Entry point to program from kernel. */ -int main(int argc, char* argv[]) -{ +int main(int argc, char* argv[]) { int opt; int local_port = 0 /* any port */; int mgmt_port = N2N_EDGE_MGMT_PORT; /* 5644 by default */ char tuntap_dev_name[N2N_IFNAMSIZ] = "edge0"; - char ip_mode[N2N_IF_MODE_SIZE]="static"; + char ip_mode[N2N_IF_MODE_SIZE] = "static"; char ip_addr[N2N_NETMASK_STR_SIZE] = ""; - char netmask[N2N_NETMASK_STR_SIZE]="255.255.255.0"; + char netmask[N2N_NETMASK_STR_SIZE] = "255.255.255.0"; int mtu = DEFAULT_MTU; int got_s = 0; #ifndef WIN32 - uid_t userid=0; /* root is the only guaranteed ID */ - gid_t groupid=0; /* root is the only guaranteed ID */ + uid_t userid = 0; /* root is the only guaranteed ID */ + gid_t groupid = 0; /* root is the only guaranteed ID */ #endif - char device_mac[N2N_MACNAMSIZ]=""; - char * encrypt_key=NULL; + char device_mac[N2N_MACNAMSIZ] = ""; + char * encrypt_key = NULL; - int i, effectiveargc=0; - char ** effectiveargv=NULL; + int i, effectiveargc = 0; + char ** effectiveargv = NULL; char * linebuffer = NULL; n2n_edge_t eee; /* single instance for this program */ - if (-1 == edge_init(&eee)) + if(-1 == edge_init(&eee)) { traceEvent(TRACE_ERROR, "Failed in edge_init"); exit(1); @@ -2002,7 +486,7 @@ int main(int argc, char* argv[]) eee.supernode.family = AF_INET; linebuffer = (char *)malloc(MAX_CMDLINE_BUFFER_LENGTH); - if (!linebuffer) + if(!linebuffer) { traceEvent(TRACE_ERROR, "Unable to allocate memory"); exit(1); @@ -2018,9 +502,9 @@ int main(int argc, char* argv[]) { if(argv[i][0] == '@') { - if (readConfFile(&argv[i][1], linebuffer)<0) exit(1); /* <<<<----- check */ + if(readConfFile(&argv[i][1], linebuffer)<0) exit(1); /* <<<<----- check */ } - else if ((strlen(linebuffer)+strlen(argv[i])+2) < MAX_CMDLINE_BUFFER_LENGTH) + else if((strlen(linebuffer)+strlen(argv[i])+2) < MAX_CMDLINE_BUFFER_LENGTH) { strncat(linebuffer, " ", 1); strncat(linebuffer, argv[i], strlen(argv[i])); @@ -2038,7 +522,7 @@ int main(int argc, char* argv[]) /* build the new argv from the linebuffer */ effectiveargv = buildargv(&effectiveargc, linebuffer); - if (linebuffer) + if(linebuffer) { free(linebuffer); linebuffer = NULL; @@ -2046,194 +530,191 @@ int main(int argc, char* argv[]) /* {int k;for(k=0;k 0) - { - fprintf(stderr, "Error: -K and -k options are mutually exclusive.\n"); - exit(1); - } else { - traceEvent(TRACE_DEBUG, "encrypt_key = '%s'\n", encrypt_key); - encrypt_key = strdup(optarg); - } - break; - } - case 'r': /* enable packet routing across n2n endpoints */ - { - eee.allow_routing = 1; - break; + case 'k': /* encrypt key */ + { + if(strlen(eee.keyschedule) > 0) + { + fprintf(stderr, "Error: -K and -k options are mutually exclusive.\n"); + exit(1); + } else { + traceEvent(TRACE_DEBUG, "encrypt_key = '%s'\n", encrypt_key); + encrypt_key = strdup(optarg); } + break; + } + case 'r': /* enable packet routing across n2n endpoints */ + { + eee.allow_routing = 1; + break; + } - case 'l': /* supernode-list */ - { - if(eee.sn_num < N2N_EDGE_NUM_SUPERNODES) - { - strncpy((eee.sn_ip_array[eee.sn_num]), optarg, N2N_EDGE_SN_HOST_SIZE); - traceEvent(TRACE_DEBUG, "Adding supernode[%u] = %s\n", (unsigned int)eee.sn_num, (eee.sn_ip_array[eee.sn_num])); - ++eee.sn_num; - } - else - { - fprintf(stderr, "Too many supernodes!\n"); - exit(1); - } - break; - } + case 'l': /* supernode-list */ + { + if(eee.sn_num < N2N_EDGE_NUM_SUPERNODES) + { + strncpy((eee.sn_ip_array[eee.sn_num]), optarg, N2N_EDGE_SN_HOST_SIZE); + traceEvent(TRACE_DEBUG, "Adding supernode[%u] = %s\n", (unsigned int)eee.sn_num, (eee.sn_ip_array[eee.sn_num])); + ++eee.sn_num; + } + else + { + fprintf(stderr, "Too many supernodes!\n"); + exit(1); + } + break; + } #if defined(N2N_CAN_NAME_IFACE) - case 'd': /* TUNTAP name */ - { - strncpy(tuntap_dev_name, optarg, N2N_IFNAMSIZ); - break; - } + case 'd': /* TUNTAP name */ + { + strncpy(tuntap_dev_name, optarg, N2N_IFNAMSIZ); + break; + } #endif - case 'b': - { - eee.re_resolve_supernode_ip = 1; - break; - } + case 'b': + { + eee.re_resolve_supernode_ip = 1; + break; + } - case 'p': - { - local_port = atoi(optarg); - break; - } - - case 't': - { - mgmt_port = atoi(optarg); - break; - } + case 'p': + { + local_port = atoi(optarg); + break; + } - case 's': /* Subnet Mask */ - { - if (0 != got_s) - { - traceEvent(TRACE_WARNING, "Multiple subnet masks supplied."); - } - strncpy(netmask, optarg, N2N_NETMASK_STR_SIZE); - got_s = 1; - break; - } + case 't': + { + mgmt_port = atoi(optarg); + break; + } - case 'h': /* help */ - { - help(); - break; - } + case 's': /* Subnet Mask */ + { + if(0 != got_s) + { + traceEvent(TRACE_WARNING, "Multiple subnet masks supplied."); + } + strncpy(netmask, optarg, N2N_NETMASK_STR_SIZE); + got_s = 1; + break; + } - case 'v': /* verbose */ - { - ++traceLevel; /* do 2 -v flags to increase verbosity to DEBUG level*/ - break; - } + case 'h': /* help */ + { + help(); + break; + } - } /* end switch */ - } + case 'v': /* verbose */ + { + ++traceLevel; /* do 2 -v flags to increase verbosity to DEBUG level*/ + break; + } + + } /* end switch */ + } #ifndef WIN32 - if(eee.daemon) - { - useSyslog = 1; /* traceEvent output now goes to syslog. */ - daemonize(); - } + if(eee.daemon) { + useSyslog = 1; /* traceEvent output now goes to syslog. */ + daemonize(); + } #endif /* #ifndef WIN32 */ - traceEvent(TRACE_NORMAL, "Starting n2n edge %s %s", n2n_sw_version, n2n_sw_buildDate); - for (i=0; i< N2N_EDGE_NUM_SUPERNODES; ++i) - { - traceEvent(TRACE_NORMAL, "supernode %u => %s\n", i, (eee.sn_ip_array[i])); - } + traceEvent(TRACE_NORMAL, "supernode %u => %s\n", i, (eee.sn_ip_array[i])); supernode2addr(&(eee.supernode), eee.sn_ip_array[eee.sn_idx]); - for (i=0; i 0) { - if (edge_init_keyschedule(&eee) != 0) { + if(edge_init_keyschedule(&eee) != 0) { fprintf(stderr, "Error: keyschedule setup failed.\n"); return(-1); } - - } + } /* else run in NULL mode */ - - eee.udp_sock = open_socket(local_port, 1 /*bind ANY*/); - if(eee.udp_sock < 0) - { - traceEvent(TRACE_ERROR, "Failed to bind main UDP port %u", (signed int)local_port); - return(-1); - } - - eee.udp_mgmt_sock = open_socket(mgmt_port, 0 /* bind LOOPBACK*/); - - if(eee.udp_mgmt_sock < 0) - { - traceEvent(TRACE_ERROR, "Failed to bind management UDP port %u", (unsigned int)N2N_EDGE_MGMT_PORT); - return(-1); - } - - + eee.udp_sock = open_socket(local_port, 1 /* bind ANY */); + if(eee.udp_sock < 0) { + traceEvent(TRACE_ERROR, "Failed to bind main UDP port %u", (signed int)local_port); + return(-1); + } + + eee.udp_mgmt_sock = open_socket(mgmt_port, 0 /* bind LOOPBACK */); + + if(eee.udp_mgmt_sock < 0) { + traceEvent(TRACE_ERROR, "Failed to bind management UDP port %u", + (unsigned int)N2N_EDGE_MGMT_PORT); + return(-1); + } + traceEvent(TRACE_NORMAL, "edge started"); update_supernode_reg(&eee, time(NULL)); - return run_loop(&eee); + return run_edge_loop(&eee); } -static int run_loop(n2n_edge_t * eee) -{ - int keep_running=1; - size_t numPurged; - time_t lastIfaceCheck=0; - time_t lastTransop=0; +/* ************************************** */ +#ifdef QUICK_INIT -#ifdef WIN32 - startTunReadThread(eee); -#endif - - /* Main loop - * - * select() is used to wait for input on either the TAP fd or the UDP/TCP - * socket. When input is present the data is read and processed by either - * readFromIPSocket() or readFromTAPSocket() - */ - - while(keep_running) - { - int rc, max_sock = 0; - fd_set socket_mask; - struct timeval wait_time; - time_t nowTime; - - FD_ZERO(&socket_mask); - FD_SET(eee->udp_sock, &socket_mask); - FD_SET(eee->udp_mgmt_sock, &socket_mask); - max_sock = max(eee->udp_sock, eee->udp_mgmt_sock); -#ifndef WIN32 - FD_SET(eee->device.fd, &socket_mask); - max_sock = max(max_sock, eee->device.fd); -#endif - - wait_time.tv_sec = SOCKET_TIMEOUT_INTERVAL_SECS; wait_time.tv_usec = 0; - - rc = select(max_sock+1, &socket_mask, NULL, NULL, &wait_time); - nowTime=time(NULL); - - /* Make sure ciphers are updated before the packet is treated. */ - if((nowTime - lastTransop) > TRANSOP_TICK_INTERVAL) - { - lastTransop = nowTime; - - n2n_tick_transop(eee, nowTime); - } - - if(rc > 0) - { - /* Any or all of the FDs could have input; check them all. */ - - if(FD_ISSET(eee->udp_sock, &socket_mask)) - { - /* Read a cooked socket from the internet socket. Writes on the TAP - * socket. */ - readFromIPSocket(eee); - } - - if(FD_ISSET(eee->udp_mgmt_sock, &socket_mask)) - { - /* Read a cooked socket from the internet socket. Writes on the TAP - * socket. */ - readFromMgmtSocket(eee, &keep_running); - } - -#ifndef WIN32 - if(FD_ISSET(eee->device.fd, &socket_mask)) - { - /* Read an ethernet frame from the TAP socket. Write on the IP - * socket. */ - readFromTAPSocket(eee); - } -#endif - } - - /* Finished processing select data. */ - - - update_supernode_reg(eee, nowTime); - - numPurged = purge_expired_registrations(&(eee->known_peers)); - numPurged += purge_expired_registrations(&(eee->pending_peers)); - if(numPurged > 0) - { - traceEvent(TRACE_NORMAL, "Peer removed: pending=%u, operational=%u", - (unsigned int)peer_list_size(eee->pending_peers), - (unsigned int)peer_list_size(eee->known_peers)); - } - - if(eee->dyn_ip_mode && - ((nowTime - lastIfaceCheck) > IFACE_UPDATE_INTERVAL)) - { - traceEvent(TRACE_NORMAL, "Re-checking dynamic IP address."); - tuntap_get_address(&(eee->device)); - lastIfaceCheck = nowTime; - } - - } /* while */ - - send_deregister(eee, &(eee->supernode)); - - closesocket(eee->udp_sock); - tuntap_close(&(eee->device)); - - edge_deinit(eee); - - return(0); +int main(int argc, char* argv[]) { + traceLevel = 10; + return(quick_edge_init("n2n0", + "mynetwork", + "ntop2018", + "DE:AD:BE:EF:01:10", + "192.168.254.10", + "192.12.193.11:7654")); } - +#endif diff --git a/egde_utils.c b/egde_utils.c new file mode 100644 index 0000000..32a3caf --- /dev/null +++ b/egde_utils.c @@ -0,0 +1,1563 @@ +/** + * (C) 2007-18 - ntop.org and contributors + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + */ + +#include "n2n.h" + +#if defined(DEBUG) +#define SOCKET_TIMEOUT_INTERVAL_SECS 5 +#define REGISTER_SUPER_INTERVAL_DFL 20 /* sec */ +#else /* #if defined(DEBUG) */ +#define SOCKET_TIMEOUT_INTERVAL_SECS 10 +#define REGISTER_SUPER_INTERVAL_DFL 60 /* sec */ +#endif /* #if defined(DEBUG) */ + +#define REGISTER_SUPER_INTERVAL_MIN 20 /* sec */ +#define REGISTER_SUPER_INTERVAL_MAX 3600 /* sec */ + +#define IFACE_UPDATE_INTERVAL (30) /* sec. How long it usually takes to get an IP lease. */ +#define TRANSOP_TICK_INTERVAL (10) /* sec */ + +/** Positions in the transop array where various transforms are stored. + * + * Used by transop_enum_to_index(). See also the transform enumerations in + * n2n_transforms.h */ +#define N2N_TRANSOP_NULL_IDX 0 +#define N2N_TRANSOP_TF_IDX 1 +#define N2N_TRANSOP_AESCBC_IDX 2 +/* etc. */ + +/* ************************************** */ + +/** Initialise an edge to defaults. + * + * This also initialises the NULL transform operation opstruct. + */ +int edge_init(n2n_edge_t * eee) { +#ifdef WIN32 + initWin32(); +#endif + memset(eee, 0, sizeof(n2n_edge_t)); + eee->start_time = time(NULL); + + transop_null_init( &(eee->transop[N2N_TRANSOP_NULL_IDX])); + transop_twofish_init(&(eee->transop[N2N_TRANSOP_TF_IDX] )); + transop_aes_init(&(eee->transop[N2N_TRANSOP_AESCBC_IDX] )); + + eee->tx_transop_idx = N2N_TRANSOP_NULL_IDX; /* No guarantee the others have been setup */ + + eee->daemon = 1; /* By default run in daemon mode. */ + eee->re_resolve_supernode_ip = 0; + /* keyschedule set to NULLs by memset */ + /* community_name set to NULLs by memset */ + eee->null_transop = 0; + eee->udp_sock = -1; + eee->udp_mgmt_sock = -1; + eee->dyn_ip_mode = 0; + eee->allow_routing = 0; + eee->drop_multicast = 1; + eee->known_peers = NULL; + eee->pending_peers = NULL; + eee->last_register_req = 0; + eee->register_lifetime = REGISTER_SUPER_INTERVAL_DFL; + eee->last_p2p = 0; + eee->last_sup = 0; + eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; + + if(lzo_init() != LZO_E_OK) { + traceEvent(TRACE_ERROR, "LZO compression error"); + return(-1); + } + + return(0); +} + +/* ***************************************************** */ + +/** Resolve the supernode IP address. + * + * REVISIT: This is a really bad idea. The edge will block completely while the + * hostname resolution is performed. This could take 15 seconds. + */ +void supernode2addr(n2n_sock_t * sn, const n2n_sn_name_t addrIn) { + n2n_sn_name_t addr; + const char *supernode_host; + + memcpy(addr, addrIn, N2N_EDGE_SN_HOST_SIZE); + + supernode_host = strtok(addr, ":"); + + if(supernode_host) + { + in_addr_t sn_addr; + char *supernode_port = strtok(NULL, ":"); + const struct addrinfo aihints = {0, PF_INET, 0, 0, 0, NULL, NULL, NULL}; + struct addrinfo * ainfo = NULL; + int nameerr; + + if(supernode_port) + sn->port = atoi(supernode_port); + else + traceEvent(TRACE_WARNING, "Bad supernode parameter (-l ) %s %s:%s", + addr, supernode_host, supernode_port); + + nameerr = getaddrinfo(supernode_host, NULL, &aihints, &ainfo); + + 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)) + { + /* 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 + { + /* Should only return IPv4 addresses due to aihints. */ + traceEvent(TRACE_WARNING, "Failed to resolve supernode IPv4 address for %s", supernode_host); + } + + freeaddrinfo(ainfo); /* free everything allocated by getaddrinfo(). */ + ainfo = NULL; + } else { + traceEvent(TRACE_WARNING, "Failed to resolve supernode host %s, assuming numeric", supernode_host); + sn_addr = inet_addr(supernode_host); /* uint32_t */ + memcpy(sn->addr.v4, &(sn_addr), IPV4_SIZE); + sn->family=AF_INET; + } + + } else + traceEvent(TRACE_WARNING, "Wrong supernode parameter (-l )"); +} + +/* ************************************** */ + +/** Update the last_seen time for this peer, or get registered. */ +void check_peer(n2n_edge_t * eee, + uint8_t from_supernode, + const n2n_mac_t mac, + const n2n_sock_t * peer) { + struct peer_info * scan = find_peer_by_mac(eee->known_peers, mac); + + if(NULL == scan) + { + /* Not in known_peers - start the REGISTER process. */ + try_send_register(eee, from_supernode, mac, peer); + } + else + { + /* Already in known_peers. */ + update_peer_address(eee, from_supernode, mac, peer, time(NULL)); + } +} +/* ************************************** */ + + +/* Move the peer from the pending_peers list to the known_peers lists. + * + * peer must be a pointer to an element of the pending_peers list. + * + * Called by main loop when Rx a REGISTER_ACK. + */ +void set_peer_operational(n2n_edge_t * eee, + const n2n_mac_t mac, + const n2n_sock_t * peer) { + struct peer_info * prev = NULL; + struct peer_info * scan; + macstr_t mac_buf; + n2n_sock_str_t sockbuf; + + traceEvent(TRACE_INFO, "set_peer_operational: %s -> %s", + macaddr_str(mac_buf, mac), + sock_to_cstr(sockbuf, peer)); + + scan=eee->pending_peers; + + while (NULL != scan) + { + if(0 == memcmp(scan->mac_addr, mac, N2N_MAC_SIZE)) + { + break; /* found. */ + } + + prev = scan; + scan = scan->next; + } + + if(scan) + { + + + /* Remove scan from pending_peers. */ + if(prev) + { + prev->next = scan->next; + } + else + { + eee->pending_peers = scan->next; + } + + /* Add scan to known_peers. */ + scan->next = eee->known_peers; + eee->known_peers = scan; + + scan->sock = *peer; + + traceEvent(TRACE_DEBUG, "=== new peer %s -> %s", + macaddr_str(mac_buf, scan->mac_addr), + sock_to_cstr(sockbuf, &(scan->sock))); + + traceEvent(TRACE_INFO, "Pending peers list size=%u", + (unsigned int)peer_list_size(eee->pending_peers)); + + traceEvent(TRACE_INFO, "Operational peers list size=%u", + (unsigned int)peer_list_size(eee->known_peers)); + + + scan->last_seen = time(NULL); + } + else + { + traceEvent(TRACE_DEBUG, "Failed to find sender in pending_peers."); + } +} + +/* ************************************** */ + +n2n_mac_t broadcast_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + +/* ************************************** */ + +int is_empty_ip_address(const n2n_sock_t * sock) { + const uint8_t * ptr=NULL; + size_t len=0; + size_t i; + + if(AF_INET6 == sock->family) + { + ptr = sock->addr.v6; + len = 16; + } + else + { + ptr = sock->addr.v4; + len = 4; + } + + for (i=0; iknown_peers; + struct peer_info *prev = NULL; /* use to remove bad registrations. */ + n2n_sock_str_t sockbuf1; + n2n_sock_str_t sockbuf2; /* don't clobber sockbuf1 if writing two addresses to trace */ + macstr_t mac_buf; + + if(is_empty_ip_address(peer)) + { + /* Not to be registered. */ + return; + } + + if(0 == memcmp(mac, broadcast_mac, N2N_MAC_SIZE)) + { + /* Not to be registered. */ + return; + } + + + while(scan != NULL) + { + if(memcmp(mac, scan->mac_addr, N2N_MAC_SIZE) == 0) + { + break; + } + + prev = scan; + scan = scan->next; + } + + if(NULL == scan) + { + /* Not in known_peers. */ + return; + } + + if(0 != sock_equal(&(scan->sock), peer)) + { + if(0 == from_supernode) + { + traceEvent(TRACE_NORMAL, "Peer changed %s: %s -> %s", + macaddr_str(mac_buf, scan->mac_addr), + sock_to_cstr(sockbuf1, &(scan->sock)), + sock_to_cstr(sockbuf2, peer)); + + /* The peer has changed public socket. It can no longer be assumed to be reachable. */ + /* Remove the peer. */ + if(NULL == prev) + { + /* scan was head of list */ + eee->known_peers = scan->next; + } + else + { + prev->next = scan->next; + } + free(scan); + + try_send_register(eee, from_supernode, mac, peer); + } + else + { + /* Don't worry about what the supernode reports, it could be seeing a different socket. */ + } + } + else + { + /* Found and unchanged. */ + scan->last_seen = when; + } +} + +/* ************************************** */ + +/** Send a datagram to a socket defined by a n2n_sock_t */ +static ssize_t sendto_sock(int fd, const void * buf, + size_t len, const n2n_sock_t * dest) { + struct sockaddr_in peer_addr; + ssize_t sent; + + fill_sockaddr((struct sockaddr *) &peer_addr, + sizeof(peer_addr), + dest); + + sent = sendto(fd, buf, len, 0/*flags*/, + (struct sockaddr *)&peer_addr, sizeof(struct sockaddr_in)); + if(sent < 0) + { + char * c = strerror(errno); + traceEvent(TRACE_ERROR, "sendto failed (%d) %s", errno, c); + } + else + { + traceEvent(TRACE_DEBUG, "sendto sent=%d to ", (signed int)sent); + } + + return sent; +} + +/* ************************************** */ + +/** Send a REGISTER_SUPER packet to the current supernode. */ +static void send_register_super(n2n_edge_t * eee, + const n2n_sock_t * supernode) { + uint8_t pktbuf[N2N_PKT_BUF_SIZE]; + size_t idx; + /* ssize_t sent; */ + n2n_common_t cmn; + n2n_REGISTER_SUPER_t reg; + n2n_sock_str_t sockbuf; + + memset(&cmn, 0, sizeof(cmn)); + memset(®, 0, sizeof(reg)); + cmn.ttl=N2N_DEFAULT_TTL; + cmn.pc = n2n_register_super; + cmn.flags = 0; + memcpy(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE); + + for(idx=0; idx < N2N_COOKIE_SIZE; ++idx) + { + eee->last_cookie[idx] = rand() % 0xff; + } + + memcpy(reg.cookie, eee->last_cookie, N2N_COOKIE_SIZE); + reg.auth.scheme=0; /* No auth yet */ + + idx=0; + encode_mac(reg.edgeMac, &idx, eee->device.mac_addr); + + idx=0; + encode_REGISTER_SUPER(pktbuf, &idx, &cmn, ®); + + traceEvent(TRACE_INFO, "send REGISTER_SUPER to %s", + sock_to_cstr(sockbuf, supernode)); + + /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, supernode); +} + +/* ************************************** */ + +/** Send a REGISTER packet to another edge. */ +void send_register(n2n_edge_t * eee, + const n2n_sock_t * remote_peer) { + uint8_t pktbuf[N2N_PKT_BUF_SIZE]; + size_t idx; + /* ssize_t sent; */ + n2n_common_t cmn; + n2n_REGISTER_t reg; + n2n_sock_str_t sockbuf; + + memset(&cmn, 0, sizeof(cmn)); + memset(®, 0, sizeof(reg)); + cmn.ttl=N2N_DEFAULT_TTL; + cmn.pc = n2n_register; + cmn.flags = 0; + memcpy(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE); + + idx=0; + encode_uint32(reg.cookie, &idx, 123456789); + idx=0; + encode_mac(reg.srcMac, &idx, eee->device.mac_addr); + + idx=0; + encode_REGISTER(pktbuf, &idx, &cmn, ®); + + traceEvent(TRACE_INFO, "send REGISTER %s", + sock_to_cstr(sockbuf, remote_peer)); + + /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer); +} + +/* ************************************** */ + +/** Send a REGISTER_ACK packet to a peer edge. */ +static void send_register_ack(n2n_edge_t * eee, + const n2n_sock_t * remote_peer, + const n2n_REGISTER_t * reg) { + uint8_t pktbuf[N2N_PKT_BUF_SIZE]; + size_t idx; + /* ssize_t sent; */ + n2n_common_t cmn; + n2n_REGISTER_ACK_t ack; + n2n_sock_str_t sockbuf; + + memset(&cmn, 0, sizeof(cmn)); + memset(&ack, 0, sizeof(reg)); + cmn.ttl=N2N_DEFAULT_TTL; + cmn.pc = n2n_register_ack; + cmn.flags = 0; + memcpy(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE); + + memset(&ack, 0, sizeof(ack)); + memcpy(ack.cookie, reg->cookie, N2N_COOKIE_SIZE); + memcpy(ack.srcMac, eee->device.mac_addr, N2N_MAC_SIZE); + memcpy(ack.dstMac, reg->srcMac, N2N_MAC_SIZE); + + idx=0; + encode_REGISTER_ACK(pktbuf, &idx, &cmn, &ack); + + traceEvent(TRACE_INFO, "send REGISTER_ACK %s", + sock_to_cstr(sockbuf, remote_peer)); + + + /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer); +} + +/* ************************************** */ + +/** @brief Check to see if we should re-register with the supernode. + * + * This is frequently called by the main loop. + */ +void update_supernode_reg(n2n_edge_t * eee, time_t nowTime) { + if(eee->sn_wait && (nowTime > (eee->last_register_req + (eee->register_lifetime/10)))) + { + /* fall through */ + traceEvent(TRACE_DEBUG, "update_supernode_reg: doing fast retry."); + } + else if(nowTime < (eee->last_register_req + eee->register_lifetime)) + { + return; /* Too early */ + } + + if(0 == eee->sup_attempts) + { + /* Give up on that supernode and try the next one. */ + ++(eee->sn_idx); + + if (eee->sn_idx >= eee->sn_num) + { + /* Got to end of list, go back to the start. Also works for list of one entry. */ + eee->sn_idx=0; + } + + traceEvent(TRACE_WARNING, "Supernode not responding - moving to %u of %u", + (unsigned int)eee->sn_idx, (unsigned int)eee->sn_num); + + eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; + } + else + { + --(eee->sup_attempts); + } + + if(eee->re_resolve_supernode_ip || (eee->sn_num > 1)) + { + supernode2addr(&(eee->supernode), eee->sn_ip_array[eee->sn_idx]); + } + + traceEvent(TRACE_DEBUG, "Registering with supernode (%s) (attempts left %u)", + supernode_ip(eee), (unsigned int)eee->sup_attempts); + + send_register_super(eee, &(eee->supernode)); + + eee->sn_wait=1; + + /* REVISIT: turn-on gratuitous ARP with config option. */ + /* send_grat_arps(sock_fd, is_udp_sock); */ + + eee->last_register_req = nowTime; +} + +/* ************************************** */ + +/** NOT IMPLEMENTED + * + * This would send a DEREGISTER packet to a peer edge or supernode to indicate + * the edge is going away. + */ +static void send_deregister(n2n_edge_t * eee, + n2n_sock_t * remote_peer) { + /* Marshall and send message */ +} + +/* ************************************** */ + +/** Return the IP address of the current supernode in the ring. */ +const char * supernode_ip(const n2n_edge_t * eee) { + return (eee->sn_ip_array)[eee->sn_idx]; +} + +/* ************************************** */ + +int edge_init_twofish(n2n_edge_t * eee, uint8_t *encrypt_pwd, + uint32_t encrypt_pwd_len) { + return transop_twofish_setup(&(eee->transop[N2N_TRANSOP_TF_IDX]), + 0, encrypt_pwd, encrypt_pwd_len); +} + +/* ************************************** */ + +/** Called periodically to roll keys and do any periodic maintenance in the + * tranform operations state machines. */ +static int n2n_tick_transop(n2n_edge_t * eee, time_t now) +{ + n2n_tostat_t tst; + size_t trop = eee->tx_transop_idx; + + /* Tests are done in order that most preferred transform is last and causes + * tx_transop_idx to be left at most preferred valid transform. */ + tst = (eee->transop[N2N_TRANSOP_NULL_IDX].tick)(&(eee->transop[N2N_TRANSOP_NULL_IDX]), now); + tst = (eee->transop[N2N_TRANSOP_AESCBC_IDX].tick)(&(eee->transop[N2N_TRANSOP_AESCBC_IDX]), now); + if(tst.can_tx) + { + traceEvent(TRACE_DEBUG, "can_tx AESCBC (idx=%u)", (unsigned int)N2N_TRANSOP_AESCBC_IDX); + trop = N2N_TRANSOP_AESCBC_IDX; + } + + tst = (eee->transop[N2N_TRANSOP_TF_IDX].tick)(&(eee->transop[N2N_TRANSOP_TF_IDX]), now); + if(tst.can_tx) + { + traceEvent(TRACE_DEBUG, "can_tx TF (idx=%u)", (unsigned int)N2N_TRANSOP_TF_IDX); + trop = N2N_TRANSOP_TF_IDX; + } + + if(trop != eee->tx_transop_idx) + { + eee->tx_transop_idx = trop; + traceEvent(TRACE_NORMAL, "Chose new tx_transop_idx=%u", (unsigned int)(eee->tx_transop_idx)); + } + + return 0; +} + +/* ************************************** */ + +/** Find the transop op-struct for the transform enumeration required. + * + * @return - index into the transop array, or -1 on failure. + */ +int transop_enum_to_index(n2n_transform_t id) { + switch (id) + { + case N2N_TRANSFORM_ID_TWOFISH: + return N2N_TRANSOP_TF_IDX; + break; + case N2N_TRANSFORM_ID_NULL: + return N2N_TRANSOP_NULL_IDX; + break; + case N2N_TRANSFORM_ID_AESCBC: + return N2N_TRANSOP_AESCBC_IDX; + break; + default: + return -1; + } +} + +/* ************************************** */ + +/** A PACKET has arrived containing an encapsulated ethernet datagram - usually + * encrypted. */ +static int handle_PACKET(n2n_edge_t * eee, + const n2n_common_t * cmn, + const n2n_PACKET_t * pkt, + const n2n_sock_t * orig_sender, + uint8_t * payload, + size_t psize) { + ssize_t data_sent_len; + uint8_t from_supernode; + uint8_t * eth_payload=NULL; + int retval = -1; + time_t now; + + now = time(NULL); + + traceEvent(TRACE_DEBUG, "handle_PACKET size %u transform %u", + (unsigned int)psize, (unsigned int)pkt->transform); + /* hexdump(payload, psize); */ + + from_supernode= cmn->flags & N2N_FLAGS_FROM_SUPERNODE; + + if(from_supernode) + { + ++(eee->rx_sup); + eee->last_sup=now; + } + else + { + ++(eee->rx_p2p); + eee->last_p2p=now; + } + + /* Update the sender in peer table entry */ + check_peer(eee, from_supernode, pkt->srcMac, orig_sender); + + /* Handle transform. */ + { + uint8_t decodebuf[N2N_PKT_BUF_SIZE]; + size_t eth_size; + int rx_transop_idx; + + rx_transop_idx = transop_enum_to_index(pkt->transform); + + if(rx_transop_idx >=0) + { + eth_payload = decodebuf; + eth_size = eee->transop[rx_transop_idx].rev(&(eee->transop[rx_transop_idx]), + eth_payload, N2N_PKT_BUF_SIZE, + payload, psize); + ++(eee->transop[rx_transop_idx].rx_cnt); /* stats */ + + /* Write ethernet packet to tap device. */ + traceEvent(TRACE_INFO, "sending to TAP %u", (unsigned int)eth_size); + data_sent_len = tuntap_write(&(eee->device), eth_payload, eth_size); + + if (data_sent_len == eth_size) + { + retval = 0; + } + } + else + { + traceEvent(TRACE_ERROR, "handle_PACKET dropped unknown transform enum %u", + (unsigned int)pkt->transform); + } + } + + return retval; +} + +/* ************************************** */ + +/** Read a datagram from the management UDP socket and take appropriate + * action. */ +static void readFromMgmtSocket(n2n_edge_t * eee, int * keep_running) { + uint8_t 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; + + 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_ERROR, "mgmt recvfrom failed with %s", strerror(errno)); + + return; /* failed to receive data from UDP */ + } + + if(recvlen >= 4) + { + if(0 == memcmp(udp_buf, "stop", 4)) + { + traceEvent(TRACE_ERROR, "stop command received."); + *keep_running = 0; + return; + } + + if(0 == memcmp(udp_buf, "help", 4)) + { + msg_len=0; + ++traceLevel; + + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "Help for edge management console:\n" + " stop Gracefully exit edge\n" + " help This help message\n" + " +verb Increase verbosity of logging\n" + " -verb Decrease verbosity of logging\n" + " reload Re-read the keyschedule\n" + " 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(recvlen >= 5) + { + if(0 == memcmp(udp_buf, "+verb", 5)) + { + msg_len=0; + ++traceLevel; + + traceEvent(TRACE_ERROR, "+verb traceLevel=%u", (unsigned int)traceLevel); + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "> +OK traceLevel=%u\n", (unsigned int)traceLevel); + + 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(traceLevel > 0) + { + --traceLevel; + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "> -OK traceLevel=%u\n", traceLevel); + } + else + { + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "> -NOK traceLevel=%u\n", traceLevel); + } + + traceEvent(TRACE_ERROR, "-verb traceLevel=%u", (unsigned int)traceLevel); + + sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, + (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); + return; + } + } + + if(recvlen >= 6) + { + if(0 == memcmp(udp_buf, "reload", 6)) + { + if(strlen(eee->keyschedule) > 0) + { + if(edge_init_keyschedule(eee) == 0) + { + msg_len=0; + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "> OK\n"); + sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, + (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); + } + return; + } + } + } + + traceEvent(TRACE_DEBUG, "mgmt status rq"); + + msg_len=0; + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "Statistics for edge\n"); + + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "uptime %lu\n", + time(NULL) - eee->start_time); + + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "paths super:%u,%u p2p:%u,%u\n", + (unsigned int)eee->tx_sup, + (unsigned int)eee->rx_sup, + (unsigned int)eee->tx_p2p, + (unsigned int)eee->rx_p2p); + + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "trans:null |%6u|%6u|\n" + "trans:tf |%6u|%6u|\n" + "trans:aes |%6u|%6u|\n", + (unsigned int)eee->transop[N2N_TRANSOP_NULL_IDX].tx_cnt, + (unsigned int)eee->transop[N2N_TRANSOP_NULL_IDX].rx_cnt, + (unsigned int)eee->transop[N2N_TRANSOP_TF_IDX].tx_cnt, + (unsigned int)eee->transop[N2N_TRANSOP_TF_IDX].rx_cnt, + (unsigned int)eee->transop[N2N_TRANSOP_AESCBC_IDX].tx_cnt, + (unsigned int)eee->transop[N2N_TRANSOP_AESCBC_IDX].rx_cnt); + + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "peers pend:%u full:%u\n", + (unsigned int)peer_list_size(eee->pending_peers), + (unsigned int)peer_list_size(eee->known_peers)); + + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "last super:%lu(%ld sec ago) p2p:%lu(%ld sec ago)\n", + eee->last_sup, (now-eee->last_sup), eee->last_p2p, (now-eee->last_p2p)); + + traceEvent(TRACE_DEBUG, "mgmt status sending: %s", udp_buf); + + + /* sendlen = */ sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, + (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); +} + +/* ************************************** */ + +/** Destination MAC 33:33:0:00:00:00 - 33:33:FF:FF:FF:FF is reserved for IPv6 + * neighbour discovery. + */ +static int is_ip6_discovery(const void * buf, size_t bufsize) { + int retval = 0; + + if(bufsize >= sizeof(ether_hdr_t)) + { + /* copy to aligned memory */ + ether_hdr_t eh; + memcpy(&eh, buf, sizeof(ether_hdr_t)); + + if((0x33 == eh.dhost[0]) && + (0x33 == eh.dhost[1])) + { + retval = 1; /* This is an IPv6 multicast packet [RFC2464]. */ + } + } + return retval; +} + +/* ************************************** */ + +/** Destination 01:00:5E:00:00:00 - 01:00:5E:7F:FF:FF is multicast ethernet. + */ +static int is_ethMulticast(const void * buf, size_t bufsize) { + int retval = 0; + + /* Match 01:00:5E:00:00:00 - 01:00:5E:7F:FF:FF */ + if(bufsize >= sizeof(ether_hdr_t)) + { + /* copy to aligned memory */ + ether_hdr_t eh; + memcpy(&eh, buf, sizeof(ether_hdr_t)); + + if((0x01 == eh.dhost[0]) && + (0x00 == eh.dhost[1]) && + (0x5E == eh.dhost[2]) && + (0 == (0x80 & eh.dhost[3]))) + { + retval = 1; /* This is an ethernet multicast packet [RFC1112]. */ + } + } + + return retval; +} + +/* ************************************** */ + +/* Choose the transop for Tx. This should be based on the newest valid + * cipherspec in the key schedule. + * + * Never fall back to NULL tranform unless no key sources were specified. It is + * better to render edge inoperative than to expose user data in the clear. In + * the case where all SAs are expired an arbitrary transform will be chosen for + * Tx. It will fail having no valid SAs but one must be selected. + */ +static size_t edge_choose_tx_transop(const n2n_edge_t * eee) { + if(eee->null_transop) + { + return N2N_TRANSOP_NULL_IDX; + } + + return eee->tx_transop_idx; +} + +/* ************************************** */ + +/* @return 1 if destination is a peer, 0 if destination is supernode */ +static int find_peer_destination(n2n_edge_t * eee, + n2n_mac_t mac_address, + n2n_sock_t * destination) { + const struct peer_info *scan = eee->known_peers; + macstr_t mac_buf; + n2n_sock_str_t sockbuf; + int retval=0; + + traceEvent(TRACE_DEBUG, "Searching destination peer for MAC %02X:%02X:%02X:%02X:%02X:%02X", + mac_address[0] & 0xFF, mac_address[1] & 0xFF, mac_address[2] & 0xFF, + mac_address[3] & 0xFF, mac_address[4] & 0xFF, mac_address[5] & 0xFF); + + while(scan != NULL) { + traceEvent(TRACE_DEBUG, "Evaluating peer [MAC=%02X:%02X:%02X:%02X:%02X:%02X]", + scan->mac_addr[0] & 0xFF, scan->mac_addr[1] & 0xFF, scan->mac_addr[2] & 0xFF, + scan->mac_addr[3] & 0xFF, scan->mac_addr[4] & 0xFF, scan->mac_addr[5] & 0xFF + ); + + if((scan->last_seen > 0) && + (memcmp(mac_address, scan->mac_addr, N2N_MAC_SIZE) == 0)) + { + memcpy(destination, &scan->sock, sizeof(n2n_sock_t)); + retval=1; + break; + } + scan = scan->next; + } + + if(0 == retval) + { + memcpy(destination, &(eee->supernode), sizeof(struct sockaddr_in)); + } + + traceEvent(TRACE_DEBUG, "find_peer_address (%s) -> [%s]", + macaddr_str(mac_buf, mac_address), + sock_to_cstr(sockbuf, destination)); + + return retval; +} + +/* ***************************************************** */ + +/** Send an ecapsulated ethernet PACKET to a destination edge or broadcast MAC + * address. */ +static int send_packet(n2n_edge_t * eee, + n2n_mac_t dstMac, + const uint8_t * pktbuf, + size_t pktlen) { + int dest; + /*ssize_t s; */ + n2n_sock_str_t sockbuf; + n2n_sock_t destination; + + /* hexdump(pktbuf, pktlen); */ + + dest = find_peer_destination(eee, dstMac, &destination); + + if(dest) + ++(eee->tx_p2p); + else + ++(eee->tx_sup); + + traceEvent(TRACE_INFO, "send_packet to %s", sock_to_cstr(sockbuf, &destination)); + + /* s = */ sendto_sock(eee->udp_sock, pktbuf, pktlen, &destination); + + return 0; +} + +/* ************************************** */ + +/** A layer-2 packet was received at the tunnel and needs to be sent via UDP. */ +void send_packet2net(n2n_edge_t * eee, + uint8_t *tap_pkt, size_t len) { + ipstr_t ip_buf; + n2n_mac_t destMac; + + n2n_common_t cmn; + n2n_PACKET_t pkt; + + uint8_t pktbuf[N2N_PKT_BUF_SIZE]; + size_t idx=0; + size_t tx_transop_idx=0; + + ether_hdr_t eh; + + /* tap_pkt is not aligned so we have to copy to aligned memory */ + memcpy(&eh, tap_pkt, sizeof(ether_hdr_t)); + + /* Discard IP packets that are not originated by this hosts */ + if(!(eee->allow_routing)) { + if(ntohs(eh.type) == 0x0800) { + /* This is an IP packet from the local source address - not forwarded. */ +#define ETH_FRAMESIZE 14 +#define IP4_SRCOFFSET 12 + uint32_t *dst = (uint32_t*)&tap_pkt[ETH_FRAMESIZE + IP4_SRCOFFSET]; + + /* Note: all elements of the_ip are in network order */ + if(*dst != eee->device.ip_addr) { + /* This is a packet that needs to be routed */ + traceEvent(TRACE_INFO, "Discarding routed packet [%s]", + intoa(ntohl(*dst), ip_buf, sizeof(ip_buf))); + return; + } else { + /* This packet is originated by us */ + /* traceEvent(TRACE_INFO, "Sending non-routed packet"); */ + } + } + } + + /* Optionally compress then apply transforms, eg encryption. */ + + /* Once processed, send to destination in PACKET */ + + memcpy(destMac, tap_pkt, N2N_MAC_SIZE); /* dest MAC is first in ethernet header */ + + memset(&cmn, 0, sizeof(cmn)); + cmn.ttl = N2N_DEFAULT_TTL; + cmn.pc = n2n_packet; + cmn.flags=0; /* no options, not from supernode, no socket */ + memcpy(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE); + + memset(&pkt, 0, sizeof(pkt)); + memcpy(pkt.srcMac, eee->device.mac_addr, N2N_MAC_SIZE); + memcpy(pkt.dstMac, destMac, N2N_MAC_SIZE); + + tx_transop_idx = edge_choose_tx_transop(eee); + + pkt.sock.family=0; /* do not encode sock */ + pkt.transform = eee->transop[tx_transop_idx].transform_id; + + idx=0; + encode_PACKET(pktbuf, &idx, &cmn, &pkt); + traceEvent(TRACE_DEBUG, "encoded PACKET header of size=%u transform %u (idx=%u)", + (unsigned int)idx, (unsigned int)pkt.transform, (unsigned int)tx_transop_idx); + + idx += eee->transop[tx_transop_idx].fwd(&(eee->transop[tx_transop_idx]), + pktbuf+idx, N2N_PKT_BUF_SIZE-idx, + tap_pkt, len); + ++(eee->transop[tx_transop_idx].tx_cnt); /* stats */ + + send_packet(eee, destMac, pktbuf, idx); /* to peer or supernode */ +} + +/* ************************************** */ + +/** Read a single packet from the TAP interface, process it and write out the + * corresponding packet to the cooked socket. + */ +static void readFromTAPSocket(n2n_edge_t * eee) { + /* tun -> remote */ + uint8_t eth_pkt[N2N_PKT_BUF_SIZE]; + macstr_t mac_buf; + ssize_t len; + + len = tuntap_read(&(eee->device), eth_pkt, N2N_PKT_BUF_SIZE); + + if((len <= 0) || (len > N2N_PKT_BUF_SIZE)) + { + traceEvent(TRACE_WARNING, "read()=%d [%d/%s]", + (signed int)len, errno, strerror(errno)); + } + else + { + const uint8_t * mac = eth_pkt; + traceEvent(TRACE_INFO, "### Rx TAP packet (%4d) for %s", + (signed int)len, macaddr_str(mac_buf, mac)); + + if(eee->drop_multicast && + (is_ip6_discovery(eth_pkt, len) || + is_ethMulticast(eth_pkt, len) + ) + ) + { + traceEvent(TRACE_DEBUG, "Dropping multicast"); + } + else + { + send_packet2net(eee, eth_pkt, len); + } + } +} + +/* ************************************** */ + +#ifdef WIN32 +static DWORD tunReadThread(LPVOID lpArg) { + n2n_edge_t *eee = (n2n_edge_t*)lpArg; + + while(1) + readFromTAPSocket(eee); + + return((DWORD)NULL); +} + +/* ************************************** */ + +/** Start a second thread in Windows because TUNTAP interfaces do not expose + * file descriptors. */ +static void startTunReadThread(n2n_edge_t *eee) { + HANDLE hThread; + DWORD dwThreadId; + + hThread = CreateThread(NULL, /* security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE)tunReadThread, /* thread function */ + (void*)eee, /* argument to thread function */ + 0, /* thread creation flags */ + &dwThreadId); /* thread id out */ +} +#endif + +/* ************************************** */ + +/** Read a datagram from the main UDP socket to the internet. */ +static void readFromIPSocket(n2n_edge_t * eee) { + n2n_common_t cmn; /* common fields in the packet header */ + + n2n_sock_str_t sockbuf1; + n2n_sock_str_t sockbuf2; /* don't clobber sockbuf1 if writing two addresses to trace */ + macstr_t mac_buf1; + macstr_t mac_buf2; + + uint8_t udp_buf[N2N_PKT_BUF_SIZE]; /* Compete UDP packet */ + ssize_t recvlen; + size_t rem; + size_t idx; + size_t msg_type; + uint8_t from_supernode; + struct sockaddr_in sender_sock; + n2n_sock_t sender; + n2n_sock_t * orig_sender=NULL; + time_t now=0; + + size_t i; + + i = sizeof(sender_sock); + recvlen=recvfrom(eee->udp_sock, udp_buf, N2N_PKT_BUF_SIZE, 0/*flags*/, + (struct sockaddr *)&sender_sock, (socklen_t*)&i); + + if(recvlen < 0) + { + traceEvent(TRACE_ERROR, "recvfrom failed with %s", strerror(errno)); + + return; /* failed to receive data from UDP */ + } + + /* REVISIT: when UDP/IPv6 is supported we will need a flag to indicate which + * IP transport version the packet arrived on. May need to UDP sockets. */ + sender.family = AF_INET; /* udp_sock was opened PF_INET v4 */ + sender.port = ntohs(sender_sock.sin_port); + memcpy(&(sender.addr.v4), &(sender_sock.sin_addr.s_addr), IPV4_SIZE); + + /* The packet may not have an orig_sender socket spec. So default to last + * hop as sender. */ + orig_sender=&sender; + + traceEvent(TRACE_INFO, "### Rx N2N UDP (%d) from %s", + (signed int)recvlen, sock_to_cstr(sockbuf1, &sender)); + + /* hexdump(udp_buf, recvlen); */ + + rem = recvlen; /* Counts down bytes of packet to protect against buffer overruns. */ + idx = 0; /* marches through packet header as parts are decoded. */ + if(decode_common(&cmn, udp_buf, &rem, &idx) < 0) + { + traceEvent(TRACE_ERROR, "Failed to decode common section in N2N_UDP"); + return; /* failed to decode packet */ + } + + now = time(NULL); + + msg_type = cmn.pc; /* packet code */ + from_supernode= cmn.flags & N2N_FLAGS_FROM_SUPERNODE; + + if(0 == memcmp(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE)) + { + if(msg_type == MSG_TYPE_PACKET) + { + /* process PACKET - most frequent so first in list. */ + n2n_PACKET_t pkt; + + decode_PACKET(&pkt, &cmn, udp_buf, &rem, &idx); + + if(pkt.sock.family) + { + orig_sender = &(pkt.sock); + } + + traceEvent(TRACE_INFO, "Rx PACKET from %s (%s)", + sock_to_cstr(sockbuf1, &sender), + sock_to_cstr(sockbuf2, orig_sender)); + + handle_PACKET(eee, &cmn, &pkt, orig_sender, udp_buf+idx, recvlen-idx); + } + else if(msg_type == MSG_TYPE_REGISTER) + { + /* Another edge is registering with us */ + n2n_REGISTER_t reg; + + decode_REGISTER(®, &cmn, udp_buf, &rem, &idx); + + if(reg.sock.family) + { + orig_sender = &(reg.sock); + } + + traceEvent(TRACE_INFO, "Rx REGISTER src=%s dst=%s from peer %s (%s)", + macaddr_str(mac_buf1, reg.srcMac), + macaddr_str(mac_buf2, reg.dstMac), + sock_to_cstr(sockbuf1, &sender), + sock_to_cstr(sockbuf2, orig_sender)); + + if(0 == memcmp(reg.dstMac, (eee->device.mac_addr), 6)) + { + check_peer(eee, from_supernode, reg.srcMac, orig_sender); + } + + send_register_ack(eee, orig_sender, ®); + } + else if(msg_type == MSG_TYPE_REGISTER_ACK) + { + /* Peer edge is acknowledging our register request */ + n2n_REGISTER_ACK_t ra; + + decode_REGISTER_ACK(&ra, &cmn, udp_buf, &rem, &idx); + + if(ra.sock.family) + { + orig_sender = &(ra.sock); + } + + traceEvent(TRACE_INFO, "Rx REGISTER_ACK src=%s dst=%s from peer %s (%s)", + macaddr_str(mac_buf1, ra.srcMac), + macaddr_str(mac_buf2, ra.dstMac), + sock_to_cstr(sockbuf1, &sender), + sock_to_cstr(sockbuf2, orig_sender)); + + /* Move from pending_peers to known_peers; ignore if not in pending. */ + set_peer_operational(eee, ra.srcMac, &sender); + } + else if(msg_type == MSG_TYPE_REGISTER_SUPER_ACK) + { + n2n_REGISTER_SUPER_ACK_t ra; + + if(eee->sn_wait) + { + decode_REGISTER_SUPER_ACK(&ra, &cmn, udp_buf, &rem, &idx); + + if(ra.sock.family) + { + orig_sender = &(ra.sock); + } + + traceEvent(TRACE_NORMAL, "Rx REGISTER_SUPER_ACK myMAC=%s [%s] (external %s). Attempts %u", + macaddr_str(mac_buf1, ra.edgeMac), + sock_to_cstr(sockbuf1, &sender), + sock_to_cstr(sockbuf2, orig_sender), + (unsigned int)eee->sup_attempts); + + if(0 == memcmp(ra.cookie, eee->last_cookie, N2N_COOKIE_SIZE)) + { + if(ra.num_sn > 0) + { + traceEvent(TRACE_NORMAL, "Rx REGISTER_SUPER_ACK backup supernode at %s", + sock_to_cstr(sockbuf1, &(ra.sn_bak))); + } + + eee->last_sup = now; + eee->sn_wait=0; + eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; /* refresh because we got a response */ + + /* REVISIT: store sn_back */ + eee->register_lifetime = ra.lifetime; + eee->register_lifetime = MAX(eee->register_lifetime, REGISTER_SUPER_INTERVAL_MIN); + eee->register_lifetime = MIN(eee->register_lifetime, REGISTER_SUPER_INTERVAL_MAX); + } + else + { + traceEvent(TRACE_WARNING, "Rx REGISTER_SUPER_ACK with wrong or old cookie."); + } + } + else + { + traceEvent(TRACE_WARNING, "Rx REGISTER_SUPER_ACK with no outstanding REGISTER_SUPER."); + } + } + else + { + /* Not a known message type */ + traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored", (signed int)msg_type); + return; + } + } /* if (community match) */ + else + { + traceEvent(TRACE_WARNING, "Received packet with invalid community"); + } +} + +/* ************************************** */ + +int run_edge_loop(n2n_edge_t * eee) { + int keep_running=1; + size_t numPurged; + time_t lastIfaceCheck=0; + time_t lastTransop=0; + +#ifdef WIN32 + startTunReadThread(eee); +#endif + + /* Main loop + * + * select() is used to wait for input on either the TAP fd or the UDP/TCP + * socket. When input is present the data is read and processed by either + * readFromIPSocket() or readFromTAPSocket() + */ + + while(keep_running) { + int rc, max_sock = 0; + fd_set socket_mask; + struct timeval wait_time; + time_t nowTime; + + FD_ZERO(&socket_mask); + FD_SET(eee->udp_sock, &socket_mask); + FD_SET(eee->udp_mgmt_sock, &socket_mask); + max_sock = max(eee->udp_sock, eee->udp_mgmt_sock); +#ifndef WIN32 + FD_SET(eee->device.fd, &socket_mask); + max_sock = max(max_sock, eee->device.fd); +#endif + + wait_time.tv_sec = SOCKET_TIMEOUT_INTERVAL_SECS; wait_time.tv_usec = 0; + + rc = select(max_sock+1, &socket_mask, NULL, NULL, &wait_time); + nowTime=time(NULL); + + /* Make sure ciphers are updated before the packet is treated. */ + if((nowTime - lastTransop) > TRANSOP_TICK_INTERVAL) + { + lastTransop = nowTime; + + n2n_tick_transop(eee, nowTime); + } + + if(rc > 0) + { + /* Any or all of the FDs could have input; check them all. */ + + if(FD_ISSET(eee->udp_sock, &socket_mask)) + { + /* Read a cooked socket from the internet socket. Writes on the TAP + * socket. */ + readFromIPSocket(eee); + } + + if(FD_ISSET(eee->udp_mgmt_sock, &socket_mask)) + { + /* Read a cooked socket from the internet socket. Writes on the TAP + * socket. */ + readFromMgmtSocket(eee, &keep_running); + } + +#ifndef WIN32 + if(FD_ISSET(eee->device.fd, &socket_mask)) + { + /* Read an ethernet frame from the TAP socket. Write on the IP + * socket. */ + readFromTAPSocket(eee); + } +#endif + } + + /* Finished processing select data. */ + + + update_supernode_reg(eee, nowTime); + + numPurged = purge_expired_registrations(&(eee->known_peers)); + numPurged += purge_expired_registrations(&(eee->pending_peers)); + + if(numPurged > 0) { + traceEvent(TRACE_NORMAL, "Peer removed: pending=%u, operational=%u", + (unsigned int)peer_list_size(eee->pending_peers), + (unsigned int)peer_list_size(eee->known_peers)); + } + + if(eee->dyn_ip_mode && + ((nowTime - lastIfaceCheck) > IFACE_UPDATE_INTERVAL)) { + traceEvent(TRACE_NORMAL, "Re-checking dynamic IP address."); + tuntap_get_address(&(eee->device)); + lastIfaceCheck = nowTime; + } + } /* while */ + + send_deregister(eee, &(eee->supernode)); + + closesocket(eee->udp_sock); + tuntap_close(&(eee->device)); + + edge_term(eee); + + return(0); +} + +/* ************************************** */ + +/** Read in a key-schedule file, parse the lines and pass each line to the + * appropriate trans_op for parsing of key-data and adding key-schedule + * entries. The lookup table of time->trans_op is constructed such that + * encoding can be passed to the correct trans_op. The trans_op internal table + * will then determine the best SA for that trans_op from the key schedule to + * use for encoding. */ + +int edge_init_keyschedule(n2n_edge_t * eee) { +#define N2N_NUM_CIPHERSPECS 32 + + int retval = -1; + ssize_t numSpecs=0; + n2n_cipherspec_t specs[N2N_NUM_CIPHERSPECS]; + size_t i; + time_t now = time(NULL); + + numSpecs = n2n_read_keyfile(specs, N2N_NUM_CIPHERSPECS, eee->keyschedule); + + if(numSpecs > 0) + { + traceEvent(TRACE_NORMAL, "keyfile = %s read -> %d specs.\n", optarg, (signed int)numSpecs); + + for (i=0; i < (size_t)numSpecs; ++i) + { + int idx; + + idx = transop_enum_to_index(specs[i].t); + + switch (idx) + { + case N2N_TRANSOP_TF_IDX: + case N2N_TRANSOP_AESCBC_IDX: + { + retval = (eee->transop[idx].addspec)(&(eee->transop[idx]), + &(specs[i])); + break; + } + default: + retval = -1; + } + + if (0 != retval) + { + traceEvent(TRACE_ERROR, "keyschedule failed to add spec[%u] to transop[%d].\n", + (unsigned int)i, idx); + + return retval; + } + } + + n2n_tick_transop(eee, now); + } + else + { + traceEvent(TRACE_ERROR, "Failed to process '%s'", eee->keyschedule); + } + + return retval; +} + +/* ************************************** */ + +/** Deinitialise the edge and deallocate any owned memory. */ +void edge_term(n2n_edge_t * eee) { + if(eee->udp_sock >= 0) + closesocket(eee->udp_sock); + + if(eee->udp_mgmt_sock >= 0) + closesocket(eee->udp_mgmt_sock); + + clear_peer_list(&(eee->pending_peers)); + clear_peer_list(&(eee->known_peers)); + + (eee->transop[N2N_TRANSOP_TF_IDX].deinit)(&eee->transop[N2N_TRANSOP_TF_IDX]); + (eee->transop[N2N_TRANSOP_NULL_IDX].deinit)(&eee->transop[N2N_TRANSOP_NULL_IDX]); +} + +/* ************************************** */ + +int quick_edge_init(char *device_name, char *community_name, + char *encrypt_key, char *device_mac, + char *local_ip_address, + char *supernode_ip_address_port) { + n2n_edge_t eee; + + edge_init(&eee); + + if(tuntap_open(&(eee.device), device_name, "static", + local_ip_address, "255.255.255.0", + device_mac, DEFAULT_MTU) < 0) + return(-1); + + if(edge_init_twofish(&eee, (uint8_t *)encrypt_key, strlen(encrypt_key)) < 0) + return(-2); + + snprintf((char*)eee.community_name, sizeof(eee.community_name), "%s", community_name); + supernode2addr(&(eee.supernode), supernode_ip_address_port); + + eee.udp_sock = open_socket(0 /* any port */, 1 /* bind ANY */); + if(eee.udp_sock < 0) + return(-3); + + eee.udp_mgmt_sock = open_socket(0 /* any port */, 0 /* bind LOOPBACK */); + + if(eee.udp_mgmt_sock < 0) + return(-4); + + update_supernode_reg(&eee, time(NULL)); + + return(run_edge_loop(&eee)); +} diff --git a/n2n.h b/n2n.h index 8f80720..cf11c48 100644 --- a/n2n.h +++ b/n2n.h @@ -20,15 +20,15 @@ #define _N2N_H_ /* - tunctl -t tun0 - tunctl -t tun1 - ifconfig tun0 1.2.3.4 up - ifconfig tun1 1.2.3.5 up - ./edge -d tun0 -l 2000 -r 127.0.0.1:3000 -c hello - ./edge -d tun1 -l 3000 -r 127.0.0.1:2000 -c hello + tunctl -t tun0 + tunctl -t tun1 + ifconfig tun0 1.2.3.4 up + ifconfig tun1 1.2.3.5 up + ./edge -d tun0 -l 2000 -r 127.0.0.1:3000 -c hello + ./edge -d tun1 -l 3000 -r 127.0.0.1:2000 -c hello - tunctl -u UID -t tunX + tunctl -u UID -t tunX */ @@ -80,9 +80,9 @@ #define ETH_ADDR_LEN 6 struct ether_hdr { - uint8_t dhost[ETH_ADDR_LEN]; - uint8_t shost[ETH_ADDR_LEN]; - uint16_t type; /* higher layer protocol encapsulated */ + uint8_t dhost[ETH_ADDR_LEN]; + uint8_t shost[ETH_ADDR_LEN]; + uint16_t type; /* higher layer protocol encapsulated */ } __attribute__ ((__packed__)); typedef struct ether_hdr ether_hdr_t; @@ -94,6 +94,9 @@ typedef struct ether_hdr ether_hdr_t; #include #include #include +#include +#include +#include "minilzo.h" #define closesocket(a) close(a) #endif /* #ifndef WIN32 */ @@ -107,6 +110,7 @@ typedef struct ether_hdr ether_hdr_t; #endif /* #ifdef WIN32 */ #include "n2n_wire.h" +#include "n2n_transforms.h" /* N2N_IFNAMSIZ is needed on win32 even if dev_name is not used after declaration */ #define N2N_IFNAMSIZ 16 /* 15 chars * NULL */ @@ -150,16 +154,69 @@ typedef char ipstr_t[32]; typedef char macstr_t[N2N_MACSTR_SIZE]; struct peer_info { - struct peer_info * next; - n2n_community_t community_name; - n2n_mac_t mac_addr; - n2n_sock_t sock; - time_t last_seen; + struct peer_info * next; + n2n_community_t community_name; + n2n_mac_t mac_addr; + n2n_sock_t sock; + time_t last_seen; }; struct n2n_edge; /* defined in edge.c */ typedef struct n2n_edge n2n_edge_t; +#define N2N_EDGE_SN_HOST_SIZE 48 +#define N2N_EDGE_NUM_SUPERNODES 2 +#define N2N_EDGE_SUP_ATTEMPTS 3 /* Number of failed attmpts before moving on to next supernode. */ +#define N2N_PATHNAME_MAXLEN 256 +#define N2N_MAX_TRANSFORMS 16 +#define N2N_EDGE_MGMT_PORT 5644 + + +typedef char n2n_sn_name_t[N2N_EDGE_SN_HOST_SIZE]; + +struct n2n_edge { + int daemon; /**< Non-zero if edge should detach and run in the background. */ + uint8_t re_resolve_supernode_ip; + + n2n_sock_t supernode; + + size_t sn_idx; /**< Currently active supernode. */ + size_t sn_num; /**< Number of supernode addresses defined. */ + n2n_sn_name_t sn_ip_array[N2N_EDGE_NUM_SUPERNODES]; + int sn_wait; /**< Whether we are waiting for a supernode response. */ + + n2n_community_t community_name; /**< The community. 16 full octets. */ + char keyschedule[N2N_PATHNAME_MAXLEN]; + int null_transop; /**< Only allowed if no key sources defined. */ + + int udp_sock; + int udp_mgmt_sock; /**< socket for status info. */ + + tuntap_dev device; /**< All about the TUNTAP device */ + int dyn_ip_mode; /**< Interface IP address is dynamically allocated, eg. DHCP. */ + int allow_routing; /**< Accept packet no to interface address. */ + int drop_multicast; /**< Multicast ethernet addresses. */ + + n2n_trans_op_t transop[N2N_MAX_TRANSFORMS]; /* one for each transform at fixed positions */ + size_t tx_transop_idx; /**< The transop to use when encoding. */ + + struct peer_info * known_peers; /**< Edges we are connected to. */ + struct peer_info * pending_peers; /**< Edges we have tried to register with. */ + time_t last_register_req; /**< Check if time to re-register with super*/ + size_t register_lifetime; /**< Time distance after last_register_req at which to re-register. */ + time_t last_p2p; /**< Last time p2p traffic was received. */ + time_t last_sup; /**< Last time a packet arrived from supernode. */ + size_t sup_attempts; /**< Number of remaining attempts to this supernode. */ + n2n_cookie_t last_cookie; /**< Cookie sent in last REGISTER_SUPER. */ + + time_t start_time; /**< For calculating uptime */ + + /* Statistics */ + size_t tx_p2p; + size_t rx_p2p; + size_t tx_sup; + size_t rx_sup; +}; /* ************************************** */ @@ -234,4 +291,47 @@ size_t purge_expired_registrations( struct peer_info ** peer_list ); /* version.c */ extern char *n2n_sw_version, *n2n_sw_osName, *n2n_sw_buildDate; +/* egde_utils.c */ +int edge_init(n2n_edge_t * eee); +void supernode2addr(n2n_sock_t * sn, const n2n_sn_name_t addrIn); +void update_supernode_reg(n2n_edge_t * eee, time_t nowTime); +int is_empty_ip_address(const n2n_sock_t * sock); +void update_peer_address(n2n_edge_t * eee, + uint8_t from_supernode, + const n2n_mac_t mac, + const n2n_sock_t * peer, + time_t when); +int transop_enum_to_index(n2n_transform_t id); +int edge_init_keyschedule(n2n_edge_t * eee); +void update_peer_address(n2n_edge_t * eee, + uint8_t from_supernode, + const n2n_mac_t mac, + const n2n_sock_t * peer, + time_t when); +int is_empty_ip_address(const n2n_sock_t * sock); +void send_register(n2n_edge_t * eee, + const n2n_sock_t * remote_peer); +void send_packet2net(n2n_edge_t * eee, + uint8_t *tap_pkt, size_t len); +void check_peer(n2n_edge_t * eee, + uint8_t from_supernode, + const n2n_mac_t mac, + const n2n_sock_t * peer); +void try_send_register(n2n_edge_t * eee, + uint8_t from_supernode, + const n2n_mac_t mac, + const n2n_sock_t * peer); +void set_peer_operational(n2n_edge_t * eee, + const n2n_mac_t mac, + const n2n_sock_t * peer); +const char * supernode_ip(const n2n_edge_t * eee); +int edge_init_twofish(n2n_edge_t * eee, uint8_t *encrypt_pwd, + uint32_t encrypt_pwd_len); +int run_edge_loop(n2n_edge_t * eee); +void edge_term(n2n_edge_t * eee); +int quick_edge_init(char *device_name, char *community_name, + char *encrypt_key, char *device_mac, + char *local_ip_address, + char *supernode_ip_address_port); + #endif /* _N2N_H_ */ diff --git a/n2n_transforms.h b/n2n_transforms.h index 6702dae..3db6a83 100644 --- a/n2n_transforms.h +++ b/n2n_transforms.h @@ -37,10 +37,9 @@ struct n2n_trans_op; typedef struct n2n_trans_op n2n_trans_op_t; -struct n2n_tostat -{ - uint8_t can_tx; /* Does this transop have a valid SA for encoding. */ - n2n_cipherspec_t tx_spec; /* If can_tx, the spec used to encode. */ +struct n2n_tostat { + uint8_t can_tx; /* Does this transop have a valid SA for encoding. */ + n2n_cipherspec_t tx_spec; /* If can_tx, the spec used to encode. */ }; typedef struct n2n_tostat n2n_tostat_t; @@ -64,19 +63,18 @@ typedef int (*n2n_transform_f)( n2n_trans_op_t * arg, * to use to decode the packet content. The transform code then decodes the * packet and consults its internal key lookup. */ -struct n2n_trans_op -{ - void * priv; /* opaque data. Key schedule goes here. */ +struct n2n_trans_op { + void * priv; /* opaque data. Key schedule goes here. */ - n2n_transform_t transform_id; /* link header enum to a transform */ - size_t tx_cnt; - size_t rx_cnt; + n2n_transform_t transform_id; /* link header enum to a transform */ + size_t tx_cnt; + size_t rx_cnt; - n2n_transdeinit_f deinit; /* destructor function */ - n2n_transaddspec_f addspec; /* parse opaque data from a key schedule file. */ - n2n_transtick_f tick; /* periodic maintenance */ - n2n_transform_f fwd; /* encode a payload */ - n2n_transform_f rev; /* decode a payload */ + n2n_transdeinit_f deinit; /* destructor function */ + n2n_transaddspec_f addspec; /* parse opaque data from a key schedule file. */ + n2n_transtick_f tick; /* periodic maintenance */ + n2n_transform_f fwd; /* encode a payload */ + n2n_transform_f rev; /* decode a payload */ }; /* Setup a single twofish SA for single-key operation. */ From 27c10a1fb8f24ed11b0c361d32dfbb015fb7d6d7 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Fri, 8 Jun 2018 00:22:36 +0200 Subject: [PATCH 10/10] Fix for #6 --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 97ea344..24e9361 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,7 @@ endif(NOT DEFINED N2N_OPTION_AES) add_definitions(-DN2N_VERSION="${N2N_VERSION}" -DN2N_OSNAME="${N2N_OSNAME}") if(N2N_OPTION_AES) +find_package(OpenSSL REQUIRED) add_definitions(-DN2N_HAVE_AES) endif(N2N_OPTION_AES)