diff --git a/.gitignore b/.gitignore index 457d792..24fda82 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ CMakeFiles/ cmake_install.cmake benchmark benchmark_hashtable -doc/ +man/ edge gnutls/ libn2n.a @@ -15,3 +15,8 @@ test *.vcxproj.filters *.vcxproj.user ~$ +*.swp +*.swo +cscope.out +gmon.out +tags diff --git a/n2n_v2/CMakeLists.txt b/CMakeLists.txt similarity index 67% rename from n2n_v2/CMakeLists.txt rename to CMakeLists.txt index e46f231..e82d694 100644 --- a/n2n_v2/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,8 @@ project(n2n) cmake_minimum_required(VERSION 2.6) +include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/FindLibGcrypt.cmake) + # N2n information set(N2N_VERSION 2.1.0) set(N2N_OSNAME ${CMAKE_SYSTEM}) @@ -40,7 +42,7 @@ if(NOT WIN32) set(CMAKE_C_FLAGS "-Wall -Wshadow -Wpointer-arith -Wmissing-declarations -Wnested-externs -fPIC") set(CMAKE_CXX_FLAGS "-Wall -Wshadow -Wpointer-arith -Wmissing-declarations -Wnested-externs") # Debug -set(CMAKE_C_FLAGS_DEBUG "-g") +set(CMAKE_C_FLAGS_DEBUG "-g -Wno-deprecated-declarations") set(CMAKE_CXX_FLAGS_DEBUG "-g") # Release set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG") @@ -54,9 +56,22 @@ endif(NOT WIN32) #message(${N2N_OPTION_AES}) ## DEBUG FOR CMAKE +# install gnutls >= 2.99.0 in your system path or here +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/gnutls/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/libgcrypt/include) +link_directories(${CMAKE_CURRENT_SOURCE_DIR}/gnutls/lib) +link_directories(${CMAKE_CURRENT_SOURCE_DIR}/libgcrypt/lib) + +# libgcrypt +gcr_check(GCRYPT REQUIRED gcrypt) + add_library(n2n n2n.c n2n_keyfile.c wire.c + crypto/crypto.c + crypto/aes.c + crypto/ecdh.c + crypto/hmac.c minilzo.c twofish.c transform_null.c @@ -74,6 +89,8 @@ add_subdirectory(win32) target_link_libraries(n2n n2n_win32) endif(DEFINED WIN32) +target_link_libraries(n2n gnutls gcrypt) + if(N2N_OPTION_AES) target_link_libraries(n2n crypto) endif(N2N_OPTION_AES) @@ -82,7 +99,7 @@ endif(N2N_OPTION_AES) #target_link_libraries(n2n socket nsl) add_executable(edge edge.c) -target_link_libraries(edge n2n) +target_link_libraries(edge n2n gcrypt gnutls) add_executable(supernode sn.c) target_link_libraries(supernode n2n) @@ -104,37 +121,37 @@ install(TARGETS edge supernode # Documentation if(DEFINED UNIX) -add_dependencies(n2n doc) -file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/doc) -add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/edge.8.gz - COMMAND gzip -c ${PROJECT_SOURCE_DIR}/edge.8 > ${PROJECT_BINARY_DIR}/doc/edge.8.gz +add_dependencies(n2n man) +file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/man) +add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/man/edge.8.gz + COMMAND gzip -c ${PROJECT_SOURCE_DIR}/edge.8 > ${PROJECT_BINARY_DIR}/man/edge.8.gz DEPENDS ${PROJECT_SOURCE_DIR}/edge.8 ) -add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/supernode.1.gz - COMMAND gzip -c ${PROJECT_SOURCE_DIR}/supernode.1 > ${PROJECT_BINARY_DIR}/doc/supernode.1.gz +add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/man/supernode.1.gz + COMMAND gzip -c ${PROJECT_SOURCE_DIR}/supernode.1 > ${PROJECT_BINARY_DIR}/man/supernode.1.gz DEPENDS ${PROJECT_SOURCE_DIR}/supernode.1 ) -add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/n2n_v2.7.gz - COMMAND gzip -c ${PROJECT_SOURCE_DIR}/n2n_v2.7 > ${PROJECT_BINARY_DIR}/doc/n2n_v2.7.gz +add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/man/n2n_v2.7.gz + COMMAND gzip -c ${PROJECT_SOURCE_DIR}/n2n_v2.7 > ${PROJECT_BINARY_DIR}/man/n2n_v2.7.gz DEPENDS ${PROJECT_SOURCE_DIR}/n2n_v2.7 ) -add_custom_target(doc DEPENDS ${PROJECT_BINARY_DIR}/doc/edge.8.gz - ${PROJECT_BINARY_DIR}/doc/supernode.1.gz - ${PROJECT_BINARY_DIR}/doc/n2n_v2.7.gz +add_custom_target(man DEPENDS ${PROJECT_BINARY_DIR}/man/edge.8.gz + ${PROJECT_BINARY_DIR}/man/supernode.1.gz + ${PROJECT_BINARY_DIR}/man/n2n_v2.7.gz ) -set_source_files_properties(${PROJECT_BINARY_DIR}/doc/edge.8.gz - ${PROJECT_BINARY_DIR}/doc/supernode.1.gz - ${PROJECT_BINARY_DIR}/doc/n2n_v2.7.gz +set_source_files_properties(${PROJECT_BINARY_DIR}/man/edge.8.gz + ${PROJECT_BINARY_DIR}/man/supernode.1.gz + ${PROJECT_BINARY_DIR}/man/n2n_v2.7.gz PROPERTIES GENERATED 1) -install(FILES ${PROJECT_BINARY_DIR}/doc/edge.8.gz +install(FILES ${PROJECT_BINARY_DIR}/man/edge.8.gz DESTINATION /usr/share/man8) -install(FILES ${PROJECT_BINARY_DIR}/doc/supernode.1.gz +install(FILES ${PROJECT_BINARY_DIR}/man/supernode.1.gz DESTINATION /usr/share/man1) -install(FILES ${PROJECT_BINARY_DIR}/doc/n2n_v2.7.gz +install(FILES ${PROJECT_BINARY_DIR}/man/n2n_v2.7.gz DESTINATION /usr/share/man7) endif(DEFINED UNIX) diff --git a/n2n_v1/COPYING b/COPYING similarity index 100% rename from n2n_v1/COPYING rename to COPYING diff --git a/n2n_v2/HACKING b/HACKING similarity index 100% rename from n2n_v2/HACKING rename to HACKING diff --git a/n2n_v2/INSTALL b/INSTALL similarity index 90% rename from n2n_v2/INSTALL rename to INSTALL index 69ca5ac..c778794 100644 --- a/n2n_v2/INSTALL +++ b/INSTALL @@ -1,3 +1,7 @@ +Dependencies: +- libgcrypt >= 1.5 +- GnuTLS >= 3.0.1 (depends itself on nettle 2.2 at the time of writing) + New install procedure, using cmake. Customize CMakeLists.txt diff --git a/n2n_v2/NEW_FEATURES.txt b/NEW_FEATURES.txt similarity index 100% rename from n2n_v2/NEW_FEATURES.txt rename to NEW_FEATURES.txt diff --git a/README b/README index de6b8b9..14928d6 100644 --- a/README +++ b/README @@ -1,4 +1,12 @@ -This is a fork of the n2n p2p vpn software. http://www.ntop.org/n2n. +This is the current development branch of the n2n p2p vpn software. + +http://www.ntop.org/products/n2n/ + +It contains some modifications of the v2 version of n2n, which is the latest stable version +and should be used for productive environments. +All the current development happens in this repository in the new_protocol branch, which is +intended to be come version v3 of n2n and then merged back into the original svn repository +on ntop.org. Uses sglib http://sglib.sourceforge.net. diff --git a/n2n_v1/README b/README.n2n.orig similarity index 92% rename from n2n_v1/README rename to README.n2n.orig index e021f41..dd96501 100644 --- a/n2n_v1/README +++ b/README.n2n.orig @@ -3,7 +3,7 @@ Edge node --------- -You need to start an egde node on each host you want to connect with the *same* +You need to start an edge node on each host you want to connect with the *same* community. 0. become root @@ -53,7 +53,7 @@ safe if your host has only one login user. Running As a Daemon (UNIX) ------------------- -When given "-f" as a command line option, edge will call daemon(3) after +Unless given "-f" as a command line option, edge will call daemon(3) after successful setup. This causes the process to fork a child which closes stdin, stdout and stderr then sets itself as process group leader. When this is done, the edge command returns immediately and you will only see the edge process in @@ -64,7 +64,7 @@ returns non-zero then edge failed to start up for some reason. When edge starts running as a daemon, all logging goes to syslog daemon.info facility. -IPv6 Support (added r3650) +IPv6 Support ------------ n2n supports the carriage of IPv6 packets within the n2n tunnel. N2n does not @@ -91,5 +91,4 @@ Once the IPv6 addresses are configured and edge started, IPv6 neighbor discovery packets flow (get broadcast) and IPv6 entities self arrange. Test your IPv6 setup with ping6 - the IPv6 ping command. - -(C) 2007,2008 - Luca Deri , Richard Andrews +(C) 2007-2010 - Luca Deri , Richard Andrews diff --git a/benchmark.c b/benchmark.c new file mode 100644 index 0000000..cfe143f --- /dev/null +++ b/benchmark.c @@ -0,0 +1,117 @@ +#include "n2n_wire.h" +#include "n2n_transforms.h" +#include "n2n.h" + +#ifndef WIN32 +#include +#endif +#include +#include +#include + +uint8_t PKT_CONTENT[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15 }; + +/* Prototypes */ +static ssize_t do_encode_packet(uint8_t * pktbuf, size_t bufsize, + const n2n_community_t c); + +int main(int argc, char * argv[]) +{ + uint8_t pktbuf[N2N_PKT_BUF_SIZE]; + n2n_trans_op_t transop_null; + + /* n2n_common_t cmn; */ + /* n2n_PACKET_t pkt; */ + n2n_community_t c; + + struct timeval t1; + struct timeval t2; + + unsigned long int i; + size_t n; + /* size_t idx; */ + /* size_t rem; */ + ssize_t nw; + unsigned long int tdiff; + + transop_null_init(&transop_null); + memset(c, 0, sizeof(N2N_COMMUNITY_SIZE)); + + n = 10000; + memcpy(c, "abc123def456", 12); + + gettimeofday(&t1, NULL); + for (i = 0; i < n; ++i) { + nw = do_encode_packet(pktbuf, N2N_PKT_BUF_SIZE, c); + + nw += transop_null.fwd(&transop_null, pktbuf + nw, + N2N_PKT_BUF_SIZE - nw, PKT_CONTENT, sizeof(PKT_CONTENT)); + + /* idx = 0; */ + /* rem = nw; */ + + /* decode_common(&cmn, pktbuf, &rem, &idx); */ + /* decode_PACKET(&pkt, &cmn, pktbuf, &rem, &idx); */ + + if (0 == (i % 1000)) { + fprintf(stderr, "."); + } + } + gettimeofday(&t2, NULL); + + tdiff = ((t2.tv_sec - t1.tv_sec) * 1000000) + (t2.tv_usec - t1.tv_usec); + + fprintf(stderr, + "\nrun %lu times. (%lu -> %lu nsec each) %u.%06u -> %u.%06u.\n", i, + tdiff, (tdiff * 1000) / i, (uint32_t) t1.tv_sec, + (uint32_t) t1.tv_usec, (uint32_t) t2.tv_sec, (uint32_t) t2.tv_usec); + + return 0; +} + +static ssize_t do_encode_packet(uint8_t * pktbuf, size_t bufsize, + const n2n_community_t c) +{ + /* n2n_mac_t destMac={0,1,2,3,4,5}; */ + /* n2n_common_t cmn; */ + n2n_PACKET_t pkt; + size_t idx; + + /* 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, c, N2N_COMMUNITY_SIZE); */ + + memset(&pkt, 0, sizeof(pkt)); + + idx = 0; + /* encode_PACKET(pktbuf, &idx, &cmn, &pkt); */ + traceEvent(TRACE_DEBUG, "encoded PACKET header of size=%u", (unsigned int)idx); + + return idx; +} diff --git a/benchmark_hashtable.c b/benchmark_hashtable.c new file mode 100644 index 0000000..199ddcb --- /dev/null +++ b/benchmark_hashtable.c @@ -0,0 +1,25 @@ +#include "n2n_wire.h" +#include "n2n_transforms.h" +#include "n2n.h" + +#ifndef WIN32 +#include +#endif +#include +#include +#include + +int main(int argc, char** argv) { + peer_info_t* testpeers[PEER_HASH_TAB_SIZE]; + struct sglib_hashed_peer_info_t_iterator it; + peer_info_t *ll; + + sglib_hashed_peer_info_t_init(testpeers); + + for (ll = sglib_hashed_peer_info_t_it_init(&it, testpeers); ll != NULL; ll = + sglib_hashed_peer_info_t_it_next(&it)) { + sglib_hashed_peer_info_t_delete(testpeers, ll); + free(ll); + } + return 0; +} diff --git a/cmake/Modules/FindLibGcrypt.cmake b/cmake/Modules/FindLibGcrypt.cmake new file mode 100644 index 0000000..e5ba901 --- /dev/null +++ b/cmake/Modules/FindLibGcrypt.cmake @@ -0,0 +1,233 @@ +# - a gcrypt-config module for CMake +# +# Usage: +# gcrypt_check( [REQUIRED] ) +# checks if gcrypt is avialable +# +# When the 'REQUIRED' argument was set, macros will fail with an error +# when gcrypt could not be found. +# +# It sets the following variables: +# GCRYPT_CONFIG_FOUND ... true if libgcrypt-config works on the system +# GCRYPT_CONFIG_EXECUTABLE ... pathname of the libgcrypt-config program +# _FOUND ... set to 1 if libgcrypt exist +# _LIBRARIES ... the libraries +# _CFLAGS ... all required cflags +# _ALGORITHMS ... the algorithms that this libgcrypt supports +# _VERSION ... gcrypt's version +# +# Examples: +# gcrypt_check (GCRYPT gcrypt) +# Check if a version of gcrypt is available, issues a warning +# if not. +# +# gcrypt_check (GCRYPT REQUIRED gcrypt) +# Check if a version of gcrypt is available and fails +# if not. +# +# gcrypt_check (GCRYPT gcrypt>=1.4) +# requires at least version 1.4 of gcrypt and defines e.g. +# GCRYPT_VERSION=1.4.4. Issues a warning if a lower version +# is available only. +# +# gcrypt_check (GCRYPT REQUIRED gcrypt>=1.4.4) +# requires at least version 1.4.4 of gcrypt and fails if +# only gcrypt 1.4.3 or lower is available only. +# + +# Copyright (C) 2010 Werner Dittmann +# +# Redistribution and use, with or without modification, are permitted +# provided that the following conditions are met: +# +# 1. Redistributions must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# 2. The name of the author may not be used to endorse or promote +# products derived from this software without specific prior +# written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# This is a much edited and simplified variant of the original UsePkgConfig.cmake +# from Enrico Scholz +# Copyright (C) 2006 Enrico Scholz +# + +### Common stuff #### +set(GCR_CONFIG_VERSION 1) +set(GCR_CONFIG_FOUND 0) + +find_program(GCR_CONFIG_EXECUTABLE NAMES libgcrypt-config --version DOC "libgcrypt-config executable") +mark_as_advanced(GCR_CONFIG_EXECUTABLE) + +if(GCR_CONFIG_EXECUTABLE) + set(GCR_CONFIG_FOUND 1) +endif(GCR_CONFIG_EXECUTABLE) + + +# Unsets the given variables +macro(_gcrconfig_unset var) + set(${var} "" CACHE INTERNAL "") +endmacro(_gcrconfig_unset) + +macro(_gcrconfig_set var value) + set(${var} ${value} CACHE INTERNAL "") +endmacro(_gcrconfig_set) + +# Invokes libgcrypt-config, cleans up the result and sets variables +macro(_gcrconfig_invoke _gcrlist _prefix _varname _regexp) + set(_gcrconfig_invoke_result) + + execute_process( + COMMAND ${GCR_CONFIG_EXECUTABLE} ${ARGN} + OUTPUT_VARIABLE _gcrconfig_invoke_result + RESULT_VARIABLE _gcrconfig_failed) + + if (_gcrconfig_failed) + set(_gcrconfig_${_varname} "") + _gcrconfig_unset(${_prefix}_${_varname}) + else(_gcrconfig_failed) + string(REGEX REPLACE "[\r\n]" " " _gcrconfig_invoke_result "${_gcrconfig_invoke_result}") + string(REGEX REPLACE " +$" "" _gcrconfig_invoke_result "${_gcrconfig_invoke_result}") + + if (NOT ${_regexp} STREQUAL "") + string(REGEX REPLACE "${_regexp}" " " _gcrconfig_invoke_result "${_gcrconfig_invoke_result}") + endif(NOT ${_regexp} STREQUAL "") + + separate_arguments(_gcrconfig_invoke_result) + + #message(STATUS " ${_varname} ... ${_gcrconfig_invoke_result}") + set(_gcrconfig_${_varname} ${_gcrconfig_invoke_result}) + _gcrconfig_set(${_prefix}_${_varname} "${_gcrconfig_invoke_result}") + endif(_gcrconfig_failed) +endmacro(_gcrconfig_invoke) + +macro(_gcrconfig_invoke_dyn _gcrlist _prefix _varname cleanup_regexp) + _gcrconfig_invoke("${_gcrlist}" ${_prefix} ${_varname} "${cleanup_regexp}" ${ARGN}) +endmacro(_gcrconfig_invoke_dyn) + +# Splits given arguments into options and a package list +macro(_gcrconfig_parse_options _result _is_req) + set(${_is_req} 0) + + foreach(_gcr ${ARGN}) + if (_gcr STREQUAL "REQUIRED") + set(${_is_req} 1) + endif (_gcr STREQUAL "REQUIRED") + endforeach(_gcr ${ARGN}) + + set(${_result} ${ARGN}) + list(REMOVE_ITEM ${_result} "REQUIRED") +endmacro(_gcrconfig_parse_options) + +### +macro(_gcr_check_modules_internal _is_required _is_silent _prefix) + _gcrconfig_unset(${_prefix}_FOUND) + _gcrconfig_unset(${_prefix}_VERSION) + _gcrconfig_unset(${_prefix}_PREFIX) + _gcrconfig_unset(${_prefix}_LIBDIR) + _gcrconfig_unset(${_prefix}_LIBRARIES) + _gcrconfig_unset(${_prefix}_CFLAGS) + _gcrconfig_unset(${_prefix}_ALGORITHMS) + + # create a better addressable variable of the modules and calculate its size + set(_gcr_check_modules_list ${ARGN}) + list(LENGTH _gcr_check_modules_list _gcr_check_modules_cnt) + + if(GCR_CONFIG_EXECUTABLE) + # give out status message telling checked module + if (NOT ${_is_silent}) + message(STATUS "checking for module '${_gcr_check_modules_list}'") + endif(NOT ${_is_silent}) + + # iterate through module list and check whether they exist and match the required version + foreach (_gcr_check_modules_gcr ${_gcr_check_modules_list}) + + # check whether version is given + if (_gcr_check_modules_gcr MATCHES ".*(>=|=|<=).*") + string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\1" _gcr_check_modules_gcr_name "${_gcr_check_modules_gcr}") + string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\2" _gcr_check_modules_gcr_op "${_gcr_check_modules_gcr}") + string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\3" _gcr_check_modules_gcr_ver "${_gcr_check_modules_gcr}") + else(_gcr_check_modules_gcr MATCHES ".*(>=|=|<=).*") + set(_gcr_check_modules_gcr_name "${_gcr_check_modules_gcr}") + set(_gcr_check_modules_gcr_op) + set(_gcr_check_modules_gcr_ver) + endif(_gcr_check_modules_gcr MATCHES ".*(>=|=|<=).*") + + set(_gcr_check_prefix "${_prefix}") + + _gcrconfig_invoke(${_gcr_check_modules_gcr_name} "${_gcr_check_prefix}" VERSION "" --version ) +# _gcrconfig_invoke(${_gcr_check_modules_gcr_name} "${_gcr_check_prefix}" PREFIX "" --prefix ) + _gcrconfig_invoke(${_gcr_check_modules_gcr_name} "${_gcr_check_prefix}" LIBRARIES "" --libs ) + _gcrconfig_invoke(${_gcr_check_modules_gcr_name} "${_gcr_check_prefix}" CFLAGS "" --cflags ) + _gcrconfig_invoke(${_gcr_check_modules_gcr_name} "${_gcr_check_prefix}" ALGORITHMS "" --algorithms ) + + message(STATUS " found ${_gcr_check_modules_gcr}, version ${_gcrconfig_VERSION}") + # handle the operands + set(_gcr_wrong_version 0) + if (_gcr_check_modules_gcr_op STREQUAL ">=") + if((_gcr_check_modules_gcr_ver VERSION_EQUAL _gcrconfig_VERSION) OR + (_gcrconfig_VERSION VERSION_LESS _gcr_check_modules_gcr_ver )) + message(STATUS " gcrypt wrong version: required: ${_gcr_check_modules_gcr_op}${_gcr_check_modules_gcr_ver}, found: ${_gcrconfig_VERSION}") + set(_gcr_wrong_version 1) + endif() + endif(_gcr_check_modules_gcr_op STREQUAL ">=") + + if (_gcr_check_modules_gcr_op STREQUAL "=") + if(_gcr_check_modules_gcr_ver VERSION_EQUAL _gcrconfig_VERSION) + message(STATUS " gcrypt wrong version: required: ${_gcr_check_modules_gcr_op}${_gcr_check_modules_gcr_ver}, found: ${_gcrconfig_VERSION}") + set(_gcr_wrong_version 1) + endif() + endif(_gcr_check_modules_gcr_op STREQUAL "=") + + if (_gcr_check_modules_gcr_op STREQUAL "<=") + if((_gcr_check_modules_gcr_ver VERSION_EQUAL _gcrconfig_VERSION) OR + (_gcrconfig_VERSION VERSION_GREATER _gcr_check_modules_gcr_ver)) + message(STATUS " gcrypt wrong version: required: ${_gcr_check_modules_gcr_op}${_gcr_check_modules_gcr_ver}, found: ${_gcrconfig_VERSION}") + set(_gcr_wrong_version 1) + endif() + endif(_gcr_check_modules_gcr_op STREQUAL "<=") + if (${_is_required} AND _gcr_wrong_version) + message(FATAL_ERROR "") + endif() + + endforeach(_gcr_check_modules_gcr) + _gcrconfig_set(${_prefix}_FOUND 1) + + else(GCR_CONFIG_EXECUTABLE) + if (${_is_required}) + message(FATAL_ERROR "libgcrypt-config tool not found") + endif (${_is_required}) + endif(GCR_CONFIG_EXECUTABLE) +endmacro(_gcr_check_modules_internal) + +### +### User visible macro starts here +### + +### +macro(gcr_check _prefix _module0) + # check cached value + if (NOT DEFINED __gcr_config_checked_${_prefix} OR __gcr_config_checked_${_prefix} LESS ${GCR_CONFIG_VERSION} OR NOT ${_prefix}_FOUND) + _gcrconfig_parse_options (_gcr_modules _gcr_is_required "${_module0}" ${ARGN}) + _gcr_check_modules_internal("${_gcr_is_required}" 0 "${_prefix}" ${_gcr_modules}) + + _gcrconfig_set(__gcr_config_checked_${_prefix} ${GCR_CONFIG_VERSION}) + endif(NOT DEFINED __gcr_config_checked_${_prefix} OR __gcr_config_checked_${_prefix} LESS ${GCR_CONFIG_VERSION} OR NOT ${_prefix}_FOUND) +endmacro(gcr_check) + +### + +### Local Variables: +### mode: cmake +### End: diff --git a/crypto/aes.c b/crypto/aes.c new file mode 100644 index 0000000..8ba4e34 --- /dev/null +++ b/crypto/aes.c @@ -0,0 +1,128 @@ +#include +#include + +#include "../n2n.h" + +#include "aes.h" +#include "crypto.h" + +//TODO code real xmalloc function +#define xmalloc xmalloc_sec + +//TODO malloc check + +/* usage for AES session keys: + * derive_key(*dh_ss, dh_sslen, *from_spi, *to_spi, *salt_a, saltlen, + * "N2N AES-GCM 256 session key", algoidlen, + * NULL, 0, **sesskey_a, 32) */ +int aes_sa_create(sa_t *sa, void *sk, int sklen) +{ + CHECK_CRYPTO(); + gnutls_datum_t iv; + iv.size = AEAD_IV_SIZE; + + /* create IV */ + sa->salt = xmalloc_sec(sizeof(uint32_t)); + sa->counter = xmalloc_sec(sizeof(uint64_t)); + GTLS(gnutls_rnd(GNUTLS_RND_RANDOM, sa->salt, sizeof(uint32_t))); + GTLS(gnutls_rnd(GNUTLS_RND_RANDOM, sa->counter, sizeof(uint64_t))); + + iv.data = xmalloc_sec(AEAD_IV_SIZE); + memcpy(iv.data, sa->salt, 4); + memcpy(iv.data + 4, sa->salt, 8); + + GTLS(gnutls_cipher_init(&sa->ctx, GNUTLS_CIPHER_AES_256_GCM, sk, &iv)); + + gnutls_free(iv.data); + + return 0; +} + + +/* free security association */ +void aes_sa_destroy(sa_t *sa) +{ + gnutls_free(sa->salt); + gnutls_free(sa->counter); + free(sa); +} + + +/* Authenticated encryption with authenticated data. Return negative error code + * or size of encrypted text. + */ +int aes_authenc(sa_t *sa, void *pt, size_t pt_len, void *ad, size_t ad_len, + void *out, size_t out_len) +{ + CHECK_CRYPTO(); + uint8_t *ptr; + + if (out_len < AEAD_IV_SIZE + pt_len + AEAD_TAG_SIZE) + return GNUTLS_E_APPLICATION_ERROR_MIN; + + ptr = out; + + /* set new IV */ + sa->counter++; // increment IV + memcpy(out, sa->salt, 4); + memcpy(out, sa->counter, 8); + gnutls_cipher_set_iv(sa->ctx, out, AEAD_IV_SIZE); + ptr += AEAD_IV_SIZE; + + /* add associated data to be authenticated but not encrypted */ + GTLS(gnutls_cipher_add_auth(sa->ctx, ad, ad_len)); + + /* encrypt plaintext */ + GTLS(gnutls_cipher_encrypt2(sa->ctx, pt, pt_len, ptr, out_len - + AEAD_IV_SIZE - AEAD_TAG_SIZE)); + ptr += pt_len; + + /* get integrity check vector */ + uint8_t tag[AEAD_TAG_SIZE]; + GTLS(gnutls_cipher_tag(sa->ctx, tag, AEAD_TAG_SIZE)); + memcpy(ptr, tag, AEAD_TAG_SIZE); + ptr += AEAD_TAG_SIZE; + return (int) (ptr - (uint8_t *) out); +} + + +/* Authenticated decryption with authenticated data. Return negative error code + * or size of plaintext. On authentication failure no plaintext will be + * returned. + */ +int aes_authdec(sa_t *sa, void *in, size_t in_len, void *ad, size_t ad_len, + void *out, size_t out_len) +{ + CHECK_CRYPTO(); + uint8_t *ptr; + size_t ct_size; // size of encrypted text == size of plain text + uint8_t tag[AEAD_TAG_SIZE]; + + ct_size = in_len - AEAD_IV_SIZE - AEAD_TAG_SIZE; + if (in_len < AEAD_IV_SIZE + AEAD_TAG_SIZE || out_len < ct_size) + return GNUTLS_E_APPLICATION_ERROR_MIN; + + /* read IV */ + gnutls_cipher_set_iv(sa->ctx, in, AEAD_IV_SIZE); + ptr = (uint8_t *) in + AEAD_IV_SIZE; + + /* authenticate additional plain data */ + GTLS(gnutls_cipher_add_auth(sa->ctx, ad, ad_len)); + + /* decrypt */ + GTLS(gnutls_cipher_decrypt2(sa->ctx, ptr, ct_size, out, out_len)); + ptr += ct_size; + + /* get integrity check vector aka tag */ + GTLS(gnutls_cipher_tag(sa->ctx, tag, AEAD_TAG_SIZE)); + + /* compare tags */ + if (memcmp(ptr, tag, AEAD_TAG_SIZE)) { + traceEvent(TRACE_WARNING, "gnutls error: packet auth failed"); + /* make sure no information is returned */ + memset(in, 0, in_len); + memset(out, 0, out_len); + return GNUTLS_E_APPLICATION_ERROR_MAX; + } + return (int) ct_size; +} diff --git a/crypto/aes.h b/crypto/aes.h new file mode 100644 index 0000000..8990cb1 --- /dev/null +++ b/crypto/aes.h @@ -0,0 +1,16 @@ +#define AEAD_IV_SIZE 12 +#define AEAD_TAG_SIZE 16 + +/* security association: never ever manipulate this outside of aes.c */ +typedef struct { + uint32_t *salt; + uint64_t *counter; + gnutls_cipher_hd_t ctx; +} sa_t; + +int aes_sa_create(sa_t *sa, void *sk, int sklen); +void aes_sa_destroy(sa_t *sa); +int aes_authenc(sa_t *sa, void *pt, size_t pt_len, void *ad, size_t ad_len, + void *out, size_t out_len); +int aes_authdec(sa_t *sa, void *in, size_t in_len, void *ad, size_t ad_len, + void *out, size_t out_len); diff --git a/crypto/crypto.c b/crypto/crypto.c new file mode 100644 index 0000000..f15f49c --- /dev/null +++ b/crypto/crypto.c @@ -0,0 +1,226 @@ +#include +#include +#include +#include "../n2n.h" +#include "crypto.h" +#include "aes.h" +#include "hmac.h" + +#define GCRYPT_NO_DEPRECATED +#define DERIV_HASH_SIZE 48 +#define GCRYPT_MIN_VERION "1.5.0" + +int CRYPTO_INITIALIZED = 0; + +/* initialize global values for the cryptographic engine */ +int crypto_init(void) +{ + /* initialize libgcrypt (overriding gnutls' gcrypt initialization) */ + //TODO remove debug + GCRY(gcry_control(GCRYCTL_SET_VERBOSITY, GCRY_LOG_DEBUG)); + // use this at good places + GCRY(gcry_control(GCRYCTL_DUMP_RANDOM_STATS)); + GCRY(gcry_control(GCRYCTL_DUMP_MEMORY_STATS)); + GCRY(gcry_control(GCRYCTL_DUMP_SECMEM_STATS)); + //GCRY(gcry_control(GCRYCTL_SET_DEBUG_FLAGS, 0x03)); + //gcry_set_log_handler(log_handler, NULL); + + GCRY(gcry_control(GCRYCTL_ENABLE_M_GUARD)); + if (!gcry_check_version(GCRYPT_MIN_VERION)) { + traceEvent(TRACE_ERROR, "gcrypt init error"); + return -1; + } + GCRY(gcry_control(GCRYCTL_USE_SECURE_RNDPOOL)); + // allocate a pool of 16k secure memory + GCRY(gcry_control(GCRYCTL_INIT_SECMEM, 16384, 0)); + GCRY(gcry_control(GCRYCTL_SELFTEST)); + + /* Tell Libgcrypt that initialization has completed. */ + GCRY(gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0)); + + /* Import secure memory handling functions from libgcrypt into gnutls, + * since gnutls doesn't have any. + */ + gnutls_global_set_mem_functions(gcry_malloc, gcry_malloc_secure, + gcry_is_secure, gcry_realloc, gcry_free); + + /* initialize gnutls engine */ + GTLS(gnutls_global_init()); + + CRYPTO_INITIALIZED = 1; + return 0; +} + +/* call this in any case of program termination */ +void crypto_deinit(void) +{ + CRYPTO_INITIALIZED = 0; + /* this will zeroise all keys stored in secure memory */ + gcry_control(GCRYCTL_TERM_SECMEM, 0); + gnutls_global_deinit(); +} + +/* check the state of the crypto engine */ +int crypto_is_initialized(void) +{ + return CRYPTO_INITIALIZED; +} + +/* use this function to allocate secure memory */ +void *xmalloc_sec(size_t size) +{ + void *ptr = gnutls_secure_malloc(size); + if (ptr == NULL) { + traceEvent(TRACE_ERROR, "allocation of secure memory failed"); + /* calls crypto_deinit(), which will wipe the memory */ + //edge_deinit(); + //TODO; also: wrap malloc to exit function as well + crypto_deinit(); + exit(42); + } else { + return ptr; + } +} + + +/* usage for AES session keys: + * derive_key(*dh_ss, dh_sslen, *from_spi, *to_spi, *salt_a, saltlen, + * "N2N AES-GCM 256 session key", algoidlen, + * NULL, 0, **sesskey_a, 32) + * + * usage for HMAC authentication keys: + * derive_key(*masterkey, masterkeylen, *from_spi, *to_spi, *salt_a, saltlen, + * "N2N HMAC-SHA384 authentication key", algoidlen, + * NULL, 0, **hmackey_a, 48) + */ +/* concatenation key derivation function as in NIST SP 800-56A */ +int derive_key(const void *ss, size_t sslen, + uint32_t *from_spi, uint32_t *to_spi, + const void *salt, size_t saltlen, + const char *algoid, size_t algoidlen, + const void *other_ss, size_t other_sslen, + void **derived, size_t derivedlen) +{ + CHECK_CRYPTO(); + /* salt and ss should have a length of at least the digest size */ + if (saltlen < DERIV_HASH_SIZE || sslen < DERIV_HASH_SIZE) + return 2; + /* currently not supported, but could be done by completely implementing + * the kdf + */ + if (derivedlen > DERIV_HASH_SIZE) + return 3; + + uint8_t *input; // the text input buffer to the hash function + void *keymat; + size_t ptr = 0; + uint32_t counter = 1; + size_t counterlen = sizeof(uint32_t); + size_t spilen = sizeof(uint32_t); + + size_t inputlen = counterlen + sslen; + inputlen += algoidlen + (2 * spilen) + saltlen + other_sslen; + + input = xmalloc_sec(inputlen); + + /* hash(counter || shared_secret || otherinfo) */ + counter = htonl(counter); // must be big endian + memcpy(input + ptr, &counter, counterlen); + ptr += counterlen; + memcpy(input + ptr, ss, sslen); + ptr += sslen; + + /* otherinfo = algoid || partyu || partyv || suppubinfo || supprivinfo */ + memcpy(input + ptr, algoid, algoidlen); + ptr += algoidlen; + memcpy(input + ptr, from_spi, spilen); + ptr += spilen; + memcpy(input + ptr, to_spi, spilen); + ptr += spilen; + memcpy(input + ptr, salt, saltlen); + ptr += saltlen; + memcpy(input + ptr, other_ss, other_sslen); + + keymat = xmalloc_sec(DERIV_HASH_SIZE); + GTLS(gnutls_hash_fast(GNUTLS_DIG_SHA384, input, inputlen, keymat)); + gnutls_free(input); + + *derived = xmalloc_sec(derivedlen); + memcpy(*derived, keymat, derivedlen); + gnutls_free(keymat); + return 0; +} +//TODO make sure to gnutls_free() derived + +/* derive a session key from the shared secret 'ss' as source_key and the salt + * using a HMAC based key derivation function (RFC 5869): + * HKDF(salt, source_key, infostring, outlen) = K1 | K2 | ... | Kt + * prk = HMAC(salt, source_key) + * K1 = HMAC(prk, infostring | 0x01) + * K2 = HMAC(prk, K1 | infostring | 0x02) + * K3 = HMAC(prk, K2 | infostring | 0x03) ... + * This function could be used instead of the concatenation function. For the + * sake of Suite B compliance we will stick with concatenation for now. + */ +static int derive_key_rfc5869(const void **salt, size_t saltlen, + const void **ss, size_t sslen, void **derived, size_t derivedlen) +{ + CHECK_CRYPTO(); + /* salt and ss should have a length of at least the digest size */ + if (saltlen < DERIV_HASH_SIZE || sslen < DERIV_HASH_SIZE) + return 2; + /* currently not supported, but could be done by completely implementing + * rfc 5869 + */ + if (derivedlen > DERIV_HASH_SIZE) + return 3; + + /* data is optional and may be constant */ + int datalen = 29; + char data[] = "n2n edge aes-gcm session key "; + data[datalen - 1] = (uint8_t) 0x01; + + uint8_t *prk; + uint8_t *okm; + prk = xmalloc_sec(DERIV_HASH_SIZE); // pseudorandom key + okm = xmalloc_sec(DERIV_HASH_SIZE); // output key material + derived = xmalloc_sec(derivedlen); + + /* the salt is used as the key, the shared secret is used as data */ + GTLS(gnutls_hmac_fast(GNUTLS_MAC_SHA384, *salt, saltlen, *ss, sslen, prk)); + + GTLS(gnutls_hmac_fast(GNUTLS_MAC_SHA384, prk, DERIV_HASH_SIZE, data, + datalen, okm)); + + memcpy(*derived, okm, derivedlen); + gnutls_free(prk); + gnutls_free(okm); + return 0; +} + +//TODO make sure this is dealloc'd correctly +/* Generate a random number in secure memory. Use this for SPI generation. + * This will drain the entropy pool, use with care. + */ +int crypto_rnd(void **rnd, size_t len) +{ + CHECK_CRYPTO(); + + *rnd = xmalloc_sec(len); + GTLS(gnutls_rnd(GNUTLS_RND_RANDOM, *rnd, len)); + return 0; +} + +/* Hash the community name for transfer over wire. + * Returns zero or negative error code. + */ +int hash_community(char *name, size_t len, void *hashed) +{ + CHECK_CRYPTO(); + + uint8_t output[48]; + GTLS(gnutls_hash_fast(GNUTLS_DIG_SHA384, name, len, output)); + // the packet format uses 8 bytes of the community hash + memcpy(hashed, output, N2N_COMMUNITY_SIZE); + return 0; +} diff --git a/crypto/crypto.h b/crypto/crypto.h new file mode 100644 index 0000000..d555cb8 --- /dev/null +++ b/crypto/crypto.h @@ -0,0 +1,34 @@ +#include +#include + +#include "../n2n.h" + +void *xmalloc_sec(size_t size); + +int crypto_init(void); +int crypto_is_initialized(void); +void crypto_deinit(void); + +int crypto_set_key_p2p(void *key, size_t len); +int crypto_set_key_snode(void *key, size_t len); + +// random number service, use with caution +int crypto_rnd(void **rnd, size_t len); + +// hashes community name giving the first eight bytes +int hash_community(char *name, size_t len, void *hashed); + +/* internal stuff */ + +int derive_key(const void *ss, size_t sslen, + uint32_t *from_spi, uint32_t *to_spi, + const void *salt, size_t saltlen, + const char *algoid, size_t algoidlen, + const void *other_ss, size_t other_sslen, + void **derived, size_t derivedlen); + +#define GCRY(x) { gcry_error_t ret = (x); if (ret) { traceEvent(TRACE_ERROR, "gcrypt error %d:%s in %s on line %d\n", gcry_err_code(ret), gcry_strerror(ret), gcry_strsource(ret), __LINE__ ); return ret; } } + +#define GTLS(x) { int ret = (x) ; if (ret) { traceEvent(TRACE_ERROR, "gnutls error %s (code %d): %s", gnutls_strerror_name(ret), ret, gnutls_strerror(ret)); return ret; } } + +#define CHECK_CRYPTO() { if (crypto_is_initialized() == 0) { return GNUTLS_E_APPLICATION_ERROR_MIN; } } diff --git a/crypto/ecdh.c b/crypto/ecdh.c new file mode 100644 index 0000000..453df25 --- /dev/null +++ b/crypto/ecdh.c @@ -0,0 +1,164 @@ +#include + +#include "crypto.h" +#include "ecdh.h" + +// TODO compute test vector + +/* generate an ephemeral ecc key pair */ +int ecdh_init(void **keypair) +{ + CHECK_CRYPTO(); + /* don't just change the curve, it might have other implications */ + gcry_sexp_t key_parms; + GCRY(gcry_sexp_build(&key_parms, NULL, "(genkey (ecdh (curve \"NIST P-384\")))")); + + GCRY(gcry_pk_genkey(*keypair, key_parms)); + + gcry_sexp_release(key_parms); + return 0; +} + +/* Export an ephemeral public key for ECDH. Send this over the wire immediately + * after export and free() it. Returns a negative error code or the length of + * the public key. + */ +int ecdh_export(void *keypair, void **ephemeral_public_key) +{ + CHECK_CRYPTO(); + gcry_sexp_t pubkey; + gcry_sexp_t sexp_q; + gcry_mpi_t mpi_q; + size_t n; + keypair = (gcry_sexp_t *) keypair; + + /* extract public key represented by point Q */ + pubkey = gcry_sexp_find_token(keypair, "public-key", 0); + sexp_q = gcry_sexp_find_token(pubkey, "q", 0); + + /* convert it to mpi for export */ + mpi_q = gcry_sexp_nth_mpi(sexp_q, 1, GCRYMPI_FMT_USG); + + n = (mpi_get_nbits(mpi_q) + 7) / 8; + *ephemeral_public_key = malloc(n); + + GCRY(gcry_mpi_print(GCRYMPI_FMT_USG, *ephemeral_public_key, n, &n, mpi_q)); + + gcry_sexp_release(pubkey); + gcry_sexp_release(sexp_q); + gcry_mpi_release(mpi_q); + return n; +} +// TODO make sure ephemeral_public_key is free() + +static void printhex(void *h, int len) +{ + int i; + unsigned char *val = (unsigned char *) h; + printf("hex value:\n"); + for (i = 0; i < len; i++) + printf("%02X", val[i]); + printf("\n"); +} + +/* Extract the x coordinate (= shared secret) of the shared point. This closely + * follows the gnupg and gcrypt ecc code. + * Returns a negative error code or the size of the shared secret. + */ +static int extract_x(gcry_mpi_t *shared_point, void **shared_secret) +{ + CHECK_CRYPTO(); + size_t mpi_size; + size_t x_size; + unsigned char *buf; + + /* size of a point with two coordinates */ + mpi_size = (gcry_mpi_get_nbits(*shared_point) + 7) / 8; + + /* get shared point */ + buf = xmalloc_sec(mpi_size); + GCRY(gcry_mpi_print(GCRYMPI_FMT_USG, buf, mpi_size, &mpi_size, + *shared_point)); + + /* size of one coordinate */ + x_size = (mpi_size - 1) / 2; + + /* cut off first byte and throw away tail with y component */ + memcpy(*shared_secret, buf + 1, x_size); + + gnutls_free(buf); + return x_size; +} + +//TODO gnutls_free(shared secret), caller must free() epubkey herself +/* Return a negative error code or the size of the shared secret + */ +int ecdh_receive_deinit(void **keypair, void *epubkey, void **shared_secret) +{ + CHECK_CRYPTO(); + gcry_sexp_t pubkey; + gcry_sexp_t value_d; // prepared secret value + int sslen; + + /* build public key */ + GCRY(gcry_sexp_build(&pubkey, 0, + "(public-key (ecdh (q %m) (curve \"NIST P-384\")))", + *(gcry_mpi_t *) epubkey)); + + /* extract private scalar d */ + { + gcry_sexp_t privkey; + gcry_sexp_t sexp_d; + gcry_mpi_t mpi_d; + + privkey = gcry_sexp_find_token(**(gcry_sexp_t **) keypair, + "private-key", 0); + sexp_d = gcry_sexp_find_token(privkey, "d", 0); + mpi_d = gcry_sexp_nth_mpi(sexp_d, 1, GCRYMPI_FMT_USG); + + /* prepare d for computation */ + GCRY(gcry_sexp_build(&value_d, 0, "(data (value %m))", mpi_d)); + + gcry_sexp_release(privkey); + gcry_sexp_release(sexp_d); + gcry_mpi_release(mpi_d); + } + + { + gcry_mpi_t mpi_s; + { + gcry_sexp_t enc; + gcry_sexp_t sexp_s; + /* encrypt our private key d with the other party's public key */ + GCRY(gcry_pk_encrypt(&enc, value_d, pubkey)); + + /* extract shared point s */ + sexp_s = gcry_sexp_find_token(enc, "s", 0 ); + mpi_s = gcry_sexp_nth_mpi(sexp_s, 1, GCRYMPI_FMT_USG); + + gcry_sexp_release(enc); + gcry_sexp_release(sexp_s); + } + + { + /* extract x coordinate of point: this is our shared secret */ + size_t n; + n = (((gcry_mpi_get_nbits(mpi_s) + 7) / 8) - 1) / 2; + *shared_secret = xmalloc_sec(n); + sslen = extract_x(&mpi_s, shared_secret); + if (sslen < 0) + return GPG_ERR_GENERAL; + } + gcry_mpi_release(mpi_s); + } + + //TODO remove debug + printf("shared secret:"); + printhex(*shared_secret, sslen); + + // wipe all byproducts of shared secret + gcry_sexp_release(pubkey); + gcry_sexp_release(value_d); + gcry_sexp_release(**(gcry_sexp_t **) keypair); + return sslen; +} diff --git a/crypto/ecdh.h b/crypto/ecdh.h new file mode 100644 index 0000000..54dc988 --- /dev/null +++ b/crypto/ecdh.h @@ -0,0 +1,3 @@ +int ecdh_init(void **keypair); +int ecdh_export(void *keypair, void **ephemeral_public_key); +int ecdh_receive_deinit(void **keypair, void *epubkey, void **shared_secret); diff --git a/crypto/hmac.c b/crypto/hmac.c new file mode 100644 index 0000000..da3bfb3 --- /dev/null +++ b/crypto/hmac.c @@ -0,0 +1,104 @@ +#include "crypto.h" +#include "hmac.h" + +#define MASTER_KEY_SIZE 48 +#define HMAC_SIZE 48 + +gnutls_datum_t *master_key_p2p; +gnutls_datum_t *master_key_snode; + +/* Set symmetric master key; use snode = 1 for supernode or snode = 0 for p2p + * key. + * There is no deinit routine, since it does not make sense to run the program + * without master keys. Use crypto_deinit() to wipe the keys. + */ +int hmac_set_key(void *key, size_t len, uint8_t snode) +{ + CHECK_CRYPTO(); + gnutls_datum_t *mkey; + if (snode) { + mkey = master_key_snode; + } else { + mkey = master_key_p2p; + } + if (mkey->size > 0 || len != MASTER_KEY_SIZE) + return GNUTLS_E_APPLICATION_ERROR_MIN; + mkey->data = xmalloc_sec(len); + memcpy(mkey->data, key, len); + mkey->size = len; + return 0; +} + +/* Pick a salt, derive special key, authenticate the data. This function + * writes the salt before the MAC tag itself. + * Returns negative error code or length of allocated salt + digest value. + * */ +int hmac_auth_tag(void *ad, size_t adlen, uint32_t *spi_from, uint32_t *spi_to, + void **digest, uint8_t snode) +{ + CHECK_CRYPTO(); + gnutls_datum_t *key; + void **mac_key = NULL; + // HMAC tag size is also used as salt size + int size = HMAC_SIZE * 2; // salt and MAC tag + + /* find out which symmetric key to use for derivation */ + if (snode) { + key = master_key_snode; + } else { + key = master_key_p2p; + } + if (key->size != MASTER_KEY_SIZE) + return GNUTLS_E_APPLICATION_ERROR_MIN; + + /* create salt */ + *digest = malloc(size); + GTLS(gnutls_rnd(GNUTLS_RND_RANDOM, *digest, HMAC_SIZE)); + + /* derive a salted key from the master key */ + GTLS(derive_key(key->data, key->size, spi_from, spi_to, *digest, HMAC_SIZE, + "N2N HMAC-SHA384 authentication key", 34, NULL, 0, mac_key, + HMAC_SIZE)); + + /* compute mac over authentication data */ + GTLS(gnutls_hmac_fast(GNUTLS_MAC_SHA384, *mac_key, HMAC_SIZE, ad, adlen, + (uint8_t *) *digest + HMAC_SIZE)); + gnutls_free(*mac_key); + return size; +} +//TODO make sure to free() digest + +/* Returns size of successfully authenticated data or a negative error code. + */ +int hmac_auth_verify(void *ad, size_t adlen, uint32_t *spi_from, + uint32_t *spi_to, void *salt, uint8_t snode, void *digest) +{ + CHECK_CRYPTO(); + gnutls_datum_t *key; + void **mac_key = NULL; + uint8_t computed_digest[HMAC_SIZE]; + + /* find out which symmetric key to use for derivation */ + if (snode) { + key = master_key_snode; + } else { + key = master_key_p2p; + } + if (key->size != MASTER_KEY_SIZE) + return GNUTLS_E_APPLICATION_ERROR_MIN; + + /* derive a salted key from the master key; salt size = HMAC tag size */ + GTLS(derive_key(key->data, key->size, spi_from, spi_to, salt, HMAC_SIZE, + "N2N HMAC-SHA384 authentication key", 34, NULL, 0, mac_key, + HMAC_SIZE)); + + GTLS(gnutls_hmac_fast(GNUTLS_MAC_SHA384, *mac_key, HMAC_SIZE, ad, adlen, + computed_digest)); + gnutls_free(*mac_key); + + if (memcmp(computed_digest, digest, HMAC_SIZE)) { + return GNUTLS_E_APPLICATION_ERROR_MAX; + } else { + return adlen; + } +} diff --git a/crypto/hmac.h b/crypto/hmac.h new file mode 100644 index 0000000..a146f1e --- /dev/null +++ b/crypto/hmac.h @@ -0,0 +1,6 @@ + +int hmac_set_key(void *key, size_t len, uint8_t snode); +int hmac_auth_tag(void *ad, size_t adlen, uint32_t *spi_from, uint32_t *spi_to, + void **digest, uint8_t snode); +int hmac_auth_verify(void *ad, size_t adlen, uint32_t *spi_from, + uint32_t *spi_to, void *salt, uint8_t snode, void *digest); diff --git a/n2n_v1/debian/README.Debian b/debian/README.Debian similarity index 100% rename from n2n_v1/debian/README.Debian rename to debian/README.Debian diff --git a/n2n_v2/debian/changelog b/debian/changelog similarity index 100% rename from n2n_v2/debian/changelog rename to debian/changelog diff --git a/n2n_v1/debian/compat b/debian/compat similarity index 100% rename from n2n_v1/debian/compat rename to debian/compat diff --git a/n2n_v2/debian/control b/debian/control similarity index 100% rename from n2n_v2/debian/control rename to debian/control diff --git a/n2n_v1/debian/copyright b/debian/copyright similarity index 100% rename from n2n_v1/debian/copyright rename to debian/copyright diff --git a/n2n_v2/debian/n2n-edge.default b/debian/n2n-edge.default similarity index 100% rename from n2n_v2/debian/n2n-edge.default rename to debian/n2n-edge.default diff --git a/n2n_v2/debian/n2n-edge.docs b/debian/n2n-edge.docs similarity index 100% rename from n2n_v2/debian/n2n-edge.docs rename to debian/n2n-edge.docs diff --git a/n2n_v2/debian/n2n-edge.init b/debian/n2n-edge.init similarity index 100% rename from n2n_v2/debian/n2n-edge.init rename to debian/n2n-edge.init diff --git a/n2n_v2/debian/n2n-edge.install b/debian/n2n-edge.install similarity index 100% rename from n2n_v2/debian/n2n-edge.install rename to debian/n2n-edge.install diff --git a/n2n_v2/debian/n2n-edge.manpages b/debian/n2n-edge.manpages similarity index 100% rename from n2n_v2/debian/n2n-edge.manpages rename to debian/n2n-edge.manpages diff --git a/n2n_v2/debian/n2n-supernode.init b/debian/n2n-supernode.init similarity index 100% rename from n2n_v2/debian/n2n-supernode.init rename to debian/n2n-supernode.init diff --git a/n2n_v2/debian/n2n-supernode.install b/debian/n2n-supernode.install similarity index 100% rename from n2n_v2/debian/n2n-supernode.install rename to debian/n2n-supernode.install diff --git a/n2n_v2/debian/n2n-supernode.manpages b/debian/n2n-supernode.manpages similarity index 100% rename from n2n_v2/debian/n2n-supernode.manpages rename to debian/n2n-supernode.manpages diff --git a/n2n_v2/debian/rules b/debian/rules similarity index 100% rename from n2n_v2/debian/rules rename to debian/rules diff --git a/doc/CRYPTO b/doc/CRYPTO new file mode 100644 index 0000000..565bcfa --- /dev/null +++ b/doc/CRYPTO @@ -0,0 +1,174 @@ +crypto protocol v0.0.1 + +Does gcrypt free() zeroize? +play through attacks + +master key +========== + +- two symmetric 384 bit highest quality keys +- user documentation should recommend to change it at least once a year + + +HMAC for handshake packets +========================== + +Derive key with NIST concat KDF from master key with: +otherInfo = AlgoID || sender_SPI || receiver_SPI || MAC_SALT +sharedSecret = symmetric master key + +The authentication tag will be truncated to 24 bytes (RFC 2104, 4868). + +The MAC_SALT as supplementary public information will be arbitrarily chosen +as a random value 48 bytes length. + +TODO: Should we really truncate the MAC tag? + + +Key negotiation +=============== + +ECDH. Look for implementations. + +Diffie-Hellman secured with long term key +see key mgmt recommendations +DH support in: +- Gnutls has DH support, but only inside the TLS layer [dh algo?] +- http://cr.yp.to/ecdh.html (ecc, seems good and simple, but not NSA Suite B) +- heimdal (not yet evaluated) +- http://point-at-infinity.org/seccure/ (seems ok) +- polarssl/tropicssl (seems simple) +- gnupg/g10 secp384r1/P-384 (not accessible) + + +Session key derivation +====================== + +NIST concatenation KDF (demanded for Suite B): +OtherInfo = AlgorithmID || PartyUInfo || PartyVInfo {|| SuppPubInfo }{|| SuppPrivInfo } +Compute Hash_i = H(counter || sharedSecret || OtherInfo). +DerivedKeyingMaterial = Hash_1 || Hash_2 || ... + +TODO: Should the master key really go into the KDF of the session key? + +This well designed KDF could be used instead: +HMAC based key derivation function ("HKDF", RFC 5869) is specifically designed +to derive symmetric keys from negotiated shared secrets as in Diffie-Hellman. + +HKDF(salt, source_key, infostring, outlen) = K1 | K2 | ... | Kt + prk = HMAC(salt, source_key) // (sic!) + K1 = HMAC(prk, infostring | 0x01) + K2 = HMAC(prk, K1 | infostring | 0x02) + K3 = HMAC(prk, K2 | infostring | 0x03) ... + +inputs: salt, source key material, infostring +- salt will be a chosen random value of length 48B +- soure key material: the DH shared secret, shall be at least 48B +- infostring will be a n2n specific constant +output: a session key + + +IV choice +========= + +The choice of the IV is of the utmost importance, since the security of GCM +depends on NO IV being used MORE THAN ONCE with the same key. + +GCM in IPsec ESP (RFC 4106): +4B salt: unpredictable but constant for SA lifetime +8B IV: LFSR or counter [garantee uniqueness] + +We choose an IV correspondingly, keep it secret until it is used and store it +with the other security association information. + + +Packet format +============= + +We choose the encrypting and authenticating AES GCM mode for performance +security. gcm 256 is not implemented in gnutls (but it is in nettle), so we use +128 bit. + +to consider: +- which fields to authenticate with GCM, but not encrypt (e.g. MAC addr) +- pad authentication data / plain text to block size? + [according to nettle spec this is not needed, we might do it anyway on the + plain text to make statistical analysis more difficult] +- security association explicit in packet? + +planned payload AES GCM 128 bit: +?B crypto protocol version [authenticated] +12B IV +---enc--- + ?B plaintext + ?B padding (counting up from 1) + 1B padding length 0-255 +-enc end- +16B ICV + + +Security Analysis +================= + +TODO + +The security is based on a shared secret key, which requires that all +communicating parties trust each other. + +security level NSA Suite B 192 bit: +ECDH P-384, AES GSM 256, SHA 384 + +Not protecting against: +- replay [TODO: consequences?; replay protection like dtls?] +- active MITM with key + + +References +========== + +NSA Suite B +http://www.nsa.gov/ia/programs/suiteb_cryptography/ + +NIST Key management recommendations +http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57-Part1-revised2_Mar08-2007.pdf p. 63 + +The Order of Encryption and Authentication for Protecting Communications +http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.106.5488&rep=rep1&type=pdf +(authenticate then encrypt vs encrypt then authenticate discussion) + +GCM spec/proposal, http://www.cryptobarn.com/gcm/ +http://www.cryptobarn.com/papers/gcm-spec.pdf + +NIST GCM spec +http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf + +Cryptolounge GCM +http://www.cryptolounge.org/wiki/GCM + +HMAC: Keyed-Hashing for Message Authentication +http://tools.ietf.org/html/rfc2104 + +The Use of Galois/Counter Mode (GCM) in IPsec Encapsulating Security Payload (ESP) +http://tools.ietf.org/html/rfc4106 + +The Use of Galois Message Authentication Code (GMAC) in IPsec ESP and AH +http://tools.ietf.org/html/rfc4543 + +Suite B Cryptographic Suites for IPsec +http://tools.ietf.org/html/rfc4869 + +An Interface and Algorithms for Authenticated Encryption +http://tools.ietf.org/html/rfc5116 + +The Transport Layer Security (TLS) Protocol Version 1.2 +http://tools.ietf.org/html/rfc5246 Section 6.2.3.2 + +AES Galois Counter Mode for the Secure Shell Transport Layer Protocol +http://tools.ietf.org/html/rfc5647 + +On Extract-then-Expand Key Derivation Functions and an HMAC-based KDF (HKDF) +http://webee.technion.ac.il/~hugo/kdf/ +http://tools.ietf.org/html/rfc5869 + +US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF) +http://tools.ietf.org/html/rfc6234 diff --git a/doc/SPEC.CRYPTO b/doc/SPEC.CRYPTO new file mode 100644 index 0000000..2d5d6c0 --- /dev/null +++ b/doc/SPEC.CRYPTO @@ -0,0 +1,147 @@ +general remarks +=============== + +Not yet specified, but very important: +- replay protection MUST be addressed [see end of file] + +Authenticated fields will be tagged [A], encrypted fields with [E]. Payload +data must never be sent unauthenticated or unencrypted. +User supplied data must never be sent to the supernode, with the exception of +network address like data such as the community name or IP and MAC addresses +in use by edge. + +Lengths are noted in octets, unless specified otherwise. "_" denotes a variable +length, which may be zero. "?" means not yet specified. + +A description of allowed packet formats follows. + +Other cryptographic protocol considerations will be discussed afterwards. + + +pre-handshake +============= + +SPI negotiation: replay protection, liveliness + + len + 4 ZERO (special SPI = 0 denotes non-payload packet) + 4 header + 8 community + 4 SPI (Destination) + 4 SPI (Source) + +SPI (Source) is chosen by the sender. The sender expects the receiver to use +the SPI (Source) value as identifier for all future packets. If the +SPI the receiver expects is known, it will be put in the SPI (Destination) +field. Otherwise this will be zero. + +The same packet is used in both directions (on return with the ACK-Flag set in +the header). + +This packet type does not need to be authenticated. + + +handshake +========= + +SPI is the security parameter index, a nonce chosen by sender to identify the +(unidirectional) security association. + + len + 4 ZERO (special SPI = 0 denotes non-payload packet) +[A] 4 header +[A] 4 SPI +[A] ? ECDH ephemeral public key +[A] 48 AEAD_KDF_SALT + 48 HMAC_KDF_SALT + 24 HMAC_TAG + +The SPI is the target expects for packets is already known at this point. +The KDF_SALT is a chosen random value used to salt the key derivation. +HMAC values will be computed using a key derived from the corresponding +symmetric master key. + +Because session keys are unidirectional, KDF_SALT must be chosen randomly by +each party. + +The same packet is used in both directions (on return with the ACK-Flag set in +the header) + +after the handshake: +Both parties compute the session keys using the ephemeral public keys, the key +derivation function and the KDF_SALT. These session keys form the security +associations (SA) identified by the SPI. + + +payload packet +============== + +A session key must be established beforehand by performing a handshake. This +key is used for the authenticating and encrypting cipher AEAD, which can also +authenticate (but not encrypt) additional data. + + len + 4 SPI + 12 AEAD_IV +[AE] _ payload + 16 AEAD_ICV + +The SPI is constant for the life time of the negotiated session key. +The AEAD_IV values must be chosen according to the specification found in +CRYPTO. They must be stored with the SA. + +Note that in contrast to the rest of the header, the IV and SPI need not be +authenticated since authentication will fail, if either of them are +manipulated. + +AEAD_ICV is the integrity check vector that authenticates the encrypted and +additionally authenticated data. + + + +hole punch packet +================= + +No data, no authentication. + + len + 4 ZERO (special SPI = 0 denotes non-payload packet) + 4 header [holepunch] + + +other goals +=========== + +Rekeying: +No explicit rekeying is supported. A new session (and thereby a new session key +must be established every 24 hours, plus a random interval to avoid +simultaneous session establishment. New keys are generated every time a +connection timed out and is reestablished. +Any rekeying whatsoever must be protected effectively with the symmetric master +secret key (i.e. not a session key). + +Traffic flow confidentiality: +Resistance against statistical analysis is difficult. For very limited +protection we could easily adopt a max. 255 Byte padding. Inside the encrypted +payload a TFC protocol header could direct sophisticated TFC algorithms in the +future. + +community name: +The community name will be hashed statically. Although it will not be visible +in plain text, user documentation must say that it will not be considered and +treated as confidential. + +!! DoS of supernode: +The short handshake makes the usual DoS protections against e.g. replay attacks +not feasable. This warrants further study. + +!! Replay protection: +The encrypted channel with the supernode must be protected against replay +attacks. Other channels could be protected as well (mostly relevant for UDP +traffic). + + + +further research to do +====================== +- hole punch packet type and security implications diff --git a/doc/SPEC.DECODING b/doc/SPEC.DECODING new file mode 100644 index 0000000..b63ab40 --- /dev/null +++ b/doc/SPEC.DECODING @@ -0,0 +1,86 @@ +EDGE +==== + +Read first four byte to Integer SPI + +SPI == 0: //special SPI; this is a non-payload packet + Parse header, check version (if wrong: discard) + switch(packet type) + pre-handshake: + discard (this is handled separatly on startup) + handshake: + HMAC check (if wrong: discard) + find_peer_by_spi (if not present: discard) + perform DH operation, save key + send handshake ack + set_peer_ready + handshake ack: + HMAC check (if wrong: discard) + find_peer_by_spi (if not present: discard) + perform DH operation, save key + set_peer_ready + holepunch packet: + discard + +SPI != 0: //this is a payload packet + find peer P associated with SPI (if not present: discard) + check and decrypt payload to PL (if failed: discard) + if SPI == supernode: + parse SN_HEADER, check version (if bad: discard) + switch(packet type) + supernode-register: + discard (this is handled separatly on startup) + keep-alive: + discard + address-resolution: + check ack flag (else:discard) + assemble reply to arp request, hand to tap interface + edge-connect: + save node information + if ack flag: + send handshake + else: + save node information + edge-resume: + find node by mac + check node information, update if necessary + send holepunch packet + if SPI != SUPERNODE: + assemble ethernet frame with payload PL + hand over to tap device + + +SUPERNODE +========= + +1. Read first four byte to Integer SPI +SPI == NULL: + Parse header, check version + switch(packet type): + pre-handshake: + if ack: discard + allocate new spi + send pre-hanshake ack + handshake: + if ack: discard + HMAC check (if wrong: discard) + find_peer_by_spi (if not present: discard) + perform DH operation, save key + send handshake ack + holepunch: + discard +SPI != NULL: + find peer P associated with SPI (else: discard) + check (throw away if bad) & decrypt payload to PL + decode SN_HEADER + switch(packet type): + supernode-register: + if ack: discard + save client infos + send supernode-register ack + address-resolution: + if ack: discard + lookup mac + send address-resolution ack + default: (keep-alive, edge-connect, edge-resume) + discard diff --git a/doc/SPEC.FORMATS b/doc/SPEC.FORMATS new file mode 100644 index 0000000..f8e85ca --- /dev/null +++ b/doc/SPEC.FORMATS @@ -0,0 +1,26 @@ +HEADER: + +The header is sent for all non-payload packets after 4 ZERO-bytes + + 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 + +---------------+---------------+---------------+---------------+ + 0 ! Version ! Packet Type ! Flags ! + +---------------+---------------+---------------+---------------+ + +Packet Types: pre-handshake, handshake, holepunch +Flags: ACK (acknowledge) + +SN_HEADER: + +the SN header is sent for all payload packets going to or coming from the +supernode + + 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 + +---------------+---------------+---------------+---------------+ + 0 ! Version ! Packet Type ! Flags ! + +---------------+---------------+---------------+---------------+ + +Packet Types: supernode-register, keep-alive, address-resolution, + edge-connect, edge-resume +Flags: ACK (acknowledge) + diff --git a/doc/SPEC.MISC b/doc/SPEC.MISC new file mode 100644 index 0000000..ff88463 --- /dev/null +++ b/doc/SPEC.MISC @@ -0,0 +1,32 @@ +MTU: +==== + +The protocol is designed to keep the MTU of the TAP-Interface as high as +possible. The overhead to payload-packets by the N2N Protocol is as follows +(lengths are noted in octets): + +4 SPI +12 AEAD_IV +16 AEAD_ICV +----------- +32 Total + +Additionally, since a TAP-Interface is used, the Ethernet Header usually +imposes an overhead of 18 bytes. Since the first 12 bytes are stripped by n2n +before sending, this imposes 6 bytes of overhead +TODO: is Frame check sequence sent? if not: -4 + +The last part of the overhead that has to be considered for the MTU is the +outer IP header. This can be assumed 20 bytes for IPv4 and 40 bytes for IPv6 +(what about special IP header options?) + +The Total overhead is therefore: +IPv4: 32 + 6 + 20 = 58 octets +IPv6: 32 + 6 + 40 = 78 octets + +Assuming an outgoing MTU of 1500, this results in a 3,87% (IPv4) / 5,20% (IPv6) +relative overhead + +Denoting the outinging interface's MTU as n, the MTU of the TAP interface hast +to be set to: +n - overhead diff --git a/doc/SPEC.PROCEDURE b/doc/SPEC.PROCEDURE new file mode 100644 index 0000000..35aa281 --- /dev/null +++ b/doc/SPEC.PROCEDURE @@ -0,0 +1,51 @@ +Note: For details on the SN_HEADER see SPEC.FORMATS + +1. Joining the Network + +Joining the Network is done by a 6-way handshake with the supernode. The first +two packets are used for a DH Exchange, the second two to exchange information. + +A -> S: pre-handshake +S -> A: pre-handshake ack +A -> S: handshake +S -> A: handshake ack +A -> S: payload packet: SN_HEADER(supernode-register:), A_MAC, A_N2N_IP +S -> A: payload packet: SN_HEADER(supernode-register:ACK), A_PUB_SOCK + +2. Supernode keep-alive + +A -> S: payload packet: SN_HEADER(keep-alive:) +S -> A: payload packet: SN_HEADER(keep-alive:ACK) + +3. ARP requests + +A -> S: payload packet: SN_HEADER(address-resolution:), B_IP +S -> A: payload packet: SN_HEADER(address-resolution:ACK), B_IP, B_MAC + +4. Establishing p2p connection to another edge + +A -> S: payload packet: SN_HEADER(edge-connect:), SPI (Source), B_MAC, + A_Timeout, A_PUB_SOCK, A_LOCAL_SOCK +S -> B: payload packet: SN_HEADER(edge-connect:), SPI (Source), B_MAC, + A_Timeout, A_PUB_SOCK, A_LOCAL_SOCK +B -> A: holepunch packet (will usually get lost) +B -> S: payload packet: SN_HEADER(edge-connect:ACK), SPI (Source), A_MAC, + B_Timeout, B_PUB_SOCK, B_LOCAL_SOCK +S -> A: payload packet: SN_HEADER(edge-connect:ACK), SPI (Source), A_MAC, + B_Timeout, B_PUB_SOCK, B_LOCAL_SOCK + +A -> B: handshake +B -> A: handshake ack + +5. Resume established connections with timeout for p2p hole + +A -> S: payload packet: SN_HEADER(edge-resume:), B_MAC, + A_Timeout, A_PUB_SOCK, A_LOCAL_SOCK +S -> B: payload packet: SN_HEADER(edge-resume:), B_MAC, + A_Timeout, A_PUB_SOCK, A_LOCAL_SOCK +B -> A: holepunch packet + +6. Data packets: + +A -> B: payload packet: DATA (as received from tap interface stripped of first + 12 Byte of the Ethernet frame -- src and dst mac) diff --git a/n2n_v2/edge.8 b/edge.8 similarity index 100% rename from n2n_v2/edge.8 rename to edge.8 diff --git a/edge.c b/edge.c new file mode 100644 index 0000000..b6e6795 --- /dev/null +++ b/edge.c @@ -0,0 +1,2724 @@ +/** + * (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. + * + * 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 + * + * Code contributions courtesy of: + * Don Bindner + * Sylwester Sosnowski + * Wilfried "Wonka" Klaebe + * Lukasz Taczuk + * + */ + +#include "n2n.h" +#include "n2n_transforms.h" +#include +#include +#include "minilzo.h" +#include "crypto/crypto.h" +#include "crypto/aes.h" + +#if defined(DEBUG) +#define SOCKET_TIMEOUT_INTERVAL_SECS 5 +#define DEFAULT_HOLEPUNCH_INTERVAL 20 /* sec */ +#else /* #if defined(DEBUG) */ +#define SOCKET_TIMEOUT_INTERVAL_SECS 5 +#define DEFAULT_HOLEPUNCH_INTERVAL 25 /* sec */ +#endif /* #if defined(DEBUG) */ + +#define REGISTER_SUPER_INTERVAL_MIN 10 /* sec */ +#define REGISTER_SUPER_INTERVAL_MAX 120 /* sec */ + +#define IFACE_UPDATE_INTERVAL (30) /* sec. How long it usually takes to get an IP lease. */ +#define TRANSOP_TICK_INTERVAL (10) /* sec */ + +#define STAT_CALC_INTERVAL (10) /* sec. Calculate the bps values in roughly this interval steps */ + +/** 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 N2N_EDGE_SN_HOST_SIZE 48 +#define N2N_EDGE_LOCAL_IP_SIZE 48 + +typedef char n2n_sn_name_t[N2N_EDGE_SN_HOST_SIZE]; +typedef char n2n_local_ip_t[N2N_EDGE_LOCAL_IP_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; + n2n_sock_t local_sock; + + 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]; + n2n_local_ip_t local_ip_str; /** storing a local ip socket */ + int local_sock_ena; /** > 0 if local_sock is enabled */ + int sn_wait; /**< Whether we are waiting for a supernode response. */ + + n2n_community_t community_name; /**< The community (hashed). */ + 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[PEER_HASH_TAB_SIZE]; /**< Edges we are connected to. */ + struct peer_info * pending_peers[PEER_HASH_TAB_SIZE]; /**< Edges we have tried to register with. */ + time_t last_register_req; /**< Check if time to re-register with super*/ + size_t holepunch_interval; /**< Time distance after last_register_req at which to re-register. */ + time_t last_purge; /** last time clients were purged **/ + 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 tx_bit_p2p; + size_t tx_bps_p2p; + size_t rx_p2p; + size_t rx_bit_p2p; + size_t rx_bps_p2p; + size_t tx_sup; + size_t tx_bit_sup; + size_t tx_bps_sup; + size_t rx_sup; + size_t rx_bit_sup; + size_t rx_bps_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 int localip2addr(n2n_sock_t * l_ip, const n2n_local_ip_t local_ip_strIn, + int local_port); + +static void send_packet2net(n2n_edge_t * eee, uint8_t *decrypted_msg, + size_t len); + +/* ************************************** */ + +/* parse the configuration file */ +static int readConfFile(const char * filename, char * const linebuffer) +{ + struct stat stats; + FILE * fd; + char * buffer = NULL; + + buffer = (char *) malloc(MAX_CONFFILE_LINE_LENGTH); + if (!buffer) { + traceEvent(TRACE_ERROR, "Unable to allocate memory"); + return -1; + } + + 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); + free(buffer); + return -1; + } + + fd = fopen(filename, "rb"); + if (!fd) { + traceEvent(TRACE_ERROR, "Unable to open parameter file '%s' (%d)...\n", + filename, errno); + free(buffer); + return -1; + } + while (fgets(buffer, MAX_CONFFILE_LINE_LENGTH, fd)) { + char * p = NULL; + + /* strip out comments */ + p = strchr(buffer, '#'); + if (p) + *p = '\0'; + + /* remove \n */ + p = strchr(buffer, '\n'); + if (p) + *p = '\0'; + + /* strip out heading spaces */ + p = buffer; + while (*p == ' ' && *p != '\0') + ++p; + 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, '@')) { + 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) { + strncat(linebuffer, " ", 1); + strncat(linebuffer, buffer, strlen(buffer)); + } else { + traceEvent(TRACE_ERROR, "too many argument"); + free(buffer); + return -1; + } + } + + free(buffer); + fclose(fd); + + 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 */ + int maxargc; + int argc = 0; + char ** argv; + char * buffer, *buff; + + *effectiveargc = 0; + buffer = (char *) calloc(1, strlen(linebuffer) + 2); + if (!buffer) { + traceEvent(TRACE_ERROR, "Unable to allocate memory"); + return NULL; + } + strncpy(buffer, linebuffer, strlen(linebuffer)); + + maxargc = INITIAL_MAXARGC; + argv = (char **) malloc(maxargc * sizeof(char*)); + if (argv == NULL) { + traceEvent(TRACE_ERROR, "Unable to allocate memory"); + return NULL; + } + buff = buffer; + while (buff) { + char * p = strchr(buff, ' '); + if (p) { + *p = '\0'; + argv[argc++] = strdup(buff); + while (*++p == ' ' && *p != '\0') + ; + buff = p; + if (argc >= maxargc) { + maxargc *= 2; + argv = (char **) realloc(argv, maxargc * sizeof(char*)); + if (argv == NULL) { + traceEvent(TRACE_ERROR, "Unable to re-allocate memory"); + free(buffer); + return NULL; + } + } + } else { + argv[argc++] = strdup(buff); + break; + } + } + 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->local_sock_ena = 0; + sglib_hashed_peer_info_t_init(eee->known_peers); + sglib_hashed_peer_info_t_init(eee->pending_peers); + eee->last_register_req = 0; + eee->holepunch_interval = DEFAULT_HOLEPUNCH_INTERVAL; + eee->last_p2p = 0; + eee->last_sup = 0; + eee->last_purge = 0; + eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; + eee->tx_bit_p2p = 0; + eee->tx_bit_sup = 0; + eee->rx_bit_p2p = 0; + eee->rx_bit_sup = 0; + + 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_hashed_peer_info_t_list(eee->pending_peers); + clear_hashed_peer_info_t_list(eee->known_peers); + crypto_deinit(); + + crypto_deinit(); + + (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(); + + printf("edge " +#if defined(N2N_CAN_NAME_IFACE) + "-d " +#endif /* #if defined(N2N_CAN_NAME_IFACE) */ + "-a [static:|dhcp:] " + "-c " + "[-k | -K ] " + "[-s ] " +#if defined(N2N_HAVE_SETUID) + "[-u -g ]" +#endif /* #ifndef N2N_HAVE_SETUID */ + +#if defined(N2N_HAVE_DAEMON) + "[-f]" +#endif /* #if defined(N2N_HAVE_DAEMON) */ + "[-m ]" + "\n" + "-l " + "[-p ] [-M ] " + "[-r] [-E] [-v] [-t ] [-b] [-h]\n\n"); + +#ifdef __linux__ + printf("-d | tun device name\n"); +#endif + + printf( + "-a | Set interface address. For DHCP use '-r -a dhcp:0.0.0.0'\n"); + printf( + "-c | n2n community name the edge belongs to.\n"); + printf( + "-k | Encryption key (ASCII) - also N2N_KEY=. Not with -K.\n"); + printf( + "-K | Specify a key schedule file to load. Not with -k.\n"); + printf( + "-s | Edge interface netmask in dotted decimal notation (255.255.255.0).\n"); + printf("-l | Supernode IP:port\n"); + printf( + "-i | Add local ip to bypass between same nat problem\n"); + printf("-b | Periodically resolve supernode IP\n"); + printf( + " : (when supernodes are running on dynamic IPs)\n"); + printf("-p | Fixed local UDP port.\n"); +#ifndef WIN32 + 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 + printf( + "-f | Do not fork and run as a daemon; rather run in foreground.\n"); +#endif /* #ifdef N2N_HAVE_DAEMON */ + 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); + printf( + "-r | Enable packet forwarding through n2n community.\n"); + printf( + "-E | Accept multicast MAC addresses (default=drop).\n"); + printf( + "-v | Make more verbose. Repeat as required.\n"); + 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"); + + 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) +{ + n2n_sock_str_t sockbuf; + 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 %s failed (%d) %s", + sock_to_cstr(sockbuf, dest), 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, + const n2n_mac_t dstMac) +{ + uint8_t pktbuf[N2N_PKT_BUF_SIZE]; + size_t idx; + n2n_common_t cmn = { 0 }; + n2n_REGISTER_t reg = { { 0 } }; + n2n_sock_str_t sockbuf; + + cmn.ttl = N2N_DEFAULT_TTL; + cmn.pc = n2n_register; + cmn.flags = 0; + memcpy(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE); + + /* NOTE: Encoding should probably not be done here but in + * encode_REGISTER (lukas) */ + idx = 0; + encode_uint32(reg.cookie, &idx, 123456789); + idx = 0; + encode_mac(reg.srcMac, &idx, eee->device.mac_addr); + if (dstMac) { + idx = 0; + encode_mac(reg.dstMac, &idx, dstMac); + } + + idx = 0; + encode_REGISTER(pktbuf, &idx, &cmn, ®); + + traceEvent(TRACE_INFO, "send REGISTER %s", sock_to_cstr(sockbuf, remote_peer)); + + sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer); +} + +/** Send a QUERY_PEER packet to the current supernode. */ +static void send_query_peer(n2n_edge_t * eee, const n2n_mac_t dstMac) +{ + uint8_t pktbuf[N2N_PKT_BUF_SIZE]; + size_t idx; + n2n_common_t cmn = { 0 }; + n2n_QUERY_PEER_t query = { { 0 } }; + + cmn.ttl = N2N_DEFAULT_TTL; + cmn.pc = n2n_query_peer; + cmn.flags = 0; + memcpy(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE); + + idx = 0; + encode_mac(query.srcMac, &idx, eee->device.mac_addr); + idx = 0; + encode_mac(query.targetMac, &idx, dstMac); + + idx = 0; + encode_QUERY_PEER(pktbuf, &idx, &cmn, &query); + + traceEvent(TRACE_INFO, "send QUERY_PEER to supernode"); + + sendto_sock(eee->udp_sock, pktbuf, idx, &(eee->supernode)); +} + +/** 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; + n2n_common_t cmn = { 0 }; + n2n_REGISTER_SUPER_t reg = { 0 }; + n2n_sock_str_t sockbuf; + + 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; + } + + reg.aflags = 0; + memcpy(reg.cookie, eee->last_cookie, N2N_COOKIE_SIZE); + reg.auth.scheme = 0; /* No auth yet */ + reg.timeout = eee->holepunch_interval; + + idx = 0; + encode_mac(reg.edgeMac, &idx, eee->device.mac_addr); + + if (eee->local_sock_ena) { + reg.aflags |= N2N_AFLAGS_LOCAL_SOCKET; + reg.local_sock = eee->local_sock; + } + + idx = 0; + encode_REGISTER_SUPER(pktbuf, &idx, &cmn, ®); + + traceEvent(TRACE_INFO, "send REGISTER_SUPER to %s", sock_to_cstr(sockbuf, supernode)); + + 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; + 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)); + + 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 establish_connection(n2n_edge_t * eee, const n2n_mac_t mac); +void set_peer_operational(n2n_edge_t * eee, const n2n_mac_t mac, + const n2n_sock_t * peer); + +/** Start the registration process. + * + * If the peer is already in pending_peers, ignore the request. + * If not in pending_peers, add it and query info about it from supernode + * + * If hdr is for a direct peer-to-peer packet, try to register back to sender + * even if the MAC is in pending_peers. This is because an incident direct + * packet indicates that peer-to-peer exchange should work so more aggressive + * registration can be permitted (once per incoming packet) as this should only + * last for a small number of packets.. + * + * Called from the main loop when Rx a packet for our device mac. + */ +void establish_connection(n2n_edge_t * eee, const n2n_mac_t mac) +{ + struct peer_info * scan = find_peer_by_mac(eee->pending_peers, mac); + macstr_t mac_buf; + n2n_sock_str_t sockbuf; + + if (NULL == scan) { + time_t now = time(NULL); + scan = calloc(1, sizeof(struct peer_info)); + + memcpy(scan->mac_addr, mac, N2N_MAC_SIZE); + scan->num_sockets = 0; + scan->sock = eee->supernode; + scan->last_seen = now; /* Don't change this it marks the pending peer for removal. */ + + sglib_hashed_peer_info_t_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_INFO, "Pending peers list size=%u", + (unsigned int)hashed_peer_list_t_size( eee->pending_peers)); + + /* trace Sending REGISTER */ + + send_query_peer(eee, scan->mac_addr); + scan->last_sent_query = now; + + /* pending_peers now owns scan. */ + } 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) +{ + peer_info_t scan; + memcpy(scan.mac_addr, mac, sizeof(n2n_mac_t)); + + if (sglib_hashed_peer_info_t_find_member(eee->known_peers, &scan) == NULL) { + /* Not in known_peers - start the REGISTER process. */ + establish_connection(eee, mac); + } 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) +{ + peer_info_t tmp; + peer_info_t *scan; + macstr_t mac_buf; + n2n_sock_str_t sockbuf; + void *key; // dummy key + gnutls_cipher_hd_t *ctx = NULL; + int err; + + traceEvent(TRACE_INFO, "set_peer_operational: %s -> %s", + macaddr_str(mac_buf, mac), sock_to_cstr(sockbuf, peer)); + + memcpy(tmp.mac_addr, mac, sizeof(n2n_mac_t)); + + scan = sglib_hashed_peer_info_t_find_member(eee->pending_peers, &tmp); + + if (scan) { + /* Remove scan from pending_peers. */ + sglib_hashed_peer_info_t_delete(eee->pending_peers, scan); + + /* Add scan to known_peers. */ + sglib_hashed_peer_info_t_add(eee->known_peers, scan); + + /* TODO: DH and key derivation, for now set dummy keys */ + /* set tx session key */ + key = aes_gcm_dummy_key(); //TODO destroy key + err = aes_gcm_session_create(key, &ctx); + if (err) { + traceEvent(TRACE_ERROR, "Failed to initialize AES session: %d", err); + scan->aes_gcm_tx_ctx = NULL; + } else { + scan->aes_gcm_tx_ctx = ctx; + traceEvent(TRACE_DEBUG, "AES session initiated"); + } + /* set rx session key */ + err = aes_gcm_session_create(key, &ctx); + if (err) { + traceEvent(TRACE_ERROR, "Failed to initialize AES session: %d", err); + scan->aes_gcm_rx_ctx = NULL; + } else { + scan->aes_gcm_rx_ctx = ctx; + traceEvent(TRACE_DEBUG, "AES session initiated"); + } + + 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)hashed_peer_list_t_size(eee->pending_peers)); + + traceEvent(TRACE_INFO, "Operational peers list size=%u", + (unsigned int)hashed_peer_list_t_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; i < len; ++i) { + if (0 != ptr[i]) { + /* found a non-zero byte in address */ + return 0; + } + } + + return 1; +} + +/** Keep the known_peers list straight. + * + * Ignore broadcast L2 packets, and packets with invalid public_ip. + * If the dst_mac is in known_peers make sure the entry is correct: + * - if the public_ip socket has changed, erase the entry + * - if the same, update its last_seen = when + */ +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) +{ + peer_info_t *scan = NULL; + peer_info_t tmp; + 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; + } + + memcpy(tmp.mac_addr, mac, sizeof(n2n_mac_t)); + scan = sglib_hashed_peer_info_t_find_member(eee->known_peers, &tmp); + + if (scan == NULL) { + /* 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. */ + sglib_hashed_peer_info_t_delete(eee->known_peers, scan); + dealloc_peer(scan); + + establish_connection(eee, mac); + } else { + /* Don't worry about what the supernode reports, it could be seeing + * a different socket. */ + /* anyways, the packet came from supernode. That is potential + * trouble... just in case we will send a register back to the + * origin */ + send_register(eee, &(scan->sock), scan->mac_addr); + } + } else { + /* Found and unchanged. */ + if(!from_supernode) + scan->last_seen = when; + } +} + + +#define MAX_SUPERNODE_TRIES 3 +#define RETRY_INTERVAL 5 + +static int initial_supernode_registration(n2n_edge_t *eee) { + socklen_t sender_socklen; + struct sockaddr_in sender_sock; + uint8_t udp_buf[N2N_PKT_BUF_SIZE]; + uint8_t payload_buf[N2N_PKT_BUF_SIZE]; + size_t trans_len, payload_len; + struct timeval wait_time; + fd_set socket_mask; + int rc, tries, phase, next_phase; + n2n_sa_t spi_self, spi_remote; + n2n_HEADER_t hdr; + n2n_supernode_register_t sn_reg; + + /* TODO: these value must come from proper sources (crypto engine) */ + spi_self = 0xAFFEEFFA; /* generate randomly */ + spi_remote = 0; /* not yet known */ + + memcpy(hdr.community, eee->community_name, N2N_COMMUNITY_SIZE); + + for (phase = 0; phase < 3; phase++) { + next_phase = 0; + + /* prepare packet */ + trans_len = 0; + switch(phase) { + case 0: + /* build pre-handshake packet */ + /* encode special SPI 0 */ + encode_uint32(udp_buf, &trans_len, 0); + /* build HEADER */ + hdr.pc = n2n_pre_handshake; + hdr.flags = 0x0; + /* encode HEADER */ + encode_HEADER(udp_buf, &trans_len, &hdr); + /* encode community */ + encode_buf(udp_buf, &trans_len, eee->community_name, + N2N_COMMUNITY_SIZE); + /* encode destination spi (0) */ + encode_uint32(udp_buf, &trans_len, spi_remote); + /* encode source spi */ + encode_uint32(udp_buf, &trans_len, spi_self); + /* finished packet building */ + break; + case 1: + /* build handshake packet*/ + /* encode special SPI 0 */ + encode_uint32(udp_buf, &trans_len, 0); + /* build HEADER */ + hdr.pc = n2n_handshake; + hdr.flags = 0x0; + /* encode HEADER */ + encode_HEADER(udp_buf, &trans_len, &hdr); + /* destination spi is now known (not 0) */ + encode_uint32(udp_buf, &trans_len, spi_remote); + /* TODO: + * ECDH ephemeral public key + * AEAD_KDF_SALT + * HMAC_KDF_SALT + * HMAC_TAG */ + break; + case 2: + /* build supernode-register packet */ + /* this is a payload packet and needs to run through crypto + * engline */ + payload_len = 0; + memcpy(sn_reg.syn.a_mac, eee->device.mac_addr, N2N_MAC_SIZE); + /* NOTE: though device.ip_addr is an uint32_t it is already + * stored in network byte order, memcpy is thus fine! */ + /* TODO: IPv6 */ + memcpy(sn_reg.syn.a_n2n_ip, &eee->device.ip_addr, IPV4_SIZE); + encode_supernode_register(payload_buf, &payload_len, 0, &sn_reg); + /* prepare packet */ + /* encode remote SPI */ + encode_uint32(udp_buf, &trans_len, spi_remote); + /* TODO: call crypto engine for handling payload */ + + break; + default: + break; + } + + for (tries = 0; tries < MAX_SUPERNODE_TRIES; tries++) { + /* (re)send packet */ + sendto_sock(eee->udp_sock, udp_buf, trans_len, &eee->supernode); + /* wait for return */ + /* TODO: set timeout using define */ + wait_time.tv_sec = 5; + wait_time.tv_usec = 0; + FD_ZERO(&socket_mask); + FD_SET(eee->udp_sock, &socket_mask); + rc = select(eee->udp_sock + 1, &socket_mask, + NULL, NULL, &wait_time); + if (rc > 0) { + sender_socklen = sizeof(sender_sock); + trans_len = recvfrom(eee->udp_sock, udp_buf, N2N_PKT_BUF_SIZE, + 0, (struct sockaddr *) &sender_sock, + (socklen_t*) &sender_socklen); + + switch(phase) { + case 0: + /* check pre-hanshake reply */ + next_phase = 1; + break; + case 1: + /* check hanshake reply */ + next_phase = 1; + break; + case 2: + /* check registration */ + next_phase = 1; + break; + default: + break; + } + /* check correct reply */ + } + if (next_phase) { + break; + } + } + if (tries == MAX_SUPERNODE_TRIES) { + return 1; + } + } + + return 0; +} + +#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 */ + 0x08, 0x06, /* ARP */ + 0x00, 0x01, /* Ethernet */ + 0x08, 0x00, /* IP */ + 0x06, /* Hw Size */ + 0x04, /* Protocol Size */ + 0x00, 0x01, /* ARP Request */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Src mac */ + 0x00, 0x00, 0x00, 0x00, /* Src IP */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Target mac */ + 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) +{ + if(buffer_len < sizeof(gratuitous_arp)) return(-1); + + memcpy(buffer, gratuitous_arp, sizeof(gratuitous_arp)); + memcpy(&buffer[6], device.mac_addr, 6); + memcpy(&buffer[22], device.mac_addr, 6); + memcpy(&buffer[28], &device.ip_addr, 4); + + /* REVISIT: BbMaj7 - use a real netmask here. This is valid only by accident + * for /24 IPv4 networks. */ + buffer[31] = 0xFF; /* Use a faked broadcast address */ + memcpy(&buffer[38], &device.ip_addr, 4); + return(sizeof(gratuitous_arp)); +} + +/** Called from update_supernode_reg to periodically send gratuitous ARP + * broadcasts. */ +static void send_grat_arps(n2n_edge_t* eee) +{ + char buffer[48]; + size_t len; + + traceEvent(TRACE_NORMAL, "Sending gratuitous ARP..."); + len = build_gratuitous_arp(buffer, sizeof(buffer)); + 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->holepunch_interval / 10)))) { + /* fall through */ + traceEvent(TRACE_DEBUG, "update_supernode_reg: doing fast retry."); + } else if (nowTime < (eee->last_register_req + eee->holepunch_interval)) { + 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; +} + +#define RETRY_INTERVAL 5 + +/* @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, peer_info_t **peer) +{ + peer_info_t tmp; + peer_info_t* scan = NULL; + peer_info_t* tryscan = NULL; + macstr_t mac_buf; + n2n_sock_str_t sockbuf; + int retval = 0; + int i; + time_t now = time(NULL); + + 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); + + memcpy(tmp.mac_addr, mac_address, sizeof(n2n_mac_t)); + scan = sglib_hashed_peer_info_t_find_member(eee->known_peers, &tmp); + if (scan) { + if (now - scan->last_seen > scan->timeout) { + /* delete the peer and establish new connection */ + sglib_hashed_peer_info_t_delete(eee->known_peers, scan); + establish_connection(eee, scan->mac_addr); + dealloc_peer(scan); + } else if (scan->last_seen > 0) { + memcpy(destination, &scan->sock, sizeof(n2n_sock_t)); + *peer = scan; + retval = 1; + } + } + + if (0 == retval) { + tryscan = sglib_hashed_peer_info_t_find_member(eee->pending_peers, &tmp); + if (tryscan) { + if (tryscan->num_sockets == 0) { + /* not yet received peer_info from supernode */ + if (now - tryscan->last_sent_query > RETRY_INTERVAL) { + send_query_peer(eee, tryscan->mac_addr); + tryscan->last_sent_query = now; + } + } else if (now - tryscan->last_seen > RETRY_INTERVAL) { + traceEvent(TRACE_INFO, "retrying to register peer (%s) -> [%s]", + macaddr_str( mac_buf, mac_address), sock_to_cstr( sockbuf, &tryscan->sock)); + for(i=0; inum_sockets; i++) + send_register(eee, &tryscan->sockets[i], tryscan->mac_addr); + tryscan->last_seen = now; + } + } + 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[] = { + {"community", required_argument, NULL, 'c' }, + {"supernode-list", required_argument, NULL, 'l'}, + {"tun-device", required_argument, NULL, 'd'}, + {"euid", required_argument, NULL, 'u'}, + {"egid", required_argument, NULL, 'g'}, + {"local-ip", required_argument, NULL, 'L'}, + {"holepunch-interval", required_argument, NULL, 'i'}, + {"help", no_argument, NULL, 'h'}, + {"verbose", no_argument, NULL, 'v'}, + {NULL, 0, NULL, 0} +}; + +/* ***************************************************** */ + +/** 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, n2n_sock_t * destination) +{ + n2n_sock_str_t sockbuf; + + /* hexdump( pktbuf, pktlen ); */ + + traceEvent(TRACE_INFO, "send_PACKET to %s", sock_to_cstr(sockbuf, destination)); + + 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; + + int dest; + int offset; + n2n_sock_t destination; + peer_info_t *peer = NULL; + + /* 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. */ + uint32_t *src = (uint32_t*) &tap_pkt[ETH_FRAMEHDRSIZE + IP4_SRCOFFSET]; + + /* Note: all elements of the_ip are in network order */ + if (*src != eee->device.ip_addr) { + /* This is a packet that needs to be routed */ + traceEvent(TRACE_INFO, "Discarding routed packet [%s]", + intoa(ntohl(*src), 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); + + dest = find_peer_destination(eee, destMac, &destination, &peer); + + memset(&pkt, 0, sizeof(pkt)); + + tx_transop_idx = edge_choose_tx_transop(eee); + + pkt.transform = eee->transop[tx_transop_idx].transform_id; + + idx = 0; + encode_PACKET(pktbuf, &idx, &cmn, &pkt); + /* make the ethernet-header part of the PACKET header */ + offset = copy_ETHFRAMEHDR(pktbuf + idx, tap_pkt); + idx += offset; + tap_pkt += offset; + len -= offset; + + 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); + + /* if we know the peer TODO: DH and key derivation */ + int err; + if (peer == NULL) { + traceEvent(TRACE_WARNING, "ENC: NONE"); + memcpy(pktbuf + idx, tap_pkt, len); + idx += len; + } else { + traceEvent(TRACE_WARNING, "ENC: AES"); + err = aes_gcm_authenc(*(peer->aes_gcm_tx_ctx), tap_pkt, len, + pktbuf + idx, N2N_PKT_BUF_SIZE - idx, NULL, 0); + if (err < 0) { + ; //TODO error condition + } else { + idx += err; + } + } + + if (dest) { + ++(eee->tx_p2p); + eee->tx_bit_p2p += idx; + } else { + ++(eee->tx_sup); + eee->tx_bit_sup += idx; + } + send_PACKET(eee, destMac, pktbuf, idx, &destination); +} + +/** 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; + n2n_ETHFRAMEHDR_t eth; + peer_info_t tmp; + peer_info_t *peer; + + 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; + eee->rx_bit_sup += psize; + } else { + ++(eee->rx_p2p); + eee->last_p2p = now; + eee->rx_bit_p2p += psize; + } + + decode_ETHFRAMEHDR(ð, payload); + /* Update the sender in peer table entry */ + check_peer(eee, from_supernode, eth.srcMac, orig_sender); + + /* Handle transform. */ + memcpy(tmp.mac_addr, eth.srcMac, sizeof(n2n_mac_t)); + peer = sglib_hashed_peer_info_t_find_member(eee->known_peers, &tmp); + + uint8_t decodebuffer[N2N_PKT_BUF_SIZE]; + uint8_t * decodebuf = decodebuffer; + size_t eth_size; + int offset; + + /* copy eth header to decodebuf */ + offset = copy_ETHFRAMEHDR(decodebuffer, payload); + decodebuf += offset; + payload += offset; + psize -= offset; + eth_size = offset; + + if (peer != NULL) { + /* authenticate and decrypt */ + int err; + eth_payload = decodebuf; + err = aes_gcm_authdec(*(peer->aes_gcm_rx_ctx), payload, psize, + eth_payload, N2N_PKT_BUF_SIZE, NULL, 0); + /* authentication failed or other error occured */ + if (err < 0) { + traceEvent(TRACE_WARNING, + "packet authentication or decryption failed"); + return err; + } else { + eth_size += err; + } + } else { + memcpy(decodebuf, payload, psize); + eth_size += psize; + } + + /* Write ethernet packet to tap device. */ + traceEvent(TRACE_INFO, "sending to TAP %u", (unsigned int)eth_size); + data_sent_len = tuntap_write(&(eee->device), decodebuffer, eth_size); + + if (data_sent_len == eth_size) + retval = 0; + + 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; + struct sockaddr_in sender_sock; + socklen_t i; + size_t msg_len; + time_t now; + macstr_t mac_buf; + n2n_sock_str_t sockbuf; + peer_info_t * lpi = NULL; + struct sglib_hashed_peer_info_t_iterator it; + int c; + + 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" + " peers List table of known peers\n" + " reload Re-read the keyschedule\n" + " mangle_peer mac ip [port] mangle peer\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 (0 == memcmp(udp_buf, "peers", 5)) { + msg_len = 0; + + msg_len += snprintf((char *)(udp_buf + msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "> known peers (connected edges):\n"); + + traceEvent(TRACE_ERROR, "listing peers on mgmt socket", 0); + sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0, + (struct sockaddr *)&sender_sock, + sizeof(struct sockaddr_in)); + + c = 0; + for (lpi = sglib_hashed_peer_info_t_it_init(&it, eee->known_peers); + lpi != NULL; lpi = sglib_hashed_peer_info_t_it_next(&it)) { + c++; + msg_len = 0; + msg_len += snprintf((char *)(udp_buf + msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "> %i: %s -> %s last: %li\n", c, + macaddr_str(mac_buf, lpi->mac_addr), + sock_to_cstr(sockbuf, &(lpi->sock)), + lpi->last_seen); + sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0, + (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), + "> known peers (tried edges):\n"); + sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0, + (struct sockaddr *)&sender_sock, + sizeof(struct sockaddr_in)); + + c = 0; + for (lpi = sglib_hashed_peer_info_t_it_init(&it, eee->pending_peers); + lpi != NULL; lpi = sglib_hashed_peer_info_t_it_next(&it)) { + c++; + msg_len = 0; + if (lpi->num_sockets == 0) + msg_len += snprintf((char *)(udp_buf + msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "> %i: %s -> (no info) last: %li\n", c, + macaddr_str(mac_buf, lpi->mac_addr), + lpi->last_seen); + else + msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "> %i: %s -> %s last: %li\n", c, + macaddr_str(mac_buf, lpi->mac_addr), + sock_to_cstr(sockbuf, lpi->sockets), + lpi->last_seen); + if (lpi->num_sockets > 1) + msg_len += snprintf((char *)(udp_buf + msg_len), (N2N_PKT_BUF_SIZE-msg_len), + " %s\n", + sock_to_cstr(sockbuf, lpi->sockets+1)); + sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0, + (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; + } + } + } + if (recvlen >= 12) { + if (0 == memcmp(udp_buf, "mangle_peer ", 12)) { + int j, n_matched; + n2n_mac_t target_mac; + unsigned int mac[6]; + int ip[4]; + int port; + struct peer_info * scan; + + udp_buf[recvlen] = 0; + n_matched = sscanf((const char *) udp_buf, + "mangle_peer %x:%x:%x:%x:%x:%x %d.%d.%d.%d %d", mac, + mac + 1, mac + 2, mac + 3, mac + 4, mac + 5, ip, ip + 1, + ip + 2, ip + 3, &port); + for (j = 0; j < 6; j++) + target_mac[j] = (uint8_t) mac[j]; + scan = find_peer_by_mac(eee->pending_peers, target_mac); + if (NULL != scan && n_matched >= 10) { + scan->sock.family = AF_INET; + printf("n_matched: %d, port: %d\n", n_matched, port); + if (n_matched >= 11 && port > 0) + scan->sock.port = (uint16_t) port; + for (j = 0; j < 4; j++) + scan->sock.addr.v4[j] = (uint8_t) ip[j]; + sendto(eee->udp_mgmt_sock, "success\n", 9, 0, + (struct sockaddr *) &sender_sock, + sizeof(struct sockaddr_in)); + } else { + sendto(eee->udp_mgmt_sock, "failure\n", 9, 0, + (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:(tx),(rx) p2p: (tx),(rx)\n"); + msg_len += snprintf((char *)(udp_buf + msg_len), (N2N_PKT_BUF_SIZE-msg_len), + "packets %u,%u %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), + "byte/s %u,%u %u,%u\n", + (unsigned int)eee->tx_bps_sup, + (unsigned int)eee->rx_bps_sup, + (unsigned int)eee->tx_bps_p2p, + (unsigned int)eee->rx_bps_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)hashed_peer_list_t_size( eee->pending_peers), + (unsigned int)hashed_peer_list_t_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); + + 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; + struct sockaddr_in sender_sock; + n2n_sock_t sender; + n2n_sock_t * orig_sender = NULL; + time_t now = 0; + size_t i; + int j; + + /* for PACKET packages */ + n2n_PACKET_t pkt; + + /* for PEER_INFO packages */ + n2n_PEER_INFO_t pi; + struct peer_info * scan; + + /* for REGISTER packages */ + n2n_REGISTER_t reg; + peer_info_t tmp; + + /* for REGISTER_ACK packages */ + n2n_REGISTER_ACK_t ra; + + /* For REGISTER_SUPER_ACK packages */ + n2n_REGISTER_SUPER_ACK_t rsa; + + 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); + + if(cmn->spi == 0) { + // non-payload + // check version + if(cmn->version_major == N2N_PROTOCOL_VERSION_MAJOR && cmn->version_minor == N2N_PROTOCOL_VERSION_MINOR) + switch(cmn->pc) { + case n2n_pre_handshake: + // discard + break; + case n2n_handshake: + + break; + case n2n_handshake_ack: + + break; + case n2n_holepunch: + // discard + break; + default: + traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored", (signed int)cmn->pc); + break; + } + } else { + traceEvent(TRACE_WARNING, "Unsupported version packed received %d.%d: ignored", cmn->version_major, cmn->version_minor); + } + } else { + // payload packet + + } + + + /*if (0 == memcmp(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE)) { + switch (msg_type) { + case MSG_TYPE_PACKET: + process PACKET + decode_PACKET(&pkt, &cmn, udp_buf, &rem, &idx); + + 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); + break; + case MSG_TYPE_PEER_INFO: + decode_PEER_INFO(&pi, &cmn, udp_buf, &rem, &idx); + + scan = find_peer_by_mac( eee->pending_peers, pi.mac ); + if (scan) { + scan->timeout = pi.timeout; + if (scan->num_sockets > 0) + free(scan->sockets); + if (pi.aflags & N2N_AFLAGS_LOCAL_SOCKET) + scan->num_sockets = 2; + else + scan->num_sockets = 1; + scan->sockets = malloc(scan->num_sockets*sizeof(n2n_sock_t)); + for(j=0; jnum_sockets; j++) + scan->sockets[j] = pi.sockets[j]; + traceEvent(TRACE_INFO, "Rx PEER_INFO on %s", + macaddr_str(mac_buf1, pi.mac)); + for(j=0; jnum_sockets; j++) + send_register(eee, scan->sockets+j, scan->mac_addr); + } else { + traceEvent(TRACE_INFO, "Rx PEER_INFO unknown peer %s", + macaddr_str(mac_buf1, pi.mac)); + } + + break; + case MSG_TYPE_REGISTER: + Another edge is registering with us + decode_REGISTER( ®, &cmn, udp_buf, &rem, &idx ); + + 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 (memcmp(reg.dstMac, (eee->device.mac_addr), 6) == 0) + { + memcpy(tmp.mac_addr, reg.srcMac, sizeof(n2n_mac_t)); + if (sglib_hashed_peer_info_t_find_member( + eee->pending_peers, &tmp) != NULL) + send_register(eee, orig_sender, NULL); + } + + send_register_ack(eee, orig_sender, ®); + break; + case MSG_TYPE_REGISTER_ACK: + Peer edge is acknowledging our register request + + 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); + break; + case MSG_TYPE_REGISTER_SUPER_ACK: + if (eee->sn_wait) { + decode_REGISTER_SUPER_ACK(&rsa, &cmn, udp_buf, &rem, &idx); + + if (rsa.sock.family) { + orig_sender = &(rsa.sock); + } + + traceEvent(TRACE_NORMAL, "Rx REGISTER_SUPER_ACK myMAC=%s [%s] (external %s). Attempts %u", + macaddr_str(mac_buf1, rsa.edgeMac), + sock_to_cstr(sockbuf1, &sender), + sock_to_cstr(sockbuf2, orig_sender), + (unsigned int)eee->sup_attempts); + + if (memcmp( rsa.cookie, eee->last_cookie, N2N_COOKIE_SIZE) == 0) { + if (rsa.num_sn > 0) { + traceEvent(TRACE_NORMAL, "Rx REGISTER_SUPER_ACK backup supernode at %s", + sock_to_cstr(sockbuf1, &(rsa.sn_bak))); + } + + eee->last_p2p = now; + 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 + don't adjust lifetime according to supernode - this value should be specified + * by the client (because dependent on NAT/firewall) (lukas) + eee->holepunch_interval = rsa.lifetime; + eee->holepunch_interval = MAX( eee->holepunch_interval, REGISTER_SUPER_INTERVAL_MIN ); + eee->holepunch_interval = MIN( eee->holepunch_interval, 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."); + } + break; + default: + Not a known message type + traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored", (signed int)msg_type); + break; + } end switch(msg_type) + } 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 (nameerr == 0) { + 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 )"); + } +} + +/** + * Decode local address string (given on command line) + */ +static int localip2addr(n2n_sock_t * l_ip, const n2n_local_ip_t local_ip_str, + int local_port) +{ + /* TODO: IPv6? */ + unsigned int ip[4]; + int i, n_matches; + + n_matches = sscanf(local_ip_str, "%u.%u.%u.%u", &ip[0], &ip[1], &ip[2], &ip[3]); + + if (n_matches != 4) { + traceEvent(TRACE_WARNING, "Wrong local_ip parameter (-i ip), disabled"); + return 0; + } + + for (i = 0; i < 4; i++) { + if (ip[i] > 255) { + traceEvent(TRACE_WARNING, "Invalid local_ip address (-i ip), disabled"); + return 0; + } + } + l_ip->family = AF_INET; + l_ip->port = local_port; + for (i = 0; i < 4; i++) + l_ip->addr.v4[i] = ip[i]; + return 1; +} + +/* ***************************************************** */ + +/** Find the address and IP mode for the tuntap device. + * + * s is one of these forms: + * + * := | A.B.C.D + * + * | static: | dhcp: + * + * If the mode is present (colon required) then fill ip_mode with that value + * otherwise do not change ip_mode. Fill ip_mode with everything after the + * colon if it is present; or s if colon is not present. + * + * ip_add and ip_mode are NULL terminated if modified. + * + * 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) +{ + int retval = -1; + char * p; + + if ((NULL == s) || (NULL == ip_addr)) { + return -1; + } + + memset(ip_addr, 0, addr_size); + + p = strpbrk(s, ":"); + + if (p) { + /* colon is present */ + if (ip_mode) { + 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; + } + } else { + /* colon is not present */ + strncpy(ip_addr, s, 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 */ + +/** 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; + +#ifndef WIN32 + 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; + + int i, effectiveargc = 0; + char ** effectiveargv = NULL; + char * linebuffer = NULL; + + n2n_sock_str_t local_sockbuf; + struct sockaddr_in sa; + socklen_t sa_len; + + n2n_edge_t eee; /* single instance for this program */ + + if (-1 == edge_init(&eee)) { + traceEvent(TRACE_ERROR, "Failed in edge_init"); + exit(1); + } + + if (getenv("N2N_KEY")) { + encrypt_key = strdup(getenv("N2N_KEY")); + } + +#ifdef WIN32 + tuntap_dev_name[0] = '\0'; +#endif + memset(&(eee.supernode), 0, sizeof(eee.supernode)); + eee.supernode.family = AF_INET; + + linebuffer = (char *) malloc(MAX_CMDLINE_BUFFER_LENGTH); + if (!linebuffer) { + traceEvent(TRACE_ERROR, "Unable to allocate memory"); + exit(1); + } + snprintf(linebuffer, MAX_CMDLINE_BUFFER_LENGTH, "%s", argv[0]); + +#ifdef WIN32 + for(i=0; i < (int)strlen(linebuffer); i++) + if(linebuffer[i] == '\\') linebuffer[i] = '/'; +#endif + + for (i = 1; i < argc; ++i) { + if (argv[i][0] == '@') { + if (readConfFile(&argv[i][1], linebuffer) < 0) + exit(1); /* <<<<----- check */ + } else if ((strlen(linebuffer) + strlen(argv[i]) + 2) + < MAX_CMDLINE_BUFFER_LENGTH) + { + strncat(linebuffer, " ", 1); + strncat(linebuffer, argv[i], strlen(argv[i])); + } else { + traceEvent(TRACE_ERROR, "too many argument"); + exit(1); + } + } + /* strip trailing spaces */ + while (strlen(linebuffer) && linebuffer[strlen(linebuffer) - 1] == ' ') + linebuffer[strlen(linebuffer) - 1] = '\0'; + + /* build the new argv from the linebuffer */ + effectiveargv = buildargv(&effectiveargc, linebuffer); + + if (linebuffer) { + free(linebuffer); + linebuffer = NULL; + } + + /* {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 '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 'i': /* holepunch-interval */ + { + eee.holepunch_interval = atoi(optarg); + eee.holepunch_interval = MAX(eee.holepunch_interval, REGISTER_SUPER_INTERVAL_MIN); + eee.holepunch_interval = MIN(eee.holepunch_interval, REGISTER_SUPER_INTERVAL_MAX); + break; + } + case 'L': /* local ip */ + { + eee.local_sock_ena = 1; + strncpy(eee.local_ip_str, optarg, N2N_EDGE_LOCAL_IP_SIZE); + if (N2N_EDGE_LOCAL_IP_SIZE > 0) + eee.local_ip_str[N2N_EDGE_LOCAL_IP_SIZE - 1] = '\0'; + traceEvent(TRACE_DEBUG, "Storing local_ip_str = %s\n", (eee.sn_ip_array[eee.sn_num])); + 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) { + useSyslog = 1; /* traceEvent output now goes to syslog. */ + if (-1 == daemon(0, 0)) { + traceEvent(TRACE_ERROR, "Failed to become daemon."); + exit(-5); + } + } +#endif /* #ifdef N2N_HAVE_DAEMON */ + + 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]) ); + } + + supernode2addr(&(eee.supernode), eee.sn_ip_array[eee.sn_idx]); + + for (i = 0; i < effectiveargc; ++i) { + free(effectiveargv[i]); + } + free(effectiveargv); + effectiveargv = 0; + effectiveargc = 0; + + if (!( +#ifdef __linux__ + (tuntap_dev_name[0] != 0) && +#endif + (eee.community_name[0] != 0) && (ip_addr[0] != 0))) { + help(); + } + + if ((NULL == encrypt_key) && (0 == strlen(eee.keyschedule))) { + traceEvent(TRACE_WARNING, "Encryption is disabled in edge."); + + eee.null_transop = 1; + } + +#ifndef WIN32 + /* If running suid root then we need to setuid before using the force. */ + setuid(0); + /* setgid( 0 ); */ +#endif + + if (strcmp("dhcp", ip_mode) == 0) { + traceEvent(TRACE_NORMAL, "Dynamic IP address assignment enabled."); + + eee.dyn_ip_mode = 1; + } else { + traceEvent(TRACE_NORMAL, "ip_mode='%s'", ip_mode); + } + + if (tuntap_open(&(eee.device), tuntap_dev_name, ip_mode, ip_addr, netmask, + device_mac, mtu) < 0) + return (-1); + +#ifndef WIN32 + if ((userid != 0) || (groupid != 0)) { + traceEvent(TRACE_NORMAL, + "Interface up. Dropping privileges to uid=%d, gid=%d", + (signed int)userid, (signed int)groupid); + + /* Finished with the need for root privileges. Drop to unprivileged user. */ + setreuid(userid, userid); + setregid(groupid, groupid); + } +#endif + + 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 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 */ + + /* set up crypto engine */ + int err = crypto_init(); + if (err) { + traceEvent(TRACE_ERROR, "Failed to initialize crypto engine: %d", err); + 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); + } + + if ((initial_supernode_registration(&eee)) != 0) { + traceEvent(TRACE_ERROR, "Failed to register with supernode"); + return(-1); + } + + if (eee.local_sock_ena) { + sa_len = sizeof(sa); + if (getsockname(eee.udp_sock, (struct sockaddr *) &sa, &sa_len) == -1) { + traceEvent(TRACE_ERROR, "getsockname() failed"); + return (-1); + } + local_port = ntohs(sa.sin_port); + memset(&(eee.local_sock), 0, sizeof(eee.local_sock)); + + if ((eee.local_sock_ena = localip2addr(&(eee.local_sock), + eee.local_ip_str, local_port) )) + traceEvent(TRACE_NORMAL, "Local Socket is %s", + sock_to_cstr(local_sockbuf, &(eee.local_sock))); + } + + 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"); + + return run_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; + time_t lastStatCalc = 0; + time_t lastStatCalcDiff; + +#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 = 0; + if ((nowTime - eee->last_purge) >= PURGE_REGISTRATION_FREQUENCY) { + numPurged += hashed_purge_expired_registrations(eee->known_peers); + numPurged += hashed_purge_expired_registrations(eee->pending_peers); + eee->last_purge = nowTime; + } + if (numPurged > 0) { + traceEvent(TRACE_NORMAL, + "Peer removed: pending=%u, operational=%u", + (unsigned int)hashed_peer_list_t_size(eee->pending_peers), + (unsigned int)hashed_peer_list_t_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; + } + + lastStatCalcDiff = nowTime - lastStatCalc; + if (lastStatCalcDiff > STAT_CALC_INTERVAL) { + // traceEvent(TRACE_NORMAL, "recalc bps."); + eee->tx_bps_p2p = eee->tx_bit_p2p / (size_t)lastStatCalcDiff; + eee->tx_bit_p2p = 0; + eee->tx_bps_sup = eee->tx_bit_sup / (size_t)lastStatCalcDiff; + eee->tx_bit_sup = 0; + eee->rx_bps_p2p = eee->rx_bit_p2p / (size_t)lastStatCalcDiff; + eee->rx_bit_p2p = 0; + eee->rx_bps_sup = eee->rx_bit_sup / (size_t)lastStatCalcDiff; + eee->rx_bit_sup = 0; + lastStatCalc = nowTime; + } + + } /* while */ + + send_deregister(eee, &(eee->supernode)); + + closesocket(eee->udp_sock); + tuntap_close(&(eee->device)); + + edge_deinit(eee); + + return (0); +} + diff --git a/n2n_v2/gen_keyfile.py b/gen_keyfile.py similarity index 100% rename from n2n_v2/gen_keyfile.py rename to gen_keyfile.py diff --git a/n2n_v1/lzoconf.h b/lzoconf.h similarity index 94% rename from n2n_v1/lzoconf.h rename to lzoconf.h index cc437f1..1fa170c 100644 --- a/n2n_v1/lzoconf.h +++ b/lzoconf.h @@ -2,19 +2,7 @@ This file is part of the LZO real-time data compression library. - Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 - 2008 Markus Franz Xaver Johannes Oberhumer All Rights Reserved. The LZO library is free software; you can redistribute it and/or diff --git a/n2n_v1/lzodefs.h b/lzodefs.h similarity index 98% rename from n2n_v1/lzodefs.h rename to lzodefs.h index 1805637..0c252e0 100644 --- a/n2n_v1/lzodefs.h +++ b/lzodefs.h @@ -2,19 +2,7 @@ This file is part of the LZO real-time data compression library. - Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 - 2008 Markus Franz Xaver Johannes Oberhumer All Rights Reserved. The LZO library is free software; you can redistribute it and/or diff --git a/n2n_v1/minilzo.c b/minilzo.c similarity index 99% rename from n2n_v1/minilzo.c rename to minilzo.c index 6a62b31..42a65e6 100644 --- a/n2n_v1/minilzo.c +++ b/minilzo.c @@ -2,19 +2,7 @@ This file is part of the LZO real-time data compression library. - Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 - 2008 Markus Franz Xaver Johannes Oberhumer All Rights Reserved. The LZO library is free software; you can redistribute it and/or diff --git a/n2n_v1/minilzo.h b/minilzo.h similarity index 77% rename from n2n_v1/minilzo.h rename to minilzo.h index 0aff50e..40d9ad1 100644 --- a/n2n_v1/minilzo.h +++ b/minilzo.h @@ -2,19 +2,7 @@ This file is part of the LZO real-time data compression library. - Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 - 2008 Markus Franz Xaver Johannes Oberhumer All Rights Reserved. The LZO library is free software; you can redistribute it and/or diff --git a/n2n.c b/n2n.c new file mode 100644 index 0000000..6485b97 --- /dev/null +++ b/n2n.c @@ -0,0 +1,479 @@ +/* + * (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. + * + * 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 + * + * Code contributions courtesy of: + * Massimo Torquati + * Matt Gilg + * + */ + +#include "n2n.h" +#include "minilzo.h" +#include "crypto/aes.h" +#include + +/* sglib hash table implementation */ + +SGLIB_DEFINE_LIST_FUNCTIONS(peer_info_t, PEER_INFO_COMPARATOR, next) +SGLIB_DEFINE_HASHED_CONTAINER_FUNCTIONS(peer_info_t, PEER_HASH_TAB_SIZE, + peer_info_t_hash_function) + +unsigned int peer_info_t_hash_function(peer_info_t *e) +{ +#if N2N_MAC_SIZE != 6 +#error not implemented yet! +#else + short i = 0; + uint32_t tmp = 0; + /* Q: why is the hashing implemented like this? + * A: because the MAC addresses basically consist of two parts + * the first three bytes are a organisation unique identifier + * the second three bytes are a interface unique identifier + * therefore if all the (randomly) generated MAC addresses of the + * tun/tap interfaces all have the same organisation unique identifier + * the hashing performance is best if only the interface unique identifier + * is taken into account + */ + for (; i < N2N_MAC_SIZE / 2; i++) { + tmp |= (e->mac_addr[i] ^ e->mac_addr[(N2N_MAC_SIZE / 2) + i]) + << (N2N_MAC_SIZE / 2 - 1 - i); + } + return tmp; +#endif +} +; + +const uint8_t broadcast_addr[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +const uint8_t multicast_addr[6] = {0x01, 0x00, 0x5E, 0x00, 0x00, 0x00}; /* First 3 bytes are meaningful */ +const uint8_t ipv6_multicast_addr[6] = {0x33, 0x33, 0x00, 0x00, 0x00, 0x00}; /* First 2 bytes are meaningful */ + +/* ************************************** */ + +SOCKET open_socket(int local_port, int bind_any) +{ + SOCKET sock_fd; + struct sockaddr_in local_address; + int sockopt = 1; + + if ((sock_fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { + traceEvent(TRACE_ERROR, "Unable to create socket [%s][%d]\n", + strerror(errno), sock_fd); + return(-1); + } + +#ifndef WIN32 + /* fcntl(sock_fd, F_SETFL, O_NONBLOCK); */ +#endif + + 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) { + traceEvent(TRACE_ERROR, "Bind error [%s]\n", strerror(errno)); + return(-1); + } + + return (sock_fd); +} + +int traceLevel = 2 /* NORMAL */; +int useSyslog = 0, syslog_opened = 0; + +#define N2N_TRACE_DATESIZE 32 +void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...) +{ + va_list va_ap; + + if(eventTraceLevel <= traceLevel) { + char buf[2048]; + char out_buf[640]; + char theDate[N2N_TRACE_DATESIZE]; + char *extra_msg = ""; + time_t theTime = time(NULL); +#ifdef WIN32 + 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), + * those without the headers !defined(USE_SYSLOG) + * those where it's parametrically off... + */ + + memset(buf, 0, sizeof(buf)); + strftime(theDate, N2N_TRACE_DATESIZE, "%d/%b/%Y %H:%M:%S", localtime(&theTime)); + + va_start (va_ap, format); + vsnprintf(buf, sizeof(buf)-1, format, va_ap); + va_end(va_ap); + + if(eventTraceLevel == 0 /* TRACE_ERROR */) + extra_msg = "ERROR: "; + else if(eventTraceLevel == 1 /* TRACE_WARNING */) + extra_msg = "WARNING: "; + + while(buf[strlen(buf)-1] == '\n') + buf[strlen(buf)-1] = '\0'; + +#ifndef WIN32 + if(useSyslog) { + if(!syslog_opened) { + openlog("n2n", LOG_PID, LOG_DAEMON); + syslog_opened = 1; + } + + snprintf(out_buf, sizeof(out_buf), "%s%s", extra_msg, buf); + syslog(LOG_INFO, "%s", out_buf); + } else { + snprintf(out_buf, sizeof(out_buf), "%s [%11s:%4d] %s%s", theDate, file, line, extra_msg, buf); + printf("%s\n", out_buf); + fflush(stdout); + } +#else + /* this is the WIN32 code */ + 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); +#endif + } +} + +/* *********************************************** */ + +/* addr should be in network order. Things are so much simpler that way. */ +char* intoa(uint32_t /* host order */addr, char* buf, uint16_t buf_len) +{ + char *cp, *retStr; + uint8_t byteval; + int n; + + cp = &buf[buf_len]; + *--cp = '\0'; + + n = 4; + do { + byteval = addr & 0xff; + *--cp = byteval % 10 + '0'; + byteval /= 10; + if (byteval > 0) { + *--cp = byteval % 10 + '0'; + byteval /= 10; + if (byteval > 0) + *--cp = byteval + '0'; + } + *--cp = '.'; + addr >>= 8; + } while (--n > 0); + + /* Convert the string to lowercase */ + retStr = (char*) (cp + 1); + + return (retStr); +} + +/* *********************************************** */ + +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); +} + +/* *********************************************** */ + +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 ); + + return is_broadcast || is_multicast || is_ipv6_multicast; + +} + +/* http://www.faqs.org/rfcs/rfc908.html */ + +/* *********************************************** */ + +char* msg_type2str(n2n_pc_t msg_type) +{ + switch (msg_type) { + case n2n_ping: + return "MSG_TYPE_PING"; + case n2n_pre_handshake: + return "N2N_TYPE_PRE-HANDSHAKE"; + case n2n_handshake: + return "N2N_TYPE_HANDSHAKE"; + case n2n_holepunch: + return "N2N_TYPE_HOLEPUNCH"; + case n2n_supernode_register: + return "N2N_TYPE_SUPERNODE-REGISTER"; + case n2n_address_resolution: + return "N2N_TYPE_ADDRESS-RESOLUTION"; + case n2n_keep_alive: + return "N2N_TYPE_KEEP-ALIVE"; + case n2n_edge_connect: + return "N2N_TYPE_EDGE-CONNECT"; + case n2n_edge_resume: + return "N2N_TYPE_EDGE-RESUME"; + default: + return ("???"); + } + + return ("???"); +} + +/* *********************************************** */ + +void hexdump(const uint8_t * buf, size_t len) +{ + size_t i; + + if (0 == len) { + return; + } + + for (i = 0; i < len; i++) { + if ((i > 0) && ((i % 16) == 0)) { + printf("\n"); + } + printf("%02X ", buf[i] & 0xFF); + } + + printf("\n"); +} + +/* *********************************************** */ + +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", n2n_sw_version, + n2n_sw_osName, n2n_sw_buildDate); +} + +/** Find the peer entry in list with mac_addr equal to mac. + * + * Does not modify the list. + * + * @return NULL if not found; otherwise pointer to peer entry. + */ +peer_info_t * find_peer_by_mac(peer_info_t ** list, const n2n_mac_t mac) +{ + peer_info_t tmp; + memcpy(tmp.mac_addr, mac, sizeof(n2n_mac_t)); + + return sglib_hashed_peer_info_t_find_member(list, &tmp); +} + +/** Return the number of elements in the list. + * + */ +size_t peer_list_size(const struct peer_info * list) +{ + size_t retval = 0; + + while (list) { + ++retval; + list = list->next; + } + + return retval; +} + +size_t hashed_peer_list_t_size(peer_info_t** htab) +{ + peer_info_t *ll; + struct sglib_hashed_peer_info_t_iterator it; + size_t retval = 0; + + for (ll = sglib_hashed_peer_info_t_it_init(&it, htab); ll != NULL; ll = + sglib_hashed_peer_info_t_it_next(&it)) { + ++retval; + } + + return retval; +} + +/** Add new to the head of list. If list is NULL; create it. + * + * 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) +{ + new->next = *list; + new->last_seen = time(NULL); + *list = new; +} + +size_t purge_with_function(struct peer_info ** peer_list, + size_t(*purger)(struct peer_info ** peer_list, time_t purge_before)) +{ + time_t now = time(NULL); + size_t num_reg = 0; + + traceEvent(TRACE_INFO, "Purging old registrations"); + + num_reg = purger(peer_list, now - REGISTRATION_TIMEOUT); + + traceEvent(TRACE_INFO, "Remove %ld registrations", num_reg); + + return num_reg; +} + +void dealloc_peer(peer_info_t* peer) +{ + free(peer->sockets); + /* free encryption handle */ + /* TODO: what are the appropriate functions? + aes_gcm_session_destroy(peer->aes_gcm_tx_ctx); + aes_gcm_session_destroy(peer->aes_gcm_rx_ctx); + */ + free(peer); +} + +/** Purge old items from the peer_list hashtable and return the number of items + * that were removed. */ +size_t purge_hashed_peer_list_t(peer_info_t ** peer_list, time_t purge_before) +{ + peer_info_t *ll; + struct sglib_hashed_peer_info_t_iterator it; + size_t retval = 0; + + for (ll = sglib_hashed_peer_info_t_it_init(&it, peer_list); ll != NULL; ll = + sglib_hashed_peer_info_t_it_next(&it)) { + if (ll->last_seen < purge_before) { + ++retval; + sglib_hashed_peer_info_t_delete(peer_list, ll); + dealloc_peer(ll); + } + } + + return retval; +} + +size_t hashed_purge_expired_registrations(peer_info_t ** peer_list) +{ + return purge_with_function(peer_list, purge_hashed_peer_list_t); +} + +size_t clear_hashed_peer_info_t_list(peer_info_t ** peer_list) +{ + peer_info_t *ll; + struct sglib_hashed_peer_info_t_iterator it; + size_t retval = 0; + + for (ll = sglib_hashed_peer_info_t_it_init(&it, peer_list); ll != NULL; ll = + sglib_hashed_peer_info_t_it_next(&it)) { + ++retval; + sglib_hashed_peer_info_t_delete(peer_list, ll); + dealloc_peer(ll); + } + + return retval; +} + +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)); +} + +extern int str2mac(uint8_t * outmac /* 6 bytes */, const char * s) +{ + size_t i; + + /* break it down as one case for the first "HH", the 5 x through loop for + * each ":HH" where HH is a two hex nibbles in ASCII. */ + + *outmac = hex2byte(s); + ++outmac; + s += 2; /* don't skip colon yet - helps generalise loop. */ + + for (i = 1; i < 6; ++i) { + s += 1; + *outmac = hex2byte(s); + ++outmac; + s += 2; + } + + return 0; /* ok */ +} + +extern char * sock_to_cstr(n2n_sock_str_t out, 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 */ + 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", (a[0] & 0xff), + (a[1] & 0xff), (a[2] & 0xff), (a[3] & 0xff), 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 */ + { + case AF_INET: + 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; + } + + return 0; +} + diff --git a/n2n_v2/n2n.h b/n2n.h similarity index 68% rename from n2n_v2/n2n.h rename to n2n.h index 6fb6c7a..e33a78a 100644 --- a/n2n_v2/n2n.h +++ b/n2n.h @@ -25,22 +25,21 @@ #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 + */ #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 @@ -90,12 +89,11 @@ #include #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 */ -} __attribute__ ((__packed__)); +struct ether_hdr { + 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; @@ -116,8 +114,9 @@ typedef struct ether_hdr ether_hdr_t; #endif /* #ifndef WIN32 */ #include - #include +#include +#include #ifdef WIN32 #include "win32/wintap.h" @@ -132,11 +131,11 @@ typedef struct ether_hdr ether_hdr_t; #define N2N_IFNAMSIZ 16 /* 15 chars * NULL */ #ifndef WIN32 typedef struct tuntap_dev { - int fd; - uint8_t mac_addr[6]; - uint32_t ip_addr, device_mask; - uint16_t mtu; - char dev_name[N2N_IFNAMSIZ]; + int fd; + uint8_t mac_addr[6]; + uint32_t ip_addr, device_mask; + uint16_t mtu; + char dev_name[N2N_IFNAMSIZ]; } tuntap_dev; #define SOCKET int @@ -144,18 +143,6 @@ typedef struct tuntap_dev { #define QUICKLZ 1 -/* N2N packet header indicators. */ -#define MSG_TYPE_REGISTER 1 -#define MSG_TYPE_DEREGISTER 2 -#define MSG_TYPE_PACKET 3 -#define MSG_TYPE_REGISTER_ACK 4 -#define MSG_TYPE_REGISTER_SUPER 5 -#define MSG_TYPE_REGISTER_SUPER_ACK 6 -#define MSG_TYPE_REGISTER_SUPER_NAK 7 -#define MSG_TYPE_FEDERATION 8 -#define MSG_TYPE_PEER_INFO 9 -#define MSG_TYPE_QUERY_PEER 10 - /* Set N2N_COMPRESSION_ENABLED to 0 to disable lzo1x compression of ethernet * frames. Doing this will break compatibility with the standard n2n packet * format so do it only for experimentation. All edges must be built with the @@ -182,21 +169,22 @@ 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; - int num_sockets; - n2n_sock_t * sockets; - time_t last_seen; - time_t last_sent_query; - size_t timeout; + struct peer_info * next; + n2n_community_t community_name; + n2n_mac_t mac_addr; + n2n_sock_t sock; + int num_sockets; + n2n_sock_t * sockets; + time_t last_seen; + time_t last_sent_query; + size_t timeout; + gnutls_cipher_hd_t *aes_gcm_tx_ctx; + gnutls_cipher_hd_t *aes_gcm_rx_ctx; }; typedef struct peer_info peer_info_t; /* sglib hash table defines */ #define PEER_HASH_TAB_SIZE 53 // prime number - /* #define PEER_INFO_COMPARATOR(e1, e2) (\ for(int i = 0; i < N2N_MAC_SIZE; i++) {\ int8_t tmp = (e1)->mac_addr[i] - (e2)->mac_addr[i]; \ @@ -205,18 +193,19 @@ typedef struct peer_info peer_info_t; } \ return 0; \ }) -*/ + */ #define PEER_INFO_COMPARATOR(e1, e2) (strncmp((const char*)(e1)->mac_addr, (const char*)(e2)->mac_addr, sizeof(n2n_mac_t))) unsigned int peer_info_t_hash_function(peer_info_t *e); SGLIB_DEFINE_LIST_PROTOTYPES(peer_info_t, PEER_INFO_COMPARATOR, next) -SGLIB_DEFINE_HASHED_CONTAINER_PROTOTYPES(peer_info_t, PEER_HASH_TAB_SIZE, peer_info_t_hash_function) - -struct n2n_edge; /* defined in edge.c */ -typedef struct n2n_edge n2n_edge_t; +SGLIB_DEFINE_HASHED_CONTAINER_PROTOTYPES(peer_info_t, PEER_HASH_TAB_SIZE, + peer_info_t_hash_function) +struct n2n_edge; +/* defined in edge.c */ +typedef struct n2n_edge n2n_edge_t; /* ************************************** */ @@ -252,10 +241,10 @@ extern const uint8_t multicast_addr[6]; /* Functions */ extern void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...); -extern int tuntap_open(tuntap_dev *device, char *dev, const char *address_mode, char *device_ip, - char *device_mask, const char * device_mac, int mtu); -extern int tuntap_read(struct tuntap_dev *tuntap, unsigned char *buf, int len); -extern int tuntap_write(struct tuntap_dev *tuntap, unsigned char *buf, int len); +extern int tuntap_open(tuntap_dev *device, char *dev, const char *address_mode, + char *device_ip, char *device_mask, const char * device_mac, int mtu); +extern int tuntap_read(struct tuntap_dev *tuntap, unsigned char *buf, int len); +extern int tuntap_write(struct tuntap_dev *tuntap, unsigned char *buf, int len); extern void tuntap_close(struct tuntap_dev *tuntap); extern void tuntap_get_address(struct tuntap_dev *tuntap); @@ -263,35 +252,28 @@ extern SOCKET open_socket(int local_port, int bind_any); extern char* intoa(uint32_t addr, char* buf, uint16_t buf_len); extern char* macaddr_str(macstr_t buf, const n2n_mac_t mac); -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 ); +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); -extern int sock_equal( const n2n_sock_t * a, - const n2n_sock_t * b ); +extern int sock_equal(const n2n_sock_t * a, const n2n_sock_t * b); extern uint8_t is_multi_broadcast(const uint8_t * dest_mac); -extern char* msg_type2str(uint16_t msg_type); +extern char* msg_type2str(n2n_pc_t msg_type); extern void hexdump(const uint8_t * buf, size_t len); void print_n2n_version(); - /* Operations on peer_info lists. */ -struct peer_info * find_peer_by_mac( peer_info_t ** list, - const n2n_mac_t mac ); -void peer_list_add( struct peer_info * * list, - struct peer_info * new ); -size_t peer_list_size( const struct peer_info * list ); -void dealloc_peer( peer_info_t* peer ); +struct peer_info * find_peer_by_mac(peer_info_t ** list, const n2n_mac_t mac); +void peer_list_add(struct peer_info * * list, struct peer_info * new); +size_t peer_list_size(const struct peer_info * list); +void dealloc_peer(peer_info_t* peer); size_t hashed_peer_list_t_size(peer_info_t** htab); -size_t purge_with_function(struct peer_info ** peer_list, size_t(*purger)(struct peer_info ** peer_list, time_t purge_before)); -size_t purge_peer_list( struct peer_info ** peer_list, - time_t purge_before ); +size_t purge_with_function(struct peer_info ** peer_list, + size_t(*purger)(struct peer_info ** peer_list, time_t purge_before)); size_t purge_hashed_peer_list_t(peer_info_t ** peer_list, time_t purge_before); -size_t clear_peer_list( struct peer_info ** peer_list ); +size_t clear_peer_list(struct peer_info ** peer_list); size_t clear_hashed_peer_info_t_list(peer_info_t ** peer_list); -size_t purge_expired_registrations( struct peer_info ** peer_list ); size_t hashed_purge_expired_registrations(struct peer_info ** peer_list); /* version.c */ diff --git a/n2n_v2/n2n.spec b/n2n.spec similarity index 100% rename from n2n_v2/n2n.spec rename to n2n.spec diff --git a/n2n_keyfile.c b/n2n_keyfile.c new file mode 100644 index 0000000..6792a1a --- /dev/null +++ b/n2n_keyfile.c @@ -0,0 +1,196 @@ +/* (c) 2009 Richard Andrews */ +/* Contributions from: + * - Jozef Kralik + */ + +#include "n2n.h" +#include "n2n_keyfile.h" +#include +#include +#include +#include + +#ifdef WIN32 +char *strsep( char **ppsz_string, const char *psz_delimiters ) +{ + char *p; + char *psz_string = *ppsz_string; + if(!psz_string) + return NULL; + + p = strpbrk(psz_string, psz_delimiters); + if( !p ) { + *ppsz_string = NULL; + return psz_string; + } + *p++ = '\0'; + + *ppsz_string = p; + return psz_string; +} +#endif + +/* Parse hex nibbles in ascii until a non-nibble character is found. Nibble + * characters are 0-9, a-f and A-F. + * + * Return number of bytes parsed into keyBuf or a negative error code. + */ +ssize_t n2n_parse_hex(uint8_t * keyBuf, size_t keyLen, const char * textKey, + size_t textLen) +{ + ssize_t retval = 0; + uint8_t * pout = keyBuf; + size_t octet = 0; + const char * textEnd; + const char * pbeg; + + textEnd = textKey + textLen; + pbeg = textKey; + + while ((pbeg + 1 < textEnd) && (retval < (ssize_t) keyLen)) { + if (1 != sscanf(pbeg, "%02x", (unsigned int*) &octet)) { + retval = -1; + break; + } + + *pout = (octet & 0xff); + ++pout; + ++retval; + pbeg += 2; + } + + return retval; +} + +static int parseKeyLine(n2n_cipherspec_t * spec, const char * linein) +{ + /* parameters are separated by whitespace */ + char line[N2N_KEYFILE_LINESIZE]; + char * lp = line; + const char * token; + strncpy(line, linein, N2N_KEYFILE_LINESIZE); + + memset(spec, 0, sizeof(n2n_cipherspec_t)); + + /* decode valid_from time */ + token = strsep(&lp, DELIMITERS); + if (!token) { + goto error; + } + spec->valid_from = atol(token); + + /* decode valid_until time */ + token = strsep(&lp, DELIMITERS); + if (!token) { + goto error; + } + spec->valid_until = atol(token); + + /* decode the transform number */ + token = strsep(&lp, DELIMITERS); + if (!token) { + goto error; + } + spec->t = atoi(token); + + /* The reset if opaque key data */ + token = strsep(&lp, DELIMITERS); + if (!token) { + goto error; + } + + strncpy((char *)spec->opaque, token, N2N_MAX_KEYSIZE); + spec->opaque_size = strlen((char *) spec->opaque); + + return 0; + +error: + return -1; +} + +#define SEP "/" + +int validCipherSpec(const n2n_cipherspec_t * k, time_t now) +{ + if (k->valid_until < k->valid_from) { + goto bad; + } + if (k->valid_from > now) { + goto bad; + } + if (k->valid_until < now) { + goto bad; + } + + return 0; + +bad: + return -1; +} + +/* Read key control file and return the number of specs stored or a negative + * error code. + * + * As the specs are read in the from and until time values are compared to + * present time. Only those keys which are valid are stored. + */ +int n2n_read_keyfile(n2n_cipherspec_t * specs, /* fill out this array of cipherspecs */ +size_t numspecs, /* number of slots in the array. */ +const char * ctrlfile_path) /* path to control file */ +{ + /* Each line contains one cipherspec. */ + + int retval = 0; + FILE * fp = NULL; + size_t idx = 0; + time_t now = time(NULL); + + traceEvent(TRACE_DEBUG, "Reading '%s'\n", ctrlfile_path); + + fp = fopen(ctrlfile_path, "r"); + if (fp) { + /* Read the file a line a time with fgets. */ + char line[N2N_KEYFILE_LINESIZE]; + size_t lineNum = 0; + + while (idx < numspecs) { + n2n_cipherspec_t * k = &(specs[idx]); + fgets(line, N2N_KEYFILE_LINESIZE, fp); + ++lineNum; + + if (strlen(line) > 1) { + if (0 == parseKeyLine(k, line)) { + if (k->valid_until > now) { + traceEvent(TRACE_INFO, + " --> [%u] from %lu, until %lu, transform=%hu, data=%s\n", + idx, k->valid_from, k->valid_until, k->t, k->opaque); + + ++retval; + ++idx; + } else { + traceEvent(TRACE_INFO, + " --X [%u] from %lu, until %lu, transform=%hu, data=%s\n", + idx, k->valid_from, k->valid_until, k->t, k->opaque); + } + } else { + traceEvent(TRACE_WARNING, "Failed to decode line %u\n", lineNum); + } + } + + if (feof(fp)) { + break; + } + + line[0] = 0; /* this line has been consumed */ + } + + fclose(fp); + fp = NULL; + } else { + traceEvent(TRACE_ERROR, "Failed to open '%s'\n", ctrlfile_path); + retval = -1; + } + + return retval; +} + diff --git a/n2n_v2/n2n_keyfile.h b/n2n_keyfile.h similarity index 75% rename from n2n_v2/n2n_keyfile.h rename to n2n_keyfile.h index 6068df1..763575e 100644 --- a/n2n_v2/n2n_keyfile.h +++ b/n2n_keyfile.h @@ -58,7 +58,6 @@ #if !defined( N2N_KEYFILE_H_ ) #define N2N_KEYFILE_H_ - #include "n2n_wire.h" #include @@ -68,34 +67,29 @@ #define N2N_KEYFILE_LINESIZE 256 /** This structure stores an encryption cipher spec. */ -struct n2n_cipherspec -{ - n2n_transform_t t; /* N2N_TRANSFORM_ID_xxx for this spec. */ - time_t valid_from; /* Start using the key at this time. */ - time_t valid_until; /* Key is valid if time < valid_until. */ - uint16_t opaque_size; /* Size in bytes of key. */ - uint8_t opaque[N2N_MAX_KEYSIZE];/* Key matter. */ +struct n2n_cipherspec { + n2n_transform_t t; /* N2N_TRANSFORM_ID_xxx for this spec. */ + time_t valid_from; /* Start using the key at this time. */ + time_t valid_until; /* Key is valid if time < valid_until. */ + uint16_t opaque_size; /* Size in bytes of key. */ + uint8_t opaque[N2N_MAX_KEYSIZE]; /* Key matter. */ }; typedef struct n2n_cipherspec n2n_cipherspec_t; - -static const char * const DELIMITERS=" \t\n\r"; - +static const char * const DELIMITERS = " \t\n\r"; /** @return number of cipherspec items filled. */ -int n2n_read_keyfile( n2n_cipherspec_t * specs, /* fill out this array of cipherspecs */ - size_t numspecs, /* number of slots in the array. */ - const char * ctrlfile_path ); /* path to control file */ +int n2n_read_keyfile(n2n_cipherspec_t * specs, /* fill out this array of cipherspecs */ +size_t numspecs, /* number of slots in the array. */ +const char * ctrlfile_path); /* path to control file */ -int validCipherSpec( const n2n_cipherspec_t * k, - time_t now ); +int validCipherSpec(const n2n_cipherspec_t * k, time_t now); -ssize_t n2n_parse_hex( uint8_t * keyBuf, - size_t keyMax, - const char * textKey, - size_t textLen ); +ssize_t n2n_parse_hex(uint8_t * keyBuf, size_t keyMax, const char * textKey, + size_t textLen); /*----------------------------------------------------------------------------*/ #endif /* #if !defined( N2N_KEYFILE_H_ ) */ + diff --git a/n2n_transforms.h b/n2n_transforms.h new file mode 100644 index 0000000..2aeca51 --- /dev/null +++ b/n2n_transforms.h @@ -0,0 +1,67 @@ +/* (c) 2009 Richard Andrews */ + +#if !defined(N2N_TRANSFORMS_H_) +#define N2N_TRANSFORMS_H_ + +#include "n2n_keyfile.h" +#include "n2n_wire.h" + +#define N2N_TRANSFORM_ID_INVAL 0 /* marks uninitialised data */ +#define N2N_TRANSFORM_ID_NULL 1 +#define N2N_TRANSFORM_ID_TWOFISH 2 +#define N2N_TRANSFORM_ID_AESCBC 3 +#define N2N_TRANSFORM_ID_LZO 4 +#define N2N_TRANSFORM_ID_TWOFISH_LZO 5 +#define N2N_TRANSFORM_ID_AESCBC_LZO 6 +#define N2N_TRANSFORM_ID_USER_START 64 +#define N2N_TRANSFORM_ID_MAX 65535 + +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. */ +}; + +typedef struct n2n_tostat n2n_tostat_t; + +typedef int (*n2n_transdeinit_f)(n2n_trans_op_t * arg); +typedef int (*n2n_transaddspec_f)(n2n_trans_op_t * arg, + const n2n_cipherspec_t * cspec); +typedef n2n_tostat_t (*n2n_transtick_f)(n2n_trans_op_t * arg, time_t now); + +typedef int (*n2n_transform_f)(n2n_trans_op_t * arg, uint8_t * outbuf, + size_t out_len, const uint8_t * inbuf, size_t in_len); + +/** Holds the info associated with a data transform plugin. + * + * When a packet arrives the transform ID is extracted. This defines the code + * 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. */ + + 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 */ +}; + +/* Setup a single twofish SA for single-key operation. */ +int transop_twofish_setup(n2n_trans_op_t * ttt, n2n_sa_t sa_num, + uint8_t * encrypt_pwd, uint32_t encrypt_pwd_len); + +/* Initialise an empty transop ready to receive cipherspec elements. */ +int transop_twofish_init(n2n_trans_op_t * ttt); +int transop_aes_init(n2n_trans_op_t * ttt); +void transop_null_init(n2n_trans_op_t * ttt); + +#endif /* #if !defined(N2N_TRANSFORMS_H_) */ + diff --git a/n2n_v1/HACKING b/n2n_v1/HACKING deleted file mode 100644 index b0b9e67..0000000 --- a/n2n_v1/HACKING +++ /dev/null @@ -1,273 +0,0 @@ -file: HACKING - -Last updated: 2008-04-10 - --------- -(C) 2008 - Richard Andrews - -This program and document 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 - --------- - - -This file describes the internals of n2n. Read this before starting to modify -the code. Because coding examples may be present in this document it is licensed -under the GPL rather than FDL. - - -SYMMETRIC NAT -------------- - -Symmetric NAT is a form of firewall NAT in which an UDP packets are only passed -back to an inside host socket when the return packets originate from the outside -socket to which the initiating UDP packets were sent. This means that when an -inside host sends UDP to some outside socket; other hosts cannot piggyback on -this opening in the firewall to send data to the inside host. - -When two inside hosts are both behind symmetric NAT, peer-to-peer packet -exchange is not possible via n2n. These hosts will require the supernode to -relay packets. - - -ARP CACHE ---------- - -n2n makes use of the host operating system's own ARP cache. Each edge node -allocates a random MAC address to itself. This MAC is constant for the life of -the edge process. ARP packets are passed around as broadcast ethernet packets -over n2n and these packets cause the native ARP cache to be updated. - -Edge nodes send gratuitous ARP packets on startup. See GRATUITOUS ARP below. - - -REGISTRATION AND PEER-TO-PEER COMMUNICATION SETUP -------------------------------------------------- - -A and B are edge nodes with public sockets Apub and Bpub; and private network -addresses A and B respectively. S is the supernode. - -A sends {REGISTER,Amac} to S. S registers {Amac->Apub}. -B sends {REGISTER,Bmac} to S. S registers {Bmac->Bpub}. - -Now ping from A to B. - -A sends broadcast "arp who-has B" to S. S relays the packet to all known edge -nodes. B replies "B at Bmac" to supernode which forwards this to A. So now ping -A->B is known to be ping Amac(A)->Bmac(B). Note: gratuitous arp also requires -discussion. - -In response to receiving the arp reply, Apub sends {REGISTER,Amac} to Bpub. If -Bpub receives the request it sends back {REGISTER_ACK,Amac} and also sends its -own {REGISTER,Bmac} request. - -In response to receiving the "arp who-has", Bpub sends {REGISTER,Bmac} to Apub. - -Now the OS has received the arp reply and sends ICMP to Bmac(B) via the tunnel -on A. A looks up Bmac in the peers list and encapsulates the packet to Bpub or -the supernode if the MAC is not found. - -We assume that between two edge nodes, if Bpub receives a packet from Apub then -Apub can receive a packet from Bpub. This is the symmetric NAT case. Note: In -the symmetric NAT case, the public socket for a MAC address will be different -for direct contact when compared to information from the supernode. - -When two edge nodes are both behind symmetric NAT they cannot establish direct -communication. - -If A receives {REGISTER,Bmac} from B, A adds {Bmac->Bpub} to its peers list -knowing that Bmac is now reachable via that public socket. Similarly if B -receives {REGISTER,Amac} from A. - -The supernode never forwards REGISTER messages because the public socket seen by -the supervisor for some edge (eg. A) may be different to the socket seen by -another edge due to the actions of symmetric NAT (alocating a new public socket -for the new outbound UDP "connection"). - - -EDGE REGISTRATION DESIGN AMMENDMENTS (starting from 2008-04-10) ------------------------------------- - - * Send REGISTER on rx of PACKET or REGISTER only when dest_mac == device MAC -(do not send REGISTER on Rx of broadcast packets). - * After sending REGISTER add the new peer to pending_peers list; but - * Don't send REGISTER to a peer in pending_peers list - * Remove old entries from pending_peers at regular intervals - * On rx of REGISTER_ACK, move peer from pending_peers to known_peers for direct -comms and set last_seen=now - * On rx of any packet set last_seen=now in the known_peers entry (if it -exists); but do not add a new entry. - * If the public socket address for a known_peers entry changes, deleted it and -restart registration to the new peer. - * Peer sockets provided by the supernode are ignored unless no other entry -exists. Direct peer-to-peer sockets are always given more priority as the -supernode socket will not be usable for direct contact if the peer is behind -symmetric NAT. - - -The pending_peers list concept is to prevent massive registration traffic when -supernode relay is in force - this would occur if REGISTER was sent for every -incident packet sent via supernode. Periodic REGISTER attempts will still occur; -not for every received packet. In the case where the peer cannot be contacted -(eg. both peers behind symmetric NAT), then there will still be periodic -attempts. Suggest a pending timeout of about 60 sec. - -A peer is only considered operational for peer-to-peer sending when a -REGISTER_ACK is returned. Once operational the peer is kept operational while -any direct packet communications are occurring. REGISTER is not required to -keep the path open through any firewalls; just some activity in one direction. - -After an idle period; the peer should be deleted from the known_peers list. We -should not try to re-register when this time expires. If there is no data to -send then forget the peer. This helps scalability. - -If a peer wants to be remembered it can send gratuitous ARP traffic which will -keep its entry in the known_peers list of any peers which already have the -entry. - - - - -peer = find_by_src_mac( hdr, known_peers ); /* return NULL or entry */ - -if ( peer ) -{ - peer_last_seen = time(NULL); -} -else -{ - if ( ! is_broadcast( hdr ) ) /* ignore broadcasts */ - { - if ( IS_REGISTER_ACK( hdr ) ) - { - /* move from pending to known_peers */ - set_peer_operational( hdr ); - } - else - { - /* add to pending and send REGISTER - ignore if in pending. */ - try_send_register( hdr ) - } - } -} - - -(Notes): - - * In testing it was noted that if a symmetric NAT firewall shuts down the UDP -association but the known_peers registration is still active, then the peer -becomes unreachable until the known_peers registration is deleted. Suggest two -ways to mitigate this problem: - (a) make the known_peers purge timeout a config paramter; - (b) send packets direct and via supernode if the registration is older than - eg. 60 sec. - - -GRATUITOUS ARP --------------- - -In addition to the ARP who-has mechanism noted above, two edge nodes can become -aware of one another by gratuitous ARP. A gratuitous ARP packet is a broadcast -packet sent by a node for no other purpose than to announce its presence and -identify its MAC and IP address. Gratuitous ARP packets are to keep ARP caches -up to date so contacting the host will be faster after an long idle time. - - -MAN PAGES ---------- - -Look at a non-installed man page like this (linux/UNIX): - -nroff -man edge.8 | less - - -PACKET FORMAT -------------- - -Version 1 - - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - 0 ! Version=1 ! Message Type ! TTL ! Origin ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - 4 ! ! - 8 ! Community Name ! -12 ! ! -16 ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -20 ! Source MAC Address : - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -24 : Source MAC Address ! Destination MAC Address : - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -28 : Destination MAC Address ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -32 ! Public Peer ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - : : - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -40 : : - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - : : - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -48 : ! Alignment ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Private Peer : - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -56 : : - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - : : - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -64 : : - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - : ! Alignment ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -72 ! Packet Type ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Seq Number ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -80 ! CRC32 ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - Payload - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - -Version = 1 -MessageType = 1 -TTL = 1 -Origin = 1 -Community = 16 -src MAC = 6 -dst MAC = 6 -Pub Peer = 19 (20) -Priv Peer = 19 (20) -Pkt Type = 1 (4) -Seq = 4 -CRC = 4 -====================== -Total = 79 (84) - -Sizes in parentheses indicate alignment adjusted sizes on i686. The intel -alignment is also shown in the diagram. Some platforms have different alignment -padding. - -The above packet format describes the header of IP packets carried between edge -nodes. Payload is an encoded ethernet frame appended to the packet header. The -ethernet payload is encrypted and compressed. - -When the payload is created it is first encrypted with twofish, then compressed -using lzo1x_compress. When the payload is decoded it is first decompressed using -lzo1x_decompress_safe then decrypted using twofish. - -------- - -January 2009 - Richard Andrews diff --git a/n2n_v1/INSTALL b/n2n_v1/INSTALL deleted file mode 100644 index 45221d4..0000000 --- a/n2n_v1/INSTALL +++ /dev/null @@ -1,50 +0,0 @@ -INSTALL - -To build the programs: - -$ make - -To install the programs and man pages: - -$ make install - -or - -$ make PREFIX=/usr/local install - - -RPM Package ------------ - -These steps should work with RPM based Linux distributions since rpmbuild was -split from the rpm utility (c RedHat 9). - - -To build an RPM the easy way follow these steps. - -1. Build SRPM - -$ cd n2n -$ scripts/mk_SRPM.sh - -Look for where the src.rpm file was put ( "Wrote:" ). - -2. Build binary RPM from SRPM - -$ rpm -i path/to/n2n-.src.rpm -$ rpmbuild -bb n2n.spec - - -All this can be done as non-root user if you have a ~/.rpmmacros file with this -line in it: - -%_topdir /home/username/rpmtopdir - - -To build an RPM the hard way follow these steps. - -$ cp -a n2ndir n2n-1.3 -$ tar czf n2n-1.3.tar.gz n2n-1.3 -$ mv n2n-1.3.tar.gz /usr/src/redhat/SOURCES -$ cp n2ndir/n2n.spec /usr/src/redhat/SPECS -$ rpmbuild -bb n2n.spec diff --git a/n2n_v1/Makefile b/n2n_v1/Makefile deleted file mode 100644 index 485adc3..0000000 --- a/n2n_v1/Makefile +++ /dev/null @@ -1,76 +0,0 @@ - -N2N_VERSION="1.3.2" - -######## - -CC=gcc -DEBUG?=-g -WARN?=-Wall -Wshadow -Wpointer-arith -Wmissing-declarations -Wnested-externs - -#Ultrasparc64 users experiencing SIGBUS should try the following gcc options -#(thanks to Robert Gibbon) -PLATOPTS_SPARC64=-mcpu=ultrasparc -pipe -fomit-frame-pointer -ffast-math -finline-functions -fweb -frename-registers -mapp-regs - - -CFLAGS+=$(DEBUG) $(WARN) $(OPTIONS) $(PLATOPTS) - -INSTALL=install -MKDIR=mkdir -p - -INSTALL_PROG=$(INSTALL) -m755 -INSTALL_DOC=$(INSTALL) -m644 - - -# DESTDIR set in debian make system -PREFIX?=$(DESTDIR)/usr -BINDIR=$(PREFIX)/bin -SBINDIR=$(PREFIX)/sbin -MANDIR?=$(PREFIX)/share/man -MAN1DIR=$(MANDIR)/man1 -MAN8DIR=$(MANDIR)/man8 - -N2N_LIB=n2n.a -N2N_OBJS=n2n.o minilzo.o twofish.o tuntap_freebsd.o tuntap_linux.o tuntap_osx.o version.o -LIBS=-lpthread - -APPS=edge supernode -DOCS=edge.8.gz supernode.1.gz - -all: $(APPS) #$(DOCS) - -edge: edge.c $(N2N_LIB) n2n.h Makefile - $(CC) $(CFLAGS) edge.c $(N2N_LIB) $(LIBS) -o edge - -supernode: supernode.c $(N2N_LIB) n2n.h Makefile - $(CC) $(CFLAGS) supernode.c $(N2N_LIB) $(LIBS) -o supernode - -.c.o: n2n.h Makefile - $(CC) $(CFLAGS) -c $< - -%.gz : % - gzip -c $< > $@ - -$(N2N_LIB): $(N2N_OBJS) - ar rcs $(N2N_LIB) $(N2N_OBJS) -# $(RANLIB) $@ - -version.c: - @echo $(N2N_VERSION) | sed -e 's/.*/const char * version = "&";/' > version.c - @uname -p | sed -e 's/.*/const char * osName = "&";/' >> version.c - @date +"%D %r" | sed -e 's/.*/const char * buildDate = "&";/' >> version.c - -clean: - rm -rf $(N2N_OBJS) $(N2N_LIB) $(APPS) $(DOCS) *.dSYM *~ version.c - -install: edge supernode edge.8.gz supernode.1.gz - echo "MANDIR=$(MANDIR)" - $(MKDIR) $(BINDIR) $(SBINDIR) $(MAN1DIR) $(MAN8DIR) - $(INSTALL_PROG) supernode $(BINDIR)/ - $(INSTALL_PROG) edge $(SBINDIR)/ - $(INSTALL_DOC) edge.8.gz $(MAN8DIR)/ - $(INSTALL_DOC) supernode.1.gz $(MAN1DIR)/ - -# Courtesy of Ole Tange - -deb: - dpkg-buildpackage \ No newline at end of file diff --git a/n2n_v1/debian/changelog b/n2n_v1/debian/changelog deleted file mode 100644 index 3ce8eb1..0000000 --- a/n2n_v1/debian/changelog +++ /dev/null @@ -1,12 +0,0 @@ -n2n (1.3-1) hardy; urgency=low - - * New upstream release - - -- Richard Andrews Fri, 30 Jan 2009 23:49:56 +1100 - -n2n (1.2-1) unstable; urgency=low - - * Initial release - - -- Richard Andrews Thu, 10 Jul 2008 22:38:02 +1000 - diff --git a/n2n_v1/debian/control b/n2n_v1/debian/control deleted file mode 100644 index 6c06ded..0000000 --- a/n2n_v1/debian/control +++ /dev/null @@ -1,22 +0,0 @@ -Source: n2n -Section: net -Priority: extra -Maintainer: Jean-Baptiste Denis -Build-Depends: cdbs, debhelper (>= 5), libc6-dev (>= 2.0), dpatch, gcc -Standards-Version: 3.7.2 - -Package: n2n -Architecture: any -Suggests: uml-utilities -Depends: ${shlibs:Depends}, ${misc:Depends} -Description: a layer-two peer-to-peer virtual private network (VPN) - n2n is a layer-two peer-to-peer virtual private network (VPN) which allows - users to exploit features typical of P2P applications at network instead of - application level. This means that users can gain native IP visibility (e.g. - two PCs belonging to the same n2n network can ping each other) and be - reachable with the same network IP address regardless of the network where - they currently belong. In a nutshell, as OpenVPN moved SSL from application - (e.g. used to implement the https protocol) to network protocol, n2n moves - P2P from application to network level. - - diff --git a/n2n_v1/debian/n2n.dirs b/n2n_v1/debian/n2n.dirs deleted file mode 100644 index 8c74f91..0000000 --- a/n2n_v1/debian/n2n.dirs +++ /dev/null @@ -1,4 +0,0 @@ -usr/bin -usr/sbin -usr/share/doc/n2n -usr/share/man/man1 diff --git a/n2n_v1/debian/n2n.docs b/n2n_v1/debian/n2n.docs deleted file mode 100644 index a74d034..0000000 --- a/n2n_v1/debian/n2n.docs +++ /dev/null @@ -1,3 +0,0 @@ -README -supernode.1 -edge.8 diff --git a/n2n_v1/debian/n2n.install b/n2n_v1/debian/n2n.install deleted file mode 100644 index 7ccf7f4..0000000 --- a/n2n_v1/debian/n2n.install +++ /dev/null @@ -1,2 +0,0 @@ -edge /usr/bin -supernode /usr/sbin diff --git a/n2n_v1/debian/n2n.manpages b/n2n_v1/debian/n2n.manpages deleted file mode 100644 index b8b5aeb..0000000 --- a/n2n_v1/debian/n2n.manpages +++ /dev/null @@ -1,2 +0,0 @@ -edge.8 -supernode.1 diff --git a/n2n_v1/debian/rules b/n2n_v1/debian/rules deleted file mode 100644 index 914e4c9..0000000 --- a/n2n_v1/debian/rules +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/make -f - -#DEB_MAKE_INSTALL_TARGET = install prefix=$(CURDIR)/debian/n2n/usr - -include /usr/share/cdbs/1/rules/debhelper.mk -include /usr/share/cdbs/1/rules/dpatch.mk -include /usr/share/cdbs/1/class/makefile.mk - -# Add here any variable or target overrides you need. diff --git a/n2n_v1/edge.8 b/n2n_v1/edge.8 deleted file mode 100644 index 37d6861..0000000 --- a/n2n_v1/edge.8 +++ /dev/null @@ -1,116 +0,0 @@ -.TH edge 1 "Jan 3, 2009" "revision 3679" "SUPERUSER COMMANDS" -.SH NAME -edge \- n2n edge node daemon -.SH SYNOPSIS -.B edge -[\-d ] \-a \-c \-k \-l -[\-p ] [\-u ] [\-g ] [-f] [\-m ] [\-t] [\-r] [\-v] -.SH DESCRIPTION -N2N is a peer-to-peer VPN system. Edge is the edge node daemon for n2n which -creates a TAP interface to expose the n2n virtual LAN. On startup n2n creates -the TAP interface and configures it then registers with the supernode so it can -begin to find other nodes in the community. -.PP -.SH OPTIONS -.TP -\-d -sets the TAP device name as seen in ifconfig. -.TP -\-a -sets the n2n virtual LAN IP address being claimed. This is a private IP -address. All IP addresses in an n2n community should belong to the same /24 -network (ie. only the last segment of the IP addresses varies). -.TP -\-b -cause edge to perform hostname resolution for the supernode address each time -the supernode is periodically contacted. -.TP -\-c -sets the n2n community name. All edges within the same community look to be on -the same LAN (layer 2 network segment). All edges communicating must use the -same key and community name. -.TP -\-h -write usage to tty then exit. -.TP -\-k -sets the twofish encryption key from ASCII text (see also N2N_KEY in -ENVIRONMENT). All edges communicating must use the same key and community name. -.TP -\-l : -sets the n2n supernode IP address and port to register to. -.TP -\-p -binds edge to the given UDP port. Useful for keeping the same external socket -across restarts of edge. -.TP -\-u -causes the edge process to drop to the given user ID when privileges are no -longer required. -.TP -\-g -causes the edge process to drop to the given group ID when privileges are no -longer required. -.TP -\-f -causes the edge process to fork and run as a daemon, closing stdin, stdout, -stderr and becoming a process group leader. -.TP -\-m -start the TAP interface with the given MAC address. This is highly recommended -as it means the same address will be used if edge stops and restarts. If this is -not done, the ARP caches of all peers will be wrong and packets will not flow to -this edge until the next ARP refresh. -.TP -\-M -set the MTU of the edge interface in bytes. MTU is the largest packet fragment -size allowed to be moved throught the interface. The default is 1400. -.TP -\-s -set the netmask of edge interface in IPv4 dotted decimal notation. The default -is 255.255.255.0 (ie. /24). -.TP -\-t -use HTTP tunneling instead of the normal UDP mechanism (experimental). -.TP -\-r -enable packet forwarding/routing through the n2n virtual LAN. Without this -option, packets arriving over n2n which are not for the -a IP address are -dropped. -.TP -\-v -use verbose logging. -.SH ENVIRONMENT -.TP -.B N2N_KEY -set the encryption key so it is not visible on the command line -.SH EXAMPLES -.TP -.B edge \-d n2n0 \-c mynetwork \-k encryptme \-u 99 \-g 99 \-m DE:AD:BE:EF:01:23 \-a 192.168.254.7 \-p 50001 \-l 123.121.120.119:7654 - -Start edge with TAP device n2n0 on community "mynetwork" with community -supernode at 123.121.120.119 UDP port 7654 and bind the locally used UDP port to -50001. Use "encryptme" as the shared encryption key. Assign MAC address -DE:AD:BE:EF:01:23 to the n2n interface and drop to user=99 and group=99 after -the TAP device is successfull configured. -.PP -Add the -f option to make edge run as a daemon. -.PP -Somewhere else setup another edge with similar parameters, eg. - -.B edge \-d n2n0 \-c mynetwork \-k encryptme \-u 99 \-g 99 \-m DE:AD:BE:EF:01:21 \-a 192.168.254.5 \-p 50001 \-l 123.121.120.119:7654 -.PP -Now you can ping from 192.168.254.5 to 192.168.254.7. -.PP -The MAC address (-m ) and virtual IP address (-a ) must be different on all edges in the same community. - -.SH CONFIGURATION -All configuration for edge is from the command line and environment -variables. If you wish to reconfigure edge you should kill the process and -restart with the desired options. -.SH EXIT STATUS -edge is a daemon and any exit is an error. -.SH AUTHOR -Luca Deri ( deri (at) ntop.org ), Richard Andrews ( andrews (at) ntop.org ), Don Bindner -.SH SEE ALSO -ifconfig(8) supernode(1) tunctl(8) diff --git a/n2n_v1/edge.c b/n2n_v1/edge.c deleted file mode 100644 index eae4ce3..0000000 --- a/n2n_v1/edge.c +++ /dev/null @@ -1,1452 +0,0 @@ -/* - * (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. - * - * 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 - * - * Code contributions courtesy of: - * Don Bindner - * Sylwester Sosnowski - * Wilfried "Wonka" Klaebe - * - */ - -#include "minilzo.h" -#include "n2n.h" -#include -#include - -/** Time between logging system STATUS messages */ -#define STATUS_UPDATE_INTERVAL (30 * 60) /*secs*/ - -/* 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 - -struct n2n_edge -{ - u_char re_resolve_supernode_ip; - struct peer_addr supernode; - char supernode_ip[48]; - char * community_name /*= NULL*/; - - /* int sock; */ - /* char is_udp_socket /\*= 1*\/; */ - n2n_sock_info_t sinfo; - - u_int pkt_sent /*= 0*/; - tuntap_dev device; - int allow_routing /*= 0*/; - int drop_ipv6_ndp /*= 0*/; - char * encrypt_key /* = NULL*/; - TWOFISH * enc_tf; - TWOFISH * dec_tf; - - struct peer_info * known_peers /* = NULL*/; - struct peer_info * pending_peers /* = NULL*/; - time_t last_register /* = 0*/; -}; - -static void supernode2addr(n2n_edge_t * eee, char* addr); - -static void send_packet2net(n2n_edge_t * eee, - char *decrypted_msg, size_t len); - - -/* ************************************** */ - -/* parse the configuration file */ -static int readConfFile(const char * filename, char * const linebuffer) { - struct stat stats; - FILE * fd; - char * buffer = NULL; - - buffer = (char *)malloc(MAX_CONFFILE_LINE_LENGTH); - if (!buffer) { - traceEvent( TRACE_ERROR, "Unable to allocate memory"); - return -1; - } - - 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); - free(buffer); - return -1; - } - - fd = fopen(filename, "rb"); - if (!fd) { - traceEvent(TRACE_ERROR, "Unable to open parameter file '%s' (%d)...\n",filename,errno); - free(buffer); - return -1; - } - while(fgets(buffer, MAX_CONFFILE_LINE_LENGTH,fd)) { - char * p = NULL; - - /* strip out comments */ - p = strchr(buffer, '#'); - if (p) *p ='\0'; - - /* remove \n */ - p = strchr(buffer, '\n'); - if (p) *p ='\0'; - - /* strip out heading spaces */ - p = buffer; - while(*p == ' ' && *p != '\0') ++p; - 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, '@')) { - 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) { - strncat(linebuffer, " ", 1); - strncat(linebuffer, buffer, strlen(buffer)); - } else { - traceEvent(TRACE_ERROR, "too many argument"); - free(buffer); - return -1; - } - } - - free(buffer); - fclose(fd); - - return 0; -} - -/* Create the argv vector */ -static char ** buildargv(char * const linebuffer) { - const int INITIAL_MAXARGC = 16; /* Number of args + NULL in initial argv */ - int maxargc; - int argc=0; - char ** argv; - char * buffer, * buff; - - buffer = (char *)calloc(1, strlen(linebuffer)+2); - if (!buffer) { - traceEvent( TRACE_ERROR, "Unable to allocate memory"); - return NULL; - } - strncpy(buffer, linebuffer,strlen(linebuffer)); - - maxargc = INITIAL_MAXARGC; - argv = (char **)malloc(maxargc * sizeof(char*)); - if (argv == NULL) { - traceEvent( TRACE_ERROR, "Unable to allocate memory"); - return NULL; - } - buff = buffer; - while(buff) { - char * p = strchr(buff,' '); - if (p) { - *p='\0'; - argv[argc++] = strdup(buff); - while(*++p == ' ' && *p != '\0'); - buff=p; - if (argc >= maxargc) { - maxargc *= 2; - argv = (char **)realloc(argv, maxargc * sizeof(char*)); - if (argv == NULL) { - traceEvent(TRACE_ERROR, "Unable to re-allocate memory"); - free(buffer); - return NULL; - } - } - } else { - argv[argc++] = strdup(buff); - break; - } - } - argv[argc] = NULL; - free(buffer); - return argv; -} - - - -/* ************************************** */ - -static int edge_init(n2n_edge_t * eee) { -#ifdef WIN32 - initWin32(); -#endif - memset(eee, 0, sizeof(n2n_edge_t)); - - eee->re_resolve_supernode_ip = 0; - eee->community_name = NULL; - eee->sinfo.sock = -1; - eee->sinfo.is_udp_socket = 1; - eee->pkt_sent = 0; - eee->allow_routing = 0; - eee->drop_ipv6_ndp = 0; - eee->encrypt_key = NULL; - eee->enc_tf = NULL; - eee->dec_tf = NULL; - eee->known_peers = NULL; - eee->pending_peers = NULL; - eee->last_register = 0; - - if(lzo_init() != LZO_E_OK) { - traceEvent(TRACE_ERROR, "LZO compression error"); - return(-1); - } - - return(0); -} - -static int edge_init_twofish( n2n_edge_t * eee, u_int8_t *encrypt_pwd, u_int32_t encrypt_pwd_len ) -{ - eee->enc_tf = TwoFishInit(encrypt_pwd, encrypt_pwd_len); - eee->dec_tf = TwoFishInit(encrypt_pwd, encrypt_pwd_len); - - if ( (eee->enc_tf) && (eee->dec_tf) ) - { - return 0; - } - else - { - return 1; - } -} - -/* ************************************** */ - -static void edge_deinit(n2n_edge_t * eee) { - TwoFishDestroy(eee->enc_tf); - TwoFishDestroy(eee->dec_tf); - if ( eee->sinfo.sock >=0 ) - { - close( eee->sinfo.sock ); - } -} - -static void readFromIPSocket( n2n_edge_t * eee ); - -static void help() { - print_n2n_version(); - - printf("edge " -#ifdef __linux__ - "-d " -#endif - "-a " - "-c " - "-k " - "-s " -#ifndef WIN32 - "[-u -g ]" - "[-f]" -#endif - "[-m ]" - "\n" - "-l " - "[-p ] [-M ] " - "[-t] [-r] [-v] [-b] [-h]\n\n"); - -#ifdef __linux__ - printf("-d | tun device name\n"); -#endif - - printf("-a | n2n IP address\n"); - printf("-c | n2n community name\n"); - printf("-k | Encryption key (ASCII) - also N2N_KEY=\n"); - printf("-s | Edge interface netmask in dotted decimal notation (255.255.255.0)\n"); - printf("-l | Supernode IP:port\n"); - printf("-b | Periodically resolve supernode IP\n"); - printf(" | (when supernodes are running on dynamic IPs)\n"); - printf("-p | Local port used for connecting to supernode\n"); -#ifndef WIN32 - printf("-u | User ID (numeric) to use when privileges are dropped\n"); - printf("-g | Group ID (numeric) to use when privileges are dropped\n"); - printf("-f | Fork and run as a daemon. Use syslog.\n"); -#endif - printf("-m | Choose a MAC address for the TAP interface\n" - " | eg. -m 01:02:03:04:05:06\n"); - printf("-M | Specify n2n MTU (default %d)\n", DEFAULT_MTU); - printf("-t | Use http tunneling (experimental)\n"); - printf("-r | Enable packet forwarding through n2n community\n"); - printf("-v | Verbose\n"); - - printf("\nEnvironment variables:\n"); - printf(" N2N_KEY | Encryption key (ASCII)\n" ); - - exit(0); -} - -/* *********************************************** */ - -static void send_register( n2n_edge_t * eee, - const struct peer_addr *remote_peer, - u_char is_ack) { - struct n2n_packet_header hdr; - char pkt[N2N_PKT_HDR_SIZE]; - size_t len = sizeof(hdr); - ipstr_t ip_buf; - - fill_standard_header_fields( &(eee->sinfo), &hdr, (char*)(eee->device.mac_addr)); - hdr.sent_by_supernode = 0; - hdr.msg_type = (is_ack == 0) ? MSG_TYPE_REGISTER : MSG_TYPE_REGISTER_ACK; - memcpy(hdr.community_name, eee->community_name, COMMUNITY_LEN); - - marshall_n2n_packet_header( (u_int8_t *)pkt, &hdr ); - send_packet( &(eee->sinfo), pkt, &len, remote_peer, N2N_COMPRESSION_ENABLED ); - - traceEvent(TRACE_INFO, "Sent %s message to %s:%hu", - ((hdr.msg_type==MSG_TYPE_REGISTER)?"MSG_TYPE_REGISTER":"MSG_TYPE_REGISTER_ACK"), - intoa(ntohl(remote_peer->addr_type.v4_addr), ip_buf, sizeof(ip_buf)), - ntohs(remote_peer->port)); -} - -/* *********************************************** */ - -static void send_deregister(n2n_edge_t * eee, - struct peer_addr *remote_peer) { - struct n2n_packet_header hdr; - char pkt[N2N_PKT_HDR_SIZE]; - size_t len = sizeof(hdr); - - fill_standard_header_fields( &(eee->sinfo), &hdr, (char*)(eee->device.mac_addr) ); - hdr.sent_by_supernode = 0; - hdr.msg_type = MSG_TYPE_DEREGISTER; - memcpy(hdr.community_name, eee->community_name, COMMUNITY_LEN); - - marshall_n2n_packet_header( (u_int8_t *)pkt, &hdr ); - send_packet( &(eee->sinfo), pkt, &len, remote_peer, N2N_COMPRESSION_ENABLED); -} - -/* *********************************************** */ - -static void update_peer_address(n2n_edge_t * eee, - const struct n2n_packet_header * hdr, - time_t when); -void trace_registrations( struct peer_info * scan ); -int is_ip6_discovery( const void * buf, size_t bufsize ); -void check_peer( n2n_edge_t * eee, - const struct n2n_packet_header * hdr ); -void try_send_register( n2n_edge_t * eee, - const struct n2n_packet_header * hdr ); -void set_peer_operational( n2n_edge_t * eee, const struct n2n_packet_header * hdr ); - - - -/** Start the registration process. - * - * If the peer is already in pending_peers, ignore the request. - * If not in pending_peers, add it and send a REGISTER. - * - * If hdr is for a direct peer-to-peer packet, try to register back to sender - * even if the MAC is in pending_peers. This is because an incident direct - * packet indicates that peer-to-peer exchange should work so more aggressive - * registration can be permitted (once per incoming packet) as this should only - * last for a small number of packets.. - * - * Called from the main loop when Rx a packet for our device mac. - */ -void try_send_register( n2n_edge_t * eee, - const struct n2n_packet_header * hdr ) -{ - ipstr_t ip_buf; - - /* REVISIT: purge of pending_peers not yet done. */ - struct peer_info * scan = find_peer_by_mac( eee->pending_peers, hdr->src_mac ); - - if ( NULL == scan ) - { - scan = calloc( 1, sizeof( struct peer_info ) ); - - memcpy(scan->mac_addr, hdr->src_mac, 6); - scan->public_ip = hdr->public_ip; - scan->last_seen = time(NULL); /* Don't change this it marks the pending peer for removal. */ - - peer_list_add( &(eee->pending_peers), scan ); - - traceEvent( TRACE_NORMAL, "Pending peers list size=%ld", - peer_list_size( eee->pending_peers ) ); - - traceEvent( TRACE_NORMAL, "Sending REGISTER request to %s:%hu", - intoa(ntohl(scan->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), - ntohs(scan->public_ip.port)); - - send_register(eee, - &(scan->public_ip), - 0 /* is not ACK */ ); - - /* pending_peers now owns scan. */ - } - else - { - /* scan already in pending_peers. */ - - if ( 0 == hdr->sent_by_supernode ) - { - /* over-write supernode-based socket with direct socket. */ - scan->public_ip = hdr->public_ip; - - traceEvent( TRACE_NORMAL, "Sending additional REGISTER request to %s:%hu", - intoa(ntohl(scan->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), - ntohs(scan->public_ip.port)); - - - send_register(eee, - &(scan->public_ip), - 0 /* is not ACK */ ); - } - } -} - - -/** Update the last_seen time for this peer, or get registered. */ -void check_peer( n2n_edge_t * eee, - const struct n2n_packet_header * hdr ) -{ - struct peer_info * scan = find_peer_by_mac( eee->known_peers, hdr->src_mac ); - - if ( NULL == scan ) - { - /* Not in known_peers - start the REGISTER process. */ - try_send_register( eee, hdr ); - } - else - { - /* Already in known_peers. */ - update_peer_address( eee, hdr, 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 struct n2n_packet_header * hdr ) -{ - struct peer_info * prev = NULL; - struct peer_info * scan; - macstr_t mac_buf; - ipstr_t ip_buf; - - scan=eee->pending_peers; - - while ( NULL != scan ) - { - if ( 0 != memcmp( scan->mac_addr, hdr->dst_mac, 6 ) ) - { - 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->public_ip = hdr->public_ip; - - traceEvent(TRACE_INFO, "=== new peer [mac=%s][socket=%s:%hu]", - macaddr_str(scan->mac_addr, mac_buf, sizeof(mac_buf)), - intoa(ntohl(scan->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), - ntohs(scan->public_ip.port)); - - traceEvent( TRACE_NORMAL, "Pending peers list size=%ld", - peer_list_size( eee->pending_peers ) ); - - traceEvent( TRACE_NORMAL, "Operational peers list size=%ld", - peer_list_size( eee->known_peers ) ); - - - scan->last_seen = time(NULL); - } - else - { - traceEvent( TRACE_WARNING, "Failed to find sender in pending_peers." ); - } -} - - -void trace_registrations( struct peer_info * scan ) -{ - macstr_t mac_buf; - ipstr_t ip_buf; - - while ( scan ) - { - traceEvent(TRACE_INFO, "=== peer [mac=%s][socket=%s:%hu]", - macaddr_str(scan->mac_addr, mac_buf, sizeof(mac_buf)), - intoa(ntohl(scan->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), - ntohs(scan->public_ip.port)); - - scan = scan->next; - } - -} - -u_int8_t broadcast_mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - - -/** Keep the known_peers list straight. - * - * Ignore broadcast L2 packets, and packets with invalid public_ip. - * If the dst_mac is in known_peers make sure the entry is correct: - * - if the public_ip socket has changed, erase the entry - * - if the same, update its last_seen = when - */ -static void update_peer_address(n2n_edge_t * eee, - const struct n2n_packet_header * hdr, - time_t when) -{ - ipstr_t ip_buf; - struct peer_info *scan = eee->known_peers; - struct peer_info *prev = NULL; /* use to remove bad registrations. */ - - if ( 0 == hdr->public_ip.addr_type.v4_addr ) - { - /* Not to be registered. */ - return; - } - - if ( 0 == memcmp( hdr->dst_mac, broadcast_mac, 6 ) ) - { - /* Not to be registered. */ - return; - } - - - while(scan != NULL) - { - if(memcmp(hdr->dst_mac, scan->mac_addr, 6) == 0) - { - break; - } - - prev = scan; - scan = scan->next; - } - - if ( NULL == scan ) - { - /* Not in known_peers. */ - return; - } - - if ( 0 != memcmp( &(scan->public_ip), &(hdr->public_ip), sizeof(struct peer_addr))) - { - if ( 0 == hdr->sent_by_supernode ) - { - traceEvent( TRACE_NORMAL, "Peer changed public socket, Was %s:%hu", - intoa(ntohl(hdr->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), - ntohs(hdr->public_ip.port)); - - /* 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, hdr ); - } - 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 */ - 0x08, 0x06, /* ARP */ - 0x00, 0x01, /* Ethernet */ - 0x08, 0x00, /* IP */ - 0x06, /* Hw Size */ - 0x04, /* Protocol Size */ - 0x00, 0x01, /* ARP Request */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Src mac */ - 0x00, 0x00, 0x00, 0x00, /* Src IP */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Target mac */ - 0x00, 0x00, 0x00, 0x00 /* Target IP */ -}; - -static int build_gratuitous_arp(char *buffer, u_short buffer_len) { - if(buffer_len < sizeof(gratuitous_arp)) return(-1); - - memcpy(buffer, gratuitous_arp, sizeof(gratuitous_arp)); - memcpy(&buffer[6], device.mac_addr, 6); - memcpy(&buffer[22], device.mac_addr, 6); - memcpy(&buffer[28], &device.ip_addr, 4); - - /* REVISIT: BbMaj7 - use a real netmask here. This is valid only by accident - * for /24 IPv4 networks. */ - buffer[31] = 0xFF; /* Use a faked broadcast address */ - memcpy(&buffer[38], &device.ip_addr, 4); - return(sizeof(gratuitous_arp)); -} - -/** Called from update_registrations to periodically send gratuitous ARP - * broadcasts. */ -static void send_grat_arps(n2n_edge_t * eee,) { - char buffer[48]; - size_t len; - - traceEvent(TRACE_NORMAL, "Sending gratuitous ARP..."); - len = build_gratuitous_arp(buffer, sizeof(buffer)); - 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 our peers and the - * supernode. - * - * This is periodically called by the main loop. The list of registrations is - * not modified. Registration packets may be sent. - */ -static void update_registrations( n2n_edge_t * eee ) { - /* REVISIT: BbMaj7: have shorter timeout to REGISTER to supernode if this has - * not yet succeeded. */ - - if(time(NULL) < (eee->last_register+REGISTER_FREQUENCY)) return; /* Too early */ - - traceEvent(TRACE_NORMAL, "Registering with supernode"); - if(eee->re_resolve_supernode_ip) - supernode2addr(eee, eee->supernode_ip); - - send_register(eee, &(eee->supernode), 0); /* Register with supernode */ - - /* REVISIT: turn-on gratuitous ARP with config option. */ - /* send_grat_arps(sock_fd, is_udp_sock); */ - - eee->last_register = time(NULL); -} - -/* ***************************************************** */ - -static int find_peer_destination(n2n_edge_t * eee, - const u_char *mac_address, - struct peer_addr *destination) { - const struct peer_info *scan = eee->known_peers; - macstr_t mac_buf; - ipstr_t ip_buf; - int retval=0; - - traceEvent(TRACE_INFO, "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_INFO, "Evaluating peer [MAC=%02X:%02X:%02X:%02X:%02X:%02X][ip=%s:%hu]", - 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, - intoa(ntohl(scan->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), - ntohs(scan->public_ip.port)); - - if((scan->last_seen > 0) && - (memcmp(mac_address, scan->mac_addr, 6) == 0)) - { - memcpy(destination, &scan->public_ip, sizeof(struct sockaddr_in)); - retval=1; - break; - } - scan = scan->next; - } - - if ( 0 == retval ) - { - memcpy(destination, &(eee->supernode), sizeof(struct sockaddr_in)); - } - - traceEvent(TRACE_INFO, "find_peer_address(%s) -> [socket=%s:%hu]", - macaddr_str( (char *)mac_address, mac_buf, sizeof(mac_buf)), - intoa(ntohl(destination->addr_type.v4_addr), ip_buf, sizeof(ip_buf)), - ntohs(destination->port)); - - return retval; -} - -/* *********************************************** */ - -static const struct option long_options[] = { - { "community", required_argument, NULL, 'c' }, - { "supernode-list", required_argument, NULL, 'l' }, - { "tun-device", required_argument, NULL, 'd' }, - { "euid", required_argument, NULL, 'u' }, - { "egid", required_argument, NULL, 'g' }, - { "help" , no_argument, NULL, 'h' }, - { "verbose", no_argument, NULL, 'v' }, - { NULL, 0, NULL, 0 } -}; - -/* ***************************************************** */ - - -/** A layer-2 packet was received at the tunnel and needs to be sent via UDP. */ -static void send_packet2net(n2n_edge_t * eee, - char *decrypted_msg, size_t len) { - ipstr_t ip_buf; - char packet[2048]; - int data_sent_len; - struct n2n_packet_header hdr; - struct peer_addr destination; - macstr_t mac_buf; - macstr_t mac2_buf; - struct ether_header *eh = (struct ether_header*)decrypted_msg; - - /* Discard IP packets that are not originated by this hosts */ - if(!(eee->allow_routing)) { - if(ntohs(eh->ether_type) == 0x0800) { - /* This is an IP packet from the local source address - not forwarded. */ -#define ETH_FRAMESIZE 14 -#define IP4_SRCOFFSET 12 - u_int32_t dst; - memcpy( &dst, &decrypted_msg[ETH_FRAMESIZE + IP4_SRCOFFSET], sizeof(dst) ); - - /* The following comparison works because device.ip_addr is stored 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"); */ - } - } - } - - /* Encrypt "decrypted_msg" into the second half of the n2n packet. */ - len = TwoFishEncryptRaw((u_int8_t *)decrypted_msg, - (u_int8_t *)&packet[N2N_PKT_HDR_SIZE], len, eee->enc_tf); - - /* Add the n2n header to the start of the n2n packet. */ - fill_standard_header_fields( &(eee->sinfo), &hdr, (char*)(eee->device.mac_addr) ); - hdr.msg_type = MSG_TYPE_PACKET; - hdr.sent_by_supernode = 0; - memcpy(hdr.community_name, eee->community_name, COMMUNITY_LEN); - memcpy(hdr.dst_mac, decrypted_msg, 6); - - marshall_n2n_packet_header( (u_int8_t *)packet, &hdr ); - - len += N2N_PKT_HDR_SIZE; - - if(find_peer_destination(eee, eh->ether_dhost, &destination)) - traceEvent(TRACE_INFO, "** Going direct [dst_mac=%s][dest=%s:%hu]", - macaddr_str((char*)eh->ether_dhost, mac_buf, sizeof(mac_buf)), - intoa(ntohl(destination.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), - ntohs(destination.port)); - else - traceEvent(TRACE_INFO, " Going via supernode [src_mac=%s][dst_mac=%s]", - macaddr_str((char*)eh->ether_shost, mac_buf, sizeof(mac_buf)), - macaddr_str((char*)eh->ether_dhost, mac2_buf, sizeof(mac2_buf))); - - data_sent_len = reliable_sendto( &(eee->sinfo), packet, &len, &destination, - N2N_COMPRESSION_ENABLED); - - if(data_sent_len != len) - traceEvent(TRACE_WARNING, "sendto() [sent=%d][attempted_to_send=%d] [%s]\n", - data_sent_len, len, strerror(errno)); - else { - ++(eee->pkt_sent); - traceEvent(TRACE_INFO, "Sent %d byte MSG_TYPE_PACKET ok", data_sent_len); - } -} - -/* ***************************************************** */ - -/** Destination MAC 33:33:0:00:00:00 - 33:33:FF:FF:FF:FF is reserved for IPv6 - * neighbour discovery. - */ -int is_ip6_discovery( const void * buf, size_t bufsize ) -{ - int retval = 0; - - if ( bufsize >= sizeof(struct ether_header) ) - { - struct ether_header *eh = (struct ether_header*)buf; - if ( (0x33 == eh->ether_dhost[0]) && - (0x33 == eh->ether_dhost[1]) ) - { - retval = 1; /* This is an IPv6 neighbour discovery packet. */ - } - } - return retval; -} - - -/* ***************************************************** */ - -/* - * Return: 0 = ok, -1 = invalid packet - * - */ -static int check_received_packet(n2n_edge_t * eee, char *pkt, - u_int pkt_len) { - - if(pkt_len == 42) { - /* ARP */ - if((pkt[12] != 0x08) || (pkt[13] != 0x06)) return(0); /* No ARP */ - if((pkt[20] != 0x00) || (pkt[21] != 0x02)) return(0); /* No ARP Reply */ - if(memcmp(&pkt[28], &(eee->device.ip_addr), 4)) return(0); /* This is not me */ - - if(memcmp(eee->device.mac_addr, &pkt[22], 6) == 0) { - traceEvent(TRACE_WARNING, "Bounced packet received: supernode bug?"); - return(0); - } - - traceEvent(TRACE_ERROR, "Duplicate address found. Your IP is used by MAC %02X:%02X:%02X:%02X:%02X:%02X", - pkt[22+0] & 0xFF, pkt[22+1] & 0xFF, pkt[22+2] & 0xFF, - pkt[22+3] & 0xFF, pkt[22+4] & 0xFF, pkt[22+5] & 0xFF); - exit(0); - } else if(pkt_len > 32 /* IP + Ethernet */) { - /* Check if this packet is for us or if it's routed */ - struct ether_header *eh = (struct ether_header*)pkt; - - const struct in_addr bcast = { 0xffffffff }; - - if(ntohs(eh->ether_type) == 0x0800) { - - /* Note: all elements of the_ip are in network order */ - struct ip the_ip; - memcpy( &the_ip, pkt+sizeof(struct ether_header), sizeof(the_ip) ); - - if((the_ip.ip_dst.s_addr != eee->device.ip_addr) - && ((the_ip.ip_dst.s_addr & eee->device.device_mask) != (eee->device.ip_addr & eee->device.device_mask)) /* Not a broadcast */ - && ((the_ip.ip_dst.s_addr & 0xE0000000) != (0xE0000000 /* 224.0.0.0-239.255.255.255 */)) /* Not a multicast */ - && ((the_ip.ip_dst.s_addr) != (bcast.s_addr)) /* always broadcast (RFC919) */ - && (!(eee->allow_routing)) /* routing is enabled so let it in */ - ) - { - /* Dropping the packet */ - - ipstr_t ip_buf; - ipstr_t ip_buf2; - - /* This is a packet that needs to be routed */ - traceEvent(TRACE_INFO, "Discarding routed packet [rcvd=%s][expected=%s]", - intoa(ntohl(the_ip.ip_dst.s_addr), ip_buf, sizeof(ip_buf)), - intoa(ntohl(eee->device.ip_addr), ip_buf2, sizeof(ip_buf2))); - } else { - /* This packet is for us */ - - /* traceEvent(TRACE_INFO, "Received non-routed packet"); */ - return(0); - } - } else - return(0); - } else { - traceEvent(TRACE_INFO, "Packet too short (%d bytes): discarded", pkt_len); - } - - return(-1); -} - -/* ***************************************************** */ - -/** Read a single packet from the TAP interface, process it and write out the - * corresponding packet to the cooked socket. - * - * REVISIT: fails if more than one packet is waiting to be read. - */ -static void readFromTAPSocket( n2n_edge_t * eee ) -{ - /* tun -> remote */ - u_char decrypted_msg[2048]; - size_t len; - - len = tuntap_read(&(eee->device), decrypted_msg, sizeof(decrypted_msg)); - - if((len <= 0) || (len > sizeof(decrypted_msg))) - traceEvent(TRACE_WARNING, "read()=%d [%d/%s]\n", - len, errno, strerror(errno)); - else { - traceEvent(TRACE_INFO, "### Rx L2 Msg (%d) tun -> network", len); - - if ( eee->drop_ipv6_ndp && is_ip6_discovery( decrypted_msg, len ) ) { - traceEvent(TRACE_WARNING, "Dropping unsupported IPv6 neighbour discovery packet"); - } else { - send_packet2net(eee, (char*)decrypted_msg, len); - } - } -} - -/* ***************************************************** */ - - -void readFromIPSocket( n2n_edge_t * eee ) -{ - ipstr_t ip_buf; - macstr_t mac_buf; - char packet[2048], decrypted_msg[2048]; - size_t len; - int data_sent_len; - struct peer_addr sender; - - /* remote -> tun */ - u_int8_t discarded_pkt; - struct n2n_packet_header hdr_storage; - - len = receive_data( &(eee->sinfo), packet, sizeof(packet), &sender, - &discarded_pkt, (char*)(eee->device.mac_addr), - N2N_COMPRESSION_ENABLED, &hdr_storage); - - if(len <= 0) return; - - traceEvent(TRACE_INFO, "### Rx N2N Msg network -> tun"); - - if(discarded_pkt) { - traceEvent(TRACE_INFO, "Discarded incoming pkt"); - } else { - if(len <= 0) - traceEvent(TRACE_WARNING, "receive_data()=%d [%s]\n", len, strerror(errno)); - else { - if(len < N2N_PKT_HDR_SIZE) - traceEvent(TRACE_WARNING, "received packet too short [len=%d]\n", len); - else { - struct n2n_packet_header *hdr = &hdr_storage; - - traceEvent(TRACE_INFO, "Received packet from %s:%hu", - intoa(ntohl(sender.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), - ntohs(sender.port)); - - traceEvent(TRACE_INFO, "Received message [msg_type=%s] from %s [dst mac=%s]", - msg_type2str(hdr->msg_type), - hdr->sent_by_supernode ? "supernode" : "peer", - macaddr_str(hdr->dst_mac, mac_buf, sizeof(mac_buf))); - - if(hdr->version != N2N_PKT_VERSION) { - traceEvent(TRACE_WARNING, - "Received packet with unknown protocol version (%d): discarded\n", - hdr->version); - return; - } - - /* FIX - Add IPv6 support */ - if(hdr->public_ip.addr_type.v4_addr == 0) { - hdr->public_ip.addr_type.v4_addr = sender.addr_type.v4_addr; - hdr->public_ip.port = sender.port; - hdr->public_ip.family = AF_INET; - } - - if(strncmp(hdr->community_name, eee->community_name, COMMUNITY_LEN) != 0) { - traceEvent(TRACE_WARNING, "Received packet with invalid community [expected=%s][received=%s]\n", - eee->community_name, hdr->community_name); - } else { - if(hdr->msg_type == MSG_TYPE_PACKET) { - /* assert: the packet received is destined for device.mac_addr or broadcast MAC. */ - - len -= N2N_PKT_HDR_SIZE; - - /* Decrypt message first */ - len = TwoFishDecryptRaw((u_int8_t *)&packet[N2N_PKT_HDR_SIZE], - (u_int8_t *)decrypted_msg, len, eee->dec_tf); - - if(len > 0) { - if(check_received_packet(eee, decrypted_msg, len) == 0) { - - if ( 0 == memcmp(hdr->dst_mac, eee->device.mac_addr, 6) ) - { - check_peer( eee, hdr ); - } - - data_sent_len = tuntap_write(&(eee->device), (u_char*)decrypted_msg, len); - - if(data_sent_len != len) - traceEvent(TRACE_WARNING, "tuntap_write() [sent=%d][attempted_to_send=%d] [%s]\n", - data_sent_len, len, strerror(errno)); - else { - /* Normal situation. */ - traceEvent(TRACE_INFO, "### Tx L2 Msg -> tun"); - } - } else { - traceEvent(TRACE_WARNING, "Bad destination: message discarded"); - } - } - /* else silently ignore empty packet. */ - - } else if(hdr->msg_type == MSG_TYPE_REGISTER) { - traceEvent(TRACE_INFO, "Received registration request from remote peer [ip=%s:%hu]", - intoa(ntohl(hdr->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), - ntohs(hdr->public_ip.port)); - if ( 0 == memcmp(hdr->dst_mac, (eee->device.mac_addr), 6) ) - { - check_peer( eee, hdr ); - } - - - send_register(eee, &hdr->public_ip, 1); /* Send ACK back */ - } else if(hdr->msg_type == MSG_TYPE_REGISTER_ACK) { - traceEvent(TRACE_NORMAL, "Received REGISTER_ACK from remote peer [ip=%s:%hu]", - intoa(ntohl(hdr->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), - ntohs(hdr->public_ip.port)); - - /* if ( 0 == memcmp(hdr->dst_mac, eee->device.mac_addr, 6) ) */ - { - if ( hdr->sent_by_supernode ) - { - /* Response to supernode registration. Supernode is not in the pending_peers list. */ - } - else - { - /* Move from pending_peers to known_peers; ignore if not in pending. */ - set_peer_operational( eee, hdr ); - } - } - - } else { - traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored\n", hdr->msg_type); - return; - } - } - } - } - } -} - -/* ***************************************************** */ - - -#ifdef WIN32 -static DWORD tunReadThread(LPVOID lpArg ) -{ - n2n_edge_t *eee = (n2n_edge_t*)lpArg; - - while(1) { - readFromTAPSocket(eee); - } - - return((DWORD)NULL); -} - -/* ***************************************************** */ - -static void startTunReadThread(n2n_edge_t *eee) { - HANDLE hThread; - DWORD dwThreadId; - - hThread = CreateThread(NULL, /* no security attributes */ - 0, /* use default stack size */ - (LPTHREAD_START_ROUTINE)tunReadThread, /* thread function */ - (void*)eee, /* argument to thread function */ - 0, /* use default creation flags */ - &dwThreadId); /* returns the thread identifier */ -} -#endif - -/* ***************************************************** */ - -static void supernode2addr(n2n_edge_t * eee, char* addr) { - char *supernode_host = strtok(addr, ":"); - - if(supernode_host) { - char *supernode_port = strtok(NULL, ":"); - const struct addrinfo aihints = {0, PF_INET, 0, 0, 0, NULL, NULL, NULL}; - struct addrinfo * ainfo = NULL; - int nameerr; - ipstr_t ip_buf; - - if ( supernode_port ) - eee->supernode.port = htons(atoi(supernode_port)); - else - traceEvent(TRACE_WARNING, "Bad supernode parameter (-l )"); - - 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; - - eee->supernode.addr_type.v4_addr = saddr->sin_addr.s_addr; - } - 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); - eee->supernode.addr_type.v4_addr = inet_addr(supernode_host); - } - - traceEvent(TRACE_NORMAL, "Using supernode %s:%hu", - intoa(ntohl(eee->supernode.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), - ntohs(eee->supernode.port)); - } else - traceEvent(TRACE_WARNING, "Wrong supernode parameter (-l )"); -} - -/* ***************************************************** */ - -extern int useSyslog; - -#define N2N_NETMASK_STR_SIZE 16 /* dotted decimal 12 numbers + 3 dots */ - - -int main(int argc, char* argv[]) { - int opt=0; - u_int16_t local_port = 0 /* any port */; - char *tuntap_dev_name = "edge0"; - char *ip_addr = NULL; - 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 */ - int fork_as_daemon=0; -#endif - - size_t numPurged; - time_t lastStatus=0; - - char * device_mac=NULL; - char * encrypt_key=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) ){ - traceEvent( TRACE_ERROR, "Failed in edge_init" ); - exit(1); - } - - if( getenv( "N2N_KEY" )) { - encrypt_key = strdup( getenv( "N2N_KEY" )); - } - -#ifdef WIN32 - tuntap_dev_name = ""; -#endif - memset(&(eee.supernode), 0, sizeof(eee.supernode)); - eee.supernode.family = AF_INET; - - linebuffer = (char *)malloc(MAX_CMDLINE_BUFFER_LENGTH); - if (!linebuffer) { - traceEvent( TRACE_ERROR, "Unable to allocate memory"); - exit(1); - } - snprintf(linebuffer, MAX_CMDLINE_BUFFER_LENGTH, "%s",argv[0]); - -#ifdef WIN32 - for(i=0; i COMMUNITY_LEN) - eee.community_name[COMMUNITY_LEN] = '\0'; - break; -#ifndef WIN32 - - case 'u': /* uid */ - { - userid = atoi(optarg); - break; - } - case 'g': /* uid */ - { - groupid = atoi(optarg); - break; - } - case 'f' : /* fork as daemon */ - { - fork_as_daemon = 1; - break; - } -#endif - case 'm' : /* device_mac */ - { - device_mac = strdup(optarg); - break; - } - case 'M' : /* device_mac */ - { - mtu = atoi(optarg); - break; - } - case 'k': /* encrypt key */ - encrypt_key = strdup(optarg); - break; - case 'r': /* enable packet routing across n2n endpoints */ - eee.allow_routing = 1; - break; - case 'l': /* supernode-list */ - snprintf(eee.supernode_ip, sizeof(eee.supernode_ip), "%s", optarg); - supernode2addr(&eee, eee.supernode_ip); - break; -#ifdef __linux__ - case 'd': /* tun-device */ - tuntap_dev_name = strdup(optarg); - break; -#endif - case 't': /* Use HTTP tunneling */ - eee.sinfo.is_udp_socket = 0; - break; - case 'b': - eee.re_resolve_supernode_ip = 1; - break; - case 'p': - local_port = atoi(optarg) & 0xffff; - 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 = 3; - break; - } - } - - if(!( -#ifdef __linux__ - tuntap_dev_name && -#endif - eee.community_name && - ip_addr && - eee.supernode.addr_type.v4_addr && - encrypt_key)) - help(); - -#ifndef WIN32 - /* If running suid root then we need to setuid before using the force. */ - setuid( 0 ); - /* setgid( 0 ); */ -#endif - - if(tuntap_open(&(eee.device), tuntap_dev_name, ip_addr, netmask, device_mac, mtu) < 0) - return(-1); - -#ifndef WIN32 - if ( (userid != 0) || (groupid != 0 ) ) { - traceEvent(TRACE_NORMAL, "Interface up. Dropping privileges to uid=%d, gid=%d", userid, groupid); - - /* Finished with the need for root privileges. Drop to unprivileged user. */ - setreuid( userid, userid ); - setregid( groupid, groupid ); - } -#endif - - if(local_port > 0) - traceEvent(TRACE_NORMAL, "Binding to local port %hu", local_port); - - if(edge_init_twofish( &eee, (u_int8_t *)(encrypt_key), strlen(encrypt_key) ) < 0) return(-1); - eee.sinfo.sock = open_socket(local_port, eee.sinfo.is_udp_socket, 0); - if(eee.sinfo.sock < 0) return(-1); - - if( !(eee.sinfo.is_udp_socket) ) { - int rc = connect_socket(eee.sinfo.sock, &(eee.supernode)); - - if(rc == -1) { - traceEvent(TRACE_WARNING, "Error while connecting to supernode\n"); - return(-1); - } - } - -#ifndef WIN32 - if ( fork_as_daemon ) - { - useSyslog=1; /* traceEvent output now goes to syslog. */ - daemon( 0, 0 ); - } -#endif - - update_registrations(&eee); - - traceEvent(TRACE_NORMAL, ""); - traceEvent(TRACE_NORMAL, "Ready"); - -#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(1) { - int rc, max_sock = 0; - fd_set socket_mask; - struct timeval wait_time; - time_t nowTime; - - FD_ZERO(&socket_mask); - FD_SET(eee.sinfo.sock, &socket_mask); -#ifndef WIN32 - FD_SET(eee.device.fd, &socket_mask); - max_sock = max( eee.sinfo.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); - - if(rc > 0) - { - /* Any or all of the FDs could have input; check them all. */ - - if(FD_ISSET(eee.sinfo.sock, &socket_mask)) - { - /* Read a cooked socket from the internet socket. Writes on the TAP - * socket. */ - readFromIPSocket(&eee); - } - -#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 - } - - update_registrations(&eee); - - numPurged = purge_expired_registrations( &(eee.known_peers) ); - numPurged += purge_expired_registrations( &(eee.pending_peers) ); - if ( numPurged > 0 ) - { - traceEvent( TRACE_NORMAL, "Peer removed: pending=%ld, operational=%ld", - peer_list_size( eee.pending_peers ), peer_list_size( eee.known_peers ) ); - } - - if ( ( nowTime - lastStatus ) > STATUS_UPDATE_INTERVAL ) - { - lastStatus = nowTime; - - traceEvent( TRACE_NORMAL, "STATUS: pending=%ld, operational=%ld", - peer_list_size( eee.pending_peers ), peer_list_size( eee.known_peers ) ); - } - } /* while */ - - send_deregister( &eee, &(eee.supernode)); - - closesocket(eee.sinfo.sock); - tuntap_close(&(eee.device)); - - edge_deinit( &eee ); - - return(0); -} - - diff --git a/n2n_v1/n2n.c b/n2n_v1/n2n.c deleted file mode 100644 index a654c9a..0000000 --- a/n2n_v1/n2n.c +++ /dev/null @@ -1,922 +0,0 @@ -/* - * (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. - * - * 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 - * - * Code contributions courtesy of: - * Richard Andrews - * Massimo Torquati - * - */ - -#include "n2n.h" - -#include "minilzo.h" - -#include - -#if defined(DEBUG) -# define PURGE_REGISTRATION_FREQUENCY 60 -# define REGISTRATION_TIMEOUT 120 -#else /* #if defined(DEBUG) */ -# define PURGE_REGISTRATION_FREQUENCY 60 -# define REGISTRATION_TIMEOUT (60*5) -#endif /* #if defined(DEBUG) */ - - -char broadcast_addr[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -char multicast_addr[6] = { 0x01, 0x00, 0x05, 0x00, 0x00, 0x00 }; /* First 3 bytes are meaningful */ - -/* ************************************** */ - -static void print_header( const char * msg, const struct n2n_packet_header * hdr ) -{ - ipstr_t buf; - ipstr_t buf2; - - traceEvent(TRACE_INFO, "%s hdr: public_ip=(%d)%s:%d, private_ip=(%d)%s:%d", msg, - hdr->public_ip.family, - intoa(ntohl(hdr->public_ip.addr_type.v4_addr), buf, sizeof(buf)), - ntohs(hdr->public_ip.port), - hdr->private_ip.family, - intoa(ntohl(hdr->private_ip.addr_type.v4_addr), buf2, sizeof(buf2)), - ntohs(hdr->private_ip.port) - ); -} - -/* *********************************************** */ - -extern void sockaddr_in2peer_addr(struct sockaddr_in *in, struct peer_addr *out) { - out->family = (u_int8_t)in->sin_family; - out->port = in->sin_port; - out->addr_type.v4_addr = in->sin_addr.s_addr; -} - -/* *********************************************** */ - -extern void peer_addr2sockaddr_in(const struct peer_addr *in, struct sockaddr_in *out) { - out->sin_family = in->family; - out->sin_port = in->port; - out->sin_addr.s_addr = in->addr_type.v4_addr; -} - -/* ************************************** */ - -static -int marshall_peer_addr( u_int8_t * buf, size_t * offset, const struct peer_addr * s ) -{ - /* RA: I'm pretty sure that this is broken. There is no guarantee that the - * peer_addr structure is packed. This will always work between like hosts but - * is almost certainly broken between different host types. */ - memcpy( buf + *offset, s, sizeof(struct peer_addr)); - *offset += sizeof(struct peer_addr); - - return sizeof(struct peer_addr); /* bytes written */ -} - -/* ************************************** */ - -static -int marshall_uint32( u_int8_t * buf, size_t * offset, u_int32_t val ) -{ - buf[*offset + 0] = ((val >> 24) & 0xff); - buf[*offset + 1] = ((val >> 16) & 0xff); - buf[*offset + 2] = ((val >> 8) & 0xff); - buf[*offset + 3] = ((val ) & 0xff); - - *offset += 4; - return 4; -} - -/* ************************************** */ - -int marshall_n2n_packet_header( u_int8_t * buf, const struct n2n_packet_header * hdr ) -{ - size_t offset = 0; - - print_header( "Marshalling ", hdr ); - - *(buf+offset) = hdr->version; - ++offset; - - *(buf+offset) = hdr->msg_type; - ++offset; - - *(buf+offset) = hdr->ttl; - ++offset; - - *(buf+offset) = hdr->sent_by_supernode; - ++offset; - - memcpy( buf+offset, hdr->community_name, COMMUNITY_LEN ); - offset += COMMUNITY_LEN; - - memcpy( buf+offset, hdr->src_mac, 6 ); - offset += 6; - - memcpy( buf+offset, hdr->dst_mac, 6 ); - offset += 6; - - marshall_peer_addr( buf, &offset, &(hdr->public_ip) ); - marshall_peer_addr( buf, &offset, &(hdr->private_ip) ); - - *(buf+offset) = (hdr->pkt_type & 0xff); - ++offset; - - marshall_uint32( buf, &offset, hdr->sequence_id ); - marshall_uint32( buf, &offset, hdr->crc ); - - return offset; -} - -/* ************************************** */ - -static -int unmarshall_peer_addr( struct peer_addr * s, size_t * offset, - const u_int8_t * buf ) -{ - memcpy(s, buf + *offset, sizeof(struct peer_addr)); - *offset += sizeof(struct peer_addr); - return (sizeof(struct peer_addr)); /* bytes written */ -} - -/* ************************************** */ - -static -int unmarshall_uint32( u_int32_t * val, size_t * offset, const u_int8_t * buf ) -{ - *val = ( (buf[*offset + 0] & 0xff) << 24 ); - *val |= ( (buf[*offset + 1] & 0xff) << 16 ); - *val |= ( (buf[*offset + 2] & 0xff) << 8 ); - *val |= ( (buf[*offset + 3] & 0xff) ); - - *offset += 4; - return 4; -} - -/* ************************************** */ - -int unmarshall_n2n_packet_header( struct n2n_packet_header * hdr, const u_int8_t * buf ) -{ - size_t offset=0; - - hdr->version = *(buf + offset); - ++offset; - - hdr->msg_type = *(buf + offset); - ++offset; - - hdr->ttl = *(buf + offset); - ++offset; - - hdr->sent_by_supernode = *(buf + offset); - ++offset; - - memcpy( hdr->community_name, (buf + offset), COMMUNITY_LEN ); - offset += COMMUNITY_LEN; - - memcpy( hdr->src_mac, (buf + offset), 6 ); - offset += 6; - - memcpy( hdr->dst_mac, (buf + offset), 6 ); - offset += 6; - - unmarshall_peer_addr( &(hdr->public_ip), &offset, buf ); - unmarshall_peer_addr( &(hdr->private_ip), &offset, buf ); - - hdr->pkt_type = (*(buf + offset) & 0xff); /* Make sure only 8 bits are copied. */ - ++offset; - - unmarshall_uint32( &(hdr->sequence_id), &offset, buf ); - unmarshall_uint32( &(hdr->crc), &offset, buf ); - - print_header( "Unmarshalled ", hdr ); - - return offset; -} - -/* ************************************** */ - -SOCKET open_socket(u_int16_t local_port, int udp_sock, int server_mode) { - SOCKET sock_fd; - struct sockaddr_in local_address; - int sockopt = 1; - - if((sock_fd = socket(PF_INET, udp_sock ? SOCK_DGRAM : SOCK_STREAM, 0)) < 0) { - traceEvent(TRACE_ERROR, "Unable to create socket [%s][%d]\n", - strerror(errno), sock_fd); - return(-1); - } - -#ifndef WIN32 - /* fcntl(sock_fd, F_SETFL, O_NONBLOCK); */ -#endif - - 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 = INADDR_ANY; - if(bind(sock_fd, (struct sockaddr*) &local_address, sizeof(local_address)) == -1) { - traceEvent(TRACE_ERROR, "Bind error [%s]\n", strerror(errno)); - return(-1); - } - - if((!udp_sock) && server_mode) { - if(listen(sock_fd, 255) == -1) { - traceEvent(TRACE_ERROR, "Listen error [%s]\n", strerror(errno)); - return(-1); - } - } - - return(sock_fd); -} - -/* ************************************** */ - -int connect_socket(int sock_fd, struct peer_addr* _dest) { - char *http_header; - int len, rc; - struct sockaddr_in dest; - - peer_addr2sockaddr_in(_dest, &dest); - - /* FIX: add IPv6 support */ - rc = connect(sock_fd, (struct sockaddr*)&dest, sizeof(struct sockaddr_in)); - - if(rc == -1) { - traceEvent(TRACE_WARNING, "connect() error [%s]\n", strerror(errno)); - return(-1); - } - - /* Send dummy http header */ - http_header = "GET / HTTP/1.0\r\n\r\n"; - len = strlen(http_header); - rc = send(sock_fd, http_header, len, 0); - - return((rc == len) ? 0 : -1); -} - - -/* *********************************************** */ - -void send_packet(n2n_sock_info_t * sinfo, - char *packet, size_t *packet_len, - const struct peer_addr *remote_peer, u_int8_t compress_data) { - int data_sent_len; - - data_sent_len = unreliable_sendto(sinfo, - packet, packet_len, remote_peer, compress_data); - - if(data_sent_len != *packet_len) - traceEvent(TRACE_WARNING, - "sendto() [sent=%d][attempted_to_send=%d] [%s]\n", - data_sent_len, *packet_len, strerror(errno)); -} - -/* *********************************************** */ - -int traceLevel = 2 /* NORMAL */; -int useSyslog = 0, syslog_opened = 0; - -#define N2N_TRACE_DATESIZE 32 -void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...) { - va_list va_ap; - - if(eventTraceLevel <= traceLevel) { - char buf[2048]; - char out_buf[640]; - char theDate[N2N_TRACE_DATESIZE]; - char *extra_msg = ""; - time_t theTime = time(NULL); -#ifdef WIN32 - 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), - * those without the headers !defined(USE_SYSLOG) - * those where it's parametrically off... - */ - - memset(buf, 0, sizeof(buf)); - strftime(theDate, N2N_TRACE_DATESIZE, "%d/%b/%Y %H:%M:%S", localtime(&theTime)); - - va_start (va_ap, format); - vsnprintf(buf, sizeof(buf)-1, format, va_ap); - va_end(va_ap); - - if(eventTraceLevel == 0 /* TRACE_ERROR */) - extra_msg = "ERROR: "; - else if(eventTraceLevel == 1 /* TRACE_WARNING */) - extra_msg = "WARNING: "; - - while(buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0'; - -#ifndef WIN32 - if(useSyslog) { - if(!syslog_opened) { - openlog("n2n", LOG_PID, LOG_DAEMON); - syslog_opened = 1; - } - - snprintf(out_buf, sizeof(out_buf), "%s%s", extra_msg, buf); - syslog(LOG_INFO, out_buf); - } else { - snprintf(out_buf, sizeof(out_buf), "%s [%11s:%4d] %s%s", theDate, file, line, extra_msg, buf); - printf("%s\n", out_buf); - fflush(stdout); - } -#else - /* this is the WIN32 code */ - 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); -#endif - } - -} - -/* *********************************************** */ - -/* addr should be in network order. Things are so much simpler that way. */ -char* intoa(u_int32_t /* host order */ addr, char* buf, u_short buf_len) { - char *cp, *retStr; - u_int byte; - int n; - - cp = &buf[buf_len]; - *--cp = '\0'; - - n = 4; - do { - byte = addr & 0xff; - *--cp = byte % 10 + '0'; - byte /= 10; - if (byte > 0) { - *--cp = byte % 10 + '0'; - byte /= 10; - if (byte > 0) - *--cp = byte + '0'; - } - *--cp = '.'; - addr >>= 8; - } while (--n > 0); - - /* Convert the string to lowercase */ - retStr = (char*)(cp+1); - - return(retStr); -} - -/* *********************************************** */ - -char* macaddr_str(const char *mac, char *buf, int buf_len) { - snprintf(buf, buf_len, "%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); -} - -/* *********************************************** */ - -void fill_standard_header_fields(n2n_sock_info_t * sinfo, - struct n2n_packet_header *hdr, char *src_mac) { - socklen_t len = sizeof(hdr->private_ip); - memset(hdr, 0, N2N_PKT_HDR_SIZE); - hdr->version = N2N_PKT_VERSION; - hdr->crc = 0; // FIX - if(src_mac != NULL) memcpy(hdr->src_mac, src_mac, 6); - getsockname(sinfo->sock, (struct sockaddr*)&hdr->private_ip, &len); - hdr->public_ip.family = AF_INET; -} - -/* *********************************************** */ - -void send_ack(n2n_sock_info_t * sinfo, - u_int16_t last_rcvd_seq_id, - struct n2n_packet_header *header, - struct peer_addr *remote_peer, - char *src_mac) { - - /* marshalling double-checked. */ - struct n2n_packet_header hdr; - u_int8_t pkt[ N2N_PKT_HDR_SIZE ]; - size_t len = sizeof(hdr); - size_t len2; - int compress_data = N2N_COMPRESSION_ENABLED; - - fill_standard_header_fields(sinfo, &hdr, src_mac); - hdr.msg_type = MSG_TYPE_ACK_RESPONSE; - hdr.sequence_id = last_rcvd_seq_id; - memcpy(hdr.community_name, header->community_name, COMMUNITY_LEN); - - len2=marshall_n2n_packet_header( pkt, &hdr ); - assert( len2 == len ); - - send_packet(sinfo, (char*)pkt, &len, remote_peer, compress_data); -} - -/* *********************************************** */ - -u_int8_t is_multi_broadcast(char *dest_mac) { - return(((!memcmp(broadcast_addr, dest_mac, 6)) - || (!memcmp(multicast_addr, dest_mac, 3))) ? 1 : 0); -} - -/* *********************************************** */ - -/* http://www.faqs.org/rfcs/rfc908.html */ - -u_int receive_data(n2n_sock_info_t * sinfo, - char *packet, size_t packet_len, - struct peer_addr *from, u_int8_t *discarded_pkt, - char *tun_mac_addr, u_int8_t decompress_data, - struct n2n_packet_header *hdr) { - socklen_t fromlen = sizeof(struct sockaddr_in); - int len; - char *payload, *pkt_type; - macstr_t src_mac_buf; - macstr_t dst_mac_buf; - ipstr_t ip_buf; - ipstr_t from_ip_buf; - - if(sinfo->is_udp_socket) { - struct sockaddr_in _from; - len = recvfrom(sinfo->sock, packet, packet_len, 0, (struct sockaddr*)&_from, &fromlen); - sockaddr_in2peer_addr(&_from, from); - } else { - len = recv(sinfo->sock, packet, 4, 0); - if(len == 4) { - packet[4] = '\0'; - len = atoi(packet); - len = recv(sinfo->sock, packet, len, 0); - } else { - traceEvent(TRACE_WARNING, "Unable to receive n2n packet length"); - return(-1); - } - } - - unmarshall_n2n_packet_header(hdr, (u_int8_t *)packet); - - payload = &packet[N2N_PKT_HDR_SIZE]; - - if(len < 0) { -#ifdef WIN32 - if(WSAGetLastError() != WSAECONNRESET /* http://support.microsoft.com/kb/263823 */ ) { - traceEvent(TRACE_WARNING, "recvfrom returned %d [err=%d]", len, WSAGetLastError()); - } -#endif - return(0); - } else if(len > MIN_COMPRESSED_PKT_LEN) { -#define N2N_DECOMPRESS_BUFSIZE 2048 - char decompressed[N2N_DECOMPRESS_BUFSIZE]; - int rc; - lzo_uint decompressed_len=N2N_DECOMPRESS_BUFSIZE; - size_t insize = len-N2N_PKT_HDR_SIZE; - - if(decompress_data) { - rc = lzo1x_decompress_safe((u_char*)&packet[N2N_PKT_HDR_SIZE], - insize, - (u_char*)decompressed, &decompressed_len, NULL); - - if(rc == LZO_E_OK) - { - traceEvent(TRACE_INFO, "%u bytes decompressed into %u", insize, decompressed_len); - } - else - { - traceEvent(TRACE_WARNING, "Failed to decompress %u byte packet. LZO error=%d", insize, rc ); - return -1; - } - - if(packet_len > decompressed_len) { - memcpy(&packet[N2N_PKT_HDR_SIZE], decompressed, decompressed_len); - len = decompressed_len+N2N_PKT_HDR_SIZE; - } else { - traceEvent(TRACE_WARNING, "Uncompressed packet is too large [decompressed_len=%d]", - decompressed_len); - return(0); - } - } - - (*discarded_pkt) = 0; - - if(!hdr->sent_by_supernode) { - memcpy( &packet[offsetof(struct n2n_packet_header, public_ip)], from, sizeof(struct sockaddr_in) ); - } - - switch(hdr->pkt_type) { - case packet_unreliable_data: - pkt_type = "unreliable data"; - break; - case packet_reliable_data: - pkt_type = "reliable data"; - break; - case packet_ping: - pkt_type = "ping"; - break; - case packet_pong: - pkt_type = "pong"; - break; - default: - pkt_type = "???"; - } - - traceEvent(TRACE_INFO, "+++ Received %s packet [rcvd_from=%s:%d][msg_type=%s][seq_id=%d]", - pkt_type, - intoa(ntohl(from->addr_type.v4_addr), from_ip_buf, sizeof(from_ip_buf)), - ntohs(from->port), msg_type2str(hdr->msg_type), - hdr->sequence_id); - traceEvent(TRACE_INFO, " [src_mac=%s][dst_mac=%s][original_sender=%s:%d]", - macaddr_str(hdr->src_mac, src_mac_buf, sizeof(src_mac_buf)), - macaddr_str(hdr->dst_mac, dst_mac_buf, sizeof(dst_mac_buf)), - intoa(ntohl(hdr->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), - ntohs(hdr->public_ip.port)); - -#ifdef HANDLE_RETRANSMISSION - if((hdr->pkt_type == packet_reliable_data) - && (hdr->msg_type == MSG_TYPE_PACKET)) { - (*discarded_pkt) = handle_ack(sock_fd, is_udp_socket, hdr, - &payload[6], payload, from, tun_mac_addr); - } else - (*discarded_pkt) = 0; -#endif - } else - traceEvent(TRACE_WARNING, "Receive error [%s] or pkt too short [len=%d]\n", - strerror(errno), len); - - return(len); -} - -/* *********************************************** */ - -#if 0 -static u_int32_t queue_packet(struct send_hash_entry *scan, - char *packet, - u_int16_t packet_len) { - struct packet_list *pkt = (struct packet_list*)malloc(sizeof(struct packet_list)); - - if(pkt == NULL) { - traceEvent(TRACE_ERROR, "Not enough memory!"); - return(0); - } - - if((pkt->packet = (char*)malloc(packet_len)) == NULL) { - traceEvent(TRACE_ERROR, "Not enough memory!"); - return(0); - } - - memcpy(pkt->packet, packet, packet_len); - pkt->packet_len = packet_len; - pkt->seq_id = scan->last_seq_id; - pkt->next = scan->unacked_packet_list; - scan->unacked_packet_list = pkt; - scan->num_unacked_pkts++; - return(pkt->seq_id); -} -#endif - -/* *********************************************** */ - -/* 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); - -/* ******************************************************* */ - -u_int send_data(n2n_sock_info_t * sinfo, - char *packet, size_t *packet_len, - const struct peer_addr *to, u_int8_t compress_data) { - char compressed[1650]; - int rc; - lzo_uint compressed_len=0; - struct sockaddr_in destsock; - - if(*packet_len < N2N_PKT_HDR_SIZE) { - traceEvent(TRACE_WARNING, "The packet about to be sent is too short [len=%d]\n", *packet_len); - return(-1); - } - - memcpy(compressed, packet, N2N_PKT_HDR_SIZE); - - peer_addr2sockaddr_in(to, &destsock); - - if(compress_data) { - rc = lzo1x_1_compress((u_char*)&packet[N2N_PKT_HDR_SIZE], - *packet_len - N2N_PKT_HDR_SIZE, - (u_char*)&compressed[N2N_PKT_HDR_SIZE], - &compressed_len, wrkmem); - - if ( 0 == compressed_len ) - { - traceEvent(TRACE_WARNING, "failed to compress %u bytes.", (*packet_len - N2N_PKT_HDR_SIZE) ); - return -1; - } - - compressed_len += N2N_PKT_HDR_SIZE; - - traceEvent(TRACE_INFO, "%u bytes compressed into %u", *packet_len, compressed_len); - /* *packet_len = compressed_len; */ - - if(sinfo->is_udp_socket) { - rc = sendto(sinfo->sock, compressed, compressed_len, 0, - (struct sockaddr*)&destsock, sizeof(struct sockaddr_in)); - } else { - char send_len[5]; - - /* 4 bytes packet length */ - snprintf(send_len, sizeof(send_len), "%04d", (int)compressed_len); - if((rc = send(sinfo->sock, send_len, 4, 0)) != 4) - return(-1); - if((rc = send(sinfo->sock, compressed, compressed_len, 0)) != compressed_len) { - traceEvent(TRACE_WARNING, "send error [%d][%s]", - errno, strerror(errno)); - } - } - } else { - compressed_len = *packet_len; - if(sinfo->is_udp_socket) - rc = sendto(sinfo->sock, packet, compressed_len, 0, - (struct sockaddr*)&destsock, sizeof(struct sockaddr_in)); - else { - char send_len[5]; - - /* 4 bytes packet length */ - snprintf(send_len, sizeof(send_len), "%04d", (int)compressed_len); - if((rc = send(sinfo->sock, send_len, 4, 0)) != 4) - return(-1); - rc = send(sinfo->sock, compressed, compressed_len, 0); - } - - if(rc == -1) { - ipstr_t ip_buf; - - traceEvent(TRACE_WARNING, "sendto() failed while attempting to send data to %s:%d", - intoa(ntohl(to->addr_type.v4_addr), ip_buf, sizeof(ip_buf)), - ntohs(to->port)); - } - } - - if ( rc >= 0) { - traceEvent(TRACE_INFO, "### Tx N2N Msg -> network"); - } - - if(rc == compressed_len) - return(*packet_len); /* fake just to avoid warnings */ - else - return(rc); -} - -/* *********************************************** */ - -u_int reliable_sendto(n2n_sock_info_t * sinfo, - char *packet, size_t *packet_len, - const struct peer_addr *to, u_int8_t compress_data) { - /* char *payload = &packet[N2N_PKT_HDR_SIZE]; */ - struct n2n_packet_header hdr_storage; - struct n2n_packet_header *hdr = &hdr_storage; - macstr_t src_mac_buf; - macstr_t dst_mac_buf; - - /* REVISIT: efficiency of unmarshal + re-marshal just to change a couple of bits. */ - unmarshall_n2n_packet_header( hdr, (u_int8_t *)packet ); - - /* hdr->sequence_id = (hdr->msg_type == MSG_TYPE_PACKET) ? mac2sequence((u_char*)payload, packet, *packet_len) : 0; */ - hdr->sequence_id = 0; - hdr->pkt_type = packet_reliable_data; - - traceEvent(TRACE_INFO, "Sent reliable packet [msg_type=%s][seq_id=%d][src_mac=%s][dst_mac=%s]", - msg_type2str(hdr->msg_type), hdr->sequence_id, - macaddr_str(&packet[6], src_mac_buf, sizeof(src_mac_buf)), - macaddr_str(packet, dst_mac_buf, sizeof(dst_mac_buf))); - - marshall_n2n_packet_header( (u_int8_t *)packet, hdr ); - - return(send_data(sinfo, packet, packet_len, to, compress_data)); -} - -/* *********************************************** */ - -/* unreliable_sendto is passed a fully marshalled, packet. Its purpose is to set - * the unreliable flags but leave the rest of the packet untouched. */ -u_int unreliable_sendto(n2n_sock_info_t * sinfo, - char *packet, size_t *packet_len, - const struct peer_addr *to, u_int8_t compress_data) { - struct n2n_packet_header hdr_storage; - struct n2n_packet_header *hdr = &hdr_storage; - macstr_t src_mac_buf; - macstr_t dst_mac_buf; - - /* REVISIT: efficiency of unmarshal + re-marshal just to change a couple of bits. */ - unmarshall_n2n_packet_header( hdr, (u_int8_t *)packet ); - - hdr->sequence_id = 0; /* Unreliable messages have 0 as sequence number */ - hdr->pkt_type = packet_unreliable_data; - - traceEvent(TRACE_INFO, "Sent unreliable packet [msg_type=%s][seq_id=%d][src_mac=%s][dst_mac=%s]", - msg_type2str(hdr->msg_type), hdr->sequence_id, - macaddr_str(hdr->src_mac, src_mac_buf, sizeof(src_mac_buf)), - macaddr_str(hdr->dst_mac, dst_mac_buf, sizeof(dst_mac_buf))); - - marshall_n2n_packet_header( (u_int8_t *)packet, hdr ); - - return(send_data(sinfo, packet, packet_len, to, compress_data)); -} - -/* *********************************************** */ - -char* msg_type2str(u_short msg_type) { - switch(msg_type) { - case MSG_TYPE_REGISTER: return("MSG_TYPE_REGISTER"); - case MSG_TYPE_DEREGISTER: return("MSG_TYPE_DEREGISTER"); - case MSG_TYPE_PACKET: return("MSG_TYPE_PACKET"); - case MSG_TYPE_REGISTER_ACK: return("MSG_TYPE_REGISTER_ACK"); - case MSG_TYPE_ACK_RESPONSE: return("MSG_TYPE_ACK_RESPONSE"); - } - - return("???"); -} - -/* *********************************************** */ - -void hexdump(char *buf, u_int len) { - u_int i; - - for(i=0; i 0) && ((i % 16) == 0)) printf("\n"); - printf("%02X ", buf[i] & 0xFF); - } - - printf("\n"); -} - -/* *********************************************** */ - -void print_n2n_version() { - printf("Welcome to n2n v.%s for %s\n" - "Built on %s\n" - "Copyright 2007-08 - http://www.ntop.org\n\n", - version, osName, buildDate); -} - - - - -/** Find the peer entry in list with mac_addr equal to mac. - * - * Does not modify the list. - * - * @return NULL if not found; otherwise pointer to peer entry. - */ -struct peer_info * find_peer_by_mac( struct peer_info * list, const char * mac ) -{ - while(list != NULL) - { - if( 0 == memcmp(mac, list->mac_addr, 6) ) - { - return list; - } - list = list->next; - } - - return NULL; -} - - -/** Return the number of elements in the list. - * - */ -size_t peer_list_size( const struct peer_info * list ) -{ - size_t retval=0; - - while ( list ) - { - ++retval; - list = list->next; - } - - return retval; -} - -/** Add new to the head of list. If list is NULL; create it. - * - * 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 ) -{ - new->next = *list; - new->last_seen = time(NULL); - *list = new; -} - - -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; - - if((now - last_purge) < PURGE_REGISTRATION_FREQUENCY) return 0; - - traceEvent(TRACE_INFO, "Purging old registrations"); - - num_reg = purge_peer_list( peer_list, now-REGISTRATION_TIMEOUT ); - - last_purge = now; - traceEvent(TRACE_INFO, "Remove %ld registrations", num_reg); - - return num_reg; -} - -/** 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 ) -{ - struct peer_info *scan; - struct peer_info *prev; - size_t retval=0; - - scan = *peer_list; - prev = NULL; - while(scan != NULL) - { - if(scan->last_seen < purge_before) - { - struct peer_info *next = scan->next; - - if(prev == NULL) - { - *peer_list = next; - } - else - { - prev->next = next; - } - - ++retval; - free(scan); - scan = next; - } - else - { - prev = scan; - scan = scan->next; - } - } - - return retval; -} - -static u_int8_t hex2byte( const char * s ) -{ - char tmp[3]; - tmp[0]=s[0]; - tmp[1]=s[1]; - tmp[2]=0; /* NULL term */ - - return((u_int8_t)strtol( s, NULL, 16 )); -} - -extern int str2mac( u_int8_t * outmac /* 6 bytes */, const char * s ) -{ - size_t i; - - /* break it down as one case for the first "HH", the 5 x through loop for - * each ":HH" where HH is a two hex nibbles in ASCII. */ - - *outmac=hex2byte(s); - ++outmac; - s+=2; /* don't skip colon yet - helps generalise loop. */ - - for (i=1; i<6; ++i ) - { - s+=1; - *outmac=hex2byte(s); - ++outmac; - s+=2; - } - - return 0; /* ok */ -} diff --git a/n2n_v1/n2n.h b/n2n_v1/n2n.h deleted file mode 100644 index 3ef4372..0000000 --- a/n2n_v1/n2n.h +++ /dev/null @@ -1,299 +0,0 @@ -/* - * (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. - * - * 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 - * - * Code contributions courtesy of: - * Babak Farrokhi [FreeBSD port] - * -*/ - -#ifndef _N2N_H_ -#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 -u UID -t tunX -*/ - -#if defined(__APPLE__) && defined(__MACH__) -#define _DARWIN_ -#endif - -#ifdef WIN32 -#include "win32/n2n_win32.h" -#endif - -#include -#include -#include - -#ifndef WIN32 -#include -#endif - -#include -#include -#include - -#ifndef WIN32 -#include -#include -#include -#include -#include - -#ifdef __linux__ -#include -#include -#endif - -#ifdef __FreeBSD__ -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define closesocket(a) close(a) -#endif - -#include -#ifdef WIN32 -#include "win32/getopt.h" -#else -#define _GNU_SOURCE -#include -#endif - -#include - -#ifdef WIN32 -#include "win32/wintap.h" -#endif - -#include "twofish.h" - -#ifndef WIN32 -typedef struct tuntap_dev { - int fd; - u_int8_t mac_addr[6]; - u_int32_t ip_addr, device_mask; - u_int mtu; -} tuntap_dev; - -#define SOCKET int -#endif /* #ifndef WIN32 */ - -#define QUICKLZ 1 -#define N2N_PKT_VERSION 1 - -#define MSG_TYPE_REGISTER 1 /* FIX invece di usare il sender del pacchetto scriverlo nel pacchetto stesso */ -#define MSG_TYPE_DEREGISTER 2 -#define MSG_TYPE_PACKET 3 -#define MSG_TYPE_REGISTER_ACK 4 -#define MSG_TYPE_ACK_RESPONSE 5 - -#define COMMUNITY_LEN 16 -#define MIN_COMPRESSED_PKT_LEN 32 - -/* Set N2N_COMPRESSION_ENABLED to 0 to disable lzo1x compression of ethernet - * frames. Doing this will break compatibility with the standard n2n packet - * format so do it only for experimentation. All edges must be built with the - * same value if they are to understand each other. */ -#define N2N_COMPRESSION_ENABLED 1 - -#define DEFAULT_MTU 1400 - -/* Maximum enum value is 255 due to marshalling into 1 byte */ -enum packet_type { - packet_unreliable_data = 0, /* no ACK needed */ - packet_reliable_data, /* needs ACK */ - packet_ping, - packet_pong -}; - -/* All information is always in network byte-order */ -struct peer_addr { - u_int8_t family; - u_int16_t port; - union { - u_int8_t v6_addr[16]; - u_int32_t v4_addr; - } addr_type; -}; - -struct n2n_packet_header { - u_int8_t version, msg_type, ttl, sent_by_supernode; - char community_name[COMMUNITY_LEN], src_mac[6], dst_mac[6]; - struct peer_addr public_ip, private_ip; - enum packet_type pkt_type; - u_int32_t sequence_id; - u_int32_t crc; // FIX - It needs to be handled for detcting forged packets -}; - -int marshall_n2n_packet_header( u_int8_t * buf, const struct n2n_packet_header * hdr ); -int unmarshall_n2n_packet_header( struct n2n_packet_header * hdr, const u_int8_t * buf ); - -#define N2N_PKT_HDR_SIZE (sizeof(struct n2n_packet_header)) - - -/** Common type used to hold stringified IP addresses. */ -typedef char ipstr_t[32]; - -/** Common type used to hold stringified MAC addresses. */ -typedef char macstr_t[32]; - -struct n2n_sock_info -{ - int sock; - char is_udp_socket /*= 1*/; -}; - -typedef struct n2n_sock_info n2n_sock_info_t; - -struct peer_info { - char community_name[COMMUNITY_LEN], mac_addr[6]; - struct peer_addr public_ip, private_ip; - time_t last_seen; - struct peer_info *next; - /* socket */ - n2n_sock_info_t sinfo; -}; - -struct n2n_edge; /* defined in edge.c */ -typedef struct n2n_edge n2n_edge_t; - - -/* ************************************** */ - -#if defined(DEBUG) -#define SOCKET_TIMEOUT_INTERVAL_SECS 5 -#define REGISTER_FREQUENCY 20 /* sec */ -#else /* #if defined(DEBUG) */ -#define SOCKET_TIMEOUT_INTERVAL_SECS 10 -#define REGISTER_FREQUENCY 60 /* sec */ -#endif /* #if defined(DEBUG) */ - -#define TRACE_ERROR 0, __FILE__, __LINE__ -#define TRACE_WARNING 1, __FILE__, __LINE__ -#define TRACE_NORMAL 2, __FILE__, __LINE__ -#define TRACE_INFO 3, __FILE__, __LINE__ - -/* ************************************** */ - -#define SUPERNODE_IP "127.0.0.1" -#define SUPERNODE_PORT 1234 - -/* ************************************** */ - -#ifndef max -#define max(a, b) ((a < b) ? b : a) -#endif - -#ifndef min -#define min(a, b) ((a > b) ? b : a) -#endif - -/* ************************************** */ - -/* Variables */ -// extern TWOFISH *tf; -extern int traceLevel; -extern char broadcast_addr[6]; -extern char multicast_addr[6]; - -/* Functions */ -extern void sockaddr_in2peer_addr(struct sockaddr_in *in, struct peer_addr *out); -extern void peer_addr2sockaddr_in(const struct peer_addr *in, struct sockaddr_in *out); -// extern int init_n2n(u_int8_t *encrypt_pwd, u_int32_t encrypt_pwd_len ); -// extern void term_n2n(); -extern void send_ack(n2n_sock_info_t * sinfo, - u_int16_t last_rcvd_seq_id, - struct n2n_packet_header *header, - struct peer_addr *remote_peer, - char *src_mac); - -extern void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...); -extern int tuntap_open(tuntap_dev *device, char *dev, char *device_ip, - char *device_mask, const char * device_mac, int mtu); -extern int tuntap_read(struct tuntap_dev *tuntap, unsigned char *buf, int len); -extern int tuntap_write(struct tuntap_dev *tuntap, unsigned char *buf, int len); -extern void tuntap_close(struct tuntap_dev *tuntap); - -extern SOCKET open_socket(u_int16_t local_port, int udp_sock, int server_mode); -extern int connect_socket(int sock_fd, struct peer_addr* dest); - -extern void send_packet(n2n_sock_info_t * sinfo, - char *packet, size_t *packet_len, - const struct peer_addr *remote_peer, - u_int8_t compress_data); -extern char* intoa(u_int32_t addr, char* buf, u_short buf_len); -extern char* macaddr_str(const char *mac, char *buf, int buf_len); -extern int str2mac( u_int8_t * outmac /* 6 bytes */, const char * s ); -extern void fill_standard_header_fields(n2n_sock_info_t * eee, - struct n2n_packet_header *hdr, - char *src_mac); - -extern u_int receive_data(n2n_sock_info_t * sinfo, - char *packet, size_t packet_len, - struct peer_addr *from, u_int8_t *discarded_pkt, - char *tun_mac_addr, u_int8_t decompress_data, - struct n2n_packet_header *hdr); -extern u_int reliable_sendto(n2n_sock_info_t * sinfo, - char *packet, size_t *packet_len, - const struct peer_addr *from, u_int8_t compress_data); -extern u_int unreliable_sendto(n2n_sock_info_t * sinfo, - char *packet, size_t *packet_len, - const struct peer_addr *from, u_int8_t compress_data); -extern u_int send_data(n2n_sock_info_t * sinfo, - char *packet, size_t *packet_len, - const struct peer_addr *to, u_int8_t compress_data); -extern u_int8_t is_multi_broadcast(char *dest_mac); -extern char* msg_type2str(u_short msg_type); -extern void hexdump(char *buf, u_int len); - -void print_n2n_version(); - - -/* Operations on peer_info lists. */ -struct peer_info * find_peer_by_mac( struct peer_info * list, - const char * mac ); -void peer_list_add( struct peer_info * * list, - struct peer_info * new ); -size_t peer_list_size( const struct peer_info * list ); -size_t purge_peer_list( struct peer_info ** peer_list, - time_t purge_before ); -size_t purge_expired_registrations( struct peer_info ** peer_list ); - -/* version.c */ -extern char *version, *osName, *buildDate; - -#endif /* _N2N_H_ */ diff --git a/n2n_v1/n2n.spec b/n2n_v1/n2n.spec deleted file mode 100644 index 0e7892a..0000000 --- a/n2n_v1/n2n.spec +++ /dev/null @@ -1,47 +0,0 @@ -Summary: N2N peer-to-peer virtual private network system. -Name: n2n -Version: 1.3 -Release: 1 -License: GPLv3 -Vendor: ntop.org -Group: None -URL: http://www.ntop.org/n2n -Source0: %{name}-%{version}.tar.gz -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root - -%description -N2N is a peer-to-peer virtual private network system. N2N uses the universal -TUNTAP interface to create TAP network interfaces to an encrypted virtual -LAN. Members of a community share a common encryption key which allows echange -of data. The supernode is used for peer discovery and initial packet relay -before direct peer-to-peer exchange is established. -Once direct packet exchange is established, the supernode is not required. - -%prep - -%setup -q - -echo -e "\n *** Building ${RPM_PACKAGE_NAME}-${RPM_PACKAGE_VERSION}-${RPM_PACKAGE_RELEASE} ***\n" - -%build -make - -%install -make PREFIX=${RPM_BUILD_ROOT}/usr install - -%clean -rm -rf $RPM_BUILD_ROOT - - -%files -%defattr(-,root,root,-) - /usr/bin/supernode - /usr/sbin/edge -%doc /usr/share/man/man1/supernode.1.gz -%doc /usr/share/man/man8/edge.8.gz - - -%changelog -* Sat May 3 2008 Richard Andrews - -- Initial build. - diff --git a/n2n_v1/openwrt/kamikaze/Makefile b/n2n_v1/openwrt/kamikaze/Makefile deleted file mode 100644 index ddcc7c1..0000000 --- a/n2n_v1/openwrt/kamikaze/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -# -# Copyright (C) 2008 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. - - -include $(TOPDIR)/rules.mk - -PKG_BRANCH:=trunk -PKG_SOURCE_URL:=https://svn.ntop.org/svn/ntop/trunk/n2n -PKG_REV:=$(shell LC_ALL=C svn info ${PKG_SOURCE_URL} | sed -ne's/^Last Changed Rev: //p') - -PKG_NAME:=n2n -PKG_VERSION:=svn$(PKG_REV) -PKG_RELEASE:=1 - -PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) -PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.gz -PKG_SOURCE_PROTO:=svn -PKG_SOURCE_VERSION:=$(PKG_REV) - -PKG_BUILD_DEPENDS:= - -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) -PKG_INSTALL_DIR:=$(PKG_BUILD_DIR) - - - -include $(INCLUDE_DIR)/package.mk - -define Package/n2n - SECTION:=net - CATEGORY:=Network - TITLE:=VPN tunneling daemon - URL:=http://www.ntop.org/n2n/ - SUBMENU:=VPN - DEPENDS:=libpthread -endef - - -define Build/Configure -endef - -define Build/Compile - $(MAKE) CC="$(TARGET_CC)" -C $(PKG_BUILD_DIR) -endef - - -define Package/n2n/install - $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/edge $(1)/usr/sbin/ - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/supernode $(1)/usr/sbin/ -endef - -$(eval $(call BuildPackage,n2n)) diff --git a/n2n_v1/scripts/mk_tar.sh b/n2n_v1/scripts/mk_tar.sh deleted file mode 100644 index 539a565..0000000 --- a/n2n_v1/scripts/mk_tar.sh +++ /dev/null @@ -1,104 +0,0 @@ -#!/bin/bash - -# This script makes a SRPM - a source RPM file which can be built into the -# appropriate distro specific RPM for any platform. -# -# To build the binary package: -# rpm -i n2n-.src.rpm -# rpmbuild -bb n2n.spec -# -# Look for the "Wrote:" line to see where the final RPM is. -# -# To run this script cd to the n2n directory and run it as follows -# scripts/mk_SRPMS.sh -# - -set -e - -function exit_fail() -{ - echo "$1" - exit 1 -} - -PACKAGE="n2n" -PKG_VERSION="1.3" -PKG_AND_VERSION="${PACKAGE}-${PKG_VERSION}" - -TEMPDIR="tmp" - -SOURCE_MANIFEST=" -README -edge.c -lzoconf.h -lzodefs.h -Makefile -minilzo.c -minilzo.h -n2n.c -n2n.h -n2n.spec -supernode.c -tuntap_linux.c -tuntap_freebsd.c -tuntap_osx.c -twofish.c -twofish.h -edge.8 -supernode.1 -debian/changelog -debian/compat -debian/control -debian/copyright -debian/n2n.dirs -debian/n2n.docs -debian/n2n.install -debian/n2n.manpages -debian/README.Debian -debian/rules -" - -BASE=`pwd` - -for F in ${SOURCE_MANIFEST}; do - test -e $F || exit_fail "Cannot find $F. Maybe you're in the wrong directory. Please execute from n2n directory."; >&2 -done - -echo "Found critical files. Proceeding." >&2 - -if [ -d ${TEMPDIR} ]; then - echo "Removing ${TEMPDIR} directory" - rm -rf ${TEMPDIR} >&2 -fi - -mkdir ${TEMPDIR} >&2 - -pushd ${TEMPDIR} >&2 - -echo "Creating staging directory ${PWD}/${PKG_AND_VERSION}" >&2 - -if [ -d ${PKG_AND_VERSION} ] ; then - echo "Removing ${PKG_AND_VERSION} directory" - rm -rf ${PKG_AND_VERSION} >&2 -fi - -mkdir ${PKG_AND_VERSION} - -pushd ${BASE} >&2 - -echo "Copying in files" >&2 -for F in ${SOURCE_MANIFEST}; do - cp --parents -a $F ${TEMPDIR}/${PKG_AND_VERSION}/ -done - -popd >&2 - -TARFILE="${PKG_AND_VERSION}.tar.gz" -echo "Creating ${TARFILE}" >&2 -tar czf ${BASE}/${TARFILE} ${PKG_AND_VERSION} - -popd >&2 - -rm -rf ${TEMPDIR} >&2 - -echo ${BASE}/${TARFILE} diff --git a/n2n_v1/supernode.1 b/n2n_v1/supernode.1 deleted file mode 100644 index 863c498..0000000 --- a/n2n_v1/supernode.1 +++ /dev/null @@ -1,40 +0,0 @@ -.TH supernode 1 "Jan 3, 2009" "revision 3679" "USER COMMANDS" -.SH NAME -supernode \- n2n supernode daemon -.SH SYNOPSIS -.B supernode \-l [\-v] -.SH DESCRIPTION -N2N is a peer-to-peer VPN system. Supernode is a node introduction registry, -broadcast conduit and packet relay node for the n2n system. On startup supernode -begins listening on the specified UDP port for node registrations, and other -packets to route. The supernode can service any number of communities and routes -packets only between members of the same community. The supernode does not hold -the community encryption key and so cannot snoop or inject packets into the -community. -.PP -Supernode can service a number of n2n communities concurrently. Traffic does not -cross between communities. -.PP -All logging goes to stdout. -.SH OPTIONS -.TP -\-l -listen on the given UDP port -.TP -\-v -use verbose logging -.SH EXAMPLES -.TP -.B supernode -l 7654 -v -Start supernode listening on UDP port 7654 with verbose output. -.PP -.SH RESTART -When suprenode restarts it loses all registration information from associated -edge nodes. It can take up to five minutes for the edge nodes to re-register and -normal traffic flow to resume. -.SH EXIT STATUS -supernode is a daemon and any exit is an error -.SH AUTHOR -Luca Deri ( deri (at) ntop.org ), Richard Andrews ( andrews (at) ntop.org ), Don Bindner -.SH SEE ALSO -ifconfig(8) edge(8) diff --git a/n2n_v1/supernode.c b/n2n_v1/supernode.c deleted file mode 100644 index 2f2d6b9..0000000 --- a/n2n_v1/supernode.c +++ /dev/null @@ -1,528 +0,0 @@ -/* - * (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. - * - * 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.h" - -struct tx_stats -{ - size_t pkts; - size_t errors; -}; - - -/* *********************************************** */ - -static void help() { - print_n2n_version(); - printf("supernode -l [-v] [-h]\n"); - exit(0); -} - -/* *********************************************** */ - -static struct peer_info *known_peers = NULL; -static struct tx_stats supernode_stats = {0,0}; - -/* *********************************************** */ - -/** Turn a REGISTER request around and send a REGISTER_ACK packet back to the - * sender. - * - * This needs to be done for all incoming REGISTER packets to keep firewalls - * open - */ -static void send_register_ack( n2n_sock_info_t * sinfo, - const struct peer_addr *destination_peer, - const struct n2n_packet_header * reqhdr ) -{ - struct n2n_packet_header hdr; - u_int8_t pkt[N2N_PKT_HDR_SIZE]; - size_t len = sizeof(hdr); - - fill_standard_header_fields(sinfo, &hdr, NULL /* zero src MAC */ ); - hdr.sent_by_supernode = 1; - hdr.msg_type = MSG_TYPE_REGISTER_ACK; - memcpy( hdr.community_name, reqhdr->community_name, COMMUNITY_LEN); - memcpy( hdr.dst_mac, reqhdr->src_mac, 6); /* turn it around */ - /* leave IP sockets unfilled. */ - - marshall_n2n_packet_header( pkt, &hdr ); - send_packet(sinfo, (char *)pkt, &len, destination_peer, N2N_COMPRESSION_ENABLED); -} - -static void register_peer(struct n2n_packet_header *hdr, - struct peer_addr *sender, - n2n_sock_info_t * sinfo) { - struct peer_info *scan = known_peers; - ipstr_t buf, buf1; - macstr_t mac_buf; - - send_register_ack( sinfo, sender, hdr ); /* keep firewalls open */ - - while(scan != NULL) { - if((strcmp(scan->community_name, hdr->community_name) == 0) - && (memcmp(&scan->mac_addr, hdr->src_mac, 6) == 0)) { - - scan->last_seen = time(NULL); - if ( ( 0 != memcmp(&scan->public_ip, sender, sizeof(struct peer_addr)) ) || - ( 0 != memcmp(&scan->private_ip, &hdr->private_ip, sizeof(struct peer_addr)) ) ) - { - /* Something is actually different. */ - memcpy(&scan->public_ip, sender, sizeof(struct peer_addr)); - memcpy(&scan->private_ip, &hdr->private_ip, sizeof(struct peer_addr)); - - /* Overwrite existing peer */ - traceEvent(TRACE_NORMAL, "Re-registered node [public_ip=(%d)%s:%hu][private_ip=%s:%hu][mac=%s][community=%s]", - scan->public_ip.family, - intoa(ntohl(scan->public_ip.addr_type.v4_addr), buf, sizeof(buf)), - ntohs(scan->public_ip.port), - intoa(ntohl(scan->private_ip.addr_type.v4_addr), buf1, sizeof(buf1)), - ntohs(scan->private_ip.port), - macaddr_str(scan->mac_addr, mac_buf, sizeof(mac_buf)), - scan->community_name); - } - - return; /* Found the registration entry so stop. */ - } - - scan = scan->next; - } - - /* FIX mettere un limite alla lista dei peer */ - - scan = (struct peer_info*)calloc(1, sizeof(struct peer_info)); - memcpy(scan->community_name, hdr->community_name, COMMUNITY_LEN); - memcpy(&scan->public_ip, sender, sizeof(struct peer_addr)); - memcpy(&scan->private_ip, &hdr->private_ip, sizeof(struct peer_addr)); - memcpy(&scan->mac_addr, hdr->src_mac, 6); - scan->last_seen = time(NULL); // FIX aggiungere un timeout - scan->next = known_peers; - scan->sinfo = *sinfo; - known_peers = scan; - - traceEvent(TRACE_NORMAL, "Registered new node [public_ip=(%d)%s:%d][private_ip=%s:%d][mac=%s][community=%s]", - scan->public_ip.family, - intoa(ntohl(scan->public_ip.addr_type.v4_addr), buf, sizeof(buf)), - ntohs(scan->public_ip.port), - intoa(ntohl(scan->private_ip.addr_type.v4_addr), buf1, sizeof(buf1)), - ntohs(scan->private_ip.port), - macaddr_str(scan->mac_addr, mac_buf, sizeof(mac_buf)), - scan->community_name); -} - -/* *********************************************** */ - -static void deregister_peer(struct n2n_packet_header *hdr, - struct peer_addr *sender) { - struct peer_info *scan = known_peers, *prev = NULL; - ipstr_t buf, buf1; - - while(scan != NULL) { - if((strcmp(scan->community_name, hdr->community_name) == 0) - && (memcmp(&scan->mac_addr, hdr->src_mac, 6) == 0)) { - /* Overwrite existing peer */ - if(prev == NULL) - known_peers = scan->next; - else - prev->next = scan->next; - - traceEvent(TRACE_INFO, "Degistered node [public_ip=%s:%hu][private_ip=%s:%hu]", - intoa(ntohl(scan->public_ip.addr_type.v4_addr), buf, sizeof(buf)), - ntohs(scan->public_ip.port), - intoa(ntohl(scan->private_ip.addr_type.v4_addr), buf1, sizeof(buf1)), - ntohs(scan->private_ip.port)); - - free(scan); - return; - } - - scan = scan->next; - } - - traceEvent(TRACE_WARNING, "Unable to delete specified peer [%s:%hu]", - intoa(ntohl(sender->addr_type.v4_addr), buf, sizeof(buf)), - ntohs(sender->port)); -} - -/* *********************************************** */ - -/* *********************************************** */ - -static const struct option long_options[] = { - { "community", required_argument, NULL, 'c' }, - { "listening-port", required_argument, NULL, 'l' }, - { "help" , no_argument, NULL, 'h' }, - { "verbose", no_argument, NULL, 'v' }, - { NULL, 0, NULL, 0 } -}; - -/* *********************************************** */ - - -/** Forward a L2 packet to every edge registered for the community of the - * originator. - * - * @return number of copies of the packet sent - */ -static size_t broadcast_packet(char *packet, u_int packet_len, - struct peer_addr *sender, - n2n_sock_info_t * sinfo, - struct n2n_packet_header *hdr ) -{ - size_t numsent=0; - struct peer_info *scan; - - scan = known_peers; - while(scan != NULL) { - if((strcmp(scan->community_name, hdr->community_name) == 0) - && (memcmp(sender, &scan->public_ip, sizeof(struct peer_addr)) /* No L3 self-send */) ) - { - int data_sent_len; - size_t len = packet_len; - - data_sent_len = send_data( &(scan->sinfo), packet, &len, &scan->public_ip, 0); - - if(data_sent_len != len) - { - ++(supernode_stats.errors); - traceEvent(TRACE_WARNING, "sendto() [sent=%d][attempted_to_send=%d] [%s]\n", - data_sent_len, len, strerror(errno)); - } - else - { - ipstr_t buf; - ipstr_t buf1; - - ++numsent; - ++(supernode_stats.pkts); - traceEvent(TRACE_INFO, "Sent multicast message to remote node [%s:%hu][mac=%s]", - intoa(ntohl(scan->public_ip.addr_type.v4_addr), buf, sizeof(buf)), - ntohs(scan->public_ip.port), - macaddr_str(scan->mac_addr, buf1, sizeof(buf1))); - } - } - - scan = scan->next; - } /* while */ - - - return numsent; -} - - -/** Forward a L2 packet. This may involve a broadcast operation. - * - * Rules are as follows: - * - * 1. If the dest MAC is a multicast address, broadcast to all edges in the - * community. - * - * 2. If the dest MAC is known forward to the destination edge only. - * Else broadcast to all edges in the community. - * - * @return number of copies of the packet sent - */ -static size_t forward_packet(char *packet, u_int packet_len, - struct peer_addr *sender, - n2n_sock_info_t * sinfo, - struct n2n_packet_header *hdr ) -{ - size_t numsent=0; - u_int8_t is_dst_broad_multi_cast; - struct peer_info *scan; - - ipstr_t buf; - ipstr_t buf1; - - hdr->ttl++; /* FIX discard packets with a high TTL */ - is_dst_broad_multi_cast = is_multi_broadcast(hdr->dst_mac); - - /* Put the original packet sender (public) address */ - memcpy(&hdr->public_ip, sender, sizeof(struct peer_addr)); - hdr->sent_by_supernode = 1; - - marshall_n2n_packet_header( (u_int8_t *)packet, hdr ); - - - if ( is_dst_broad_multi_cast ) - { - traceEvent(TRACE_INFO, "Broadcasting. Multicast address [mac=%s]", - macaddr_str(hdr->dst_mac, buf, sizeof(buf))); - - numsent = broadcast_packet( packet, packet_len, sender, sinfo, hdr ); - } - else - { - scan = find_peer_by_mac( known_peers, hdr->dst_mac ); - if ( scan ) - { - int data_sent_len; - size_t len = packet_len; - - data_sent_len = send_data( &(scan->sinfo), packet, &len, &scan->public_ip, 0); - - if(data_sent_len != len) - { - ++(supernode_stats.errors); - traceEvent(TRACE_WARNING, "sendto() [sent=%d][attempted_to_send=%d] [%s]\n", - data_sent_len, len, strerror(errno)); - } - else { - ++(supernode_stats.pkts); - traceEvent(TRACE_INFO, "Sent message to remote node [%s:%hu][mac=%s]", - intoa(ntohl(scan->public_ip.addr_type.v4_addr), buf, sizeof(buf)), - ntohs(scan->public_ip.port), - macaddr_str(scan->mac_addr, buf1, sizeof(buf1))); - } - - numsent = 1; - } - else - { - traceEvent(TRACE_INFO, "Broadcasting because unknown dest [mac=%s]", - macaddr_str(hdr->dst_mac, buf, sizeof(buf))); - numsent = broadcast_packet( packet, packet_len, sender, sinfo, hdr ); - } - } - - return numsent; -} - -static void handle_packet(char *packet, u_int packet_len, - struct peer_addr *sender, - n2n_sock_info_t * sinfo) { - ipstr_t buf; - - traceEvent(TRACE_INFO, "Received message from node [%s:%hu]", - intoa(ntohl(sender->addr_type.v4_addr), buf, sizeof(buf)), - ntohs(sender->port)); - - if(packet_len < N2N_PKT_HDR_SIZE) - traceEvent(TRACE_WARNING, "Received packet too short [len=%d]\n", packet_len); - else { - struct n2n_packet_header hdr_storage; - struct n2n_packet_header *hdr = &hdr_storage; - - unmarshall_n2n_packet_header( hdr, (u_int8_t *)packet ); - - if(hdr->version != N2N_PKT_VERSION) { - traceEvent(TRACE_WARNING, - "Received packet with unknown protocol version (%d): discarded\n", - hdr->version); - return; - } - - if(hdr->msg_type == MSG_TYPE_REGISTER) - { - register_peer(hdr, sender, sinfo); - } - else if(hdr->msg_type == MSG_TYPE_DEREGISTER) { - deregister_peer(hdr, sender); - } else if(hdr->msg_type == MSG_TYPE_PACKET) { - forward_packet( packet, packet_len, sender, sinfo, hdr ); - } else { - traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored\n", - hdr->msg_type); - } - } -} - -/* *********************************************** */ - -static -#ifdef WIN32 -DWORD tcpReadThread(LPVOID lpArg) -#else - void* tcpReadThread(void *lpArg) -#endif -{ - n2n_sock_info_t sinfo; - char c[1600]; - int new_line = 0; - - sinfo.sock=(int)lpArg; - sinfo.is_udp_socket=0; /* TCP in this case */ - - traceEvent(TRACE_NORMAL, "Handling sock_fd %d", sinfo.sock); - - while(1) { - int rc; - - if((rc = recv(sinfo.sock, c, 2, 0)) > 0) { - if((c[0] == '\r') && (c[1] == '\n')) { - if(!new_line) - new_line = 1; - else - break; /* Double \r\n\r\n, the http header is over */ - } else - printf("%c%c [%d][%d] ", c[0], c[1], c[0], c[1]); fflush(stdout); - } else { - traceEvent(TRACE_NORMAL, "recv() error [rc=%d][%s]", rc, strerror(errno)); - break; - } - } - - /* Beginning of n2n protocol over TCP */ - c[5] = 0; - - while(1) { - int rc; - - // FIX: add select - if((rc = recv(sinfo.sock, c, 4, 0)) == 4) { - int len = atoi(c); - socklen_t from_len = sizeof(struct sockaddr_in ); - struct sockaddr_in from; - - /* Check packet length */ - if((len <= 0) || (len >= 1600)) break; - rc = recvfrom(sinfo.sock, c, len, 0, (struct sockaddr*)&from, &from_len); - - if((rc <= 0) || (rc != len)) - break; - else { - struct peer_addr _from; - - sockaddr_in2peer_addr(&from, &_from); - handle_packet(c, len, &_from, &sinfo); - } - } else - break; - } - - closesocket(sinfo.sock); -#ifdef WIN32 - return(0); -#else - return(NULL); -#endif -} - - -/* *********************************************** */ - -static void startTcpReadThread(int sock_fd) { -#ifdef WIN32 - HANDLE hThread; - DWORD dwThreadId; - - hThread = CreateThread(NULL, /* no security attributes */ - 0, /* use default stack size */ - (LPTHREAD_START_ROUTINE)tcpReadThread, /* thread function */ - (void*)sock_fd, /* argument to thread function */ - 0, /* use default creation flags */ - &dwThreadId); /* returns the thread identifier */ -#else - int rc; - pthread_t threadId; - - rc = pthread_create(&threadId, NULL, tcpReadThread, (void*)sock_fd); -#endif -} - -/* *********************************************** */ - -int main(int argc, char* argv[]) { - int opt; - u_int16_t local_port = 0; - n2n_sock_info_t udp_sinfo; - n2n_sock_info_t tcp_sinfo; - -#ifdef WIN32 - initWin32(); -#endif - - optarg = NULL; - while((opt = getopt_long(argc, argv, "l:vh", long_options, NULL)) != EOF) { - switch (opt) { - case 'l': /* local-port */ - local_port = atoi(optarg) & 0xffff; - break; - case 'h': /* help */ - help(); - break; - case 'v': /* verbose */ - traceLevel = 3; - break; - } - } - - if(!(local_port)) - help(); - - udp_sinfo.is_udp_socket=1; - udp_sinfo.sock = open_socket(local_port, 1, 0); - if(udp_sinfo.sock < 0) return(-1); - - tcp_sinfo.is_udp_socket=0; - tcp_sinfo.sock = open_socket(local_port, 0, 1); - if(tcp_sinfo.sock < 0) return(-1); - - traceEvent(TRACE_NORMAL, "Supernode ready: listening on port %hu [TCP/UDP]", local_port); - - while(1) { - int rc, max_sock; - fd_set socket_mask; - struct timeval wait_time; - - FD_ZERO(&socket_mask); - max_sock = max(udp_sinfo.sock, tcp_sinfo.sock); - FD_SET(udp_sinfo.sock, &socket_mask); - FD_SET(tcp_sinfo.sock, &socket_mask); - - wait_time.tv_sec = 10; wait_time.tv_usec = 0; - rc = select(max_sock+1, &socket_mask, NULL, NULL, &wait_time); - - if(rc > 0) { - if(FD_ISSET(udp_sinfo.sock, &socket_mask)) { - char packet[2048]; - size_t len; - struct peer_addr sender; - u_int8_t discarded_pkt; - struct n2n_packet_header hdr; - - len = receive_data( &udp_sinfo, packet, sizeof(packet), &sender, &discarded_pkt, NULL, 0, &hdr); - - if(len <= 0) - traceEvent(TRACE_WARNING, "recvfrom()=%d [%s]\n", len, strerror(errno)); - else { - handle_packet(packet, len, &sender, &udp_sinfo); - } - } else if(FD_ISSET(tcp_sinfo.sock, &socket_mask)) { - struct sockaddr from; - int from_len = sizeof(from); - int new_sock = accept(tcp_sinfo.sock, (struct sockaddr*)&from, - (socklen_t*)&from_len); - - if(new_sock < 0) { - traceEvent(TRACE_WARNING, "TCP connection accept() failed [%s]\n", strerror(errno)); - } else { - startTcpReadThread(new_sock); - } - } - } - - purge_expired_registrations( &known_peers ); - } /* while */ - - closesocket(udp_sinfo.sock); - closesocket(tcp_sinfo.sock); - - return(0); -} diff --git a/n2n_v1/tuntap_freebsd.c b/n2n_v1/tuntap_freebsd.c deleted file mode 100644 index 95308be..0000000 --- a/n2n_v1/tuntap_freebsd.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * (C) 2007-09 - Luca Deri - * - * 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" - -#ifdef __FreeBSD__ - -void tun_close(tuntap_dev *device); - -/* ********************************** */ - -#define N2N_FREEBSD_TAPDEVICE_SIZE 32 -int tuntap_open(tuntap_dev *device /* ignored */, - char *dev, - char *device_ip, - char *device_mask, - const char * device_mac, - int mtu) { - int i; - char tap_device[N2N_FREEBSD_TAPDEVICE_SIZE]; - - for (i = 0; i < 255; i++) { - snprintf(tap_device, sizeof(tap_device), "/dev/tap%d", i); - - device->fd = open(tap_device, O_RDWR); - if(device->fd > 0) { - traceEvent(TRACE_NORMAL, "Succesfully open %s", tap_device); - break; - } - } - - if(device->fd < 0) { - traceEvent(TRACE_ERROR, "Unable to open tap device"); - return(-1); - } else { - char buf[256]; - FILE *fd; - - device->ip_addr = inet_addr(device_ip); - - if ( device_mac ) - { - /* FIXME - This is not tested. Might be wrong syntax for OS X */ - - /* Set the hw address before bringing the if up. */ - snprintf(buf, sizeof(buf), "ifconfig tap%d ether %s", - i, device_mac); - system(buf); - } - - snprintf(buf, sizeof(buf), "ifconfig tap%d %s netmask %s mtu %d up", - i, device_ip, device_mask, mtu); - system(buf); - - traceEvent(TRACE_NORMAL, "Interface tap%d up and running (%s/%s)", - i, device_ip, device_mask); - - /* Read MAC address */ - - snprintf(buf, sizeof(buf), "ifconfig tap%d |grep ether|cut -c 8-24", i); - /* traceEvent(TRACE_INFO, "%s", buf); */ - - fd = popen(buf, "r"); - if(fd < 0) { - tun_close(device); - return(-1); - } else { - int a, b, c, d, e, f; - - buf[0] = 0; - fgets(buf, sizeof(buf), fd); - pclose(fd); - - if(buf[0] == '\0') { - traceEvent(TRACE_ERROR, "Unable to read tap%d interface MAC address"); - exit(0); - } - - traceEvent(TRACE_NORMAL, "Interface tap%d mac %s", i, buf); - if(sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", &a, &b, &c, &d, &e, &f) == 6) { - device->mac_addr[0] = a, device->mac_addr[1] = b; - device->mac_addr[2] = c, device->mac_addr[3] = d; - device->mac_addr[4] = e, device->mac_addr[5] = f; - } - } - } - - - /* read_mac(dev, device->mac_addr); */ - 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); -} - -#endif diff --git a/n2n_v1/tuntap_linux.c b/n2n_v1/tuntap_linux.c deleted file mode 100644 index a1d20fb..0000000 --- a/n2n_v1/tuntap_linux.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * (C) 2007-09 - Luca Deri - * - * 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.h" - -#ifdef __linux__ - -static void read_mac(char *ifname, char *mac_addr) { - int _sock, res; - struct ifreq ifr; - macstr_t mac_addr_buf; - - memset (&ifr,0,sizeof(struct ifreq)); - - /* Dummy socket, just to make ioctls with */ - _sock=socket(PF_INET, SOCK_DGRAM, 0); - strcpy(ifr.ifr_name, ifname); - res = ioctl(_sock,SIOCGIFHWADDR,&ifr); - if (res<0) { - perror ("Get hw addr"); - } else - memcpy(mac_addr, ifr.ifr_ifru.ifru_hwaddr.sa_data, 6); - - traceEvent(TRACE_NORMAL, "Interface %s has MAC %s", - ifname, - macaddr_str(mac_addr, mac_addr_buf, sizeof(mac_addr_buf))); - close(_sock); -} - -/* ********************************** */ - -/** @brief Open and configure the TAP device for packet read/write. - * - * This routine creates the interface via the tuntap driver then uses ifconfig - * to configure address/mask and MTU. - * - * @param device - [inout] a device info holder object - * @param dev - user-defined name for the new iface, - * if NULL system will assign a name - * @param device_ip - address of iface - * @param device_mask - netmask for device_ip - * @param mtu - MTU for device_ip - * - * @return - negative value on error - * - non-negative file-descriptor on success - */ -int tuntap_open(tuntap_dev *device, - char *dev, /* user-definable interface name, eg. edge0 */ - char *device_ip, - char *device_mask, - const char * device_mac, - int mtu) { - char *tuntap_device = "/dev/net/tun"; -#define N2N_LINUX_SYSTEMCMD_SIZE 128 - char buf[N2N_LINUX_SYSTEMCMD_SIZE]; - struct ifreq ifr; - int rc; - - device->fd = open(tuntap_device, O_RDWR); - if(device->fd < 0) { - printf("ERROR: ioctl() [%s][%d]\n", strerror(errno), errno); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_flags = IFF_TAP|IFF_NO_PI; /* Want a TAP device for layer 2 frames. */ - strncpy(ifr.ifr_name, dev, IFNAMSIZ); - rc = ioctl(device->fd, TUNSETIFF, (void *)&ifr); - - if(rc < 0) { - traceEvent(TRACE_ERROR, "ioctl() [%s][%d]\n", strerror(errno), rc); - close(device->fd); - return -1; - } - - if ( device_mac ) - { - /* 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); - } - - 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); - - device->ip_addr = inet_addr(device_ip); - device->device_mask = inet_addr(device_mask); - read_mac(dev, (char*)device->mac_addr); - 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); -} - -#endif /* #ifdef __linux__ */ diff --git a/n2n_v1/tuntap_osx.c b/n2n_v1/tuntap_osx.c deleted file mode 100644 index c0c4c08..0000000 --- a/n2n_v1/tuntap_osx.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * (C) 2007-09 - Luca Deri - * - * 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" - -#ifdef _DARWIN_ - -void tun_close(tuntap_dev *device); - -/* ********************************** */ - -#define N2N_OSX_TAPDEVICE_SIZE 32 -int tuntap_open(tuntap_dev *device /* ignored */, - char *dev, - char *device_ip, - char *device_mask, - const char * device_mac, - int mtu) { - int i; - char tap_device[N2N_OSX_TAPDEVICE_SIZE]; - - for (i = 0; i < 255; i++) { - snprintf(tap_device, sizeof(tap_device), "/dev/tap%d", i); - - device->fd = open(tap_device, O_RDWR); - if(device->fd > 0) { - traceEvent(TRACE_NORMAL, "Succesfully open %s", tap_device); - break; - } - } - - if(device->fd < 0) { - traceEvent(TRACE_ERROR, "Unable to open tap device"); - return(-1); - } else { - char buf[256]; - FILE *fd; - - device->ip_addr = inet_addr(device_ip); - - if ( device_mac ) - { - /* FIXME - This is not tested. Might be wrong syntax for OS X */ - - /* Set the hw address before bringing the if up. */ - snprintf(buf, sizeof(buf), "ifconfig tap%d ether %s", - i, device_mac); - system(buf); - } - - snprintf(buf, sizeof(buf), "ifconfig tap%d %s netmask %s mtu %d up", - i, device_ip, device_mask, mtu); - system(buf); - - traceEvent(TRACE_NORMAL, "Interface tap%d up and running (%s/%s)", - i, device_ip, device_mask); - - /* Read MAC address */ - - snprintf(buf, sizeof(buf), "ifconfig tap%d |grep ether|cut -c 8-24", i); - /* traceEvent(TRACE_INFO, "%s", buf); */ - - fd = popen(buf, "r"); - if(fd < 0) { - tun_close(device); - return(-1); - } else { - int a, b, c, d, e, f; - - buf[0] = 0; - fgets(buf, sizeof(buf), fd); - pclose(fd); - - if(buf[0] == '\0') { - traceEvent(TRACE_ERROR, "Unable to read tap%d interface MAC address"); - exit(0); - } - - traceEvent(TRACE_NORMAL, "Interface tap%d [MTU %d] mac %s", i, mtu, buf); - if(sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", &a, &b, &c, &d, &e, &f) == 6) { - device->mac_addr[0] = a, device->mac_addr[1] = b; - device->mac_addr[2] = c, device->mac_addr[3] = d; - device->mac_addr[4] = e, device->mac_addr[5] = f; - } - } - } - - - /* read_mac(dev, device->mac_addr); */ - 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); -} - -#endif diff --git a/n2n_v1/twofish.c b/n2n_v1/twofish.c deleted file mode 100644 index 73a1a8e..0000000 --- a/n2n_v1/twofish.c +++ /dev/null @@ -1,1031 +0,0 @@ -/* $Id: twofish.c,v 2.0 2002/08/11 22:32:25 fknobbe Exp $ - * - * - * Copyright (C) 1997-2000 The Cryptix Foundation Limited. - * Copyright (C) 2000 Farm9. - * Copyright (C) 2001 Frank Knobbe. - * All rights reserved. - * - * For Cryptix code: - * Use, modification, copying and distribution of this software is subject - * the terms and conditions of the Cryptix General Licence. You should have - * received a copy of the Cryptix General Licence along with this library; - * if not, you can download a copy from http://www.cryptix.org/ . - * - * For Farm9: - * --- jojo@farm9.com, August 2000, converted from Java to C++, added CBC mode and - * ciphertext stealing technique, added AsciiTwofish class for easy encryption - * decryption of text strings - * - * Frank Knobbe : - * --- April 2001, converted from C++ to C, prefixed global variables - * with TwoFish, substituted some defines, changed functions to make use of - * variables supplied in a struct, modified and added routines for modular calls. - * Cleaned up the code so that defines are used instead of fixed 16's and 32's. - * Created two general purpose crypt routines for one block and multiple block - * encryption using Joh's CBC code. - * Added crypt routines that use a header (with a magic and data length). - * (Basically a major rewrite). - * - * Note: Routines labeled _TwoFish are private and should not be used - * (or with extreme caution). - * - */ - -#ifndef __TWOFISH_LIBRARY_SOURCE__ -#define __TWOFISH_LIBRARY_SOURCE__ - -#include -#include -#include -#include -#include -#include "twofish.h" - - -bool TwoFish_srand=TRUE; /* if TRUE, first call of TwoFishInit will seed rand(); */ -/* of TwoFishInit */ - -/* Fixed 8x8 permutation S-boxes */ -static const u_int8_t TwoFish_P[2][256] = - { - { /* p0 */ - 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, - 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, - 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30, - 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, - 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, - 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, - 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45, - 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, - 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, - 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, - 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED, - 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, - 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, - 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, - 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F, - 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, - 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, - 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, - 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, - 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, - 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, - 0x4A, 0x5E, 0xC1, 0xE0 - }, - { /* p1 */ - 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, - 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, - 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B, - 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, - 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, - 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, - 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7, - 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, - 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, - 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, - 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D, - 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, - 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, - 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, - 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E, - 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, - 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, - 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, - 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B, - 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, - 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, - 0x55, 0x09, 0xBE, 0x91 - } - }; - -static bool TwoFish_MDSready=FALSE; -static u_int32_t TwoFish_MDS[4][256]; /* TwoFish_MDS matrix */ - - -#define TwoFish_LFSR1(x) (((x)>>1)^(((x)&0x01)?TwoFish_MDS_GF_FDBK/2:0)) -#define TwoFish_LFSR2(x) (((x)>>2)^(((x)&0x02)?TwoFish_MDS_GF_FDBK/2:0)^(((x)&0x01)?TwoFish_MDS_GF_FDBK/4:0)) - -#define TwoFish_Mx_1(x) ((u_int32_t)(x)) /* force result to dword so << will work */ -#define TwoFish_Mx_X(x) ((u_int32_t)((x)^TwoFish_LFSR2(x))) /* 5B */ -#define TwoFish_Mx_Y(x) ((u_int32_t)((x)^TwoFish_LFSR1(x)^TwoFish_LFSR2(x))) /* EF */ -#define TwoFish_RS_rem(x) { u_int8_t b=(u_int8_t)(x>>24); u_int32_t g2=((b<<1)^((b&0x80)?TwoFish_RS_GF_FDBK:0))&0xFF; u_int32_t g3=((b>>1)&0x7F)^((b&1)?TwoFish_RS_GF_FDBK>>1:0)^g2; x=(x<<8)^(g3<<24)^(g2<<16)^(g3<<8)^b; } - -/*#define TwoFish__b(x,N) (((u_int8_t *)&x)[((N)&3)^TwoFish_ADDR_XOR])*/ /* pick bytes out of a dword */ - -#define TwoFish_b0(x) TwoFish__b(x,0) /* extract LSB of u_int32_t */ -#define TwoFish_b1(x) TwoFish__b(x,1) -#define TwoFish_b2(x) TwoFish__b(x,2) -#define TwoFish_b3(x) TwoFish__b(x,3) /* extract MSB of u_int32_t */ - -u_int8_t TwoFish__b(u_int32_t x,int n) -{ n&=3; - while(n-->0) - x>>=8; - return (u_int8_t)x; -} - - -/* TwoFish Initialization - * - * This routine generates a global data structure for use with TwoFish, - * initializes important values (such as subkeys, sBoxes), generates subkeys - * and precomputes the MDS matrix if not already done. - * - * Input: User supplied password (will be appended by default password of 'SnortHas2FishEncryptionRoutines!') - * - * Output: Pointer to TWOFISH structure. This data structure contains key dependent data. - * This pointer is used with all other crypt functions. - */ - -TWOFISH *TwoFishInit(const u_int8_t *userkey, u_int32_t keysize) -{ TWOFISH *tfdata; - int i,x,m; - u_int8_t tkey[TwoFish_KEY_LENGTH+40]; - - memset( tkey, 0, TwoFish_KEY_LENGTH+40 ); - tfdata=(TWOFISH *)malloc(sizeof(TWOFISH)); /* allocate the TwoFish structure */ - if(tfdata!=NULL) - { - - /* Changes here prevented a dangerous random key segment for keys of length < TwoFish_KEY_LENGTH */ - if(keysize > 0) - { - memcpy( tkey, userkey, keysize ); /* The rest will be zeros */ - } - else - { - memcpy( tkey, TwoFish_DEFAULT_PW, TwoFish_DEFAULT_PW_LEN ); /* if no key defined, use default password */ - } - - /* This loop is awful - surely a loop on memcpy() would be clearer and more efficient */ - for(i=0,x=0,m=keysize;ikey[i]=tkey[x++]; /* fill the whole keyspace with repeating key. */ - if(x==m) - x=0; - } - - if(!TwoFish_MDSready) - _TwoFish_PrecomputeMDSmatrix(); /* "Wake Up, Neo" */ - _TwoFish_MakeSubKeys(tfdata); /* generate subkeys */ - _TwoFish_ResetCBC(tfdata); /* reset the CBC */ - tfdata->output=NULL; /* nothing to output yet */ - tfdata->dontflush=FALSE; /* reset decrypt skip block flag */ - if(TwoFish_srand) - { - TwoFish_srand=FALSE; - /* REVISIT: BbMaj7 : Should choose something with less predictability - * particularly for embedded targets with no real-time clock. */ - srand((unsigned int)time(NULL)); - } - } - return tfdata; /* return the data pointer */ -} - - -void TwoFishDestroy(TWOFISH *tfdata) -{ if(tfdata!=NULL) - free(tfdata); -} - - -/* en/decryption with CBC mode */ -u_int32_t _TwoFish_CryptRawCBC(u_int8_t *in,u_int8_t *out,u_int32_t len,bool decrypt,TWOFISH *tfdata) -{ u_int32_t rl; - - rl=len; /* remember how much data to crypt. */ - while(len>TwoFish_BLOCK_SIZE) /* and now we process block by block. */ - { _TwoFish_BlockCrypt(in,out,TwoFish_BLOCK_SIZE,decrypt,tfdata); /* de/encrypt it. */ - in+=TwoFish_BLOCK_SIZE; /* adjust pointers. */ - out+=TwoFish_BLOCK_SIZE; - len-=TwoFish_BLOCK_SIZE; - } - if(len>0) /* if we have less than a block left... */ - _TwoFish_BlockCrypt(in,out,len,decrypt,tfdata); /* ...then we de/encrypt that too. */ - if(tfdata->qBlockDefined && !tfdata->dontflush) /* in case len was exactly one block... */ - _TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata); /* ...we need to write the... */ - /* ...remaining bytes of the buffer */ - return rl; -} - -/* en/decryption on one block only */ -u_int32_t _TwoFish_CryptRaw16(u_int8_t *in,u_int8_t *out,u_int32_t len,bool decrypt,TWOFISH *tfdata) -{ /* qBlockPlain already zero'ed through ResetCBC */ - memcpy(tfdata->qBlockPlain,in,len); /* toss the data into it. */ - _TwoFish_BlockCrypt16(tfdata->qBlockPlain,tfdata->qBlockCrypt,decrypt,tfdata); /* encrypt just that block without CBC. */ - memcpy(out,tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE); /* and return what we got */ - return TwoFish_BLOCK_SIZE; -} - -/* en/decryption without reset of CBC and output assignment */ -u_int32_t _TwoFish_CryptRaw(u_int8_t *in,u_int8_t *out,u_int32_t len,bool decrypt,TWOFISH *tfdata) -{ - if(in!=NULL && out!=NULL && len>0 && tfdata!=NULL) /* if we have valid data, then... */ - { if(len>TwoFish_BLOCK_SIZE) /* ...check if we have more than one block. */ - return _TwoFish_CryptRawCBC(in,out,len,decrypt,tfdata); /* if so, use the CBC routines... */ - else - return _TwoFish_CryptRaw16(in,out,len,decrypt,tfdata); /* ...otherwise just do one block. */ - } - return 0; -} - - -/* TwoFish Raw Encryption - * - * Does not use header, but does use CBC (if more than one block has to be encrypted). - * - * Input: Pointer to the buffer of the plaintext to be encrypted. - * Pointer to the buffer receiving the ciphertext. - * The length of the plaintext buffer. - * The TwoFish structure. - * - * Output: The amount of bytes encrypted if successful, otherwise 0. - */ - -u_int32_t TwoFishEncryptRaw(u_int8_t *in, - u_int8_t *out, - u_int32_t len, - TWOFISH *tfdata) -{ _TwoFish_ResetCBC(tfdata); /* reset CBC flag. */ - tfdata->output=out; /* output straight into output buffer. */ - return _TwoFish_CryptRaw(in,out,len,FALSE,tfdata); /* and go for it. */ -} - -/* TwoFish Raw Decryption - * - * Does not use header, but does use CBC (if more than one block has to be decrypted). - * - * Input: Pointer to the buffer of the ciphertext to be decrypted. - * Pointer to the buffer receiving the plaintext. - * The length of the ciphertext buffer (at least one cipher block). - * The TwoFish structure. - * - * Output: The amount of bytes decrypted if successful, otherwise 0. - */ - -u_int32_t TwoFishDecryptRaw(u_int8_t *in, - u_int8_t *out, - u_int32_t len, - TWOFISH *tfdata) -{ _TwoFish_ResetCBC(tfdata); /* reset CBC flag. */ - tfdata->output=out; /* output straight into output buffer. */ - return _TwoFish_CryptRaw(in,out,len,TRUE,tfdata); /* and go for it. */ -} - -/* TwoFish Free - * - * Free's the allocated buffer. - * - * Input: Pointer to the TwoFish structure - * - * Output: (none) - */ - -void TwoFishFree(TWOFISH *tfdata) -{ if(tfdata->output!=NULL) /* if a valid buffer is present... */ - { free(tfdata->output); /* ...then we free it for you... */ - tfdata->output=NULL; /* ...and mark as such. */ - } -} - -/* TwoFish Set Output - * - * If you want to allocate the output buffer yourself, - * then you can set it with this function. - * - * Input: Pointer to your output buffer - * Pointer to the TwoFish structure - * - * Output: (none) - */ - -void TwoFishSetOutput(u_int8_t *outp,TWOFISH *tfdata) -{ tfdata->output=outp; /* (do we really need a function for this?) */ -} - -/* TwoFish Alloc - * - * Allocates enough memory for the output buffer that would be required - * - * Input: Length of the plaintext. - * Boolean flag for BinHex Output. - * Pointer to the TwoFish structure. - * - * Output: Returns a pointer to the memory allocated. - */ - -void *TwoFishAlloc(u_int32_t len,bool binhex,bool decrypt,TWOFISH *tfdata) -{ - /* TwoFishFree(tfdata); */ /* (don't for now) discard whatever was allocated earlier. */ - if(decrypt) /* if decrypting... */ - { if(binhex) /* ...and input is binhex encoded... */ - len/=2; /* ...use half as much for output. */ - len-=TwoFish_BLOCK_SIZE; /* Also, subtract the size of the header. */ - } - else - { len+=TwoFish_BLOCK_SIZE; /* the size is just increased by the header... */ - if(binhex) - len*=2; /* ...and doubled if output is to be binhexed. */ - } - tfdata->output=malloc(len+TwoFish_BLOCK_SIZE);/* grab some memory...plus some extra (it's running over somewhere, crashes without extra padding) */ - - return tfdata->output; /* ...and return to caller. */ -} - -/* bin2hex and hex2bin conversion */ -void _TwoFish_BinHex(u_int8_t *buf,u_int32_t len,bool bintohex) -{ u_int8_t *pi,*po,c; - - if(bintohex) - { for(pi=buf+len-1,po=buf+(2*len)-1;len>0;pi--,po--,len--) /* let's start from the end of the bin block. */ - { c=*pi; /* grab value. */ - c&=15; /* use lower 4 bits. */ - if(c>9) /* convert to ascii. */ - c+=('a'-10); - else - c+='0'; - *po--=c; /* set the lower nibble. */ - c=*pi; /* grab value again. */ - c>>=4; /* right shift 4 bits. */ - c&=15; /* make sure we only have 4 bits. */ - if(c>9) /* convert to ascii. */ - c+=('a'-10); - else - c+='0'; - *po=c; /* set the higher nibble. */ - } /* and keep going. */ - } - else - { for(pi=buf,po=buf;len>0;pi++,po++,len-=2) /* let's start from the beginning of the hex block. */ - { c=tolower(*pi++)-'0'; /* grab higher nibble. */ - if(c>9) /* convert to value. */ - c-=('0'-9); - *po=c<<4; /* left shit 4 bits. */ - c=tolower(*pi)-'0'; /* grab lower nibble. */ - if(c>9) /* convert to value. */ - c-=('0'-9); - *po|=c; /* and add to value. */ - } - } -} - - -/* TwoFish Encryption - * - * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc, - * this routine will alloc the memory. In addition, it will include a small 'header' - * containing the magic and some salt. That way the decrypt routine can check if the - * packet got decrypted successfully, and return 0 instead of garbage. - * - * Input: Pointer to the buffer of the plaintext to be encrypted. - * Pointer to the pointer to the buffer receiving the ciphertext. - * The pointer either points to user allocated output buffer space, or to NULL, in which case - * this routine will set the pointer to the buffer allocated through the struct. - * The length of the plaintext buffer. - * Can be -1 if the input is a null terminated string, in which case we'll count for you. - * Boolean flag for BinHex Output (if used, output will be twice as large as input). - * Note: BinHex conversion overwrites (converts) input buffer! - * The TwoFish structure. - * - * Output: The amount of bytes encrypted if successful, otherwise 0. - */ - -u_int32_t TwoFishEncrypt(u_int8_t *in, - u_int8_t **out, - signed long len, - bool binhex, - TWOFISH *tfdata) -{ u_int32_t ilen,olen; - - -#if 0 -/* This is so broken it doesn't deserve to live. */ - if(len== -1) /* if we got -1 for len, we'll assume IN is a... */ - ilen=strlen(in); /* ...\0 terminated string and figure len out ourselves... */ - else - ilen=len; /* ...otherwise we trust you supply a correct length. */ -#endif - - ilen = len; - - if(in!=NULL && out!=NULL && ilen>0 && tfdata!=NULL) /* if we got usable stuff, we'll do it. */ - { if(*out==NULL) /* if OUT points to a NULL pointer... */ - *out=TwoFishAlloc(ilen,binhex,FALSE,tfdata); /* ...we'll (re-)allocate buffer space. */ - if(*out!=NULL) - { tfdata->output=*out; /* set output buffer. */ - tfdata->header.salt=rand()*65536+rand(); /* toss in some salt. */ - tfdata->header.length[0]= (u_int8_t)(ilen); - tfdata->header.length[1]= (u_int8_t)(ilen>>8); - tfdata->header.length[2]= (u_int8_t)(ilen>>16); - tfdata->header.length[3]= (u_int8_t)(ilen>>24); - memcpy(tfdata->header.magic,TwoFish_MAGIC,TwoFish_MAGIC_LEN); /* set the magic. */ - olen=TwoFish_BLOCK_SIZE; /* set output counter. */ - _TwoFish_ResetCBC(tfdata); /* reset the CBC flag */ - _TwoFish_BlockCrypt((u_int8_t *)&(tfdata->header),*out,olen,FALSE,tfdata); /* encrypt first block (without flush on 16 byte boundary). */ - olen+=_TwoFish_CryptRawCBC(in,*out+TwoFish_BLOCK_SIZE,ilen,FALSE,tfdata); /* and encrypt the rest (we do not reset the CBC flag). */ - if(binhex) /* if binhex... */ - { _TwoFish_BinHex(*out,olen,TRUE); /* ...convert output to binhex... */ - olen*=2; /* ...and size twice as large. */ - } - tfdata->output=*out; - return olen; - } - } - return 0; -} - -/* TwoFish Decryption - * - * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc, - * this routine will alloc the memory. In addition, it will check the small 'header' - * containing the magic. If magic does not match we return 0. Otherwise we return the - * amount of bytes decrypted (should be the same as the length in the header). - * - * Input: Pointer to the buffer of the ciphertext to be decrypted. - * Pointer to the pointer to the buffer receiving the plaintext. - * The pointer either points to user allocated output buffer space, or to NULL, in which case - * this routine will set the pointer to the buffer allocated through the struct. - * The length of the ciphertext buffer. - * Can be -1 if the input is a null terminated binhex string, in which case we'll count for you. - * Boolean flag for BinHex Input (if used, plaintext will be half as large as input). - * Note: BinHex conversion overwrites (converts) input buffer! - * The TwoFish structure. - * - * Output: The amount of bytes decrypted if successful, otherwise 0. - */ - -u_int32_t TwoFishDecrypt(u_int8_t *in, - u_int8_t **out, - signed long len, - bool binhex, - TWOFISH *tfdata) -{ u_int32_t ilen,elen,olen; - const u_int8_t cmagic[TwoFish_MAGIC_LEN]=TwoFish_MAGIC; - u_int8_t *tbuf; - - - -#if 0 -/* This is so broken it doesn't deserve to live. */ - if(len== -1) /* if we got -1 for len, we'll assume IN is a... */ - ilen=strlen(in); /* ...\0 terminated string and figure len out ourselves... */ - else - ilen=len; /* ...otherwise we trust you supply a correct length. */ -#endif - - ilen = len; - - if(in!=NULL && out!=NULL && ilen>0 && tfdata!=NULL) /* if we got usable stuff, we'll do it. */ - { if(*out==NULL) /* if OUT points to a NULL pointer... */ - *out=TwoFishAlloc(ilen,binhex,TRUE,tfdata); /* ...we'll (re-)allocate buffer space. */ - if(*out!=NULL) - { if(binhex) /* if binhex... */ - { _TwoFish_BinHex(in,ilen,FALSE); /* ...convert input to values... */ - ilen/=2; /* ...and size half as much. */ - } - _TwoFish_ResetCBC(tfdata); /* reset the CBC flag. */ - - tbuf=(u_int8_t *)malloc(ilen+TwoFish_BLOCK_SIZE); /* get memory for data and header. */ - if(tbuf==NULL) - return 0; - tfdata->output=tbuf; /* set output to temp buffer. */ - - olen=_TwoFish_CryptRawCBC(in,tbuf,ilen,TRUE,tfdata)-TwoFish_BLOCK_SIZE; /* decrypt the whole thing. */ - memcpy(&(tfdata->header),tbuf,TwoFish_BLOCK_SIZE); /* copy first block into header. */ - tfdata->output=*out; - for(elen=0;elenheader.magic[elen]!=cmagic[elen]) - break; - if(elen==TwoFish_MAGIC_LEN) /* if magic matches then... */ - { elen=(tfdata->header.length[0]) | - (tfdata->header.length[1])<<8 | - (tfdata->header.length[2])<<16 | - (tfdata->header.length[3])<<24; /* .. we know how much to expect. */ - if(elen>olen) /* adjust if necessary. */ - elen=olen; - memcpy(*out,tbuf+TwoFish_BLOCK_SIZE,elen); /* copy data into intended output. */ - free(tbuf); - return elen; - } - free(tbuf); - } - } - return 0; -} - -void _TwoFish_PrecomputeMDSmatrix(void) /* precompute the TwoFish_MDS matrix */ -{ u_int32_t m1[2]; - u_int32_t mX[2]; - u_int32_t mY[2]; - u_int32_t i, j; - - for (i = 0; i < 256; i++) - { j = TwoFish_P[0][i] & 0xFF; /* compute all the matrix elements */ - m1[0] = j; - mX[0] = TwoFish_Mx_X( j ) & 0xFF; - mY[0] = TwoFish_Mx_Y( j ) & 0xFF; - - j = TwoFish_P[1][i] & 0xFF; - m1[1] = j; - mX[1] = TwoFish_Mx_X( j ) & 0xFF; - mY[1] = TwoFish_Mx_Y( j ) & 0xFF; - - TwoFish_MDS[0][i] = m1[TwoFish_P_00] | /* fill matrix w/ above elements */ - mX[TwoFish_P_00] << 8 | - mY[TwoFish_P_00] << 16 | - mY[TwoFish_P_00] << 24; - TwoFish_MDS[1][i] = mY[TwoFish_P_10] | - mY[TwoFish_P_10] << 8 | - mX[TwoFish_P_10] << 16 | - m1[TwoFish_P_10] << 24; - TwoFish_MDS[2][i] = mX[TwoFish_P_20] | - mY[TwoFish_P_20] << 8 | - m1[TwoFish_P_20] << 16 | - mY[TwoFish_P_20] << 24; - TwoFish_MDS[3][i] = mX[TwoFish_P_30] | - m1[TwoFish_P_30] << 8 | - mY[TwoFish_P_30] << 16 | - mX[TwoFish_P_30] << 24; - } - TwoFish_MDSready=TRUE; -} - - -void _TwoFish_MakeSubKeys(TWOFISH *tfdata) /* Expand a user-supplied key material into a session key. */ -{ u_int32_t k64Cnt = TwoFish_KEY_LENGTH / 8; - u_int32_t k32e[4]; /* even 32-bit entities */ - u_int32_t k32o[4]; /* odd 32-bit entities */ - u_int32_t sBoxKey[4]; - u_int32_t offset,i,j; - u_int32_t A, B, q=0; - u_int32_t k0,k1,k2,k3; - u_int32_t b0,b1,b2,b3; - - /* split user key material into even and odd 32-bit entities and */ - /* compute S-box keys using (12, 8) Reed-Solomon code over GF(256) */ - - - for (offset=0,i=0,j=k64Cnt-1;i<4 && offsetkey[offset++]; - k32e[i]|= tfdata->key[offset++]<<8; - k32e[i]|= tfdata->key[offset++]<<16; - k32e[i]|= tfdata->key[offset++]<<24; - k32o[i] = tfdata->key[offset++]; - k32o[i]|= tfdata->key[offset++]<<8; - k32o[i]|= tfdata->key[offset++]<<16; - k32o[i]|= tfdata->key[offset++]<<24; - sBoxKey[j] = _TwoFish_RS_MDS_Encode( k32e[i], k32o[i] ); /* reverse order */ - } - - /* compute the round decryption subkeys for PHT. these same subkeys */ - /* will be used in encryption but will be applied in reverse order. */ - i=0; - while(i < TwoFish_TOTAL_SUBKEYS) - { A = _TwoFish_F32( k64Cnt, q, k32e ); /* A uses even key entities */ - q += TwoFish_SK_BUMP; - - B = _TwoFish_F32( k64Cnt, q, k32o ); /* B uses odd key entities */ - q += TwoFish_SK_BUMP; - - B = B << 8 | B >> 24; - - A += B; - tfdata->subKeys[i++] = A; /* combine with a PHT */ - - A += B; - tfdata->subKeys[i++] = A << TwoFish_SK_ROTL | A >> (32-TwoFish_SK_ROTL); - } - - /* fully expand the table for speed */ - k0 = sBoxKey[0]; - k1 = sBoxKey[1]; - k2 = sBoxKey[2]; - k3 = sBoxKey[3]; - - for (i = 0; i < 256; i++) - { b0 = b1 = b2 = b3 = i; - switch (k64Cnt & 3) - { case 1: /* 64-bit keys */ - tfdata->sBox[ 2*i ] = TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][b0]) ^ TwoFish_b0(k0)]; - tfdata->sBox[ 2*i+1] = TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][b1]) ^ TwoFish_b1(k0)]; - tfdata->sBox[0x200+2*i ] = TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][b2]) ^ TwoFish_b2(k0)]; - tfdata->sBox[0x200+2*i+1] = TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][b3]) ^ TwoFish_b3(k0)]; - break; - case 0: /* 256-bit keys (same as 4) */ - b0 = (TwoFish_P[TwoFish_P_04][b0]) ^ TwoFish_b0(k3); - b1 = (TwoFish_P[TwoFish_P_14][b1]) ^ TwoFish_b1(k3); - b2 = (TwoFish_P[TwoFish_P_24][b2]) ^ TwoFish_b2(k3); - b3 = (TwoFish_P[TwoFish_P_34][b3]) ^ TwoFish_b3(k3); - case 3: /* 192-bit keys */ - b0 = (TwoFish_P[TwoFish_P_03][b0]) ^ TwoFish_b0(k2); - b1 = (TwoFish_P[TwoFish_P_13][b1]) ^ TwoFish_b1(k2); - b2 = (TwoFish_P[TwoFish_P_23][b2]) ^ TwoFish_b2(k2); - b3 = (TwoFish_P[TwoFish_P_33][b3]) ^ TwoFish_b3(k2); - case 2: /* 128-bit keys */ - tfdata->sBox[ 2*i ]= - TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][(TwoFish_P[TwoFish_P_02][b0]) ^ - TwoFish_b0(k1)]) ^ TwoFish_b0(k0)]; - - tfdata->sBox[ 2*i+1]= - TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][(TwoFish_P[TwoFish_P_12][b1]) ^ - TwoFish_b1(k1)]) ^ TwoFish_b1(k0)]; - - tfdata->sBox[0x200+2*i ]= - TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][(TwoFish_P[TwoFish_P_22][b2]) ^ - TwoFish_b2(k1)]) ^ TwoFish_b2(k0)]; - - tfdata->sBox[0x200+2*i+1]= - TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][(TwoFish_P[TwoFish_P_32][b3]) ^ - TwoFish_b3(k1)]) ^ TwoFish_b3(k0)]; - } - } -} - - -/** - * Encrypt or decrypt exactly one block of plaintext in CBC mode. - * Use "ciphertext stealing" technique described on pg. 196 - * of "Applied Cryptography" to encrypt the final partial - * (i.e. <16 byte) block if necessary. - * - * jojo: the "ciphertext stealing" requires we read ahead and have - * special handling for the last two blocks. Because of this, the - * output from the TwoFish algorithm is handled internally here. - * It would be better to have a higher level handle this as well as - * CBC mode. Unfortunately, I've mixed the two together, which is - * pretty crappy... The Java version separates these out correctly. - * - * fknobbe: I have reduced the CBC mode to work on memory buffer only. - * Higher routines should use an intermediate buffer and handle - * their output seperately (mainly so the data can be flushed - * in one chunk, not seperate 16 byte blocks...) - * - * @param in The plaintext. - * @param out The ciphertext - * @param size how much to encrypt - * @param tfdata: Pointer to the global data structure containing session keys. - * @return none - */ -void _TwoFish_BlockCrypt(u_int8_t *in,u_int8_t *out,u_int32_t size,int decrypt,TWOFISH *tfdata) -{ u_int8_t PnMinusOne[TwoFish_BLOCK_SIZE]; - u_int8_t CnMinusOne[TwoFish_BLOCK_SIZE]; - u_int8_t CBCplusCprime[TwoFish_BLOCK_SIZE]; - u_int8_t Pn[TwoFish_BLOCK_SIZE]; - u_int8_t *p,*pout; - u_int32_t i; - - /* here is where we implement CBC mode and cipher block stealing */ - if(size==TwoFish_BLOCK_SIZE) - { /* if we are encrypting, CBC means we XOR the plain text block with the */ - /* previous cipher text block before encrypting */ - if(!decrypt && tfdata->qBlockDefined) - { for(p=in,i=0;iqBlockCrypt[i]; /* FK: I'm copying the xor'ed input into Pn... */ - } - else - memcpy(Pn,in,TwoFish_BLOCK_SIZE); /* FK: same here. we work of Pn all the time. */ - - /* TwoFish block level encryption or decryption */ - _TwoFish_BlockCrypt16(Pn,out,decrypt,tfdata); - - /* if we are decrypting, CBC means we XOR the result of the decryption */ - /* with the previous cipher text block to get the resulting plain text */ - if(decrypt && tfdata->qBlockDefined) - { for (p=out,i=0;iqBlockPlain[i]; - } - - /* save the input and output blocks, since CBC needs these for XOR */ - /* operations */ - _TwoFish_qBlockPush(Pn,out,tfdata); - } - else - { /* cipher block stealing, we are at Pn, */ - /* but since Cn-1 must now be replaced with CnC' */ - /* we pop it off, and recalculate Cn-1 */ - - if(decrypt) - { /* We are on an odd block, and had to do cipher block stealing, */ - /* so the PnMinusOne has to be derived differently. */ - - /* First we decrypt it into CBC and C' */ - _TwoFish_qBlockPop(CnMinusOne,PnMinusOne,tfdata); - _TwoFish_BlockCrypt16(CnMinusOne,CBCplusCprime,decrypt,tfdata); - - /* we then xor the first few bytes with the "in" bytes (Cn) */ - /* to recover Pn, which we put in out */ - for(p=in,pout=out,i=0;iprevCipher[i]; - - /* So at this point, out has PnMinusOne */ - _TwoFish_qBlockPush(CnMinusOne,PnMinusOne,tfdata); - _TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata); - _TwoFish_FlushOutput(out,size,tfdata); - } - else - { _TwoFish_qBlockPop(PnMinusOne,CnMinusOne,tfdata); - memset(Pn,0,TwoFish_BLOCK_SIZE); - memcpy(Pn,in,size); - for(i=0;iqBlockCrypt,TwoFish_BLOCK_SIZE,tfdata); - _TwoFish_FlushOutput(CnMinusOne,size,tfdata); /* old Cn-1 becomes new partial Cn */ - } - tfdata->qBlockDefined=FALSE; - } -} - -void _TwoFish_qBlockPush(u_int8_t *p,u_int8_t *c,TWOFISH *tfdata) -{ if(tfdata->qBlockDefined) - _TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata); - memcpy(tfdata->prevCipher,tfdata->qBlockPlain,TwoFish_BLOCK_SIZE); - memcpy(tfdata->qBlockPlain,p,TwoFish_BLOCK_SIZE); - memcpy(tfdata->qBlockCrypt,c,TwoFish_BLOCK_SIZE); - tfdata->qBlockDefined=TRUE; -} - -void _TwoFish_qBlockPop(u_int8_t *p,u_int8_t *c,TWOFISH *tfdata) -{ memcpy(p,tfdata->qBlockPlain,TwoFish_BLOCK_SIZE ); - memcpy(c,tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE ); - tfdata->qBlockDefined=FALSE; -} - -/* Reset's the CBC flag and zero's PrevCipher (through qBlockPlain) (important) */ -void _TwoFish_ResetCBC(TWOFISH *tfdata) -{ tfdata->qBlockDefined=FALSE; - memset(tfdata->qBlockPlain,0,TwoFish_BLOCK_SIZE); -} - -void _TwoFish_FlushOutput(u_int8_t *b,u_int32_t len,TWOFISH *tfdata) -{ u_int32_t i; - - for(i=0;idontflush;i++) - *tfdata->output++ = *b++; - tfdata->dontflush=FALSE; -} - -void _TwoFish_BlockCrypt16(u_int8_t *in,u_int8_t *out,bool decrypt,TWOFISH *tfdata) -{ u_int32_t x0,x1,x2,x3; - u_int32_t k,t0,t1,R; - - - x0=*in++; - x0|=(*in++ << 8 ); - x0|=(*in++ << 16); - x0|=(*in++ << 24); - x1=*in++; - x1|=(*in++ << 8 ); - x1|=(*in++ << 16); - x1|=(*in++ << 24); - x2=*in++; - x2|=(*in++ << 8 ); - x2|=(*in++ << 16); - x2|=(*in++ << 24); - x3=*in++; - x3|=(*in++ << 8 ); - x3|=(*in++ << 16); - x3|=(*in++ << 24); - - if(decrypt) - { x0 ^= tfdata->subKeys[4]; /* swap input and output whitening keys when decrypting */ - x1 ^= tfdata->subKeys[5]; - x2 ^= tfdata->subKeys[6]; - x3 ^= tfdata->subKeys[7]; - - k = 7+(TwoFish_ROUNDS*2); - for (R = 0; R < TwoFish_ROUNDS; R += 2) - { t0 = _TwoFish_Fe320( tfdata->sBox, x0); - t1 = _TwoFish_Fe323( tfdata->sBox, x1); - x3 ^= t0 + (t1<<1) + tfdata->subKeys[k--]; - x3 = x3 >> 1 | x3 << 31; - x2 = x2 << 1 | x2 >> 31; - x2 ^= t0 + t1 + tfdata->subKeys[k--]; - - t0 = _TwoFish_Fe320( tfdata->sBox, x2); - t1 = _TwoFish_Fe323( tfdata->sBox, x3); - x1 ^= t0 + (t1<<1) + tfdata->subKeys[k--]; - x1 = x1 >> 1 | x1 << 31; - x0 = x0 << 1 | x0 >> 31; - x0 ^= t0 + t1 + tfdata->subKeys[k--]; - } - - x2 ^= tfdata->subKeys[0]; - x3 ^= tfdata->subKeys[1]; - x0 ^= tfdata->subKeys[2]; - x1 ^= tfdata->subKeys[3]; - } - else - { x0 ^= tfdata->subKeys[0]; - x1 ^= tfdata->subKeys[1]; - x2 ^= tfdata->subKeys[2]; - x3 ^= tfdata->subKeys[3]; - - k = 8; - for (R = 0; R < TwoFish_ROUNDS; R += 2) - { t0 = _TwoFish_Fe320( tfdata->sBox, x0); - t1 = _TwoFish_Fe323( tfdata->sBox, x1); - x2 ^= t0 + t1 + tfdata->subKeys[k++]; - x2 = x2 >> 1 | x2 << 31; - x3 = x3 << 1 | x3 >> 31; - x3 ^= t0 + (t1<<1) + tfdata->subKeys[k++]; - - t0 = _TwoFish_Fe320( tfdata->sBox, x2); - t1 = _TwoFish_Fe323( tfdata->sBox, x3); - x0 ^= t0 + t1 + tfdata->subKeys[k++]; - x0 = x0 >> 1 | x0 << 31; - x1 = x1 << 1 | x1 >> 31; - x1 ^= t0 + (t1<<1) + tfdata->subKeys[k++]; - } - - x2 ^= tfdata->subKeys[4]; - x3 ^= tfdata->subKeys[5]; - x0 ^= tfdata->subKeys[6]; - x1 ^= tfdata->subKeys[7]; - } - - *out++ = (u_int8_t)(x2 ); - *out++ = (u_int8_t)(x2 >> 8); - *out++ = (u_int8_t)(x2 >> 16); - *out++ = (u_int8_t)(x2 >> 24); - - *out++ = (u_int8_t)(x3 ); - *out++ = (u_int8_t)(x3 >> 8); - *out++ = (u_int8_t)(x3 >> 16); - *out++ = (u_int8_t)(x3 >> 24); - - *out++ = (u_int8_t)(x0 ); - *out++ = (u_int8_t)(x0 >> 8); - *out++ = (u_int8_t)(x0 >> 16); - *out++ = (u_int8_t)(x0 >> 24); - - *out++ = (u_int8_t)(x1 ); - *out++ = (u_int8_t)(x1 >> 8); - *out++ = (u_int8_t)(x1 >> 16); - *out++ = (u_int8_t)(x1 >> 24); -} - -/** - * Use (12, 8) Reed-Solomon code over GF(256) to produce a key S-box - * 32-bit entity from two key material 32-bit entities. - * - * @param k0 1st 32-bit entity. - * @param k1 2nd 32-bit entity. - * @return Remainder polynomial generated using RS code - */ -u_int32_t _TwoFish_RS_MDS_Encode(u_int32_t k0,u_int32_t k1) -{ u_int32_t i,r; - - for(r=k1,i=0;i<4;i++) /* shift 1 byte at a time */ - TwoFish_RS_rem(r); - r ^= k0; - for(i=0;i<4;i++) - TwoFish_RS_rem(r); - - return r; -} - -u_int32_t _TwoFish_F32(u_int32_t k64Cnt,u_int32_t x,u_int32_t *k32) -{ u_int8_t b0,b1,b2,b3; - u_int32_t k0,k1,k2,k3,result = 0; - - b0=TwoFish_b0(x); - b1=TwoFish_b1(x); - b2=TwoFish_b2(x); - b3=TwoFish_b3(x); - k0=k32[0]; - k1=k32[1]; - k2=k32[2]; - k3=k32[3]; - - switch (k64Cnt & 3) - { case 1: /* 64-bit keys */ - result = - TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][b0] & 0xFF) ^ TwoFish_b0(k0)] ^ - TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][b1] & 0xFF) ^ TwoFish_b1(k0)] ^ - TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][b2] & 0xFF) ^ TwoFish_b2(k0)] ^ - TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][b3] & 0xFF) ^ TwoFish_b3(k0)]; - break; - case 0: /* 256-bit keys (same as 4) */ - b0 = (TwoFish_P[TwoFish_P_04][b0] & 0xFF) ^ TwoFish_b0(k3); - b1 = (TwoFish_P[TwoFish_P_14][b1] & 0xFF) ^ TwoFish_b1(k3); - b2 = (TwoFish_P[TwoFish_P_24][b2] & 0xFF) ^ TwoFish_b2(k3); - b3 = (TwoFish_P[TwoFish_P_34][b3] & 0xFF) ^ TwoFish_b3(k3); - - case 3: /* 192-bit keys */ - b0 = (TwoFish_P[TwoFish_P_03][b0] & 0xFF) ^ TwoFish_b0(k2); - b1 = (TwoFish_P[TwoFish_P_13][b1] & 0xFF) ^ TwoFish_b1(k2); - b2 = (TwoFish_P[TwoFish_P_23][b2] & 0xFF) ^ TwoFish_b2(k2); - b3 = (TwoFish_P[TwoFish_P_33][b3] & 0xFF) ^ TwoFish_b3(k2); - case 2: /* 128-bit keys (optimize for this case) */ - result = - TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][(TwoFish_P[TwoFish_P_02][b0] & 0xFF) ^ TwoFish_b0(k1)] & 0xFF) ^ TwoFish_b0(k0)] ^ - TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][(TwoFish_P[TwoFish_P_12][b1] & 0xFF) ^ TwoFish_b1(k1)] & 0xFF) ^ TwoFish_b1(k0)] ^ - TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][(TwoFish_P[TwoFish_P_22][b2] & 0xFF) ^ TwoFish_b2(k1)] & 0xFF) ^ TwoFish_b2(k0)] ^ - TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][(TwoFish_P[TwoFish_P_32][b3] & 0xFF) ^ TwoFish_b3(k1)] & 0xFF) ^ TwoFish_b3(k0)]; - break; - } - return result; -} - -u_int32_t _TwoFish_Fe320(u_int32_t *lsBox,u_int32_t x) -{ return lsBox[ TwoFish_b0(x)<<1 ]^ - lsBox[ ((TwoFish_b1(x)<<1)|1)]^ - lsBox[0x200+ (TwoFish_b2(x)<<1) ]^ - lsBox[0x200+((TwoFish_b3(x)<<1)|1)]; -} - -u_int32_t _TwoFish_Fe323(u_int32_t *lsBox,u_int32_t x) -{ return lsBox[ (TwoFish_b3(x)<<1) ]^ - lsBox[ ((TwoFish_b0(x)<<1)|1)]^ - lsBox[0x200+ (TwoFish_b1(x)<<1) ]^ - lsBox[0x200+((TwoFish_b2(x)<<1)|1)]; -} - -u_int32_t _TwoFish_Fe32(u_int32_t *lsBox,u_int32_t x,u_int32_t R) -{ return lsBox[ 2*TwoFish__b(x,R ) ]^ - lsBox[ 2*TwoFish__b(x,R+1)+1]^ - lsBox[0x200+2*TwoFish__b(x,R+2) ]^ - lsBox[0x200+2*TwoFish__b(x,R+3)+1]; -} - - -#endif - -/* ******************************************* */ -#if defined TWOFISH_UNIT_TEST -#include - -#define TEST_DATA_SIZE 327 - -int main(int argc, char* argv[]) -{ - int i; - int n; - - char outbuf[4096]; - char * outp = outbuf; - - u_int8_t key[] = { 0xfc, 0x77, 0x1a, 0xda, 0xaa }; - TWOFISH *tfa = TwoFishInit( key, 5 ); - TWOFISH *tfb = TwoFishInit( key, 5 ); - - u_int8_t out[2048], out2[2048]; - u_int8_t in[TEST_DATA_SIZE]; - - for ( i=0; i: - * --- April 2001, converted from C++ to C, prefixed global variables - * with TwoFish, substituted some defines, changed functions to make use of - * variables supplied in a struct, modified and added routines for modular calls. - * Cleaned up the code so that defines are used instead of fixed 16's and 32's. - * Created two general purpose crypt routines for one block and multiple block - * encryption using Joh's CBC code. - * Added crypt routines that use a header (with a magic and data length). - * (Basically a major rewrite). - * - * Note: Routines labeled _TwoFish are private and should not be used - * (or with extreme caution). - * - */ - -#ifndef __TWOFISH_LIBRARY_HEADER__ -#define __TWOFISH_LIBRARY_HEADER__ - -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE !FALSE -#endif -#ifndef bool -#define bool int -#endif - -#ifdef WIN32 -#include "win32/n2n_win32.h" -#endif - -/* Constants */ - -#define TwoFish_DEFAULT_PW "SnortHas2FishEncryptionRoutines!" /* default password (not more than 32 chars) */ -#define TwoFish_DEFAULT_PW_LEN 32 -#define TwoFish_MAGIC "TwoFish" /* to indentify a successful decryption */ - -enum -{ TwoFish_KEY_SIZE = 256, /* Valid values: 64, 128, 192, 256 */ - /* User 256, other key sizes have not been tested. */ - /* (But should work. I substitutes as much as */ - /* I could with this define.) */ - TwoFish_ROUNDS = 16, - TwoFish_BLOCK_SIZE = 16, /* bytes in a data-block */ - TwoFish_KEY_LENGTH = TwoFish_KEY_SIZE/8, /* 32= 256-bit key */ - TwoFish_TOTAL_SUBKEYS = 4+4+2*TwoFish_ROUNDS, - TwoFish_MAGIC_LEN = TwoFish_BLOCK_SIZE-8, - TwoFish_SK_BUMP = 0x01010101, - TwoFish_SK_ROTL = 9, - TwoFish_P_00 = 1, - TwoFish_P_01 = 0, - TwoFish_P_02 = 0, - TwoFish_P_03 = TwoFish_P_01 ^ 1, - TwoFish_P_04 = 1, - TwoFish_P_10 = 0, - TwoFish_P_11 = 0, - TwoFish_P_12 = 1, - TwoFish_P_13 = TwoFish_P_11 ^ 1, - TwoFish_P_14 = 0, - TwoFish_P_20 = 1, - TwoFish_P_21 = 1, - TwoFish_P_22 = 0, - TwoFish_P_23 = TwoFish_P_21 ^ 1, - TwoFish_P_24 = 0, - TwoFish_P_30 = 0, - TwoFish_P_31 = 1, - TwoFish_P_32 = 1, - TwoFish_P_33 = TwoFish_P_31 ^ 1, - TwoFish_P_34 = 1, - TwoFish_GF256_FDBK = 0x169, - TwoFish_GF256_FDBK_2 = 0x169 / 2, - TwoFish_GF256_FDBK_4 = 0x169 / 4, - TwoFish_RS_GF_FDBK = 0x14D, /* field generator */ - TwoFish_MDS_GF_FDBK = 0x169 /* primitive polynomial for GF(256) */ -}; - - -/* Global data structure for callers */ - -typedef struct -{ - u_int32_t sBox[4 * 256]; /* Key dependent S-box */ - u_int32_t subKeys[TwoFish_TOTAL_SUBKEYS]; /* Subkeys */ - u_int8_t key[TwoFish_KEY_LENGTH]; /* Encryption Key */ - u_int8_t *output; /* Pointer to output buffer */ - u_int8_t qBlockPlain[TwoFish_BLOCK_SIZE]; /* Used by CBC */ - u_int8_t qBlockCrypt[TwoFish_BLOCK_SIZE]; - u_int8_t prevCipher[TwoFish_BLOCK_SIZE]; - struct /* Header for crypt functions. Has to be at least one block long. */ - { u_int32_t salt; /* Random salt in first block (will salt the rest through CBC) */ - u_int8_t length[4]; /* The amount of data following the header */ - u_int8_t magic[TwoFish_MAGIC_LEN]; /* Magic to identify successful decryption */ - } header; - bool qBlockDefined; - bool dontflush; -} TWOFISH; - -#ifndef __TWOFISH_LIBRARY_SOURCE__ - -extern bool TwoFish_srand; /* if set to TRUE (default), first call of TwoFishInit will seed rand(); */ - /* call of TwoFishInit */ -#endif - - -/**** Public Functions ****/ - -/* TwoFish Initialization - * - * This routine generates a global data structure for use with TwoFish, - * initializes important values (such as subkeys, sBoxes), generates subkeys - * and precomputes the MDS matrix if not already done. - * - * Input: User supplied password (will be appended by default password of 'SnortHas2FishEncryptionRoutines!') - * - * Output: Pointer to TWOFISH structure. This data structure contains key dependent data. - * This pointer is used with all other crypt functions. - */ -TWOFISH *TwoFishInit(const u_int8_t *userkey, u_int32_t keysize ); - - -/* TwoFish Destroy - * - * Nothing else but a free... - * - * Input: Pointer to the TwoFish structure. - * - */ -void TwoFishDestroy(TWOFISH *tfdata); - - -/* TwoFish Alloc - * - * Allocates enough memory for the output buffer as required. - * - * Input: Length of the plaintext. - * Boolean flag for BinHex Output. - * Pointer to the TwoFish structure. - * - * Output: Returns a pointer to the memory allocated. - */ -void *TwoFishAlloc(u_int32_t len,bool binhex,bool decrypt,TWOFISH *tfdata); - - -/* TwoFish Free - * - * Free's the allocated buffer. - * - * Input: Pointer to the TwoFish structure - * - * Output: (none) - */ -void TwoFishFree(TWOFISH *tfdata); - - -/* TwoFish Set Output - * - * If you want to allocate the output buffer yourself, - * then you can set it with this function. - * - * Input: Pointer to your output buffer - * Pointer to the TwoFish structure - * - * Output: (none) - */ -void TwoFishSetOutput(u_int8_t *outp,TWOFISH *tfdata); - - -/* TwoFish Raw Encryption - * - * Does not use header, but does use CBC (if more than one block has to be encrypted). - * - * Input: Pointer to the buffer of the plaintext to be encrypted. - * Pointer to the buffer receiving the ciphertext. - * The length of the plaintext buffer. - * The TwoFish structure. - * - * Output: The amount of bytes encrypted if successful, otherwise 0. - */ -u_int32_t TwoFishEncryptRaw(u_int8_t *in,u_int8_t *out,u_int32_t len,TWOFISH *tfdata); - -/* TwoFish Raw Decryption - * - * Does not use header, but does use CBC (if more than one block has to be decrypted). - * - * Input: Pointer to the buffer of the ciphertext to be decrypted. - * Pointer to the buffer receiving the plaintext. - * The length of the ciphertext buffer (at least one cipher block). - * The TwoFish structure. - * - * Output: The amount of bytes decrypted if successful, otherwise 0. - */ -u_int32_t TwoFishDecryptRaw(u_int8_t *in,u_int8_t *out,u_int32_t len,TWOFISH *tfdata); - - -/* TwoFish Encryption - * - * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc, - * this routine will alloc the memory. In addition, it will include a small 'header' - * containing the magic and some salt. That way the decrypt routine can check if the - * packet got decrypted successfully, and return 0 instead of garbage. - * - * Input: Pointer to the buffer of the plaintext to be encrypted. - * Pointer to the pointer to the buffer receiving the ciphertext. - * The pointer either points to user allocated output buffer space, or to NULL, in which case - * this routine will set the pointer to the buffer allocated through the struct. - * The length of the plaintext buffer. - * Can be -1 if the input is a null terminated string, in which case we'll count for you. - * Boolean flag for BinHex Output (if used, output will be twice as large as input). - * Note: BinHex conversion overwrites (converts) input buffer! - * The TwoFish structure. - * - * Output: The amount of bytes encrypted if successful, otherwise 0. - */ -u_int32_t TwoFishEncrypt(u_int8_t *in,u_int8_t **out,signed long len,bool binhex,TWOFISH *tfdata); - - -/* TwoFish Decryption - * - * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc, - * this routine will alloc the memory. In addition, it will check the small 'header' - * containing the magic. If magic does not match we return 0. Otherwise we return the - * amount of bytes decrypted (should be the same as the length in the header). - * - * Input: Pointer to the buffer of the ciphertext to be decrypted. - * Pointer to the pointer to the buffer receiving the plaintext. - * The pointer either points to user allocated output buffer space, or to NULL, in which case - * this routine will set the pointer to the buffer allocated through the struct. - * The length of the ciphertext buffer. - * Can be -1 if the input is a null terminated binhex string, in which case we'll count for you. - * Boolean flag for BinHex Input (if used, plaintext will be half as large as input). - * Note: BinHex conversion overwrites (converts) input buffer! - * The TwoFish structure. - * - * Output: The amount of bytes decrypted if successful, otherwise 0. - */ -u_int32_t TwoFishDecrypt(u_int8_t *in,u_int8_t **out,signed long len,bool binhex,TWOFISH *tfdata); - - -/**** Private Functions ****/ - -u_int8_t TwoFish__b(u_int32_t x,int n); -void _TwoFish_BinHex(u_int8_t *buf,u_int32_t len,bool bintohex); -u_int32_t _TwoFish_CryptRawCBC(u_int8_t *in,u_int8_t *out,u_int32_t len,bool decrypt,TWOFISH *tfdata); -u_int32_t _TwoFish_CryptRaw16(u_int8_t *in,u_int8_t *out,u_int32_t len,bool decrypt,TWOFISH *tfdata); -u_int32_t _TwoFish_CryptRaw(u_int8_t *in,u_int8_t *out,u_int32_t len,bool decrypt,TWOFISH *tfdata); -void _TwoFish_PrecomputeMDSmatrix(void); -void _TwoFish_MakeSubKeys(TWOFISH *tfdata); -void _TwoFish_qBlockPush(u_int8_t *p,u_int8_t *c,TWOFISH *tfdata); -void _TwoFish_qBlockPop(u_int8_t *p,u_int8_t *c,TWOFISH *tfdata); -void _TwoFish_ResetCBC(TWOFISH *tfdata); -void _TwoFish_FlushOutput(u_int8_t *b,u_int32_t len,TWOFISH *tfdata); -void _TwoFish_BlockCrypt(u_int8_t *in,u_int8_t *out,u_int32_t size,int decrypt,TWOFISH *tfdata); -void _TwoFish_BlockCrypt16(u_int8_t *in,u_int8_t *out,bool decrypt,TWOFISH *tfdata); -u_int32_t _TwoFish_RS_MDS_Encode(u_int32_t k0,u_int32_t k1); -u_int32_t _TwoFish_F32(u_int32_t k64Cnt,u_int32_t x,u_int32_t *k32); -u_int32_t _TwoFish_Fe320(u_int32_t *lsBox,u_int32_t x); -u_int32_t _TwoFish_Fe323(u_int32_t *lsBox,u_int32_t x); -u_int32_t _TwoFish_Fe32(u_int32_t *lsBox,u_int32_t x,u_int32_t R); - - -#endif diff --git a/n2n_v1/win32/DotNet/n2n.sln b/n2n_v1/win32/DotNet/n2n.sln deleted file mode 100644 index 93a58d4..0000000 --- a/n2n_v1/win32/DotNet/n2n.sln +++ /dev/null @@ -1,26 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual C++ Express 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "edge", "n2n.vcproj", "{4911ADD4-08A3-4C9F-B9C9-9492DA10D01D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "supernode", "supernode\supernode.vcproj", "{1F7F0E45-7DE9-4CE2-845F-38D59C2E4F51}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {4911ADD4-08A3-4C9F-B9C9-9492DA10D01D}.Debug|Win32.ActiveCfg = Debug|Win32 - {4911ADD4-08A3-4C9F-B9C9-9492DA10D01D}.Debug|Win32.Build.0 = Debug|Win32 - {4911ADD4-08A3-4C9F-B9C9-9492DA10D01D}.Release|Win32.ActiveCfg = Release|Win32 - {4911ADD4-08A3-4C9F-B9C9-9492DA10D01D}.Release|Win32.Build.0 = Release|Win32 - {1F7F0E45-7DE9-4CE2-845F-38D59C2E4F51}.Debug|Win32.ActiveCfg = Debug|Win32 - {1F7F0E45-7DE9-4CE2-845F-38D59C2E4F51}.Debug|Win32.Build.0 = Debug|Win32 - {1F7F0E45-7DE9-4CE2-845F-38D59C2E4F51}.Release|Win32.ActiveCfg = Release|Win32 - {1F7F0E45-7DE9-4CE2-845F-38D59C2E4F51}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/n2n_v1/win32/DotNet/n2n.vcproj b/n2n_v1/win32/DotNet/n2n.vcproj deleted file mode 100644 index c1b97c1..0000000 --- a/n2n_v1/win32/DotNet/n2n.vcproj +++ /dev/null @@ -1,263 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/n2n_v1/win32/DotNet/supernode/supernode.vcproj b/n2n_v1/win32/DotNet/supernode/supernode.vcproj deleted file mode 100644 index 49fcf9b..0000000 --- a/n2n_v1/win32/DotNet/supernode/supernode.vcproj +++ /dev/null @@ -1,259 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/n2n_v1/win32/n2n_win32.h b/n2n_v1/win32/n2n_win32.h deleted file mode 100644 index 6eafecb..0000000 --- a/n2n_v1/win32/n2n_win32.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - - (C) 2007 - Luca Deri - -*/ - -#ifndef _N2N_WIN32_H_ -#define _N2N_WIN32_H_ - -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include "wintap.h" - -typedef unsigned int u_int32_t; -typedef unsigned short u_int16_t; -typedef unsigned char u_int8_t; -typedef int int32_t; -typedef short int16_t; -typedef char int8_t; - -#define snprintf _snprintf -#define strdup _strdup - -#define socklen_t int - -#define ETHER_ADDR_LEN 6 -/* - * Structure of a 10Mb/s Ethernet header. - */ -struct ether_header { - u_char ether_dhost[ETHER_ADDR_LEN]; - u_char ether_shost[ETHER_ADDR_LEN]; - u_short ether_type; -}; - -/* ************************************* */ - -struct ip { -#if BYTE_ORDER == LITTLE_ENDIAN - u_char ip_hl:4, /* header length */ - ip_v:4; /* version */ -#else - u_char ip_v:4, /* version */ - ip_hl:4; /* header length */ -#endif - u_char ip_tos; /* type of service */ - short ip_len; /* total length */ - u_short ip_id; /* identification */ - short ip_off; /* fragment offset field */ -#define IP_DF 0x4000 /* dont fragment flag */ -#define IP_MF 0x2000 /* more fragments flag */ -#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ - u_char ip_ttl; /* time to live */ - u_char ip_p; /* protocol */ - u_short ip_sum; /* checksum */ - struct in_addr ip_src,ip_dst; /* source and dest address */ -}; - - -/* ************************************* */ - -typedef struct tuntap_dev { - HANDLE device_handle; - char *device_name; - char *ifName; - OVERLAPPED overlap_read, overlap_write; - u_int8_t mac_addr[6]; - u_int32_t ip_addr, device_mask; - u_int mtu; -} tuntap_dev; - -#endif \ No newline at end of file diff --git a/n2n_v1/win32/wintap.c b/n2n_v1/win32/wintap.c deleted file mode 100644 index 8c13aa4..0000000 --- a/n2n_v1/win32/wintap.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - (C) 2007-08 - Luca Deri -*/ - -#include "../n2n.h" -#include "n2n_win32.h" - -/* 1500 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */ -#define MTU 1518 - -void initWin32() { - WSADATA wsaData; - int err; - - err = WSAStartup(MAKEWORD(2, 2), &wsaData ); - if( err != 0 ) { - /* Tell the user that we could not find a usable */ - /* WinSock DLL. */ - printf("FATAL ERROR: unable to initialise Winsock 2.x."); - exit(-1); - } -} - -int open_wintap(struct tuntap_dev *device, - char *device_ip, char *device_mask, - char *device_mac, int mtu) { - HKEY key, key2; - LONG rc; - char regpath[1024], cmd[256]; - char adapterid[1024]; - char adaptername[1024]; - char tapname[1024]; - long len; - int found = 0; - int err, i; - ULONG status = TRUE; - - memset(device, 0, sizeof(struct tuntap_dev)); - device->device_handle = INVALID_HANDLE_VALUE; - device->device_name = NULL; - device->ifName = NULL; - device->ip_addr = inet_addr(device_ip); - - /* Open registry and look for network adapters */ - if((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key))) { - printf("Unable to read registry: [rc=%d]\n", rc); - exit(-1); - } - - for (i = 0; ; i++) { - len = sizeof(adapterid); - if(RegEnumKeyEx(key, i, (LPCWSTR)adapterid, &len, 0, 0, 0, NULL)) - break; - - /* Find out more about this adapter */ - - _snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapterid); - if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)regpath, 0, KEY_READ, &key2)) - continue; - - len = sizeof(adaptername); - err = RegQueryValueEx(key2, "Name", 0, 0, adaptername, &len); - - RegCloseKey(key2); - - if(err) - continue; - - if(device->device_name) { - if(!strcmp(device->device_name, adapterid)) { - found = 1; - break; - } else - continue; - } - - if(device->ifName) { - if(!strcmp(device->ifName, adaptername)) { - found = 1; - break; - } else - continue; - } - - _snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid); - device->device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, - 0, /* Don't let other processes share or open - the resource until the handle's been closed */ - 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0); - if(device->device_handle != INVALID_HANDLE_VALUE) { - found = 1; - break; - } - } - - RegCloseKey(key); - - if(!found) { - printf("No Windows tap device found!\n"); - exit(0); - } - - /* ************************************** */ - - if(!device->device_name) - device->device_name = _strdup(adapterid); - - if(!device->ifName) - device->ifName = _strdup(adaptername); - - /* Try to open the corresponding tap device->device_name */ - - if(device->device_handle == INVALID_HANDLE_VALUE) { - _snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, device->device_name); - device->device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, - OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0); - } - - if(device->device_handle == INVALID_HANDLE_VALUE) { - printf("%s (%s) is not a usable Windows tap device\n", device->device_name, device->ifName); - exit(-1); - } - - /* Get MAC address from tap device->device_name */ - - if(!DeviceIoControl(device->device_handle, TAP_IOCTL_GET_MAC, - device->mac_addr, sizeof(device->mac_addr), - device->mac_addr, sizeof(device->mac_addr), &len, 0)) { - printf("Could not get MAC address from Windows tap %s (%s)\n", - device->device_name, device->ifName); - return -1; - } - - device->mtu = mtu; - - printf("Open device [name=%s][ip=%s][ifName=%s][MTU=%d][mac=%02X:%02X:%02X:%02X:%02X:%02X]\n", - device->device_name, device_ip, device->ifName, device->mtu, - device->mac_addr[0] & 0xFF, - device->mac_addr[1] & 0xFF, - device->mac_addr[2] & 0xFF, - device->mac_addr[3] & 0xFF, - device->mac_addr[4] & 0xFF, - device->mac_addr[5] & 0xFF); - - /* ****************** */ - - printf("Setting %s device address...\n", device->ifName); - - _snprintf(cmd, sizeof(cmd), - "netsh interface ip set address \"%s\" static %s %s", - device->ifName, device_ip, device_mask); - - if(system(cmd) == 0) { - device->ip_addr = inet_addr(device_ip); - device->device_mask = inet_addr(device_mask); - printf("Device %s set to %s/%s\n", - device->ifName, device_ip, device_mask); - } else - printf("WARNING: Unable to set device %s IP address [%s]\n", - device->ifName, cmd); - - /* ****************** */ - - if(device->mtu != DEFAULT_MTU) - printf("WARNING: MTU set is not supported on Windows\n"); - - /* set driver media status to 'connected' (i.e. set the interface up) */ - if (!DeviceIoControl (device->device_handle, TAP_IOCTL_SET_MEDIA_STATUS, - &status, sizeof (status), - &status, sizeof (status), &len, NULL)) - printf("WARNING: Unable to enable TAP adapter\n"); - - /* - * Initialize overlapped structures - */ - device->overlap_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - device->overlap_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if (!device->overlap_read.hEvent || !device->overlap_write.hEvent) { - return -1; - } - - return(0); -} - -/* ************************************************ */ - -int tuntap_read(struct tuntap_dev *tuntap, unsigned char *buf, int len) -{ - DWORD read_size, last_err; - - ResetEvent(tuntap->overlap_read.hEvent); - if (ReadFile(tuntap->device_handle, buf, len, &read_size, &tuntap->overlap_read)) { - //printf("tun_read(len=%d)\n", read_size); - return read_size; - } - switch (last_err = GetLastError()) { - case ERROR_IO_PENDING: - WaitForSingleObject(tuntap->overlap_read.hEvent, INFINITE); - GetOverlappedResult(tuntap->device_handle, &tuntap->overlap_read, &read_size, FALSE); - return read_size; - break; - default: - printf("GetLastError() returned %d\n", last_err); - break; - } - - return -1; -} -/* ************************************************ */ - -int tuntap_write(struct tuntap_dev *tuntap, unsigned char *buf, int len) -{ - DWORD write_size; - - //printf("tun_write(len=%d)\n", len); - - ResetEvent(tuntap->overlap_write.hEvent); - if (WriteFile(tuntap->device_handle, - buf, - len, - &write_size, - &tuntap->overlap_write)) { - //printf("DONE tun_write(len=%d)\n", write_size); - return write_size; - } - switch (GetLastError()) { - case ERROR_IO_PENDING: - WaitForSingleObject(tuntap->overlap_write.hEvent, INFINITE); - GetOverlappedResult(tuntap->device_handle, &tuntap->overlap_write, - &write_size, FALSE); - return write_size; - break; - default: - break; - } - - return -1; -} - -/* ************************************************ */ - -int tuntap_open(tuntap_dev *device, char *dev, char *device_ip, - char *device_mask, const char * device_mac, int mtu) { - return(open_wintap(device, device_ip, device_mask, device_mac, mtu)); -} - -/* ************************************************ */ - -void tuntap_close(struct tuntap_dev *tuntap) { - CloseHandle(tuntap->device_handle); -} - -/* ************************************************ */ - -#if 0 -int main(int argc, char* argv[]) { - struct tuntap_dev tuntap; - int i; - int mtu = 1400; - - printf("Welcome to n2n\n"); - initWin32(); - open_wintap(&tuntap, "1.2.3.20", "255.255.255.0", mtu); - - for(i=0; i<10; i++) { - u_char buf[MTU]; - int rc; - - rc = tun_read(&tuntap, buf, sizeof(buf)); - buf[0]=2; - buf[1]=3; - buf[2]=4; - - printf("tun_read returned %d\n", rc); - rc = tun_write(&tuntap, buf, rc); - printf("tun_write returned %d\n", rc); - } - // rc = tun_open (device->device_name, IF_MODE_TUN); - WSACleanup (); - return(0); -} - -#endif diff --git a/n2n_v1/win32/wintap.h b/n2n_v1/win32/wintap.h deleted file mode 100644 index 0eef8f0..0000000 --- a/n2n_v1/win32/wintap.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - (C) 2007 - Luca Deri -*/ - -#ifndef _WINTAP_H_ -#define _WINTAP_H_ - -#undef UNICODE -#undef _UNICODE -#define _CRT_SECURE_NO_WARNINGS - -#include -#include -#include - - - -//=============================================== -// This file is included both by OpenVPN and -// the TAP-Win32 driver and contains definitions -// common to both. -//=============================================== - -//============= -// TAP IOCTLs -//============= - -#define TAP_CONTROL_CODE(request,method) \ - CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) - -#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED) -#define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED) -#define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED) -#define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED) -#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED) -#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED) -#define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED) -#define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED) -#define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED) - -//================= -// Registry keys -//================= - -#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" -#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" - -//====================== -// Filesystem prefixes -//====================== - -#define USERMODEDEVICEDIR "\\\\.\\Global\\" -#define SYSDEVICEDIR "\\Device\\" -#define USERDEVICEDIR "\\DosDevices\\Global\\" -#define TAPSUFFIX ".tap" - -//========================================================= -// TAP_COMPONENT_ID -- This string defines the TAP driver -// type -- different component IDs can reside in the system -// simultaneously. -//========================================================= - -#define TAP_COMPONENT_ID "tap0801" - -extern void initWin32(); - -#endif \ No newline at end of file diff --git a/n2n_v2/n2n_v2.7 b/n2n_v2.7 similarity index 100% rename from n2n_v2/n2n_v2.7 rename to n2n_v2.7 diff --git a/n2n_v2/COPYING b/n2n_v2/COPYING deleted file mode 100644 index b33b35d..0000000 --- a/n2n_v2/COPYING +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - 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 . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - n2n Copyright (C) 2007-08 Luca Deri - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/n2n_v2/README b/n2n_v2/README deleted file mode 100644 index f21422b..0000000 --- a/n2n_v2/README +++ /dev/null @@ -1,111 +0,0 @@ - - -Edge node ---------- - -You need to start an edge node on each host you want to connect with the *same* -community. - -0. become root - -1. create tun device -# tunctl -t tun0 - -3. enable the edge process -# ./edge -d n2n0 -c mynetwork -k encryptme -u 99 -g 99 -m 3C:A0:12:34:56:78 -a 1.2.3.4 -l a.b.c.d:xyw - or -# N2N_KEY=encryptme ./edge -d n2n0 -c mynetwork -u 99 -g 99 -m 3C:A0:12:34:56:78 -a 1.2.3.4 -l a.b.c.d:xyw - -Once you have this worked out, you can add the "-f" option to make edge detach -and run as a daemon. - -Note that -u, -g and -f options are not available for Windows. - -Supernode --------- - -You need to start the supernode once - -1. ./supernode -l 1234 -v - - -Dropping Root Privileges and SUID-Root Executables (UNIX) --------------------------------------------------- - -The edge node uses superuser privileges to create a TAP network interface -device. Once this is created root privileges are not required and can constitute -a security hazard if there is some way for an attacker to take control of an -edge process while it is running. Edge will drop to a non-privileged user if you -specify the -u and -g options. These are numeric IDs. Consult -/etc/passwd. - -You may choose to install edge SUID-root to do this: - -1. Become root -2. chown root:root edge -3. chmod +s edge -done - -Any user can now run edge. You may not want this, but it may be convenient and -safe if your host has only one login user. - - -Running As a Daemon (UNIX) -------------------- - -Unless given "-f" as a command line option, edge will call daemon(3) after -successful setup. This causes the process to fork a child which closes stdin, -stdout and stderr then sets itself as process group leader. When this is done, -the edge command returns immediately and you will only see the edge process in -the process listings, eg. from ps or top. - -If the edge command returns 0 then the daemon started successfully. If it -returns non-zero then edge failed to start up for some reason. When edge starts -running as a daemon, all logging goes to syslog daemon.info facility. - - -IPv6 Support ------------- - -n2n supports the carriage of IPv6 packets within the n2n tunnel. N2n does not -yet use IPv6 for transport between edges and supernodes. - -To make IPv6 carriage work you need to manually add IPv6 addresses to the TAP -interfaces at each end. There is currently no way to specify an IPv6 address on -the edge command line. - -eg. under linux: - -on hostA: -[hostA] # /sbin/ip -6 addr add fc00:abcd:1234::7/48 dev n2n0 - -on hostB: -[hostB] # /sbin/ip -6 addr add fc00:abcd:1234::6/48 dev n2n0 - -You may find it useful to make use of tunctl from the uml-utilities -package. Tunctl allow you to bring up a TAP interface and configure addressing -prior to starting edge. It also allows edge to be restarted without the -interface closing (which would normally affect routing tables). - -Once the IPv6 addresses are configured and edge started, IPv6 neighbor discovery -packets flow (get broadcast) and IPv6 entities self arrange. Test your IPv6 -setup with ping6 - the IPv6 ping command. - - -Performance Notes ------------------ - -The time taken to perform a ping test for various ciphers is given below: - -Test: ping -f -l 8 -s 800 -c 10000 - -AES (-O0) 11820 -TF (-O0) 25761 - -TF (-O2) 20554 - -AES (-O3) 12532 -TF (-O3) 14046 -NULL (-O3) 10659 - -(C) 2007-2010 - Luca Deri , Richard Andrews diff --git a/n2n_v2/benchmark.c b/n2n_v2/benchmark.c deleted file mode 100644 index 0541095..0000000 --- a/n2n_v2/benchmark.c +++ /dev/null @@ -1,108 +0,0 @@ -#include "n2n_wire.h" -#include "n2n_transforms.h" -#include "n2n.h" - -#ifndef WIN32 -#include -#endif -#include -#include -#include - -uint8_t PKT_CONTENT[]={ - 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, - 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, - 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, - 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, - 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, - 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, - 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, - 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, - 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, - 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, - 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, - 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, - 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, - 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, - 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, - 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }; - -/* Prototypes */ -static ssize_t do_encode_packet( uint8_t * pktbuf, size_t bufsize, const n2n_community_t c ); - -int main( int argc, char * argv[] ) -{ - uint8_t pktbuf[N2N_PKT_BUF_SIZE]; - n2n_trans_op_t transop_null; - - n2n_common_t cmn; - n2n_PACKET_t pkt; - n2n_community_t c; - - struct timeval t1; - struct timeval t2; - - unsigned long int i; - size_t n; - size_t idx; - size_t rem; - ssize_t nw; - unsigned long int tdiff; - - transop_null_init( &transop_null ); - memset(c,0,sizeof(N2N_COMMUNITY_SIZE)); - - n=10000; - memcpy( c, "abc123def456", 12 ); - - gettimeofday( &t1, NULL ); - for(i=0; i %lu nsec each) %u.%06u -> %u.%06u.\n", i, tdiff, (tdiff *1000)/i, (uint32_t)t1.tv_sec, (uint32_t)t1.tv_usec, (uint32_t)t2.tv_sec, (uint32_t)t2.tv_usec ); - - return 0; -} - -static ssize_t do_encode_packet( uint8_t * pktbuf, size_t bufsize, const n2n_community_t c ) -{ - /* n2n_mac_t destMac={0,1,2,3,4,5}; */ - n2n_common_t cmn; - n2n_PACKET_t pkt; - size_t idx; - - - 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, c, N2N_COMMUNITY_SIZE ); - - memset( &pkt, 0, sizeof(pkt) ); - - idx=0; - encode_PACKET( pktbuf, &idx, &cmn, &pkt ); - traceEvent( TRACE_DEBUG, "encoded PACKET header of size=%u", (unsigned int)idx ); - - return idx; -} diff --git a/n2n_v2/benchmark_hashtable.c b/n2n_v2/benchmark_hashtable.c deleted file mode 100644 index 41fe6f9..0000000 --- a/n2n_v2/benchmark_hashtable.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "n2n_wire.h" -#include "n2n_transforms.h" -#include "n2n.h" - -#ifndef WIN32 -#include -#endif -#include -#include -#include - -int main(int argc, char** argv) { - peer_info_t* testpeers[PEER_HASH_TAB_SIZE]; - struct sglib_hashed_peer_info_t_iterator it; - peer_info_t *ll; - - sglib_hashed_peer_info_t_init(testpeers); - - for(ll=sglib_hashed_peer_info_t_it_init(&it, testpeers); ll!=NULL; ll=sglib_hashed_peer_info_t_it_next(&it)) { - sglib_hashed_peer_info_t_delete(testpeers, ll); - free(ll); - } - return 0; -} \ No newline at end of file diff --git a/n2n_v2/debian/README.Debian b/n2n_v2/debian/README.Debian deleted file mode 100644 index 700c74e..0000000 --- a/n2n_v2/debian/README.Debian +++ /dev/null @@ -1,7 +0,0 @@ -n2n for Debian --------------- - -This package depends on the kernel having the TUN/TAP driver configured in using -CONFIG_TUN=yes. - - -- Richard Andrews Thu, 10 Jul 2008 22:38:02 +1000 diff --git a/n2n_v2/debian/compat b/n2n_v2/debian/compat deleted file mode 100644 index 7ed6ff8..0000000 --- a/n2n_v2/debian/compat +++ /dev/null @@ -1 +0,0 @@ -5 diff --git a/n2n_v2/debian/copyright b/n2n_v2/debian/copyright deleted file mode 100644 index 38346ce..0000000 --- a/n2n_v2/debian/copyright +++ /dev/null @@ -1,23 +0,0 @@ -This package was debianized by Jean-Baptiste Denis on -Thu, 20 Nov 2008 23:53:02 +1000. - -It was downloaded from http://www.ntop.org/n2n/ - -Upstream Author(s): - - Luca Deri - Richard Andrews - -Copyright: - - Copyright (C) 2008 Luca Deri - Copyright (C) 2008 Richard Andrews - -License: - - GPLv3 - -The Debian packaging is (C) 2008, Richard Andrews , -Luca Deri and is licensed under the GPLv3, see -`/usr/share/common-licenses/GPL-3'. - diff --git a/n2n_v2/edge.c b/n2n_v2/edge.c deleted file mode 100644 index a5daa6f..0000000 --- a/n2n_v2/edge.c +++ /dev/null @@ -1,2696 +0,0 @@ -/** - * (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. - * - * 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 - * - * Code contributions courtesy of: - * Don Bindner - * Sylwester Sosnowski - * Wilfried "Wonka" Klaebe - * Lukasz Taczuk - * - */ - -#include "n2n.h" -#include "n2n_transforms.h" -#include -#include -#include "minilzo.h" - -#if defined(DEBUG) -#define SOCKET_TIMEOUT_INTERVAL_SECS 5 -#define DEFAULT_HOLEPUNCH_INTERVAL 20 /* sec */ -#else /* #if defined(DEBUG) */ -#define SOCKET_TIMEOUT_INTERVAL_SECS 5 -#define DEFAULT_HOLEPUNCH_INTERVAL 25 /* sec */ -#endif /* #if defined(DEBUG) */ - -#define REGISTER_SUPER_INTERVAL_MIN 10 /* sec */ -#define REGISTER_SUPER_INTERVAL_MAX 120 /* sec */ - -#define IFACE_UPDATE_INTERVAL (30) /* sec. How long it usually takes to get an IP lease. */ -#define TRANSOP_TICK_INTERVAL (10) /* sec */ - -#define STAT_CALC_INTERVAL (10) /* sec. Calculate the bps values in roughly this interval steps */ - -/** 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 N2N_EDGE_SN_HOST_SIZE 48 -#define N2N_EDGE_LOCAL_IP_SIZE 48 - -typedef char n2n_sn_name_t[N2N_EDGE_SN_HOST_SIZE]; -typedef char n2n_local_ip_t[N2N_EDGE_LOCAL_IP_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; - n2n_sock_t local_sock; - - 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]; - n2n_local_ip_t local_ip_str; /** storing a local ip socket */ - int local_sock_ena; /** > 0 if local_sock is enabled */ - 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[PEER_HASH_TAB_SIZE]; /**< Edges we are connected to. */ - struct peer_info * pending_peers[PEER_HASH_TAB_SIZE]; /**< Edges we have tried to register with. */ - time_t last_register_req; /**< Check if time to re-register with super*/ - size_t holepunch_interval; /**< Time distance after last_register_req at which to re-register. */ - time_t last_purge; /** last time clients were purged **/ - 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 tx_bit_p2p; - size_t tx_bps_p2p; - size_t rx_p2p; - size_t rx_bit_p2p; - size_t rx_bps_p2p; - size_t tx_sup; - size_t tx_bit_sup; - size_t tx_bps_sup; - size_t rx_sup; - size_t rx_bit_sup; - size_t rx_bps_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 int localip2addr(n2n_sock_t * l_ip, - const n2n_local_ip_t local_ip_strIn, int local_port); - -static void send_packet2net(n2n_edge_t * eee, - uint8_t *decrypted_msg, size_t len); - - -/* ************************************** */ - -/* parse the configuration file */ -static int readConfFile(const char * filename, char * const linebuffer) { - struct stat stats; - FILE * fd; - char * buffer = NULL; - - buffer = (char *)malloc(MAX_CONFFILE_LINE_LENGTH); - if (!buffer) { - traceEvent( TRACE_ERROR, "Unable to allocate memory"); - return -1; - } - - 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); - free(buffer); - return -1; - } - - fd = fopen(filename, "rb"); - if (!fd) { - traceEvent(TRACE_ERROR, "Unable to open parameter file '%s' (%d)...\n",filename,errno); - free(buffer); - return -1; - } - while(fgets(buffer, MAX_CONFFILE_LINE_LENGTH,fd)) { - char * p = NULL; - - /* strip out comments */ - p = strchr(buffer, '#'); - if (p) *p ='\0'; - - /* remove \n */ - p = strchr(buffer, '\n'); - if (p) *p ='\0'; - - /* strip out heading spaces */ - p = buffer; - while(*p == ' ' && *p != '\0') ++p; - 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, '@')) { - 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) { - strncat(linebuffer, " ", 1); - strncat(linebuffer, buffer, strlen(buffer)); - } else { - traceEvent(TRACE_ERROR, "too many argument"); - free(buffer); - return -1; - } - } - - free(buffer); - fclose(fd); - - 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 */ - int maxargc; - int argc=0; - char ** argv; - char * buffer, * buff; - - *effectiveargc = 0; - buffer = (char *)calloc(1, strlen(linebuffer)+2); - if (!buffer) { - traceEvent( TRACE_ERROR, "Unable to allocate memory"); - return NULL; - } - strncpy(buffer, linebuffer,strlen(linebuffer)); - - maxargc = INITIAL_MAXARGC; - argv = (char **)malloc(maxargc * sizeof(char*)); - if (argv == NULL) { - traceEvent( TRACE_ERROR, "Unable to allocate memory"); - return NULL; - } - buff = buffer; - while(buff) { - char * p = strchr(buff,' '); - if (p) { - *p='\0'; - argv[argc++] = strdup(buff); - while(*++p == ' ' && *p != '\0'); - buff=p; - if (argc >= maxargc) { - maxargc *= 2; - argv = (char **)realloc(argv, maxargc * sizeof(char*)); - if (argv == NULL) { - traceEvent(TRACE_ERROR, "Unable to re-allocate memory"); - free(buffer); - return NULL; - } - } - } else { - argv[argc++] = strdup(buff); - break; - } - } - 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->local_sock_ena = 0; - sglib_hashed_peer_info_t_init(eee->known_peers); - sglib_hashed_peer_info_t_init(eee->pending_peers); - eee->last_register_req = 0; - eee->holepunch_interval = DEFAULT_HOLEPUNCH_INTERVAL; - eee->last_p2p = 0; - eee->last_sup = 0; - eee->last_purge = 0; - eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; - eee->tx_bit_p2p = 0; - eee->tx_bit_sup = 0; - eee->rx_bit_p2p = 0; - eee->rx_bit_sup = 0; - - 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_hashed_peer_info_t_list( eee->pending_peers ); - clear_hashed_peer_info_t_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(); - - printf("edge " -#if defined(N2N_CAN_NAME_IFACE) - "-d " -#endif /* #if defined(N2N_CAN_NAME_IFACE) */ - "-a [static:|dhcp:] " - "-c " - "[-k | -K ] " - "[-s ] " -#if defined(N2N_HAVE_SETUID) - "[-u -g ]" -#endif /* #ifndef N2N_HAVE_SETUID */ - -#if defined(N2N_HAVE_DAEMON) - "[-f]" -#endif /* #if defined(N2N_HAVE_DAEMON) */ - "[-m ]" - "\n" - "-l " - "[-p ] [-M ] " - "[-r] [-E] [-v] [-t ] [-b] [-h]\n\n"); - -#ifdef __linux__ - printf("-d | tun device name\n"); -#endif - - printf("-a | Set interface address. For DHCP use '-r -a dhcp:0.0.0.0'\n"); - printf("-c | n2n community name the edge belongs to.\n"); - printf("-k | Encryption key (ASCII) - also N2N_KEY=. Not with -K.\n"); - printf("-K | Specify a key schedule file to load. Not with -k.\n"); - printf("-s | Edge interface netmask in dotted decimal notation (255.255.255.0).\n"); - printf("-l | Supernode IP:port\n"); - printf("-i | Add local ip to bypass between same nat problem\n"); - printf("-b | Periodically resolve supernode IP\n"); - printf(" : (when supernodes are running on dynamic IPs)\n"); - printf("-p | Fixed local UDP port.\n"); -#ifndef WIN32 - 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 - printf("-f | Do not fork and run as a daemon; rather run in foreground.\n"); -#endif /* #ifdef N2N_HAVE_DAEMON */ - 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); - printf("-r | Enable packet forwarding through n2n community.\n"); - printf("-E | Accept multicast MAC addresses (default=drop).\n"); - printf("-v | Make more verbose. Repeat as required.\n"); - 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" ); - - 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 ) -{ - n2n_sock_str_t sockbuf; - 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 %s failed (%d) %s", - sock_to_cstr( sockbuf, dest ), 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, - const n2n_mac_t dstMac) -{ - uint8_t pktbuf[N2N_PKT_BUF_SIZE]; - size_t idx; - n2n_common_t cmn = {0}; - n2n_REGISTER_t reg = {{0}}; - n2n_sock_str_t sockbuf; - - cmn.ttl=N2N_DEFAULT_TTL; - cmn.pc = n2n_register; - cmn.flags = 0; - memcpy( cmn.community, eee->community_name, N2N_COMMUNITY_SIZE ); - - /* NOTE: Encoding should probably not be done here but in - * encode_REGISTER (lukas) */ - idx=0; - encode_uint32( reg.cookie, &idx, 123456789 ); - idx=0; - encode_mac( reg.srcMac, &idx, eee->device.mac_addr ); - if(dstMac) { - idx=0; - encode_mac( reg.dstMac, &idx, dstMac ); - } - - idx=0; - encode_REGISTER( pktbuf, &idx, &cmn, ® ); - - traceEvent( TRACE_INFO, "send REGISTER %s", - sock_to_cstr( sockbuf, remote_peer ) ); - - - sendto_sock( eee->udp_sock, pktbuf, idx, remote_peer ); -} - -/** Send a QUERY_PEER packet to the current supernode. */ -static void send_query_peer( n2n_edge_t * eee, - const n2n_mac_t dstMac) -{ - uint8_t pktbuf[N2N_PKT_BUF_SIZE]; - size_t idx; - n2n_common_t cmn = {0}; - n2n_QUERY_PEER_t query = {{0}}; - - cmn.ttl=N2N_DEFAULT_TTL; - cmn.pc = n2n_query_peer; - cmn.flags = 0; - memcpy( cmn.community, eee->community_name, N2N_COMMUNITY_SIZE ); - - idx=0; - encode_mac( query.srcMac, &idx, eee->device.mac_addr ); - idx=0; - encode_mac( query.targetMac, &idx, dstMac ); - - idx=0; - encode_QUERY_PEER( pktbuf, &idx, &cmn, &query ); - - traceEvent( TRACE_INFO, "send QUERY_PEER to supernode" ); - - sendto_sock( eee->udp_sock, pktbuf, idx, &(eee->supernode) ); -} - -/** 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; - n2n_common_t cmn = {0}; - n2n_REGISTER_SUPER_t reg = {0}; - n2n_sock_str_t sockbuf; - - 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; - } - - reg.aflags = 0; - memcpy( reg.cookie, eee->last_cookie, N2N_COOKIE_SIZE ); - reg.auth.scheme=0; /* No auth yet */ - reg.timeout = eee->holepunch_interval; - - idx=0; - encode_mac( reg.edgeMac, &idx, eee->device.mac_addr ); - - if(eee->local_sock_ena) { - reg.aflags |= N2N_AFLAGS_LOCAL_SOCKET; - reg.local_sock = eee->local_sock; - } - - idx=0; - encode_REGISTER_SUPER( pktbuf, &idx, &cmn, ® ); - - traceEvent( TRACE_INFO, "send REGISTER_SUPER to %s", - sock_to_cstr( sockbuf, supernode ) ); - - - 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; - 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 ) ); - - - 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 establish_connection( n2n_edge_t * eee, - const n2n_mac_t mac ); -void set_peer_operational( n2n_edge_t * eee, - const n2n_mac_t mac, - const n2n_sock_t * peer ); - - - -/** Start the registration process. - * - * If the peer is already in pending_peers, ignore the request. - * If not in pending_peers, add it and query info about it from supernode - * - * If hdr is for a direct peer-to-peer packet, try to register back to sender - * even if the MAC is in pending_peers. This is because an incident direct - * packet indicates that peer-to-peer exchange should work so more aggressive - * registration can be permitted (once per incoming packet) as this should only - * last for a small number of packets.. - * - * Called from the main loop when Rx a packet for our device mac. - */ -void establish_connection( n2n_edge_t * eee, - const n2n_mac_t mac ) -{ - struct peer_info * scan = find_peer_by_mac( eee->pending_peers, mac ); - macstr_t mac_buf; - n2n_sock_str_t sockbuf; - - if ( NULL == scan ) - { - time_t now = time(NULL); - scan = calloc( 1, sizeof( struct peer_info ) ); - - memcpy(scan->mac_addr, mac, N2N_MAC_SIZE); - scan->num_sockets = 0; - scan->sock = eee->supernode; - scan->last_seen = now; /* Don't change this it marks the pending peer for removal. */ - - sglib_hashed_peer_info_t_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_INFO, "Pending peers list size=%u", - (unsigned int)hashed_peer_list_t_size( eee->pending_peers ) ); - - /* trace Sending REGISTER */ - - send_query_peer(eee, scan->mac_addr); - scan->last_sent_query = now; - - /* pending_peers now owns scan. */ - } - 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) -{ - peer_info_t scan; - memcpy(scan.mac_addr, mac, sizeof(n2n_mac_t)); - - if (sglib_hashed_peer_info_t_find_member(eee->known_peers, &scan) == NULL) - { - /* Not in known_peers - start the REGISTER process. */ - establish_connection( eee, mac ); - } - 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 ) -{ - peer_info_t tmp; - peer_info_t *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 ) ); - - memcpy(tmp.mac_addr, mac, sizeof(n2n_mac_t)); - - scan = sglib_hashed_peer_info_t_find_member(eee->pending_peers, &tmp); - - if(scan) { - /* Remove scan from pending_peers. */ - sglib_hashed_peer_info_t_delete(eee->pending_peers, scan); - - /* Add scan to known_peers. */ - sglib_hashed_peer_info_t_add(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)hashed_peer_list_t_size( eee->pending_peers ) ); - - traceEvent( TRACE_INFO, "Operational peers list size=%u", - (unsigned int)hashed_peer_list_t_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, &tmp); - - if ( scan == NULL ) - { - /* 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. */ - sglib_hashed_peer_info_t_delete(eee->known_peers, scan); - dealloc_peer(scan); - - establish_connection( eee, mac ); - } - else - { - /* Don't worry about what the supernode reports, it could be seeing - * a different socket. */ - /* anyways, the packet came from supernode. That is potential - * trouble... just in case we will send a register back to the - * origin */ - send_register( eee, &(scan->sock), scan->mac_addr ); - } - } - else - { - /* Found and unchanged. */ - if(!from_supernode) - 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 */ - 0x08, 0x06, /* ARP */ - 0x00, 0x01, /* Ethernet */ - 0x08, 0x00, /* IP */ - 0x06, /* Hw Size */ - 0x04, /* Protocol Size */ - 0x00, 0x01, /* ARP Request */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Src mac */ - 0x00, 0x00, 0x00, 0x00, /* Src IP */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Target mac */ - 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) { - if(buffer_len < sizeof(gratuitous_arp)) return(-1); - - memcpy(buffer, gratuitous_arp, sizeof(gratuitous_arp)); - memcpy(&buffer[6], device.mac_addr, 6); - memcpy(&buffer[22], device.mac_addr, 6); - memcpy(&buffer[28], &device.ip_addr, 4); - - /* REVISIT: BbMaj7 - use a real netmask here. This is valid only by accident - * for /24 IPv4 networks. */ - buffer[31] = 0xFF; /* Use a faked broadcast address */ - memcpy(&buffer[38], &device.ip_addr, 4); - return(sizeof(gratuitous_arp)); -} - -/** Called from update_supernode_reg to periodically send gratuitous ARP - * broadcasts. */ -static void send_grat_arps(n2n_edge_t * eee,) { - char buffer[48]; - size_t len; - - traceEvent(TRACE_NORMAL, "Sending gratuitous ARP..."); - len = build_gratuitous_arp(buffer, sizeof(buffer)); - 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->holepunch_interval/10) ) ) ) - { - /* fall through */ - traceEvent( TRACE_DEBUG, "update_supernode_reg: doing fast retry." ); - } - else if ( nowTime < (eee->last_register_req + eee->holepunch_interval)) - { - 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; -} - - -#define RETRY_INTERVAL 5 - - -/* @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) -{ - peer_info_t tmp; - peer_info_t* scan = NULL; - peer_info_t* tryscan = NULL; - macstr_t mac_buf; - n2n_sock_str_t sockbuf; - int retval=0; - int i; - time_t now = time(NULL); - - 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); - - memcpy(tmp.mac_addr, mac_address, sizeof(n2n_mac_t)); - scan = sglib_hashed_peer_info_t_find_member(eee->known_peers, &tmp); - if(scan) { - if(now-scan->last_seen > scan->timeout) { - /* delete the peer and establish new connection */ - sglib_hashed_peer_info_t_delete(eee->known_peers, scan); - establish_connection( eee, scan->mac_addr ); - dealloc_peer(scan); - } else if(scan->last_seen > 0) { - memcpy(destination, &scan->sock, sizeof(n2n_sock_t)); - retval = 1; - } - } - - if ( 0 == retval ) - { - tryscan = sglib_hashed_peer_info_t_find_member(eee->pending_peers, &tmp); - if(tryscan) { - if(tryscan->num_sockets == 0) { - /* not yet received peer_info from supernode */ - if(now - tryscan->last_sent_query > RETRY_INTERVAL) { - send_query_peer(eee, tryscan->mac_addr); - tryscan->last_sent_query = now; - } - } else if(now - tryscan->last_seen > RETRY_INTERVAL) { - traceEvent(TRACE_INFO, "retrying to register peer (%s) -> [%s]", - macaddr_str( mac_buf, mac_address), - sock_to_cstr( sockbuf, &tryscan->sock)); - for(i=0; inum_sockets; i++) - send_register(eee, &tryscan->sockets[i], tryscan->mac_addr); - tryscan->last_seen = now; - } - } - 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[] = { - { "community", required_argument, NULL, 'c' }, - { "supernode-list", required_argument, NULL, 'l' }, - { "tun-device", required_argument, NULL, 'd' }, - { "euid", required_argument, NULL, 'u' }, - { "egid", required_argument, NULL, 'g' }, - { "local-ip", required_argument, NULL, 'L' }, - { "holepunch-interval", required_argument, NULL, 'i' }, - { "help" , no_argument, NULL, 'h' }, - { "verbose", no_argument, NULL, 'v' }, - { NULL, 0, NULL, 0 } -}; - -/* ***************************************************** */ - - -/** 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, - n2n_sock_t * destination) -{ - n2n_sock_str_t sockbuf; - - /* hexdump( pktbuf, pktlen ); */ - - - traceEvent( TRACE_INFO, "send_PACKET to %s", sock_to_cstr( sockbuf, destination ) ); - - 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; - - int dest; - int offset; - n2n_sock_t destination; - - /* 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. */ - uint32_t *src = (uint32_t*)&tap_pkt[ETH_FRAMEHDRSIZE + IP4_SRCOFFSET]; - - /* Note: all elements of the_ip are in network order */ - if( *src != eee->device.ip_addr) { - /* This is a packet that needs to be routed */ - traceEvent(TRACE_INFO, "Discarding routed packet [%s]", - intoa(ntohl(*src), 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 ); - - dest = find_peer_destination(eee, destMac, &destination); - - memset( &pkt, 0, sizeof(pkt) ); - - tx_transop_idx = edge_choose_tx_transop( eee ); - - pkt.transform = eee->transop[tx_transop_idx].transform_id; - - idx=0; - encode_PACKET( pktbuf, &idx, &cmn, &pkt ); - /* make the ethernet-header part of the PACKET header */ - offset = copy_ETHFRAMEHDR( pktbuf+idx , tap_pkt); - idx += offset; - tap_pkt += offset; - len -= offset; - - 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 */ - - if ( dest ) - { - ++(eee->tx_p2p); - eee->tx_bit_p2p += idx; - } - else - { - ++(eee->tx_sup); - eee->tx_bit_sup += idx; - } - send_PACKET( eee, destMac, pktbuf, idx, &destination); -} - - -/** 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; - n2n_ETHFRAMEHDR_t eth; - - 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; - eee->rx_bit_sup += psize; - } - else - { - ++(eee->rx_p2p); - eee->last_p2p=now; - eee->rx_bit_p2p += psize; - } - - decode_ETHFRAMEHDR(ð, payload); - /* Update the sender in peer table entry */ - check_peer( eee, from_supernode, eth.srcMac, orig_sender); - - /* Handle transform. */ - { - uint8_t decodebuffer[N2N_PKT_BUF_SIZE]; - uint8_t * decodebuf = decodebuffer; - size_t eth_size; - size_t rx_transop_idx=0; - int offset; - - /* copy eth header to decodebuf */ - offset = copy_ETHFRAMEHDR(decodebuffer, payload); - decodebuf += offset; - payload += offset; - psize -= offset; - eth_size = offset; - - 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), decodebuffer, 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; - struct sockaddr_in sender_sock; - socklen_t i; - size_t msg_len; - time_t now; - macstr_t mac_buf; - n2n_sock_str_t sockbuf; - peer_info_t * lpi = NULL; - struct sglib_hashed_peer_info_t_iterator it; - int c; - - 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" - " peers List table of known peers\n" - " reload Re-read the keyschedule\n" - " mangle_peer mac ip [port] mangle peer\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 ( 0 == memcmp( udp_buf, "peers", 5 ) ) - { - msg_len = 0; - - msg_len += snprintf( (char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "> known peers (connected edges):\n"); - - traceEvent( TRACE_ERROR, "listing peers on mgmt socket", 0); - sendto( eee->udp_mgmt_sock, udp_buf, msg_len, 0, - (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in) ); - - c = 0; - for(lpi=sglib_hashed_peer_info_t_it_init(&it,eee->known_peers); lpi!=NULL; lpi=sglib_hashed_peer_info_t_it_next(&it)) { - c++; - msg_len = 0; - msg_len += snprintf( (char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "> %i: %s -> %s last: %li\n", c, macaddr_str( mac_buf, lpi->mac_addr ), - sock_to_cstr( sockbuf, &(lpi->sock) ), - lpi->last_seen); - sendto( eee->udp_mgmt_sock, udp_buf, msg_len, 0, - (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), - "> known peers (tried edges):\n"); - sendto( eee->udp_mgmt_sock, udp_buf, msg_len, 0, - (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in) ); - - c = 0; - for(lpi=sglib_hashed_peer_info_t_it_init(&it,eee->pending_peers); lpi!=NULL; lpi=sglib_hashed_peer_info_t_it_next(&it)) { - c++; - msg_len = 0; - if(lpi->num_sockets == 0) - msg_len += snprintf( (char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "> %i: %s -> (no info) last: %li\n", c, - macaddr_str( mac_buf, lpi->mac_addr ), - lpi->last_seen); - else - msg_len += snprintf( (char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "> %i: %s -> %s last: %li\n", c, macaddr_str( mac_buf, lpi->mac_addr ), - sock_to_cstr( sockbuf, lpi->sockets ), - lpi->last_seen); - if(lpi->num_sockets > 1) - msg_len += snprintf( (char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - " %s\n", - sock_to_cstr( sockbuf, lpi->sockets+1 )); - sendto( eee->udp_mgmt_sock, udp_buf, msg_len, 0, - (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; - } - } - } - if ( recvlen >= 12 ) - { - if ( 0 == memcmp (udp_buf, "mangle_peer ", 12) ) - { - int j, n_matched; - n2n_mac_t target_mac; - unsigned int mac[6]; - int ip[4]; - int port; - struct peer_info * scan; - - udp_buf[recvlen] = 0; - n_matched = sscanf((const char *) udp_buf, - "mangle_peer %x:%x:%x:%x:%x:%x %d.%d.%d.%d %d", mac, mac+1, - mac+2, mac+3, mac+4, mac+5, ip, ip+1, ip+2, ip+3, &port); - for( j=0; j<6; j++ ) - target_mac[j] = (uint8_t) mac[j]; - scan = find_peer_by_mac( eee->pending_peers, target_mac ); - if (NULL != scan && n_matched >= 10) { - scan->sock.family = AF_INET; - printf("n_matched: %d, port: %d\n", n_matched, port); - if (n_matched >= 11 && port > 0) - scan->sock.port = (uint16_t) port; - for( j=0; j<4; j++) - scan->sock.addr.v4[j] = (uint8_t) ip[j]; - sendto( eee->udp_mgmt_sock, "success\n", 9, 0, - (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in) ); - } else { - sendto( eee->udp_mgmt_sock, "failure\n", 9, 0, - (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:(tx),(rx) p2p: (tx),(rx)\n"); - msg_len += snprintf( (char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "packets %u,%u %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), - "byte/s %u,%u %u,%u\n", - (unsigned int)eee->tx_bps_sup, - (unsigned int)eee->rx_bps_sup, - (unsigned int)eee->tx_bps_p2p, - (unsigned int)eee->rx_bps_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)hashed_peer_list_t_size( eee->pending_peers ), - (unsigned int)hashed_peer_list_t_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 ); - - - 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; - struct sockaddr_in sender_sock; - n2n_sock_t sender; - n2n_sock_t * orig_sender=NULL; - time_t now=0; - size_t i; - int j; - - /* for PACKET packages */ - n2n_PACKET_t pkt; - - /* for PEER_INFO packages */ - n2n_PEER_INFO_t pi; - struct peer_info * scan; - - /* for REGISTER packages */ - n2n_REGISTER_t reg; - peer_info_t tmp; - - /* for REGISTER_ACK packages */ - n2n_REGISTER_ACK_t ra; - - /* For REGISTER_SUPER_ACK packages */ - n2n_REGISTER_SUPER_ACK_t rsa; - - - 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 */ - - if( 0 == memcmp(cmn.community, eee->community_name, N2N_COMMUNITY_SIZE) ) - { - switch(msg_type) { - case MSG_TYPE_PACKET: - /* process PACKET */ - decode_PACKET( &pkt, &cmn, udp_buf, &rem, &idx ); - - 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 ); - break; - case MSG_TYPE_PEER_INFO: - decode_PEER_INFO( &pi, &cmn, udp_buf, &rem, &idx ); - - scan = find_peer_by_mac( eee->pending_peers, pi.mac ); - if (scan) { - scan->timeout = pi.timeout; - if (scan->num_sockets > 0) - free(scan->sockets); - if (pi.aflags & N2N_AFLAGS_LOCAL_SOCKET) - scan->num_sockets = 2; - else - scan->num_sockets = 1; - scan->sockets = malloc(scan->num_sockets*sizeof(n2n_sock_t)); - for(j=0; jnum_sockets; j++) - scan->sockets[j] = pi.sockets[j]; - traceEvent(TRACE_INFO, "Rx PEER_INFO on %s", - macaddr_str(mac_buf1, pi.mac) ); - for(j=0; jnum_sockets; j++) - send_register(eee, scan->sockets+j, scan->mac_addr); - } else { - traceEvent(TRACE_INFO, "Rx PEER_INFO unknown peer %s", - macaddr_str(mac_buf1, pi.mac) ); - } - - break; - case MSG_TYPE_REGISTER: - /* Another edge is registering with us */ - decode_REGISTER( ®, &cmn, udp_buf, &rem, &idx ); - - 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) ) - { - memcpy(tmp.mac_addr, reg.srcMac, sizeof(n2n_mac_t)); - if (sglib_hashed_peer_info_t_find_member( - eee->pending_peers, &tmp) != NULL) - send_register(eee, orig_sender, NULL); - } - - send_register_ack(eee, orig_sender, ®); - break; - case MSG_TYPE_REGISTER_ACK: - /* Peer edge is acknowledging our register request */ - - 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 ); - break; - case MSG_TYPE_REGISTER_SUPER_ACK: - if ( eee->sn_wait ) - { - decode_REGISTER_SUPER_ACK( &rsa, &cmn, udp_buf, &rem, &idx ); - - if ( rsa.sock.family ) - { - orig_sender = &(rsa.sock); - } - - traceEvent(TRACE_NORMAL, "Rx REGISTER_SUPER_ACK myMAC=%s [%s] (external %s). Attempts %u", - macaddr_str( mac_buf1, rsa.edgeMac ), - sock_to_cstr(sockbuf1, &sender), - sock_to_cstr(sockbuf2, orig_sender), - (unsigned int)eee->sup_attempts ); - - if ( 0 == memcmp( rsa.cookie, eee->last_cookie, N2N_COOKIE_SIZE ) ) - { - if ( rsa.num_sn > 0 ) - { - traceEvent(TRACE_NORMAL, "Rx REGISTER_SUPER_ACK backup supernode at %s", - sock_to_cstr(sockbuf1, &(rsa.sn_bak) ) ); - } - - eee->last_p2p = now; - 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 */ - /* don't adjust lifetime according to supernode - this value should be specified - * by the client (because dependent on NAT/firewall) (lukas) - eee->holepunch_interval = rsa.lifetime; - eee->holepunch_interval = MAX( eee->holepunch_interval, REGISTER_SUPER_INTERVAL_MIN ); - eee->holepunch_interval = MIN( eee->holepunch_interval, 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." ); - } - break; - default: - /* Not a known message type */ - traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored", (signed int)msg_type); - break; - } /* end switch(msg_type) */ - } /* 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 )"); -} - -/** Decode local address string (given on command line) - */ -static int localip2addr(n2n_sock_t * l_ip, - const n2n_local_ip_t local_ip_str, int local_port) -{ - /* TODO: IPv6? */ - unsigned int ip[4]; - int i, n_matches; - - n_matches = sscanf( local_ip_str, "%u.%u.%u.%u", &ip[0], &ip[1], &ip[2], - &ip[3]); - - if( n_matches != 4) { - traceEvent(TRACE_WARNING, "Wrong local_ip parameter (-i ip), disabled"); - return 0; - } - - for( i=0; i < 4; i++ ) { - if( ip[i] > 255 ) { - traceEvent(TRACE_WARNING, "Invalid local_ip address (-i ip), disabled"); - return 0; - } - } - l_ip->family = AF_INET; - l_ip->port = local_port; - for( i = 0; i < 4; i++ ) - l_ip->addr.v4[i] = ip[i]; - return 1; -} - -/* ***************************************************** */ - - -/** Find the address and IP mode for the tuntap device. - * - * s is one of these forms: - * - * := | A.B.C.D - * - * | static: | dhcp: - * - * If the mode is present (colon required) then fill ip_mode with that value - * otherwise do not change ip_mode. Fill ip_mode with everything after the - * colon if it is present; or s if colon is not present. - * - * ip_add and ip_mode are NULL terminated if modified. - * - * 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 ) -{ - int retval = -1; - char * p; - - if ( ( NULL == s ) || ( NULL == ip_addr) ) - { - return -1; - } - - memset(ip_addr, 0, addr_size); - - p = strpbrk(s, ":"); - - if ( p ) - { - /* colon is present */ - if ( ip_mode ) - { - 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; - } - } - else - { - /* colon is not present */ - strncpy( ip_addr, s, 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 */ - -/** 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; - -#ifndef WIN32 - 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; - - int i, effectiveargc=0; - char ** effectiveargv=NULL; - char * linebuffer = NULL; - - n2n_sock_str_t local_sockbuf; - struct sockaddr_in sa; - socklen_t sa_len; - - n2n_edge_t eee; /* single instance for this program */ - - if (-1 == edge_init(&eee) ) - { - traceEvent( TRACE_ERROR, "Failed in edge_init" ); - exit(1); - } - - if( getenv( "N2N_KEY" )) - { - encrypt_key = strdup( getenv( "N2N_KEY" )); - } - -#ifdef WIN32 - tuntap_dev_name[0] = '\0'; -#endif - memset(&(eee.supernode), 0, sizeof(eee.supernode)); - eee.supernode.family = AF_INET; - - linebuffer = (char *)malloc(MAX_CMDLINE_BUFFER_LENGTH); - if (!linebuffer) - { - traceEvent( TRACE_ERROR, "Unable to allocate memory"); - exit(1); - } - snprintf(linebuffer, MAX_CMDLINE_BUFFER_LENGTH, "%s",argv[0]); - -#ifdef WIN32 - for(i=0; i < (int)strlen(linebuffer); i++) - if(linebuffer[i] == '\\') linebuffer[i] = '/'; -#endif - - for(i=1;i 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 'i': /* holepunch-interval */ - { - eee.holepunch_interval = atoi(optarg); - eee.holepunch_interval = MAX( eee.holepunch_interval, REGISTER_SUPER_INTERVAL_MIN ); - eee.holepunch_interval = MIN( eee.holepunch_interval, REGISTER_SUPER_INTERVAL_MAX ); - break; - } - case 'L': /* local ip */ - { - eee.local_sock_ena = 1; - strncpy( eee.local_ip_str, optarg, N2N_EDGE_LOCAL_IP_SIZE); - if ( N2N_EDGE_LOCAL_IP_SIZE > 0 ) - eee.local_ip_str[N2N_EDGE_LOCAL_IP_SIZE - 1] = '\0'; - traceEvent(TRACE_DEBUG, "Storing local_ip_str = %s\n", (eee.sn_ip_array[eee.sn_num]) ); - 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 ) - { - useSyslog=1; /* traceEvent output now goes to syslog. */ - if ( -1 == daemon( 0, 0 ) ) - { - traceEvent( TRACE_ERROR, "Failed to become daemon." ); - exit(-5); - } - } -#endif /* #ifdef N2N_HAVE_DAEMON */ - - - 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]) ); - } - - 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); - } - - } - /* 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); - } - - - if(eee.local_sock_ena) { - sa_len = sizeof(sa); - if ( getsockname(eee.udp_sock, (struct sockaddr *) &sa, &sa_len) == -1 ) { - traceEvent( TRACE_ERROR, "getsockname() failed" ); - return(-1); - } - local_port = ntohs(sa.sin_port); - memset(&(eee.local_sock), 0, sizeof(eee.local_sock)); - - if ( (eee.local_sock_ena = localip2addr( &(eee.local_sock), - eee.local_ip_str, local_port ) ) ) - traceEvent(TRACE_NORMAL, "Local Socket is %s", - sock_to_cstr( local_sockbuf, &(eee.local_sock) ) ); - } - - 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); -} - -static int run_loop(n2n_edge_t * eee ) -{ - int keep_running=1; - size_t numPurged; - time_t lastIfaceCheck=0; - time_t lastTransop=0; - time_t lastStatCalc=0; - time_t lastStatCalcDiff; - - -#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 = 0; - if ((nowTime - eee->last_purge) >= PURGE_REGISTRATION_FREQUENCY) { - numPurged += hashed_purge_expired_registrations(eee->known_peers); - numPurged += hashed_purge_expired_registrations(eee->pending_peers); - eee->last_purge = nowTime; - } - if ( numPurged > 0 ) - { - traceEvent( TRACE_NORMAL, "Peer removed: pending=%u, operational=%u", - (unsigned int)hashed_peer_list_t_size( eee->pending_peers ), - (unsigned int)hashed_peer_list_t_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; - } - - lastStatCalcDiff = nowTime - lastStatCalc; - if(lastStatCalcDiff > STAT_CALC_INTERVAL) { - // traceEvent(TRACE_NORMAL, "recalc bps."); - eee->tx_bps_p2p = eee->tx_bit_p2p / (size_t)lastStatCalcDiff; - eee->tx_bit_p2p = 0; - eee->tx_bps_sup = eee->tx_bit_sup / (size_t)lastStatCalcDiff; - eee->tx_bit_sup = 0; - eee->rx_bps_p2p = eee->rx_bit_p2p / (size_t)lastStatCalcDiff; - eee->rx_bit_p2p = 0; - eee->rx_bps_sup = eee->rx_bit_sup / (size_t)lastStatCalcDiff; - eee->rx_bit_sup = 0; - lastStatCalc = nowTime; - } - - } /* while */ - - send_deregister( eee, &(eee->supernode)); - - closesocket(eee->udp_sock); - tuntap_close(&(eee->device)); - - edge_deinit( eee ); - - return(0); -} - - diff --git a/n2n_v2/lzoconf.h b/n2n_v2/lzoconf.h deleted file mode 100644 index cc437f1..0000000 --- a/n2n_v2/lzoconf.h +++ /dev/null @@ -1,417 +0,0 @@ -/* lzoconf.h -- configuration for the LZO real-time data compression library - - This file is part of the LZO real-time data compression library. - - Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer - All Rights Reserved. - - The LZO library 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 2 of - the License, or (at your option) any later version. - - The LZO library 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 the LZO library; see the file COPYING. - If not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - Markus F.X.J. Oberhumer - - http://www.oberhumer.com/opensource/lzo/ - */ - - -#ifndef __LZOCONF_H_INCLUDED -#define __LZOCONF_H_INCLUDED - -#define LZO_VERSION 0x2030 -#define LZO_VERSION_STRING "2.03" -#define LZO_VERSION_DATE "Apr 30 2008" - -/* internal Autoconf configuration file - only used when building LZO */ -#if defined(LZO_HAVE_CONFIG_H) -# include -#endif -#include -#include - - -/*********************************************************************** -// LZO requires a conforming -************************************************************************/ - -#if !defined(CHAR_BIT) || (CHAR_BIT != 8) -# error "invalid CHAR_BIT" -#endif -#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) -# error "check your compiler installation" -#endif -#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) -# error "your limits.h macros are broken" -#endif - -/* get OS and architecture defines */ -#ifndef __LZODEFS_H_INCLUDED -#include "lzodefs.h" -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - - -/*********************************************************************** -// some core defines -************************************************************************/ - -#if !defined(LZO_UINT32_C) -# if (UINT_MAX < LZO_0xffffffffL) -# define LZO_UINT32_C(c) c ## UL -# else -# define LZO_UINT32_C(c) ((c) + 0U) -# endif -#endif - -/* memory checkers */ -#if !defined(__LZO_CHECKER) -# if defined(__BOUNDS_CHECKING_ON) -# define __LZO_CHECKER 1 -# elif defined(__CHECKER__) -# define __LZO_CHECKER 1 -# elif defined(__INSURE__) -# define __LZO_CHECKER 1 -# elif defined(__PURIFY__) -# define __LZO_CHECKER 1 -# endif -#endif - - -/*********************************************************************** -// integral and pointer types -************************************************************************/ - -/* lzo_uint should match size_t */ -#if !defined(LZO_UINT_MAX) -# if defined(LZO_ABI_LLP64) /* WIN64 */ -# if defined(LZO_OS_WIN64) - typedef unsigned __int64 lzo_uint; - typedef __int64 lzo_int; -# else - typedef unsigned long long lzo_uint; - typedef long long lzo_int; -# endif -# define LZO_UINT_MAX 0xffffffffffffffffull -# define LZO_INT_MAX 9223372036854775807LL -# define LZO_INT_MIN (-1LL - LZO_INT_MAX) -# elif defined(LZO_ABI_IP32L64) /* MIPS R5900 */ - typedef unsigned int lzo_uint; - typedef int lzo_int; -# define LZO_UINT_MAX UINT_MAX -# define LZO_INT_MAX INT_MAX -# define LZO_INT_MIN INT_MIN -# elif (ULONG_MAX >= LZO_0xffffffffL) - typedef unsigned long lzo_uint; - typedef long lzo_int; -# define LZO_UINT_MAX ULONG_MAX -# define LZO_INT_MAX LONG_MAX -# define LZO_INT_MIN LONG_MIN -# else -# error "lzo_uint" -# endif -#endif - -/* Integral types with 32 bits or more. */ -#if !defined(LZO_UINT32_MAX) -# if (UINT_MAX >= LZO_0xffffffffL) - typedef unsigned int lzo_uint32; - typedef int lzo_int32; -# define LZO_UINT32_MAX UINT_MAX -# define LZO_INT32_MAX INT_MAX -# define LZO_INT32_MIN INT_MIN -# elif (ULONG_MAX >= LZO_0xffffffffL) - typedef unsigned long lzo_uint32; - typedef long lzo_int32; -# define LZO_UINT32_MAX ULONG_MAX -# define LZO_INT32_MAX LONG_MAX -# define LZO_INT32_MIN LONG_MIN -# else -# error "lzo_uint32" -# endif -#endif - -/* The larger type of lzo_uint and lzo_uint32. */ -#if (LZO_UINT_MAX >= LZO_UINT32_MAX) -# define lzo_xint lzo_uint -#else -# define lzo_xint lzo_uint32 -#endif - -/* Memory model that allows to access memory at offsets of lzo_uint. */ -#if !defined(__LZO_MMODEL) -# if (LZO_UINT_MAX <= UINT_MAX) -# define __LZO_MMODEL -# elif defined(LZO_HAVE_MM_HUGE_PTR) -# define __LZO_MMODEL_HUGE 1 -# define __LZO_MMODEL __huge -# else -# define __LZO_MMODEL -# endif -#endif - -/* no typedef here because of const-pointer issues */ -#define lzo_bytep unsigned char __LZO_MMODEL * -#define lzo_charp char __LZO_MMODEL * -#define lzo_voidp void __LZO_MMODEL * -#define lzo_shortp short __LZO_MMODEL * -#define lzo_ushortp unsigned short __LZO_MMODEL * -#define lzo_uint32p lzo_uint32 __LZO_MMODEL * -#define lzo_int32p lzo_int32 __LZO_MMODEL * -#define lzo_uintp lzo_uint __LZO_MMODEL * -#define lzo_intp lzo_int __LZO_MMODEL * -#define lzo_xintp lzo_xint __LZO_MMODEL * -#define lzo_voidpp lzo_voidp __LZO_MMODEL * -#define lzo_bytepp lzo_bytep __LZO_MMODEL * -/* deprecated - use `lzo_bytep' instead of `lzo_byte *' */ -#define lzo_byte unsigned char __LZO_MMODEL - -typedef int lzo_bool; - - -/*********************************************************************** -// function types -************************************************************************/ - -/* name mangling */ -#if !defined(__LZO_EXTERN_C) -# ifdef __cplusplus -# define __LZO_EXTERN_C extern "C" -# else -# define __LZO_EXTERN_C extern -# endif -#endif - -/* calling convention */ -#if !defined(__LZO_CDECL) -# define __LZO_CDECL __lzo_cdecl -#endif - -/* DLL export information */ -#if !defined(__LZO_EXPORT1) -# define __LZO_EXPORT1 -#endif -#if !defined(__LZO_EXPORT2) -# define __LZO_EXPORT2 -#endif - -/* __cdecl calling convention for public C and assembly functions */ -#if !defined(LZO_PUBLIC) -# define LZO_PUBLIC(_rettype) __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL -#endif -#if !defined(LZO_EXTERN) -# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype) -#endif -#if !defined(LZO_PRIVATE) -# define LZO_PRIVATE(_rettype) static _rettype __LZO_CDECL -#endif - -/* function types */ -typedef int -(__LZO_CDECL *lzo_compress_t) ( const lzo_bytep src, lzo_uint src_len, - lzo_bytep dst, lzo_uintp dst_len, - lzo_voidp wrkmem ); - -typedef int -(__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint src_len, - lzo_bytep dst, lzo_uintp dst_len, - lzo_voidp wrkmem ); - -typedef int -(__LZO_CDECL *lzo_optimize_t) ( lzo_bytep src, lzo_uint src_len, - lzo_bytep dst, lzo_uintp dst_len, - lzo_voidp wrkmem ); - -typedef int -(__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint src_len, - lzo_bytep dst, lzo_uintp dst_len, - lzo_voidp wrkmem, - const lzo_bytep dict, lzo_uint dict_len ); - -typedef int -(__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint src_len, - lzo_bytep dst, lzo_uintp dst_len, - lzo_voidp wrkmem, - const lzo_bytep dict, lzo_uint dict_len ); - - -/* Callback interface. Currently only the progress indicator ("nprogress") - * is used, but this may change in a future release. */ - -struct lzo_callback_t; -typedef struct lzo_callback_t lzo_callback_t; -#define lzo_callback_p lzo_callback_t __LZO_MMODEL * - -/* malloc & free function types */ -typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t) - (lzo_callback_p self, lzo_uint items, lzo_uint size); -typedef void (__LZO_CDECL *lzo_free_func_t) - (lzo_callback_p self, lzo_voidp ptr); - -/* a progress indicator callback function */ -typedef void (__LZO_CDECL *lzo_progress_func_t) - (lzo_callback_p, lzo_uint, lzo_uint, int); - -struct lzo_callback_t -{ - /* custom allocators (set to 0 to disable) */ - lzo_alloc_func_t nalloc; /* [not used right now] */ - lzo_free_func_t nfree; /* [not used right now] */ - - /* a progress indicator callback function (set to 0 to disable) */ - lzo_progress_func_t nprogress; - - /* NOTE: the first parameter "self" of the nalloc/nfree/nprogress - * callbacks points back to this struct, so you are free to store - * some extra info in the following variables. */ - lzo_voidp user1; - lzo_xint user2; - lzo_xint user3; -}; - - -/*********************************************************************** -// error codes and prototypes -************************************************************************/ - -/* Error codes for the compression/decompression functions. Negative - * values are errors, positive values will be used for special but - * normal events. - */ -#define LZO_E_OK 0 -#define LZO_E_ERROR (-1) -#define LZO_E_OUT_OF_MEMORY (-2) /* [not used right now] */ -#define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */ -#define LZO_E_INPUT_OVERRUN (-4) -#define LZO_E_OUTPUT_OVERRUN (-5) -#define LZO_E_LOOKBEHIND_OVERRUN (-6) -#define LZO_E_EOF_NOT_FOUND (-7) -#define LZO_E_INPUT_NOT_CONSUMED (-8) -#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */ - - -#ifndef lzo_sizeof_dict_t -# define lzo_sizeof_dict_t ((unsigned)sizeof(lzo_bytep)) -#endif - -/* lzo_init() should be the first function you call. - * Check the return code ! - * - * lzo_init() is a macro to allow checking that the library and the - * compiler's view of various types are consistent. - */ -#define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ - (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\ - (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ - (int)sizeof(lzo_callback_t)) -LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int); - -/* version functions (useful for shared libraries) */ -LZO_EXTERN(unsigned) lzo_version(void); -LZO_EXTERN(const char *) lzo_version_string(void); -LZO_EXTERN(const char *) lzo_version_date(void); -LZO_EXTERN(const lzo_charp) _lzo_version_string(void); -LZO_EXTERN(const lzo_charp) _lzo_version_date(void); - -/* string functions */ -LZO_EXTERN(int) -lzo_memcmp(const lzo_voidp _s1, const lzo_voidp _s2, lzo_uint _len); -LZO_EXTERN(lzo_voidp) -lzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); -LZO_EXTERN(lzo_voidp) -lzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); -LZO_EXTERN(lzo_voidp) -lzo_memset(lzo_voidp _s, int _c, lzo_uint _len); - -/* checksum functions */ -LZO_EXTERN(lzo_uint32) -lzo_adler32(lzo_uint32 _adler, const lzo_bytep _buf, lzo_uint _len); -LZO_EXTERN(lzo_uint32) -lzo_crc32(lzo_uint32 _c, const lzo_bytep _buf, lzo_uint _len); -LZO_EXTERN(const lzo_uint32p) -lzo_get_crc32_table(void); - -/* misc. */ -LZO_EXTERN(int) _lzo_config_check(void); -typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u; -typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u; -typedef union { void *vp; lzo_bytep bp; lzo_uint32 u32; long l; } lzo_align_t; - -/* align a char pointer on a boundary that is a multiple of `size' */ -LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp _ptr, lzo_uint _size); -#define LZO_PTR_ALIGN_UP(_ptr,_size) \ - ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size))) - - -/*********************************************************************** -// deprecated macros - only for backward compatibility with LZO v1.xx -************************************************************************/ - -#if defined(LZO_CFG_COMPAT) - -#define __LZOCONF_H 1 - -#if defined(LZO_ARCH_I086) -# define __LZO_i386 1 -#elif defined(LZO_ARCH_I386) -# define __LZO_i386 1 -#endif - -#if defined(LZO_OS_DOS16) -# define __LZO_DOS 1 -# define __LZO_DOS16 1 -#elif defined(LZO_OS_DOS32) -# define __LZO_DOS 1 -#elif defined(LZO_OS_WIN16) -# define __LZO_WIN 1 -# define __LZO_WIN16 1 -#elif defined(LZO_OS_WIN32) -# define __LZO_WIN 1 -#endif - -#define __LZO_CMODEL -#define __LZO_DMODEL -#define __LZO_ENTRY __LZO_CDECL -#define LZO_EXTERN_CDECL LZO_EXTERN -#define LZO_ALIGN LZO_PTR_ALIGN_UP - -#define lzo_compress_asm_t lzo_compress_t -#define lzo_decompress_asm_t lzo_decompress_t - -#endif /* LZO_CFG_COMPAT */ - - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* already included */ - - -/* vim:set ts=4 et: */ diff --git a/n2n_v2/lzodefs.h b/n2n_v2/lzodefs.h deleted file mode 100644 index 1805637..0000000 --- a/n2n_v2/lzodefs.h +++ /dev/null @@ -1,1807 +0,0 @@ -/* lzodefs.h -- architecture, OS and compiler specific defines - - This file is part of the LZO real-time data compression library. - - Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer - All Rights Reserved. - - The LZO library 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 2 of - the License, or (at your option) any later version. - - The LZO library 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 the LZO library; see the file COPYING. - If not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - Markus F.X.J. Oberhumer - - http://www.oberhumer.com/opensource/lzo/ - */ - - -#ifndef __LZODEFS_H_INCLUDED -#define __LZODEFS_H_INCLUDED 1 - -#if defined(__CYGWIN32__) && !defined(__CYGWIN__) -# define __CYGWIN__ __CYGWIN32__ -#endif -#if defined(__IBMCPP__) && !defined(__IBMC__) -# define __IBMC__ __IBMCPP__ -#endif -#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER) -# define __INTEL_COMPILER __ICL -#endif -#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) -# define _ALL_SOURCE 1 -#endif -#if defined(__mips__) && defined(__R5900__) -# if !defined(__LONG_MAX__) -# define __LONG_MAX__ 9223372036854775807L -# endif -#endif -#if defined(__INTEL_COMPILER) && defined(__linux__) -# pragma warning(disable: 193) -#endif -#if defined(__KEIL__) && defined(__C166__) -# pragma warning disable = 322 -#elif 0 && defined(__C251__) -# pragma warning disable = 322 -#endif -#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) -# if (_MSC_VER >= 1300) -# pragma warning(disable: 4668) -# endif -#endif -#if 0 && defined(__WATCOMC__) -# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) -# pragma warning 203 9 -# endif -#endif -#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) -# pragma option -h -#endif -#if 0 -#define LZO_0xffffL 0xfffful -#define LZO_0xffffffffL 0xfffffffful -#else -#define LZO_0xffffL 65535ul -#define LZO_0xffffffffL 4294967295ul -#endif -#if (LZO_0xffffL == LZO_0xffffffffL) -# error "your preprocessor is broken 1" -#endif -#if (16ul * 16384ul != 262144ul) -# error "your preprocessor is broken 2" -#endif -#if 0 -#if (32767 >= 4294967295ul) -# error "your preprocessor is broken 3" -#endif -#if (65535u >= 4294967295ul) -# error "your preprocessor is broken 4" -#endif -#endif -#if (UINT_MAX == LZO_0xffffL) -#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) -# if !defined(MSDOS) -# define MSDOS 1 -# endif -# if !defined(_MSDOS) -# define _MSDOS 1 -# endif -#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) -# if (__VERSION == 520) && (MB_LEN_MAX == 1) -# if !defined(__AZTEC_C__) -# define __AZTEC_C__ __VERSION -# endif -# if !defined(__DOS__) -# define __DOS__ 1 -# endif -# endif -#endif -#endif -#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL) -# define ptrdiff_t long -# define _PTRDIFF_T_DEFINED -#endif -#if (UINT_MAX == LZO_0xffffL) -# undef __LZO_RENAME_A -# undef __LZO_RENAME_B -# if defined(__AZTEC_C__) && defined(__DOS__) -# define __LZO_RENAME_A 1 -# elif defined(_MSC_VER) && defined(MSDOS) -# if (_MSC_VER < 600) -# define __LZO_RENAME_A 1 -# elif (_MSC_VER < 700) -# define __LZO_RENAME_B 1 -# endif -# elif defined(__TSC__) && defined(__OS2__) -# define __LZO_RENAME_A 1 -# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) -# define __LZO_RENAME_A 1 -# elif defined(__PACIFIC__) && defined(DOS) -# if !defined(__far) -# define __far far -# endif -# if !defined(__near) -# define __near near -# endif -# endif -# if defined(__LZO_RENAME_A) -# if !defined(__cdecl) -# define __cdecl cdecl -# endif -# if !defined(__far) -# define __far far -# endif -# if !defined(__huge) -# define __huge huge -# endif -# if !defined(__near) -# define __near near -# endif -# if !defined(__pascal) -# define __pascal pascal -# endif -# if !defined(__huge) -# define __huge huge -# endif -# elif defined(__LZO_RENAME_B) -# if !defined(__cdecl) -# define __cdecl _cdecl -# endif -# if !defined(__far) -# define __far _far -# endif -# if !defined(__huge) -# define __huge _huge -# endif -# if !defined(__near) -# define __near _near -# endif -# if !defined(__pascal) -# define __pascal _pascal -# endif -# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) -# if !defined(__cdecl) -# define __cdecl cdecl -# endif -# if !defined(__pascal) -# define __pascal pascal -# endif -# endif -# undef __LZO_RENAME_A -# undef __LZO_RENAME_B -#endif -#if (UINT_MAX == LZO_0xffffL) -#if defined(__AZTEC_C__) && defined(__DOS__) -# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 -#elif defined(_MSC_VER) && defined(MSDOS) -# if (_MSC_VER < 600) -# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 -# endif -# if (_MSC_VER < 700) -# define LZO_BROKEN_INTEGRAL_PROMOTION 1 -# define LZO_BROKEN_SIZEOF 1 -# endif -#elif defined(__PACIFIC__) && defined(DOS) -# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 -#elif defined(__TURBOC__) && defined(__MSDOS__) -# if (__TURBOC__ < 0x0150) -# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 -# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 -# define LZO_BROKEN_INTEGRAL_PROMOTION 1 -# endif -# if (__TURBOC__ < 0x0200) -# define LZO_BROKEN_SIZEOF 1 -# endif -# if (__TURBOC__ < 0x0400) && defined(__cplusplus) -# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 -# endif -#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) -# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 -# define LZO_BROKEN_SIZEOF 1 -#endif -#endif -#if defined(__WATCOMC__) && (__WATCOMC__ < 900) -# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 -#endif -#if defined(_CRAY) && defined(_CRAY1) -# define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 -#endif -#define LZO_PP_STRINGIZE(x) #x -#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) -#define LZO_PP_CONCAT2(a,b) a ## b -#define LZO_PP_CONCAT3(a,b,c) a ## b ## c -#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d -#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e -#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) -#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) -#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) -#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) -#if 1 -#define LZO_CPP_STRINGIZE(x) #x -#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) -#define LZO_CPP_CONCAT2(a,b) a ## b -#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c -#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d -#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e -#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) -#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) -#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) -#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) -#endif -#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o)) -#if 1 && defined(__cplusplus) -# if !defined(__STDC_CONSTANT_MACROS) -# define __STDC_CONSTANT_MACROS 1 -# endif -# if !defined(__STDC_LIMIT_MACROS) -# define __STDC_LIMIT_MACROS 1 -# endif -#endif -#if defined(__cplusplus) -# define LZO_EXTERN_C extern "C" -#else -# define LZO_EXTERN_C extern -#endif -#if !defined(__LZO_OS_OVERRIDE) -#if defined(LZO_OS_FREESTANDING) -# define LZO_INFO_OS "freestanding" -#elif defined(LZO_OS_EMBEDDED) -# define LZO_INFO_OS "embedded" -#elif 1 && defined(__IAR_SYSTEMS_ICC__) -# define LZO_OS_EMBEDDED 1 -# define LZO_INFO_OS "embedded" -#elif defined(__CYGWIN__) && defined(__GNUC__) -# define LZO_OS_CYGWIN 1 -# define LZO_INFO_OS "cygwin" -#elif defined(__EMX__) && defined(__GNUC__) -# define LZO_OS_EMX 1 -# define LZO_INFO_OS "emx" -#elif defined(__BEOS__) -# define LZO_OS_BEOS 1 -# define LZO_INFO_OS "beos" -#elif defined(__Lynx__) -# define LZO_OS_LYNXOS 1 -# define LZO_INFO_OS "lynxos" -#elif defined(__OS400__) -# define LZO_OS_OS400 1 -# define LZO_INFO_OS "os400" -#elif defined(__QNX__) -# define LZO_OS_QNX 1 -# define LZO_INFO_OS "qnx" -#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) -# define LZO_OS_DOS32 1 -# define LZO_INFO_OS "dos32" -#elif defined(__BORLANDC__) && defined(__DPMI16__) -# define LZO_OS_DOS16 1 -# define LZO_INFO_OS "dos16" -#elif defined(__ZTC__) && defined(DOS386) -# define LZO_OS_DOS32 1 -# define LZO_INFO_OS "dos32" -#elif defined(__OS2__) || defined(__OS2V2__) -# if (UINT_MAX == LZO_0xffffL) -# define LZO_OS_OS216 1 -# define LZO_INFO_OS "os216" -# elif (UINT_MAX == LZO_0xffffffffL) -# define LZO_OS_OS2 1 -# define LZO_INFO_OS "os2" -# else -# error "check your limits.h header" -# endif -#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) -# define LZO_OS_WIN64 1 -# define LZO_INFO_OS "win64" -#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) -# define LZO_OS_WIN32 1 -# define LZO_INFO_OS "win32" -#elif defined(__MWERKS__) && defined(__INTEL__) -# define LZO_OS_WIN32 1 -# define LZO_INFO_OS "win32" -#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) -# if (UINT_MAX == LZO_0xffffL) -# define LZO_OS_WIN16 1 -# define LZO_INFO_OS "win16" -# elif (UINT_MAX == LZO_0xffffffffL) -# define LZO_OS_WIN32 1 -# define LZO_INFO_OS "win32" -# else -# error "check your limits.h header" -# endif -#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) -# if (UINT_MAX == LZO_0xffffL) -# define LZO_OS_DOS16 1 -# define LZO_INFO_OS "dos16" -# elif (UINT_MAX == LZO_0xffffffffL) -# define LZO_OS_DOS32 1 -# define LZO_INFO_OS "dos32" -# else -# error "check your limits.h header" -# endif -#elif defined(__WATCOMC__) -# if defined(__NT__) && (UINT_MAX == LZO_0xffffL) -# define LZO_OS_DOS16 1 -# define LZO_INFO_OS "dos16" -# elif defined(__NT__) && (__WATCOMC__ < 1100) -# define LZO_OS_WIN32 1 -# define LZO_INFO_OS "win32" -# elif defined(__linux__) || defined(__LINUX__) -# define LZO_OS_POSIX 1 -# define LZO_INFO_OS "posix" -# else -# error "please specify a target using the -bt compiler option" -# endif -#elif defined(__palmos__) -# define LZO_OS_PALMOS 1 -# define LZO_INFO_OS "palmos" -#elif defined(__TOS__) || defined(__atarist__) -# define LZO_OS_TOS 1 -# define LZO_INFO_OS "tos" -#elif defined(macintosh) && !defined(__ppc__) -# define LZO_OS_MACCLASSIC 1 -# define LZO_INFO_OS "macclassic" -#elif defined(__VMS) -# define LZO_OS_VMS 1 -# define LZO_INFO_OS "vms" -#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) -# define LZO_OS_CONSOLE 1 -# define LZO_OS_CONSOLE_PS2 1 -# define LZO_INFO_OS "console" -# define LZO_INFO_OS_CONSOLE "ps2" -#elif (defined(__mips__) && defined(__psp__)) -# define LZO_OS_CONSOLE 1 -# define LZO_OS_CONSOLE_PSP 1 -# define LZO_INFO_OS "console" -# define LZO_INFO_OS_CONSOLE "psp" -#else -# define LZO_OS_POSIX 1 -# define LZO_INFO_OS "posix" -#endif -#if (LZO_OS_POSIX) -# if defined(_AIX) || defined(__AIX__) || defined(__aix__) -# define LZO_OS_POSIX_AIX 1 -# define LZO_INFO_OS_POSIX "aix" -# elif defined(__FreeBSD__) -# define LZO_OS_POSIX_FREEBSD 1 -# define LZO_INFO_OS_POSIX "freebsd" -# elif defined(__hpux__) || defined(__hpux) -# define LZO_OS_POSIX_HPUX 1 -# define LZO_INFO_OS_POSIX "hpux" -# elif defined(__INTERIX) -# define LZO_OS_POSIX_INTERIX 1 -# define LZO_INFO_OS_POSIX "interix" -# elif defined(__IRIX__) || defined(__irix__) -# define LZO_OS_POSIX_IRIX 1 -# define LZO_INFO_OS_POSIX "irix" -# elif defined(__linux__) || defined(__linux) || defined(__LINUX__) -# define LZO_OS_POSIX_LINUX 1 -# define LZO_INFO_OS_POSIX "linux" -# elif defined(__APPLE__) || defined(__MACOS__) -# define LZO_OS_POSIX_MACOSX 1 -# define LZO_INFO_OS_POSIX "macosx" -# elif defined(__minix__) || defined(__minix) -# define LZO_OS_POSIX_MINIX 1 -# define LZO_INFO_OS_POSIX "minix" -# elif defined(__NetBSD__) -# define LZO_OS_POSIX_NETBSD 1 -# define LZO_INFO_OS_POSIX "netbsd" -# elif defined(__OpenBSD__) -# define LZO_OS_POSIX_OPENBSD 1 -# define LZO_INFO_OS_POSIX "openbsd" -# elif defined(__osf__) -# define LZO_OS_POSIX_OSF 1 -# define LZO_INFO_OS_POSIX "osf" -# elif defined(__solaris__) || defined(__sun) -# if defined(__SVR4) || defined(__svr4__) -# define LZO_OS_POSIX_SOLARIS 1 -# define LZO_INFO_OS_POSIX "solaris" -# else -# define LZO_OS_POSIX_SUNOS 1 -# define LZO_INFO_OS_POSIX "sunos" -# endif -# elif defined(__ultrix__) || defined(__ultrix) -# define LZO_OS_POSIX_ULTRIX 1 -# define LZO_INFO_OS_POSIX "ultrix" -# elif defined(_UNICOS) -# define LZO_OS_POSIX_UNICOS 1 -# define LZO_INFO_OS_POSIX "unicos" -# else -# define LZO_OS_POSIX_UNKNOWN 1 -# define LZO_INFO_OS_POSIX "unknown" -# endif -#endif -#endif -#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) -# if (UINT_MAX != LZO_0xffffL) -# error "this should not happen" -# endif -# if (ULONG_MAX != LZO_0xffffffffL) -# error "this should not happen" -# endif -#endif -#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) -# if (UINT_MAX != LZO_0xffffffffL) -# error "this should not happen" -# endif -# if (ULONG_MAX != LZO_0xffffffffL) -# error "this should not happen" -# endif -#endif -#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) -# define LZO_CC_CILLY 1 -# define LZO_INFO_CC "Cilly" -# if defined(__CILLY__) -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) -# else -# define LZO_INFO_CCVER "unknown" -# endif -#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) -# define LZO_CC_SDCC 1 -# define LZO_INFO_CC "sdcc" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) -#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) -# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__) -# define LZO_INFO_CC "Pathscale C" -# define LZO_INFO_CCVER __PATHSCALE__ -#elif defined(__INTEL_COMPILER) -# define LZO_CC_INTELC 1 -# define LZO_INFO_CC "Intel C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) -# if defined(_WIN32) || defined(_WIN64) -# define LZO_CC_SYNTAX_MSC 1 -# else -# define LZO_CC_SYNTAX_GNUC 1 -# endif -#elif defined(__POCC__) && defined(_WIN32) -# define LZO_CC_PELLESC 1 -# define LZO_INFO_CC "Pelles C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) -#elif defined(__llvm__) && defined(__GNUC__) && defined(__VERSION__) -# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) -# define LZO_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) -# else -# define LZO_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) -# endif -# define LZO_INFO_CC "llvm-gcc" -# define LZO_INFO_CCVER __VERSION__ -#elif defined(__GNUC__) && defined(__VERSION__) -# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) -# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) -# elif defined(__GNUC_MINOR__) -# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) -# else -# define LZO_CC_GNUC (__GNUC__ * 0x10000L) -# endif -# define LZO_INFO_CC "gcc" -# define LZO_INFO_CCVER __VERSION__ -#elif defined(__ACK__) && defined(_ACK) -# define LZO_CC_ACK 1 -# define LZO_INFO_CC "Amsterdam Compiler Kit C" -# define LZO_INFO_CCVER "unknown" -#elif defined(__AZTEC_C__) -# define LZO_CC_AZTECC 1 -# define LZO_INFO_CC "Aztec C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) -#elif defined(__BORLANDC__) -# define LZO_CC_BORLANDC 1 -# define LZO_INFO_CC "Borland C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) -#elif defined(_CRAYC) && defined(_RELEASE) -# define LZO_CC_CRAYC 1 -# define LZO_INFO_CC "Cray C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) -#elif defined(__DMC__) && defined(__SC__) -# define LZO_CC_DMC 1 -# define LZO_INFO_CC "Digital Mars C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) -#elif defined(__DECC) -# define LZO_CC_DECC 1 -# define LZO_INFO_CC "DEC C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) -#elif defined(__HIGHC__) -# define LZO_CC_HIGHC 1 -# define LZO_INFO_CC "MetaWare High C" -# define LZO_INFO_CCVER "unknown" -#elif defined(__IAR_SYSTEMS_ICC__) -# define LZO_CC_IARC 1 -# define LZO_INFO_CC "IAR C" -# if defined(__VER__) -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) -# else -# define LZO_INFO_CCVER "unknown" -# endif -#elif defined(__IBMC__) -# define LZO_CC_IBMC 1 -# define LZO_INFO_CC "IBM C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) -#elif defined(__KEIL__) && defined(__C166__) -# define LZO_CC_KEILC 1 -# define LZO_INFO_CC "Keil C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) -#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) -# define LZO_CC_LCCWIN32 1 -# define LZO_INFO_CC "lcc-win32" -# define LZO_INFO_CCVER "unknown" -#elif defined(__LCC__) -# define LZO_CC_LCC 1 -# define LZO_INFO_CC "lcc" -# if defined(__LCC_VERSION__) -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) -# else -# define LZO_INFO_CCVER "unknown" -# endif -#elif defined(_MSC_VER) -# define LZO_CC_MSC 1 -# define LZO_INFO_CC "Microsoft C" -# if defined(_MSC_FULL_VER) -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) -# else -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) -# endif -#elif defined(__MWERKS__) -# define LZO_CC_MWERKS 1 -# define LZO_INFO_CC "Metrowerks C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) -#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) -# define LZO_CC_NDPC 1 -# define LZO_INFO_CC "Microway NDP C" -# define LZO_INFO_CCVER "unknown" -#elif defined(__PACIFIC__) -# define LZO_CC_PACIFICC 1 -# define LZO_INFO_CC "Pacific C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) -#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) -# define LZO_CC_PGI 1 -# define LZO_INFO_CC "Portland Group PGI C" -# define LZO_INFO_CCVER "unknown" -#elif defined(__PUREC__) && defined(__TOS__) -# define LZO_CC_PUREC 1 -# define LZO_INFO_CC "Pure C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) -#elif defined(__SC__) && defined(__ZTC__) -# define LZO_CC_SYMANTECC 1 -# define LZO_INFO_CC "Symantec C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) -#elif defined(__SUNPRO_C) -# define LZO_INFO_CC "SunPro C" -# if ((__SUNPRO_C)+0 > 0) -# define LZO_CC_SUNPROC __SUNPRO_C -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) -# else -# define LZO_CC_SUNPROC 1 -# define LZO_INFO_CCVER "unknown" -# endif -#elif defined(__SUNPRO_CC) -# define LZO_INFO_CC "SunPro C" -# if ((__SUNPRO_CC)+0 > 0) -# define LZO_CC_SUNPROC __SUNPRO_CC -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) -# else -# define LZO_CC_SUNPROC 1 -# define LZO_INFO_CCVER "unknown" -# endif -#elif defined(__TINYC__) -# define LZO_CC_TINYC 1 -# define LZO_INFO_CC "Tiny C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) -#elif defined(__TSC__) -# define LZO_CC_TOPSPEEDC 1 -# define LZO_INFO_CC "TopSpeed C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) -#elif defined(__WATCOMC__) -# define LZO_CC_WATCOMC 1 -# define LZO_INFO_CC "Watcom C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) -#elif defined(__TURBOC__) -# define LZO_CC_TURBOC 1 -# define LZO_INFO_CC "Turbo C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) -#elif defined(__ZTC__) -# define LZO_CC_ZORTECHC 1 -# define LZO_INFO_CC "Zortech C" -# if (__ZTC__ == 0x310) -# define LZO_INFO_CCVER "0x310" -# else -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) -# endif -#else -# define LZO_CC_UNKNOWN 1 -# define LZO_INFO_CC "unknown" -# define LZO_INFO_CCVER "unknown" -#endif -#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) -# error "LZO_CC_MSC: _MSC_FULL_VER is not defined" -#endif -#if !defined(__LZO_ARCH_OVERRIDE) && !defined(LZO_ARCH_GENERIC) && defined(_CRAY) -# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) -# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) -# define LZO_ARCH_CRAY_MPP 1 -# elif defined(_CRAY1) -# define LZO_ARCH_CRAY_PVP 1 -# endif -# endif -#endif -#if !defined(__LZO_ARCH_OVERRIDE) -#if defined(LZO_ARCH_GENERIC) -# define LZO_INFO_ARCH "generic" -#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) -# define LZO_ARCH_I086 1 -# define LZO_ARCH_IA16 1 -# define LZO_INFO_ARCH "i086" -#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) -# define LZO_ARCH_ALPHA 1 -# define LZO_INFO_ARCH "alpha" -#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) -# define LZO_ARCH_ALPHA 1 -# define LZO_INFO_ARCH "alpha" -#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) -# define LZO_ARCH_AMD64 1 -# define LZO_INFO_ARCH "amd64" -#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB)) -# define LZO_ARCH_ARM 1 -# define LZO_ARCH_ARM_THUMB 1 -# define LZO_INFO_ARCH "arm_thumb" -#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) -# define LZO_ARCH_ARM 1 -# if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1) -# define LZO_ARCH_ARM_THUMB 1 -# define LZO_INFO_ARCH "arm_thumb" -# elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2) -# define LZO_INFO_ARCH "arm" -# else -# define LZO_INFO_ARCH "arm" -# endif -#elif defined(__arm__) || defined(_M_ARM) -# define LZO_ARCH_ARM 1 -# define LZO_INFO_ARCH "arm" -#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) -# define LZO_ARCH_AVR 1 -# define LZO_INFO_ARCH "avr" -#elif defined(__bfin__) -# define LZO_ARCH_BLACKFIN 1 -# define LZO_INFO_ARCH "blackfin" -#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) -# define LZO_ARCH_C166 1 -# define LZO_INFO_ARCH "c166" -#elif defined(__cris__) -# define LZO_ARCH_CRIS 1 -# define LZO_INFO_ARCH "cris" -#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) -# define LZO_ARCH_EZ80 1 -# define LZO_INFO_ARCH "ez80" -#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) -# define LZO_ARCH_H8300 1 -# define LZO_INFO_ARCH "h8300" -#elif defined(__hppa__) || defined(__hppa) -# define LZO_ARCH_HPPA 1 -# define LZO_INFO_ARCH "hppa" -#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) -# define LZO_ARCH_I386 1 -# define LZO_ARCH_IA32 1 -# define LZO_INFO_ARCH "i386" -#elif (LZO_CC_ZORTECHC && defined(__I86__)) -# define LZO_ARCH_I386 1 -# define LZO_ARCH_IA32 1 -# define LZO_INFO_ARCH "i386" -#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) -# define LZO_ARCH_I386 1 -# define LZO_ARCH_IA32 1 -# define LZO_INFO_ARCH "i386" -#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) -# define LZO_ARCH_IA64 1 -# define LZO_INFO_ARCH "ia64" -#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) -# define LZO_ARCH_M16C 1 -# define LZO_INFO_ARCH "m16c" -#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) -# define LZO_ARCH_M16C 1 -# define LZO_INFO_ARCH "m16c" -#elif defined(__m32r__) -# define LZO_ARCH_M32R 1 -# define LZO_INFO_ARCH "m32r" -#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) -# define LZO_ARCH_M68K 1 -# define LZO_INFO_ARCH "m68k" -#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) -# define LZO_ARCH_MCS251 1 -# define LZO_INFO_ARCH "mcs251" -#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) -# define LZO_ARCH_MCS51 1 -# define LZO_INFO_ARCH "mcs51" -#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) -# define LZO_ARCH_MCS51 1 -# define LZO_INFO_ARCH "mcs51" -#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) -# define LZO_ARCH_MIPS 1 -# define LZO_INFO_ARCH "mips" -#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) -# define LZO_ARCH_MSP430 1 -# define LZO_INFO_ARCH "msp430" -#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) -# define LZO_ARCH_MSP430 1 -# define LZO_INFO_ARCH "msp430" -#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) -# define LZO_ARCH_POWERPC 1 -# define LZO_INFO_ARCH "powerpc" -#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) -# define LZO_ARCH_S390 1 -# define LZO_INFO_ARCH "s390" -#elif defined(__sh__) || defined(_M_SH) -# define LZO_ARCH_SH 1 -# define LZO_INFO_ARCH "sh" -#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) -# define LZO_ARCH_SPARC 1 -# define LZO_INFO_ARCH "sparc" -#elif defined(__SPU__) -# define LZO_ARCH_SPU 1 -# define LZO_INFO_ARCH "spu" -#elif (UINT_MAX == LZO_0xffffL) && defined(__z80) -# define LZO_ARCH_Z80 1 -# define LZO_INFO_ARCH "z80" -#elif (LZO_ARCH_CRAY_PVP) -# if defined(_CRAYSV1) -# define LZO_ARCH_CRAY_SV1 1 -# define LZO_INFO_ARCH "cray_sv1" -# elif (_ADDR64) -# define LZO_ARCH_CRAY_T90 1 -# define LZO_INFO_ARCH "cray_t90" -# elif (_ADDR32) -# define LZO_ARCH_CRAY_YMP 1 -# define LZO_INFO_ARCH "cray_ymp" -# else -# define LZO_ARCH_CRAY_XMP 1 -# define LZO_INFO_ARCH "cray_xmp" -# endif -#else -# define LZO_ARCH_UNKNOWN 1 -# define LZO_INFO_ARCH "unknown" -#endif -#endif -#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) -# error "FIXME - missing define for CPU architecture" -#endif -#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) -# error "FIXME - missing WIN32 define for CPU architecture" -#endif -#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) -# error "FIXME - missing WIN64 define for CPU architecture" -#endif -#if (LZO_OS_OS216 || LZO_OS_WIN16) -# define LZO_ARCH_I086PM 1 -# define LZO_ARCH_IA16PM 1 -#elif 1 && (LZO_OS_DOS16 && defined(BLX286)) -# define LZO_ARCH_I086PM 1 -# define LZO_ARCH_IA16PM 1 -#elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) -# define LZO_ARCH_I086PM 1 -# define LZO_ARCH_IA16PM 1 -#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) -# define LZO_ARCH_I086PM 1 -# define LZO_ARCH_IA16PM 1 -#endif -#if defined(LZO_ARCH_ARM_THUMB) && !defined(LZO_ARCH_ARM) -# error "this should not happen" -#endif -#if defined(LZO_ARCH_I086PM) && !defined(LZO_ARCH_I086) -# error "this should not happen" -#endif -#if (LZO_ARCH_I086) -# if (UINT_MAX != LZO_0xffffL) -# error "this should not happen" -# endif -# if (ULONG_MAX != LZO_0xffffffffL) -# error "this should not happen" -# endif -#endif -#if (LZO_ARCH_I386) -# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) -# error "this should not happen" -# endif -# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) -# error "this should not happen" -# endif -# if (ULONG_MAX != LZO_0xffffffffL) -# error "this should not happen" -# endif -#endif -#if !defined(__LZO_MM_OVERRIDE) -#if (LZO_ARCH_I086) -#if (UINT_MAX != LZO_0xffffL) -# error "this should not happen" -#endif -#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) -# define LZO_MM_TINY 1 -#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) -# define LZO_MM_HUGE 1 -#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) -# define LZO_MM_SMALL 1 -#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) -# define LZO_MM_MEDIUM 1 -#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) -# define LZO_MM_COMPACT 1 -#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) -# define LZO_MM_LARGE 1 -#elif (LZO_CC_AZTECC) -# if defined(_LARGE_CODE) && defined(_LARGE_DATA) -# define LZO_MM_LARGE 1 -# elif defined(_LARGE_CODE) -# define LZO_MM_MEDIUM 1 -# elif defined(_LARGE_DATA) -# define LZO_MM_COMPACT 1 -# else -# define LZO_MM_SMALL 1 -# endif -#elif (LZO_CC_ZORTECHC && defined(__VCM__)) -# define LZO_MM_LARGE 1 -#else -# error "unknown memory model" -#endif -#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) -#define LZO_HAVE_MM_HUGE_PTR 1 -#define LZO_HAVE_MM_HUGE_ARRAY 1 -#if (LZO_MM_TINY) -# undef LZO_HAVE_MM_HUGE_ARRAY -#endif -#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) -# undef LZO_HAVE_MM_HUGE_PTR -# undef LZO_HAVE_MM_HUGE_ARRAY -#elif (LZO_CC_DMC || LZO_CC_SYMANTECC) -# undef LZO_HAVE_MM_HUGE_ARRAY -#elif (LZO_CC_MSC && defined(_QC)) -# undef LZO_HAVE_MM_HUGE_ARRAY -# if (_MSC_VER < 600) -# undef LZO_HAVE_MM_HUGE_PTR -# endif -#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) -# undef LZO_HAVE_MM_HUGE_ARRAY -#endif -#if (LZO_ARCH_I086PM) && !defined(LZO_HAVE_MM_HUGE_PTR) -# if (LZO_OS_DOS16) -# error "this should not happen" -# elif (LZO_CC_ZORTECHC) -# else -# error "this should not happen" -# endif -#endif -#ifdef __cplusplus -extern "C" { -#endif -#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) - extern void __near __cdecl _AHSHIFT(void); -# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) -#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) - extern void __near __cdecl _AHSHIFT(void); -# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) -#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) - extern void __near __cdecl _AHSHIFT(void); -# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) -#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) - extern void __near __cdecl _AHSHIFT(void); -# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) -#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) -# define LZO_MM_AHSHIFT 12 -#elif (LZO_CC_WATCOMC) - extern unsigned char _HShift; -# define LZO_MM_AHSHIFT ((unsigned) _HShift) -#else -# error "FIXME - implement LZO_MM_AHSHIFT" -#endif -#ifdef __cplusplus -} -#endif -#endif -#elif (LZO_ARCH_C166) -#if !defined(__MODEL__) -# error "FIXME - C166 __MODEL__" -#elif ((__MODEL__) == 0) -# define LZO_MM_SMALL 1 -#elif ((__MODEL__) == 1) -# define LZO_MM_SMALL 1 -#elif ((__MODEL__) == 2) -# define LZO_MM_LARGE 1 -#elif ((__MODEL__) == 3) -# define LZO_MM_TINY 1 -#elif ((__MODEL__) == 4) -# define LZO_MM_XTINY 1 -#elif ((__MODEL__) == 5) -# define LZO_MM_XSMALL 1 -#else -# error "FIXME - C166 __MODEL__" -#endif -#elif (LZO_ARCH_MCS251) -#if !defined(__MODEL__) -# error "FIXME - MCS251 __MODEL__" -#elif ((__MODEL__) == 0) -# define LZO_MM_SMALL 1 -#elif ((__MODEL__) == 2) -# define LZO_MM_LARGE 1 -#elif ((__MODEL__) == 3) -# define LZO_MM_TINY 1 -#elif ((__MODEL__) == 4) -# define LZO_MM_XTINY 1 -#elif ((__MODEL__) == 5) -# define LZO_MM_XSMALL 1 -#else -# error "FIXME - MCS251 __MODEL__" -#endif -#elif (LZO_ARCH_MCS51) -#if !defined(__MODEL__) -# error "FIXME - MCS51 __MODEL__" -#elif ((__MODEL__) == 1) -# define LZO_MM_SMALL 1 -#elif ((__MODEL__) == 2) -# define LZO_MM_LARGE 1 -#elif ((__MODEL__) == 3) -# define LZO_MM_TINY 1 -#elif ((__MODEL__) == 4) -# define LZO_MM_XTINY 1 -#elif ((__MODEL__) == 5) -# define LZO_MM_XSMALL 1 -#else -# error "FIXME - MCS51 __MODEL__" -#endif -#elif (LZO_ARCH_CRAY_PVP) -# define LZO_MM_PVP 1 -#else -# define LZO_MM_FLAT 1 -#endif -#if (LZO_MM_COMPACT) -# define LZO_INFO_MM "compact" -#elif (LZO_MM_FLAT) -# define LZO_INFO_MM "flat" -#elif (LZO_MM_HUGE) -# define LZO_INFO_MM "huge" -#elif (LZO_MM_LARGE) -# define LZO_INFO_MM "large" -#elif (LZO_MM_MEDIUM) -# define LZO_INFO_MM "medium" -#elif (LZO_MM_PVP) -# define LZO_INFO_MM "pvp" -#elif (LZO_MM_SMALL) -# define LZO_INFO_MM "small" -#elif (LZO_MM_TINY) -# define LZO_INFO_MM "tiny" -#else -# error "unknown memory model" -#endif -#endif -#if defined(SIZEOF_SHORT) -# define LZO_SIZEOF_SHORT (SIZEOF_SHORT) -#endif -#if defined(SIZEOF_INT) -# define LZO_SIZEOF_INT (SIZEOF_INT) -#endif -#if defined(SIZEOF_LONG) -# define LZO_SIZEOF_LONG (SIZEOF_LONG) -#endif -#if defined(SIZEOF_LONG_LONG) -# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) -#endif -#if defined(SIZEOF___INT16) -# define LZO_SIZEOF___INT16 (SIZEOF___INT16) -#endif -#if defined(SIZEOF___INT32) -# define LZO_SIZEOF___INT32 (SIZEOF___INT32) -#endif -#if defined(SIZEOF___INT64) -# define LZO_SIZEOF___INT64 (SIZEOF___INT64) -#endif -#if defined(SIZEOF_VOID_P) -# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) -#endif -#if defined(SIZEOF_SIZE_T) -# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) -#endif -#if defined(SIZEOF_PTRDIFF_T) -# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) -#endif -#define __LZO_LSR(x,b) (((x)+0ul) >> (b)) -#if !defined(LZO_SIZEOF_SHORT) -# if (LZO_ARCH_CRAY_PVP) -# define LZO_SIZEOF_SHORT 8 -# elif (USHRT_MAX == LZO_0xffffL) -# define LZO_SIZEOF_SHORT 2 -# elif (__LZO_LSR(USHRT_MAX,7) == 1) -# define LZO_SIZEOF_SHORT 1 -# elif (__LZO_LSR(USHRT_MAX,15) == 1) -# define LZO_SIZEOF_SHORT 2 -# elif (__LZO_LSR(USHRT_MAX,31) == 1) -# define LZO_SIZEOF_SHORT 4 -# elif (__LZO_LSR(USHRT_MAX,63) == 1) -# define LZO_SIZEOF_SHORT 8 -# elif (__LZO_LSR(USHRT_MAX,127) == 1) -# define LZO_SIZEOF_SHORT 16 -# else -# error "LZO_SIZEOF_SHORT" -# endif -#endif -#if !defined(LZO_SIZEOF_INT) -# if (LZO_ARCH_CRAY_PVP) -# define LZO_SIZEOF_INT 8 -# elif (UINT_MAX == LZO_0xffffL) -# define LZO_SIZEOF_INT 2 -# elif (UINT_MAX == LZO_0xffffffffL) -# define LZO_SIZEOF_INT 4 -# elif (__LZO_LSR(UINT_MAX,7) == 1) -# define LZO_SIZEOF_INT 1 -# elif (__LZO_LSR(UINT_MAX,15) == 1) -# define LZO_SIZEOF_INT 2 -# elif (__LZO_LSR(UINT_MAX,31) == 1) -# define LZO_SIZEOF_INT 4 -# elif (__LZO_LSR(UINT_MAX,63) == 1) -# define LZO_SIZEOF_INT 8 -# elif (__LZO_LSR(UINT_MAX,127) == 1) -# define LZO_SIZEOF_INT 16 -# else -# error "LZO_SIZEOF_INT" -# endif -#endif -#if !defined(LZO_SIZEOF_LONG) -# if (ULONG_MAX == LZO_0xffffffffL) -# define LZO_SIZEOF_LONG 4 -# elif (__LZO_LSR(ULONG_MAX,7) == 1) -# define LZO_SIZEOF_LONG 1 -# elif (__LZO_LSR(ULONG_MAX,15) == 1) -# define LZO_SIZEOF_LONG 2 -# elif (__LZO_LSR(ULONG_MAX,31) == 1) -# define LZO_SIZEOF_LONG 4 -# elif (__LZO_LSR(ULONG_MAX,63) == 1) -# define LZO_SIZEOF_LONG 8 -# elif (__LZO_LSR(ULONG_MAX,127) == 1) -# define LZO_SIZEOF_LONG 16 -# else -# error "LZO_SIZEOF_LONG" -# endif -#endif -#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) -#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) -# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) -# if (LZO_CC_GNUC >= 0x030300ul) -# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0) -# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG -# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) -# define LZO_SIZEOF_LONG_LONG 4 -# endif -# endif -# endif -#endif -#endif -#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) -#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) -#if (LZO_ARCH_I086 && LZO_CC_DMC) -#elif (LZO_CC_CILLY) && defined(__GNUC__) -# define LZO_SIZEOF_LONG_LONG 8 -#elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define LZO_SIZEOF_LONG_LONG 8 -#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) -# define LZO_SIZEOF_LONG_LONG 8 -#elif (LZO_OS_WIN64 || defined(_WIN64)) -# define LZO_SIZEOF___INT64 8 -#elif (LZO_ARCH_I386 && (LZO_CC_DMC)) -# define LZO_SIZEOF_LONG_LONG 8 -#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) -# define LZO_SIZEOF_LONG_LONG 8 -#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) -# define LZO_SIZEOF_LONG_LONG 8 -#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) -# define LZO_SIZEOF_LONG_LONG 8 -#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) -# define LZO_SIZEOF___INT64 8 -#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) -# define LZO_SIZEOF___INT64 8 -#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) -# define LZO_SIZEOF___INT64 8 -#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) -# define LZO_SIZEOF___INT64 8 -#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64)) -# define LZO_SIZEOF___INT64 8 -#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) -# define LZO_SIZEOF_LONG_LONG 8 -#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) -# define LZO_SIZEOF_LONG_LONG 8 -#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) -#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -# define LZO_SIZEOF_LONG_LONG 8 -#endif -#endif -#endif -#if defined(__cplusplus) && defined(LZO_CC_GNUC) -# if (LZO_CC_GNUC < 0x020800ul) -# undef LZO_SIZEOF_LONG_LONG -# endif -#endif -#if defined(LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG) -# undef LZO_SIZEOF_LONG_LONG -#endif -#if !defined(LZO_SIZEOF_VOID_P) -#if (LZO_ARCH_I086) -# define __LZO_WORDSIZE 2 -# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) -# define LZO_SIZEOF_VOID_P 2 -# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) -# define LZO_SIZEOF_VOID_P 4 -# else -# error "LZO_MM" -# endif -#elif (LZO_ARCH_AVR || LZO_ARCH_Z80) -# define __LZO_WORDSIZE 1 -# define LZO_SIZEOF_VOID_P 2 -#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) -# define LZO_SIZEOF_VOID_P 2 -#elif (LZO_ARCH_H8300) -# if defined(__NORMAL_MODE__) -# define __LZO_WORDSIZE 4 -# define LZO_SIZEOF_VOID_P 2 -# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) -# define __LZO_WORDSIZE 4 -# define LZO_SIZEOF_VOID_P 4 -# else -# define __LZO_WORDSIZE 2 -# define LZO_SIZEOF_VOID_P 2 -# endif -# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) -# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT -# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT -# endif -#elif (LZO_ARCH_M16C) -# define __LZO_WORDSIZE 2 -# if defined(__m32c_cpu__) || defined(__m32cm_cpu__) -# define LZO_SIZEOF_VOID_P 4 -# else -# define LZO_SIZEOF_VOID_P 2 -# endif -#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) -# define __LZO_WORDSIZE 8 -# define LZO_SIZEOF_VOID_P 4 -#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) -# define __LZO_WORDSIZE 8 -# define LZO_SIZEOF_VOID_P 8 -#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) -# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG -# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG -# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG -#elif (LZO_OS_OS400 || defined(__OS400__)) -# define __LZO_WORDSIZE LZO_SIZEOF_LONG -# define LZO_SIZEOF_VOID_P 16 -# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG -# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG -#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) -# define LZO_SIZEOF_VOID_P 8 -# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG -# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG -#elif (LZO_ARCH_SPU) -# if 0 -# define __LZO_WORDSIZE 16 -# endif -# define LZO_SIZEOF_VOID_P 4 -#else -# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG -#endif -#endif -#if !defined(LZO_WORDSIZE) -# if defined(__LZO_WORDSIZE) -# define LZO_WORDSIZE __LZO_WORDSIZE -# else -# define LZO_WORDSIZE LZO_SIZEOF_VOID_P -# endif -#endif -#if !defined(LZO_SIZEOF_SIZE_T) -#if (LZO_ARCH_I086 || LZO_ARCH_M16C) -# define LZO_SIZEOF_SIZE_T 2 -#else -# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P -#endif -#endif -#if !defined(LZO_SIZEOF_PTRDIFF_T) -#if (LZO_ARCH_I086) -# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) -# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P -# elif (LZO_MM_COMPACT || LZO_MM_LARGE) -# if (LZO_CC_BORLANDC || LZO_CC_TURBOC) -# define LZO_SIZEOF_PTRDIFF_T 4 -# else -# define LZO_SIZEOF_PTRDIFF_T 2 -# endif -# else -# error "LZO_MM" -# endif -#else -# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T -#endif -#endif -#if defined(LZO_ABI_NEUTRAL_ENDIAN) -# undef LZO_ABI_BIG_ENDIAN -# undef LZO_ABI_LITTLE_ENDIAN -#elif !defined(LZO_ABI_BIG_ENDIAN) && !defined(LZO_ABI_LITTLE_ENDIAN) -#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) -# define LZO_ABI_BIG_ENDIAN 1 -#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430) -# define LZO_ABI_LITTLE_ENDIAN 1 -#elif (LZO_ARCH_M68K || LZO_ARCH_S390) -# define LZO_ABI_BIG_ENDIAN 1 -#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) -# if (__LITTLE_ENDIAN__ == 1) -# define LZO_ABI_LITTLE_ENDIAN 1 -# else -# define LZO_ABI_BIG_ENDIAN 1 -# endif -#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) -# define LZO_ABI_BIG_ENDIAN 1 -#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) -# define LZO_ABI_LITTLE_ENDIAN 1 -#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) -# define LZO_ABI_BIG_ENDIAN 1 -#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) -# define LZO_ABI_LITTLE_ENDIAN 1 -#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) -# define LZO_ABI_BIG_ENDIAN 1 -#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) -# define LZO_ABI_LITTLE_ENDIAN 1 -#endif -#endif -#if defined(LZO_ABI_BIG_ENDIAN) && defined(LZO_ABI_LITTLE_ENDIAN) -# error "this should not happen" -#endif -#if defined(LZO_ABI_BIG_ENDIAN) -# define LZO_INFO_ABI_ENDIAN "be" -#elif defined(LZO_ABI_LITTLE_ENDIAN) -# define LZO_INFO_ABI_ENDIAN "le" -#elif defined(LZO_ABI_NEUTRAL_ENDIAN) -# define LZO_INFO_ABI_ENDIAN "neutral" -#endif -#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) -# define LZO_ABI_I8LP16 1 -# define LZO_INFO_ABI_PM "i8lp16" -#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) -# define LZO_ABI_ILP16 1 -# define LZO_INFO_ABI_PM "ilp16" -#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) -# define LZO_ABI_ILP32 1 -# define LZO_INFO_ABI_PM "ilp32" -#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) -# define LZO_ABI_LLP64 1 -# define LZO_INFO_ABI_PM "llp64" -#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) -# define LZO_ABI_LP64 1 -# define LZO_INFO_ABI_PM "lp64" -#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) -# define LZO_ABI_ILP64 1 -# define LZO_INFO_ABI_PM "ilp64" -#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) -# define LZO_ABI_IP32L64 1 -# define LZO_INFO_ABI_PM "ip32l64" -#endif -#if !defined(__LZO_LIBC_OVERRIDE) -#if defined(LZO_LIBC_NAKED) -# define LZO_INFO_LIBC "naked" -#elif defined(LZO_LIBC_FREESTANDING) -# define LZO_INFO_LIBC "freestanding" -#elif defined(LZO_LIBC_MOSTLY_FREESTANDING) -# define LZO_INFO_LIBC "mfreestanding" -#elif defined(LZO_LIBC_ISOC90) -# define LZO_INFO_LIBC "isoc90" -#elif defined(LZO_LIBC_ISOC99) -# define LZO_INFO_LIBC "isoc99" -#elif defined(__dietlibc__) -# define LZO_LIBC_DIETLIBC 1 -# define LZO_INFO_LIBC "dietlibc" -#elif defined(_NEWLIB_VERSION) -# define LZO_LIBC_NEWLIB 1 -# define LZO_INFO_LIBC "newlib" -#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) -# if defined(__UCLIBC_SUBLEVEL__) -# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__) -# else -# define LZO_LIBC_UCLIBC 0x00090bL -# endif -# define LZO_INFO_LIBC "uclibc" -#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) -# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100) -# define LZO_INFO_LIBC "glibc" -#elif (LZO_CC_MWERKS) && defined(__MSL__) -# define LZO_LIBC_MSL __MSL__ -# define LZO_INFO_LIBC "msl" -#elif 1 && defined(__IAR_SYSTEMS_ICC__) -# define LZO_LIBC_ISOC90 1 -# define LZO_INFO_LIBC "isoc90" -#else -# define LZO_LIBC_DEFAULT 1 -# define LZO_INFO_LIBC "default" -#endif -#endif -#if !defined(__lzo_gnuc_extension__) -#if (LZO_CC_GNUC >= 0x020800ul) -# define __lzo_gnuc_extension__ __extension__ -#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_gnuc_extension__ __extension__ -#else -# define __lzo_gnuc_extension__ -#endif -#endif -#if !defined(__lzo_ua_volatile) -# define __lzo_ua_volatile volatile -#endif -#if !defined(__lzo_alignof) -#if (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) -# define __lzo_alignof(e) __alignof__(e) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) -# define __lzo_alignof(e) __alignof__(e) -#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) -# define __lzo_alignof(e) __alignof(e) -#endif -#endif -#if defined(__lzo_alignof) -# define __lzo_HAVE_alignof 1 -#endif -#if !defined(__lzo_constructor) -#if (LZO_CC_GNUC >= 0x030400ul) -# define __lzo_constructor __attribute__((__constructor__,__used__)) -#elif (LZO_CC_GNUC >= 0x020700ul) -# define __lzo_constructor __attribute__((__constructor__)) -#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_constructor __attribute__((__constructor__)) -#endif -#endif -#if defined(__lzo_constructor) -# define __lzo_HAVE_constructor 1 -#endif -#if !defined(__lzo_destructor) -#if (LZO_CC_GNUC >= 0x030400ul) -# define __lzo_destructor __attribute__((__destructor__,__used__)) -#elif (LZO_CC_GNUC >= 0x020700ul) -# define __lzo_destructor __attribute__((__destructor__)) -#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_destructor __attribute__((__destructor__)) -#endif -#endif -#if defined(__lzo_destructor) -# define __lzo_HAVE_destructor 1 -#endif -#if defined(__lzo_HAVE_destructor) && !defined(__lzo_HAVE_constructor) -# error "this should not happen" -#endif -#if !defined(__lzo_inline) -#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) -#elif defined(__cplusplus) -# define __lzo_inline inline -#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) -# define __lzo_inline __inline -#elif (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) -# define __lzo_inline __inline__ -#elif (LZO_CC_DMC) -# define __lzo_inline __inline -#elif (LZO_CC_INTELC) -# define __lzo_inline __inline -#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) -# define __lzo_inline __inline -#elif (LZO_CC_MSC && (_MSC_VER >= 900)) -# define __lzo_inline __inline -#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -# define __lzo_inline inline -#endif -#endif -#if defined(__lzo_inline) -# define __lzo_HAVE_inline 1 -#else -# define __lzo_inline -#endif -#if !defined(__lzo_forceinline) -#if (LZO_CC_GNUC >= 0x030200ul) -# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) -# define __lzo_forceinline __forceinline -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) -# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) -#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) -#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) -# define __lzo_forceinline __forceinline -#endif -#endif -#if defined(__lzo_forceinline) -# define __lzo_HAVE_forceinline 1 -#else -# define __lzo_forceinline -#endif -#if !defined(__lzo_noinline) -#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) -# define __lzo_noinline __attribute__((__noinline__,__used__)) -#elif (LZO_CC_GNUC >= 0x030200ul) -# define __lzo_noinline __attribute__((__noinline__)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_MSC) -# define __lzo_noinline __declspec(noinline) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) -# define __lzo_noinline __attribute__((__noinline__)) -#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_noinline __attribute__((__noinline__)) -#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) -# define __lzo_noinline __declspec(noinline) -#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) -# if defined(__cplusplus) -# else -# define __lzo_noinline __declspec(noinline) -# endif -#endif -#endif -#if defined(__lzo_noinline) -# define __lzo_HAVE_noinline 1 -#else -# define __lzo_noinline -#endif -#if (defined(__lzo_HAVE_forceinline) || defined(__lzo_HAVE_noinline)) && !defined(__lzo_HAVE_inline) -# error "this should not happen" -#endif -#if !defined(__lzo_noreturn) -#if (LZO_CC_GNUC >= 0x020700ul) -# define __lzo_noreturn __attribute__((__noreturn__)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) -# define __lzo_noreturn __declspec(noreturn) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) -# define __lzo_noreturn __attribute__((__noreturn__)) -#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_noreturn __attribute__((__noreturn__)) -#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) -# define __lzo_noreturn __declspec(noreturn) -#endif -#endif -#if defined(__lzo_noreturn) -# define __lzo_HAVE_noreturn 1 -#else -# define __lzo_noreturn -#endif -#if !defined(__lzo_nothrow) -#if (LZO_CC_GNUC >= 0x030300ul) -# define __lzo_nothrow __attribute__((__nothrow__)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) && defined(__cplusplus) -# define __lzo_nothrow __declspec(nothrow) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) -# define __lzo_nothrow __attribute__((__nothrow__)) -#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_nothrow __attribute__((__nothrow__)) -#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) -# define __lzo_nothrow __declspec(nothrow) -#endif -#endif -#if defined(__lzo_nothrow) -# define __lzo_HAVE_nothrow 1 -#else -# define __lzo_nothrow -#endif -#if !defined(__lzo_restrict) -#if (LZO_CC_GNUC >= 0x030400ul) -# define __lzo_restrict __restrict__ -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) -# define __lzo_restrict __restrict__ -#elif (LZO_CC_LLVM) -# define __lzo_restrict __restrict__ -#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) -# define __lzo_restrict __restrict -#endif -#endif -#if defined(__lzo_restrict) -# define __lzo_HAVE_restrict 1 -#else -# define __lzo_restrict -#endif -#if !defined(__lzo_likely) && !defined(__lzo_unlikely) -#if (LZO_CC_GNUC >= 0x030200ul) -# define __lzo_likely(e) (__builtin_expect(!!(e),1)) -# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) -# define __lzo_likely(e) (__builtin_expect(!!(e),1)) -# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) -#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_likely(e) (__builtin_expect(!!(e),1)) -# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) -#endif -#endif -#if defined(__lzo_likely) -# define __lzo_HAVE_likely 1 -#else -# define __lzo_likely(e) (e) -#endif -#if defined(__lzo_unlikely) -# define __lzo_HAVE_unlikely 1 -#else -# define __lzo_unlikely(e) (e) -#endif -#if !defined(LZO_UNUSED) -# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) -# define LZO_UNUSED(var) ((void) &var) -# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) -# define LZO_UNUSED(var) if (&var) ; else -# elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define LZO_UNUSED(var) ((void) var) -# elif (LZO_CC_MSC && (_MSC_VER < 900)) -# define LZO_UNUSED(var) if (&var) ; else -# elif (LZO_CC_KEILC) -# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];} -# elif (LZO_CC_PACIFICC) -# define LZO_UNUSED(var) ((void) sizeof(var)) -# elif (LZO_CC_WATCOMC) && defined(__cplusplus) -# define LZO_UNUSED(var) ((void) var) -# else -# define LZO_UNUSED(var) ((void) &var) -# endif -#endif -#if !defined(LZO_UNUSED_FUNC) -# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) -# define LZO_UNUSED_FUNC(func) ((void) func) -# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) -# define LZO_UNUSED_FUNC(func) if (func) ; else -# elif (LZO_CC_LLVM) -# define LZO_UNUSED_FUNC(func) ((void) &func) -# elif (LZO_CC_MSC && (_MSC_VER < 900)) -# define LZO_UNUSED_FUNC(func) if (func) ; else -# elif (LZO_CC_MSC) -# define LZO_UNUSED_FUNC(func) ((void) &func) -# elif (LZO_CC_KEILC || LZO_CC_PELLESC) -# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];} -# else -# define LZO_UNUSED_FUNC(func) ((void) func) -# endif -#endif -#if !defined(LZO_UNUSED_LABEL) -# if (LZO_CC_WATCOMC) && defined(__cplusplus) -# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l -# elif (LZO_CC_INTELC || LZO_CC_WATCOMC) -# define LZO_UNUSED_LABEL(l) if (0) goto l -# else -# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l -# endif -#endif -#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) -# if 0 -# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var -# elif 0 && (LZO_CC_GNUC) -# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var -# else -# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init -# endif -#endif -#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) -# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) -# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; -# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) -# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)]; -# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) -# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; -# else -# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)]; -# endif -#endif -#if !defined(LZO_COMPILE_TIME_ASSERT) -# if (LZO_CC_AZTECC) -# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];} -# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) -# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; -# elif (LZO_CC_MSC && (_MSC_VER < 900)) -# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; -# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) -# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; -# else -# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];} -# endif -#endif -#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) -# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) -# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) -# define __lzo_cdecl __cdecl -# define __lzo_cdecl_atexit -# define __lzo_cdecl_main __cdecl -# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) -# define __lzo_cdecl_qsort __pascal -# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) -# define __lzo_cdecl_qsort _stdcall -# else -# define __lzo_cdecl_qsort __cdecl -# endif -# elif (LZO_CC_WATCOMC) -# define __lzo_cdecl __cdecl -# else -# define __lzo_cdecl __cdecl -# define __lzo_cdecl_atexit __cdecl -# define __lzo_cdecl_main __cdecl -# define __lzo_cdecl_qsort __cdecl -# endif -# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) -# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) -# define __lzo_cdecl_sighandler __pascal -# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) -# define __lzo_cdecl_sighandler _stdcall -# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) -# define __lzo_cdecl_sighandler __clrcall -# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) -# if defined(_DLL) -# define __lzo_cdecl_sighandler _far _cdecl _loadds -# elif defined(_MT) -# define __lzo_cdecl_sighandler _far _cdecl -# else -# define __lzo_cdecl_sighandler _cdecl -# endif -# else -# define __lzo_cdecl_sighandler __cdecl -# endif -#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) -# define __lzo_cdecl __cdecl -#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) -# define __lzo_cdecl cdecl -#endif -#if !defined(__lzo_cdecl) -# define __lzo_cdecl -#endif -#if !defined(__lzo_cdecl_atexit) -# define __lzo_cdecl_atexit -#endif -#if !defined(__lzo_cdecl_main) -# define __lzo_cdecl_main -#endif -#if !defined(__lzo_cdecl_qsort) -# define __lzo_cdecl_qsort -#endif -#if !defined(__lzo_cdecl_sighandler) -# define __lzo_cdecl_sighandler -#endif -#if !defined(__lzo_cdecl_va) -# define __lzo_cdecl_va __lzo_cdecl -#endif -#if !defined(LZO_CFG_NO_WINDOWS_H) -#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) -# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) -# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__) -# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) -# else -# define LZO_HAVE_WINDOWS_H 1 -# endif -#endif -#endif -#if (LZO_ARCH_ALPHA) -# define LZO_OPT_AVOID_UINT_INDEX 1 -# define LZO_OPT_AVOID_SHORT 1 -# define LZO_OPT_AVOID_USHORT 1 -#elif (LZO_ARCH_AMD64) -# define LZO_OPT_AVOID_INT_INDEX 1 -# define LZO_OPT_AVOID_UINT_INDEX 1 -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 -# define LZO_OPT_UNALIGNED64 1 -#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB) -#elif (LZO_ARCH_ARM) -# define LZO_OPT_AVOID_SHORT 1 -# define LZO_OPT_AVOID_USHORT 1 -#elif (LZO_ARCH_CRIS) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 -#elif (LZO_ARCH_I386) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 -#elif (LZO_ARCH_IA64) -# define LZO_OPT_AVOID_INT_INDEX 1 -# define LZO_OPT_AVOID_UINT_INDEX 1 -# define LZO_OPT_PREFER_POSTINC 1 -#elif (LZO_ARCH_M68K) -# define LZO_OPT_PREFER_POSTINC 1 -# define LZO_OPT_PREFER_PREDEC 1 -# if defined(__mc68020__) && !defined(__mcoldfire__) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 -# endif -#elif (LZO_ARCH_MIPS) -# define LZO_OPT_AVOID_UINT_INDEX 1 -#elif (LZO_ARCH_POWERPC) -# define LZO_OPT_PREFER_PREINC 1 -# define LZO_OPT_PREFER_PREDEC 1 -# if defined(LZO_ABI_BIG_ENDIAN) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 -# endif -#elif (LZO_ARCH_S390) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 -# if (LZO_SIZEOF_SIZE_T == 8) -# define LZO_OPT_UNALIGNED64 1 -# endif -#elif (LZO_ARCH_SH) -# define LZO_OPT_PREFER_POSTINC 1 -# define LZO_OPT_PREFER_PREDEC 1 -#endif -#if !defined(LZO_CFG_NO_INLINE_ASM) -#if defined(LZO_CC_LLVM) -# define LZO_CFG_NO_INLINE_ASM 1 -#endif -#endif -#if !defined(LZO_CFG_NO_UNALIGNED) -#if defined(LZO_ABI_NEUTRAL_ENDIAN) || defined(LZO_ARCH_GENERIC) -# define LZO_CFG_NO_UNALIGNED 1 -#endif -#endif -#if defined(LZO_CFG_NO_UNALIGNED) -# undef LZO_OPT_UNALIGNED16 -# undef LZO_OPT_UNALIGNED32 -# undef LZO_OPT_UNALIGNED64 -#endif -#if defined(LZO_CFG_NO_INLINE_ASM) -#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) -# define LZO_ASM_SYNTAX_MSC 1 -#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) -#elif (LZO_ARCH_I386 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) -# define LZO_ASM_SYNTAX_GNUC 1 -#elif (LZO_ARCH_AMD64 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) -# define LZO_ASM_SYNTAX_GNUC 1 -#endif -#if (LZO_ASM_SYNTAX_GNUC) -#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) -# define __LZO_ASM_CLOBBER "ax" -#elif (LZO_CC_INTELC) -# define __LZO_ASM_CLOBBER "memory" -#else -# define __LZO_ASM_CLOBBER "cc", "memory" -#endif -#endif -#if defined(__LZO_INFOSTR_MM) -#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) -# define __LZO_INFOSTR_MM "" -#elif defined(LZO_INFO_MM) -# define __LZO_INFOSTR_MM "." LZO_INFO_MM -#else -# define __LZO_INFOSTR_MM "" -#endif -#if defined(__LZO_INFOSTR_PM) -#elif defined(LZO_INFO_ABI_PM) -# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM -#else -# define __LZO_INFOSTR_PM "" -#endif -#if defined(__LZO_INFOSTR_ENDIAN) -#elif defined(LZO_INFO_ABI_ENDIAN) -# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN -#else -# define __LZO_INFOSTR_ENDIAN "" -#endif -#if defined(__LZO_INFOSTR_OSNAME) -#elif defined(LZO_INFO_OS_CONSOLE) -# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE -#elif defined(LZO_INFO_OS_POSIX) -# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX -#else -# define __LZO_INFOSTR_OSNAME LZO_INFO_OS -#endif -#if defined(__LZO_INFOSTR_LIBC) -#elif defined(LZO_INFO_LIBC) -# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC -#else -# define __LZO_INFOSTR_LIBC "" -#endif -#if defined(__LZO_INFOSTR_CCVER) -#elif defined(LZO_INFO_CCVER) -# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER -#else -# define __LZO_INFOSTR_CCVER "" -#endif -#define LZO_INFO_STRING \ - LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ - " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER - -#endif /* already included */ - -/* vim:set ts=4 et: */ diff --git a/n2n_v2/minilzo.c b/n2n_v2/minilzo.c deleted file mode 100644 index 6a62b31..0000000 --- a/n2n_v2/minilzo.c +++ /dev/null @@ -1,4112 +0,0 @@ -/* minilzo.c -- mini subset of the LZO real-time data compression library - - This file is part of the LZO real-time data compression library. - - Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer - All Rights Reserved. - - The LZO library 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 2 of - the License, or (at your option) any later version. - - The LZO library 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 the LZO library; see the file COPYING. - If not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - Markus F.X.J. Oberhumer - - http://www.oberhumer.com/opensource/lzo/ - */ - -/* - * NOTE: - * the full LZO package can be found at - * http://www.oberhumer.com/opensource/lzo/ - */ - -#define __LZO_IN_MINILZO -#define LZO_BUILD - -#if defined(LZO_CFG_FREESTANDING) -# undef MINILZO_HAVE_CONFIG_H -# define LZO_LIBC_FREESTANDING 1 -# define LZO_OS_FREESTANDING 1 -#endif - -#ifdef MINILZO_HAVE_CONFIG_H -# include -#endif -#include -#include -#if defined(MINILZO_CFG_USE_INTERNAL_LZODEFS) - -#ifndef __LZODEFS_H_INCLUDED -#define __LZODEFS_H_INCLUDED 1 - -#if defined(__CYGWIN32__) && !defined(__CYGWIN__) -# define __CYGWIN__ __CYGWIN32__ -#endif -#if defined(__IBMCPP__) && !defined(__IBMC__) -# define __IBMC__ __IBMCPP__ -#endif -#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER) -# define __INTEL_COMPILER __ICL -#endif -#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) -# define _ALL_SOURCE 1 -#endif -#if defined(__mips__) && defined(__R5900__) -# if !defined(__LONG_MAX__) -# define __LONG_MAX__ 9223372036854775807L -# endif -#endif -#if defined(__INTEL_COMPILER) && defined(__linux__) -# pragma warning(disable: 193) -#endif -#if defined(__KEIL__) && defined(__C166__) -# pragma warning disable = 322 -#elif 0 && defined(__C251__) -# pragma warning disable = 322 -#endif -#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) -# if (_MSC_VER >= 1300) -# pragma warning(disable: 4668) -# endif -#endif -#if 0 && defined(__WATCOMC__) -# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) -# pragma warning 203 9 -# endif -#endif -#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) -# pragma option -h -#endif -#if 0 -#define LZO_0xffffL 0xfffful -#define LZO_0xffffffffL 0xfffffffful -#else -#define LZO_0xffffL 65535ul -#define LZO_0xffffffffL 4294967295ul -#endif -#if (LZO_0xffffL == LZO_0xffffffffL) -# error "your preprocessor is broken 1" -#endif -#if (16ul * 16384ul != 262144ul) -# error "your preprocessor is broken 2" -#endif -#if 0 -#if (32767 >= 4294967295ul) -# error "your preprocessor is broken 3" -#endif -#if (65535u >= 4294967295ul) -# error "your preprocessor is broken 4" -#endif -#endif -#if (UINT_MAX == LZO_0xffffL) -#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) -# if !defined(MSDOS) -# define MSDOS 1 -# endif -# if !defined(_MSDOS) -# define _MSDOS 1 -# endif -#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) -# if (__VERSION == 520) && (MB_LEN_MAX == 1) -# if !defined(__AZTEC_C__) -# define __AZTEC_C__ __VERSION -# endif -# if !defined(__DOS__) -# define __DOS__ 1 -# endif -# endif -#endif -#endif -#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL) -# define ptrdiff_t long -# define _PTRDIFF_T_DEFINED -#endif -#if (UINT_MAX == LZO_0xffffL) -# undef __LZO_RENAME_A -# undef __LZO_RENAME_B -# if defined(__AZTEC_C__) && defined(__DOS__) -# define __LZO_RENAME_A 1 -# elif defined(_MSC_VER) && defined(MSDOS) -# if (_MSC_VER < 600) -# define __LZO_RENAME_A 1 -# elif (_MSC_VER < 700) -# define __LZO_RENAME_B 1 -# endif -# elif defined(__TSC__) && defined(__OS2__) -# define __LZO_RENAME_A 1 -# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) -# define __LZO_RENAME_A 1 -# elif defined(__PACIFIC__) && defined(DOS) -# if !defined(__far) -# define __far far -# endif -# if !defined(__near) -# define __near near -# endif -# endif -# if defined(__LZO_RENAME_A) -# if !defined(__cdecl) -# define __cdecl cdecl -# endif -# if !defined(__far) -# define __far far -# endif -# if !defined(__huge) -# define __huge huge -# endif -# if !defined(__near) -# define __near near -# endif -# if !defined(__pascal) -# define __pascal pascal -# endif -# if !defined(__huge) -# define __huge huge -# endif -# elif defined(__LZO_RENAME_B) -# if !defined(__cdecl) -# define __cdecl _cdecl -# endif -# if !defined(__far) -# define __far _far -# endif -# if !defined(__huge) -# define __huge _huge -# endif -# if !defined(__near) -# define __near _near -# endif -# if !defined(__pascal) -# define __pascal _pascal -# endif -# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) -# if !defined(__cdecl) -# define __cdecl cdecl -# endif -# if !defined(__pascal) -# define __pascal pascal -# endif -# endif -# undef __LZO_RENAME_A -# undef __LZO_RENAME_B -#endif -#if (UINT_MAX == LZO_0xffffL) -#if defined(__AZTEC_C__) && defined(__DOS__) -# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 -#elif defined(_MSC_VER) && defined(MSDOS) -# if (_MSC_VER < 600) -# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 -# endif -# if (_MSC_VER < 700) -# define LZO_BROKEN_INTEGRAL_PROMOTION 1 -# define LZO_BROKEN_SIZEOF 1 -# endif -#elif defined(__PACIFIC__) && defined(DOS) -# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 -#elif defined(__TURBOC__) && defined(__MSDOS__) -# if (__TURBOC__ < 0x0150) -# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 -# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 -# define LZO_BROKEN_INTEGRAL_PROMOTION 1 -# endif -# if (__TURBOC__ < 0x0200) -# define LZO_BROKEN_SIZEOF 1 -# endif -# if (__TURBOC__ < 0x0400) && defined(__cplusplus) -# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 -# endif -#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) -# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 -# define LZO_BROKEN_SIZEOF 1 -#endif -#endif -#if defined(__WATCOMC__) && (__WATCOMC__ < 900) -# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 -#endif -#if defined(_CRAY) && defined(_CRAY1) -# define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 -#endif -#define LZO_PP_STRINGIZE(x) #x -#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) -#define LZO_PP_CONCAT2(a,b) a ## b -#define LZO_PP_CONCAT3(a,b,c) a ## b ## c -#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d -#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e -#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) -#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) -#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) -#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) -#if 1 -#define LZO_CPP_STRINGIZE(x) #x -#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) -#define LZO_CPP_CONCAT2(a,b) a ## b -#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c -#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d -#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e -#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) -#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) -#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) -#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) -#endif -#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o)) -#if 1 && defined(__cplusplus) -# if !defined(__STDC_CONSTANT_MACROS) -# define __STDC_CONSTANT_MACROS 1 -# endif -# if !defined(__STDC_LIMIT_MACROS) -# define __STDC_LIMIT_MACROS 1 -# endif -#endif -#if defined(__cplusplus) -# define LZO_EXTERN_C extern "C" -#else -# define LZO_EXTERN_C extern -#endif -#if !defined(__LZO_OS_OVERRIDE) -#if defined(LZO_OS_FREESTANDING) -# define LZO_INFO_OS "freestanding" -#elif defined(LZO_OS_EMBEDDED) -# define LZO_INFO_OS "embedded" -#elif 1 && defined(__IAR_SYSTEMS_ICC__) -# define LZO_OS_EMBEDDED 1 -# define LZO_INFO_OS "embedded" -#elif defined(__CYGWIN__) && defined(__GNUC__) -# define LZO_OS_CYGWIN 1 -# define LZO_INFO_OS "cygwin" -#elif defined(__EMX__) && defined(__GNUC__) -# define LZO_OS_EMX 1 -# define LZO_INFO_OS "emx" -#elif defined(__BEOS__) -# define LZO_OS_BEOS 1 -# define LZO_INFO_OS "beos" -#elif defined(__Lynx__) -# define LZO_OS_LYNXOS 1 -# define LZO_INFO_OS "lynxos" -#elif defined(__OS400__) -# define LZO_OS_OS400 1 -# define LZO_INFO_OS "os400" -#elif defined(__QNX__) -# define LZO_OS_QNX 1 -# define LZO_INFO_OS "qnx" -#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) -# define LZO_OS_DOS32 1 -# define LZO_INFO_OS "dos32" -#elif defined(__BORLANDC__) && defined(__DPMI16__) -# define LZO_OS_DOS16 1 -# define LZO_INFO_OS "dos16" -#elif defined(__ZTC__) && defined(DOS386) -# define LZO_OS_DOS32 1 -# define LZO_INFO_OS "dos32" -#elif defined(__OS2__) || defined(__OS2V2__) -# if (UINT_MAX == LZO_0xffffL) -# define LZO_OS_OS216 1 -# define LZO_INFO_OS "os216" -# elif (UINT_MAX == LZO_0xffffffffL) -# define LZO_OS_OS2 1 -# define LZO_INFO_OS "os2" -# else -# error "check your limits.h header" -# endif -#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) -# define LZO_OS_WIN64 1 -# define LZO_INFO_OS "win64" -#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) -# define LZO_OS_WIN32 1 -# define LZO_INFO_OS "win32" -#elif defined(__MWERKS__) && defined(__INTEL__) -# define LZO_OS_WIN32 1 -# define LZO_INFO_OS "win32" -#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) -# if (UINT_MAX == LZO_0xffffL) -# define LZO_OS_WIN16 1 -# define LZO_INFO_OS "win16" -# elif (UINT_MAX == LZO_0xffffffffL) -# define LZO_OS_WIN32 1 -# define LZO_INFO_OS "win32" -# else -# error "check your limits.h header" -# endif -#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) -# if (UINT_MAX == LZO_0xffffL) -# define LZO_OS_DOS16 1 -# define LZO_INFO_OS "dos16" -# elif (UINT_MAX == LZO_0xffffffffL) -# define LZO_OS_DOS32 1 -# define LZO_INFO_OS "dos32" -# else -# error "check your limits.h header" -# endif -#elif defined(__WATCOMC__) -# if defined(__NT__) && (UINT_MAX == LZO_0xffffL) -# define LZO_OS_DOS16 1 -# define LZO_INFO_OS "dos16" -# elif defined(__NT__) && (__WATCOMC__ < 1100) -# define LZO_OS_WIN32 1 -# define LZO_INFO_OS "win32" -# elif defined(__linux__) || defined(__LINUX__) -# define LZO_OS_POSIX 1 -# define LZO_INFO_OS "posix" -# else -# error "please specify a target using the -bt compiler option" -# endif -#elif defined(__palmos__) -# define LZO_OS_PALMOS 1 -# define LZO_INFO_OS "palmos" -#elif defined(__TOS__) || defined(__atarist__) -# define LZO_OS_TOS 1 -# define LZO_INFO_OS "tos" -#elif defined(macintosh) && !defined(__ppc__) -# define LZO_OS_MACCLASSIC 1 -# define LZO_INFO_OS "macclassic" -#elif defined(__VMS) -# define LZO_OS_VMS 1 -# define LZO_INFO_OS "vms" -#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) -# define LZO_OS_CONSOLE 1 -# define LZO_OS_CONSOLE_PS2 1 -# define LZO_INFO_OS "console" -# define LZO_INFO_OS_CONSOLE "ps2" -#elif (defined(__mips__) && defined(__psp__)) -# define LZO_OS_CONSOLE 1 -# define LZO_OS_CONSOLE_PSP 1 -# define LZO_INFO_OS "console" -# define LZO_INFO_OS_CONSOLE "psp" -#else -# define LZO_OS_POSIX 1 -# define LZO_INFO_OS "posix" -#endif -#if (LZO_OS_POSIX) -# if defined(_AIX) || defined(__AIX__) || defined(__aix__) -# define LZO_OS_POSIX_AIX 1 -# define LZO_INFO_OS_POSIX "aix" -# elif defined(__FreeBSD__) -# define LZO_OS_POSIX_FREEBSD 1 -# define LZO_INFO_OS_POSIX "freebsd" -# elif defined(__hpux__) || defined(__hpux) -# define LZO_OS_POSIX_HPUX 1 -# define LZO_INFO_OS_POSIX "hpux" -# elif defined(__INTERIX) -# define LZO_OS_POSIX_INTERIX 1 -# define LZO_INFO_OS_POSIX "interix" -# elif defined(__IRIX__) || defined(__irix__) -# define LZO_OS_POSIX_IRIX 1 -# define LZO_INFO_OS_POSIX "irix" -# elif defined(__linux__) || defined(__linux) || defined(__LINUX__) -# define LZO_OS_POSIX_LINUX 1 -# define LZO_INFO_OS_POSIX "linux" -# elif defined(__APPLE__) || defined(__MACOS__) -# define LZO_OS_POSIX_MACOSX 1 -# define LZO_INFO_OS_POSIX "macosx" -# elif defined(__minix__) || defined(__minix) -# define LZO_OS_POSIX_MINIX 1 -# define LZO_INFO_OS_POSIX "minix" -# elif defined(__NetBSD__) -# define LZO_OS_POSIX_NETBSD 1 -# define LZO_INFO_OS_POSIX "netbsd" -# elif defined(__OpenBSD__) -# define LZO_OS_POSIX_OPENBSD 1 -# define LZO_INFO_OS_POSIX "openbsd" -# elif defined(__osf__) -# define LZO_OS_POSIX_OSF 1 -# define LZO_INFO_OS_POSIX "osf" -# elif defined(__solaris__) || defined(__sun) -# if defined(__SVR4) || defined(__svr4__) -# define LZO_OS_POSIX_SOLARIS 1 -# define LZO_INFO_OS_POSIX "solaris" -# else -# define LZO_OS_POSIX_SUNOS 1 -# define LZO_INFO_OS_POSIX "sunos" -# endif -# elif defined(__ultrix__) || defined(__ultrix) -# define LZO_OS_POSIX_ULTRIX 1 -# define LZO_INFO_OS_POSIX "ultrix" -# elif defined(_UNICOS) -# define LZO_OS_POSIX_UNICOS 1 -# define LZO_INFO_OS_POSIX "unicos" -# else -# define LZO_OS_POSIX_UNKNOWN 1 -# define LZO_INFO_OS_POSIX "unknown" -# endif -#endif -#endif -#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) -# if (UINT_MAX != LZO_0xffffL) -# error "this should not happen" -# endif -# if (ULONG_MAX != LZO_0xffffffffL) -# error "this should not happen" -# endif -#endif -#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) -# if (UINT_MAX != LZO_0xffffffffL) -# error "this should not happen" -# endif -# if (ULONG_MAX != LZO_0xffffffffL) -# error "this should not happen" -# endif -#endif -#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) -# define LZO_CC_CILLY 1 -# define LZO_INFO_CC "Cilly" -# if defined(__CILLY__) -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) -# else -# define LZO_INFO_CCVER "unknown" -# endif -#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) -# define LZO_CC_SDCC 1 -# define LZO_INFO_CC "sdcc" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) -#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) -# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__) -# define LZO_INFO_CC "Pathscale C" -# define LZO_INFO_CCVER __PATHSCALE__ -#elif defined(__INTEL_COMPILER) -# define LZO_CC_INTELC 1 -# define LZO_INFO_CC "Intel C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) -# if defined(_WIN32) || defined(_WIN64) -# define LZO_CC_SYNTAX_MSC 1 -# else -# define LZO_CC_SYNTAX_GNUC 1 -# endif -#elif defined(__POCC__) && defined(_WIN32) -# define LZO_CC_PELLESC 1 -# define LZO_INFO_CC "Pelles C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) -#elif defined(__llvm__) && defined(__GNUC__) && defined(__VERSION__) -# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) -# define LZO_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) -# else -# define LZO_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) -# endif -# define LZO_INFO_CC "llvm-gcc" -# define LZO_INFO_CCVER __VERSION__ -#elif defined(__GNUC__) && defined(__VERSION__) -# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) -# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) -# elif defined(__GNUC_MINOR__) -# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) -# else -# define LZO_CC_GNUC (__GNUC__ * 0x10000L) -# endif -# define LZO_INFO_CC "gcc" -# define LZO_INFO_CCVER __VERSION__ -#elif defined(__ACK__) && defined(_ACK) -# define LZO_CC_ACK 1 -# define LZO_INFO_CC "Amsterdam Compiler Kit C" -# define LZO_INFO_CCVER "unknown" -#elif defined(__AZTEC_C__) -# define LZO_CC_AZTECC 1 -# define LZO_INFO_CC "Aztec C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) -#elif defined(__BORLANDC__) -# define LZO_CC_BORLANDC 1 -# define LZO_INFO_CC "Borland C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) -#elif defined(_CRAYC) && defined(_RELEASE) -# define LZO_CC_CRAYC 1 -# define LZO_INFO_CC "Cray C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) -#elif defined(__DMC__) && defined(__SC__) -# define LZO_CC_DMC 1 -# define LZO_INFO_CC "Digital Mars C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) -#elif defined(__DECC) -# define LZO_CC_DECC 1 -# define LZO_INFO_CC "DEC C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) -#elif defined(__HIGHC__) -# define LZO_CC_HIGHC 1 -# define LZO_INFO_CC "MetaWare High C" -# define LZO_INFO_CCVER "unknown" -#elif defined(__IAR_SYSTEMS_ICC__) -# define LZO_CC_IARC 1 -# define LZO_INFO_CC "IAR C" -# if defined(__VER__) -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) -# else -# define LZO_INFO_CCVER "unknown" -# endif -#elif defined(__IBMC__) -# define LZO_CC_IBMC 1 -# define LZO_INFO_CC "IBM C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) -#elif defined(__KEIL__) && defined(__C166__) -# define LZO_CC_KEILC 1 -# define LZO_INFO_CC "Keil C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) -#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) -# define LZO_CC_LCCWIN32 1 -# define LZO_INFO_CC "lcc-win32" -# define LZO_INFO_CCVER "unknown" -#elif defined(__LCC__) -# define LZO_CC_LCC 1 -# define LZO_INFO_CC "lcc" -# if defined(__LCC_VERSION__) -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) -# else -# define LZO_INFO_CCVER "unknown" -# endif -#elif defined(_MSC_VER) -# define LZO_CC_MSC 1 -# define LZO_INFO_CC "Microsoft C" -# if defined(_MSC_FULL_VER) -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) -# else -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) -# endif -#elif defined(__MWERKS__) -# define LZO_CC_MWERKS 1 -# define LZO_INFO_CC "Metrowerks C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) -#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) -# define LZO_CC_NDPC 1 -# define LZO_INFO_CC "Microway NDP C" -# define LZO_INFO_CCVER "unknown" -#elif defined(__PACIFIC__) -# define LZO_CC_PACIFICC 1 -# define LZO_INFO_CC "Pacific C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) -#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) -# define LZO_CC_PGI 1 -# define LZO_INFO_CC "Portland Group PGI C" -# define LZO_INFO_CCVER "unknown" -#elif defined(__PUREC__) && defined(__TOS__) -# define LZO_CC_PUREC 1 -# define LZO_INFO_CC "Pure C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) -#elif defined(__SC__) && defined(__ZTC__) -# define LZO_CC_SYMANTECC 1 -# define LZO_INFO_CC "Symantec C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) -#elif defined(__SUNPRO_C) -# define LZO_INFO_CC "SunPro C" -# if ((__SUNPRO_C)+0 > 0) -# define LZO_CC_SUNPROC __SUNPRO_C -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) -# else -# define LZO_CC_SUNPROC 1 -# define LZO_INFO_CCVER "unknown" -# endif -#elif defined(__SUNPRO_CC) -# define LZO_INFO_CC "SunPro C" -# if ((__SUNPRO_CC)+0 > 0) -# define LZO_CC_SUNPROC __SUNPRO_CC -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) -# else -# define LZO_CC_SUNPROC 1 -# define LZO_INFO_CCVER "unknown" -# endif -#elif defined(__TINYC__) -# define LZO_CC_TINYC 1 -# define LZO_INFO_CC "Tiny C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) -#elif defined(__TSC__) -# define LZO_CC_TOPSPEEDC 1 -# define LZO_INFO_CC "TopSpeed C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) -#elif defined(__WATCOMC__) -# define LZO_CC_WATCOMC 1 -# define LZO_INFO_CC "Watcom C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) -#elif defined(__TURBOC__) -# define LZO_CC_TURBOC 1 -# define LZO_INFO_CC "Turbo C" -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) -#elif defined(__ZTC__) -# define LZO_CC_ZORTECHC 1 -# define LZO_INFO_CC "Zortech C" -# if (__ZTC__ == 0x310) -# define LZO_INFO_CCVER "0x310" -# else -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) -# endif -#else -# define LZO_CC_UNKNOWN 1 -# define LZO_INFO_CC "unknown" -# define LZO_INFO_CCVER "unknown" -#endif -#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) -# error "LZO_CC_MSC: _MSC_FULL_VER is not defined" -#endif -#if !defined(__LZO_ARCH_OVERRIDE) && !defined(LZO_ARCH_GENERIC) && defined(_CRAY) -# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) -# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) -# define LZO_ARCH_CRAY_MPP 1 -# elif defined(_CRAY1) -# define LZO_ARCH_CRAY_PVP 1 -# endif -# endif -#endif -#if !defined(__LZO_ARCH_OVERRIDE) -#if defined(LZO_ARCH_GENERIC) -# define LZO_INFO_ARCH "generic" -#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) -# define LZO_ARCH_I086 1 -# define LZO_ARCH_IA16 1 -# define LZO_INFO_ARCH "i086" -#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) -# define LZO_ARCH_ALPHA 1 -# define LZO_INFO_ARCH "alpha" -#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) -# define LZO_ARCH_ALPHA 1 -# define LZO_INFO_ARCH "alpha" -#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) -# define LZO_ARCH_AMD64 1 -# define LZO_INFO_ARCH "amd64" -#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB)) -# define LZO_ARCH_ARM 1 -# define LZO_ARCH_ARM_THUMB 1 -# define LZO_INFO_ARCH "arm_thumb" -#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) -# define LZO_ARCH_ARM 1 -# if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1) -# define LZO_ARCH_ARM_THUMB 1 -# define LZO_INFO_ARCH "arm_thumb" -# elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2) -# define LZO_INFO_ARCH "arm" -# else -# define LZO_INFO_ARCH "arm" -# endif -#elif defined(__arm__) || defined(_M_ARM) -# define LZO_ARCH_ARM 1 -# define LZO_INFO_ARCH "arm" -#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) -# define LZO_ARCH_AVR 1 -# define LZO_INFO_ARCH "avr" -#elif defined(__bfin__) -# define LZO_ARCH_BLACKFIN 1 -# define LZO_INFO_ARCH "blackfin" -#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) -# define LZO_ARCH_C166 1 -# define LZO_INFO_ARCH "c166" -#elif defined(__cris__) -# define LZO_ARCH_CRIS 1 -# define LZO_INFO_ARCH "cris" -#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) -# define LZO_ARCH_EZ80 1 -# define LZO_INFO_ARCH "ez80" -#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) -# define LZO_ARCH_H8300 1 -# define LZO_INFO_ARCH "h8300" -#elif defined(__hppa__) || defined(__hppa) -# define LZO_ARCH_HPPA 1 -# define LZO_INFO_ARCH "hppa" -#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) -# define LZO_ARCH_I386 1 -# define LZO_ARCH_IA32 1 -# define LZO_INFO_ARCH "i386" -#elif (LZO_CC_ZORTECHC && defined(__I86__)) -# define LZO_ARCH_I386 1 -# define LZO_ARCH_IA32 1 -# define LZO_INFO_ARCH "i386" -#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) -# define LZO_ARCH_I386 1 -# define LZO_ARCH_IA32 1 -# define LZO_INFO_ARCH "i386" -#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) -# define LZO_ARCH_IA64 1 -# define LZO_INFO_ARCH "ia64" -#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) -# define LZO_ARCH_M16C 1 -# define LZO_INFO_ARCH "m16c" -#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) -# define LZO_ARCH_M16C 1 -# define LZO_INFO_ARCH "m16c" -#elif defined(__m32r__) -# define LZO_ARCH_M32R 1 -# define LZO_INFO_ARCH "m32r" -#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) -# define LZO_ARCH_M68K 1 -# define LZO_INFO_ARCH "m68k" -#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) -# define LZO_ARCH_MCS251 1 -# define LZO_INFO_ARCH "mcs251" -#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) -# define LZO_ARCH_MCS51 1 -# define LZO_INFO_ARCH "mcs51" -#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) -# define LZO_ARCH_MCS51 1 -# define LZO_INFO_ARCH "mcs51" -#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) -# define LZO_ARCH_MIPS 1 -# define LZO_INFO_ARCH "mips" -#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) -# define LZO_ARCH_MSP430 1 -# define LZO_INFO_ARCH "msp430" -#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) -# define LZO_ARCH_MSP430 1 -# define LZO_INFO_ARCH "msp430" -#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) -# define LZO_ARCH_POWERPC 1 -# define LZO_INFO_ARCH "powerpc" -#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) -# define LZO_ARCH_S390 1 -# define LZO_INFO_ARCH "s390" -#elif defined(__sh__) || defined(_M_SH) -# define LZO_ARCH_SH 1 -# define LZO_INFO_ARCH "sh" -#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) -# define LZO_ARCH_SPARC 1 -# define LZO_INFO_ARCH "sparc" -#elif defined(__SPU__) -# define LZO_ARCH_SPU 1 -# define LZO_INFO_ARCH "spu" -#elif (UINT_MAX == LZO_0xffffL) && defined(__z80) -# define LZO_ARCH_Z80 1 -# define LZO_INFO_ARCH "z80" -#elif (LZO_ARCH_CRAY_PVP) -# if defined(_CRAYSV1) -# define LZO_ARCH_CRAY_SV1 1 -# define LZO_INFO_ARCH "cray_sv1" -# elif (_ADDR64) -# define LZO_ARCH_CRAY_T90 1 -# define LZO_INFO_ARCH "cray_t90" -# elif (_ADDR32) -# define LZO_ARCH_CRAY_YMP 1 -# define LZO_INFO_ARCH "cray_ymp" -# else -# define LZO_ARCH_CRAY_XMP 1 -# define LZO_INFO_ARCH "cray_xmp" -# endif -#else -# define LZO_ARCH_UNKNOWN 1 -# define LZO_INFO_ARCH "unknown" -#endif -#endif -#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) -# error "FIXME - missing define for CPU architecture" -#endif -#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) -# error "FIXME - missing WIN32 define for CPU architecture" -#endif -#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) -# error "FIXME - missing WIN64 define for CPU architecture" -#endif -#if (LZO_OS_OS216 || LZO_OS_WIN16) -# define LZO_ARCH_I086PM 1 -# define LZO_ARCH_IA16PM 1 -#elif 1 && (LZO_OS_DOS16 && defined(BLX286)) -# define LZO_ARCH_I086PM 1 -# define LZO_ARCH_IA16PM 1 -#elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) -# define LZO_ARCH_I086PM 1 -# define LZO_ARCH_IA16PM 1 -#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) -# define LZO_ARCH_I086PM 1 -# define LZO_ARCH_IA16PM 1 -#endif -#if defined(LZO_ARCH_ARM_THUMB) && !defined(LZO_ARCH_ARM) -# error "this should not happen" -#endif -#if defined(LZO_ARCH_I086PM) && !defined(LZO_ARCH_I086) -# error "this should not happen" -#endif -#if (LZO_ARCH_I086) -# if (UINT_MAX != LZO_0xffffL) -# error "this should not happen" -# endif -# if (ULONG_MAX != LZO_0xffffffffL) -# error "this should not happen" -# endif -#endif -#if (LZO_ARCH_I386) -# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) -# error "this should not happen" -# endif -# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) -# error "this should not happen" -# endif -# if (ULONG_MAX != LZO_0xffffffffL) -# error "this should not happen" -# endif -#endif -#if !defined(__LZO_MM_OVERRIDE) -#if (LZO_ARCH_I086) -#if (UINT_MAX != LZO_0xffffL) -# error "this should not happen" -#endif -#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) -# define LZO_MM_TINY 1 -#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) -# define LZO_MM_HUGE 1 -#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) -# define LZO_MM_SMALL 1 -#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) -# define LZO_MM_MEDIUM 1 -#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) -# define LZO_MM_COMPACT 1 -#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) -# define LZO_MM_LARGE 1 -#elif (LZO_CC_AZTECC) -# if defined(_LARGE_CODE) && defined(_LARGE_DATA) -# define LZO_MM_LARGE 1 -# elif defined(_LARGE_CODE) -# define LZO_MM_MEDIUM 1 -# elif defined(_LARGE_DATA) -# define LZO_MM_COMPACT 1 -# else -# define LZO_MM_SMALL 1 -# endif -#elif (LZO_CC_ZORTECHC && defined(__VCM__)) -# define LZO_MM_LARGE 1 -#else -# error "unknown memory model" -#endif -#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) -#define LZO_HAVE_MM_HUGE_PTR 1 -#define LZO_HAVE_MM_HUGE_ARRAY 1 -#if (LZO_MM_TINY) -# undef LZO_HAVE_MM_HUGE_ARRAY -#endif -#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) -# undef LZO_HAVE_MM_HUGE_PTR -# undef LZO_HAVE_MM_HUGE_ARRAY -#elif (LZO_CC_DMC || LZO_CC_SYMANTECC) -# undef LZO_HAVE_MM_HUGE_ARRAY -#elif (LZO_CC_MSC && defined(_QC)) -# undef LZO_HAVE_MM_HUGE_ARRAY -# if (_MSC_VER < 600) -# undef LZO_HAVE_MM_HUGE_PTR -# endif -#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) -# undef LZO_HAVE_MM_HUGE_ARRAY -#endif -#if (LZO_ARCH_I086PM) && !defined(LZO_HAVE_MM_HUGE_PTR) -# if (LZO_OS_DOS16) -# error "this should not happen" -# elif (LZO_CC_ZORTECHC) -# else -# error "this should not happen" -# endif -#endif -#ifdef __cplusplus -extern "C" { -#endif -#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) - extern void __near __cdecl _AHSHIFT(void); -# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) -#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) - extern void __near __cdecl _AHSHIFT(void); -# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) -#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) - extern void __near __cdecl _AHSHIFT(void); -# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) -#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) - extern void __near __cdecl _AHSHIFT(void); -# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) -#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) -# define LZO_MM_AHSHIFT 12 -#elif (LZO_CC_WATCOMC) - extern unsigned char _HShift; -# define LZO_MM_AHSHIFT ((unsigned) _HShift) -#else -# error "FIXME - implement LZO_MM_AHSHIFT" -#endif -#ifdef __cplusplus -} -#endif -#endif -#elif (LZO_ARCH_C166) -#if !defined(__MODEL__) -# error "FIXME - C166 __MODEL__" -#elif ((__MODEL__) == 0) -# define LZO_MM_SMALL 1 -#elif ((__MODEL__) == 1) -# define LZO_MM_SMALL 1 -#elif ((__MODEL__) == 2) -# define LZO_MM_LARGE 1 -#elif ((__MODEL__) == 3) -# define LZO_MM_TINY 1 -#elif ((__MODEL__) == 4) -# define LZO_MM_XTINY 1 -#elif ((__MODEL__) == 5) -# define LZO_MM_XSMALL 1 -#else -# error "FIXME - C166 __MODEL__" -#endif -#elif (LZO_ARCH_MCS251) -#if !defined(__MODEL__) -# error "FIXME - MCS251 __MODEL__" -#elif ((__MODEL__) == 0) -# define LZO_MM_SMALL 1 -#elif ((__MODEL__) == 2) -# define LZO_MM_LARGE 1 -#elif ((__MODEL__) == 3) -# define LZO_MM_TINY 1 -#elif ((__MODEL__) == 4) -# define LZO_MM_XTINY 1 -#elif ((__MODEL__) == 5) -# define LZO_MM_XSMALL 1 -#else -# error "FIXME - MCS251 __MODEL__" -#endif -#elif (LZO_ARCH_MCS51) -#if !defined(__MODEL__) -# error "FIXME - MCS51 __MODEL__" -#elif ((__MODEL__) == 1) -# define LZO_MM_SMALL 1 -#elif ((__MODEL__) == 2) -# define LZO_MM_LARGE 1 -#elif ((__MODEL__) == 3) -# define LZO_MM_TINY 1 -#elif ((__MODEL__) == 4) -# define LZO_MM_XTINY 1 -#elif ((__MODEL__) == 5) -# define LZO_MM_XSMALL 1 -#else -# error "FIXME - MCS51 __MODEL__" -#endif -#elif (LZO_ARCH_CRAY_PVP) -# define LZO_MM_PVP 1 -#else -# define LZO_MM_FLAT 1 -#endif -#if (LZO_MM_COMPACT) -# define LZO_INFO_MM "compact" -#elif (LZO_MM_FLAT) -# define LZO_INFO_MM "flat" -#elif (LZO_MM_HUGE) -# define LZO_INFO_MM "huge" -#elif (LZO_MM_LARGE) -# define LZO_INFO_MM "large" -#elif (LZO_MM_MEDIUM) -# define LZO_INFO_MM "medium" -#elif (LZO_MM_PVP) -# define LZO_INFO_MM "pvp" -#elif (LZO_MM_SMALL) -# define LZO_INFO_MM "small" -#elif (LZO_MM_TINY) -# define LZO_INFO_MM "tiny" -#else -# error "unknown memory model" -#endif -#endif -#if defined(SIZEOF_SHORT) -# define LZO_SIZEOF_SHORT (SIZEOF_SHORT) -#endif -#if defined(SIZEOF_INT) -# define LZO_SIZEOF_INT (SIZEOF_INT) -#endif -#if defined(SIZEOF_LONG) -# define LZO_SIZEOF_LONG (SIZEOF_LONG) -#endif -#if defined(SIZEOF_LONG_LONG) -# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) -#endif -#if defined(SIZEOF___INT16) -# define LZO_SIZEOF___INT16 (SIZEOF___INT16) -#endif -#if defined(SIZEOF___INT32) -# define LZO_SIZEOF___INT32 (SIZEOF___INT32) -#endif -#if defined(SIZEOF___INT64) -# define LZO_SIZEOF___INT64 (SIZEOF___INT64) -#endif -#if defined(SIZEOF_VOID_P) -# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) -#endif -#if defined(SIZEOF_SIZE_T) -# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) -#endif -#if defined(SIZEOF_PTRDIFF_T) -# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) -#endif -#define __LZO_LSR(x,b) (((x)+0ul) >> (b)) -#if !defined(LZO_SIZEOF_SHORT) -# if (LZO_ARCH_CRAY_PVP) -# define LZO_SIZEOF_SHORT 8 -# elif (USHRT_MAX == LZO_0xffffL) -# define LZO_SIZEOF_SHORT 2 -# elif (__LZO_LSR(USHRT_MAX,7) == 1) -# define LZO_SIZEOF_SHORT 1 -# elif (__LZO_LSR(USHRT_MAX,15) == 1) -# define LZO_SIZEOF_SHORT 2 -# elif (__LZO_LSR(USHRT_MAX,31) == 1) -# define LZO_SIZEOF_SHORT 4 -# elif (__LZO_LSR(USHRT_MAX,63) == 1) -# define LZO_SIZEOF_SHORT 8 -# elif (__LZO_LSR(USHRT_MAX,127) == 1) -# define LZO_SIZEOF_SHORT 16 -# else -# error "LZO_SIZEOF_SHORT" -# endif -#endif -#if !defined(LZO_SIZEOF_INT) -# if (LZO_ARCH_CRAY_PVP) -# define LZO_SIZEOF_INT 8 -# elif (UINT_MAX == LZO_0xffffL) -# define LZO_SIZEOF_INT 2 -# elif (UINT_MAX == LZO_0xffffffffL) -# define LZO_SIZEOF_INT 4 -# elif (__LZO_LSR(UINT_MAX,7) == 1) -# define LZO_SIZEOF_INT 1 -# elif (__LZO_LSR(UINT_MAX,15) == 1) -# define LZO_SIZEOF_INT 2 -# elif (__LZO_LSR(UINT_MAX,31) == 1) -# define LZO_SIZEOF_INT 4 -# elif (__LZO_LSR(UINT_MAX,63) == 1) -# define LZO_SIZEOF_INT 8 -# elif (__LZO_LSR(UINT_MAX,127) == 1) -# define LZO_SIZEOF_INT 16 -# else -# error "LZO_SIZEOF_INT" -# endif -#endif -#if !defined(LZO_SIZEOF_LONG) -# if (ULONG_MAX == LZO_0xffffffffL) -# define LZO_SIZEOF_LONG 4 -# elif (__LZO_LSR(ULONG_MAX,7) == 1) -# define LZO_SIZEOF_LONG 1 -# elif (__LZO_LSR(ULONG_MAX,15) == 1) -# define LZO_SIZEOF_LONG 2 -# elif (__LZO_LSR(ULONG_MAX,31) == 1) -# define LZO_SIZEOF_LONG 4 -# elif (__LZO_LSR(ULONG_MAX,63) == 1) -# define LZO_SIZEOF_LONG 8 -# elif (__LZO_LSR(ULONG_MAX,127) == 1) -# define LZO_SIZEOF_LONG 16 -# else -# error "LZO_SIZEOF_LONG" -# endif -#endif -#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) -#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) -# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) -# if (LZO_CC_GNUC >= 0x030300ul) -# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0) -# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG -# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) -# define LZO_SIZEOF_LONG_LONG 4 -# endif -# endif -# endif -#endif -#endif -#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) -#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) -#if (LZO_ARCH_I086 && LZO_CC_DMC) -#elif (LZO_CC_CILLY) && defined(__GNUC__) -# define LZO_SIZEOF_LONG_LONG 8 -#elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define LZO_SIZEOF_LONG_LONG 8 -#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) -# define LZO_SIZEOF_LONG_LONG 8 -#elif (LZO_OS_WIN64 || defined(_WIN64)) -# define LZO_SIZEOF___INT64 8 -#elif (LZO_ARCH_I386 && (LZO_CC_DMC)) -# define LZO_SIZEOF_LONG_LONG 8 -#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) -# define LZO_SIZEOF_LONG_LONG 8 -#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) -# define LZO_SIZEOF_LONG_LONG 8 -#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) -# define LZO_SIZEOF_LONG_LONG 8 -#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) -# define LZO_SIZEOF___INT64 8 -#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) -# define LZO_SIZEOF___INT64 8 -#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) -# define LZO_SIZEOF___INT64 8 -#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) -# define LZO_SIZEOF___INT64 8 -#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64)) -# define LZO_SIZEOF___INT64 8 -#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) -# define LZO_SIZEOF_LONG_LONG 8 -#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) -# define LZO_SIZEOF_LONG_LONG 8 -#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) -#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -# define LZO_SIZEOF_LONG_LONG 8 -#endif -#endif -#endif -#if defined(__cplusplus) && defined(LZO_CC_GNUC) -# if (LZO_CC_GNUC < 0x020800ul) -# undef LZO_SIZEOF_LONG_LONG -# endif -#endif -#if defined(LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG) -# undef LZO_SIZEOF_LONG_LONG -#endif -#if !defined(LZO_SIZEOF_VOID_P) -#if (LZO_ARCH_I086) -# define __LZO_WORDSIZE 2 -# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) -# define LZO_SIZEOF_VOID_P 2 -# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) -# define LZO_SIZEOF_VOID_P 4 -# else -# error "LZO_MM" -# endif -#elif (LZO_ARCH_AVR || LZO_ARCH_Z80) -# define __LZO_WORDSIZE 1 -# define LZO_SIZEOF_VOID_P 2 -#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) -# define LZO_SIZEOF_VOID_P 2 -#elif (LZO_ARCH_H8300) -# if defined(__NORMAL_MODE__) -# define __LZO_WORDSIZE 4 -# define LZO_SIZEOF_VOID_P 2 -# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) -# define __LZO_WORDSIZE 4 -# define LZO_SIZEOF_VOID_P 4 -# else -# define __LZO_WORDSIZE 2 -# define LZO_SIZEOF_VOID_P 2 -# endif -# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) -# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT -# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT -# endif -#elif (LZO_ARCH_M16C) -# define __LZO_WORDSIZE 2 -# if defined(__m32c_cpu__) || defined(__m32cm_cpu__) -# define LZO_SIZEOF_VOID_P 4 -# else -# define LZO_SIZEOF_VOID_P 2 -# endif -#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) -# define __LZO_WORDSIZE 8 -# define LZO_SIZEOF_VOID_P 4 -#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) -# define __LZO_WORDSIZE 8 -# define LZO_SIZEOF_VOID_P 8 -#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) -# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG -# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG -# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG -#elif (LZO_OS_OS400 || defined(__OS400__)) -# define __LZO_WORDSIZE LZO_SIZEOF_LONG -# define LZO_SIZEOF_VOID_P 16 -# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG -# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG -#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) -# define LZO_SIZEOF_VOID_P 8 -# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG -# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG -#elif (LZO_ARCH_SPU) -# if 0 -# define __LZO_WORDSIZE 16 -# endif -# define LZO_SIZEOF_VOID_P 4 -#else -# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG -#endif -#endif -#if !defined(LZO_WORDSIZE) -# if defined(__LZO_WORDSIZE) -# define LZO_WORDSIZE __LZO_WORDSIZE -# else -# define LZO_WORDSIZE LZO_SIZEOF_VOID_P -# endif -#endif -#if !defined(LZO_SIZEOF_SIZE_T) -#if (LZO_ARCH_I086 || LZO_ARCH_M16C) -# define LZO_SIZEOF_SIZE_T 2 -#else -# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P -#endif -#endif -#if !defined(LZO_SIZEOF_PTRDIFF_T) -#if (LZO_ARCH_I086) -# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) -# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P -# elif (LZO_MM_COMPACT || LZO_MM_LARGE) -# if (LZO_CC_BORLANDC || LZO_CC_TURBOC) -# define LZO_SIZEOF_PTRDIFF_T 4 -# else -# define LZO_SIZEOF_PTRDIFF_T 2 -# endif -# else -# error "LZO_MM" -# endif -#else -# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T -#endif -#endif -#if defined(LZO_ABI_NEUTRAL_ENDIAN) -# undef LZO_ABI_BIG_ENDIAN -# undef LZO_ABI_LITTLE_ENDIAN -#elif !defined(LZO_ABI_BIG_ENDIAN) && !defined(LZO_ABI_LITTLE_ENDIAN) -#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) -# define LZO_ABI_BIG_ENDIAN 1 -#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430) -# define LZO_ABI_LITTLE_ENDIAN 1 -#elif (LZO_ARCH_M68K || LZO_ARCH_S390) -# define LZO_ABI_BIG_ENDIAN 1 -#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) -# if (__LITTLE_ENDIAN__ == 1) -# define LZO_ABI_LITTLE_ENDIAN 1 -# else -# define LZO_ABI_BIG_ENDIAN 1 -# endif -#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) -# define LZO_ABI_BIG_ENDIAN 1 -#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) -# define LZO_ABI_LITTLE_ENDIAN 1 -#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) -# define LZO_ABI_BIG_ENDIAN 1 -#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) -# define LZO_ABI_LITTLE_ENDIAN 1 -#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) -# define LZO_ABI_BIG_ENDIAN 1 -#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) -# define LZO_ABI_LITTLE_ENDIAN 1 -#endif -#endif -#if defined(LZO_ABI_BIG_ENDIAN) && defined(LZO_ABI_LITTLE_ENDIAN) -# error "this should not happen" -#endif -#if defined(LZO_ABI_BIG_ENDIAN) -# define LZO_INFO_ABI_ENDIAN "be" -#elif defined(LZO_ABI_LITTLE_ENDIAN) -# define LZO_INFO_ABI_ENDIAN "le" -#elif defined(LZO_ABI_NEUTRAL_ENDIAN) -# define LZO_INFO_ABI_ENDIAN "neutral" -#endif -#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) -# define LZO_ABI_I8LP16 1 -# define LZO_INFO_ABI_PM "i8lp16" -#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) -# define LZO_ABI_ILP16 1 -# define LZO_INFO_ABI_PM "ilp16" -#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) -# define LZO_ABI_ILP32 1 -# define LZO_INFO_ABI_PM "ilp32" -#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) -# define LZO_ABI_LLP64 1 -# define LZO_INFO_ABI_PM "llp64" -#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) -# define LZO_ABI_LP64 1 -# define LZO_INFO_ABI_PM "lp64" -#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) -# define LZO_ABI_ILP64 1 -# define LZO_INFO_ABI_PM "ilp64" -#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) -# define LZO_ABI_IP32L64 1 -# define LZO_INFO_ABI_PM "ip32l64" -#endif -#if !defined(__LZO_LIBC_OVERRIDE) -#if defined(LZO_LIBC_NAKED) -# define LZO_INFO_LIBC "naked" -#elif defined(LZO_LIBC_FREESTANDING) -# define LZO_INFO_LIBC "freestanding" -#elif defined(LZO_LIBC_MOSTLY_FREESTANDING) -# define LZO_INFO_LIBC "mfreestanding" -#elif defined(LZO_LIBC_ISOC90) -# define LZO_INFO_LIBC "isoc90" -#elif defined(LZO_LIBC_ISOC99) -# define LZO_INFO_LIBC "isoc99" -#elif defined(__dietlibc__) -# define LZO_LIBC_DIETLIBC 1 -# define LZO_INFO_LIBC "dietlibc" -#elif defined(_NEWLIB_VERSION) -# define LZO_LIBC_NEWLIB 1 -# define LZO_INFO_LIBC "newlib" -#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) -# if defined(__UCLIBC_SUBLEVEL__) -# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__) -# else -# define LZO_LIBC_UCLIBC 0x00090bL -# endif -# define LZO_INFO_LIBC "uclibc" -#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) -# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100) -# define LZO_INFO_LIBC "glibc" -#elif (LZO_CC_MWERKS) && defined(__MSL__) -# define LZO_LIBC_MSL __MSL__ -# define LZO_INFO_LIBC "msl" -#elif 1 && defined(__IAR_SYSTEMS_ICC__) -# define LZO_LIBC_ISOC90 1 -# define LZO_INFO_LIBC "isoc90" -#else -# define LZO_LIBC_DEFAULT 1 -# define LZO_INFO_LIBC "default" -#endif -#endif -#if !defined(__lzo_gnuc_extension__) -#if (LZO_CC_GNUC >= 0x020800ul) -# define __lzo_gnuc_extension__ __extension__ -#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_gnuc_extension__ __extension__ -#else -# define __lzo_gnuc_extension__ -#endif -#endif -#if !defined(__lzo_ua_volatile) -# define __lzo_ua_volatile volatile -#endif -#if !defined(__lzo_alignof) -#if (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) -# define __lzo_alignof(e) __alignof__(e) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) -# define __lzo_alignof(e) __alignof__(e) -#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) -# define __lzo_alignof(e) __alignof(e) -#endif -#endif -#if defined(__lzo_alignof) -# define __lzo_HAVE_alignof 1 -#endif -#if !defined(__lzo_constructor) -#if (LZO_CC_GNUC >= 0x030400ul) -# define __lzo_constructor __attribute__((__constructor__,__used__)) -#elif (LZO_CC_GNUC >= 0x020700ul) -# define __lzo_constructor __attribute__((__constructor__)) -#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_constructor __attribute__((__constructor__)) -#endif -#endif -#if defined(__lzo_constructor) -# define __lzo_HAVE_constructor 1 -#endif -#if !defined(__lzo_destructor) -#if (LZO_CC_GNUC >= 0x030400ul) -# define __lzo_destructor __attribute__((__destructor__,__used__)) -#elif (LZO_CC_GNUC >= 0x020700ul) -# define __lzo_destructor __attribute__((__destructor__)) -#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_destructor __attribute__((__destructor__)) -#endif -#endif -#if defined(__lzo_destructor) -# define __lzo_HAVE_destructor 1 -#endif -#if defined(__lzo_HAVE_destructor) && !defined(__lzo_HAVE_constructor) -# error "this should not happen" -#endif -#if !defined(__lzo_inline) -#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) -#elif defined(__cplusplus) -# define __lzo_inline inline -#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) -# define __lzo_inline __inline -#elif (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) -# define __lzo_inline __inline__ -#elif (LZO_CC_DMC) -# define __lzo_inline __inline -#elif (LZO_CC_INTELC) -# define __lzo_inline __inline -#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) -# define __lzo_inline __inline -#elif (LZO_CC_MSC && (_MSC_VER >= 900)) -# define __lzo_inline __inline -#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -# define __lzo_inline inline -#endif -#endif -#if defined(__lzo_inline) -# define __lzo_HAVE_inline 1 -#else -# define __lzo_inline -#endif -#if !defined(__lzo_forceinline) -#if (LZO_CC_GNUC >= 0x030200ul) -# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) -# define __lzo_forceinline __forceinline -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) -# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) -#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) -#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) -# define __lzo_forceinline __forceinline -#endif -#endif -#if defined(__lzo_forceinline) -# define __lzo_HAVE_forceinline 1 -#else -# define __lzo_forceinline -#endif -#if !defined(__lzo_noinline) -#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) -# define __lzo_noinline __attribute__((__noinline__,__used__)) -#elif (LZO_CC_GNUC >= 0x030200ul) -# define __lzo_noinline __attribute__((__noinline__)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_MSC) -# define __lzo_noinline __declspec(noinline) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) -# define __lzo_noinline __attribute__((__noinline__)) -#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_noinline __attribute__((__noinline__)) -#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) -# define __lzo_noinline __declspec(noinline) -#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) -# if defined(__cplusplus) -# else -# define __lzo_noinline __declspec(noinline) -# endif -#endif -#endif -#if defined(__lzo_noinline) -# define __lzo_HAVE_noinline 1 -#else -# define __lzo_noinline -#endif -#if (defined(__lzo_HAVE_forceinline) || defined(__lzo_HAVE_noinline)) && !defined(__lzo_HAVE_inline) -# error "this should not happen" -#endif -#if !defined(__lzo_noreturn) -#if (LZO_CC_GNUC >= 0x020700ul) -# define __lzo_noreturn __attribute__((__noreturn__)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) -# define __lzo_noreturn __declspec(noreturn) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) -# define __lzo_noreturn __attribute__((__noreturn__)) -#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_noreturn __attribute__((__noreturn__)) -#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) -# define __lzo_noreturn __declspec(noreturn) -#endif -#endif -#if defined(__lzo_noreturn) -# define __lzo_HAVE_noreturn 1 -#else -# define __lzo_noreturn -#endif -#if !defined(__lzo_nothrow) -#if (LZO_CC_GNUC >= 0x030300ul) -# define __lzo_nothrow __attribute__((__nothrow__)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) && defined(__cplusplus) -# define __lzo_nothrow __declspec(nothrow) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) -# define __lzo_nothrow __attribute__((__nothrow__)) -#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_nothrow __attribute__((__nothrow__)) -#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) -# define __lzo_nothrow __declspec(nothrow) -#endif -#endif -#if defined(__lzo_nothrow) -# define __lzo_HAVE_nothrow 1 -#else -# define __lzo_nothrow -#endif -#if !defined(__lzo_restrict) -#if (LZO_CC_GNUC >= 0x030400ul) -# define __lzo_restrict __restrict__ -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) -# define __lzo_restrict __restrict__ -#elif (LZO_CC_LLVM) -# define __lzo_restrict __restrict__ -#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) -# define __lzo_restrict __restrict -#endif -#endif -#if defined(__lzo_restrict) -# define __lzo_HAVE_restrict 1 -#else -# define __lzo_restrict -#endif -#if !defined(__lzo_likely) && !defined(__lzo_unlikely) -#if (LZO_CC_GNUC >= 0x030200ul) -# define __lzo_likely(e) (__builtin_expect(!!(e),1)) -# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) -# define __lzo_likely(e) (__builtin_expect(!!(e),1)) -# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) -#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_likely(e) (__builtin_expect(!!(e),1)) -# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) -#endif -#endif -#if defined(__lzo_likely) -# define __lzo_HAVE_likely 1 -#else -# define __lzo_likely(e) (e) -#endif -#if defined(__lzo_unlikely) -# define __lzo_HAVE_unlikely 1 -#else -# define __lzo_unlikely(e) (e) -#endif -#if !defined(LZO_UNUSED) -# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) -# define LZO_UNUSED(var) ((void) &var) -# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) -# define LZO_UNUSED(var) if (&var) ; else -# elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define LZO_UNUSED(var) ((void) var) -# elif (LZO_CC_MSC && (_MSC_VER < 900)) -# define LZO_UNUSED(var) if (&var) ; else -# elif (LZO_CC_KEILC) -# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];} -# elif (LZO_CC_PACIFICC) -# define LZO_UNUSED(var) ((void) sizeof(var)) -# elif (LZO_CC_WATCOMC) && defined(__cplusplus) -# define LZO_UNUSED(var) ((void) var) -# else -# define LZO_UNUSED(var) ((void) &var) -# endif -#endif -#if !defined(LZO_UNUSED_FUNC) -# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) -# define LZO_UNUSED_FUNC(func) ((void) func) -# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) -# define LZO_UNUSED_FUNC(func) if (func) ; else -# elif (LZO_CC_LLVM) -# define LZO_UNUSED_FUNC(func) ((void) &func) -# elif (LZO_CC_MSC && (_MSC_VER < 900)) -# define LZO_UNUSED_FUNC(func) if (func) ; else -# elif (LZO_CC_MSC) -# define LZO_UNUSED_FUNC(func) ((void) &func) -# elif (LZO_CC_KEILC || LZO_CC_PELLESC) -# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];} -# else -# define LZO_UNUSED_FUNC(func) ((void) func) -# endif -#endif -#if !defined(LZO_UNUSED_LABEL) -# if (LZO_CC_WATCOMC) && defined(__cplusplus) -# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l -# elif (LZO_CC_INTELC || LZO_CC_WATCOMC) -# define LZO_UNUSED_LABEL(l) if (0) goto l -# else -# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l -# endif -#endif -#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) -# if 0 -# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var -# elif 0 && (LZO_CC_GNUC) -# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var -# else -# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init -# endif -#endif -#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) -# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) -# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; -# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) -# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)]; -# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) -# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; -# else -# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)]; -# endif -#endif -#if !defined(LZO_COMPILE_TIME_ASSERT) -# if (LZO_CC_AZTECC) -# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];} -# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) -# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; -# elif (LZO_CC_MSC && (_MSC_VER < 900)) -# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; -# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) -# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; -# else -# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];} -# endif -#endif -#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) -# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) -# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) -# define __lzo_cdecl __cdecl -# define __lzo_cdecl_atexit -# define __lzo_cdecl_main __cdecl -# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) -# define __lzo_cdecl_qsort __pascal -# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) -# define __lzo_cdecl_qsort _stdcall -# else -# define __lzo_cdecl_qsort __cdecl -# endif -# elif (LZO_CC_WATCOMC) -# define __lzo_cdecl __cdecl -# else -# define __lzo_cdecl __cdecl -# define __lzo_cdecl_atexit __cdecl -# define __lzo_cdecl_main __cdecl -# define __lzo_cdecl_qsort __cdecl -# endif -# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) -# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) -# define __lzo_cdecl_sighandler __pascal -# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) -# define __lzo_cdecl_sighandler _stdcall -# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) -# define __lzo_cdecl_sighandler __clrcall -# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) -# if defined(_DLL) -# define __lzo_cdecl_sighandler _far _cdecl _loadds -# elif defined(_MT) -# define __lzo_cdecl_sighandler _far _cdecl -# else -# define __lzo_cdecl_sighandler _cdecl -# endif -# else -# define __lzo_cdecl_sighandler __cdecl -# endif -#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) -# define __lzo_cdecl __cdecl -#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) -# define __lzo_cdecl cdecl -#endif -#if !defined(__lzo_cdecl) -# define __lzo_cdecl -#endif -#if !defined(__lzo_cdecl_atexit) -# define __lzo_cdecl_atexit -#endif -#if !defined(__lzo_cdecl_main) -# define __lzo_cdecl_main -#endif -#if !defined(__lzo_cdecl_qsort) -# define __lzo_cdecl_qsort -#endif -#if !defined(__lzo_cdecl_sighandler) -# define __lzo_cdecl_sighandler -#endif -#if !defined(__lzo_cdecl_va) -# define __lzo_cdecl_va __lzo_cdecl -#endif -#if !defined(LZO_CFG_NO_WINDOWS_H) -#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) -# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) -# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__) -# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) -# else -# define LZO_HAVE_WINDOWS_H 1 -# endif -#endif -#endif -#if (LZO_ARCH_ALPHA) -# define LZO_OPT_AVOID_UINT_INDEX 1 -# define LZO_OPT_AVOID_SHORT 1 -# define LZO_OPT_AVOID_USHORT 1 -#elif (LZO_ARCH_AMD64) -# define LZO_OPT_AVOID_INT_INDEX 1 -# define LZO_OPT_AVOID_UINT_INDEX 1 -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 -# define LZO_OPT_UNALIGNED64 1 -#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB) -#elif (LZO_ARCH_ARM) -# define LZO_OPT_AVOID_SHORT 1 -# define LZO_OPT_AVOID_USHORT 1 -#elif (LZO_ARCH_CRIS) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 -#elif (LZO_ARCH_I386) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 -#elif (LZO_ARCH_IA64) -# define LZO_OPT_AVOID_INT_INDEX 1 -# define LZO_OPT_AVOID_UINT_INDEX 1 -# define LZO_OPT_PREFER_POSTINC 1 -#elif (LZO_ARCH_M68K) -# define LZO_OPT_PREFER_POSTINC 1 -# define LZO_OPT_PREFER_PREDEC 1 -# if defined(__mc68020__) && !defined(__mcoldfire__) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 -# endif -#elif (LZO_ARCH_MIPS) -# define LZO_OPT_AVOID_UINT_INDEX 1 -#elif (LZO_ARCH_POWERPC) -# define LZO_OPT_PREFER_PREINC 1 -# define LZO_OPT_PREFER_PREDEC 1 -# if defined(LZO_ABI_BIG_ENDIAN) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 -# endif -#elif (LZO_ARCH_S390) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 -# if (LZO_SIZEOF_SIZE_T == 8) -# define LZO_OPT_UNALIGNED64 1 -# endif -#elif (LZO_ARCH_SH) -# define LZO_OPT_PREFER_POSTINC 1 -# define LZO_OPT_PREFER_PREDEC 1 -#endif -#if !defined(LZO_CFG_NO_INLINE_ASM) -#if defined(LZO_CC_LLVM) -# define LZO_CFG_NO_INLINE_ASM 1 -#endif -#endif -#if !defined(LZO_CFG_NO_UNALIGNED) -#if defined(LZO_ABI_NEUTRAL_ENDIAN) || defined(LZO_ARCH_GENERIC) -# define LZO_CFG_NO_UNALIGNED 1 -#endif -#endif -#if defined(LZO_CFG_NO_UNALIGNED) -# undef LZO_OPT_UNALIGNED16 -# undef LZO_OPT_UNALIGNED32 -# undef LZO_OPT_UNALIGNED64 -#endif -#if defined(LZO_CFG_NO_INLINE_ASM) -#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) -# define LZO_ASM_SYNTAX_MSC 1 -#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) -#elif (LZO_ARCH_I386 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) -# define LZO_ASM_SYNTAX_GNUC 1 -#elif (LZO_ARCH_AMD64 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) -# define LZO_ASM_SYNTAX_GNUC 1 -#endif -#if (LZO_ASM_SYNTAX_GNUC) -#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) -# define __LZO_ASM_CLOBBER "ax" -#elif (LZO_CC_INTELC) -# define __LZO_ASM_CLOBBER "memory" -#else -# define __LZO_ASM_CLOBBER "cc", "memory" -#endif -#endif -#if defined(__LZO_INFOSTR_MM) -#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) -# define __LZO_INFOSTR_MM "" -#elif defined(LZO_INFO_MM) -# define __LZO_INFOSTR_MM "." LZO_INFO_MM -#else -# define __LZO_INFOSTR_MM "" -#endif -#if defined(__LZO_INFOSTR_PM) -#elif defined(LZO_INFO_ABI_PM) -# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM -#else -# define __LZO_INFOSTR_PM "" -#endif -#if defined(__LZO_INFOSTR_ENDIAN) -#elif defined(LZO_INFO_ABI_ENDIAN) -# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN -#else -# define __LZO_INFOSTR_ENDIAN "" -#endif -#if defined(__LZO_INFOSTR_OSNAME) -#elif defined(LZO_INFO_OS_CONSOLE) -# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE -#elif defined(LZO_INFO_OS_POSIX) -# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX -#else -# define __LZO_INFOSTR_OSNAME LZO_INFO_OS -#endif -#if defined(__LZO_INFOSTR_LIBC) -#elif defined(LZO_INFO_LIBC) -# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC -#else -# define __LZO_INFOSTR_LIBC "" -#endif -#if defined(__LZO_INFOSTR_CCVER) -#elif defined(LZO_INFO_CCVER) -# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER -#else -# define __LZO_INFOSTR_CCVER "" -#endif -#define LZO_INFO_STRING \ - LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ - " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER - -#endif - -#endif - -#undef LZO_HAVE_CONFIG_H -#include "minilzo.h" - -#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x2030) -# error "version mismatch in miniLZO source files" -#endif - -#ifdef MINILZO_HAVE_CONFIG_H -# define LZO_HAVE_CONFIG_H -#endif - -#ifndef __LZO_CONF_H -#define __LZO_CONF_H - -#if !defined(__LZO_IN_MINILZO) -#if defined(LZO_CFG_FREESTANDING) -# define LZO_LIBC_FREESTANDING 1 -# define LZO_OS_FREESTANDING 1 -# define ACC_LIBC_FREESTANDING 1 -# define ACC_OS_FREESTANDING 1 -#endif -#if defined(LZO_CFG_NO_UNALIGNED) -# define ACC_CFG_NO_UNALIGNED 1 -#endif -#if defined(LZO_ARCH_GENERIC) -# define ACC_ARCH_GENERIC 1 -#endif -#if defined(LZO_ABI_NEUTRAL_ENDIAN) -# define ACC_ABI_NEUTRAL_ENDIAN 1 -#endif -#if defined(LZO_HAVE_CONFIG_H) -# define ACC_CONFIG_NO_HEADER 1 -#endif -#if defined(LZO_CFG_EXTRA_CONFIG_HEADER) -# include LZO_CFG_EXTRA_CONFIG_HEADER -#endif -#if defined(__LZOCONF_H) || defined(__LZOCONF_H_INCLUDED) -# error "include this file first" -#endif -#include "lzo/lzoconf.h" -#endif - -#if (LZO_VERSION < 0x02000) || !defined(__LZOCONF_H_INCLUDED) -# error "version mismatch" -#endif - -#if (LZO_CC_BORLANDC && LZO_ARCH_I086) -# pragma option -h -#endif - -#if (LZO_CC_MSC && (_MSC_VER >= 1000)) -# pragma warning(disable: 4127 4701) -#endif -#if (LZO_CC_MSC && (_MSC_VER >= 1300)) -# pragma warning(disable: 4820) -# pragma warning(disable: 4514 4710 4711) -#endif - -#if (LZO_CC_SUNPROC) -# pragma error_messages(off,E_END_OF_LOOP_CODE_NOT_REACHED) -# pragma error_messages(off,E_LOOP_NOT_ENTERED_AT_TOP) -#endif - -#if defined(__LZO_MMODEL_HUGE) && (!LZO_HAVE_MM_HUGE_PTR) -# error "this should not happen - check defines for __huge" -#endif - -#if defined(__LZO_IN_MINILZO) || defined(LZO_CFG_FREESTANDING) -#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) -# define ACC_WANT_ACC_INCD_H 1 -# define ACC_WANT_ACC_INCE_H 1 -# define ACC_WANT_ACC_INCI_H 1 -#elif 1 -# include -#else -# define ACC_WANT_ACC_INCD_H 1 -#endif - -#if (LZO_ARCH_I086) -# define ACC_MM_AHSHIFT LZO_MM_AHSHIFT -# define ACC_PTR_FP_OFF(x) (((const unsigned __far*)&(x))[0]) -# define ACC_PTR_FP_SEG(x) (((const unsigned __far*)&(x))[1]) -# define ACC_PTR_MK_FP(s,o) ((void __far*)(((unsigned long)(s)<<16)+(unsigned)(o))) -#endif - -#if !defined(lzo_uintptr_t) -# if defined(__LZO_MMODEL_HUGE) -# define lzo_uintptr_t unsigned long -# elif 1 && defined(LZO_OS_OS400) && (LZO_SIZEOF_VOID_P == 16) -# define __LZO_UINTPTR_T_IS_POINTER 1 - typedef char* lzo_uintptr_t; -# define lzo_uintptr_t lzo_uintptr_t -# elif (LZO_SIZEOF_SIZE_T == LZO_SIZEOF_VOID_P) -# define lzo_uintptr_t size_t -# elif (LZO_SIZEOF_LONG == LZO_SIZEOF_VOID_P) -# define lzo_uintptr_t unsigned long -# elif (LZO_SIZEOF_INT == LZO_SIZEOF_VOID_P) -# define lzo_uintptr_t unsigned int -# elif (LZO_SIZEOF_LONG_LONG == LZO_SIZEOF_VOID_P) -# define lzo_uintptr_t unsigned long long -# else -# define lzo_uintptr_t size_t -# endif -#endif -LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) - -#if 1 && !defined(LZO_CFG_FREESTANDING) -#if 1 && !defined(HAVE_STRING_H) -#define HAVE_STRING_H 1 -#endif -#if 1 && !defined(HAVE_MEMCMP) -#define HAVE_MEMCMP 1 -#endif -#if 1 && !defined(HAVE_MEMCPY) -#define HAVE_MEMCPY 1 -#endif -#if 1 && !defined(HAVE_MEMMOVE) -#define HAVE_MEMMOVE 1 -#endif -#if 1 && !defined(HAVE_MEMSET) -#define HAVE_MEMSET 1 -#endif -#endif - -#if 1 && defined(HAVE_STRING_H) -#include -#endif - -#if defined(LZO_CFG_FREESTANDING) -# undef HAVE_MEMCMP -# undef HAVE_MEMCPY -# undef HAVE_MEMMOVE -# undef HAVE_MEMSET -#endif - -#if !defined(HAVE_MEMCMP) -# undef memcmp -# define memcmp(a,b,c) lzo_memcmp(a,b,c) -#elif !defined(__LZO_MMODEL_HUGE) -# define lzo_memcmp(a,b,c) memcmp(a,b,c) -#endif -#if !defined(HAVE_MEMCPY) -# undef memcpy -# define memcpy(a,b,c) lzo_memcpy(a,b,c) -#elif !defined(__LZO_MMODEL_HUGE) -# define lzo_memcpy(a,b,c) memcpy(a,b,c) -#endif -#if !defined(HAVE_MEMMOVE) -# undef memmove -# define memmove(a,b,c) lzo_memmove(a,b,c) -#elif !defined(__LZO_MMODEL_HUGE) -# define lzo_memmove(a,b,c) memmove(a,b,c) -#endif -#if !defined(HAVE_MEMSET) -# undef memset -# define memset(a,b,c) lzo_memset(a,b,c) -#elif !defined(__LZO_MMODEL_HUGE) -# define lzo_memset(a,b,c) memset(a,b,c) -#endif - -#undef NDEBUG -#if defined(LZO_CFG_FREESTANDING) -# undef LZO_DEBUG -# define NDEBUG 1 -# undef assert -# define assert(e) ((void)0) -#else -# if !defined(LZO_DEBUG) -# define NDEBUG 1 -# endif -# include -#endif - -#if 0 && defined(__BOUNDS_CHECKING_ON) -# include -#else -# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt -# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) -#endif - -#if !defined(__lzo_inline) -# define __lzo_inline -#endif -#if !defined(__lzo_forceinline) -# define __lzo_forceinline -#endif -#if !defined(__lzo_noinline) -# define __lzo_noinline -#endif - -#if 1 -# define LZO_BYTE(x) ((unsigned char) (x)) -#else -# define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) -#endif - -#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) -#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) -#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c)) -#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c)) - -#define lzo_sizeof(type) ((lzo_uint) (sizeof(type))) - -#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array)))) - -#define LZO_SIZE(bits) (1u << (bits)) -#define LZO_MASK(bits) (LZO_SIZE(bits) - 1) - -#define LZO_LSIZE(bits) (1ul << (bits)) -#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1) - -#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) -#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) - -#if !defined(DMUL) -#if 0 - -# define DMUL(a,b) ((lzo_xint) ((lzo_uint32)(a) * (lzo_uint32)(b))) -#else -# define DMUL(a,b) ((lzo_xint) ((a) * (b))) -#endif -#endif - -#if 1 && !defined(LZO_CFG_NO_UNALIGNED) -#if 1 && (LZO_ARCH_AMD64 || LZO_ARCH_I386) -# if (LZO_SIZEOF_SHORT == 2) -# define LZO_UNALIGNED_OK_2 -# endif -# if (LZO_SIZEOF_INT == 4) -# define LZO_UNALIGNED_OK_4 -# endif -#endif -#endif - -#if defined(LZO_UNALIGNED_OK_2) - LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(short) == 2) -#endif -#if defined(LZO_UNALIGNED_OK_4) - LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32) == 4) -#elif defined(LZO_ALIGNED_OK_4) - LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32) == 4) -#endif - -#define MEMCPY8_DS(dest,src,len) \ - lzo_memcpy(dest,src,len); dest += len; src += len - -#define BZERO8_PTR(s,l,n) \ - lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) - -#define MEMCPY_DS(dest,src,len) \ - do *dest++ = *src++; while (--len > 0) - -__LZO_EXTERN_C int __lzo_init_done; -__LZO_EXTERN_C const char __lzo_copyright[]; -LZO_EXTERN(const lzo_bytep) lzo_copyright(void); - -#ifndef __LZO_PTR_H -#define __LZO_PTR_H - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(lzo_uintptr_t) -# if defined(__LZO_MMODEL_HUGE) -# define lzo_uintptr_t unsigned long -# else -# define lzo_uintptr_t acc_uintptr_t -# ifdef __ACC_INTPTR_T_IS_POINTER -# define __LZO_UINTPTR_T_IS_POINTER 1 -# endif -# endif -#endif - -#if (LZO_ARCH_I086) -#define PTR(a) ((lzo_bytep) (a)) -#define PTR_ALIGNED_4(a) ((ACC_PTR_FP_OFF(a) & 3) == 0) -#define PTR_ALIGNED2_4(a,b) (((ACC_PTR_FP_OFF(a) | ACC_PTR_FP_OFF(b)) & 3) == 0) -#elif (LZO_MM_PVP) -#define PTR(a) ((lzo_bytep) (a)) -#define PTR_ALIGNED_8(a) ((((lzo_uintptr_t)(a)) >> 61) == 0) -#define PTR_ALIGNED2_8(a,b) ((((lzo_uintptr_t)(a)|(lzo_uintptr_t)(b)) >> 61) == 0) -#else -#define PTR(a) ((lzo_uintptr_t) (a)) -#define PTR_LINEAR(a) PTR(a) -#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0) -#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0) -#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0) -#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0) -#endif - -#define PTR_LT(a,b) (PTR(a) < PTR(b)) -#define PTR_GE(a,b) (PTR(a) >= PTR(b)) -#define PTR_DIFF(a,b) (PTR(a) - PTR(b)) -#define pd(a,b) ((lzo_uint) ((a)-(b))) - -LZO_EXTERN(lzo_uintptr_t) -__lzo_ptr_linear(const lzo_voidp ptr); - -typedef union -{ - char a_char; - unsigned char a_uchar; - short a_short; - unsigned short a_ushort; - int a_int; - unsigned int a_uint; - long a_long; - unsigned long a_ulong; - lzo_int a_lzo_int; - lzo_uint a_lzo_uint; - lzo_int32 a_lzo_int32; - lzo_uint32 a_lzo_uint32; - ptrdiff_t a_ptrdiff_t; - lzo_uintptr_t a_lzo_uintptr_t; - lzo_voidp a_lzo_voidp; - void * a_void_p; - lzo_bytep a_lzo_bytep; - lzo_bytepp a_lzo_bytepp; - lzo_uintp a_lzo_uintp; - lzo_uint * a_lzo_uint_p; - lzo_uint32p a_lzo_uint32p; - lzo_uint32 * a_lzo_uint32_p; - unsigned char * a_uchar_p; - char * a_char_p; -} -lzo_full_align_t; - -#ifdef __cplusplus -} -#endif - -#endif - -#define LZO_DETERMINISTIC - -#define LZO_DICT_USE_PTR -#if 0 && (LZO_ARCH_I086) -# undef LZO_DICT_USE_PTR -#endif - -#if defined(LZO_DICT_USE_PTR) -# define lzo_dict_t const lzo_bytep -# define lzo_dict_p lzo_dict_t __LZO_MMODEL * -#else -# define lzo_dict_t lzo_uint -# define lzo_dict_p lzo_dict_t __LZO_MMODEL * -#endif - -#endif - -#if !defined(MINILZO_CFG_SKIP_LZO_PTR) - -LZO_PUBLIC(lzo_uintptr_t) -__lzo_ptr_linear(const lzo_voidp ptr) -{ - lzo_uintptr_t p; - -#if (LZO_ARCH_I086) - p = (((lzo_uintptr_t)(ACC_PTR_FP_SEG(ptr))) << (16 - ACC_MM_AHSHIFT)) + (ACC_PTR_FP_OFF(ptr)); -#elif (LZO_MM_PVP) - p = (lzo_uintptr_t) (ptr); - p = (p << 3) | (p >> 61); -#else - p = (lzo_uintptr_t) PTR_LINEAR(ptr); -#endif - - return p; -} - -LZO_PUBLIC(unsigned) -__lzo_align_gap(const lzo_voidp ptr, lzo_uint size) -{ -#if defined(__LZO_UINTPTR_T_IS_POINTER) - size_t n = (size_t) ptr; - n = (((n + size - 1) / size) * size) - n; -#else - lzo_uintptr_t p, n; - p = __lzo_ptr_linear(ptr); - n = (((p + size - 1) / size) * size) - p; -#endif - - assert(size > 0); - assert((long)n >= 0); - assert(n <= size); - return (unsigned)n; -} - -#endif - -/* If you use the LZO library in a product, I would appreciate that you - * keep this copyright string in the executable of your product. - */ - -const char __lzo_copyright[] = -#if !defined(__LZO_IN_MINLZO) - LZO_VERSION_STRING; -#else - "\r\n\n" - "LZO data compression library.\n" - "$Copyright: LZO (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Markus Franz Xaver Johannes Oberhumer\n" - "\n" - "http://www.oberhumer.com $\n\n" - "$Id: LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE " $\n" - "$Built: " __DATE__ " " __TIME__ " $\n" - "$Info: " LZO_INFO_STRING " $\n"; -#endif - -LZO_PUBLIC(const lzo_bytep) -lzo_copyright(void) -{ -#if (LZO_OS_DOS16 && LZO_CC_TURBOC) - return (lzo_voidp) __lzo_copyright; -#else - return (const lzo_bytep) __lzo_copyright; -#endif -} - -LZO_PUBLIC(unsigned) -lzo_version(void) -{ - return LZO_VERSION; -} - -LZO_PUBLIC(const char *) -lzo_version_string(void) -{ - return LZO_VERSION_STRING; -} - -LZO_PUBLIC(const char *) -lzo_version_date(void) -{ - return LZO_VERSION_DATE; -} - -LZO_PUBLIC(const lzo_charp) -_lzo_version_string(void) -{ - return LZO_VERSION_STRING; -} - -LZO_PUBLIC(const lzo_charp) -_lzo_version_date(void) -{ - return LZO_VERSION_DATE; -} - -#define LZO_BASE 65521u -#define LZO_NMAX 5552 - -#define LZO_DO1(buf,i) s1 += buf[i]; s2 += s1 -#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1); -#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2); -#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4); -#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8); - -LZO_PUBLIC(lzo_uint32) -lzo_adler32(lzo_uint32 adler, const lzo_bytep buf, lzo_uint len) -{ - lzo_uint32 s1 = adler & 0xffff; - lzo_uint32 s2 = (adler >> 16) & 0xffff; - unsigned k; - - if (buf == NULL) - return 1; - - while (len > 0) - { - k = len < LZO_NMAX ? (unsigned) len : LZO_NMAX; - len -= k; - if (k >= 16) do - { - LZO_DO16(buf,0); - buf += 16; - k -= 16; - } while (k >= 16); - if (k != 0) do - { - s1 += *buf++; - s2 += s1; - } while (--k > 0); - s1 %= LZO_BASE; - s2 %= LZO_BASE; - } - return (s2 << 16) | s1; -} - -#undef LZO_DO1 -#undef LZO_DO2 -#undef LZO_DO4 -#undef LZO_DO8 -#undef LZO_DO16 - -#if !defined(MINILZO_CFG_SKIP_LZO_STRING) -#undef lzo_memcmp -#undef lzo_memcpy -#undef lzo_memmove -#undef lzo_memset -#if !defined(__LZO_MMODEL_HUGE) -# undef LZO_HAVE_MM_HUGE_PTR -#endif -#define lzo_hsize_t lzo_uint -#define lzo_hvoid_p lzo_voidp -#define lzo_hbyte_p lzo_bytep -#define LZOLIB_PUBLIC(r,f) LZO_PUBLIC(r) f -#define lzo_hmemcmp lzo_memcmp -#define lzo_hmemcpy lzo_memcpy -#define lzo_hmemmove lzo_memmove -#define lzo_hmemset lzo_memset -#define __LZOLIB_HMEMCPY_CH_INCLUDED 1 -#if !defined(LZOLIB_PUBLIC) -# define LZOLIB_PUBLIC(r,f) r __LZOLIB_FUNCNAME(f) -#endif -LZOLIB_PUBLIC(int, lzo_hmemcmp) (const lzo_hvoid_p s1, const lzo_hvoid_p s2, lzo_hsize_t len) -{ -#if (LZO_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMCMP) - const lzo_hbyte_p p1 = (const lzo_hbyte_p) s1; - const lzo_hbyte_p p2 = (const lzo_hbyte_p) s2; - if __lzo_likely(len > 0) do - { - int d = *p1 - *p2; - if (d != 0) - return d; - p1++; p2++; - } while __lzo_likely(--len > 0); - return 0; -#else - return memcmp(s1, s2, len); -#endif -} -LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemcpy) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) -{ -#if (LZO_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMCPY) - lzo_hbyte_p p1 = (lzo_hbyte_p) dest; - const lzo_hbyte_p p2 = (const lzo_hbyte_p) src; - if (!(len > 0) || p1 == p2) - return dest; - do - *p1++ = *p2++; - while __lzo_likely(--len > 0); - return dest; -#else - return memcpy(dest, src, len); -#endif -} -LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemmove) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) -{ -#if (LZO_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMMOVE) - lzo_hbyte_p p1 = (lzo_hbyte_p) dest; - const lzo_hbyte_p p2 = (const lzo_hbyte_p) src; - if (!(len > 0) || p1 == p2) - return dest; - if (p1 < p2) - { - do - *p1++ = *p2++; - while __lzo_likely(--len > 0); - } - else - { - p1 += len; - p2 += len; - do - *--p1 = *--p2; - while __lzo_likely(--len > 0); - } - return dest; -#else - return memmove(dest, src, len); -#endif -} -LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int c, lzo_hsize_t len) -{ -#if (LZO_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMSET) - lzo_hbyte_p p = (lzo_hbyte_p) s; - if __lzo_likely(len > 0) do - *p++ = (unsigned char) c; - while __lzo_likely(--len > 0); - return s; -#else - return memset(s, c, len); -#endif -} -#undef LZOLIB_PUBLIC -#endif - -#if !defined(__LZO_IN_MINILZO) - -#define ACC_WANT_ACC_CHK_CH 1 -#undef ACCCHK_ASSERT - - ACCCHK_ASSERT_IS_SIGNED_T(lzo_int) - ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint) - - ACCCHK_ASSERT_IS_SIGNED_T(lzo_int32) - ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint32) - ACCCHK_ASSERT((LZO_UINT32_C(1) << (int)(8*sizeof(LZO_UINT32_C(1))-1)) > 0) - ACCCHK_ASSERT(sizeof(lzo_uint32) >= 4) - -#if !defined(__LZO_UINTPTR_T_IS_POINTER) - ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uintptr_t) -#endif - ACCCHK_ASSERT(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) - - ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_xint) - ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint32)) - ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint)) - ACCCHK_ASSERT(sizeof(lzo_xint) == sizeof(lzo_uint32) || sizeof(lzo_xint) == sizeof(lzo_uint)) - -#endif -#undef ACCCHK_ASSERT - -LZO_PUBLIC(int) -_lzo_config_check(void) -{ - lzo_bool r = 1; - union { unsigned char c[2*sizeof(lzo_xint)]; lzo_xint l[2]; } u; - lzo_uintptr_t p; - -#if !defined(LZO_CFG_NO_CONFIG_CHECK) -#if defined(LZO_ABI_BIG_ENDIAN) - u.l[0] = u.l[1] = 0; u.c[sizeof(lzo_xint) - 1] = 128; - r &= (u.l[0] == 128); -#endif -#if defined(LZO_ABI_LITTLE_ENDIAN) - u.l[0] = u.l[1] = 0; u.c[0] = 128; - r &= (u.l[0] == 128); -#endif -#if defined(LZO_UNALIGNED_OK_2) - p = (lzo_uintptr_t) (const lzo_voidp) &u.c[0]; - u.l[0] = u.l[1] = 0; - r &= ((* (const lzo_ushortp) (p+1)) == 0); -#endif -#if defined(LZO_UNALIGNED_OK_4) - p = (lzo_uintptr_t) (const lzo_voidp) &u.c[0]; - u.l[0] = u.l[1] = 0; - r &= ((* (const lzo_uint32p) (p+1)) == 0); -#endif -#endif - - LZO_UNUSED(u); LZO_UNUSED(p); - return r == 1 ? LZO_E_OK : LZO_E_ERROR; -} - -int __lzo_init_done = 0; - -LZO_PUBLIC(int) -__lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5, - int s6, int s7, int s8, int s9) -{ - int r; - -#if defined(__LZO_IN_MINILZO) -#elif (LZO_CC_MSC && ((_MSC_VER) < 700)) -#else -#define ACC_WANT_ACC_CHK_CH 1 -#undef ACCCHK_ASSERT -#define ACCCHK_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) -#endif -#undef ACCCHK_ASSERT - - __lzo_init_done = 1; - - if (v == 0) - return LZO_E_ERROR; - - r = (s1 == -1 || s1 == (int) sizeof(short)) && - (s2 == -1 || s2 == (int) sizeof(int)) && - (s3 == -1 || s3 == (int) sizeof(long)) && - (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) && - (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && - (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && - (s7 == -1 || s7 == (int) sizeof(char *)) && - (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) && - (s9 == -1 || s9 == (int) sizeof(lzo_callback_t)); - if (!r) - return LZO_E_ERROR; - - r = _lzo_config_check(); - if (r != LZO_E_OK) - return r; - - return r; -} - -#if !defined(__LZO_IN_MINILZO) - -#if (LZO_OS_WIN16 && LZO_CC_WATCOMC) && defined(__SW_BD) - -#if 0 -BOOL FAR PASCAL LibMain ( HANDLE hInstance, WORD wDataSegment, - WORD wHeapSize, LPSTR lpszCmdLine ) -#else -int __far __pascal LibMain ( int a, short b, short c, long d ) -#endif -{ - LZO_UNUSED(a); LZO_UNUSED(b); LZO_UNUSED(c); LZO_UNUSED(d); - return 1; -} - -#endif - -#endif - -#define do_compress _lzo1x_1_do_compress - -#if !defined(MINILZO_CFG_SKIP_LZO1X_1_COMPRESS) - -#define LZO_NEED_DICT_H -#define D_BITS 14 -#define D_INDEX1(d,p) d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5) -#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f) - -#ifndef __LZO_CONFIG1X_H -#define __LZO_CONFIG1X_H - -#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z) -# define LZO1X -#endif - -#if !defined(__LZO_IN_MINILZO) -#include "lzo/lzo1x.h" -#endif - -#define LZO_EOF_CODE -#undef LZO_DETERMINISTIC - -#define M1_MAX_OFFSET 0x0400 -#ifndef M2_MAX_OFFSET -#define M2_MAX_OFFSET 0x0800 -#endif -#define M3_MAX_OFFSET 0x4000 -#define M4_MAX_OFFSET 0xbfff - -#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET) - -#define M1_MIN_LEN 2 -#define M1_MAX_LEN 2 -#define M2_MIN_LEN 3 -#ifndef M2_MAX_LEN -#define M2_MAX_LEN 8 -#endif -#define M3_MIN_LEN 3 -#define M3_MAX_LEN 33 -#define M4_MIN_LEN 3 -#define M4_MAX_LEN 9 - -#define M1_MARKER 0 -#define M2_MARKER 64 -#define M3_MARKER 32 -#define M4_MARKER 16 - -#ifndef MIN_LOOKAHEAD -#define MIN_LOOKAHEAD (M2_MAX_LEN + 1) -#endif - -#if defined(LZO_NEED_DICT_H) - -#ifndef LZO_HASH -#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B -#endif -#define DL_MIN_LEN M2_MIN_LEN - -#ifndef __LZO_DICT_H -#define __LZO_DICT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(D_BITS) && defined(DBITS) -# define D_BITS DBITS -#endif -#if !defined(D_BITS) -# error "D_BITS is not defined" -#endif -#if (D_BITS < 16) -# define D_SIZE LZO_SIZE(D_BITS) -# define D_MASK LZO_MASK(D_BITS) -#else -# define D_SIZE LZO_USIZE(D_BITS) -# define D_MASK LZO_UMASK(D_BITS) -#endif -#define D_HIGH ((D_MASK >> 1) + 1) - -#if !defined(DD_BITS) -# define DD_BITS 0 -#endif -#define DD_SIZE LZO_SIZE(DD_BITS) -#define DD_MASK LZO_MASK(DD_BITS) - -#if !defined(DL_BITS) -# define DL_BITS (D_BITS - DD_BITS) -#endif -#if (DL_BITS < 16) -# define DL_SIZE LZO_SIZE(DL_BITS) -# define DL_MASK LZO_MASK(DL_BITS) -#else -# define DL_SIZE LZO_USIZE(DL_BITS) -# define DL_MASK LZO_UMASK(DL_BITS) -#endif - -#if (D_BITS != DL_BITS + DD_BITS) -# error "D_BITS does not match" -#endif -#if (D_BITS < 8 || D_BITS > 18) -# error "invalid D_BITS" -#endif -#if (DL_BITS < 8 || DL_BITS > 20) -# error "invalid DL_BITS" -#endif -#if (DD_BITS < 0 || DD_BITS > 6) -# error "invalid DD_BITS" -#endif - -#if !defined(DL_MIN_LEN) -# define DL_MIN_LEN 3 -#endif -#if !defined(DL_SHIFT) -# define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN) -#endif - -#define LZO_HASH_GZIP 1 -#define LZO_HASH_GZIP_INCREMENTAL 2 -#define LZO_HASH_LZO_INCREMENTAL_A 3 -#define LZO_HASH_LZO_INCREMENTAL_B 4 - -#if !defined(LZO_HASH) -# error "choose a hashing strategy" -#endif - -#undef DM -#undef DX - -#if (DL_MIN_LEN == 3) -# define _DV2_A(p,shift1,shift2) \ - (((( (lzo_xint)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2]) -# define _DV2_B(p,shift1,shift2) \ - (((( (lzo_xint)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0]) -# define _DV3_B(p,shift1,shift2,shift3) \ - ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0]) -#elif (DL_MIN_LEN == 2) -# define _DV2_A(p,shift1,shift2) \ - (( (lzo_xint)(p[0]) << shift1) ^ p[1]) -# define _DV2_B(p,shift1,shift2) \ - (( (lzo_xint)(p[1]) << shift1) ^ p[2]) -#else -# error "invalid DL_MIN_LEN" -#endif -#define _DV_A(p,shift) _DV2_A(p,shift,shift) -#define _DV_B(p,shift) _DV2_B(p,shift,shift) -#define DA2(p,s1,s2) \ - (((((lzo_xint)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0]) -#define DS2(p,s1,s2) \ - (((((lzo_xint)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0]) -#define DX2(p,s1,s2) \ - (((((lzo_xint)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0]) -#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0]) -#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0]) -#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0]) -#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s))) -#define DM(v) DMS(v,0) - -#if (LZO_HASH == LZO_HASH_GZIP) -# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT)) - -#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL) -# define __LZO_HASH_INCREMENTAL -# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT) -# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2]) -# define _DINDEX(dv,p) (dv) -# define DVAL_LOOKAHEAD DL_MIN_LEN - -#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A) -# define __LZO_HASH_INCREMENTAL -# define DVAL_FIRST(dv,p) dv = _DV_A((p),5) -# define DVAL_NEXT(dv,p) \ - dv ^= (lzo_xint)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2]) -# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) -# define DVAL_LOOKAHEAD DL_MIN_LEN - -#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B) -# define __LZO_HASH_INCREMENTAL -# define DVAL_FIRST(dv,p) dv = _DV_B((p),5) -# define DVAL_NEXT(dv,p) \ - dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_xint)(p[2]) << (2*5))) -# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) -# define DVAL_LOOKAHEAD DL_MIN_LEN - -#else -# error "choose a hashing strategy" -#endif - -#ifndef DINDEX -#define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS) -#endif -#if !defined(DINDEX1) && defined(D_INDEX1) -#define DINDEX1 D_INDEX1 -#endif -#if !defined(DINDEX2) && defined(D_INDEX2) -#define DINDEX2 D_INDEX2 -#endif - -#if !defined(__LZO_HASH_INCREMENTAL) -# define DVAL_FIRST(dv,p) ((void) 0) -# define DVAL_NEXT(dv,p) ((void) 0) -# define DVAL_LOOKAHEAD 0 -#endif - -#if !defined(DVAL_ASSERT) -#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) -static void DVAL_ASSERT(lzo_xint dv, const lzo_bytep p) -{ - lzo_xint df; - DVAL_FIRST(df,(p)); - assert(DINDEX(dv,p) == DINDEX(df,p)); -} -#else -# define DVAL_ASSERT(dv,p) ((void) 0) -#endif -#endif - -#if defined(LZO_DICT_USE_PTR) -# define DENTRY(p,in) (p) -# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex] -#else -# define DENTRY(p,in) ((lzo_uint) ((p)-(in))) -# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex] -#endif - -#if (DD_BITS == 0) - -# define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in) -# define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in) -# define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in) - -#else - -# define UPDATE_D(dict,drun,dv,p,in) \ - dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK -# define UPDATE_I(dict,drun,index,p,in) \ - dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK -# define UPDATE_P(ptr,drun,p,in) \ - (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK - -#endif - -#if defined(LZO_DICT_USE_PTR) - -#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ - (m_pos == NULL || (m_off = pd(ip, m_pos)) > max_offset) - -#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ - (BOUNDS_CHECKING_OFF_IN_EXPR(( \ - m_pos = ip - (lzo_uint) PTR_DIFF(ip,m_pos), \ - PTR_LT(m_pos,in) || \ - (m_off = (lzo_uint) PTR_DIFF(ip,m_pos)) <= 0 || \ - m_off > max_offset ))) - -#else - -#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ - (m_off == 0 || \ - ((m_off = pd(ip, in) - m_off) > max_offset) || \ - (m_pos = (ip) - (m_off), 0) ) - -#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ - (pd(ip, in) <= m_off || \ - ((m_off = pd(ip, in) - m_off) > max_offset) || \ - (m_pos = (ip) - (m_off), 0) ) - -#endif - -#if defined(LZO_DETERMINISTIC) -# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET -#else -# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET -#endif - -#ifdef __cplusplus -} -#endif - -#endif - -#endif - -#endif - -#define DO_COMPRESS lzo1x_1_compress - -static __lzo_noinline lzo_uint -do_compress ( const lzo_bytep in , lzo_uint in_len, - lzo_bytep out, lzo_uintp out_len, - lzo_voidp wrkmem ) -{ - register const lzo_bytep ip; - lzo_bytep op; - const lzo_bytep const in_end = in + in_len; - const lzo_bytep const ip_end = in + in_len - M2_MAX_LEN - 5; - const lzo_bytep ii; - lzo_dict_p const dict = (lzo_dict_p) wrkmem; - - op = out; - ip = in; - ii = ip; - - ip += 4; - for (;;) - { - register const lzo_bytep m_pos; - lzo_uint m_off; - lzo_uint m_len; - lzo_uint dindex; - - DINDEX1(dindex,ip); - GINDEX(m_pos,m_off,dict,dindex,in); - if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) - goto literal; -#if 1 - if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) - goto try_match; - DINDEX2(dindex,ip); -#endif - GINDEX(m_pos,m_off,dict,dindex,in); - if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) - goto literal; - if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) - goto try_match; - goto literal; - -try_match: -#if 1 && defined(LZO_UNALIGNED_OK_2) - if (* (const lzo_ushortp) m_pos != * (const lzo_ushortp) ip) -#else - if (m_pos[0] != ip[0] || m_pos[1] != ip[1]) -#endif - { - } - else - { - if __lzo_likely(m_pos[2] == ip[2]) - { -#if 0 - if (m_off <= M2_MAX_OFFSET) - goto match; - if (lit <= 3) - goto match; - if (lit == 3) - { - assert(op - 2 > out); op[-2] |= LZO_BYTE(3); - *op++ = *ii++; *op++ = *ii++; *op++ = *ii++; - goto code_match; - } - if (m_pos[3] == ip[3]) -#endif - goto match; - } - else - { -#if 0 -#if 0 - if (m_off <= M1_MAX_OFFSET && lit > 0 && lit <= 3) -#else - if (m_off <= M1_MAX_OFFSET && lit == 3) -#endif - { - register lzo_uint t; - - t = lit; - assert(op - 2 > out); op[-2] |= LZO_BYTE(t); - do *op++ = *ii++; while (--t > 0); - assert(ii == ip); - m_off -= 1; - *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2)); - *op++ = LZO_BYTE(m_off >> 2); - ip += 2; - goto match_done; - } -#endif - } - } - -literal: - UPDATE_I(dict,0,dindex,ip,in); - ++ip; - if __lzo_unlikely(ip >= ip_end) - break; - continue; - -match: - UPDATE_I(dict,0,dindex,ip,in); - if (pd(ip,ii) > 0) - { - register lzo_uint t = pd(ip,ii); - - if (t <= 3) - { - assert(op - 2 > out); - op[-2] |= LZO_BYTE(t); - } - else if (t <= 18) - *op++ = LZO_BYTE(t - 3); - else - { - register lzo_uint tt = t - 18; - - *op++ = 0; - while (tt > 255) - { - tt -= 255; - *op++ = 0; - } - assert(tt > 0); - *op++ = LZO_BYTE(tt); - } - do *op++ = *ii++; while (--t > 0); - } - - assert(ii == ip); - ip += 3; - if (m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++ || - m_pos[6] != *ip++ || m_pos[7] != *ip++ || m_pos[8] != *ip++ -#ifdef LZO1Y - || m_pos[ 9] != *ip++ || m_pos[10] != *ip++ || m_pos[11] != *ip++ - || m_pos[12] != *ip++ || m_pos[13] != *ip++ || m_pos[14] != *ip++ -#endif - ) - { - --ip; - m_len = pd(ip, ii); - assert(m_len >= 3); assert(m_len <= M2_MAX_LEN); - - if (m_off <= M2_MAX_OFFSET) - { - m_off -= 1; -#if defined(LZO1X) - *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); - *op++ = LZO_BYTE(m_off >> 3); -#elif defined(LZO1Y) - *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); - *op++ = LZO_BYTE(m_off >> 2); -#endif - } - else if (m_off <= M3_MAX_OFFSET) - { - m_off -= 1; - *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); - goto m3_m4_offset; - } - else -#if defined(LZO1X) - { - m_off -= 0x4000; - assert(m_off > 0); assert(m_off <= 0x7fff); - *op++ = LZO_BYTE(M4_MARKER | - ((m_off & 0x4000) >> 11) | (m_len - 2)); - goto m3_m4_offset; - } -#elif defined(LZO1Y) - goto m4_match; -#endif - } - else - { - { - const lzo_bytep end = in_end; - const lzo_bytep m = m_pos + M2_MAX_LEN + 1; - while (ip < end && *m == *ip) - m++, ip++; - m_len = pd(ip, ii); - } - assert(m_len > M2_MAX_LEN); - - if (m_off <= M3_MAX_OFFSET) - { - m_off -= 1; - if (m_len <= 33) - *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); - else - { - m_len -= 33; - *op++ = M3_MARKER | 0; - goto m3_m4_len; - } - } - else - { -#if defined(LZO1Y) -m4_match: -#endif - m_off -= 0x4000; - assert(m_off > 0); assert(m_off <= 0x7fff); - if (m_len <= M4_MAX_LEN) - *op++ = LZO_BYTE(M4_MARKER | - ((m_off & 0x4000) >> 11) | (m_len - 2)); - else - { - m_len -= M4_MAX_LEN; - *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11)); -m3_m4_len: - while (m_len > 255) - { - m_len -= 255; - *op++ = 0; - } - assert(m_len > 0); - *op++ = LZO_BYTE(m_len); - } - } - -m3_m4_offset: - *op++ = LZO_BYTE((m_off & 63) << 2); - *op++ = LZO_BYTE(m_off >> 6); - } - -#if 0 -match_done: -#endif - ii = ip; - if __lzo_unlikely(ip >= ip_end) - break; - } - - *out_len = pd(op, out); - return pd(in_end,ii); -} - -LZO_PUBLIC(int) -DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len, - lzo_bytep out, lzo_uintp out_len, - lzo_voidp wrkmem ) -{ - lzo_bytep op = out; - lzo_uint t; - - if __lzo_unlikely(in_len <= M2_MAX_LEN + 5) - t = in_len; - else - { - t = do_compress(in,in_len,op,out_len,wrkmem); - op += *out_len; - } - - if (t > 0) - { - const lzo_bytep ii = in + in_len - t; - - if (op == out && t <= 238) - *op++ = LZO_BYTE(17 + t); - else if (t <= 3) - op[-2] |= LZO_BYTE(t); - else if (t <= 18) - *op++ = LZO_BYTE(t - 3); - else - { - lzo_uint tt = t - 18; - - *op++ = 0; - while (tt > 255) - { - tt -= 255; - *op++ = 0; - } - assert(tt > 0); - *op++ = LZO_BYTE(tt); - } - do *op++ = *ii++; while (--t > 0); - } - - *op++ = M4_MARKER | 1; - *op++ = 0; - *op++ = 0; - - *out_len = pd(op, out); - return LZO_E_OK; -} - -#endif - -#undef do_compress -#undef DO_COMPRESS -#undef LZO_HASH - -#undef LZO_TEST_OVERRUN -#undef DO_DECOMPRESS -#define DO_DECOMPRESS lzo1x_decompress - -#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS) - -#if defined(LZO_TEST_OVERRUN) -# if !defined(LZO_TEST_OVERRUN_INPUT) -# define LZO_TEST_OVERRUN_INPUT 2 -# endif -# if !defined(LZO_TEST_OVERRUN_OUTPUT) -# define LZO_TEST_OVERRUN_OUTPUT 2 -# endif -# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) -# define LZO_TEST_OVERRUN_LOOKBEHIND -# endif -#endif - -#undef TEST_IP -#undef TEST_OP -#undef TEST_LB -#undef TEST_LBO -#undef NEED_IP -#undef NEED_OP -#undef HAVE_TEST_IP -#undef HAVE_TEST_OP -#undef HAVE_NEED_IP -#undef HAVE_NEED_OP -#undef HAVE_ANY_IP -#undef HAVE_ANY_OP - -#if defined(LZO_TEST_OVERRUN_INPUT) -# if (LZO_TEST_OVERRUN_INPUT >= 1) -# define TEST_IP (ip < ip_end) -# endif -# if (LZO_TEST_OVERRUN_INPUT >= 2) -# define NEED_IP(x) \ - if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun -# endif -#endif - -#if defined(LZO_TEST_OVERRUN_OUTPUT) -# if (LZO_TEST_OVERRUN_OUTPUT >= 1) -# define TEST_OP (op <= op_end) -# endif -# if (LZO_TEST_OVERRUN_OUTPUT >= 2) -# undef TEST_OP -# define NEED_OP(x) \ - if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun -# endif -#endif - -#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) -# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun -# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun -#else -# define TEST_LB(m_pos) ((void) 0) -# define TEST_LBO(m_pos,o) ((void) 0) -#endif - -#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) -# define TEST_IP (ip < ip_end) -#endif - -#if defined(TEST_IP) -# define HAVE_TEST_IP -#else -# define TEST_IP 1 -#endif -#if defined(TEST_OP) -# define HAVE_TEST_OP -#else -# define TEST_OP 1 -#endif - -#if defined(NEED_IP) -# define HAVE_NEED_IP -#else -# define NEED_IP(x) ((void) 0) -#endif -#if defined(NEED_OP) -# define HAVE_NEED_OP -#else -# define NEED_OP(x) ((void) 0) -#endif - -#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) -# define HAVE_ANY_IP -#endif -#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) -# define HAVE_ANY_OP -#endif - -#undef __COPY4 -#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) - -#undef COPY4 -#if defined(LZO_UNALIGNED_OK_4) -# define COPY4(dst,src) __COPY4(dst,src) -#elif defined(LZO_ALIGNED_OK_4) -# define COPY4(dst,src) __COPY4((lzo_uintptr_t)(dst),(lzo_uintptr_t)(src)) -#endif - -#if defined(DO_DECOMPRESS) -LZO_PUBLIC(int) -DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, - lzo_bytep out, lzo_uintp out_len, - lzo_voidp wrkmem ) -#endif -{ - register lzo_bytep op; - register const lzo_bytep ip; - register lzo_uint t; -#if defined(COPY_DICT) - lzo_uint m_off; - const lzo_bytep dict_end; -#else - register const lzo_bytep m_pos; -#endif - - const lzo_bytep const ip_end = in + in_len; -#if defined(HAVE_ANY_OP) - lzo_bytep const op_end = out + *out_len; -#endif -#if defined(LZO1Z) - lzo_uint last_m_off = 0; -#endif - - LZO_UNUSED(wrkmem); - -#if defined(COPY_DICT) - if (dict) - { - if (dict_len > M4_MAX_OFFSET) - { - dict += dict_len - M4_MAX_OFFSET; - dict_len = M4_MAX_OFFSET; - } - dict_end = dict + dict_len; - } - else - { - dict_len = 0; - dict_end = NULL; - } -#endif - - *out_len = 0; - - op = out; - ip = in; - - if (*ip > 17) - { - t = *ip++ - 17; - if (t < 4) - goto match_next; - assert(t > 0); NEED_OP(t); NEED_IP(t+1); - do *op++ = *ip++; while (--t > 0); - goto first_literal_run; - } - - while (TEST_IP && TEST_OP) - { - t = *ip++; - if (t >= 16) - goto match; - if (t == 0) - { - NEED_IP(1); - while (*ip == 0) - { - t += 255; - ip++; - NEED_IP(1); - } - t += 15 + *ip++; - } - assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); -#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) -#if !defined(LZO_UNALIGNED_OK_4) - if (PTR_ALIGNED2_4(op,ip)) - { -#endif - COPY4(op,ip); - op += 4; ip += 4; - if (--t > 0) - { - if (t >= 4) - { - do { - COPY4(op,ip); - op += 4; ip += 4; t -= 4; - } while (t >= 4); - if (t > 0) do *op++ = *ip++; while (--t > 0); - } - else - do *op++ = *ip++; while (--t > 0); - } -#if !defined(LZO_UNALIGNED_OK_4) - } - else -#endif -#endif -#if !defined(LZO_UNALIGNED_OK_4) - { - *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; - do *op++ = *ip++; while (--t > 0); - } -#endif - -first_literal_run: - - t = *ip++; - if (t >= 16) - goto match; -#if defined(COPY_DICT) -#if defined(LZO1Z) - m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); - last_m_off = m_off; -#else - m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); -#endif - NEED_OP(3); - t = 3; COPY_DICT(t,m_off) -#else -#if defined(LZO1Z) - t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); - m_pos = op - t; - last_m_off = t; -#else - m_pos = op - (1 + M2_MAX_OFFSET); - m_pos -= t >> 2; - m_pos -= *ip++ << 2; -#endif - TEST_LB(m_pos); NEED_OP(3); - *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; -#endif - goto match_done; - - do { -match: - if (t >= 64) - { -#if defined(COPY_DICT) -#if defined(LZO1X) - m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); - t = (t >> 5) - 1; -#elif defined(LZO1Y) - m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); - t = (t >> 4) - 3; -#elif defined(LZO1Z) - m_off = t & 0x1f; - if (m_off >= 0x1c) - m_off = last_m_off; - else - { - m_off = 1 + (m_off << 6) + (*ip++ >> 2); - last_m_off = m_off; - } - t = (t >> 5) - 1; -#endif -#else -#if defined(LZO1X) - m_pos = op - 1; - m_pos -= (t >> 2) & 7; - m_pos -= *ip++ << 3; - t = (t >> 5) - 1; -#elif defined(LZO1Y) - m_pos = op - 1; - m_pos -= (t >> 2) & 3; - m_pos -= *ip++ << 2; - t = (t >> 4) - 3; -#elif defined(LZO1Z) - { - lzo_uint off = t & 0x1f; - m_pos = op; - if (off >= 0x1c) - { - assert(last_m_off > 0); - m_pos -= last_m_off; - } - else - { - off = 1 + (off << 6) + (*ip++ >> 2); - m_pos -= off; - last_m_off = off; - } - } - t = (t >> 5) - 1; -#endif - TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); - goto copy_match; -#endif - } - else if (t >= 32) - { - t &= 31; - if (t == 0) - { - NEED_IP(1); - while (*ip == 0) - { - t += 255; - ip++; - NEED_IP(1); - } - t += 31 + *ip++; - } -#if defined(COPY_DICT) -#if defined(LZO1Z) - m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); - last_m_off = m_off; -#else - m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); -#endif -#else -#if defined(LZO1Z) - { - lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); - m_pos = op - off; - last_m_off = off; - } -#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) - m_pos = op - 1; - m_pos -= (* (const lzo_ushortp) ip) >> 2; -#else - m_pos = op - 1; - m_pos -= (ip[0] >> 2) + (ip[1] << 6); -#endif -#endif - ip += 2; - } - else if (t >= 16) - { -#if defined(COPY_DICT) - m_off = (t & 8) << 11; -#else - m_pos = op; - m_pos -= (t & 8) << 11; -#endif - t &= 7; - if (t == 0) - { - NEED_IP(1); - while (*ip == 0) - { - t += 255; - ip++; - NEED_IP(1); - } - t += 7 + *ip++; - } -#if defined(COPY_DICT) -#if defined(LZO1Z) - m_off += (ip[0] << 6) + (ip[1] >> 2); -#else - m_off += (ip[0] >> 2) + (ip[1] << 6); -#endif - ip += 2; - if (m_off == 0) - goto eof_found; - m_off += 0x4000; -#if defined(LZO1Z) - last_m_off = m_off; -#endif -#else -#if defined(LZO1Z) - m_pos -= (ip[0] << 6) + (ip[1] >> 2); -#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) - m_pos -= (* (const lzo_ushortp) ip) >> 2; -#else - m_pos -= (ip[0] >> 2) + (ip[1] << 6); -#endif - ip += 2; - if (m_pos == op) - goto eof_found; - m_pos -= 0x4000; -#if defined(LZO1Z) - last_m_off = pd((const lzo_bytep)op, m_pos); -#endif -#endif - } - else - { -#if defined(COPY_DICT) -#if defined(LZO1Z) - m_off = 1 + (t << 6) + (*ip++ >> 2); - last_m_off = m_off; -#else - m_off = 1 + (t >> 2) + (*ip++ << 2); -#endif - NEED_OP(2); - t = 2; COPY_DICT(t,m_off) -#else -#if defined(LZO1Z) - t = 1 + (t << 6) + (*ip++ >> 2); - m_pos = op - t; - last_m_off = t; -#else - m_pos = op - 1; - m_pos -= t >> 2; - m_pos -= *ip++ << 2; -#endif - TEST_LB(m_pos); NEED_OP(2); - *op++ = *m_pos++; *op++ = *m_pos; -#endif - goto match_done; - } - -#if defined(COPY_DICT) - - NEED_OP(t+3-1); - t += 3-1; COPY_DICT(t,m_off) - -#else - - TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); -#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) -#if !defined(LZO_UNALIGNED_OK_4) - if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) - { - assert((op - m_pos) >= 4); -#else - if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) - { -#endif - COPY4(op,m_pos); - op += 4; m_pos += 4; t -= 4 - (3 - 1); - do { - COPY4(op,m_pos); - op += 4; m_pos += 4; t -= 4; - } while (t >= 4); - if (t > 0) do *op++ = *m_pos++; while (--t > 0); - } - else -#endif - { -copy_match: - *op++ = *m_pos++; *op++ = *m_pos++; - do *op++ = *m_pos++; while (--t > 0); - } - -#endif - -match_done: -#if defined(LZO1Z) - t = ip[-1] & 3; -#else - t = ip[-2] & 3; -#endif - if (t == 0) - break; - -match_next: - assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1); -#if 0 - do *op++ = *ip++; while (--t > 0); -#else - *op++ = *ip++; - if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } -#endif - t = *ip++; - } while (TEST_IP && TEST_OP); - } - -#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) - *out_len = pd(op, out); - return LZO_E_EOF_NOT_FOUND; -#endif - -eof_found: - assert(t == 1); - *out_len = pd(op, out); - return (ip == ip_end ? LZO_E_OK : - (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); - -#if defined(HAVE_NEED_IP) -input_overrun: - *out_len = pd(op, out); - return LZO_E_INPUT_OVERRUN; -#endif - -#if defined(HAVE_NEED_OP) -output_overrun: - *out_len = pd(op, out); - return LZO_E_OUTPUT_OVERRUN; -#endif - -#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) -lookbehind_overrun: - *out_len = pd(op, out); - return LZO_E_LOOKBEHIND_OVERRUN; -#endif -} - -#endif - -#define LZO_TEST_OVERRUN -#undef DO_DECOMPRESS -#define DO_DECOMPRESS lzo1x_decompress_safe - -#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS_SAFE) - -#if defined(LZO_TEST_OVERRUN) -# if !defined(LZO_TEST_OVERRUN_INPUT) -# define LZO_TEST_OVERRUN_INPUT 2 -# endif -# if !defined(LZO_TEST_OVERRUN_OUTPUT) -# define LZO_TEST_OVERRUN_OUTPUT 2 -# endif -# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) -# define LZO_TEST_OVERRUN_LOOKBEHIND -# endif -#endif - -#undef TEST_IP -#undef TEST_OP -#undef TEST_LB -#undef TEST_LBO -#undef NEED_IP -#undef NEED_OP -#undef HAVE_TEST_IP -#undef HAVE_TEST_OP -#undef HAVE_NEED_IP -#undef HAVE_NEED_OP -#undef HAVE_ANY_IP -#undef HAVE_ANY_OP - -#if defined(LZO_TEST_OVERRUN_INPUT) -# if (LZO_TEST_OVERRUN_INPUT >= 1) -# define TEST_IP (ip < ip_end) -# endif -# if (LZO_TEST_OVERRUN_INPUT >= 2) -# define NEED_IP(x) \ - if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun -# endif -#endif - -#if defined(LZO_TEST_OVERRUN_OUTPUT) -# if (LZO_TEST_OVERRUN_OUTPUT >= 1) -# define TEST_OP (op <= op_end) -# endif -# if (LZO_TEST_OVERRUN_OUTPUT >= 2) -# undef TEST_OP -# define NEED_OP(x) \ - if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun -# endif -#endif - -#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) -# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun -# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun -#else -# define TEST_LB(m_pos) ((void) 0) -# define TEST_LBO(m_pos,o) ((void) 0) -#endif - -#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) -# define TEST_IP (ip < ip_end) -#endif - -#if defined(TEST_IP) -# define HAVE_TEST_IP -#else -# define TEST_IP 1 -#endif -#if defined(TEST_OP) -# define HAVE_TEST_OP -#else -# define TEST_OP 1 -#endif - -#if defined(NEED_IP) -# define HAVE_NEED_IP -#else -# define NEED_IP(x) ((void) 0) -#endif -#if defined(NEED_OP) -# define HAVE_NEED_OP -#else -# define NEED_OP(x) ((void) 0) -#endif - -#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) -# define HAVE_ANY_IP -#endif -#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) -# define HAVE_ANY_OP -#endif - -#undef __COPY4 -#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) - -#undef COPY4 -#if defined(LZO_UNALIGNED_OK_4) -# define COPY4(dst,src) __COPY4(dst,src) -#elif defined(LZO_ALIGNED_OK_4) -# define COPY4(dst,src) __COPY4((lzo_uintptr_t)(dst),(lzo_uintptr_t)(src)) -#endif - -#if defined(DO_DECOMPRESS) -LZO_PUBLIC(int) -DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, - lzo_bytep out, lzo_uintp out_len, - lzo_voidp wrkmem ) -#endif -{ - register lzo_bytep op; - register const lzo_bytep ip; - register lzo_uint t; -#if defined(COPY_DICT) - lzo_uint m_off; - const lzo_bytep dict_end; -#else - register const lzo_bytep m_pos; -#endif - - const lzo_bytep const ip_end = in + in_len; -#if defined(HAVE_ANY_OP) - lzo_bytep const op_end = out + *out_len; -#endif -#if defined(LZO1Z) - lzo_uint last_m_off = 0; -#endif - - LZO_UNUSED(wrkmem); - -#if defined(COPY_DICT) - if (dict) - { - if (dict_len > M4_MAX_OFFSET) - { - dict += dict_len - M4_MAX_OFFSET; - dict_len = M4_MAX_OFFSET; - } - dict_end = dict + dict_len; - } - else - { - dict_len = 0; - dict_end = NULL; - } -#endif - - *out_len = 0; - - op = out; - ip = in; - - if (*ip > 17) - { - t = *ip++ - 17; - if (t < 4) - goto match_next; - assert(t > 0); NEED_OP(t); NEED_IP(t+1); - do *op++ = *ip++; while (--t > 0); - goto first_literal_run; - } - - while (TEST_IP && TEST_OP) - { - t = *ip++; - if (t >= 16) - goto match; - if (t == 0) - { - NEED_IP(1); - while (*ip == 0) - { - t += 255; - ip++; - NEED_IP(1); - } - t += 15 + *ip++; - } - assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); -#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) -#if !defined(LZO_UNALIGNED_OK_4) - if (PTR_ALIGNED2_4(op,ip)) - { -#endif - COPY4(op,ip); - op += 4; ip += 4; - if (--t > 0) - { - if (t >= 4) - { - do { - COPY4(op,ip); - op += 4; ip += 4; t -= 4; - } while (t >= 4); - if (t > 0) do *op++ = *ip++; while (--t > 0); - } - else - do *op++ = *ip++; while (--t > 0); - } -#if !defined(LZO_UNALIGNED_OK_4) - } - else -#endif -#endif -#if !defined(LZO_UNALIGNED_OK_4) - { - *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; - do *op++ = *ip++; while (--t > 0); - } -#endif - -first_literal_run: - - t = *ip++; - if (t >= 16) - goto match; -#if defined(COPY_DICT) -#if defined(LZO1Z) - m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); - last_m_off = m_off; -#else - m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); -#endif - NEED_OP(3); - t = 3; COPY_DICT(t,m_off) -#else -#if defined(LZO1Z) - t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); - m_pos = op - t; - last_m_off = t; -#else - m_pos = op - (1 + M2_MAX_OFFSET); - m_pos -= t >> 2; - m_pos -= *ip++ << 2; -#endif - TEST_LB(m_pos); NEED_OP(3); - *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; -#endif - goto match_done; - - do { -match: - if (t >= 64) - { -#if defined(COPY_DICT) -#if defined(LZO1X) - m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); - t = (t >> 5) - 1; -#elif defined(LZO1Y) - m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); - t = (t >> 4) - 3; -#elif defined(LZO1Z) - m_off = t & 0x1f; - if (m_off >= 0x1c) - m_off = last_m_off; - else - { - m_off = 1 + (m_off << 6) + (*ip++ >> 2); - last_m_off = m_off; - } - t = (t >> 5) - 1; -#endif -#else -#if defined(LZO1X) - m_pos = op - 1; - m_pos -= (t >> 2) & 7; - m_pos -= *ip++ << 3; - t = (t >> 5) - 1; -#elif defined(LZO1Y) - m_pos = op - 1; - m_pos -= (t >> 2) & 3; - m_pos -= *ip++ << 2; - t = (t >> 4) - 3; -#elif defined(LZO1Z) - { - lzo_uint off = t & 0x1f; - m_pos = op; - if (off >= 0x1c) - { - assert(last_m_off > 0); - m_pos -= last_m_off; - } - else - { - off = 1 + (off << 6) + (*ip++ >> 2); - m_pos -= off; - last_m_off = off; - } - } - t = (t >> 5) - 1; -#endif - TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); - goto copy_match; -#endif - } - else if (t >= 32) - { - t &= 31; - if (t == 0) - { - NEED_IP(1); - while (*ip == 0) - { - t += 255; - ip++; - NEED_IP(1); - } - t += 31 + *ip++; - } -#if defined(COPY_DICT) -#if defined(LZO1Z) - m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); - last_m_off = m_off; -#else - m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); -#endif -#else -#if defined(LZO1Z) - { - lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); - m_pos = op - off; - last_m_off = off; - } -#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) - m_pos = op - 1; - m_pos -= (* (const lzo_ushortp) ip) >> 2; -#else - m_pos = op - 1; - m_pos -= (ip[0] >> 2) + (ip[1] << 6); -#endif -#endif - ip += 2; - } - else if (t >= 16) - { -#if defined(COPY_DICT) - m_off = (t & 8) << 11; -#else - m_pos = op; - m_pos -= (t & 8) << 11; -#endif - t &= 7; - if (t == 0) - { - NEED_IP(1); - while (*ip == 0) - { - t += 255; - ip++; - NEED_IP(1); - } - t += 7 + *ip++; - } -#if defined(COPY_DICT) -#if defined(LZO1Z) - m_off += (ip[0] << 6) + (ip[1] >> 2); -#else - m_off += (ip[0] >> 2) + (ip[1] << 6); -#endif - ip += 2; - if (m_off == 0) - goto eof_found; - m_off += 0x4000; -#if defined(LZO1Z) - last_m_off = m_off; -#endif -#else -#if defined(LZO1Z) - m_pos -= (ip[0] << 6) + (ip[1] >> 2); -#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) - m_pos -= (* (const lzo_ushortp) ip) >> 2; -#else - m_pos -= (ip[0] >> 2) + (ip[1] << 6); -#endif - ip += 2; - if (m_pos == op) - goto eof_found; - m_pos -= 0x4000; -#if defined(LZO1Z) - last_m_off = pd((const lzo_bytep)op, m_pos); -#endif -#endif - } - else - { -#if defined(COPY_DICT) -#if defined(LZO1Z) - m_off = 1 + (t << 6) + (*ip++ >> 2); - last_m_off = m_off; -#else - m_off = 1 + (t >> 2) + (*ip++ << 2); -#endif - NEED_OP(2); - t = 2; COPY_DICT(t,m_off) -#else -#if defined(LZO1Z) - t = 1 + (t << 6) + (*ip++ >> 2); - m_pos = op - t; - last_m_off = t; -#else - m_pos = op - 1; - m_pos -= t >> 2; - m_pos -= *ip++ << 2; -#endif - TEST_LB(m_pos); NEED_OP(2); - *op++ = *m_pos++; *op++ = *m_pos; -#endif - goto match_done; - } - -#if defined(COPY_DICT) - - NEED_OP(t+3-1); - t += 3-1; COPY_DICT(t,m_off) - -#else - - TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); -#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) -#if !defined(LZO_UNALIGNED_OK_4) - if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) - { - assert((op - m_pos) >= 4); -#else - if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) - { -#endif - COPY4(op,m_pos); - op += 4; m_pos += 4; t -= 4 - (3 - 1); - do { - COPY4(op,m_pos); - op += 4; m_pos += 4; t -= 4; - } while (t >= 4); - if (t > 0) do *op++ = *m_pos++; while (--t > 0); - } - else -#endif - { -copy_match: - *op++ = *m_pos++; *op++ = *m_pos++; - do *op++ = *m_pos++; while (--t > 0); - } - -#endif - -match_done: -#if defined(LZO1Z) - t = ip[-1] & 3; -#else - t = ip[-2] & 3; -#endif - if (t == 0) - break; - -match_next: - assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1); -#if 0 - do *op++ = *ip++; while (--t > 0); -#else - *op++ = *ip++; - if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } -#endif - t = *ip++; - } while (TEST_IP && TEST_OP); - } - -#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) - *out_len = pd(op, out); - return LZO_E_EOF_NOT_FOUND; -#endif - -eof_found: - assert(t == 1); - *out_len = pd(op, out); - return (ip == ip_end ? LZO_E_OK : - (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); - -#if defined(HAVE_NEED_IP) -input_overrun: - *out_len = pd(op, out); - return LZO_E_INPUT_OVERRUN; -#endif - -#if defined(HAVE_NEED_OP) -output_overrun: - *out_len = pd(op, out); - return LZO_E_OUTPUT_OVERRUN; -#endif - -#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) -lookbehind_overrun: - *out_len = pd(op, out); - return LZO_E_LOOKBEHIND_OVERRUN; -#endif -} - -#endif - -/***** End of minilzo.c *****/ - diff --git a/n2n_v2/minilzo.h b/n2n_v2/minilzo.h deleted file mode 100644 index 0aff50e..0000000 --- a/n2n_v2/minilzo.h +++ /dev/null @@ -1,106 +0,0 @@ -/* minilzo.h -- mini subset of the LZO real-time data compression library - - This file is part of the LZO real-time data compression library. - - Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer - All Rights Reserved. - - The LZO library 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 2 of - the License, or (at your option) any later version. - - The LZO library 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 the LZO library; see the file COPYING. - If not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - Markus F.X.J. Oberhumer - - http://www.oberhumer.com/opensource/lzo/ - */ - -/* - * NOTE: - * the full LZO package can be found at - * http://www.oberhumer.com/opensource/lzo/ - */ - - -#ifndef __MINILZO_H -#define __MINILZO_H - -#define MINILZO_VERSION 0x2030 - -#ifdef __LZOCONF_H -# error "you cannot use both LZO and miniLZO" -#endif - -#undef LZO_HAVE_CONFIG_H -#include "lzoconf.h" - -#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION) -# error "version mismatch in header files" -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - - -/*********************************************************************** -// -************************************************************************/ - -/* Memory required for the wrkmem parameter. - * When the required size is 0, you can also pass a NULL pointer. - */ - -#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS -#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) -#define LZO1X_MEM_DECOMPRESS (0) - - -/* compression */ -LZO_EXTERN(int) -lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len, - lzo_bytep dst, lzo_uintp dst_len, - lzo_voidp wrkmem ); - -/* decompression */ -LZO_EXTERN(int) -lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len, - lzo_bytep dst, lzo_uintp dst_len, - lzo_voidp wrkmem /* NOT USED */ ); - -/* safe decompression with overrun testing */ -LZO_EXTERN(int) -lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len, - lzo_bytep dst, lzo_uintp dst_len, - lzo_voidp wrkmem /* NOT USED */ ); - - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* already included */ - diff --git a/n2n_v2/n2n.c b/n2n_v2/n2n.c deleted file mode 100644 index afec49c..0000000 --- a/n2n_v2/n2n.c +++ /dev/null @@ -1,481 +0,0 @@ -/* - * (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. - * - * 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 - * - * Code contributions courtesy of: - * Massimo Torquati - * Matt Gilg - * - */ - -#include "n2n.h" - -#include "minilzo.h" - -#include - -/* sglib hash table implementation */ - -SGLIB_DEFINE_LIST_FUNCTIONS(peer_info_t, PEER_INFO_COMPARATOR, next) -SGLIB_DEFINE_HASHED_CONTAINER_FUNCTIONS(peer_info_t, PEER_HASH_TAB_SIZE, peer_info_t_hash_function) - -unsigned int peer_info_t_hash_function(peer_info_t *e) { -#if N2N_MAC_SIZE != 6 - #error not implemented yet! -#else - short i = 0; - uint32_t tmp = 0; - /* Q: why is the hashing implemented like this? - * A: because the MAC addresses basically consist of two parts - * the first three bytes are a organisation unique identifier - * the second three bytes are a interface unique identifier - * therefore if all the (randomly) generated MAC addresses of the - * tun/tap interfaces all have the same organisation unique identifier - * the hashing performance is best if only the interface unique identifier - * is taken into account - */ - for(; i < N2N_MAC_SIZE / 2; i++) { - tmp |= (e->mac_addr[i] ^ e->mac_addr[(N2N_MAC_SIZE/2)+1]) - << (N2N_MAC_SIZE/2-1-i); - } - return tmp; -#endif -}; - - -const uint8_t broadcast_addr[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -const uint8_t multicast_addr[6] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x00 }; /* First 3 bytes are meaningful */ -const uint8_t ipv6_multicast_addr[6] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 }; /* First 2 bytes are meaningful */ - -/* ************************************** */ - -SOCKET open_socket(int local_port, int bind_any) { - SOCKET sock_fd; - struct sockaddr_in local_address; - int sockopt = 1; - - if((sock_fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { - traceEvent(TRACE_ERROR, "Unable to create socket [%s][%d]\n", - strerror(errno), sock_fd); - return(-1); - } - -#ifndef WIN32 - /* fcntl(sock_fd, F_SETFL, O_NONBLOCK); */ -#endif - - 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) { - traceEvent(TRACE_ERROR, "Bind error [%s]\n", strerror(errno)); - return(-1); - } - - return(sock_fd); -} - - - - - -int traceLevel = 2 /* NORMAL */; -int useSyslog = 0, syslog_opened = 0; - -#define N2N_TRACE_DATESIZE 32 -void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...) { - va_list va_ap; - - if(eventTraceLevel <= traceLevel) { - char buf[2048]; - char out_buf[640]; - char theDate[N2N_TRACE_DATESIZE]; - char *extra_msg = ""; - time_t theTime = time(NULL); -#ifdef WIN32 - 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), - * those without the headers !defined(USE_SYSLOG) - * those where it's parametrically off... - */ - - memset(buf, 0, sizeof(buf)); - strftime(theDate, N2N_TRACE_DATESIZE, "%d/%b/%Y %H:%M:%S", localtime(&theTime)); - - va_start (va_ap, format); - vsnprintf(buf, sizeof(buf)-1, format, va_ap); - va_end(va_ap); - - if(eventTraceLevel == 0 /* TRACE_ERROR */) - extra_msg = "ERROR: "; - else if(eventTraceLevel == 1 /* TRACE_WARNING */) - extra_msg = "WARNING: "; - - while(buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0'; - -#ifndef WIN32 - if(useSyslog) { - if(!syslog_opened) { - openlog("n2n", LOG_PID, LOG_DAEMON); - syslog_opened = 1; - } - - snprintf(out_buf, sizeof(out_buf), "%s%s", extra_msg, buf); - syslog(LOG_INFO, "%s", out_buf); - } else { - snprintf(out_buf, sizeof(out_buf), "%s [%11s:%4d] %s%s", theDate, file, line, extra_msg, buf); - printf("%s\n", out_buf); - fflush(stdout); - } -#else - /* this is the WIN32 code */ - 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); -#endif - } - -} - -/* *********************************************** */ - -/* addr should be in network order. Things are so much simpler that way. */ -char* intoa(uint32_t /* host order */ addr, char* buf, uint16_t buf_len) { - char *cp, *retStr; - uint8_t byteval; - int n; - - cp = &buf[buf_len]; - *--cp = '\0'; - - n = 4; - do { - byteval = addr & 0xff; - *--cp = byteval % 10 + '0'; - byteval /= 10; - if (byteval > 0) { - *--cp = byteval % 10 + '0'; - byteval /= 10; - if (byteval > 0) - *--cp = byteval + '0'; - } - *--cp = '.'; - addr >>= 8; - } while (--n > 0); - - /* Convert the string to lowercase */ - retStr = (char*)(cp+1); - - return(retStr); -} - -/* *********************************************** */ - -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); -} - -/* *********************************************** */ - -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 ); - - return is_broadcast || is_multicast || is_ipv6_multicast; - -} - -/* http://www.faqs.org/rfcs/rfc908.html */ - - -/* *********************************************** */ - -char* msg_type2str(uint16_t msg_type) { - switch(msg_type) { - case MSG_TYPE_REGISTER: return("MSG_TYPE_REGISTER"); - case MSG_TYPE_DEREGISTER: return("MSG_TYPE_DEREGISTER"); - case MSG_TYPE_PACKET: return("MSG_TYPE_PACKET"); - case MSG_TYPE_REGISTER_ACK: return("MSG_TYPE_REGISTER_ACK"); - case MSG_TYPE_REGISTER_SUPER: return("MSG_TYPE_REGISTER_SUPER"); - case MSG_TYPE_REGISTER_SUPER_ACK: return("MSG_TYPE_REGISTER_SUPER_ACK"); - case MSG_TYPE_REGISTER_SUPER_NAK: return("MSG_TYPE_REGISTER_SUPER_NAK"); - case MSG_TYPE_FEDERATION: return("MSG_TYPE_FEDERATION"); - default: return("???"); - } - - return("???"); -} - -/* *********************************************** */ - -void hexdump(const uint8_t * buf, size_t len) -{ - size_t i; - - if ( 0 == len ) { return; } - - for(i=0; i 0) && ((i % 16) == 0)) { printf("\n"); } - printf("%02X ", buf[i] & 0xFF); - } - - printf("\n"); -} - -/* *********************************************** */ - -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", - n2n_sw_version, n2n_sw_osName, n2n_sw_buildDate); -} - - - - -/** Find the peer entry in list with mac_addr equal to mac. - * - * Does not modify the list. - * - * @return NULL if not found; otherwise pointer to peer entry. - */ -peer_info_t * find_peer_by_mac( peer_info_t ** list, const n2n_mac_t mac ) -{ - peer_info_t tmp; - memcpy(tmp.mac_addr, mac, sizeof(n2n_mac_t)); - - return sglib_hashed_peer_info_t_find_member(list, &tmp); -} - - -/** Return the number of elements in the list. - * - */ -size_t peer_list_size( const struct peer_info * list ) -{ - size_t retval=0; - - while ( list ) - { - ++retval; - list = list->next; - } - - return retval; -} - -size_t hashed_peer_list_t_size(peer_info_t** htab) { - peer_info_t *ll; - struct sglib_hashed_peer_info_t_iterator it; - size_t retval = 0; - - for(ll=sglib_hashed_peer_info_t_it_init(&it,htab); ll!=NULL; ll=sglib_hashed_peer_info_t_it_next(&it)) { - ++retval; - } - - return retval; -} - -/** Add new to the head of list. If list is NULL; create it. - * - * 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 ) -{ - new->next = *list; - new->last_seen = time(NULL); - *list = new; -} - -size_t purge_with_function(struct peer_info ** peer_list, size_t(*purger)(struct peer_info ** peer_list, time_t purge_before)) { - time_t now = time(NULL); - size_t num_reg = 0; - - traceEvent(TRACE_INFO, "Purging old registrations"); - - num_reg = purger( peer_list, now-REGISTRATION_TIMEOUT ); - - traceEvent(TRACE_INFO, "Remove %ld registrations", num_reg); - - return num_reg; -} - -void dealloc_peer( peer_info_t* peer ) -{ - free(peer->sockets); - free(peer); -} - - -/** 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 ) -{ - struct peer_info *scan; - struct peer_info *prev; - size_t retval=0; - - scan = *peer_list; - prev = NULL; - while(scan != NULL) { - if(scan->last_seen < purge_before) { - struct peer_info *next = scan->next; - - if(prev == NULL) { - *peer_list = next; - } else { - prev->next = next; - } - ++retval; - dealloc_peer(scan); - scan = next; - } else { - prev = scan; - scan = scan->next; - } - } - return retval; -} - -size_t purge_hashed_peer_list_t(peer_info_t ** peer_list, time_t purge_before) { - peer_info_t *ll; - struct sglib_hashed_peer_info_t_iterator it; - size_t retval = 0; - - for(ll=sglib_hashed_peer_info_t_it_init(&it,peer_list); ll!=NULL; - ll=sglib_hashed_peer_info_t_it_next(&it)) { - if(ll->last_seen < purge_before) { - ++retval; - sglib_hashed_peer_info_t_delete(peer_list, ll); - dealloc_peer(ll); - } - } - - return retval; -} - -size_t purge_expired_registrations( struct peer_info ** peer_list ) { - return purge_with_function(peer_list, purge_peer_list); -} - -size_t hashed_purge_expired_registrations(peer_info_t ** peer_list) { - return purge_with_function(peer_list, purge_hashed_peer_list_t); -} - -size_t clear_hashed_peer_info_t_list(peer_info_t ** peer_list) { - peer_info_t *ll; - struct sglib_hashed_peer_info_t_iterator it; - size_t retval = 0; - - for(ll=sglib_hashed_peer_info_t_it_init(&it,peer_list); ll!=NULL; ll=sglib_hashed_peer_info_t_it_next(&it)) { - ++retval; - sglib_hashed_peer_info_t_delete(peer_list, ll); - dealloc_peer(ll); - } - - return retval; -} - -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 )); -} - -extern int str2mac( uint8_t * outmac /* 6 bytes */, const char * s ) -{ - size_t i; - - /* break it down as one case for the first "HH", the 5 x through loop for - * each ":HH" where HH is a two hex nibbles in ASCII. */ - - *outmac=hex2byte(s); - ++outmac; - s+=2; /* don't skip colon yet - helps generalise loop. */ - - for (i=1; i<6; ++i ) - { - s+=1; - *outmac=hex2byte(s); - ++outmac; - s+=2; - } - - return 0; /* ok */ -} - -extern char * sock_to_cstr( n2n_sock_str_t out, - 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 */ - 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", (a[0] & 0xff), - (a[1] & 0xff), (a[2] & 0xff), (a[3] & 0xff), 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 */ - { - case AF_INET: - 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; - } - - return 0; -} - diff --git a/n2n_v2/n2n_keyfile.c b/n2n_v2/n2n_keyfile.c deleted file mode 100644 index 56de3a1..0000000 --- a/n2n_v2/n2n_keyfile.c +++ /dev/null @@ -1,203 +0,0 @@ -/* (c) 2009 Richard Andrews */ -/* Contributions from: - * - Jozef Kralik - */ - -#include "n2n.h" -#include "n2n_keyfile.h" -#include -#include -#include -#include - - -#ifdef WIN32 -char *strsep( char **ppsz_string, const char *psz_delimiters ) -{ - char *p; - char *psz_string = *ppsz_string; - if( !psz_string ) - return NULL; - - p = strpbrk( psz_string, psz_delimiters ); - if( !p ) - { - *ppsz_string = NULL; - return psz_string; - } - *p++ = '\0'; - - *ppsz_string = p; - return psz_string; -} -#endif - - -/* Parse hex nibbles in ascii until a non-nibble character is found. Nibble - * characters are 0-9, a-f and A-F. - * - * Return number of bytes parsed into keyBuf or a negative error code. - */ -ssize_t n2n_parse_hex( uint8_t * keyBuf, - size_t keyLen, - const char * textKey, - size_t textLen) -{ - ssize_t retval=0; - uint8_t * pout=keyBuf; - size_t octet=0; - const char * textEnd; - const char * pbeg; - - textEnd = textKey+textLen; - pbeg=textKey; - - while ( ( pbeg + 1 < textEnd ) && ( retval < (ssize_t)keyLen ) ) - { - if ( 1 != sscanf( pbeg, "%02x", (unsigned int*)&octet ) ) - { - retval=-1; - break; - } - - *pout = (octet & 0xff); - ++pout; - ++retval; - pbeg += 2; - } - - return retval; -} - - -static int parseKeyLine( n2n_cipherspec_t * spec, - const char * linein ) -{ - /* parameters are separated by whitespace */ - char line[N2N_KEYFILE_LINESIZE]; - char * lp=line; - const char * token; - strncpy( line, linein, N2N_KEYFILE_LINESIZE ); - - memset( spec, 0, sizeof( n2n_cipherspec_t ) ); - - /* decode valid_from time */ - token = strsep( &lp, DELIMITERS ); - if ( !token ) { goto error; } - spec->valid_from = atol(token); - - /* decode valid_until time */ - token = strsep( &lp, DELIMITERS ); - if ( !token ) { goto error; } - spec->valid_until = atol(token); - - /* decode the transform number */ - token = strsep( &lp, DELIMITERS ); - if ( !token ) { goto error; } - spec->t = atoi(token); - - /* The reset if opaque key data */ - token = strsep( &lp, DELIMITERS ); - if ( !token ) { goto error; } - strncpy( (char *)spec->opaque, token, N2N_MAX_KEYSIZE ); - spec->opaque_size=strlen( (char *)spec->opaque); - - return 0; - -error: - return -1; -} - - -#define SEP "/" - - -int validCipherSpec( const n2n_cipherspec_t * k, - time_t now ) -{ - if ( k->valid_until < k->valid_from ) { goto bad; } - if ( k->valid_from > now ) { goto bad; } - if ( k->valid_until < now ) { goto bad; } - - return 0; - -bad: - return -1; -} - -/* Read key control file and return the number of specs stored or a negative - * error code. - * - * As the specs are read in the from and until time values are compared to - * present time. Only those keys which are valid are stored. - */ -int n2n_read_keyfile( n2n_cipherspec_t * specs, /* fill out this array of cipherspecs */ - size_t numspecs, /* number of slots in the array. */ - const char * ctrlfile_path ) /* path to control file */ -{ - /* Each line contains one cipherspec. */ - - int retval=0; - FILE * fp=NULL; - size_t idx=0; - time_t now = time(NULL); - - traceEvent( TRACE_DEBUG, "Reading '%s'\n", ctrlfile_path ); - - fp = fopen( ctrlfile_path, "r" ); - if ( fp ) - { - /* Read the file a line a time with fgets. */ - char line[N2N_KEYFILE_LINESIZE]; - size_t lineNum=0; - - while ( idx < numspecs ) - { - n2n_cipherspec_t * k = &(specs[idx]); - fgets( line, N2N_KEYFILE_LINESIZE, fp ); - ++lineNum; - - if ( strlen(line) > 1 ) - { - if ( 0 == parseKeyLine( k, line ) ) - { - if ( k->valid_until > now ) - { - traceEvent( TRACE_INFO, " --> [%u] from %lu, until %lu, transform=%hu, data=%s\n", - idx, k->valid_from, k->valid_until, k->t, k->opaque ); - - ++retval; - ++idx; - } - else - { - traceEvent( TRACE_INFO, " --X [%u] from %lu, until %lu, transform=%hu, data=%s\n", - idx, k->valid_from, k->valid_until, k->t, k->opaque ); - - } - } - else - { - traceEvent( TRACE_WARNING, "Failed to decode line %u\n", lineNum ); - } - } - - if ( feof(fp) ) - { - break; - } - - line[0]=0; /* this line has been consumed */ - } - - fclose( fp); - fp=NULL; - } - else - { - traceEvent( TRACE_ERROR, "Failed to open '%s'\n", ctrlfile_path ); - retval = -1; - } - - return retval; -} diff --git a/n2n_v2/n2n_transforms.h b/n2n_v2/n2n_transforms.h deleted file mode 100644 index effbc50..0000000 --- a/n2n_v2/n2n_transforms.h +++ /dev/null @@ -1,78 +0,0 @@ -/* (c) 2009 Richard Andrews */ - -#if !defined(N2N_TRANSFORMS_H_) -#define N2N_TRANSFORMS_H_ - -#include "n2n_keyfile.h" -#include "n2n_wire.h" - - -#define N2N_TRANSFORM_ID_INVAL 0 /* marks uninitialised data */ -#define N2N_TRANSFORM_ID_NULL 1 -#define N2N_TRANSFORM_ID_TWOFISH 2 -#define N2N_TRANSFORM_ID_AESCBC 3 -#define N2N_TRANSFORM_ID_LZO 4 -#define N2N_TRANSFORM_ID_TWOFISH_LZO 5 -#define N2N_TRANSFORM_ID_AESCBC_LZO 6 -#define N2N_TRANSFORM_ID_USER_START 64 -#define N2N_TRANSFORM_ID_MAX 65535 - - -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. */ -}; - -typedef struct n2n_tostat n2n_tostat_t; - - -typedef int (*n2n_transdeinit_f)( n2n_trans_op_t * arg ); -typedef int (*n2n_transaddspec_f)( n2n_trans_op_t * arg, - const n2n_cipherspec_t * cspec ); -typedef n2n_tostat_t (*n2n_transtick_f)( n2n_trans_op_t * arg, - time_t now ); - -typedef int (*n2n_transform_f)( n2n_trans_op_t * arg, - uint8_t * outbuf, - size_t out_len, - const uint8_t * inbuf, - size_t in_len ); - -/** Holds the info associated with a data transform plugin. - * - * When a packet arrives the transform ID is extracted. This defines the code - * 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. */ - - 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 */ -}; - -/* Setup a single twofish SA for single-key operation. */ -int transop_twofish_setup( n2n_trans_op_t * ttt, - n2n_sa_t sa_num, - uint8_t * encrypt_pwd, - uint32_t encrypt_pwd_len ); - -/* Initialise an empty transop ready to receive cipherspec elements. */ -int transop_twofish_init( n2n_trans_op_t * ttt ); -int transop_aes_init( n2n_trans_op_t * ttt ); -void transop_null_init( n2n_trans_op_t * ttt ); - -#endif /* #if !defined(N2N_TRANSFORMS_H_) */ - diff --git a/n2n_v2/n2n_wire.h b/n2n_v2/n2n_wire.h deleted file mode 100644 index 4e9c023..0000000 --- a/n2n_v2/n2n_wire.h +++ /dev/null @@ -1,380 +0,0 @@ -/* (c) 2009 Richard Andrews - * - * Contributions by: - * Luca Deri - * Lukasz Taczuk - */ - -#if !defined( N2N_WIRE_H_ ) -#define N2N_WIRE_H_ - -#include - -#if defined(WIN32) -#include "win32/n2n_win32.h" - -#if defined(__MINGW32__) -#include -#endif /* #ifdef __MINGW32__ */ - -#else /* #if defined(WIN32) */ -#include -#include -#include /* AF_INET and AF_INET6 */ -#endif /* #if defined(WIN32) */ - -#define N2N_PKT_VERSION 2 -#define N2N_DEFAULT_TTL 2 /* can be forwarded twice at most */ -#define N2N_COMMUNITY_SIZE 16 -#define N2N_MAC_SIZE 6 -#define N2N_COOKIE_SIZE 4 -#define N2N_PKT_BUF_SIZE 2048 -#define N2N_SOCKBUF_SIZE 64 /* string representation of INET or INET6 sockets */ - -typedef uint8_t n2n_community_t[N2N_COMMUNITY_SIZE]; -typedef uint8_t n2n_mac_t[N2N_MAC_SIZE]; -typedef uint8_t n2n_cookie_t[N2N_COOKIE_SIZE]; - -typedef char n2n_sock_str_t[N2N_SOCKBUF_SIZE]; /* tracing string buffer */ - -enum n2n_pc -{ - n2n_ping=0, /* Not used */ - n2n_register=1, /* Register edge to edge */ - n2n_deregister=2, /* Deregister this edge */ - n2n_packet=3, /* PACKET data content */ - n2n_register_ack=4, /* ACK of a registration from edge to edge */ - n2n_register_super=5, /* Register edge to supernode */ - n2n_register_super_ack=6, /* ACK from supernode to edge */ - n2n_register_super_nak=7, /* NAK from supernode to edge - registration refused */ - n2n_federation=8, /* Not used by edge */ - n2n_peer_info=9, /* Send info on a peer from sn to edge */ - n2n_query_peer=10 /* ask supernode for info on a peer */ -}; - -typedef enum n2n_pc n2n_pc_t; - -/* for the additional_flags present in some non-PACKET types */ -#define N2N_AFLAGS_LOCAL_SOCKET 0x0001 - -/* for the common header section */ -#define N2N_FLAGS_FROM_SUPERNODE 0x0020 - -/* The bits in flag that are the packet type */ -#define N2N_FLAGS_TYPE_MASK 0x001f /* 0 - 31 */ -#define N2N_FLAGS_BITS_MASK 0xffe0 - -#define IPV4_SIZE 4 -#define IPV6_SIZE 16 - -#define ETH_FRAMEHDRSIZE 14 -#define IP4_SRCOFFSET 12 - -#define N2N_AUTH_TOKEN_SIZE 32 /* bytes */ - - -#define N2N_EUNKNOWN -1 -#define N2N_ENOTIMPL -2 -#define N2N_EINVAL -3 -#define N2N_ENOSPACE -4 - - -typedef uint16_t n2n_flags_t; -typedef uint16_t n2n_transform_t; /* Encryption, compression type. */ -typedef uint32_t n2n_sa_t; /* security association number */ - -struct n2n_sock -{ - uint8_t family; /* AF_INET or AF_INET6; or 0 if invalid */ - uint16_t port; /* host order */ - union - { - uint8_t v6[IPV6_SIZE]; /* byte sequence */ - uint8_t v4[IPV4_SIZE]; /* byte sequence */ - } addr; -}; - -typedef struct n2n_sock n2n_sock_t; - -struct n2n_auth -{ - uint16_t scheme; /* What kind of auth */ - uint16_t toksize; /* Size of auth token */ - uint8_t token[N2N_AUTH_TOKEN_SIZE]; /* Auth data interpreted based on scheme */ -}; - -typedef struct n2n_auth n2n_auth_t; - - -struct n2n_common -{ - /* int version; */ - uint8_t ttl; - n2n_pc_t pc; - n2n_flags_t flags; - n2n_community_t community; -}; - -typedef struct n2n_common n2n_common_t; - -struct n2n_REGISTER -{ - n2n_cookie_t cookie; /* Link REGISTER and REGISTER_ACK */ - n2n_mac_t srcMac; /* MAC of registering party */ - n2n_mac_t dstMac; /* MAC of target edge */ - n2n_sock_t sock; /* when relaying by supernode */ -}; - -typedef struct n2n_REGISTER n2n_REGISTER_t; - -struct n2n_REGISTER_ACK -{ - n2n_cookie_t cookie; /* Return cookie from REGISTER */ - n2n_mac_t srcMac; /* MAC of acknowledging party (supernode or edge) */ - n2n_mac_t dstMac; /* Reflected MAC of registering edge from REGISTER */ - n2n_sock_t sock; /* Supernode's view of edge socket (IP Addr, port) */ -}; - -typedef struct n2n_REGISTER_ACK n2n_REGISTER_ACK_t; - -struct n2n_PACKET -{ - n2n_transform_t transform; -}; - -typedef struct n2n_PACKET n2n_PACKET_t; - -struct n2n_ETHFRAMEHDR -{ - n2n_mac_t srcMac; - n2n_mac_t dstMac; - /* uint16_t ethertype; */ /* is there a reason to use this? */ -}; - -typedef struct n2n_ETHFRAMEHDR n2n_ETHFRAMEHDR_t; - - -/* Linked with n2n_register_super in n2n_pc_t. Only from edge to supernode. */ -struct n2n_REGISTER_SUPER -{ - uint16_t aflags; /* additional flags */ - n2n_cookie_t cookie; /* Link REGISTER_SUPER and REGISTER_SUPER_ACK */ - uint16_t timeout; - n2n_mac_t edgeMac; /* MAC to register with edge sending socket */ - n2n_auth_t auth; /* Authentication scheme and tokens */ - n2n_sock_t local_sock; -}; - -typedef struct n2n_REGISTER_SUPER n2n_REGISTER_SUPER_t; - - -/* Linked with n2n_register_super_ack in n2n_pc_t. Only from supernode to edge. */ -struct n2n_REGISTER_SUPER_ACK -{ - n2n_cookie_t cookie; /* Return cookie from REGISTER_SUPER */ - n2n_mac_t edgeMac; /* MAC registered to edge sending socket */ - uint16_t lifetime; /* How long the registration will live */ - n2n_sock_t sock; /* Sending sockets associated with edgeMac */ - - /* The packet format provides additional supernode definitions here. - * uint8_t count, then for each count there is one - * n2n_sock_t. - */ - uint8_t num_sn; /* Number of supernodes that were send - * even if we cannot store them all. If - * non-zero then sn_bak is valid. */ - n2n_sock_t sn_bak; /* Socket of the first backup supernode */ - -}; - -typedef struct n2n_REGISTER_SUPER_ACK n2n_REGISTER_SUPER_ACK_t; - - -/* Linked with n2n_register_super_ack in n2n_pc_t. Only from supernode to edge. */ -struct n2n_REGISTER_SUPER_NAK -{ - n2n_cookie_t cookie; /* Return cookie from REGISTER_SUPER */ -}; - -typedef struct n2n_REGISTER_SUPER_NAK n2n_REGISTER_SUPER_NAK_t; - -struct n2n_PEER_INFO -{ - uint16_t aflags; - uint16_t timeout; - n2n_mac_t mac; - n2n_sock_t sockets[2]; -}; - -typedef struct n2n_PEER_INFO n2n_PEER_INFO_t; - -struct n2n_QUERY_PEER -{ - n2n_mac_t srcMac; - n2n_mac_t targetMac; -}; - -typedef struct n2n_QUERY_PEER n2n_QUERY_PEER_t; - -struct n2n_buf -{ - uint8_t * data; - size_t size; -}; - -typedef struct n2n_buf n2n_buf_t; - -int encode_uint8( uint8_t * base, - size_t * idx, - const uint8_t v ); - -int decode_uint8( uint8_t * out, - const uint8_t * base, - size_t * rem, - size_t * idx ); - -int encode_uint16( uint8_t * base, - size_t * idx, - const uint16_t v ); - -int decode_uint16( uint16_t * out, - const uint8_t * base, - size_t * rem, - size_t * idx ); - -int encode_uint32( uint8_t * base, - size_t * idx, - const uint32_t v ); - -int decode_uint32( uint32_t * out, - const uint8_t * base, - size_t * rem, - size_t * idx ); - -int encode_buf( uint8_t * base, - size_t * idx, - const void * p, - size_t s); - -int decode_buf( uint8_t * out, - size_t bufsize, - const uint8_t * base, - size_t * rem, - size_t * idx ); - -int encode_mac( uint8_t * base, - size_t * idx, - const n2n_mac_t m ); - -int decode_mac( uint8_t * out, /* of size N2N_MAC_SIZE. This clearer than passing a n2n_mac_t */ - const uint8_t * base, - size_t * rem, - size_t * idx ); - -int encode_common( uint8_t * base, - size_t * idx, - const n2n_common_t * common ); - -int decode_common( n2n_common_t * out, - const uint8_t * base, - size_t * rem, - size_t * idx ); - -int encode_sock( uint8_t * base, - size_t * idx, - const n2n_sock_t * sock ); - -int decode_sock( n2n_sock_t * sock, - const uint8_t * base, - size_t * rem, - size_t * idx ); - -int encode_REGISTER( uint8_t * base, - size_t * idx, - const n2n_common_t * common, - const n2n_REGISTER_t * reg ); - -int decode_REGISTER( n2n_REGISTER_t * pkt, - const n2n_common_t * cmn, /* info on how to interpret it */ - const uint8_t * base, - size_t * rem, - size_t * idx ); - -int encode_REGISTER_SUPER( uint8_t * base, - size_t * idx, - const n2n_common_t * common, - const n2n_REGISTER_SUPER_t * reg ); - -int decode_REGISTER_SUPER( n2n_REGISTER_SUPER_t * pkt, - const n2n_common_t * cmn, /* info on how to interpret it */ - const uint8_t * base, - size_t * rem, - size_t * idx ); - -int encode_REGISTER_ACK( uint8_t * base, - size_t * idx, - const n2n_common_t * common, - const n2n_REGISTER_ACK_t * reg ); - -int decode_REGISTER_ACK( n2n_REGISTER_ACK_t * pkt, - const n2n_common_t * cmn, /* info on how to interpret it */ - const uint8_t * base, - size_t * rem, - size_t * idx ); - -int encode_REGISTER_SUPER_ACK( uint8_t * base, - size_t * idx, - const n2n_common_t * cmn, - const n2n_REGISTER_SUPER_ACK_t * reg ); - -int decode_REGISTER_SUPER_ACK( n2n_REGISTER_SUPER_ACK_t * reg, - const n2n_common_t * cmn, /* info on how to interpret it */ - const uint8_t * base, - size_t * rem, - size_t * idx ); - -int fill_sockaddr( struct sockaddr * addr, - size_t addrlen, - const n2n_sock_t * sock ); - -int encode_PACKET( uint8_t * base, - size_t * idx, - const n2n_common_t * common, - const n2n_PACKET_t * pkt ); - -int decode_PACKET( n2n_PACKET_t * pkt, - const n2n_common_t * cmn, /* info on how to interpret it */ - const uint8_t * base, - size_t * rem, - size_t * idx ); - -int encode_PEER_INFO( uint8_t * base, - size_t * idx, - const n2n_common_t * common, - const n2n_PEER_INFO_t * pi ); - -int decode_PEER_INFO( n2n_PEER_INFO_t * pi, - const n2n_common_t * cmn, /* info on how to interpret it */ - const uint8_t * base, - size_t * rem, - size_t * idx ); - -int encode_QUERY_PEER( uint8_t * base, - size_t * idx, - const n2n_common_t * common, - const n2n_QUERY_PEER_t * qp ); - -int decode_QUERY_PEER( n2n_QUERY_PEER_t * qp, - const n2n_common_t * cmn, /* info on how to interpret it */ - const uint8_t * base, - size_t * rem, - size_t * idx ); - -void decode_ETHFRAMEHDR( n2n_ETHFRAMEHDR_t * eth, - const uint8_t * base ); - -int copy_ETHFRAMEHDR( uint8_t * base, - uint8_t * pkt); - - -#endif /* #if !defined( N2N_WIRE_H_ ) */ diff --git a/n2n_v2/openwrt/kamikaze/Makefile b/n2n_v2/openwrt/kamikaze/Makefile deleted file mode 100644 index ddcc7c1..0000000 --- a/n2n_v2/openwrt/kamikaze/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -# -# Copyright (C) 2008 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. - - -include $(TOPDIR)/rules.mk - -PKG_BRANCH:=trunk -PKG_SOURCE_URL:=https://svn.ntop.org/svn/ntop/trunk/n2n -PKG_REV:=$(shell LC_ALL=C svn info ${PKG_SOURCE_URL} | sed -ne's/^Last Changed Rev: //p') - -PKG_NAME:=n2n -PKG_VERSION:=svn$(PKG_REV) -PKG_RELEASE:=1 - -PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) -PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.gz -PKG_SOURCE_PROTO:=svn -PKG_SOURCE_VERSION:=$(PKG_REV) - -PKG_BUILD_DEPENDS:= - -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) -PKG_INSTALL_DIR:=$(PKG_BUILD_DIR) - - - -include $(INCLUDE_DIR)/package.mk - -define Package/n2n - SECTION:=net - CATEGORY:=Network - TITLE:=VPN tunneling daemon - URL:=http://www.ntop.org/n2n/ - SUBMENU:=VPN - DEPENDS:=libpthread -endef - - -define Build/Configure -endef - -define Build/Compile - $(MAKE) CC="$(TARGET_CC)" -C $(PKG_BUILD_DIR) -endef - - -define Package/n2n/install - $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/edge $(1)/usr/sbin/ - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/supernode $(1)/usr/sbin/ -endef - -$(eval $(call BuildPackage,n2n)) diff --git a/n2n_v2/scripts/mk_SRPM.sh b/n2n_v2/scripts/mk_SRPM.sh deleted file mode 100644 index 2b1b374..0000000 --- a/n2n_v2/scripts/mk_SRPM.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh - -# This script makes a SRPM - a source RPM file which can be built into the -# appropriate distro specific RPM for any platform. -# -# To build the binary package: -# rpm -i n2n-.src.rpm -# rpmbuild -bb n2n.spec -# -# Look for the "Wrote:" line to see where the final RPM is. -# -# To run this script cd to the n2n directory and run it as follows -# scripts/mk_SRPMS.sh -# - -set -e - -set -x - -BASE=`pwd` - -TARFILE=`${BASE}/scripts/mk_tar.sh` - -test -f ${TARFILE} - -echo "Building SRPM" -# -ts means build source RPM from tarfile -rpmbuild -ts ${TARFILE} - -echo "Done" diff --git a/n2n_v2/scripts/mk_deb.sh b/n2n_v2/scripts/mk_deb.sh deleted file mode 100644 index 42d8691..0000000 --- a/n2n_v2/scripts/mk_deb.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash - -# This script makes a SRPM - a source RPM file which can be built into the -# appropriate distro specific RPM for any platform. -# -# To build the binary package: -# rpm -i n2n-.src.rpm -# rpmbuild -bb n2n.spec -# -# Look for the "Wrote:" line to see where the final RPM is. -# -# To run this script cd to the n2n directory and run it as follows -# scripts/mk_SRPMS.sh -# - -set -e - -set -x - -BASE=`pwd` - -TARFILE=`${BASE}/scripts/mk_tar.sh` -TEMPDIR="build_deb" - -test -f ${TARFILE} - -echo "Building .deb" - -if [ -d ${TEMPDIR} ]; then - echo "Removing ${TEMPDIR} directory" - rm -rf ${TEMPDIR} >&2 -fi - -mkdir ${TEMPDIR} - -pushd ${TEMPDIR} - -tar xzf ${TARFILE} #At original location - -cd n2n* - -dpkg-buildpackage -rfakeroot - -popd - -echo "Done" diff --git a/n2n_v2/sn.c b/n2n_v2/sn.c deleted file mode 100644 index 0719295..0000000 --- a/n2n_v2/sn.c +++ /dev/null @@ -1,864 +0,0 @@ -/* Supernode for n2n-2.x */ - -/* (c) 2009 Richard Andrews - * - * Contributions by: - * Lukasz Taczuk - * Struan Bartlett - */ - - -#include "n2n.h" - - -#define N2N_SN_LPORT_DEFAULT 7654 -#define N2N_SN_PKTBUF_SIZE 2048 - -#define N2N_SN_MGMT_PORT 5645 - - -struct sn_stats -{ - size_t errors; /* Number of errors encountered. */ - size_t reg_super; /* Number of REGISTER_SUPER requests received. */ - size_t reg_super_nak; /* Number of REGISTER_SUPER requests declined. */ - size_t fwd; /* Number of messages forwarded. */ - size_t broadcast; /* Number of messages broadcast to a community. */ - time_t last_fwd; /* Time when last message was forwarded. */ - time_t last_reg_super; /* Time when last REGISTER_SUPER was received. */ -}; - -typedef struct sn_stats sn_stats_t; - -struct n2n_sn -{ - time_t start_time; /* Used to measure uptime. */ - sn_stats_t stats; - int daemon; /* If non-zero then daemonise. */ - uint16_t lport; /* Local UDP port to bind to. */ - int sock; /* Main socket for UDP traffic with edges. */ - int mgmt_sock; /* management socket. */ - time_t last_purge; /* last purge time */ - peer_info_t * edges[PEER_HASH_TAB_SIZE]; /* Link list of registered edges. */ -}; - -typedef struct n2n_sn n2n_sn_t; - - -static int try_forward( n2n_sn_t * sss, - const n2n_common_t * cmn, - const n2n_mac_t dstMac, - const uint8_t * pktbuf, - size_t pktsize ); - -static int try_broadcast( n2n_sn_t * sss, - const n2n_common_t * cmn, - const n2n_mac_t srcMac, - const uint8_t * pktbuf, - size_t pktsize ); - - - -/** Initialise the supernode structure */ -static int init_sn( n2n_sn_t * sss ) -{ -#ifdef WIN32 - initWin32(); -#endif - memset( sss, 0, sizeof(n2n_sn_t) ); - - sss->daemon = 1; /* By defult run as a daemon. */ - sss->lport = N2N_SN_LPORT_DEFAULT; - sss->sock = -1; - sss->mgmt_sock = -1; - sss->last_purge = 0; - sglib_hashed_peer_info_t_init(sss->edges); - - return 0; /* OK */ -} - -/** Deinitialise the supernode structure and deallocate any memory owned by - * it. */ -static void deinit_sn( n2n_sn_t * sss ) -{ - if (sss->sock >= 0) - { - closesocket(sss->sock); - } - sss->sock=-1; - - if ( sss->mgmt_sock >= 0 ) - { - closesocket(sss->mgmt_sock); - } - sss->mgmt_sock=-1; - - purge_hashed_peer_list_t(sss->edges, 0xffffffff); -} - - -/** Determine the appropriate lifetime for new registrations. - * - * If the supernode has been put into a pre-shutdown phase then this lifetime - * should not allow registrations to continue beyond the shutdown point. - */ -static uint16_t reg_lifetime( n2n_sn_t * sss ) -{ - return 30; -} - - -/** Update the edge table with the details of the edge which contacted the - * supernode. */ -static int update_edge( n2n_sn_t * sss, - const n2n_REGISTER_SUPER_t * reg, - const n2n_community_t community, - const n2n_sock_t * sender_sock, - time_t now) -{ - macstr_t mac_buf; - n2n_sock_str_t sockbuf; - struct peer_info * scan; - - traceEvent( TRACE_DEBUG, "update_edge for %s [%s]", - macaddr_str( mac_buf, reg->edgeMac ), - sock_to_cstr( sockbuf, sender_sock ) ); - - scan = find_peer_by_mac( sss->edges, reg->edgeMac ); - - if ( NULL == scan ) - { - /* Not known */ - - scan = (struct peer_info*)calloc(1, sizeof(struct peer_info)); /* deallocated in purge_expired_registrations */ - - memcpy(scan->community_name, community, sizeof(n2n_community_t) ); - memcpy(&(scan->mac_addr), reg->edgeMac, sizeof(n2n_mac_t)); - memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t)); - - scan->timeout = reg->timeout; - if(reg->aflags & N2N_AFLAGS_LOCAL_SOCKET) { - scan->num_sockets = 2; - scan->sockets = malloc(scan->num_sockets*sizeof(n2n_sock_t)); - scan->sockets[1] = reg->local_sock; - } else { - scan->num_sockets = 1; - scan->sockets = malloc(scan->num_sockets*sizeof(n2n_sock_t)); - } - scan->sockets[0] = scan->sock; - - /* insert this guy at the head of the edges list */ - sglib_hashed_peer_info_t_add(sss->edges, scan); - - traceEvent( TRACE_INFO, "update_edge created %s ==> %s", - macaddr_str( mac_buf, reg->edgeMac ), - sock_to_cstr( sockbuf, sender_sock ) ); - } - else - { - /* Known */ - int num_changes = 0; - scan->timeout = reg->timeout; - if (0 != memcmp(community, scan->community_name, sizeof(n2n_community_t))) - { - memcpy(scan->community_name, community, sizeof(n2n_community_t) ); - num_changes++; - } - if (0 != sock_equal(sender_sock, &(scan->sock) )) { - memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t)); - memcpy(scan->sockets, sender_sock, sizeof(n2n_sock_t)); - num_changes++; - } - if (scan->num_sockets == 1) { - if (reg->aflags & N2N_AFLAGS_LOCAL_SOCKET) { - scan->num_sockets = 2; - free(scan->sockets); - scan->sockets = malloc(scan->num_sockets*sizeof(n2n_sock_t)); - scan->sockets[0] = scan->sock; - scan->sockets[1] = reg->local_sock; - } - } else { - if (reg->aflags & N2N_AFLAGS_LOCAL_SOCKET) { - if (0 != sock_equal(&(reg->local_sock), scan->sockets+1 )) { - memcpy(scan->sockets+1, &(reg->local_sock), sizeof(n2n_sock_t)); - } - } else { - scan->num_sockets = 1; - free(scan->sockets); - scan->sockets = malloc(scan->num_sockets*sizeof(n2n_sock_t)); - scan->sockets[0] = scan->sock; - } - } - if (num_changes) { - traceEvent( TRACE_INFO, "update_edge updated %s ==> %s", - macaddr_str( mac_buf, reg->edgeMac ), - sock_to_cstr( sockbuf, sender_sock ) ); - } else { - traceEvent( TRACE_DEBUG, "update_edge unchanged %s ==> %s", - macaddr_str( mac_buf, reg->edgeMac ), - sock_to_cstr( sockbuf, sender_sock ) ); - } - - } - - scan->last_seen = now; - return 0; -} - - -/** Send a datagram to the destination embodied in a n2n_sock_t. - * - * @return -1 on error otherwise number of bytes sent - */ -static ssize_t sendto_sock(n2n_sn_t * sss, - const n2n_sock_t * sock, - const uint8_t * pktbuf, - size_t pktsize) -{ - n2n_sock_str_t sockbuf; - - if ( AF_INET == sock->family ) - { - struct sockaddr_in udpsock; - - udpsock.sin_family = AF_INET; - udpsock.sin_port = htons( sock->port ); - memcpy( &(udpsock.sin_addr.s_addr), &(sock->addr.v4), IPV4_SIZE ); - - traceEvent( TRACE_DEBUG, "sendto_sock %lu to [%s]", - pktsize, - sock_to_cstr( sockbuf, sock ) ); - - return sendto( sss->sock, pktbuf, pktsize, 0, - (const struct sockaddr *)&udpsock, sizeof(struct sockaddr_in) ); - } - else - { - /* AF_INET6 not implemented */ - errno = EAFNOSUPPORT; - return -1; - } -} - - - -/** Try to forward a message to a unicast MAC. If the MAC is unknown then - * broadcast to all edges in the destination community. - */ -static int try_forward( n2n_sn_t * sss, - const n2n_common_t * cmn, - const n2n_mac_t dstMac, - const uint8_t * pktbuf, - size_t pktsize ) -{ - struct peer_info * scan; - macstr_t mac_buf; - n2n_sock_str_t sockbuf; - - scan = find_peer_by_mac( sss->edges, dstMac ); - - if ( NULL != scan ) - { - int data_sent_len; - data_sent_len = sendto_sock( sss, &(scan->sock), pktbuf, pktsize ); - - if ( data_sent_len == pktsize ) - { - ++(sss->stats.fwd); - traceEvent(TRACE_DEBUG, "unicast %lu to [%s] %s", - pktsize, - sock_to_cstr( sockbuf, &(scan->sock) ), - macaddr_str(mac_buf, scan->mac_addr)); - } - else - { - ++(sss->stats.errors); - traceEvent(TRACE_ERROR, "unicast %lu to [%s] %s FAILED (%d: %s)", - pktsize, - sock_to_cstr( sockbuf, &(scan->sock) ), - macaddr_str(mac_buf, scan->mac_addr), - errno, strerror(errno) ); - } - } - else - { - traceEvent( TRACE_DEBUG, "try_forward unknown MAC" ); - - /* Not a known MAC so drop. */ - } - - return 0; -} - - -/** Try and broadcast a message to all edges in the community. - * - * This will send the exact same datagram to zero or more edges registered to - * the supernode. - */ -static int try_broadcast( n2n_sn_t * sss, - const n2n_common_t * cmn, - const n2n_mac_t srcMac, - const uint8_t * pktbuf, - size_t pktsize ) -{ - peer_info_t * ll; - struct sglib_hashed_peer_info_t_iterator it; - macstr_t mac_buf; - n2n_sock_str_t sockbuf; - - traceEvent( TRACE_DEBUG, "try_broadcast" ); - - for(ll=sglib_hashed_peer_info_t_it_init(&it,sss->edges); ll!=NULL; ll=sglib_hashed_peer_info_t_it_next(&it)) { - if( 0 == (memcmp(ll->community_name, cmn->community, sizeof(n2n_community_t)) ) - && (0 != memcmp(srcMac, ll->mac_addr, sizeof(n2n_mac_t)) ) ) - /* REVISIT: exclude if the destination socket is where the packet came from. */ - { - int data_sent_len; - - data_sent_len = sendto_sock(sss, &(ll->sock), pktbuf, pktsize); - - if(data_sent_len != pktsize) - { - ++(sss->stats.errors); - traceEvent(TRACE_WARNING, "multicast %lu to [%s] %s failed %s", - pktsize, - sock_to_cstr( sockbuf, &(ll->sock) ), - macaddr_str(mac_buf, ll->mac_addr), - strerror(errno)); - } - else - { - ++(sss->stats.broadcast); - traceEvent(TRACE_DEBUG, "multicast %lu to [%s] %s", - pktsize, - sock_to_cstr( sockbuf, &(ll->sock) ), - macaddr_str(mac_buf, ll->mac_addr)); - } - } - } /* for */ - - return 0; -} - - -static int process_mgmt( n2n_sn_t * sss, - const struct sockaddr_in * sender_sock, - const uint8_t * mgmt_buf, - size_t mgmt_size, - time_t now) -{ - char resbuf[N2N_SN_PKTBUF_SIZE]; - size_t ressize=0; - ssize_t r; - - traceEvent( TRACE_DEBUG, "process_mgmt" ); - - ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "----------------\n" ); - - ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "uptime %lu\n", (now - sss->start_time) ); - - ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "edges %u\n", - (unsigned int)hashed_peer_list_t_size( sss->edges )); - - ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "errors %u\n", - (unsigned int)sss->stats.errors ); - - ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "reg_sup %u\n", - (unsigned int)sss->stats.reg_super ); - - ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "reg_nak %u\n", - (unsigned int)sss->stats.reg_super_nak ); - - ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "fwd %u\n", - (unsigned int) sss->stats.fwd ); - - ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "broadcast %u\n", - (unsigned int) sss->stats.broadcast ); - - ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "last fwd %lu sec ago\n", - (long unsigned int)(now - sss->stats.last_fwd) ); - - ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "last reg %lu sec ago\n", - (long unsigned int) (now - sss->stats.last_reg_super) ); - - - r = sendto( sss->mgmt_sock, resbuf, ressize, 0/*flags*/, - (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) ); - - if ( r <= 0 ) - { - ++(sss->stats.errors); - traceEvent( TRACE_ERROR, "process_mgmt : sendto failed. %s", strerror(errno) ); - } - - return 0; -} - - -/** Examine a datagram and determine what to do with it. - * - */ -static int process_udp( n2n_sn_t * sss, - const struct sockaddr_in * sender_sock, - const uint8_t * udp_buf, - size_t udp_size, - time_t now) -{ - n2n_common_t cmn; /* common fields in the packet header */ - n2n_common_t cmn2; /* common fields of newly generated packets */ - size_t rem; - size_t idx; - size_t msg_type; - uint8_t from_supernode; - macstr_t mac_buf; - macstr_t mac_buf2; - n2n_sock_str_t sockbuf; - const uint8_t * rec_buf; /* either udp_buf or encbuf */ - int unicast; /* non-zero if unicast */ - size_t encx=0; - uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; - n2n_ETHFRAMEHDR_t eth; - int i; - - /* for PACKET packages */ - n2n_PACKET_t pkt; - - /* for QUERY_PEER packages */ - n2n_QUERY_PEER_t query; - struct peer_info * scan; - n2n_PEER_INFO_t pi; - - /* for REGISTER packages */ - n2n_REGISTER_t reg; - - /* for REGISTER_SUPER packages */ - n2n_REGISTER_SUPER_t regs; - n2n_REGISTER_SUPER_ACK_t ack; - - traceEvent( TRACE_DEBUG, "process_udp(%lu)", udp_size ); - - /* Use decode_common() to determine the kind of packet then process it: - * - * REGISTER_SUPER adds an edge and generate a return REGISTER_SUPER_ACK - * - * REGISTER, REGISTER_ACK and PACKET messages are forwarded to their - * destination edge. If the destination is not known then PACKETs are - * broadcast. - */ - - rem = udp_size; /* 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" ); - return -1; /* failed to decode packet */ - } - - msg_type = cmn.pc; /* packet code */ - from_supernode= cmn.flags & N2N_FLAGS_FROM_SUPERNODE; - - if ( cmn.ttl < 1 ) - { - traceEvent( TRACE_WARNING, "Expired TTL" ); - return 0; /* Don't process further */ - } - - --(cmn.ttl); /* The value copied into all forwarded packets. */ - - switch(msg_type) { - case MSG_TYPE_PACKET: - /* PACKET from one edge to another edge via supernode. */ - - /* pkt will be modified in place and recoded to an output of potentially - * different size due to addition of the socket.*/ - - - sss->stats.last_fwd=now; - decode_PACKET( &pkt, &cmn, udp_buf, &rem, &idx ); - decode_ETHFRAMEHDR( ð, udp_buf+idx ); - - unicast = (0 == is_multi_broadcast(eth.dstMac) ); - - traceEvent( TRACE_DEBUG, "Rx PACKET (%s) %s -> %s %s", - (unicast?"unicast":"multicast"), - macaddr_str( mac_buf, eth.srcMac ), - macaddr_str( mac_buf2, eth.dstMac ), - (from_supernode?"from sn":"local") ); - - if ( !from_supernode ) - { - memcpy( &cmn2, &cmn, sizeof( n2n_common_t ) ); - - /* We are going to add socket even if it was not there before */ - cmn2.flags |= N2N_FLAGS_FROM_SUPERNODE; - - rec_buf = encbuf; - - /* Re-encode the header. */ - encode_PACKET( encbuf, &encx, &cmn2, &pkt ); - - /* Copy the original payload unchanged */ - encode_buf( encbuf, &encx, (udp_buf + idx), (udp_size - idx ) ); - } - else - { - /* Already from a supernode. Nothing to modify, just pass to - * destination. */ - - traceEvent( TRACE_DEBUG, "Rx PACKET fwd unmodified" ); - - rec_buf = udp_buf; - encx = udp_size; - } - - /* Common section to forward the final product. */ - if ( unicast ) - { - try_forward( sss, &cmn, eth.dstMac, rec_buf, encx ); - } - else - { - try_broadcast( sss, &cmn, eth.srcMac, rec_buf, encx ); - } - break; - case MSG_TYPE_QUERY_PEER: - decode_QUERY_PEER( &query, &cmn, udp_buf, &rem, &idx ); - - traceEvent( TRACE_DEBUG, "Rx QUERY_PEER from %s for %s", - macaddr_str( mac_buf, query.srcMac ), - macaddr_str( mac_buf2, query.targetMac ) ); - - scan = find_peer_by_mac( sss->edges, query.targetMac ); - if (scan && 0 == memcmp(cmn.community, scan->community_name, - sizeof(n2n_community_t))) { - cmn2.ttl = N2N_DEFAULT_TTL; - cmn2.pc = n2n_peer_info; - cmn2.flags = N2N_FLAGS_FROM_SUPERNODE; - memcpy( cmn2.community, cmn.community, sizeof(n2n_community_t) ); - - pi.aflags = 0; - pi.timeout = scan->timeout; - memcpy( pi.mac, query.targetMac, sizeof(n2n_mac_t) ); - for(i=0; inum_sockets; i++) - pi.sockets[i] = scan->sockets[i]; - if(scan->num_sockets > 1) - pi.aflags |= N2N_AFLAGS_LOCAL_SOCKET; - - encode_PEER_INFO( encbuf, &encx, &cmn2, &pi ); - - sendto( sss->sock, encbuf, encx, 0, - (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) ); - - traceEvent( TRACE_DEBUG, "Tx PEER_INFO to %s", - macaddr_str( mac_buf, query.srcMac ) ); - } else { - traceEvent( TRACE_DEBUG, "Ignoring QUERY_PEER for unknown edge %s", - macaddr_str( mac_buf, query.targetMac ) ); - } - - break; - case MSG_TYPE_REGISTER: - /* Forwarding a REGISTER from one edge to the next */ - - - sss->stats.last_fwd=now; - decode_REGISTER( ®, &cmn, udp_buf, &rem, &idx ); - - unicast = (0 == is_multi_broadcast(reg.dstMac) ); - - if ( unicast ) - { - traceEvent( TRACE_DEBUG, "Rx REGISTER %s -> %s %s", - macaddr_str( mac_buf, reg.srcMac ), - macaddr_str( mac_buf2, reg.dstMac ), - ((cmn.flags & N2N_FLAGS_FROM_SUPERNODE)?"from sn":"local") ); - - if ( 0 != (cmn.flags & N2N_FLAGS_FROM_SUPERNODE) ) - { - memcpy( &cmn2, &cmn, sizeof( n2n_common_t ) ); - - /* We are going to add socket even if it was not there before */ - cmn2.flags |= N2N_FLAGS_FROM_SUPERNODE; - - reg.sock.family = AF_INET; - reg.sock.port = ntohs(sender_sock->sin_port); - memcpy( reg.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE ); - - rec_buf = encbuf; - - /* Re-encode the header. */ - encode_REGISTER( encbuf, &encx, &cmn2, ® ); - - /* Copy the original payload unchanged */ - encode_buf( encbuf, &encx, (udp_buf + idx), (udp_size - idx ) ); - } - else - { - /* Already from a supernode. Nothing to modify, just pass to - * destination. */ - - rec_buf = udp_buf; - encx = udp_size; - } - - try_forward( sss, &cmn, reg.dstMac, rec_buf, encx ); /* unicast only */ - } - else - { - traceEvent( TRACE_ERROR, "Rx REGISTER with multicast destination" ); - } - break; - case MSG_TYPE_REGISTER_ACK: - traceEvent( TRACE_DEBUG, "Rx REGISTER_ACK (NOT IMPLEMENTED) SHould not be via supernode" ); - break; - case MSG_TYPE_REGISTER_SUPER: - /* Edge requesting registration with us. */ - - sss->stats.last_reg_super=now; - ++(sss->stats.reg_super); - decode_REGISTER_SUPER( ®s, &cmn, udp_buf, &rem, &idx ); - - cmn2.ttl = N2N_DEFAULT_TTL; - cmn2.pc = n2n_register_super_ack; - cmn2.flags = N2N_FLAGS_FROM_SUPERNODE; - memcpy( cmn2.community, cmn.community, sizeof(n2n_community_t) ); - - memcpy( &(ack.cookie), &(regs.cookie), sizeof(n2n_cookie_t) ); - memcpy( ack.edgeMac, regs.edgeMac, sizeof(n2n_mac_t) ); - ack.lifetime = reg_lifetime( sss ); - - ack.sock.family = AF_INET; - ack.sock.port = ntohs(sender_sock->sin_port); - memcpy( ack.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE ); - - ack.num_sn=0; /* No backup */ - memset( &(ack.sn_bak), 0, sizeof(n2n_sock_t) ); - - traceEvent( TRACE_DEBUG, "Rx REGISTER_SUPER for %s [%s]", - macaddr_str( mac_buf, regs.edgeMac ), - sock_to_cstr( sockbuf, &(ack.sock) ) ); - - update_edge( sss, ®s, cmn.community, &(ack.sock), now ); - - encode_REGISTER_SUPER_ACK( encbuf, &encx, &cmn2, &ack ); - - sendto( sss->sock, encbuf, encx, 0, - (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) ); - - traceEvent( TRACE_DEBUG, "Tx REGISTER_SUPER_ACK for %s [%s]", - macaddr_str( mac_buf, regs.edgeMac ), - sock_to_cstr( sockbuf, &(ack.sock) ) ); - break; - default: - /* Not a known message type */ - traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored", (signed int)msg_type); - break; - } - - return 0; -} - - -/** Help message to print if the command line arguments are not valid. */ -static void exit_help(int argc, char * const argv[]) -{ - fprintf( stderr, "%s usage\n", argv[0] ); - fprintf( stderr, "-l \tSet UDP main listen port to \n" ); - -#if defined(N2N_HAVE_DAEMON) - fprintf( stderr, "-f \tRun in foreground.\n" ); -#endif /* #if defined(N2N_HAVE_DAEMON) */ - fprintf( stderr, "-v \tIncrease verbosity. Can be used multiple times.\n" ); - fprintf( stderr, "-h \tThis help message.\n" ); - fprintf( stderr, "\n" ); - exit(1); -} - -static int run_loop( n2n_sn_t * sss ); - -/* *********************************************** */ - -static const struct option long_options[] = { - { "foreground", no_argument, NULL, 'f' }, - { "local-port", required_argument, NULL, 'l' }, - { "help" , no_argument, NULL, 'h' }, - { "verbose", no_argument, NULL, 'v' }, - { NULL, 0, NULL, 0 } -}; - -/** Main program entry point from kernel. */ -int main( int argc, char * const argv[] ) -{ - n2n_sn_t sss; - - init_sn( &sss ); - - { - int opt; - - while((opt = getopt_long(argc, argv, "fl:vh", long_options, NULL)) != -1) - { - switch (opt) - { - case 'l': /* local-port */ - sss.lport = atoi(optarg); - break; - case 'f': /* foreground */ - sss.daemon = 0; - break; - case 'h': /* help */ - exit_help(argc, argv); - break; - case 'v': /* verbose */ - ++traceLevel; - break; - } - } - - } - -#if defined(N2N_HAVE_DAEMON) - if (sss.daemon) - { - useSyslog=1; /* traceEvent output now goes to syslog. */ - if ( -1 == daemon( 0, 0 ) ) - { - traceEvent( TRACE_ERROR, "Failed to become daemon." ); - exit(-5); - } - } -#endif /* #if defined(N2N_HAVE_DAEMON) */ - - traceEvent( TRACE_DEBUG, "traceLevel is %d", traceLevel); - - sss.sock = open_socket(sss.lport, 1 /*bind ANY*/ ); - if ( -1 == sss.sock ) - { - traceEvent( TRACE_ERROR, "Failed to open main socket. %s", strerror(errno) ); - exit(-2); - } - else - { - traceEvent( TRACE_NORMAL, "supernode is listening on UDP %u (main)", sss.lport ); - } - - sss.mgmt_sock = open_socket(N2N_SN_MGMT_PORT, 0 /* bind LOOPBACK */ ); - if ( -1 == sss.mgmt_sock ) - { - traceEvent( TRACE_ERROR, "Failed to open management socket. %s", strerror(errno) ); - exit(-2); - } - else - { - traceEvent( TRACE_NORMAL, "supernode is listening on UDP %u (management)", N2N_SN_MGMT_PORT ); - } - - traceEvent(TRACE_NORMAL, "supernode started"); - - return run_loop(&sss); -} - - -/** Long lived processing entry point. Split out from main to simply - * daemonisation on some platforms. */ -static int run_loop( n2n_sn_t * sss ) -{ - uint8_t pktbuf[N2N_SN_PKTBUF_SIZE]; - int keep_running=1; - - sss->start_time = time(NULL); - - while(keep_running) - { - int rc; - ssize_t bread; - int max_sock; - fd_set socket_mask; - struct timeval wait_time; - time_t now=0; - - FD_ZERO(&socket_mask); - max_sock = MAX(sss->sock, sss->mgmt_sock); - - FD_SET(sss->sock, &socket_mask); - FD_SET(sss->mgmt_sock, &socket_mask); - - wait_time.tv_sec = 10; wait_time.tv_usec = 0; - rc = select(max_sock+1, &socket_mask, NULL, NULL, &wait_time); - - now = time(NULL); - - if(rc > 0) - { - if (FD_ISSET(sss->sock, &socket_mask)) - { - struct sockaddr_in sender_sock; - socklen_t i; - - i = sizeof(sender_sock); - bread = recvfrom( sss->sock, pktbuf, N2N_SN_PKTBUF_SIZE, 0/*flags*/, - (struct sockaddr *)&sender_sock, (socklen_t*)&i); - - if ( bread < 0 ) /* For UDP bread of zero just means no data (unlike TCP). */ - { - /* The fd is no good now. Maybe we lost our interface. */ - traceEvent( TRACE_ERROR, "recvfrom() failed %d errno %d (%s)", bread, errno, strerror(errno) ); - keep_running=0; - break; - } - - /* We have a datagram to process */ - if ( bread > 0 ) - { - /* And the datagram has data (not just a header) */ - process_udp( sss, &sender_sock, pktbuf, bread, now ); - } - } - - if (FD_ISSET(sss->mgmt_sock, &socket_mask)) - { - struct sockaddr_in sender_sock; - size_t i; - - i = sizeof(sender_sock); - bread = recvfrom( sss->mgmt_sock, pktbuf, N2N_SN_PKTBUF_SIZE, 0/*flags*/, - (struct sockaddr *)&sender_sock, (socklen_t*)&i); - - if ( bread <= 0 ) - { - traceEvent( TRACE_ERROR, "recvfrom() failed %d errno %d (%s)", bread, errno, strerror(errno) ); - keep_running=0; - break; - } - - /* We have a datagram to process */ - process_mgmt( sss, &sender_sock, pktbuf, bread, now ); - } - } - else - { - traceEvent( TRACE_DEBUG, "timeout" ); - } - if ((now - sss->last_purge) >= PURGE_REGISTRATION_FREQUENCY) { - hashed_purge_expired_registrations( sss->edges ); - sss->last_purge = now; - } - - } /* while */ - - deinit_sn( sss ); - - return 0; -} - diff --git a/n2n_v2/test.c b/n2n_v2/test.c deleted file mode 100644 index 97ec91b..0000000 --- a/n2n_v2/test.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "n2n.h" -#include "n2n_keyfile.h" -#include -#include -#include - -int main(int arc, const char * argv[] ) -{ - int e; - n2n_cipherspec_t specs[N2N_MAX_NUM_CIPHERSPECS]; - - e = n2n_read_keyfile( specs, N2N_MAX_NUM_CIPHERSPECS, "keyctrl.conf" ); - - if ( e < 0 ) - { - perror( "Failed to read keyfile" ); - } - else - { - fprintf( stderr, "Stored %d keys.\n", e ); - } - - return 0; -} diff --git a/n2n_v2/transform_aes.c b/n2n_v2/transform_aes.c deleted file mode 100644 index a8c4969..0000000 --- a/n2n_v2/transform_aes.c +++ /dev/null @@ -1,597 +0,0 @@ -/* (c) 2009 Richard Andrews */ -/* Contributions from: - * - Jozef Kralik - */ - -#include "n2n.h" -#include "n2n_transforms.h" - -#if defined(N2N_HAVE_AES) - - -#include "openssl/aes.h" -#ifndef _MSC_VER -/* Not included in Visual Studio 2008 */ -#include /* index() */ -#endif - -#define N2N_AES_NUM_SA 32 /* space for SAa */ - -#define N2N_AES_TRANSFORM_VERSION 1 /* version of the transform encoding */ -#define N2N_AES_IVEC_SIZE 32 /* Enough space for biggest AES ivec */ - -typedef unsigned char n2n_aes_ivec_t[N2N_AES_IVEC_SIZE]; - -struct sa_aes -{ - n2n_cipherspec_t spec; /* cipher spec parameters */ - n2n_sa_t sa_id; /* security association index */ - AES_KEY enc_key; /* tx key */ - n2n_aes_ivec_t enc_ivec; /* tx CBC state */ - AES_KEY dec_key; /* tx key */ - n2n_aes_ivec_t dec_ivec; /* tx CBC state */ -}; - -typedef struct sa_aes sa_aes_t; - - -/** Aes transform state data. - * - * With a key-schedule in place this will be populated with a number of - * SAs. Each SA has a lifetime and some opque data. The opaque data for aes - * consists of the SA number and key material. - * - */ -struct transop_aes -{ - ssize_t tx_sa; - size_t num_sa; - sa_aes_t sa[N2N_AES_NUM_SA]; -}; - -typedef struct transop_aes transop_aes_t; - -static int transop_deinit_aes( n2n_trans_op_t * arg ) -{ - transop_aes_t * priv = (transop_aes_t *)arg->priv; - size_t i; - - if ( priv ) - { - /* Memory was previously allocated */ - for (i=0; isa[i]); - - sa->sa_id=0; - } - - priv->num_sa=0; - priv->tx_sa=-1; - - free(priv); - } - - arg->priv=NULL; /* return to fully uninitialised state */ - - return 0; -} - -static size_t aes_choose_tx_sa( transop_aes_t * priv ) -{ - return priv->tx_sa; /* set in tick */ -} - -#define TRANSOP_AES_VER_SIZE 1 /* Support minor variants in encoding in one module. */ -#define TRANSOP_AES_NONCE_SIZE 4 -#define TRANSOP_AES_SA_SIZE 4 - - -#define AES256_KEY_BYTES (256/8) -#define AES192_KEY_BYTES (192/8) -#define AES128_KEY_BYTES (128/8) - -/* Return the best acceptable AES key size (in bytes) given an input keysize. - * - * The value returned will be one of AES128_KEY_BYTES, AES192_KEY_BYTES or - * AES256_KEY_BYTES. - */ -static size_t aes_best_keysize(size_t numBytes) -{ - if (numBytes >= AES256_KEY_BYTES ) - { - return AES256_KEY_BYTES; - } - else if (numBytes >= AES192_KEY_BYTES) - { - return AES192_KEY_BYTES; - } - else - { - return AES128_KEY_BYTES; - } -} - -/** The aes packet format consists of: - * - * - a 8-bit aes encoding version in clear text - * - a 32-bit SA number in clear text - * - ciphertext encrypted from a 32-bit nonce followed by the payload. - * - * [V|SSSS|nnnnDDDDDDDDDDDDDDDDDDDDD] - * |<------ encrypted ------>| - */ -static int transop_encode_aes( n2n_trans_op_t * arg, - uint8_t * outbuf, - size_t out_len, - const uint8_t * inbuf, - size_t in_len ) -{ - int len2=-1; - transop_aes_t * priv = (transop_aes_t *)arg->priv; - uint8_t assembly[N2N_PKT_BUF_SIZE]; - uint32_t * pnonce; - - if ( (in_len + TRANSOP_AES_NONCE_SIZE) <= N2N_PKT_BUF_SIZE ) - { - if ( (in_len + TRANSOP_AES_NONCE_SIZE + TRANSOP_AES_SA_SIZE + TRANSOP_AES_VER_SIZE) <= out_len ) - { - int len=-1; - size_t idx=0; - sa_aes_t * sa; - size_t tx_sa_num = 0; - - /* The transmit sa is periodically updated */ - tx_sa_num = aes_choose_tx_sa( priv ); - - sa = &(priv->sa[tx_sa_num]); /* Proper Tx SA index */ - - traceEvent( TRACE_DEBUG, "encode_aes %lu with SA %lu.", in_len, sa->sa_id ); - - /* Encode the aes format version. */ - encode_uint8( outbuf, &idx, N2N_AES_TRANSFORM_VERSION ); - - /* Encode the security association (SA) number */ - encode_uint32( outbuf, &idx, sa->sa_id ); - - /* Encrypt the assembly contents and write the ciphertext after the SA. */ - len = in_len + TRANSOP_AES_NONCE_SIZE; - - /* The assembly buffer is a source for encrypting data. The nonce is - * written in first followed by the packet payload. The whole - * contents of assembly are encrypted. */ - pnonce = (uint32_t *)assembly; - *pnonce = rand(); - memcpy( assembly + TRANSOP_AES_NONCE_SIZE, inbuf, in_len ); - - /* Need at least one encrypted byte at the end for the padding. */ - len2 = ( (len / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE; /* Round up to next whole AES adding at least one byte. */ - assembly[ len2-1 ]=(len2-len); - traceEvent( TRACE_DEBUG, "padding = %u", assembly[ len2-1 ] ); - - memset( &(sa->enc_ivec), 0, sizeof(N2N_AES_IVEC_SIZE) ); - AES_cbc_encrypt( assembly, /* source */ - outbuf + TRANSOP_AES_VER_SIZE + TRANSOP_AES_SA_SIZE, /* dest */ - len2, /* enc size */ - &(sa->enc_key), sa->enc_ivec, 1 /* encrypt */ ); - - len2 += TRANSOP_AES_VER_SIZE + TRANSOP_AES_SA_SIZE; /* size of data carried in UDP. */ - } - else - { - traceEvent( TRACE_ERROR, "encode_aes outbuf too small." ); - } - } - else - { - traceEvent( TRACE_ERROR, "encode_aes inbuf too big to encrypt." ); - } - - return len2; -} - - -/* Search through the array of SAs to find the one with the required ID. - * - * @return array index where found or -1 if not found - */ -static ssize_t aes_find_sa( const transop_aes_t * priv, const n2n_sa_t req_id ) -{ - size_t i; - - for (i=0; i < priv->num_sa; ++i) - { - const sa_aes_t * sa=NULL; - - sa = &(priv->sa[i]); - if (req_id == sa->sa_id) - { - return i; - } - } - - return -1; -} - - -/** The aes packet format consists of: - * - * - a 8-bit aes encoding version in clear text - * - a 32-bit SA number in clear text - * - ciphertext encrypted from a 32-bit nonce followed by the payload. - * - * [V|SSSS|nnnnDDDDDDDDDDDDDDDDDDDDD] - * |<------ encrypted ------>| - */ -static int transop_decode_aes( n2n_trans_op_t * arg, - uint8_t * outbuf, - size_t out_len, - const uint8_t * inbuf, - size_t in_len ) -{ - int len=0; - transop_aes_t * priv = (transop_aes_t *)arg->priv; - uint8_t assembly[N2N_PKT_BUF_SIZE]; - - if ( ( (in_len - (TRANSOP_AES_VER_SIZE + TRANSOP_AES_SA_SIZE)) <= N2N_PKT_BUF_SIZE ) /* Cipher text fits in assembly */ - && (in_len >= (TRANSOP_AES_VER_SIZE + TRANSOP_AES_SA_SIZE + TRANSOP_AES_NONCE_SIZE) ) /* Has at least version, SA and nonce */ - ) - { - n2n_sa_t sa_rx; - ssize_t sa_idx=-1; - size_t rem=in_len; - size_t idx=0; - uint8_t aes_enc_ver=0; - - /* Get the encoding version to make sure it is supported */ - decode_uint8( &aes_enc_ver, inbuf, &rem, &idx ); - - if ( N2N_AES_TRANSFORM_VERSION == aes_enc_ver ) - { - /* Get the SA number and make sure we are decrypting with the right one. */ - decode_uint32( &sa_rx, inbuf, &rem, &idx ); - - sa_idx = aes_find_sa(priv, sa_rx); - if ( sa_idx >= 0 ) - { - sa_aes_t * sa = &(priv->sa[sa_idx]); - - traceEvent( TRACE_DEBUG, "decode_aes %lu with SA %lu.", in_len, sa_rx, sa->sa_id ); - - len = (in_len - (TRANSOP_AES_VER_SIZE + TRANSOP_AES_SA_SIZE)); - - if ( 0 == (len % AES_BLOCK_SIZE ) ) - { - uint8_t padding; - - memset( &(sa->dec_ivec), 0, sizeof(N2N_AES_IVEC_SIZE) ); - AES_cbc_encrypt( (inbuf + TRANSOP_AES_VER_SIZE + TRANSOP_AES_SA_SIZE), - assembly, /* destination */ - len, - &(sa->dec_key), - sa->dec_ivec, 0 /* decrypt */ ); - - /* last byte is how much was padding: max value should be - * AES_BLOCKSIZE-1 */ - padding = assembly[ len-1 ] & 0xff; - - if ( len >= (padding + TRANSOP_AES_NONCE_SIZE)) - { - /* strictly speaking for this to be an ethernet packet - * it is going to need to be even bigger; but this is - * enough to prevent segfaults. */ - traceEvent( TRACE_DEBUG, "padding = %u", padding ); - len -= padding; - - len -= TRANSOP_AES_NONCE_SIZE; /* size of ethernet packet */ - - /* Step over 4-byte random nonce value */ - memcpy( outbuf, - assembly + TRANSOP_AES_NONCE_SIZE, - len ); - } - else - { - traceEvent( TRACE_WARNING, "UDP payload decryption failed." ); - } - } - else - { - traceEvent( TRACE_WARNING, "Encrypted length %d is not a multiple of AES_BLOCK_SIZE (%d)", len, AES_BLOCK_SIZE ); - len = 0; - } - - } - else - { - /* Wrong security association; drop the packet as it is undecodable. */ - traceEvent( TRACE_ERROR, "decode_aes SA number %lu not found.", sa_rx ); - - /* REVISIT: should be able to load a new SA at this point to complete the decoding. */ - } - } - else - { - /* Wrong security association; drop the packet as it is undecodable. */ - traceEvent( TRACE_ERROR, "decode_aes unsupported aes version %u.", aes_enc_ver ); - - /* REVISIT: should be able to load a new SA at this point to complete the decoding. */ - } - } - else - { - traceEvent( TRACE_ERROR, "decode_aes inbuf wrong size (%ul) to decrypt.", in_len ); - } - - return len; -} - -static int transop_addspec_aes( n2n_trans_op_t * arg, const n2n_cipherspec_t * cspec ) -{ - int retval = 1; - ssize_t pstat=-1; - transop_aes_t * priv = (transop_aes_t *)arg->priv; - uint8_t keybuf[N2N_MAX_KEYSIZE]; - - if ( priv->num_sa < N2N_AES_NUM_SA ) - { - const char * op = (const char *)cspec->opaque; - const char * sep = index( op, '_' ); - - if ( sep ) - { - char tmp[256]; - size_t s; - - s = sep - op; - memcpy( tmp, cspec->opaque, s ); - tmp[s]=0; - - s = strlen(sep+1); /* sep is the _ which might be immediately followed by NULL */ - - priv->sa[priv->num_sa].spec = *cspec; - priv->sa[priv->num_sa].sa_id = strtoul(tmp, NULL, 10); - - memset( keybuf, 0, N2N_MAX_KEYSIZE ); - pstat = n2n_parse_hex( keybuf, N2N_MAX_KEYSIZE, sep+1, s ); - if ( pstat > 0 ) - { - /* pstat is number of bytes read into keybuf. */ - sa_aes_t * sa = &(priv->sa[priv->num_sa]); - size_t aes_keysize_bytes; - size_t aes_keysize_bits; - - /* Clear out any old possibly longer key matter. */ - memset( &(sa->enc_key), 0, sizeof(AES_KEY) ); - memset( &(sa->dec_key), 0, sizeof(AES_KEY) ); - - memset( &(sa->enc_ivec), 0, sizeof(N2N_AES_IVEC_SIZE) ); - memset( &(sa->dec_ivec), 0, sizeof(N2N_AES_IVEC_SIZE) ); - - aes_keysize_bytes = aes_best_keysize(pstat); - aes_keysize_bits = 8 * aes_keysize_bytes; - - /* Use N2N_MAX_KEYSIZE because the AES key needs to be of fixed - * size. If fewer bits specified then the rest will be - * zeroes. AES acceptable key sizes are 128, 192 and 256 - * bits. */ - AES_set_encrypt_key( keybuf, aes_keysize_bits, &(sa->enc_key)); - AES_set_decrypt_key( keybuf, aes_keysize_bits, &(sa->dec_key)); - /* Leave ivecs set to all zeroes */ - - traceEvent( TRACE_DEBUG, "transop_addspec_aes sa_id=%u, %u bits data=%s.\n", - priv->sa[priv->num_sa].sa_id, aes_keysize_bits, sep+1); - - ++(priv->num_sa); - retval = 0; - } - } - else - { - traceEvent( TRACE_ERROR, "transop_addspec_aes : bad key data - missing '_'.\n"); - } - } - else - { - traceEvent( TRACE_ERROR, "transop_addspec_aes : full.\n"); - } - - return retval; -} - - -static n2n_tostat_t transop_tick_aes( n2n_trans_op_t * arg, time_t now ) -{ - transop_aes_t * priv = (transop_aes_t *)arg->priv; - size_t i; - int found=0; - n2n_tostat_t r; - - memset( &r, 0, sizeof(r) ); - - traceEvent( TRACE_DEBUG, "transop_aes tick num_sa=%u now=%lu", priv->num_sa, now ); - - for ( i=0; i < priv->num_sa; ++i ) - { - if ( 0 == validCipherSpec( &(priv->sa[i].spec), now ) ) - { - time_t remaining = priv->sa[i].spec.valid_until - now; - - traceEvent( TRACE_INFO, "transop_aes choosing tx_sa=%u (valid for %lu sec)", priv->sa[i].sa_id, remaining ); - priv->tx_sa=i; - found=1; - break; - } - else - { - traceEvent( TRACE_DEBUG, "transop_aes tick rejecting sa=%u %lu -> %lu", - priv->sa[i].sa_id, priv->sa[i].spec.valid_from, priv->sa[i].spec.valid_until ); - } - } - - if ( 0==found) - { - traceEvent( TRACE_INFO, "transop_aes no keys are currently valid. Keeping tx_sa=%u", priv->tx_sa ); - } - else - { - r.can_tx = 1; - r.tx_spec.t = N2N_TRANSFORM_ID_AESCBC; - r.tx_spec = priv->sa[priv->tx_sa].spec; - } - - return r; -} - - -int transop_aes_init( n2n_trans_op_t * ttt ) -{ - int retval = 1; - transop_aes_t * priv = NULL; - - if ( ttt->priv ) - { - transop_deinit_aes( ttt ); - } - - memset( ttt, 0, sizeof( n2n_trans_op_t ) ); - - priv = (transop_aes_t *) malloc( sizeof(transop_aes_t) ); - - if ( NULL != priv ) - { - size_t i; - sa_aes_t * sa=NULL; - - /* install the private structure. */ - ttt->priv = priv; - priv->num_sa=0; - priv->tx_sa=0; /* We will use this sa index for encoding. */ - - ttt->transform_id = N2N_TRANSFORM_ID_AESCBC; - ttt->addspec = transop_addspec_aes; - ttt->tick = transop_tick_aes; /* chooses a new tx_sa */ - ttt->deinit = transop_deinit_aes; - ttt->fwd = transop_encode_aes; - ttt->rev = transop_decode_aes; - - for(i=0; isa[i]); - sa->sa_id=0; - memset( &(sa->spec), 0, sizeof(n2n_cipherspec_t) ); - memset( &(sa->enc_key), 0, sizeof(AES_KEY) ); - memset( &(sa->enc_ivec), 0, sizeof(N2N_AES_IVEC_SIZE) ); - memset( &(sa->dec_key), 0, sizeof(AES_KEY) ); - memset( &(sa->dec_ivec), 0, sizeof(N2N_AES_IVEC_SIZE) ); - } - - retval = 0; - } - else - { - memset( ttt, 0, sizeof(n2n_trans_op_t) ); - traceEvent( TRACE_ERROR, "Failed to allocate priv for aes" ); - } - - return retval; -} - -#else /* #if defined(N2N_HAVE_AES) */ - -struct transop_aes -{ - ssize_t tx_sa; -}; - -typedef struct transop_aes transop_aes_t; - - -static int transop_deinit_aes( n2n_trans_op_t * arg ) -{ - transop_aes_t * priv = (transop_aes_t *)arg->priv; - - if ( priv ) - { - free(priv); - } - - arg->priv=NULL; /* return to fully uninitialised state */ - - return 0; -} - -static int transop_encode_aes( n2n_trans_op_t * arg, - uint8_t * outbuf, - size_t out_len, - const uint8_t * inbuf, - size_t in_len ) -{ - return -1; -} - -static int transop_decode_aes( n2n_trans_op_t * arg, - uint8_t * outbuf, - size_t out_len, - const uint8_t * inbuf, - size_t in_len ) -{ - return -1; -} - -static int transop_addspec_aes( n2n_trans_op_t * arg, const n2n_cipherspec_t * cspec ) -{ - traceEvent( TRACE_DEBUG, "transop_addspec_aes AES not built into edge.\n"); - - return -1; -} - -static n2n_tostat_t transop_tick_aes( n2n_trans_op_t * arg, time_t now ) -{ - n2n_tostat_t r; - - memset( &r, 0, sizeof(r) ); - - return r; -} - -int transop_aes_init( n2n_trans_op_t * ttt ) -{ - int retval = 1; - transop_aes_t * priv = NULL; - - if ( ttt->priv ) - { - transop_deinit_aes( ttt ); - } - - memset( ttt, 0, sizeof( n2n_trans_op_t ) ); - - priv = (transop_aes_t *) malloc( sizeof(transop_aes_t) ); - - if ( NULL != priv ) - { - /* install the private structure. */ - ttt->priv = priv; - priv->tx_sa=0; /* We will use this sa index for encoding. */ - - ttt->transform_id = N2N_TRANSFORM_ID_AESCBC; - ttt->addspec = transop_addspec_aes; - ttt->tick = transop_tick_aes; /* chooses a new tx_sa */ - ttt->deinit = transop_deinit_aes; - ttt->fwd = transop_encode_aes; - ttt->rev = transop_decode_aes; - - retval = 0; - } - else - { - memset( ttt, 0, sizeof(n2n_trans_op_t) ); - traceEvent( TRACE_ERROR, "Failed to allocate priv for aes" ); - } - - return retval; -} - -#endif /* #if defined(N2N_HAVE_AES) */ - diff --git a/n2n_v2/transform_null.c b/n2n_v2/transform_null.c deleted file mode 100644 index b486989..0000000 --- a/n2n_v2/transform_null.c +++ /dev/null @@ -1,84 +0,0 @@ -/* (c) 2009 Richard Andrews */ - -#include "n2n.h" -#include "n2n_transforms.h" - -static int transop_deinit_null( n2n_trans_op_t * arg ) -{ - /* nothing to deallocate, nothing to release. */ - return 0; -} - -static int transop_encode_null( n2n_trans_op_t * arg, - uint8_t * outbuf, - size_t out_len, - const uint8_t * inbuf, - size_t in_len ) -{ - int retval = -1; - - traceEvent( TRACE_DEBUG, "encode_null %lu", in_len ); - if ( out_len >= in_len ) - { - memcpy( outbuf, inbuf, in_len ); - retval = in_len; - } - else - { - traceEvent( TRACE_DEBUG, "encode_null %lu too big for packet buffer", in_len ); - } - - return retval; -} - -static int transop_decode_null( n2n_trans_op_t * arg, - uint8_t * outbuf, - size_t out_len, - const uint8_t * inbuf, - size_t in_len ) -{ - int retval = -1; - - traceEvent( TRACE_DEBUG, "decode_null %lu", in_len ); - if ( out_len >= in_len ) - { - memcpy( outbuf, inbuf, in_len ); - retval = in_len; - } - else - { - traceEvent( TRACE_DEBUG, "decode_null %lu too big for packet buffer", in_len ); - } - - return retval; -} - -static int transop_addspec_null( n2n_trans_op_t * arg, const n2n_cipherspec_t * cspec ) -{ - return 0; -} - -static n2n_tostat_t transop_tick_null( n2n_trans_op_t * arg, time_t now ) -{ - n2n_tostat_t r; - - r.can_tx=1; - r.tx_spec.t = N2N_TRANSFORM_ID_NULL; - r.tx_spec.valid_from = 0; - r.tx_spec.valid_until = (time_t)(-1); - r.tx_spec.opaque_size=0; - - return r; -} - -void transop_null_init( n2n_trans_op_t * ttt ) -{ - memset(ttt, 0, sizeof(n2n_trans_op_t) ); - - ttt->transform_id = N2N_TRANSFORM_ID_NULL; - ttt->deinit = transop_deinit_null; - ttt->addspec = transop_addspec_null; - ttt->tick = transop_tick_null; - ttt->fwd = transop_encode_null; - ttt->rev = transop_decode_null; -} diff --git a/n2n_v2/transform_tf.c b/n2n_v2/transform_tf.c deleted file mode 100644 index 1ae5bc5..0000000 --- a/n2n_v2/transform_tf.c +++ /dev/null @@ -1,487 +0,0 @@ -/* (c) 2009 Richard Andrews */ - -#include "n2n.h" -#include "n2n_transforms.h" -#include "twofish.h" -#ifndef _MSC_VER -/* Not included in Visual Studio 2008 */ -#include /* index() */ -#endif - -#define N2N_TWOFISH_NUM_SA 32 /* space for SAa */ - -#define N2N_TWOFISH_TRANSFORM_VERSION 1 /* version of the transform encoding */ - -struct sa_twofish -{ - n2n_cipherspec_t spec; /* cipher spec parameters */ - n2n_sa_t sa_id; /* security association index */ - TWOFISH * enc_tf; /* tx state */ - TWOFISH * dec_tf; /* rx state */ -}; - -typedef struct sa_twofish sa_twofish_t; - - -/** Twofish transform state data. - * - * With a key-schedule in place this will be populated with a number of - * SAs. Each SA has a lifetime and some opque data. The opaque data for twofish - * consists of the SA number and key material. - * - */ -struct transop_tf -{ - ssize_t tx_sa; - size_t num_sa; - sa_twofish_t sa[N2N_TWOFISH_NUM_SA]; -}; - -typedef struct transop_tf transop_tf_t; - -static int transop_deinit_twofish( n2n_trans_op_t * arg ) -{ - transop_tf_t * priv = (transop_tf_t *)arg->priv; - size_t i; - - if ( priv ) - { - /* Memory was previously allocated */ - for (i=0; isa[i]); - - TwoFishDestroy(sa->enc_tf); /* deallocate TWOFISH */ - sa->enc_tf=NULL; - - TwoFishDestroy(sa->dec_tf); /* deallocate TWOFISH */ - sa->dec_tf=NULL; - - sa->sa_id=0; - } - - priv->num_sa=0; - priv->tx_sa=-1; - - free(priv); - } - - arg->priv=NULL; /* return to fully uninitialised state */ - - return 0; -} - -static size_t tf_choose_tx_sa( transop_tf_t * priv ) -{ - return priv->tx_sa; /* set in tick */ -} - -#define TRANSOP_TF_VER_SIZE 1 /* Support minor variants in encoding in one module. */ -#define TRANSOP_TF_NONCE_SIZE 4 -#define TRANSOP_TF_SA_SIZE 4 - -/** The twofish packet format consists of: - * - * - a 8-bit twofish encoding version in clear text - * - a 32-bit SA number in clear text - * - ciphertext encrypted from a 32-bit nonce followed by the payload. - * - * [V|SSSS|nnnnDDDDDDDDDDDDDDDDDDDDD] - * |<------ encrypted ------>| - */ -static int transop_encode_twofish( n2n_trans_op_t * arg, - uint8_t * outbuf, - size_t out_len, - const uint8_t * inbuf, - size_t in_len ) -{ - int len=-1; - transop_tf_t * priv = (transop_tf_t *)arg->priv; - uint8_t assembly[N2N_PKT_BUF_SIZE]; - uint32_t * pnonce; - - if ( (in_len + TRANSOP_TF_NONCE_SIZE) <= N2N_PKT_BUF_SIZE ) - { - if ( (in_len + TRANSOP_TF_NONCE_SIZE + TRANSOP_TF_SA_SIZE + TRANSOP_TF_VER_SIZE) <= out_len ) - { - size_t idx=0; - sa_twofish_t * sa; - size_t tx_sa_num = 0; - - /* The transmit sa is periodically updated */ - tx_sa_num = tf_choose_tx_sa( priv ); - - sa = &(priv->sa[tx_sa_num]); /* Proper Tx SA index */ - - traceEvent( TRACE_DEBUG, "encode_twofish %lu with SA %lu.", in_len, sa->sa_id ); - - /* Encode the twofish format version. */ - encode_uint8( outbuf, &idx, N2N_TWOFISH_TRANSFORM_VERSION ); - - /* Encode the security association (SA) number */ - encode_uint32( outbuf, &idx, sa->sa_id ); - - /* The assembly buffer is a source for encrypting data. The nonce is - * written in first followed by the packet payload. The whole - * contents of assembly are encrypted. */ - pnonce = (uint32_t *)assembly; - *pnonce = rand(); - memcpy( assembly + TRANSOP_TF_NONCE_SIZE, inbuf, in_len ); - - /* Encrypt the assembly contents and write the ciphertext after the SA. */ - len = TwoFishEncryptRaw( assembly, /* source */ - outbuf + TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE, - in_len + TRANSOP_TF_NONCE_SIZE, /* enc size */ - sa->enc_tf); - if ( len > 0 ) - { - len += TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE; /* size of data carried in UDP. */ - } - else - { - traceEvent( TRACE_ERROR, "encode_twofish encryption failed." ); - } - - } - else - { - traceEvent( TRACE_ERROR, "encode_twofish outbuf too small." ); - } - } - else - { - traceEvent( TRACE_ERROR, "encode_twofish inbuf too big to encrypt." ); - } - - return len; -} - - -/* Search through the array of SAs to find the one with the required ID. - * - * @return array index where found or -1 if not found - */ -static ssize_t twofish_find_sa( const transop_tf_t * priv, const n2n_sa_t req_id ) -{ - size_t i; - - for (i=0; i < priv->num_sa; ++i) - { - const sa_twofish_t * sa=NULL; - - sa = &(priv->sa[i]); - if (req_id == sa->sa_id) - { - return i; - } - } - - return -1; -} - - -/** The twofish packet format consists of: - * - * - a 8-bit twofish encoding version in clear text - * - a 32-bit SA number in clear text - * - ciphertext encrypted from a 32-bit nonce followed by the payload. - * - * [V|SSSS|nnnnDDDDDDDDDDDDDDDDDDDDD] - * |<------ encrypted ------>| - */ -static int transop_decode_twofish( n2n_trans_op_t * arg, - uint8_t * outbuf, - size_t out_len, - const uint8_t * inbuf, - size_t in_len ) -{ - int len=0; - transop_tf_t * priv = (transop_tf_t *)arg->priv; - uint8_t assembly[N2N_PKT_BUF_SIZE]; - - if ( ( (in_len - (TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE)) <= N2N_PKT_BUF_SIZE ) /* Cipher text fits in assembly */ - && (in_len >= (TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE + TRANSOP_TF_NONCE_SIZE) ) /* Has at least version, SA and nonce */ - ) - { - n2n_sa_t sa_rx; - ssize_t sa_idx=-1; - size_t rem=in_len; - size_t idx=0; - uint8_t tf_enc_ver=0; - - /* Get the encoding version to make sure it is supported */ - decode_uint8( &tf_enc_ver, inbuf, &rem, &idx ); - - if ( N2N_TWOFISH_TRANSFORM_VERSION == tf_enc_ver ) - { - /* Get the SA number and make sure we are decrypting with the right one. */ - decode_uint32( &sa_rx, inbuf, &rem, &idx ); - - sa_idx = twofish_find_sa(priv, sa_rx); - if ( sa_idx >= 0 ) - { - sa_twofish_t * sa = &(priv->sa[sa_idx]); - - traceEvent( TRACE_DEBUG, "decode_twofish %lu with SA %lu.", in_len, sa_rx, sa->sa_id ); - - len = TwoFishDecryptRaw( (void *)(inbuf + TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE), - assembly, /* destination */ - (in_len - (TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE)), - sa->dec_tf); - - if ( len > 0 ) - { - /* Step over 4-byte random nonce value */ - len -= TRANSOP_TF_NONCE_SIZE; /* size of ethernet packet */ - - memcpy( outbuf, - assembly + TRANSOP_TF_NONCE_SIZE, - len ); - } - else - { - traceEvent( TRACE_ERROR, "decode_twofish decryption failed." ); - } - - } - else - { - /* Wrong security association; drop the packet as it is undecodable. */ - traceEvent( TRACE_ERROR, "decode_twofish SA number %lu not found.", sa_rx ); - - /* REVISIT: should be able to load a new SA at this point to complete the decoding. */ - } - } - else - { - /* Wrong security association; drop the packet as it is undecodable. */ - traceEvent( TRACE_ERROR, "decode_twofish unsupported twofish version %u.", tf_enc_ver ); - - /* REVISIT: should be able to load a new SA at this point to complete the decoding. */ - } - } - else - { - traceEvent( TRACE_ERROR, "decode_twofish inbuf wrong size (%ul) to decrypt.", in_len ); - } - - return len; -} - -static int transop_addspec_twofish( n2n_trans_op_t * arg, const n2n_cipherspec_t * cspec ) -{ - int retval = 1; - ssize_t pstat=-1; - transop_tf_t * priv = (transop_tf_t *)arg->priv; - uint8_t keybuf[N2N_MAX_KEYSIZE]; - - if ( priv->num_sa < N2N_TWOFISH_NUM_SA ) - { - const char * op = (const char *)cspec->opaque; - const char * sep = index( op, '_' ); - - if ( sep ) - { - char tmp[256]; - size_t s; - - s = sep - op; - memcpy( tmp, cspec->opaque, s ); - tmp[s]=0; - - s = strlen(sep+1); /* sep is the _ which might be immediately followed by NULL */ - - priv->sa[priv->num_sa].spec = *cspec; - priv->sa[priv->num_sa].sa_id = strtoul(tmp, NULL, 10); - - pstat = n2n_parse_hex( keybuf, N2N_MAX_KEYSIZE, sep+1, s ); - if ( pstat > 0 ) - { - priv->sa[priv->num_sa].enc_tf = TwoFishInit( keybuf, pstat); - priv->sa[priv->num_sa].dec_tf = TwoFishInit( keybuf, pstat); - - traceEvent( TRACE_DEBUG, "transop_addspec_twofish sa_id=%u data=%s.\n", - priv->sa[priv->num_sa].sa_id, sep+1); - - ++(priv->num_sa); - retval = 0; - } - } - else - { - traceEvent( TRACE_ERROR, "transop_addspec_twofish : bad key data - missing '_'.\n"); - } - } - else - { - traceEvent( TRACE_ERROR, "transop_addspec_twofish : full.\n"); - } - - return retval; -} - - -static n2n_tostat_t transop_tick_twofish( n2n_trans_op_t * arg, time_t now ) -{ - transop_tf_t * priv = (transop_tf_t *)arg->priv; - size_t i; - int found=0; - n2n_tostat_t r; - - memset( &r, 0, sizeof(r) ); - - traceEvent( TRACE_DEBUG, "transop_tf tick num_sa=%u", priv->num_sa ); - - for ( i=0; i < priv->num_sa; ++i ) - { - if ( 0 == validCipherSpec( &(priv->sa[i].spec), now ) ) - { - time_t remaining = priv->sa[i].spec.valid_until - now; - - traceEvent( TRACE_INFO, "transop_tf choosing tx_sa=%u (valid for %lu sec)", priv->sa[i].sa_id, remaining ); - priv->tx_sa=i; - found=1; - break; - } - else - { - traceEvent( TRACE_DEBUG, "transop_tf tick rejecting sa=%u %lu -> %lu", - priv->sa[i].sa_id, priv->sa[i].spec.valid_from, priv->sa[i].spec.valid_until ); - } - } - - if ( 0==found) - { - traceEvent( TRACE_INFO, "transop_tf no keys are currently valid. Keeping tx_sa=%u", priv->tx_sa ); - } - else - { - r.can_tx = 1; - r.tx_spec.t = N2N_TRANSFORM_ID_TWOFISH; - r.tx_spec = priv->sa[priv->tx_sa].spec; - } - - return r; -} - - -int transop_twofish_setup( n2n_trans_op_t * ttt, - n2n_sa_t sa_num, - uint8_t * encrypt_pwd, - uint32_t encrypt_pwd_len ) -{ - int retval = 1; - transop_tf_t * priv = NULL; - - if ( ttt->priv ) - { - transop_deinit_twofish( ttt ); - } - - memset( ttt, 0, sizeof( n2n_trans_op_t ) ); - - priv = (transop_tf_t *) malloc( sizeof(transop_tf_t) ); - - if ( NULL != priv ) - { - size_t i; - sa_twofish_t * sa=NULL; - - /* install the private structure. */ - ttt->priv = priv; - - for(i=0; isa[i]); - sa->sa_id=0; - memset( &(sa->spec), 0, sizeof(n2n_cipherspec_t) ); - sa->enc_tf=NULL; - sa->dec_tf=NULL; - } - - priv->num_sa=1; /* There is one SA in the array. */ - priv->tx_sa=0; - sa = &(priv->sa[priv->tx_sa]); - sa->sa_id=sa_num; - sa->spec.valid_until = 0x7fffffff; - - /* This is a preshared key setup. Both Tx and Rx are using the same security association. */ - - sa->enc_tf = TwoFishInit(encrypt_pwd, encrypt_pwd_len); - sa->dec_tf = TwoFishInit(encrypt_pwd, encrypt_pwd_len); - - if ( (sa->enc_tf) && (sa->dec_tf) ) - { - ttt->transform_id = N2N_TRANSFORM_ID_TWOFISH; - ttt->deinit = transop_deinit_twofish; - ttt->addspec = transop_addspec_twofish; - ttt->tick = transop_tick_twofish; /* chooses a new tx_sa */ - ttt->fwd = transop_encode_twofish; - ttt->rev = transop_decode_twofish; - - retval = 0; - } - else - { - traceEvent( TRACE_ERROR, "TwoFishInit failed" ); - } - } - else - { - memset( ttt, 0, sizeof(n2n_trans_op_t) ); - traceEvent( TRACE_ERROR, "Failed to allocate priv for twofish" ); - } - - return retval; -} - -int transop_twofish_init( n2n_trans_op_t * ttt ) -{ - int retval = 1; - transop_tf_t * priv = NULL; - - if ( ttt->priv ) - { - transop_deinit_twofish( ttt ); - } - - memset( ttt, 0, sizeof( n2n_trans_op_t ) ); - - priv = (transop_tf_t *) malloc( sizeof(transop_tf_t) ); - - if ( NULL != priv ) - { - size_t i; - sa_twofish_t * sa=NULL; - - /* install the private structure. */ - ttt->priv = priv; - priv->num_sa=0; - priv->tx_sa=0; /* We will use this sa index for encoding. */ - - ttt->transform_id = N2N_TRANSFORM_ID_TWOFISH; - ttt->addspec = transop_addspec_twofish; - ttt->tick = transop_tick_twofish; /* chooses a new tx_sa */ - ttt->deinit = transop_deinit_twofish; - ttt->fwd = transop_encode_twofish; - ttt->rev = transop_decode_twofish; - - for(i=0; isa[i]); - sa->sa_id=0; - memset( &(sa->spec), 0, sizeof(n2n_cipherspec_t) ); - sa->enc_tf=NULL; - sa->dec_tf=NULL; - } - - retval = 0; - } - else - { - memset( ttt, 0, sizeof(n2n_trans_op_t) ); - traceEvent( TRACE_ERROR, "Failed to allocate priv for twofish" ); - } - - return retval; -} diff --git a/n2n_v2/tuntap_freebsd.c b/n2n_v2/tuntap_freebsd.c deleted file mode 100644 index 7d9096a..0000000 --- a/n2n_v2/tuntap_freebsd.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * (C) 2007-09 - Luca Deri - * - * 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" - -#ifdef __FreeBSD__ - -void tun_close(tuntap_dev *device); - -/* ********************************** */ - -#define N2N_FREEBSD_TAPDEVICE_SIZE 32 -int tuntap_open(tuntap_dev *device /* ignored */, - char *dev, - const char *address_mode, /* static or dhcp */ - char *device_ip, - char *device_mask, - const char * device_mac, - int mtu) { - int i; - char tap_device[N2N_FREEBSD_TAPDEVICE_SIZE]; - - for (i = 0; i < 255; i++) { - snprintf(tap_device, sizeof(tap_device), "/dev/tap%d", i); - - device->fd = open(tap_device, O_RDWR); - if(device->fd > 0) { - traceEvent(TRACE_NORMAL, "Succesfully open %s", tap_device); - break; - } - } - - if(device->fd < 0) { - traceEvent(TRACE_ERROR, "Unable to open tap device"); - return(-1); - } else { - char buf[256]; - FILE *fd; - - device->ip_addr = inet_addr(device_ip); - - if ( device_mac && device_mac[0] != '\0' ) - { - /* FIXME - This is not tested. Might be wrong syntax for OS X */ - - /* Set the hw address before bringing the if up. */ - snprintf(buf, sizeof(buf), "ifconfig tap%d ether %s", - i, device_mac); - system(buf); - } - - snprintf(buf, sizeof(buf), "ifconfig tap%d %s netmask %s mtu %d up", - i, device_ip, device_mask, mtu); - system(buf); - - traceEvent(TRACE_NORMAL, "Interface tap%d up and running (%s/%s)", - i, device_ip, device_mask); - - /* Read MAC address */ - - snprintf(buf, sizeof(buf), "ifconfig tap%d |grep ether|cut -c 8-24", i); - /* traceEvent(TRACE_INFO, "%s", buf); */ - - fd = popen(buf, "r"); - if(fd < 0) { - tun_close(device); - return(-1); - } else { - int a, b, c, d, e, f; - - buf[0] = 0; - fgets(buf, sizeof(buf), fd); - pclose(fd); - - if(buf[0] == '\0') { - traceEvent(TRACE_ERROR, "Unable to read tap%d interface MAC address"); - exit(0); - } - - traceEvent(TRACE_NORMAL, "Interface tap%d mac %s", i, buf); - if(sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", &a, &b, &c, &d, &e, &f) == 6) { - device->mac_addr[0] = a, device->mac_addr[1] = b; - device->mac_addr[2] = c, device->mac_addr[3] = d; - device->mac_addr[4] = e, device->mac_addr[5] = f; - } - } - } - - - /* read_mac(dev, device->mac_addr); */ - 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) -{ -} - -#endif /* #ifdef __FreeBSD__ */ diff --git a/n2n_v2/tuntap_linux.c b/n2n_v2/tuntap_linux.c deleted file mode 100644 index be3cbb9..0000000 --- a/n2n_v2/tuntap_linux.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * (C) 2007-09 - Luca Deri - * - * 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.h" - -#ifdef __linux__ - -static void read_mac(char *ifname, n2n_mac_t mac_addr) { - int _sock, res; - struct ifreq ifr; - macstr_t mac_addr_buf; - - memset (&ifr,0,sizeof(struct ifreq)); - - /* Dummy socket, just to make ioctls with */ - _sock=socket(PF_INET, SOCK_DGRAM, 0); - strcpy(ifr.ifr_name, ifname); - res = ioctl(_sock,SIOCGIFHWADDR,&ifr); - if (res<0) { - perror ("Get hw addr"); - } else - memcpy(mac_addr, ifr.ifr_ifru.ifru_hwaddr.sa_data, 6); - - traceEvent(TRACE_NORMAL, "Interface %s has MAC %s", - ifname, - macaddr_str(mac_addr_buf, mac_addr )); - close(_sock); -} - -/* ********************************** */ - -/** @brief Open and configure the TAP device for packet read/write. - * - * This routine creates the interface via the tuntap driver then uses ifconfig - * to configure address/mask and MTU. - * - * @param device - [inout] a device info holder object - * @param dev - user-defined name for the new iface, - * if NULL system will assign a name - * @param device_ip - address of iface - * @param device_mask - netmask for device_ip - * @param mtu - MTU for device_ip - * - * @return - negative value on error - * - non-negative file-descriptor on success - */ -int tuntap_open(tuntap_dev *device, - char *dev, /* user-definable interface name, eg. edge0 */ - const char *address_mode, /* static or dhcp */ - char *device_ip, - char *device_mask, - const char * device_mac, - int mtu) { - char *tuntap_device = "/dev/net/tun"; -#define N2N_LINUX_SYSTEMCMD_SIZE 128 - char buf[N2N_LINUX_SYSTEMCMD_SIZE]; - struct ifreq ifr; - int rc; - - device->fd = open(tuntap_device, O_RDWR); - if(device->fd < 0) { - printf("ERROR: ioctl() [%s][%d]\n", strerror(errno), errno); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_flags = IFF_TAP|IFF_NO_PI; /* Want a TAP device for layer 2 frames. */ - strncpy(ifr.ifr_name, dev, IFNAMSIZ); - rc = ioctl(device->fd, TUNSETIFF, (void *)&ifr); - - if(rc < 0) { - traceEvent(TRACE_ERROR, "ioctl() [%s][%d]\n", strerror(errno), rc); - close(device->fd); - return -1; - } - - /* Store the device name for later reuse */ - 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); - - device->ip_addr = inet_addr(device_ip); - device->device_mask = inet_addr(device_mask); - read_mac(dev, device->mac_addr); - 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; - 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. */ - - /* 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. */ - fread(buf, 1, 15, fp); - fclose(fp); - fp=NULL; - - traceEvent(TRACE_INFO, "ifconfig address = %s", buf); - - tuntap->ip_addr = inet_addr(buf); - } -} - - -#endif /* #ifdef __linux__ */ diff --git a/n2n_v2/tuntap_netbsd.c b/n2n_v2/tuntap_netbsd.c deleted file mode 100644 index 011f7df..0000000 --- a/n2n_v2/tuntap_netbsd.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * (C) 2007-09 - Luca Deri - * (C) 2009 - Alaric Snell-Pym - * - * 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" - -#ifdef __NetBSD__ - -#include -#include -#include - -void tun_close(tuntap_dev *device); - -/* ********************************** */ - -#define N2N_NETBSD_TAPDEVICE_SIZE 32 -int tuntap_open(tuntap_dev *device /* ignored */, - char *dev, - const char *address_mode, /* static or dhcp */ - char *device_ip, - char *device_mask, - const char * device_mac, - int mtu) { - char tap_device[N2N_NETBSD_TAPDEVICE_SIZE]; - struct ifreq req; - - 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); - } - else { - device->fd = open("/dev/tap", O_RDWR); - if(device->fd >= 0) { - 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); - } - else { - snprintf(tap_device, sizeof(tap_device), req.ifr_name); - } - } - } - - if(device->fd < 0) { - traceEvent(TRACE_ERROR, "Unable to open tap device (%s)", strerror(errno)); - return(-1); - } else { - char buf[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' ) - { - /* Set the hw address before bringing the if up. */ - snprintf(buf, sizeof(buf), "ifconfig %s link %s active", - tap_device, device_mac); - system(buf); - } - - snprintf(buf, sizeof(buf), "ifconfig %s %s netmask %s mtu %d up", - tap_device, device_ip, device_mask, mtu); - system(buf); - - traceEvent(TRACE_NORMAL, "Interface %s up and running (%s/%s)", - tap_device, device_ip, device_mask); - - /* Read MAC address */ - - snprintf(buf, sizeof(buf), "ifconfig %s |grep address|cut -c 11-28", tap_device); - /* traceEvent(TRACE_INFO, "%s", buf); */ - - fd = popen(buf, "r"); - if(fd < 0) { - tun_close(device); - return(-1); - } else { - int a, b, c, d, e, f; - - 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); - exit(0); - } - - traceEvent(TRACE_NORMAL, "Interface %s mac %s", tap_device, buf); - if(sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", &a, &b, &c, &d, &e, &f) == 6) { - device->mac_addr[0] = a, device->mac_addr[1] = b; - device->mac_addr[2] = c, device->mac_addr[3] = d; - device->mac_addr[4] = e, device->mac_addr[5] = f; - } - } - } - - - /* read_mac(dev, device->mac_addr); */ - 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) -{ -} - -#endif /* #ifdef __NetBSD__ */ diff --git a/n2n_v2/tuntap_osx.c b/n2n_v2/tuntap_osx.c deleted file mode 100644 index 6b37b1f..0000000 --- a/n2n_v2/tuntap_osx.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * (C) 2007-09 - Luca Deri - * - * 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" - -#ifdef _DARWIN_ - -void tun_close(tuntap_dev *device); - -/* ********************************** */ - -#define N2N_OSX_TAPDEVICE_SIZE 32 -int tuntap_open(tuntap_dev *device /* ignored */, - char *dev, - const char *address_mode, /* static or dhcp */ - char *device_ip, - char *device_mask, - const char * device_mac, - int mtu) { - int i; - char tap_device[N2N_OSX_TAPDEVICE_SIZE]; - - for (i = 0; i < 255; i++) { - snprintf(tap_device, sizeof(tap_device), "/dev/tap%d", i); - - device->fd = open(tap_device, O_RDWR); - if(device->fd > 0) { - traceEvent(TRACE_NORMAL, "Succesfully open %s", tap_device); - break; - } - } - - if(device->fd < 0) { - traceEvent(TRACE_ERROR, "Unable to open tap device"); - return(-1); - } else { - char buf[256]; - FILE *fd; - - device->ip_addr = inet_addr(device_ip); - - if ( device_mac && device_mac[0] != '\0' ) - { - /* FIXME - This is not tested. Might be wrong syntax for OS X */ - - /* Set the hw address before bringing the if up. */ - snprintf(buf, sizeof(buf), "ifconfig tap%d ether %s", - i, device_mac); - system(buf); - } - - snprintf(buf, sizeof(buf), "ifconfig tap%d %s netmask %s mtu %d up", - i, device_ip, device_mask, mtu); - system(buf); - - traceEvent(TRACE_NORMAL, "Interface tap%d up and running (%s/%s)", - i, device_ip, device_mask); - - /* Read MAC address */ - - snprintf(buf, sizeof(buf), "ifconfig tap%d |grep ether|cut -c 8-24", i); - /* traceEvent(TRACE_INFO, "%s", buf); */ - - fd = popen(buf, "r"); - if(fd < 0) { - tun_close(device); - return(-1); - } else { - int a, b, c, d, e, f; - - buf[0] = 0; - fgets(buf, sizeof(buf), fd); - pclose(fd); - - if(buf[0] == '\0') { - traceEvent(TRACE_ERROR, "Unable to read tap%d interface MAC address"); - exit(0); - } - - traceEvent(TRACE_NORMAL, "Interface tap%d [MTU %d] mac %s", i, mtu, buf); - if(sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", &a, &b, &c, &d, &e, &f) == 6) { - device->mac_addr[0] = a, device->mac_addr[1] = b; - device->mac_addr[2] = c, device->mac_addr[3] = d; - device->mac_addr[4] = e, device->mac_addr[5] = f; - } - } - } - - - /* read_mac(dev, device->mac_addr); */ - 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) -{ -} - -#endif /* _DARWIN_ */ diff --git a/n2n_v2/version.c b/n2n_v2/version.c deleted file mode 100644 index 0963b8f..0000000 --- a/n2n_v2/version.c +++ /dev/null @@ -1,3 +0,0 @@ -const char * n2n_sw_version = N2N_VERSION; -const char * n2n_sw_osName = N2N_OSNAME; -const char * n2n_sw_buildDate = __DATE__ " " __TIME__; diff --git a/n2n_v2/win32/DotNet/n2n.suo b/n2n_v2/win32/DotNet/n2n.suo deleted file mode 100644 index aae212b..0000000 Binary files a/n2n_v2/win32/DotNet/n2n.suo and /dev/null differ diff --git a/n2n_v2/win32/getopt.c b/n2n_v2/win32/getopt.c deleted file mode 100644 index c938ea3..0000000 --- a/n2n_v2/win32/getopt.c +++ /dev/null @@ -1,1074 +0,0 @@ -/* Getopt for GNU. - NOTE: getopt is now part of the C library, so if you don't know what - "Keep this file name-space clean" means, talk to drepper@gnu.org - before changing it! - - Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000 - Free Software Foundation, Inc. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* This tells Alpha OSF/1 not to define a getopt prototype in . - Ditto for AIX 3.2 and . */ -#ifndef _NO_PROTO -# define _NO_PROTO -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#if !defined __STDC__ || !__STDC__ -/* This is a separate conditional since some stdc systems - reject `defined (const)'. */ -# ifndef const -# define const -# endif -#endif - -#include -#ifdef WIN32 -#include -#endif - -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself. This code is part of the GNU C - Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, - it is simpler to just do this in the source for each such file. */ - -#define GETOPT_INTERFACE_VERSION 2 -#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 -# include -# if _GNU_GETOPT<_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION -# define ELIDE_CODE -# endif -#endif - -#ifndef ELIDE_CODE - - -/* This needs to come after some library #include - to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ -/* Don't include stdlib.h for non-GNU C libraries because some of them - contain conflicting prototypes for getopt. */ -# include -# include -#endif /* GNU C library. */ - -#ifdef VMS -# include -# if HAVE_STRING_H - 0 -# include -# endif -#endif - -#ifndef _ -/* This is for other GNU distributions with internationalized messages. - When compiling libc, the _ macro is predefined. */ -# ifdef HAVE_LIBINTL_H -# include -# define _(msgid) gettext (msgid) -# else -# define _(msgid) (msgid) -# endif -#endif - -/* This version of `getopt' appears to the caller like standard Unix `getopt' - but it behaves differently for the user, since it allows the user - to intersperse the options with the other arguments. - - As `getopt' works, it permutes the elements of ARGV so that, - when it is done, all the options precede everything else. Thus - all application programs are extended to handle flexible argument order. - - Setting the environment variable POSIXLY_CORRECT disables permutation. - Then the behavior is completely standard. - - GNU application programs can use a third alternative mode in which - they can distinguish the relative order of options and other arguments. */ - -#include "getopt.h" - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -#ifndef DARWIN -char *optarg; -#endif - - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -/* 1003.2 says this must be 1 before any call. */ -#ifndef DARWIN -int optind = 1; -#endif - -/* Formerly, initialization of getopt depended on optind==0, which - causes problems with re-calling getopt as programs generally don't - know that. */ - -int __getopt_initialized; - -/* The next char to be scanned in the option-element - in which the last option character we returned was found. - This allows us to pick up the scan where we left off. - - If this is zero, or a null string, it means resume the scan - by advancing to the next ARGV-element. */ - -static char *nextchar; - -/* Callers store zero here to inhibit the error message - for unrecognized options. */ - -#ifndef DARWIN -#ifdef WIN32 -int opterr = 0; -#else -int opterr = 1; -#endif -#endif - -/* Set to an option character which was unrecognized. - This must be initialized on some systems to avoid linking in the - system's own getopt implementation. */ -#ifndef DARWIN -int optopt = '?'; -#endif - -/* Describe how to deal with options that follow non-option ARGV-elements. - - If the caller did not specify anything, - the default is REQUIRE_ORDER if the environment variable - POSIXLY_CORRECT is defined, PERMUTE otherwise. - - REQUIRE_ORDER means don't recognize them as options; - stop option processing when the first non-option is seen. - This is what Unix does. - This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using `+' as the first character - of the list of option characters. - - PERMUTE is the default. We permute the contents of ARGV as we scan, - so that eventually all the non-options are at the end. This allows options - to be given in any order, even with programs that were not written to - expect this. - - RETURN_IN_ORDER is an option available to programs that were written - to expect options and other ARGV-elements in any order and that care about - the ordering of the two. We describe each non-option ARGV-element - as if it were the argument of an option with character code 1. - Using `-' as the first character of the list of option characters - selects this mode of operation. - - The special argument `--' forces an end of option-scanning regardless - of the value of `ordering'. In the case of RETURN_IN_ORDER, only - `--' can cause `getopt' to return -1 with `optind' != ARGC. */ - -static enum -{ - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER -} ordering; - -/* Value of POSIXLY_CORRECT environment variable. */ -static char *posixly_correct; - -#ifdef __GNU_LIBRARY__ -/* We want to avoid inclusion of string.h with non-GNU libraries - because there are many ways it can cause trouble. - On some systems, it contains special magic macros that don't work - in GCC. */ -# include -# define my_index strchr -#else - -#ifndef WIN32 -# if HAVE_STRING_H -# include -# else -# include -# endif -#endif - -/* Avoid depending on library functions or files - whose names are inconsistent. */ - -#ifndef getenv -extern char *getenv (); -#endif - -static char * -my_index (str, chr) - const char *str; - int chr; -{ - while (*str) - { - if (*str == chr) - return (char *) str; - str++; - } - return 0; -} - -/* If using GCC, we can safely declare strlen this way. - If not using GCC, it is ok not to declare it. */ -#ifdef __GNUC__ -/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. - That was relevant to code that was here before. */ -# if (!defined __STDC__ || !__STDC__) && !defined strlen -/* gcc with -traditional declares the built-in strlen to return int, - and has done so at least since version 2.4.5. -- rms. */ -extern int strlen (const char *); -# endif /* not __STDC__ */ -#endif /* __GNUC__ */ - -#endif /* not __GNU_LIBRARY__ */ - -/* Handle permutation of arguments. */ - -/* Describe the part of ARGV that contains non-options that have - been skipped. `first_nonopt' is the index in ARGV of the first of them; - `last_nonopt' is the index after the last of them. */ - -static int first_nonopt; -static int last_nonopt; - -#ifdef _LIBC -/* Bash 2.0 gives us an environment variable containing flags - indicating ARGV elements that should not be considered arguments. */ - -/* Defined in getopt_init.c */ -extern char *__getopt_nonoption_flags; - -static int nonoption_flags_max_len; -static int nonoption_flags_len; - -static int original_argc; -static char *const *original_argv; - -/* Make sure the environment variable bash 2.0 puts in the environment - is valid for the getopt call we must make sure that the ARGV passed - to getopt is that one passed to the process. */ -static void -__attribute__ ((unused)) -store_args_and_env (int argc, char *const *argv) -{ - /* XXX This is no good solution. We should rather copy the args so - that we can compare them later. But we must not use malloc(3). */ - original_argc = argc; - original_argv = argv; -} -# ifdef text_set_element -text_set_element (__libc_subinit, store_args_and_env); -# endif /* text_set_element */ - -# define SWAP_FLAGS(ch1, ch2) \ - if (nonoption_flags_len > 0) \ - { \ - char __tmp = __getopt_nonoption_flags[ch1]; \ - __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ - __getopt_nonoption_flags[ch2] = __tmp; \ - } -#else /* !_LIBC */ -# define SWAP_FLAGS(ch1, ch2) -#endif /* _LIBC */ - -/* Exchange two adjacent subsequences of ARGV. - One subsequence is elements [first_nonopt,last_nonopt) - which contains all the non-options that have been skipped so far. - The other is elements [last_nonopt,optind), which contains all - the options processed since those non-options were skipped. - - `first_nonopt' and `last_nonopt' are relocated so that they describe - the new indices of the non-options in ARGV after they are moved. */ - -#if defined __STDC__ && __STDC__ -static void exchange (char **); -#endif - -static void -exchange (argv) - char **argv; -{ - int bottom = first_nonopt; - int middle = last_nonopt; - int top = optind; - char *tem; - - /* Exchange the shorter segment with the far end of the longer segment. - That puts the shorter segment into the right place. - It leaves the longer segment in the right place overall, - but it consists of two parts that need to be swapped next. */ - -#ifdef _LIBC - /* First make sure the handling of the `__getopt_nonoption_flags' - string can work normally. Our top argument must be in the range - of the string. */ - if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) - { - /* We must extend the array. The user plays games with us and - presents new arguments. */ - char *new_str = malloc (top + 1); - if (new_str == NULL) - nonoption_flags_len = nonoption_flags_max_len = 0; - else - { - memset (__mempcpy (new_str, __getopt_nonoption_flags, - nonoption_flags_max_len), - '\0', top + 1 - nonoption_flags_max_len); - nonoption_flags_max_len = top + 1; - __getopt_nonoption_flags = new_str; - } - } -#endif - - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - /* Bottom segment is the short one. */ - int len = middle - bottom; - register int i; - - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; - } - else - { - /* Top segment is the short one. */ - int len = top - middle; - register int i; - - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - SWAP_FLAGS (bottom + i, middle + i); - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; - } - } - - /* Update records for the slots the non-options now occupy. */ - - first_nonopt += (optind - last_nonopt); - last_nonopt = optind; -} - -/* Initialize the internal data when the first call is made. */ - -#if defined __STDC__ && __STDC__ -static const char *_getopt_initialize (int, char *const *, const char *); -#endif -static const char * -_getopt_initialize (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; -{ - /* Start processing options with ARGV-element 1 (since ARGV-element 0 - is the program name); the sequence of previously skipped - non-option ARGV-elements is empty. */ - - first_nonopt = last_nonopt = optind; - - nextchar = NULL; - - posixly_correct = getenv ("POSIXLY_CORRECT"); - - /* Determine how to handle the ordering of options and nonoptions. */ - - if (optstring[0] == '-') - { - ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - ordering = REQUIRE_ORDER; - ++optstring; - } - else if (posixly_correct != NULL) - ordering = REQUIRE_ORDER; - else - ordering = PERMUTE; - -#ifdef _LIBC - if (posixly_correct == NULL - && argc == original_argc && argv == original_argv) - { - if (nonoption_flags_max_len == 0) - { - if (__getopt_nonoption_flags == NULL - || __getopt_nonoption_flags[0] == '\0') - nonoption_flags_max_len = -1; - else - { - const char *orig_str = __getopt_nonoption_flags; - int len = nonoption_flags_max_len = strlen (orig_str); - if (nonoption_flags_max_len < argc) - nonoption_flags_max_len = argc; - __getopt_nonoption_flags = - (char *) malloc (nonoption_flags_max_len); - if (__getopt_nonoption_flags == NULL) - nonoption_flags_max_len = -1; - else - memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), - '\0', nonoption_flags_max_len - len); - } - } - nonoption_flags_len = nonoption_flags_max_len; - } - else - nonoption_flags_len = 0; -#endif - - return optstring; -} - -/* Scan elements of ARGV (whose length is ARGC) for option characters - given in OPTSTRING. - - If an element of ARGV starts with '-', and is not exactly "-" or "--", - then it is an option element. The characters of this element - (aside from the initial '-') are option characters. If `getopt' - is called repeatedly, it returns successively each of the option characters - from each of the option elements. - - If `getopt' finds another option character, it returns that character, - updating `optind' and `nextchar' so that the next call to `getopt' can - resume the scan with the following option character or ARGV-element. - - If there are no more option characters, `getopt' returns -1. - Then `optind' is the index in ARGV of the first ARGV-element - that is not an option. (The ARGV-elements have been permuted - so that those that are not options now come last.) - - OPTSTRING is a string containing the legitimate option characters. - If an option character is seen that is not listed in OPTSTRING, - return '?' after printing an error message. If you set `opterr' to - zero, the error message is suppressed but we still return '?'. - - If a char in OPTSTRING is followed by a colon, that means it wants an arg, - so the following text in the same ARGV-element, or the text of the following - ARGV-element, is returned in `optarg'. Two colons mean an option that - wants an optional arg; if there is text in the current ARGV-element, - it is returned in `optarg', otherwise `optarg' is set to zero. - - If OPTSTRING starts with `-' or `+', it requests different methods of - handling the non-option ARGV-elements. - See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. - - Long-named options begin with `--' instead of `-'. - Their names may be abbreviated as long as the abbreviation is unique - or is an exact match for some defined option. If they have an - argument, it follows the option name in the same ARGV-element, separated - from the option name by a `=', or else the in next ARGV-element. - When `getopt' finds a long-named option, it returns 0 if that option's - `flag' field is nonzero, the value of the option's `val' field - if the `flag' field is zero. - - The elements of ARGV aren't really const, because we permute them. - But we pretend they're const in the prototype to be compatible - with other systems. - - LONGOPTS is a vector of `struct option' terminated by an - element containing a name which is zero. - - LONGIND returns the index in LONGOPT of the long-named option found. - It is only valid when a long-named option has been found by the most - recent call. - - If LONG_ONLY is nonzero, '-' as well as '--' can introduce - long-named options. */ - -int -_getopt_internal (argc, argv, optstring, longopts, longind, long_only) - int argc; - char *const *argv; - const char *optstring; - const struct option *longopts; - int *longind; - int long_only; -{ - int print_errors = opterr; - if (optstring[0] == ':') - print_errors = 0; - - optarg = NULL; - - if (optind == 0 || !__getopt_initialized) - { - if (optind == 0) - optind = 1; /* Don't scan ARGV[0], the program name. */ - optstring = _getopt_initialize (argc, argv, optstring); - __getopt_initialized = 1; - } - - /* Test whether ARGV[optind] points to a non-option argument. - Either it does not have option syntax, or there is an environment flag - from the shell indicating it is not an option. The later information - is only used when the used in the GNU libc. */ -#ifdef _LIBC -# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ - || (optind < nonoption_flags_len \ - && __getopt_nonoption_flags[optind] == '1')) -#else -# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') -#endif - - if (nextchar == NULL || *nextchar == '\0') - { - /* Advance to the next ARGV-element. */ - - /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been - moved back by the user (who may also have changed the arguments). */ - if (last_nonopt > optind) - last_nonopt = optind; - if (first_nonopt > optind) - first_nonopt = optind; - - if (ordering == PERMUTE) - { - /* If we have just processed some options following some non-options, - exchange them so that the options come first. */ - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (last_nonopt != optind) - first_nonopt = optind; - - /* Skip any additional non-options - and extend the range of non-options previously skipped. */ - - while (optind < argc && NONOPTION_P) - optind++; - last_nonopt = optind; - } - - /* The special ARGV-element `--' means premature end of options. - Skip it like a null option, - then exchange with previous non-options as if it were an option, - then skip everything else like a non-option. */ - - if (optind != argc && !strcmp (argv[optind], "--")) - { - optind++; - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (first_nonopt == last_nonopt) - first_nonopt = optind; - last_nonopt = argc; - - optind = argc; - } - - /* If we have done all the ARGV-elements, stop the scan - and back over any non-options that we skipped and permuted. */ - - if (optind == argc) - { - /* Set the next-arg-index to point at the non-options - that we previously skipped, so the caller will digest them. */ - if (first_nonopt != last_nonopt) - optind = first_nonopt; - return -1; - } - - /* If we have come to a non-option and did not permute it, - either stop the scan or describe it to the caller and pass it by. */ - - if (NONOPTION_P) - { - if (ordering == REQUIRE_ORDER) - return -1; - - optarg = argv[optind++]; - return 1; - } - - /* We have found another option-ARGV-element. - Skip the initial punctuation. */ - - nextchar = (argv[optind] + 1 - + (longopts != NULL && argv[optind][1] == '-')); - } - - /* Decode the current option-ARGV-element. */ - - /* Check whether the ARGV-element is a long option. - - If long_only and the ARGV-element has the form "-f", where f is - a valid short option, don't consider it an abbreviated form of - a long option that starts with f. Otherwise there would be no - way to give the -f short option. - - On the other hand, if there's a long option "fubar" and - the ARGV-element is "-fu", do consider that an abbreviation of - the long option, just like "--fu", and not "-f" with arg "u". - - This distinction seems to be the most useful approach. */ - - if (longopts != NULL - && (argv[optind][1] == '-' - || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = -1; - int option_index; - - for (nameend = nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if ((unsigned int) (nameend - nextchar) - == (unsigned int) strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - - if (ambig && !exact) - { - if (print_errors) - fprintf (stderr, _("%s: option `%s' is ambiguous\n"), - argv[0], argv[optind]); - nextchar += strlen (nextchar); - optind++; - optopt = 0; - return '?'; - } - - if (pfound != NULL) - { - option_index = indfound; - optind++; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (print_errors) - { - if (argv[optind - 1][1] == '-') - /* --option */ - fprintf (stderr, - _("%s: option `--%s' doesn't allow an argument\n"), - argv[0], pfound->name); - else - /* +option or -option */ - fprintf (stderr, - _("%s: option `%c%s' doesn't allow an argument\n"), - argv[0], argv[optind - 1][0], pfound->name); - } - - nextchar += strlen (nextchar); - - optopt = pfound->val; - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (print_errors) - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); - nextchar += strlen (nextchar); - optopt = pfound->val; - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - - /* Can't find it as a long option. If this is not getopt_long_only, - or the option starts with '--' or is not a valid short - option, then it's an error. - Otherwise interpret it as a short option. */ - if (!long_only || argv[optind][1] == '-' - || my_index (optstring, *nextchar) == NULL) - { - if (print_errors) - { - if (argv[optind][1] == '-') - /* --option */ - fprintf (stderr, _("%s: unrecognized option `--%s'\n"), - argv[0], nextchar); - else - /* +option or -option */ - fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), - argv[0], argv[optind][0], nextchar); - } - nextchar = (char *) ""; - optind++; - optopt = 0; - return '?'; - } - } - - /* Look at and handle the next short option-character. */ - - { - char c = *nextchar++; - char *temp = my_index (optstring, c); - - /* Increment `optind' when we start to process its last character. */ - if (*nextchar == '\0') - ++optind; - - if (temp == NULL || c == ':') - { - if (print_errors) - { - if (posixly_correct) - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, _("%s: illegal option -- %c\n"), - argv[0], c); - else - fprintf (stderr, _("%s: invalid option -- %c\n"), - argv[0], c); - } - optopt = c; - return '?'; - } - /* Convenience. Treat POSIX -W foo same as long option --foo */ - if (temp[0] == 'W' && temp[1] == ';') - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = 0; - int option_index; - - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (print_errors) - { - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, _("%s: option requires an argument -- %c\n"), - argv[0], c); - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - return c; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - - /* optarg is now the argument, see if it's in the - table of longopts. */ - - for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if ((unsigned int) (nameend - nextchar) == strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - if (ambig && !exact) - { - if (print_errors) - fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), - argv[0], argv[optind]); - nextchar += strlen (nextchar); - optind++; - return '?'; - } - if (pfound != NULL) - { - option_index = indfound; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (print_errors) - fprintf (stderr, _("\ -%s: option `-W %s' doesn't allow an argument\n"), - argv[0], pfound->name); - - nextchar += strlen (nextchar); - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (print_errors) - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); - nextchar += strlen (nextchar); - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - nextchar = NULL; - return 'W'; /* Let the application handle it. */ - } - if (temp[1] == ':') - { - if (temp[2] == ':') - { - /* This is an option that accepts an argument optionally. */ - if (*nextchar != '\0') - { - optarg = nextchar; - optind++; - } - else - optarg = NULL; - nextchar = NULL; - } - else - { - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (print_errors) - { - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, - _("%s: option requires an argument -- %c\n"), - argv[0], c); - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - nextchar = NULL; - } - } - return c; - } -} - -int -getopt____ (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; -{ - return _getopt_internal (argc, argv, optstring, - (const struct option *) 0, - (int *) 0, - 0); -} - -#endif /* Not ELIDE_CODE. */ - -#ifdef TEST - -/* Compile with -DTEST to make an executable for use in testing - the above definition of `getopt'. */ - -int -main (argc, argv) - int argc; - char **argv; -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - - c = getopt (argc, argv, "abc:d:0123456789"); - if (c == -1) - break; - - switch (c) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */ - diff --git a/n2n_v2/win32/getopt.h b/n2n_v2/win32/getopt.h deleted file mode 100644 index 91eb54e..0000000 --- a/n2n_v2/win32/getopt.h +++ /dev/null @@ -1,169 +0,0 @@ -/* Declarations for getopt. - Copyright (C) 1989,90,91,92,93,94,96,97,98 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _GETOPT_H - -#ifndef __need_getopt -# define _GETOPT_H 1 -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -extern char *optarg; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -extern int optind; - -/* Callers store zero here to inhibit the error message `getopt' prints - for unrecognized options. */ - -extern int opterr; - -/* Set to an option character which was unrecognized. */ - -extern int optopt; - -#ifndef __need_getopt -/* Describe the long-named options requested by the application. - The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector - of `struct option' terminated by an element containing a name which is - zero. - - The field `has_arg' is: - no_argument (or 0) if the option does not take an argument, - required_argument (or 1) if the option requires an argument, - optional_argument (or 2) if the option takes an optional argument. - - If the field `flag' is not NULL, it points to a variable that is set - to the value given in the field `val' when the option is found, but - left unchanged if the option is not found. - - To have a long-named option do something other than set an `int' to - a compiled-in constant, such as set a value from `optarg', set the - option's `flag' field to zero and its `val' field to a nonzero - value (the equivalent single-letter option character, if there is - one). For long options that have a zero `flag' field, `getopt' - returns the contents of the `val' field. */ - -struct option -{ -# if defined __STDC__ && __STDC__ - const char *name; -# else - char *name; -# endif - /* has_arg can't be an enum because some compilers complain about - type mismatches in all the code that assumes it is an int. */ - int has_arg; - int *flag; - int val; -}; - -/* Names for the values of the `has_arg' field of `struct option'. */ - -# define no_argument 0 -# define required_argument 1 -# define optional_argument 2 -#endif /* need getopt */ - - -/* Get definitions and prototypes for functions to process the - arguments in ARGV (ARGC of them, minus the program name) for - options given in OPTS. - - Return the option character from OPTS just read. Return -1 when - there are no more options. For unrecognized options, or options - missing arguments, `optopt' is set to the option letter, and '?' is - returned. - - The OPTS string is a list of characters which are recognized option - letters, optionally followed by colons, specifying that that letter - takes an argument, to be placed in `optarg'. - - If a letter in OPTS is followed by two colons, its argument is - optional. This behavior is specific to the GNU `getopt'. - - The argument `--' causes premature termination of argument - scanning, explicitly telling `getopt' that there are no more - options. - - If OPTS begins with `--', then non-option arguments are treated as - arguments to the option '\0'. This behavior is specific to the GNU - `getopt'. */ - -#if defined __STDC__ && __STDC__ -# ifdef __GNU_LIBRARY__ -/* Many other libraries have conflicting prototypes for getopt, with - differences in the consts, in stdlib.h. To avoid compilation - errors, only prototype getopt for the GNU C library. */ -extern int getopt (int __argc, char *const *__argv, const char *__shortopts); -# else /* not __GNU_LIBRARY__ */ -extern int getopt (); -# endif /* __GNU_LIBRARY__ */ - -# ifndef __need_getopt -extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts, - const struct option *__longopts, int *__longind); -extern int getopt_long_only (int __argc, char *const *__argv, - const char *__shortopts, - const struct option *__longopts, int *__longind); - -/* Internal only. Users should not call this directly. */ -extern int _getopt_internal (int __argc, char *const *__argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - int __long_only); -# endif -#else /* not __STDC__ */ -extern int getopt (); -# ifndef __need_getopt -extern int getopt_long (); -extern int getopt_long_only (); - -extern int _getopt_internal (); -# endif -#endif /* __STDC__ */ - -#ifdef __cplusplus -} -#endif - -/* Make sure we later can get all the definitions and declarations. */ -#undef __need_getopt - -#endif /* getopt.h */ diff --git a/n2n_v2/win32/getopt1.c b/n2n_v2/win32/getopt1.c deleted file mode 100644 index f7ca91c..0000000 --- a/n2n_v2/win32/getopt1.c +++ /dev/null @@ -1,188 +0,0 @@ -/* getopt_long and getopt_long_only entry points for GNU getopt. - Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 - Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "getopt.h" - -#if !defined __STDC__ || !__STDC__ -/* This is a separate conditional since some stdc systems - reject `defined (const)'. */ -#ifndef const -#define const -#endif -#endif - -#include - -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself. This code is part of the GNU C - Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, - it is simpler to just do this in the source for each such file. */ - -#define GETOPT_INTERFACE_VERSION 2 -#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 -#include -#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION -#define ELIDE_CODE -#endif -#endif - -#ifndef ELIDE_CODE - - -/* This needs to come after some library #include - to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ -#include -#endif - -#ifndef NULL -#define NULL 0 -#endif - -int -getopt_long (argc, argv, options, long_options, opt_index) - int argc; - char *const *argv; - const char *options; - const struct option *long_options; - int *opt_index; -{ - return _getopt_internal (argc, argv, options, long_options, opt_index, 0); -} - -/* Like getopt_long, but '-' as well as '--' can indicate a long option. - If an option that starts with '-' (not '--') doesn't match a long option, - but does match a short option, it is parsed as a short option - instead. */ - -int -getopt_long_only (argc, argv, options, long_options, opt_index) - int argc; - char *const *argv; - const char *options; - const struct option *long_options; - int *opt_index; -{ - return _getopt_internal (argc, argv, options, long_options, opt_index, 1); -} - - -#endif /* Not ELIDE_CODE. */ - -#ifdef TEST - -#include - -int -main (argc, argv) - int argc; - char **argv; -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - int option_index = 0; - static struct option long_options[] = - { - {"add", 1, 0, 0}, - {"append", 0, 0, 0}, - {"delete", 1, 0, 0}, - {"verbose", 0, 0, 0}, - {"create", 0, 0, 0}, - {"file", 1, 0, 0}, - {0, 0, 0, 0} - }; - - c = getopt_long (argc, argv, "abc:d:0123456789", - long_options, &option_index); - if (c == -1) - break; - - switch (c) - { - case 0: - printf ("option %s", long_options[option_index].name); - if (optarg) - printf (" with arg %s", optarg); - printf ("\n"); - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case 'd': - printf ("option d with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */ diff --git a/n2n_v2/win32/n2n_win32.c b/n2n_v2/win32/n2n_win32.c deleted file mode 100644 index 032a5a8..0000000 --- a/n2n_v2/win32/n2n_win32.c +++ /dev/null @@ -1,18 +0,0 @@ -/* - * win32 compile fix 05/01/2011 Dominik Meyer - */ - -#include "n2n_win32.h" - -int gettimeofday (struct timeval *tv, void* tz) -{ - union { - long long ns100; /*time since 1 Jan 1601 in 100ns units */ - FILETIME ft; - } now; - - GetSystemTimeAsFileTime (&now.ft); - tv->tv_usec = (long) ((now.ns100 / 10LL) % 1000000LL); - tv->tv_sec = (long) ((now.ns100 - 116444736000000000LL) / 10000000LL); - return (0); -}; \ No newline at end of file diff --git a/n2n_v2/win32/wintap.c b/n2n_v2/win32/wintap.c deleted file mode 100644 index e2e96bb..0000000 --- a/n2n_v2/win32/wintap.c +++ /dev/null @@ -1,310 +0,0 @@ -/* - (C) 2007-09 - Luca Deri -*/ - -#include "../n2n.h" -#include "n2n_win32.h" - -/* 1500 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */ -#define MTU 1518 - -void initWin32() { - WSADATA wsaData; - int err; - - err = WSAStartup(MAKEWORD(2, 2), &wsaData ); - if( err != 0 ) { - /* Tell the user that we could not find a usable */ - /* WinSock DLL. */ - printf("FATAL ERROR: unable to initialise Winsock 2.x."); - exit(-1); - } -} - -int open_wintap(struct tuntap_dev *device, - const char * address_mode, /* "static" or "dhcp" */ - char *device_ip, - char *device_mask, - const char *device_mac, - int mtu) { - HKEY key, key2; - LONG rc; - char regpath[1024], cmd[256]; - char adapterid[1024]; - char adaptername[1024]; - char tapname[1024]; - long len; - int found = 0; - int err, i; - ULONG status = TRUE; - - memset(device, 0, sizeof(struct tuntap_dev)); - device->device_handle = INVALID_HANDLE_VALUE; - device->device_name = NULL; - device->ifName = NULL; - device->ip_addr = inet_addr(device_ip); - - /* Open registry and look for network adapters */ - if((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key))) { - printf("Unable to read registry: [rc=%d]\n", rc); - exit(-1); - /* MSVC Note: If you keep getting rc=2 errors, make sure you set: - Project -> Properties -> Configuration Properties -> General -> Character set - to: "Use Multi-Byte Character Set" - */ - } - - for (i = 0; ; i++) { - len = sizeof(adapterid); - if(RegEnumKeyEx(key, i, (LPTSTR)adapterid, &len, 0, 0, 0, NULL)) - break; - - /* Find out more about this adapter */ - - _snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapterid); - if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)regpath, 0, KEY_READ, &key2)) - continue; - - len = sizeof(adaptername); - err = RegQueryValueEx(key2, "Name", 0, 0, adaptername, &len); - - RegCloseKey(key2); - - if(err) - continue; - - if(device->device_name) { - if(!strcmp(device->device_name, adapterid)) { - found = 1; - break; - } else - continue; - } - - if(device->ifName) { - if(!strcmp(device->ifName, adaptername)) { - found = 1; - break; - } else - continue; - } - - _snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid); - device->device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, - 0, /* Don't let other processes share or open - the resource until the handle's been closed */ - 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0); - if(device->device_handle != INVALID_HANDLE_VALUE) { - found = 1; - break; - } - } - - RegCloseKey(key); - - if(!found) { - printf("No Windows tap device found!\n"); - exit(0); - } - - /* ************************************** */ - - if(!device->device_name) - device->device_name = _strdup(adapterid); - - if(!device->ifName) - device->ifName = _strdup(adaptername); - - /* Try to open the corresponding tap device->device_name */ - - if(device->device_handle == INVALID_HANDLE_VALUE) { - _snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, device->device_name); - device->device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, - OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0); - } - - if(device->device_handle == INVALID_HANDLE_VALUE) { - printf("%s (%s) is not a usable Windows tap device\n", device->device_name, device->ifName); - exit(-1); - } - - /* Get MAC address from tap device->device_name */ - - if(!DeviceIoControl(device->device_handle, TAP_IOCTL_GET_MAC, - device->mac_addr, sizeof(device->mac_addr), - device->mac_addr, sizeof(device->mac_addr), &len, 0)) { - printf("Could not get MAC address from Windows tap %s (%s)\n", - device->device_name, device->ifName); - return -1; - } - - device->mtu = mtu; - - printf("Open device [name=%s][ip=%s][ifName=%s][MTU=%d][mac=%02X:%02X:%02X:%02X:%02X:%02X]\n", - device->device_name, device_ip, device->ifName, device->mtu, - device->mac_addr[0] & 0xFF, - device->mac_addr[1] & 0xFF, - device->mac_addr[2] & 0xFF, - device->mac_addr[3] & 0xFF, - device->mac_addr[4] & 0xFF, - device->mac_addr[5] & 0xFF); - - /* ****************** */ - - printf("Setting %s device address...\n", device->ifName); - - if ( 0 == strcmp("dhcp", address_mode) ) - { - _snprintf(cmd, sizeof(cmd), - "netsh interface ip set address \"%s\" dhcp", - device->ifName); - } - else - { - _snprintf(cmd, sizeof(cmd), - "netsh interface ip set address \"%s\" static %s %s", - device->ifName, device_ip, device_mask); - } - - if(system(cmd) == 0) { - device->ip_addr = inet_addr(device_ip); - device->device_mask = inet_addr(device_mask); - printf("Device %s set to %s/%s\n", - device->ifName, device_ip, device_mask); - } else - printf("WARNING: Unable to set device %s IP address [%s]\n", - device->ifName, cmd); - - /* ****************** */ - - if(device->mtu != DEFAULT_MTU) - printf("WARNING: MTU set is not supported on Windows\n"); - - /* set driver media status to 'connected' (i.e. set the interface up) */ - if (!DeviceIoControl (device->device_handle, TAP_IOCTL_SET_MEDIA_STATUS, - &status, sizeof (status), - &status, sizeof (status), &len, NULL)) - printf("WARNING: Unable to enable TAP adapter\n"); - - /* - * Initialize overlapped structures - */ - device->overlap_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - device->overlap_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if (!device->overlap_read.hEvent || !device->overlap_write.hEvent) { - return -1; - } - - return(0); -} - -/* ************************************************ */ - -int tuntap_read(struct tuntap_dev *tuntap, unsigned char *buf, int len) -{ - DWORD read_size, last_err; - - ResetEvent(tuntap->overlap_read.hEvent); - if (ReadFile(tuntap->device_handle, buf, len, &read_size, &tuntap->overlap_read)) { - //printf("tun_read(len=%d)\n", read_size); - return read_size; - } - switch (last_err = GetLastError()) { - case ERROR_IO_PENDING: - WaitForSingleObject(tuntap->overlap_read.hEvent, INFINITE); - GetOverlappedResult(tuntap->device_handle, &tuntap->overlap_read, &read_size, FALSE); - return read_size; - break; - default: - printf("GetLastError() returned %d\n", last_err); - break; - } - - return -1; -} -/* ************************************************ */ - -int tuntap_write(struct tuntap_dev *tuntap, unsigned char *buf, int len) -{ - DWORD write_size; - - //printf("tun_write(len=%d)\n", len); - - ResetEvent(tuntap->overlap_write.hEvent); - if (WriteFile(tuntap->device_handle, - buf, - len, - &write_size, - &tuntap->overlap_write)) { - //printf("DONE tun_write(len=%d)\n", write_size); - return write_size; - } - switch (GetLastError()) { - case ERROR_IO_PENDING: - WaitForSingleObject(tuntap->overlap_write.hEvent, INFINITE); - GetOverlappedResult(tuntap->device_handle, &tuntap->overlap_write, - &write_size, FALSE); - return write_size; - break; - default: - break; - } - - return -1; -} - -/* ************************************************ */ - -int tuntap_open(struct tuntap_dev *device, - char *dev, - const char *address_mode, /* static or dhcp */ - char *device_ip, - char *device_mask, - const char * device_mac, - int mtu) { - return(open_wintap(device, address_mode, device_ip, device_mask, device_mac, mtu)); -} - -/* ************************************************ */ - -void tuntap_close(struct tuntap_dev *tuntap) { - CloseHandle(tuntap->device_handle); -} - -/* Fill out the ip_addr value from the interface. Called to pick up dynamic - * address changes. */ -void tuntap_get_address(struct tuntap_dev *tuntap) -{ -} - -/* ************************************************ */ - -#if 0 -int main(int argc, char* argv[]) { - struct tuntap_dev tuntap; - int i; - int mtu = 1400; - - printf("Welcome to n2n\n"); - initWin32(); - open_wintap(&tuntap, "static", "1.2.3.20", "255.255.255.0", mtu); - - for(i=0; i<10; i++) { - u_char buf[MTU]; - int rc; - - rc = tun_read(&tuntap, buf, sizeof(buf)); - buf[0]=2; - buf[1]=3; - buf[2]=4; - - printf("tun_read returned %d\n", rc); - rc = tun_write(&tuntap, buf, rc); - printf("tun_write returned %d\n", rc); - } - // rc = tun_open (device->device_name, IF_MODE_TUN); - WSACleanup (); - return(0); -} - -#endif diff --git a/n2n_v2/wire.c b/n2n_v2/wire.c deleted file mode 100644 index f8306cd..0000000 --- a/n2n_v2/wire.c +++ /dev/null @@ -1,507 +0,0 @@ -/* (c) 2009 Richard Andrews */ - -/** Routines for encoding and decoding n2n packets on the wire. - * - * encode_X(base,idx,v) prototypes are inspired by the erlang internal - * encoding model. Passing the start of a buffer in base and a pointer to an - * integer (initially set to zero). Each encode routine increases idx by the - * amount written and returns the amount written. In this way complex sequences - * of encodings can be represented cleanly. See encode_register() for an - * example. - */ - -#include "n2n_wire.h" -#include - -int encode_uint8( uint8_t * base, - size_t * idx, - const uint8_t v ) -{ - *(base + (*idx)) = (v & 0xff); - ++(*idx); - return 1; -} - -int decode_uint8( uint8_t * out, - const uint8_t * base, - size_t * rem, - size_t * idx ) -{ - if (*rem < 1 ) { return 0; } - - *out = ( base[*idx] & 0xff ); - ++(*idx); - --(*rem); - return 1; -} - -int encode_uint16( uint8_t * base, - size_t * idx, - const uint16_t v ) -{ - *(base + (*idx)) = ( v >> 8) & 0xff; - *(base + (1 + *idx)) = ( v & 0xff ); - *idx += 2; - return 2; -} - -int decode_uint16( uint16_t * out, - const uint8_t * base, - size_t * rem, - size_t * idx ) -{ - if (*rem < 2 ) { return 0; } - - *out = ( base[*idx] & 0xff ) << 8; - *out |= ( base[1 + *idx] & 0xff ); - *idx += 2; - *rem -= 2; - return 2; -} - -int encode_uint32( uint8_t * base, - size_t * idx, - const uint32_t v ) -{ - *(base + (0 + *idx)) = ( v >> 24) & 0xff; - *(base + (1 + *idx)) = ( v >> 16) & 0xff; - *(base + (2 + *idx)) = ( v >> 8) & 0xff; - *(base + (3 + *idx)) = ( v & 0xff ); - *idx += 4; - return 4; -} - -int decode_uint32( uint32_t * out, - const uint8_t * base, - size_t * rem, - size_t * idx ) -{ - if (*rem < 4 ) { return 0; } - - *out = ( base[0 + *idx] & 0xff ) << 24; - *out |= ( base[1 + *idx] & 0xff ) << 16; - *out |= ( base[2 + *idx] & 0xff ) << 8; - *out |= ( base[3 + *idx] & 0xff ); - *idx += 4; - *rem -= 4; - return 4; -} - -int encode_buf( uint8_t * base, - size_t * idx, - const void * p, - size_t s) -{ - memcpy( (base + (*idx)), p, s ); - *idx += s; - return s; -} - -/* Copy from base to out of size bufsize */ -int decode_buf( uint8_t * out, - size_t bufsize, - const uint8_t * base, - size_t * rem, - size_t * idx ) -{ - if (*rem < bufsize ) { return 0; } - - memcpy( out, (base + *idx), bufsize ); - *idx += bufsize; - *rem -= bufsize; - return bufsize; -} - - - -int encode_mac( uint8_t * base, - size_t * idx, - const n2n_mac_t m ) -{ - return encode_buf( base, idx, m, N2N_MAC_SIZE ); -} - -int decode_mac( uint8_t * out, /* of size N2N_MAC_SIZE. This clearer than passing a n2n_mac_t */ - const uint8_t * base, - size_t * rem, - size_t * idx ) -{ - return decode_buf( out, N2N_MAC_SIZE, base, rem, idx ); -} - - - -int encode_common( uint8_t * base, - size_t * idx, - const n2n_common_t * common ) -{ - uint16_t flags=0; - encode_uint8( base, idx, N2N_PKT_VERSION ); - encode_uint8( base, idx, common->ttl ); - - flags = common->pc & N2N_FLAGS_TYPE_MASK; - flags |= common->flags & N2N_FLAGS_BITS_MASK; - - encode_uint16( base, idx, flags ); - encode_buf( base, idx, common->community, N2N_COMMUNITY_SIZE ); - - return -1; -} - -int decode_common( n2n_common_t * out, - const uint8_t * base, - size_t * rem, - size_t * idx ) -{ - size_t idx0=*idx; - uint8_t dummy=0; - decode_uint8( &dummy, base, rem, idx ); - - if ( N2N_PKT_VERSION != dummy ) - { - return -1; - } - - decode_uint8( &(out->ttl), base, rem, idx ); - decode_uint16( &(out->flags), base, rem, idx ); - out->pc = ( out->flags & N2N_FLAGS_TYPE_MASK ); - out->flags &= N2N_FLAGS_BITS_MASK; - - decode_buf( out->community, N2N_COMMUNITY_SIZE, base, rem, idx ); - - return (*idx - idx0); -} - - -int encode_sock( uint8_t * base, - size_t * idx, - const n2n_sock_t * sock ) -{ - int retval=0; - uint16_t f; - - switch (sock->family) - { - case AF_INET: - { - f = 0; - retval += encode_uint16(base,idx,f); - retval += encode_uint16(base,idx,sock->port); - retval += encode_buf(base,idx,sock->addr.v4,IPV4_SIZE); - break; - } - case AF_INET6: - { - f = 0x8000; - retval += encode_uint16(base,idx,f); - retval += encode_uint16(base,idx,sock->port); - retval += encode_buf(base,idx,sock->addr.v6,IPV6_SIZE); - break; - } - default: - retval=-1; - } - - return retval; -} - - -int decode_sock( n2n_sock_t * sock, - const uint8_t * base, - size_t * rem, - size_t * idx ) -{ - size_t * idx0=idx; - uint16_t f; - - decode_uint16( &f, base, rem, idx ); - - if( f & 0x8000 ) - { - /* IPv6 */ - sock->family = AF_INET6; - decode_uint16( &(sock->port), base, rem, idx ); - decode_buf( sock->addr.v6, IPV6_SIZE, base, rem, idx ); - } - else - { - /* IPv4 */ - sock->family = AF_INET; - decode_uint16( &(sock->port), base, rem, idx ); - memset( sock->addr.v6, 0, IPV6_SIZE ); /* so memcmp() works for equality. */ - decode_buf( sock->addr.v4, IPV4_SIZE, base, rem, idx ); - } - - return (idx-idx0); -} - -int encode_REGISTER( uint8_t * base, - size_t * idx, - const n2n_common_t * common, - const n2n_REGISTER_t * reg ) -{ - int retval=0; - retval += encode_common( base, idx, common ); - retval += encode_buf( base, idx, reg->cookie, N2N_COOKIE_SIZE ); - retval += encode_mac( base, idx, reg->srcMac ); - retval += encode_mac( base, idx, reg->dstMac ); - - return retval; -} - -int decode_REGISTER( n2n_REGISTER_t * reg, - const n2n_common_t * cmn, /* info on how to interpret it */ - const uint8_t * base, - size_t * rem, - size_t * idx ) -{ - size_t retval=0; - memset( reg, 0, sizeof(n2n_REGISTER_t) ); - retval += decode_buf( reg->cookie, N2N_COOKIE_SIZE, base, rem, idx ); - retval += decode_mac( reg->srcMac, base, rem, idx ); - retval += decode_mac( reg->dstMac, base, rem, idx ); - - return retval; -} - -int encode_REGISTER_SUPER( uint8_t * base, - size_t * idx, - const n2n_common_t * common, - const n2n_REGISTER_SUPER_t * reg ) -{ - int retval=0; - retval += encode_common( base, idx, common ); - retval += encode_uint16( base, idx, reg->aflags ); - retval += encode_uint16( base, idx, reg->timeout ); - retval += encode_buf( base, idx, reg->cookie, N2N_COOKIE_SIZE ); - retval += encode_mac( base, idx, reg->edgeMac ); - retval += encode_uint16( base, idx, 0 ); /* NULL auth scheme */ - retval += encode_uint16( base, idx, 0 ); /* No auth data */ - if(reg->aflags & N2N_AFLAGS_LOCAL_SOCKET) - retval += encode_sock( base, idx, &(reg->local_sock) ); - - return retval; -} - -int decode_REGISTER_SUPER( n2n_REGISTER_SUPER_t * reg, - const n2n_common_t * cmn, /* info on how to interpret it */ - const uint8_t * base, - size_t * rem, - size_t * idx ) -{ - size_t retval=0; - memset( reg, 0, sizeof(n2n_REGISTER_SUPER_t) ); - retval += decode_uint16( &(reg->aflags), base, rem, idx ); - retval += decode_uint16( &(reg->timeout), base, rem, idx ); - retval += decode_buf( reg->cookie, N2N_COOKIE_SIZE, base, rem, idx ); - retval += decode_mac( reg->edgeMac, base, rem, idx ); - retval += decode_uint16( &(reg->auth.scheme), base, rem, idx ); - retval += decode_uint16( &(reg->auth.toksize), base, rem, idx ); - retval += decode_buf( reg->auth.token, reg->auth.toksize, base, rem, idx ); - if(reg->aflags & N2N_AFLAGS_LOCAL_SOCKET) - retval += decode_sock( &(reg->local_sock), base, rem, idx ); - - return retval; -} - -int encode_PEER_INFO( uint8_t * base, - size_t * idx, - const n2n_common_t * common, - const n2n_PEER_INFO_t * pi ) -{ - int retval=0; - retval += encode_common( base, idx, common ); - retval += encode_uint16( base, idx, pi->aflags ); - retval += encode_uint16( base, idx, pi->timeout ); - retval += encode_mac( base, idx, pi->mac ); - retval += encode_sock( base, idx, pi->sockets ); - if(pi->aflags & N2N_AFLAGS_LOCAL_SOCKET) - retval += encode_sock( base, idx, pi->sockets+1 ); - - return retval; -} - -int decode_PEER_INFO( n2n_PEER_INFO_t * pi, - const n2n_common_t * cmn, /* info on how to interpret it */ - const uint8_t * base, - size_t * rem, - size_t * idx ) -{ - size_t retval=0; - memset( pi, 0, sizeof(n2n_PEER_INFO_t) ); - retval += decode_uint16( &(pi->aflags), base, rem, idx ); - retval += decode_uint16( &(pi->timeout), base, rem, idx ); - retval += decode_mac( pi->mac, base, rem, idx ); - retval += decode_sock( pi->sockets, base, rem, idx ); - if(pi->aflags & N2N_AFLAGS_LOCAL_SOCKET) - retval += decode_sock( pi->sockets+1, base, rem, idx ); - - return retval; -} - -int encode_QUERY_PEER( uint8_t * base, - size_t * idx, - const n2n_common_t * common, - const n2n_QUERY_PEER_t * qp ) -{ - int retval=0; - retval += encode_common( base, idx, common ); - retval += encode_mac( base, idx, qp->srcMac ); - retval += encode_mac( base, idx, qp->targetMac ); - - return retval; -} - -int decode_QUERY_PEER( n2n_QUERY_PEER_t * qp, - const n2n_common_t * cmn, /* info on how to interpret it */ - const uint8_t * base, - size_t * rem, - size_t * idx ) -{ - size_t retval=0; - memset( qp, 0, sizeof(n2n_QUERY_PEER_t) ); - retval += decode_mac( qp->srcMac, base, rem, idx ); - retval += decode_mac( qp->targetMac, base, rem, idx ); - - return retval; -} - -int encode_REGISTER_ACK( uint8_t * base, - size_t * idx, - const n2n_common_t * common, - const n2n_REGISTER_ACK_t * reg ) -{ - int retval=0; - retval += encode_common( base, idx, common ); - retval += encode_buf( base, idx, reg->cookie, N2N_COOKIE_SIZE ); - retval += encode_mac( base, idx, reg->dstMac ); - retval += encode_mac( base, idx, reg->srcMac ); - - return retval; -} - -int decode_REGISTER_ACK( n2n_REGISTER_ACK_t * reg, - const n2n_common_t * cmn, /* info on how to interpret it */ - const uint8_t * base, - size_t * rem, - size_t * idx ) -{ - size_t retval=0; - memset( reg, 0, sizeof(n2n_REGISTER_ACK_t) ); - retval += decode_buf( reg->cookie, N2N_COOKIE_SIZE, base, rem, idx ); - retval += decode_mac( reg->dstMac, base, rem, idx ); - retval += decode_mac( reg->srcMac, base, rem, idx ); - - return retval; -} - -int encode_REGISTER_SUPER_ACK( uint8_t * base, - size_t * idx, - const n2n_common_t * common, - const n2n_REGISTER_SUPER_ACK_t * reg ) -{ - int retval=0; - retval += encode_common( base, idx, common ); - retval += encode_buf( base, idx, reg->cookie, N2N_COOKIE_SIZE ); - retval += encode_mac( base, idx, reg->edgeMac ); - retval += encode_uint16( base, idx, reg->lifetime ); - retval += encode_sock( base, idx, &(reg->sock) ); - retval += encode_uint8( base, idx, reg->num_sn ); - if ( reg->num_sn > 0 ) - { - /* We only support 0 or 1 at this stage */ - retval += encode_sock( base, idx, &(reg->sn_bak) ); - } - - return retval; -} - -int decode_REGISTER_SUPER_ACK( n2n_REGISTER_SUPER_ACK_t * reg, - const n2n_common_t * cmn, /* info on how to interpret it */ - const uint8_t * base, - size_t * rem, - size_t * idx ) -{ - size_t retval=0; - - memset( reg, 0, sizeof(n2n_REGISTER_SUPER_ACK_t) ); - retval += decode_buf( reg->cookie, N2N_COOKIE_SIZE, base, rem, idx ); - retval += decode_mac( reg->edgeMac, base, rem, idx ); - retval += decode_uint16( &(reg->lifetime), base, rem, idx ); - - /* Socket is mandatory in this message type */ - retval += decode_sock( &(reg->sock), base, rem, idx ); - - /* Following the edge socket are an array of backup supernodes. */ - retval += decode_uint8( &(reg->num_sn), base, rem, idx ); - if ( reg->num_sn > 0 ) - { - /* We only support 0 or 1 at this stage */ - retval += decode_sock( &(reg->sn_bak), base, rem, idx ); - } - - return retval; -} - -int fill_sockaddr( struct sockaddr * addr, - size_t addrlen, - const n2n_sock_t * sock ) -{ - int retval=-1; - - if ( AF_INET == sock->family ) - { - if ( addrlen >= sizeof(struct sockaddr_in) ) - { - struct sockaddr_in * si = (struct sockaddr_in *)addr; - si->sin_family = sock->family; - si->sin_port = htons( sock->port ); - memcpy( &(si->sin_addr.s_addr), sock->addr.v4, IPV4_SIZE ); - retval=0; - } - } - - return retval; -} - - -int encode_PACKET( uint8_t * base, - size_t * idx, - const n2n_common_t * common, - const n2n_PACKET_t * pkt ) -{ - int retval=0; - retval += encode_common( base, idx, common ); - retval += encode_uint16( base, idx, pkt->transform ); - - return retval; -} - - -int decode_PACKET( n2n_PACKET_t * pkt, - const n2n_common_t * cmn, /* info on how to interpret it */ - const uint8_t * base, - size_t * rem, - size_t * idx ) -{ - size_t retval=0; - memset( pkt, 0, sizeof(n2n_PACKET_t) ); - retval += decode_uint16( &(pkt->transform), base, rem, idx ); - - return retval; -} - -void decode_ETHFRAMEHDR( n2n_ETHFRAMEHDR_t * eth, - const uint8_t * base ) -{ - memcpy( eth->dstMac, base, N2N_MAC_SIZE ); - base += N2N_MAC_SIZE; - memcpy( eth->srcMac, base, N2N_MAC_SIZE ); -} - -int copy_ETHFRAMEHDR(uint8_t * base, - uint8_t * pkt) -{ - memcpy( base, pkt, ETH_FRAMEHDRSIZE); - return ETH_FRAMEHDRSIZE; -} diff --git a/n2n_wire.h b/n2n_wire.h new file mode 100644 index 0000000..3b79966 --- /dev/null +++ b/n2n_wire.h @@ -0,0 +1,268 @@ +/* (c) 2009 Richard Andrews + * + * Contributions by: + * Luca Deri + * Lukasz Taczuk + */ + +#if !defined( N2N_WIRE_H_ ) +#define N2N_WIRE_H_ + +#include + +#if defined(WIN32) +#include "win32/n2n_win32.h" + +#if defined(__MINGW32__) +#include +#endif /* #ifdef __MINGW32__ */ + +#else /* #if defined(WIN32) */ +#include +#include +#include /* AF_INET and AF_INET6 */ +#endif /* #if defined(WIN32) */ + +#define N2N_PROTOCOL_VERSION_MAJOR 3 +#define N2N_PROTOCOL_VERSION_MINOR 0 +#define N2N_MAJOR_VERSION 3 +#define N2N_MINOR_VERSION 0 +#define N2N_COMMUNITY_SIZE 8 +/* Warning: Builds with a different N2N_COMMUNITY_SIZE are incompatible! */ +#define N2N_MAC_SIZE 6 +#define N2N_COOKIE_SIZE 4 +#define N2N_PKT_BUF_SIZE 2048 +#define N2N_SOCKBUF_SIZE 64 /* string representation of INET or INET6 sockets */ + +#define IPV4_SIZE 4 +#define IPV6_SIZE 16 + +typedef uint8_t n2n_community_t[N2N_COMMUNITY_SIZE]; +typedef uint8_t n2n_mac_t[N2N_MAC_SIZE]; +typedef uint8_t n2n_ip_t[IPV4_SIZE]; /* currently only IPv4 + address supported */ +typedef uint8_t n2n_cookie_t[N2N_COOKIE_SIZE]; +typedef uint32_t n2n_spi_t; + +typedef char n2n_sock_str_t[N2N_SOCKBUF_SIZE]; /* tracing string buffer */ + +enum n2n_pc { + n2n_ping = 0, /* Not used */ + n2n_pre_handshake, + n2n_handshake, + n2n_holepunch, + n2n_supernode_register, + n2n_address_resolution, + n2n_keep_alive, + n2n_edge_connect, + n2n_edge_resume +}; + +typedef enum n2n_pc n2n_pc_t; + +enum n2n_flags { + n2n_ack = 0x1 +}; + +typedef enum n2n_flags n2n_flags_t; + +#define ETH_FRAMEHDRSIZE 14 +#define IP4_SRCOFFSET 12 + +#define N2N_AUTH_TOKEN_SIZE 32 /* bytes */ + +#define N2N_EUNKNOWN -1 +#define N2N_ENOTIMPL -2 +#define N2N_EINVAL -3 +#define N2N_ENOSPACE -4 + +typedef uint16_t n2n_transform_t; /* Encryption, compression type. */ +typedef uint32_t n2n_sa_t; /* security association number */ +typedef uint8_t n2n_version_major_t; +typedef uint8_t n2n_version_minor_t; + +struct n2n_sock { + uint8_t family; /* AF_INET or AF_INET6; or 0 if invalid */ + uint16_t port; /* host order */ + union { + uint8_t v6[IPV6_SIZE]; /* byte sequence */ + uint8_t v4[IPV4_SIZE]; /* byte sequence */ + } addr; +}; + +typedef struct n2n_sock n2n_sock_t; + + +struct n2n_auth { + uint16_t scheme; /* What kind of auth */ + uint16_t toksize; /* Size of auth token */ + uint8_t token[N2N_AUTH_TOKEN_SIZE]; /* Auth data interpreted based on scheme */ +}; + +typedef struct n2n_auth n2n_auth_t; + +struct n2n_preauth { + n2n_community_t community; + n2n_spi_t spi_dest; + n2n_spi_t spi_src; +}; + +union n2n_supernode_register { + struct { + n2n_mac_t a_mac; + n2n_ip_t a_n2n_ip; + } syn; + struct { + n2n_sock_t a_pub_sock; + } ack; +}; + +typedef union n2n_supernode_register n2n_supernode_register_t; + +struct n2n_REGISTER_ACK { + n2n_cookie_t cookie; /* Return cookie from REGISTER */ + n2n_mac_t srcMac; /* MAC of acknowledging party (supernode or edge) */ + n2n_mac_t dstMac; /* Reflected MAC of registering edge from REGISTER */ + n2n_sock_t sock; /* Supernode's view of edge socket (IP Addr, port) */ +}; + +typedef struct n2n_REGISTER_ACK n2n_REGISTER_ACK_t; + +struct n2n_PACKET { + n2n_transform_t transform; +}; + +typedef struct n2n_PACKET n2n_PACKET_t; + +struct n2n_ETHFRAMEHDR { + n2n_mac_t srcMac; + n2n_mac_t dstMac; +/* uint16_t ethertype; *//* is there a reason to use this? */ +}; + +typedef struct n2n_ETHFRAMEHDR n2n_ETHFRAMEHDR_t; + +/* Linked with n2n_register_super in n2n_pc_t. Only from edge to supernode. */ +struct n2n_REGISTER_SUPER { + uint16_t aflags; /* additional flags */ + n2n_cookie_t cookie; /* Link REGISTER_SUPER and REGISTER_SUPER_ACK */ + uint16_t timeout; + n2n_mac_t edgeMac; /* MAC to register with edge sending socket */ + n2n_auth_t auth; /* Authentication scheme and tokens */ + n2n_sock_t local_sock; +}; + +typedef struct n2n_REGISTER_SUPER n2n_REGISTER_SUPER_t; + +/* Linked with n2n_register_super_ack in n2n_pc_t. Only from supernode to edge. */ +struct n2n_REGISTER_SUPER_ACK { + n2n_cookie_t cookie; /* Return cookie from REGISTER_SUPER */ + n2n_mac_t edgeMac; /* MAC registered to edge sending socket */ + uint16_t lifetime; /* How long the registration will live */ + n2n_sock_t sock; /* Sending sockets associated with edgeMac */ + + /* The packet format provides additional supernode definitions here. + * uint8_t count, then for each count there is one + * n2n_sock_t. + */ + uint8_t num_sn; /* Number of supernodes that were send + * even if we cannot store them all. If + * non-zero then sn_bak is valid. */ + n2n_sock_t sn_bak; /* Socket of the first backup supernode */ + +}; + +typedef struct n2n_REGISTER_SUPER_ACK n2n_REGISTER_SUPER_ACK_t; + +/* Linked with n2n_register_super_ack in n2n_pc_t. Only from supernode to edge. */ +struct n2n_REGISTER_SUPER_NAK { + n2n_cookie_t cookie; /* Return cookie from REGISTER_SUPER */ +}; + +typedef struct n2n_REGISTER_SUPER_NAK n2n_REGISTER_SUPER_NAK_t; + +struct n2n_PEER_INFO { + uint16_t aflags; + uint16_t timeout; + n2n_mac_t mac; + n2n_sock_t sockets[2]; +}; + +typedef struct n2n_PEER_INFO n2n_PEER_INFO_t; + +struct n2n_QUERY_PEER { + n2n_mac_t srcMac; + n2n_mac_t targetMac; +}; + +typedef struct n2n_QUERY_PEER n2n_QUERY_PEER_t; + +struct n2n_HEADER { + n2n_pc_t pc; + n2n_flags_t flags; +}; + +typedef struct n2n_HEADER n2n_HEADER_t; + +struct n2n_buf { + uint8_t * data; + size_t size; +}; + +typedef struct n2n_buf n2n_buf_t; + +int encode_uint8(uint8_t * base, size_t * idx, const uint8_t v); + +int decode_uint8(const uint8_t * base, size_t * idx, size_t * rem, + uint8_t * out); + +int encode_uint16(uint8_t * base, size_t * idx, const uint16_t v); + +int decode_uint16(const uint8_t * base, size_t * idx, size_t * rem, + uint16_t * out); + +int encode_uint32(uint8_t * base, size_t * idx, const uint32_t v); + +int decode_uint32(const uint8_t * base, size_t * idx, size_t * rem, + uint32_t * out); + +int encode_buf(uint8_t * base, size_t * idx, const void * p, size_t s); + +int decode_buf(const uint8_t * base, size_t * idx, size_t * rem, + uint8_t * out, size_t bufsize); + +int encode_ip(uint8_t * base, size_t * idx, const n2n_ip_t ip); + +int decode_ip(const uint8_t * base, size_t * idx, size_t * rem, + n2n_ip_t ip); + +int encode_mac(uint8_t * base, size_t * idx, const n2n_mac_t m); + +int decode_mac(const uint8_t * base, size_t * idx, size_t * rem, + uint8_t * out /* of size N2N_MAC_SIZE. + This clearer than passing a n2n_mac_t */ ); + +int encode_sock(uint8_t * base, size_t * idx, const n2n_sock_t * sock); + +int decode_sock(const uint8_t * base, size_t * idx, size_t * rem, + n2n_sock_t * sock); + +int encode_supernode_register(uint8_t * base, size_t * idx, + int ack, const n2n_supernode_register_t * reg); + +int decode_supernode_register(const uint8_t * base, size_t * idx, size_t * rem, + int ack, n2n_supernode_register_t * reg); + +int fill_sockaddr(struct sockaddr * addr, size_t addrlen, + const n2n_sock_t * sock); + +int encode_HEADER(uint8_t * base, size_t * idx, const n2n_HEADER_t *hdr); +int decode_HEADER(const uint8_t * base, size_t * idx, size_t * rem, + n2n_HEADER_t *hdr); + +void decode_ETHFRAMEHDR(const uint8_t * base, n2n_ETHFRAMEHDR_t * eth); + +int copy_ETHFRAMEHDR(uint8_t * base, uint8_t * pkt); + +#endif /* #if !defined( N2N_WIRE_H_ ) */ + diff --git a/n2n_v1/scripts/mk_SRPM.sh b/scripts/mk_SRPM.sh similarity index 100% rename from n2n_v1/scripts/mk_SRPM.sh rename to scripts/mk_SRPM.sh diff --git a/n2n_v1/scripts/mk_deb.sh b/scripts/mk_deb.sh similarity index 100% rename from n2n_v1/scripts/mk_deb.sh rename to scripts/mk_deb.sh diff --git a/n2n_v2/scripts/mk_tar.sh b/scripts/mk_tar.sh similarity index 100% rename from n2n_v2/scripts/mk_tar.sh rename to scripts/mk_tar.sh diff --git a/n2n_v2/sglib.h b/sglib.h similarity index 99% rename from n2n_v2/sglib.h rename to sglib.h index 7630438..8854a09 100644 --- a/n2n_v2/sglib.h +++ b/sglib.h @@ -1,5 +1,4 @@ /* - This is SGLIB version 1.0.3 (C) by Marian Vittek, Bratislava, http://www.xref-tech.com/sglib, 2003-5 @@ -10,9 +9,6 @@ Software license or under terms of GNU Public License. If you need to use a derivative form in a commercial project, or you need sglib under any other license conditions, contact the author. - - - */ diff --git a/sn.c b/sn.c new file mode 100644 index 0000000..32f58fe --- /dev/null +++ b/sn.c @@ -0,0 +1,763 @@ +/* Supernode for n2n-2.x */ + +/* (c) 2009 Richard Andrews + * + * Contributions by: + * Lukasz Taczuk + * Struan Bartlett + */ + +#include "n2n.h" + +#define N2N_SN_LPORT_DEFAULT 7654 +#define N2N_SN_PKTBUF_SIZE 2048 + +#define N2N_SN_MGMT_PORT 5645 + +struct sn_stats { + size_t errors; /* Number of errors encountered. */ + size_t reg_super; /* Number of REGISTER_SUPER requests received. */ + size_t reg_super_nak; /* Number of REGISTER_SUPER requests declined. */ + size_t fwd; /* Number of messages forwarded. */ + size_t broadcast; /* Number of messages broadcast to a community. */ + time_t last_fwd; /* Time when last message was forwarded. */ + time_t last_reg_super; /* Time when last REGISTER_SUPER was received. */ +}; + +typedef struct sn_stats sn_stats_t; + +struct n2n_sn { + time_t start_time; /* Used to measure uptime. */ + sn_stats_t stats; + int daemon; /* If non-zero then daemonise. */ + uint16_t lport; /* Local UDP port to bind to. */ + int sock; /* Main socket for UDP traffic with edges. */ + int mgmt_sock; /* management socket. */ + time_t last_purge; /* last purge time */ + peer_info_t * edges[PEER_HASH_TAB_SIZE]; /* Link list of registered edges. */ +}; + +typedef struct n2n_sn n2n_sn_t; + +static int try_forward(n2n_sn_t * sss, const n2n_common_t * cmn, + const n2n_mac_t dstMac, const uint8_t * pktbuf, size_t pktsize); + +static int try_broadcast(n2n_sn_t * sss, const n2n_common_t * cmn, + const n2n_mac_t srcMac, const uint8_t * pktbuf, size_t pktsize); + +/** Initialise the supernode structure */ +static int init_sn(n2n_sn_t * sss) +{ +#ifdef WIN32 + initWin32(); +#endif + memset(sss, 0, sizeof(n2n_sn_t)); + + sss->daemon = 1; /* By defult run as a daemon. */ + sss->lport = N2N_SN_LPORT_DEFAULT; + sss->sock = -1; + sss->mgmt_sock = -1; + sss->last_purge = 0; + sglib_hashed_peer_info_t_init(sss->edges); + + return 0; /* OK */ +} + +/** Deinitialise the supernode structure and deallocate any memory owned by + * it. */ +static void deinit_sn(n2n_sn_t * sss) +{ + if (sss->sock >= 0) { + closesocket(sss->sock); + } + sss->sock = -1; + + if (sss->mgmt_sock >= 0) { + closesocket(sss->mgmt_sock); + } + sss->mgmt_sock = -1; + + purge_hashed_peer_list_t(sss->edges, 0xffffffff); +} + +/** Determine the appropriate lifetime for new registrations. + * + * If the supernode has been put into a pre-shutdown phase then this lifetime + * should not allow registrations to continue beyond the shutdown point. + */ +static uint16_t reg_lifetime(n2n_sn_t * sss) +{ + return 30; +} + +/** Update the edge table with the details of the edge which contacted the + * supernode. */ +static int update_edge(n2n_sn_t * sss, const n2n_REGISTER_SUPER_t * reg, + const n2n_community_t community, const n2n_sock_t * sender_sock, + time_t now) +{ + macstr_t mac_buf; + n2n_sock_str_t sockbuf; + struct peer_info * scan; + + traceEvent(TRACE_DEBUG, "update_edge for %s [%s]", + macaddr_str(mac_buf, reg->edgeMac), sock_to_cstr(sockbuf, sender_sock)); + + scan = find_peer_by_mac(sss->edges, reg->edgeMac); + + if (NULL == scan) { + /* Not known */ + + scan = (struct peer_info*)calloc(1, sizeof(struct peer_info)); /* deallocated in purge_expired_registrations */ + + memcpy(scan->community_name, community, sizeof(n2n_community_t)); + memcpy(&(scan->mac_addr), reg->edgeMac, sizeof(n2n_mac_t)); + memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t)); + + scan->timeout = reg->timeout; + if (reg->aflags & N2N_AFLAGS_LOCAL_SOCKET) { + scan->num_sockets = 2; + scan->sockets = malloc(scan->num_sockets * sizeof(n2n_sock_t)); + scan->sockets[1] = reg->local_sock; + } else { + scan->num_sockets = 1; + scan->sockets = malloc(scan->num_sockets * sizeof(n2n_sock_t)); + } + scan->sockets[0] = scan->sock; + + /* insert this guy at the head of the edges list */ + sglib_hashed_peer_info_t_add(sss->edges, scan); + + traceEvent(TRACE_INFO, "update_edge created %s ==> %s", + macaddr_str(mac_buf, reg->edgeMac), sock_to_cstr(sockbuf, sender_sock)); + } else { + /* Known */ + int num_changes = 0; + scan->timeout = reg->timeout; + if (memcmp(community, scan->community_name, sizeof(n2n_community_t)) != 0) { + memcpy(scan->community_name, community, sizeof(n2n_community_t) ); + num_changes++; + } + if (sock_equal(sender_sock, &(scan->sock)) != 0) { + memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t)); + memcpy(scan->sockets, sender_sock, sizeof(n2n_sock_t)); + num_changes++; + } + if (scan->num_sockets == 1) { + if (reg->aflags & N2N_AFLAGS_LOCAL_SOCKET) { + scan->num_sockets = 2; + free(scan->sockets); + scan->sockets = malloc(scan->num_sockets*sizeof(n2n_sock_t)); + scan->sockets[0] = scan->sock; + scan->sockets[1] = reg->local_sock; + } + } else { + if (reg->aflags & N2N_AFLAGS_LOCAL_SOCKET) { + if (sock_equal(&(reg->local_sock), scan->sockets+1) != 0) { + memcpy(scan->sockets+1, &(reg->local_sock), sizeof(n2n_sock_t)); + } + } else { + scan->num_sockets = 1; + free(scan->sockets); + scan->sockets = malloc(scan->num_sockets*sizeof(n2n_sock_t)); + scan->sockets[0] = scan->sock; + } + } + if (num_changes) { + traceEvent(TRACE_INFO, "update_edge updated %s ==> %s", + macaddr_str(mac_buf, reg->edgeMac), + sock_to_cstr(sockbuf, sender_sock)); + } else { + traceEvent(TRACE_DEBUG, "update_edge unchanged %s ==> %s", + macaddr_str(mac_buf, reg->edgeMac), + sock_to_cstr(sockbuf, sender_sock)); + } + + } + + scan->last_seen = now; + + return 0; +} + +/** Send a datagram to the destination embodied in a n2n_sock_t. + * + * @return -1 on error otherwise number of bytes sent + */ +static ssize_t sendto_sock(n2n_sn_t * sss, const n2n_sock_t * sock, + const uint8_t * pktbuf, size_t pktsize) +{ + n2n_sock_str_t sockbuf; + + if (AF_INET == sock->family) { + struct sockaddr_in udpsock; + + udpsock.sin_family = AF_INET; + udpsock.sin_port = htons(sock->port); + memcpy(&(udpsock.sin_addr.s_addr), &(sock->addr.v4), IPV4_SIZE); + + traceEvent(TRACE_DEBUG, "sendto_sock %lu to [%s]", pktsize, sock_to_cstr(sockbuf,sock)); + + return sendto(sss->sock, pktbuf, pktsize, 0, + (const struct sockaddr *)&udpsock, sizeof(struct sockaddr_in)); + } else { + /* AF_INET6 not implemented */ + errno = EAFNOSUPPORT; + return -1; + } +} + +/** Try to forward a message to a unicast MAC. If the MAC is unknown then + * broadcast to all edges in the destination community. + */ +static int try_forward(n2n_sn_t * sss, const n2n_common_t * cmn, + const n2n_mac_t dstMac, const uint8_t * pktbuf, size_t pktsize) +{ + struct peer_info * scan; + macstr_t mac_buf; + n2n_sock_str_t sockbuf; + + scan = find_peer_by_mac(sss->edges, dstMac); + + if (NULL != scan) { + int data_sent_len; + data_sent_len = sendto_sock(sss, &(scan->sock), pktbuf, pktsize); + + if (data_sent_len == pktsize) { + ++(sss->stats.fwd); + traceEvent(TRACE_DEBUG, "unicast %lu to [%s] %s", pktsize, + sock_to_cstr(sockbuf, &(scan->sock)), + macaddr_str(mac_buf, scan->mac_addr)); + } else { + ++(sss->stats.errors); + traceEvent(TRACE_ERROR, "unicast %lu to [%s] %s FAILED (%d: %s)", + pktsize, + sock_to_cstr(sockbuf, &(scan->sock)), + macaddr_str(mac_buf, scan->mac_addr), + errno, strerror(errno) ); + } + } else { + traceEvent(TRACE_DEBUG, "try_forward unknown MAC"); + + /* Not a known MAC so drop. */ + } + + return 0; +} + +/** Try and broadcast a message to all edges in the community. + * + * This will send the exact same datagram to zero or more edges registered to + * the supernode. + */ +static int try_broadcast(n2n_sn_t * sss, const n2n_common_t * cmn, + const n2n_mac_t srcMac, const uint8_t * pktbuf, size_t pktsize) +{ + peer_info_t * ll; + struct sglib_hashed_peer_info_t_iterator it; + macstr_t mac_buf; + n2n_sock_str_t sockbuf; + + traceEvent(TRACE_DEBUG, "try_broadcast"); + + for (ll = sglib_hashed_peer_info_t_it_init(&it, sss->edges); ll != NULL; + ll = sglib_hashed_peer_info_t_it_next(&it)) { + if ((memcmp(ll->community_name, cmn->community, sizeof(n2n_community_t)) == 0) + && (0 != memcmp(srcMac, ll->mac_addr, sizeof(n2n_mac_t)))) + /* REVISIT: exclude if the destination socket is where the packet came from. */ + { + int data_sent_len; + + data_sent_len = sendto_sock(sss, &(ll->sock), pktbuf, pktsize); + + if (data_sent_len != pktsize) { + ++(sss->stats.errors); + traceEvent(TRACE_WARNING, "multicast %lu to [%s] %s failed %s", + pktsize, sock_to_cstr(sockbuf, &(ll->sock)), + macaddr_str(mac_buf, ll->mac_addr), + strerror(errno)); + } else { + ++(sss->stats.broadcast); + traceEvent(TRACE_DEBUG, "multicast %lu to [%s] %s", pktsize, + sock_to_cstr(sockbuf, &(ll->sock)), + macaddr_str(mac_buf, ll->mac_addr)); + } + } + } /* for */ + + return 0; +} + +static int process_mgmt(n2n_sn_t * sss, const struct sockaddr_in * sender_sock, + const uint8_t * mgmt_buf, size_t mgmt_size, time_t now) +{ + char resbuf[N2N_SN_PKTBUF_SIZE]; + size_t ressize = 0; + ssize_t r; + + traceEvent(TRACE_DEBUG, "process_mgmt"); + + ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, + "----------------\n"); + + ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, + "uptime %lu\n", (now - sss->start_time)); + + ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, + "edges %u\n", + (unsigned int) hashed_peer_list_t_size(sss->edges)); + + ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, + "errors %u\n", (unsigned int) sss->stats.errors); + + ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, + "reg_sup %u\n", (unsigned int) sss->stats.reg_super); + + ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, + "reg_nak %u\n", (unsigned int) sss->stats.reg_super_nak); + + ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, + "fwd %u\n", (unsigned int) sss->stats.fwd); + + ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, + "broadcast %u\n", (unsigned int) sss->stats.broadcast); + + ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, + "last fwd %lu sec ago\n", + (long unsigned int) (now - sss->stats.last_fwd)); + + ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, + "last reg %lu sec ago\n", + (long unsigned int) (now - sss->stats.last_reg_super)); + + r = sendto(sss->mgmt_sock, resbuf, ressize, 0/*flags*/, + (struct sockaddr *) sender_sock, sizeof(struct sockaddr_in)); + + if (r <= 0) { + ++(sss->stats.errors); + traceEvent(TRACE_ERROR, "process_mgmt : sendto failed. %s", strerror(errno) ); + } + + return 0; +} + +/** Examine a datagram and determine what to do with it. + * + */ +static int process_udp(n2n_sn_t * sss, const struct sockaddr_in * sender_sock, + const uint8_t * udp_buf, size_t udp_size, time_t now) +{ + n2n_common_t cmn; /* common fields in the packet header */ + n2n_common_t cmn2; /* common fields of newly generated packets */ + size_t rem; + size_t idx; + size_t msg_type; + uint8_t from_supernode; + macstr_t mac_buf; + macstr_t mac_buf2; + n2n_sock_str_t sockbuf; + const uint8_t * rec_buf; /* either udp_buf or encbuf */ + int unicast; /* non-zero if unicast */ + size_t encx = 0; + uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; + n2n_ETHFRAMEHDR_t eth; + int i; + + /* for PACKET packages */ + n2n_PACKET_t pkt; + + /* for QUERY_PEER packages */ + n2n_QUERY_PEER_t query; + struct peer_info * scan; + n2n_PEER_INFO_t pi; + + /* for REGISTER packages */ + n2n_REGISTER_t reg; + + /* for REGISTER_SUPER packages */ + n2n_REGISTER_SUPER_t regs; + n2n_REGISTER_SUPER_ACK_t ack; + + traceEvent(TRACE_DEBUG, "process_udp(%lu)", udp_size); + + /* Use decode_common() to determine the kind of packet then process it: + * + * REGISTER_SUPER adds an edge and generate a return REGISTER_SUPER_ACK + * + * REGISTER, REGISTER_ACK and PACKET messages are forwarded to their + * destination edge. If the destination is not known then PACKETs are + * broadcast. + */ + + rem = udp_size; /* 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"); + return -1; /* failed to decode packet */ + } + + msg_type = cmn.pc; /* packet code */ + from_supernode = cmn.flags & N2N_FLAGS_FROM_SUPERNODE; + + if (cmn.ttl < 1) { + traceEvent(TRACE_WARNING, "Expired TTL"); + return 0; /* Don't process further */ + } + + --(cmn.ttl); /* The value copied into all forwarded packets. */ + + switch (msg_type) { + case MSG_TYPE_PACKET: + /* PACKET from one edge to another edge via supernode. */ + + /* pkt will be modified in place and recoded to an output of potentially + * different size due to addition of the socket.*/ + + sss->stats.last_fwd = now; + decode_PACKET(&pkt, &cmn, udp_buf, &rem, &idx); + decode_ETHFRAMEHDR(ð, udp_buf + idx); + + unicast = (0 == is_multi_broadcast(eth.dstMac)); + + traceEvent(TRACE_DEBUG, "Rx PACKET (%s) %s -> %s %s", + (unicast?"unicast":"multicast"), + macaddr_str(mac_buf, eth.srcMac), + macaddr_str(mac_buf2, eth.dstMac), + (from_supernode?"from sn":"local")); + + if (!from_supernode) { + memcpy(&cmn2, &cmn, sizeof(n2n_common_t)); + + /* We are going to add socket even if it was not there before */ + cmn2.flags |= N2N_FLAGS_FROM_SUPERNODE; + + rec_buf = encbuf; + + /* Re-encode the header. */ + encode_PACKET(encbuf, &encx, &cmn2, &pkt); + + /* Copy the original payload unchanged */ + encode_buf(encbuf, &encx, (udp_buf + idx), (udp_size - idx)); + } else { + /* Already from a supernode. Nothing to modify, just pass to + * destination. */ + + traceEvent(TRACE_DEBUG, "Rx PACKET fwd unmodified"); + + rec_buf = udp_buf; + encx = udp_size; + } + + /* Common section to forward the final product. */ + if (unicast) { + try_forward(sss, &cmn, eth.dstMac, rec_buf, encx); + } else { + try_broadcast(sss, &cmn, eth.srcMac, rec_buf, encx); + } + break; + case MSG_TYPE_QUERY_PEER: + decode_QUERY_PEER(&query, &cmn, udp_buf, &rem, &idx); + + traceEvent(TRACE_DEBUG, "Rx QUERY_PEER from %s for %s", + macaddr_str(mac_buf, query.srcMac), + macaddr_str(mac_buf2, query.targetMac)); + + scan = find_peer_by_mac(sss->edges, query.targetMac); + if (scan && memcmp(cmn.community, scan->community_name, sizeof(n2n_community_t)) == 0) { + cmn2.ttl = N2N_DEFAULT_TTL; + cmn2.pc = n2n_peer_info; + cmn2.flags = N2N_FLAGS_FROM_SUPERNODE; + memcpy(cmn2.community, cmn.community, sizeof(n2n_community_t)); + + pi.aflags = 0; + pi.timeout = scan->timeout; + memcpy(pi.mac, query.targetMac, sizeof(n2n_mac_t)); + for(i = 0; i < scan->num_sockets; i++) + pi.sockets[i] = scan->sockets[i]; + if(scan->num_sockets > 1) + pi.aflags |= N2N_AFLAGS_LOCAL_SOCKET; + + encode_PEER_INFO(encbuf, &encx, &cmn2, &pi); + + sendto(sss->sock, encbuf, encx, 0, + (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); + + traceEvent(TRACE_DEBUG, "Tx PEER_INFO to %s", + macaddr_str(mac_buf, query.srcMac)); + } else { + traceEvent(TRACE_DEBUG, "Ignoring QUERY_PEER for unknown edge %s", + macaddr_str(mac_buf, query.targetMac)); + } + + break; + case MSG_TYPE_REGISTER: + /* Forwarding a REGISTER from one edge to the next */ + sss->stats.last_fwd=now; + decode_REGISTER(®, &cmn, udp_buf, &rem, &idx); + + unicast = (is_multi_broadcast(reg.dstMac) == 0); + + if (unicast) { + traceEvent(TRACE_DEBUG, "Rx REGISTER %s -> %s %s", + macaddr_str(mac_buf, reg.srcMac), + macaddr_str(mac_buf2, reg.dstMac), + ((cmn.flags & N2N_FLAGS_FROM_SUPERNODE)?"from sn":"local")); + + if ((cmn.flags & N2N_FLAGS_FROM_SUPERNODE) != 0) { + memcpy(&cmn2, &cmn, sizeof(n2n_common_t)); + + /* We are going to add socket even if it was not there before */ + cmn2.flags |= N2N_FLAGS_FROM_SUPERNODE; + + reg.sock.family = AF_INET; + reg.sock.port = ntohs(sender_sock->sin_port); + memcpy(reg.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); + + rec_buf = encbuf; + + /* Re-encode the header. */ + encode_REGISTER(encbuf, &encx, &cmn2, ®); + + /* Copy the original payload unchanged */ + encode_buf(encbuf, &encx, (udp_buf + idx), (udp_size - idx)); + } else { + /* Already from a supernode. Nothing to modify, just pass to + * destination. */ + + rec_buf = udp_buf; + encx = udp_size; + } + + try_forward(sss, &cmn, reg.dstMac, rec_buf, encx); /* unicast only */ + } else { + traceEvent(TRACE_ERROR, "Rx REGISTER with multicast destination"); + } + break; + case MSG_TYPE_REGISTER_ACK: + traceEvent(TRACE_DEBUG, "Rx REGISTER_ACK (NOT IMPLEMENTED) Should not be via supernode"); + break; + case MSG_TYPE_REGISTER_SUPER: + /* Edge requesting registration with us. */ + + sss->stats.last_reg_super=now; + ++(sss->stats.reg_super); + decode_REGISTER_SUPER(®s, &cmn, udp_buf, &rem, &idx); + + cmn2.ttl = N2N_DEFAULT_TTL; + cmn2.pc = n2n_register_super_ack; + cmn2.flags = N2N_FLAGS_FROM_SUPERNODE; + memcpy(cmn2.community, cmn.community, sizeof(n2n_community_t)); + + memcpy(&(ack.cookie), &(regs.cookie), sizeof(n2n_cookie_t)); + memcpy(ack.edgeMac, regs.edgeMac, sizeof(n2n_mac_t)); + ack.lifetime = reg_lifetime(sss); + + ack.sock.family = AF_INET; + ack.sock.port = ntohs(sender_sock->sin_port); + memcpy(ack.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); + + ack.num_sn=0; /* No backup */ + memset(&(ack.sn_bak), 0, sizeof(n2n_sock_t)); + + traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER for %s [%s]", + macaddr_str(mac_buf, regs.edgeMac), + sock_to_cstr(sockbuf, &(ack.sock))); + + update_edge(sss, ®s, cmn.community, &(ack.sock), now); + + encode_REGISTER_SUPER_ACK(encbuf, &encx, &cmn2, &ack); + + sendto(sss->sock, encbuf, encx, 0, + (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); + + traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_ACK for %s [%s]", + macaddr_str(mac_buf, regs.edgeMac), + sock_to_cstr(sockbuf, &(ack.sock))); + break; + default: + /* Not a known message type */ + traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored", (signed int)msg_type); + break; + } + + return 0; +} + +/** Help message to print if the command line arguments are not valid. */ +static void exit_help(int argc, char * const argv[]) +{ + fprintf(stderr, "%s usage\n", argv[0]); + fprintf(stderr, "-l \tSet UDP main listen port to \n"); + +#if defined(N2N_HAVE_DAEMON) + fprintf(stderr, "-f \tRun in foreground.\n"); +#endif /* #if defined(N2N_HAVE_DAEMON) */ + fprintf(stderr, + "-v \tIncrease verbosity. Can be used multiple times.\n"); + fprintf(stderr, "-h \tThis help message.\n"); + fprintf(stderr, "\n"); + exit(1); +} + +static int run_loop(n2n_sn_t * sss); + +/* *********************************************** */ + +static const struct option long_options[] = { + {"foreground", no_argument, NULL, 'f' }, + {"local-port", required_argument, NULL, 'l' }, + {"help", no_argument, NULL, 'h' }, + {"verbose", no_argument, NULL, 'v'}, + {NULL, 0, NULL, 0} +}; + +/** Main program entry point from kernel. */ +int main(int argc, char * const argv[]) +{ + n2n_sn_t sss; + + init_sn(&sss); + + { + int opt; + + while ((opt = getopt_long(argc, argv, "fl:vh", long_options, NULL)) != -1) { + switch (opt) { + case 'l': /* local-port */ + sss.lport = atoi(optarg); + break; + case 'f': /* foreground */ + sss.daemon = 0; + break; + case 'h': /* help */ + exit_help(argc, argv); + break; + case 'v': /* verbose */ + ++traceLevel; + break; + } + } + + } + +#if defined(N2N_HAVE_DAEMON) + if (sss.daemon) { + useSyslog = 1; /* traceEvent output now goes to syslog. */ + if (-1 == daemon(0, 0)) { + traceEvent(TRACE_ERROR, "Failed to become daemon."); + exit(-5); + } + } +#endif /* #if defined(N2N_HAVE_DAEMON) */ + + traceEvent(TRACE_DEBUG, "traceLevel is %d", traceLevel); + + sss.sock = open_socket(sss.lport, 1 /*bind ANY*/); + if (sss.sock == -1) { + traceEvent(TRACE_ERROR, "Failed to open main socket. %s", strerror(errno)); + exit(-2); + } else { + traceEvent(TRACE_NORMAL, "supernode is listening on UDP %u (main)", sss.lport); + } + + sss.mgmt_sock = open_socket(N2N_SN_MGMT_PORT, 0 /* bind LOOPBACK */); + if (sss.mgmt_sock == -1) { + traceEvent(TRACE_ERROR, "Failed to open management socket. %s", strerror(errno)); + exit(-2); + } else { + traceEvent(TRACE_NORMAL, "supernode is listening on UDP %u (management)", N2N_SN_MGMT_PORT); + } + + traceEvent(TRACE_NORMAL, "supernode started"); + + return run_loop(&sss); +} + +/** Long lived processing entry point. Split out from main to simply + * daemonisation on some platforms. */ +static int run_loop(n2n_sn_t * sss) +{ + uint8_t pktbuf[N2N_SN_PKTBUF_SIZE]; + int keep_running = 1; + + sss->start_time = time(NULL); + + while (keep_running) { + int rc; + ssize_t bread; + int max_sock; + fd_set socket_mask; + struct timeval wait_time; + time_t now = 0; + + FD_ZERO(&socket_mask); + max_sock = MAX(sss->sock, sss->mgmt_sock); + + FD_SET(sss->sock, &socket_mask); + FD_SET(sss->mgmt_sock, &socket_mask); + + wait_time.tv_sec = 10; + wait_time.tv_usec = 0; + rc = select(max_sock + 1, &socket_mask, NULL, NULL, &wait_time); + + now = time(NULL); + + if (rc > 0) { + if (FD_ISSET(sss->sock, &socket_mask)) { + struct sockaddr_in sender_sock; + socklen_t i; + + i = sizeof(sender_sock); + bread = recvfrom(sss->sock, pktbuf, N2N_SN_PKTBUF_SIZE, + 0/*flags*/, (struct sockaddr *) &sender_sock, + (socklen_t*) &i); + + if (bread < 0) /* For UDP bread of zero just means no data (unlike TCP). */ { + /* The fd is no good now. Maybe we lost our interface. */ + traceEvent(TRACE_ERROR, + "recvfrom() failed %d errno %d (%s)", bread, errno, strerror(errno)); + keep_running=0; + break; + } + + /* We have a datagram to process */ + if (bread > 0) { + /* And the datagram has data (not just a header) */ + process_udp(sss, &sender_sock, pktbuf, bread, now); + } + } + + if (FD_ISSET(sss->mgmt_sock, &socket_mask)) { + struct sockaddr_in sender_sock; + size_t i; + + i = sizeof(sender_sock); + bread = recvfrom(sss->mgmt_sock, pktbuf, N2N_SN_PKTBUF_SIZE, + 0/*flags*/, (struct sockaddr *) &sender_sock, + (socklen_t*) &i); + + if (bread <= 0) { + traceEvent(TRACE_ERROR, + "recvfrom() failed %d errno %d (%s)", bread, errno, strerror(errno)); + keep_running=0; + break; + } + + /* We have a datagram to process */ + process_mgmt(sss, &sender_sock, pktbuf, bread, now); + } + } else { + traceEvent(TRACE_DEBUG, "timeout"); + } + if ((now - sss->last_purge) >= PURGE_REGISTRATION_FREQUENCY) { + hashed_purge_expired_registrations(sss->edges); + sss->last_purge = now; + } + + } /* while */ + + deinit_sn(sss); + + return 0; +} + diff --git a/n2n_v2/supernode.1 b/supernode.1 similarity index 100% rename from n2n_v2/supernode.1 rename to supernode.1 diff --git a/test.c b/test.c new file mode 100644 index 0000000..c9d2366 --- /dev/null +++ b/test.c @@ -0,0 +1,20 @@ +#include "n2n.h" +#include "n2n_keyfile.h" +#include +#include +#include + +int main(int arc, const char * argv[]) { + int e; + n2n_cipherspec_t specs[N2N_MAX_NUM_CIPHERSPECS]; + + e = n2n_read_keyfile(specs, N2N_MAX_NUM_CIPHERSPECS, "keyctrl.conf"); + + if (e < 0) { + perror("Failed to read keyfile"); + } else { + fprintf(stderr, "Stored %d keys.\n", e); + } + + return 0; +} diff --git a/transform_aes.c b/transform_aes.c new file mode 100644 index 0000000..3cbc361 --- /dev/null +++ b/transform_aes.c @@ -0,0 +1,528 @@ +/* (c) 2009 Richard Andrews */ +/* Contributions from: + * - Jozef Kralik + */ + +#include "n2n.h" +#include "n2n_transforms.h" + +#if defined(N2N_HAVE_AES) + +#include "openssl/aes.h" +#ifndef _MSC_VER +/* Not included in Visual Studio 2008 */ +#include /* index() */ +#endif + +#define N2N_AES_NUM_SA 32 /* space for SAa */ + +#define N2N_AES_TRANSFORM_VERSION 1 /* version of the transform encoding */ +#define N2N_AES_IVEC_SIZE 32 /* Enough space for biggest AES ivec */ + +typedef unsigned char n2n_aes_ivec_t[N2N_AES_IVEC_SIZE]; + +struct sa_aes { + n2n_cipherspec_t spec; /* cipher spec parameters */ + n2n_sa_t sa_id; /* security association index */ + AES_KEY enc_key; /* tx key */ + n2n_aes_ivec_t enc_ivec; /* tx CBC state */ + AES_KEY dec_key; /* tx key */ + n2n_aes_ivec_t dec_ivec; /* tx CBC state */ +}; + +typedef struct sa_aes sa_aes_t; + +/** Aes transform state data. + * + * With a key-schedule in place this will be populated with a number of + * SAs. Each SA has a lifetime and some opque data. The opaque data for aes + * consists of the SA number and key material. + * + */ +struct transop_aes { + ssize_t tx_sa; + size_t num_sa; + sa_aes_t sa[N2N_AES_NUM_SA]; +}; + +typedef struct transop_aes transop_aes_t; + +static int transop_deinit_aes( n2n_trans_op_t * arg ) +{ + transop_aes_t * priv = (transop_aes_t *)arg->priv; + size_t i; + + if (priv) { + /* Memory was previously allocated */ + for (i = 0; i < N2N_AES_NUM_SA; ++i) { + sa_aes_t * sa = &(priv->sa[i]); + + sa->sa_id=0; + } + + priv->num_sa=0; + priv->tx_sa=-1; + + free(priv); + } + + arg->priv=NULL; /* return to fully uninitialised state */ + + return 0; +} + +static size_t aes_choose_tx_sa( transop_aes_t * priv ) +{ + return priv->tx_sa; /* set in tick */ +} + +#define TRANSOP_AES_VER_SIZE 1 /* Support minor variants in encoding in one module. */ +#define TRANSOP_AES_NONCE_SIZE 4 +#define TRANSOP_AES_SA_SIZE 4 + +#define AES256_KEY_BYTES (256/8) +#define AES192_KEY_BYTES (192/8) +#define AES128_KEY_BYTES (128/8) + +/* Return the best acceptable AES key size (in bytes) given an input keysize. + * + * The value returned will be one of AES128_KEY_BYTES, AES192_KEY_BYTES or + * AES256_KEY_BYTES. + */ +static size_t aes_best_keysize(size_t numBytes) +{ + if (numBytes >= AES256_KEY_BYTES) { + return AES256_KEY_BYTES; + } else if (numBytes >= AES192_KEY_BYTES) { + return AES192_KEY_BYTES; + } else { + return AES128_KEY_BYTES; + } +} + +/** The aes packet format consists of: + * + * - a 8-bit aes encoding version in clear text + * - a 32-bit SA number in clear text + * - ciphertext encrypted from a 32-bit nonce followed by the payload. + * + * [V|SSSS|nnnnDDDDDDDDDDDDDDDDDDDDD] + * |<------ encrypted ------>| + */ +static int transop_encode_aes( n2n_trans_op_t * arg, + uint8_t * outbuf, + size_t out_len, + const uint8_t * inbuf, + size_t in_len ) +{ + int len2 = -1; + transop_aes_t * priv = (transop_aes_t *)arg->priv; + uint8_t assembly[N2N_PKT_BUF_SIZE]; + uint32_t * pnonce; + + if ((in_len + TRANSOP_AES_NONCE_SIZE) <= N2N_PKT_BUF_SIZE) { + if ((in_len + TRANSOP_AES_NONCE_SIZE + TRANSOP_AES_SA_SIZE + TRANSOP_AES_VER_SIZE) <= out_len) { + int len=-1; + size_t idx=0; + sa_aes_t * sa; + size_t tx_sa_num = 0; + + /* The transmit sa is periodically updated */ + tx_sa_num = aes_choose_tx_sa(priv); + + sa = &(priv->sa[tx_sa_num]); /* Proper Tx SA index */ + + traceEvent(TRACE_DEBUG, "encode_aes %lu with SA %lu.", in_len, sa->sa_id); + + /* Encode the aes format version. */ + encode_uint8(outbuf, &idx, N2N_AES_TRANSFORM_VERSION); + + /* Encode the security association (SA) number */ + encode_uint32(outbuf, &idx, sa->sa_id); + + /* Encrypt the assembly contents and write the ciphertext after the SA. */ + len = in_len + TRANSOP_AES_NONCE_SIZE; + + /* The assembly buffer is a source for encrypting data. The nonce is + * written in first followed by the packet payload. The whole + * contents of assembly are encrypted. */ + pnonce = (uint32_t *)assembly; + *pnonce = rand(); + memcpy(assembly + TRANSOP_AES_NONCE_SIZE, inbuf, in_len); + + /* Need at least one encrypted byte at the end for the padding. */ + len2 = ((len / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE; /* Round up to next whole AES adding at least one byte. */ + assembly[len2 - 1] = (len2 - len); + traceEvent(TRACE_DEBUG, "padding = %u", assembly[len2 - 1]); + + memset(&(sa->enc_ivec), 0, sizeof(N2N_AES_IVEC_SIZE)); + AES_cbc_encrypt(assembly, /* source */ + outbuf + TRANSOP_AES_VER_SIZE + TRANSOP_AES_SA_SIZE, /* dest */ + len2, /* enc size */ + &(sa->enc_key), sa->enc_ivec, 1 /* encrypt */); + + len2 += TRANSOP_AES_VER_SIZE + TRANSOP_AES_SA_SIZE; /* size of data carried in UDP. */ + } else { + traceEvent(TRACE_ERROR, "encode_aes outbuf too small."); + } + } else { + traceEvent(TRACE_ERROR, "encode_aes inbuf too big to encrypt."); + } + + return len2; +} + +/* Search through the array of SAs to find the one with the required ID. + * + * @return array index where found or -1 if not found + */ +static ssize_t aes_find_sa( const transop_aes_t * priv, const n2n_sa_t req_id ) +{ + size_t i; + + for (i=0; i < priv->num_sa; ++i) { + const sa_aes_t * sa=NULL; + + sa = &(priv->sa[i]); + if (req_id == sa->sa_id) { + return i; + } + } + + return -1; +} + +/** The aes packet format consists of: + * + * - a 8-bit aes encoding version in clear text + * - a 32-bit SA number in clear text + * - ciphertext encrypted from a 32-bit nonce followed by the payload. + * + * [V|SSSS|nnnnDDDDDDDDDDDDDDDDDDDDD] + * |<------ encrypted ------>| + */ +static int transop_decode_aes( n2n_trans_op_t * arg, + uint8_t * outbuf, + size_t out_len, + const uint8_t * inbuf, + size_t in_len ) +{ + int len=0; + transop_aes_t * priv = (transop_aes_t *)arg->priv; + uint8_t assembly[N2N_PKT_BUF_SIZE]; + + if (((in_len - (TRANSOP_AES_VER_SIZE + TRANSOP_AES_SA_SIZE)) <= N2N_PKT_BUF_SIZE) /* Cipher text fits in assembly */ + && (in_len >= (TRANSOP_AES_VER_SIZE + TRANSOP_AES_SA_SIZE + TRANSOP_AES_NONCE_SIZE)) /* Has at least version, SA and nonce */ + ) + { + n2n_sa_t sa_rx; + ssize_t sa_idx=-1; + size_t rem=in_len; + size_t idx=0; + uint8_t aes_enc_ver=0; + + /* Get the encoding version to make sure it is supported */ + decode_uint8(inbuf, &idx, &rem, &aes_enc_ver); + + if (N2N_AES_TRANSFORM_VERSION == aes_enc_ver) { + /* Get the SA number and make sure we are decrypting with the right one. */ + decode_uint32(inbuf, &idx, &rem, &sa_rx); + + sa_idx = aes_find_sa(priv, sa_rx); + if (sa_idx >= 0) { + sa_aes_t * sa = &(priv->sa[sa_idx]); + + traceEvent(TRACE_DEBUG, "decode_aes %lu with SA %lu.", in_len, sa_rx, sa->sa_id); + + len = (in_len - (TRANSOP_AES_VER_SIZE + TRANSOP_AES_SA_SIZE)); + + if ((len % AES_BLOCK_SIZE) == 0) { + uint8_t padding; + + memset(&(sa->dec_ivec), 0, sizeof(N2N_AES_IVEC_SIZE)); + AES_cbc_encrypt((inbuf + TRANSOP_AES_VER_SIZE + TRANSOP_AES_SA_SIZE), + assembly, /* destination */ + len, + &(sa->dec_key), + sa->dec_ivec, 0 /* decrypt */); + + /* last byte is how much was padding: max value should be + * AES_BLOCKSIZE-1 */ + padding = assembly[len - 1] & 0xff; + + if (len >= (padding + TRANSOP_AES_NONCE_SIZE)) { + /* strictly speaking for this to be an ethernet packet + * it is going to need to be even bigger; but this is + * enough to prevent segfaults. */ + traceEvent(TRACE_DEBUG, "padding = %u", padding); + len -= padding; + + len -= TRANSOP_AES_NONCE_SIZE; /* size of ethernet packet */ + + /* Step over 4-byte random nonce value */ + memcpy(outbuf, + assembly + TRANSOP_AES_NONCE_SIZE, + len); + } else { + traceEvent(TRACE_WARNING, "UDP payload decryption failed."); + } + } else { + traceEvent(TRACE_WARNING, "Encrypted length %d is not a multiple of AES_BLOCK_SIZE (%d)", len, AES_BLOCK_SIZE); + len = 0; + } + + } else { + /* Wrong security association; drop the packet as it is undecodable. */ + traceEvent(TRACE_ERROR, "decode_aes SA number %lu not found.", sa_rx); + + /* REVISIT: should be able to load a new SA at this point to complete the decoding. */ + } + } else { + /* Wrong security association; drop the packet as it is undecodable. */ + traceEvent(TRACE_ERROR, "decode_aes unsupported aes version %u.", aes_enc_ver); + + /* REVISIT: should be able to load a new SA at this point to complete the decoding. */ + } + } else { + traceEvent(TRACE_ERROR, "decode_aes inbuf wrong size (%ul) to decrypt.", in_len); + } + + return len; +} + +static int transop_addspec_aes( n2n_trans_op_t * arg, const n2n_cipherspec_t * cspec ) +{ + int retval = 1; + ssize_t pstat=-1; + transop_aes_t * priv = (transop_aes_t *)arg->priv; + uint8_t keybuf[N2N_MAX_KEYSIZE]; + + if (priv->num_sa < N2N_AES_NUM_SA) { + const char * op = (const char *)cspec->opaque; + const char * sep = index( op, '_' ); + + if (sep) { + char tmp[256]; + size_t s; + + s = sep - op; + memcpy(tmp, cspec->opaque, s); + tmp[s] = 0; + + s = strlen(sep + 1); /* sep is the _ which might be immediately followed by NULL */ + + priv->sa[priv->num_sa].spec = *cspec; + priv->sa[priv->num_sa].sa_id = strtoul(tmp, NULL, 10); + + memset(keybuf, 0, N2N_MAX_KEYSIZE); + pstat = n2n_parse_hex(keybuf, N2N_MAX_KEYSIZE, sep+1, s); + if (pstat > 0) { + /* pstat is number of bytes read into keybuf. */ + sa_aes_t * sa = &(priv->sa[priv->num_sa]); + size_t aes_keysize_bytes; + size_t aes_keysize_bits; + + /* Clear out any old possibly longer key matter. */ + memset(&(sa->enc_key), 0, sizeof(AES_KEY)); + memset(&(sa->dec_key), 0, sizeof(AES_KEY)); + + memset(&(sa->enc_ivec), 0, sizeof(N2N_AES_IVEC_SIZE)); + memset(&(sa->dec_ivec), 0, sizeof(N2N_AES_IVEC_SIZE)); + + aes_keysize_bytes = aes_best_keysize(pstat); + aes_keysize_bits = 8 * aes_keysize_bytes; + + /* Use N2N_MAX_KEYSIZE because the AES key needs to be of fixed + * size. If fewer bits specified then the rest will be + * zeroes. AES acceptable key sizes are 128, 192 and 256 + * bits. */ + AES_set_encrypt_key(keybuf, aes_keysize_bits, &(sa->enc_key)); + AES_set_decrypt_key(keybuf, aes_keysize_bits, &(sa->dec_key)); + /* Leave ivecs set to all zeroes */ + + traceEvent(TRACE_DEBUG, "transop_addspec_aes sa_id=%u, %u bits data=%s.\n", + priv->sa[priv->num_sa].sa_id, aes_keysize_bits, sep + 1); + + ++(priv->num_sa); + retval = 0; + } + } else { + traceEvent(TRACE_ERROR, "transop_addspec_aes : bad key data - missing '_'.\n"); + } + } else { + traceEvent(TRACE_ERROR, "transop_addspec_aes : full.\n"); + } + + return retval; +} + +static n2n_tostat_t transop_tick_aes( n2n_trans_op_t * arg, time_t now ) +{ + transop_aes_t * priv = (transop_aes_t *)arg->priv; + size_t i; + int found = 0; + n2n_tostat_t r; + + memset(&r, 0, sizeof(r)); + + traceEvent(TRACE_DEBUG, "transop_aes tick num_sa=%u now=%lu", priv->num_sa, now); + + for (i = 0; i < priv->num_sa; ++i) { + if (validCipherSpec(&(priv->sa[i].spec), now) == 0) { + time_t remaining = priv->sa[i].spec.valid_until - now; + + traceEvent(TRACE_INFO, "transop_aes choosing tx_sa=%u (valid for %lu sec)", priv->sa[i].sa_id, remaining); + priv->tx_sa = i; + found = 1; + break; + } else { + traceEvent(TRACE_DEBUG, "transop_aes tick rejecting sa=%u %lu -> %lu", + priv->sa[i].sa_id, priv->sa[i].spec.valid_from, priv->sa[i].spec.valid_until); + } + } + + if (found == 0) { + traceEvent(TRACE_INFO, "transop_aes no keys are currently valid. Keeping tx_sa=%u", priv->tx_sa); + } else { + r.can_tx = 1; + r.tx_spec.t = N2N_TRANSFORM_ID_AESCBC; + r.tx_spec = priv->sa[priv->tx_sa].spec; + } + + return r; +} + +int transop_aes_init( n2n_trans_op_t * ttt ) +{ + int retval = 1; + transop_aes_t * priv = NULL; + + if (ttt->priv) { + transop_deinit_aes(ttt); + } + + memset(ttt, 0, sizeof(n2n_trans_op_t)); + + priv = (transop_aes_t *)malloc(sizeof(transop_aes_t)); + + if (NULL != priv) { + size_t i; + sa_aes_t * sa = NULL; + + /* install the private structure. */ + ttt->priv = priv; + priv->num_sa = 0; + priv->tx_sa = 0; /* We will use this sa index for encoding. */ + + ttt->transform_id = N2N_TRANSFORM_ID_AESCBC; + ttt->addspec = transop_addspec_aes; + ttt->tick = transop_tick_aes; /* chooses a new tx_sa */ + ttt->deinit = transop_deinit_aes; + ttt->fwd = transop_encode_aes; + ttt->rev = transop_decode_aes; + + for(i = 0; i < N2N_AES_NUM_SA; ++i) { + sa = &(priv->sa[i]); + sa->sa_id=0; + memset(&(sa->spec), 0, sizeof(n2n_cipherspec_t)); + memset(&(sa->enc_key), 0, sizeof(AES_KEY)); + memset(&(sa->enc_ivec), 0, sizeof(N2N_AES_IVEC_SIZE)); + memset(&(sa->dec_key), 0, sizeof(AES_KEY)); + memset(&(sa->dec_ivec), 0, sizeof(N2N_AES_IVEC_SIZE)); + } + + retval = 0; + } else { + memset(ttt, 0, sizeof(n2n_trans_op_t)); + traceEvent(TRACE_ERROR, "Failed to allocate priv for aes"); + } + + return retval; +} + +#else /* #if defined(N2N_HAVE_AES) */ + +struct transop_aes { + ssize_t tx_sa; +}; + +typedef struct transop_aes transop_aes_t; + +static int transop_deinit_aes(n2n_trans_op_t * arg) +{ + transop_aes_t * priv = (transop_aes_t *) arg->priv; + + if (priv) { + free(priv); + } + + arg->priv = NULL; /* return to fully uninitialised state */ + + return 0; +} + +static int transop_encode_aes(n2n_trans_op_t * arg, uint8_t * outbuf, + size_t out_len, const uint8_t * inbuf, size_t in_len) +{ + return -1; +} + +static int transop_decode_aes(n2n_trans_op_t * arg, uint8_t * outbuf, + size_t out_len, const uint8_t * inbuf, size_t in_len) +{ + return -1; +} + +static int transop_addspec_aes(n2n_trans_op_t * arg, + const n2n_cipherspec_t * cspec) +{ + traceEvent(TRACE_DEBUG, "transop_addspec_aes AES not built into edge.\n"); + + return -1; +} + +static n2n_tostat_t transop_tick_aes(n2n_trans_op_t * arg, time_t now) +{ + n2n_tostat_t r; + + memset(&r, 0, sizeof(r)); + + return r; +} + +int transop_aes_init(n2n_trans_op_t * ttt) +{ + int retval = 1; + transop_aes_t * priv = NULL; + + if (ttt->priv) { + transop_deinit_aes(ttt); + } + + memset(ttt, 0, sizeof(n2n_trans_op_t)); + + priv = (transop_aes_t *)malloc(sizeof(transop_aes_t)); + + if (priv != NULL) { + /* install the private structure. */ + ttt->priv = priv; + priv->tx_sa = 0; /* We will use this sa index for encoding. */ + + ttt->transform_id = N2N_TRANSFORM_ID_AESCBC; + ttt->addspec = transop_addspec_aes; + ttt->tick = transop_tick_aes; /* chooses a new tx_sa */ + ttt->deinit = transop_deinit_aes; + ttt->fwd = transop_encode_aes; + ttt->rev = transop_decode_aes; + + retval = 0; + } else { + memset(ttt, 0, sizeof(n2n_trans_op_t)); + traceEvent(TRACE_ERROR, "Failed to allocate priv for aes"); + } + + return retval; +} + +#endif /* #if defined(N2N_HAVE_AES) */ + diff --git a/transform_null.c b/transform_null.c new file mode 100644 index 0000000..49eb90f --- /dev/null +++ b/transform_null.c @@ -0,0 +1,73 @@ +/* (c) 2009 Richard Andrews */ + +#include "n2n.h" +#include "n2n_transforms.h" + +static int transop_deinit_null(n2n_trans_op_t * arg) +{ + /* nothing to deallocate, nothing to release. */ + return 0; +} + +static int transop_encode_null(n2n_trans_op_t * arg, uint8_t * outbuf, + size_t out_len, const uint8_t * inbuf, size_t in_len) +{ + int retval = -1; + + traceEvent(TRACE_DEBUG, "encode_null %lu", in_len); + if (out_len >= in_len) { + memcpy(outbuf, inbuf, in_len); + retval = in_len; + } else { + traceEvent(TRACE_DEBUG, "encode_null %lu too big for packet buffer", in_len); + } + + return retval; +} + +static int transop_decode_null(n2n_trans_op_t * arg, uint8_t * outbuf, + size_t out_len, const uint8_t * inbuf, size_t in_len) +{ + int retval = -1; + + traceEvent(TRACE_DEBUG, "decode_null %lu", in_len); + if (out_len >= in_len) { + memcpy(outbuf, inbuf, in_len); + retval = in_len; + } else { + traceEvent(TRACE_DEBUG, "decode_null %lu too big for packet buffer", in_len); + } + + return retval; +} + +static int transop_addspec_null(n2n_trans_op_t * arg, + const n2n_cipherspec_t * cspec) +{ + return 0; +} + +static n2n_tostat_t transop_tick_null(n2n_trans_op_t * arg, time_t now) +{ + n2n_tostat_t r; + + r.can_tx = 1; + r.tx_spec.t = N2N_TRANSFORM_ID_NULL; + r.tx_spec.valid_from = 0; + r.tx_spec.valid_until = (time_t) (-1); + r.tx_spec.opaque_size = 0; + + return r; +} + +void transop_null_init(n2n_trans_op_t * ttt) +{ + memset(ttt, 0, sizeof(n2n_trans_op_t)); + + ttt->transform_id = N2N_TRANSFORM_ID_NULL; + ttt->deinit = transop_deinit_null; + ttt->addspec = transop_addspec_null; + ttt->tick = transop_tick_null; + ttt->fwd = transop_encode_null; + ttt->rev = transop_decode_null; +} diff --git a/transform_tf.c b/transform_tf.c new file mode 100644 index 0000000..8dc8fd3 --- /dev/null +++ b/transform_tf.c @@ -0,0 +1,428 @@ +/* (c) 2009 Richard Andrews */ + +#include "n2n.h" +#include "n2n_transforms.h" +#include "twofish.h" +#ifndef _MSC_VER +/* Not included in Visual Studio 2008 */ +#include /* index() */ +#endif + +#define N2N_TWOFISH_NUM_SA 32 /* space for SAa */ + +#define N2N_TWOFISH_TRANSFORM_VERSION 1 /* version of the transform encoding */ + +struct sa_twofish { + n2n_cipherspec_t spec; /* cipher spec parameters */ + n2n_sa_t sa_id; /* security association index */ + TWOFISH * enc_tf; /* tx state */ + TWOFISH * dec_tf; /* rx state */ +}; + +typedef struct sa_twofish sa_twofish_t; + +/** Twofish transform state data. + * + * With a key-schedule in place this will be populated with a number of + * SAs. Each SA has a lifetime and some opque data. The opaque data for twofish + * consists of the SA number and key material. + * + */ +struct transop_tf { + ssize_t tx_sa; + size_t num_sa; + sa_twofish_t sa[N2N_TWOFISH_NUM_SA]; +}; + +typedef struct transop_tf transop_tf_t; + +static int transop_deinit_twofish(n2n_trans_op_t * arg) +{ + transop_tf_t * priv = (transop_tf_t *) arg->priv; + size_t i; + + if (priv) { + /* Memory was previously allocated */ + for (i = 0; i < N2N_TWOFISH_NUM_SA; ++i) { + sa_twofish_t * sa = &(priv->sa[i]); + + TwoFishDestroy(sa->enc_tf); /* deallocate TWOFISH */ + sa->enc_tf = NULL; + + TwoFishDestroy(sa->dec_tf); /* deallocate TWOFISH */ + sa->dec_tf = NULL; + + sa->sa_id = 0; + } + + priv->num_sa = 0; + priv->tx_sa = -1; + + free(priv); + } + + arg->priv = NULL; /* return to fully uninitialised state */ + + return 0; +} + +static size_t tf_choose_tx_sa(transop_tf_t * priv) +{ + return priv->tx_sa; /* set in tick */ +} + +#define TRANSOP_TF_VER_SIZE 1 /* Support minor variants in encoding in one module. */ +#define TRANSOP_TF_NONCE_SIZE 4 +#define TRANSOP_TF_SA_SIZE 4 + +/** The twofish packet format consists of: + * + * - a 8-bit twofish encoding version in clear text + * - a 32-bit SA number in clear text + * - ciphertext encrypted from a 32-bit nonce followed by the payload. + * + * [V|SSSS|nnnnDDDDDDDDDDDDDDDDDDDDD] + * |<------ encrypted ------>| + */ +static int transop_encode_twofish(n2n_trans_op_t * arg, uint8_t * outbuf, + size_t out_len, const uint8_t * inbuf, size_t in_len) +{ + int len = -1; + transop_tf_t * priv = (transop_tf_t *) arg->priv; + uint8_t assembly[N2N_PKT_BUF_SIZE]; + uint32_t * pnonce; + + if ((in_len + TRANSOP_TF_NONCE_SIZE) <= N2N_PKT_BUF_SIZE) { + if ((in_len + TRANSOP_TF_NONCE_SIZE + TRANSOP_TF_SA_SIZE + + TRANSOP_TF_VER_SIZE) <= out_len) { + size_t idx = 0; + sa_twofish_t * sa; + size_t tx_sa_num = 0; + + /* The transmit sa is periodically updated */ + tx_sa_num = tf_choose_tx_sa(priv); + + sa = &(priv->sa[tx_sa_num]); /* Proper Tx SA index */ + + traceEvent(TRACE_DEBUG, "encode_twofish %lu with SA %lu.", in_len, sa->sa_id); + + /* Encode the twofish format version. */ + encode_uint8(outbuf, &idx, N2N_TWOFISH_TRANSFORM_VERSION); + + /* Encode the security association (SA) number */ + encode_uint32(outbuf, &idx, sa->sa_id); + + /* The assembly buffer is a source for encrypting data. The nonce is + * written in first followed by the packet payload. The whole + * contents of assembly are encrypted. */ + pnonce = (uint32_t *) assembly; + *pnonce = rand(); + memcpy(assembly + TRANSOP_TF_NONCE_SIZE, inbuf, in_len); + + /* Encrypt the assembly contents and write the ciphertext after the SA. */ + len = TwoFishEncryptRaw(assembly, /* source */ + outbuf + TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE, + in_len + TRANSOP_TF_NONCE_SIZE, /* enc size */ + sa->enc_tf); + if (len > 0) { + len += TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE; /* size of data carried in UDP. */ + } else { + traceEvent(TRACE_ERROR, "encode_twofish encryption failed."); + } + + } else { + traceEvent(TRACE_ERROR, "encode_twofish outbuf too small."); + } + } else { + traceEvent(TRACE_ERROR, "encode_twofish inbuf too big to encrypt."); + } + + return len; +} + +/* Search through the array of SAs to find the one with the required ID. + * + * @return array index where found or -1 if not found + */ +static ssize_t twofish_find_sa(const transop_tf_t * priv, const n2n_sa_t req_id) +{ + size_t i; + + for (i = 0; i < priv->num_sa; ++i) { + const sa_twofish_t * sa = NULL; + + sa = &(priv->sa[i]); + if (req_id == sa->sa_id) { + return i; + } + } + + return -1; +} + +/** The twofish packet format consists of: + * + * - a 8-bit twofish encoding version in clear text + * - a 32-bit SA number in clear text + * - ciphertext encrypted from a 32-bit nonce followed by the payload. + * + * [V|SSSS|nnnnDDDDDDDDDDDDDDDDDDDDD] + * |<------ encrypted ------>| + */ +static int transop_decode_twofish(n2n_trans_op_t * arg, uint8_t * outbuf, + size_t out_len, const uint8_t * inbuf, size_t in_len) +{ + int len = 0; + transop_tf_t * priv = (transop_tf_t *)arg->priv; + uint8_t assembly[N2N_PKT_BUF_SIZE]; + + if (((in_len - (TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE)) <= N2N_PKT_BUF_SIZE) /* Cipher text fits in assembly */ + && (in_len >= (TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE + TRANSOP_TF_NONCE_SIZE)) /* Has at least version, SA and nonce */) { + n2n_sa_t sa_rx; + ssize_t sa_idx = -1; + size_t rem = in_len; + size_t idx = 0; + uint8_t tf_enc_ver = 0; + + /* Get the encoding version to make sure it is supported */ + decode_uint8(inbuf, &idx, &rem, &tf_enc_ver); + + if (N2N_TWOFISH_TRANSFORM_VERSION == tf_enc_ver) { + /* Get the SA number and make sure we are decrypting with the right one. */ + decode_uint32(inbuf, &idx, &rem, &sa_rx); + + sa_idx = twofish_find_sa(priv, sa_rx); + if (sa_idx >= 0) { + sa_twofish_t * sa = &(priv->sa[sa_idx]); + + traceEvent(TRACE_DEBUG, "decode_twofish %lu with SA %lu.", + in_len, sa_rx, sa->sa_id ); + + len = TwoFishDecryptRaw( + (void *) (inbuf + TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE), + assembly, /* destination */ + (in_len - (TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE)), + sa->dec_tf); + + if (len > 0) { + /* Step over 4-byte random nonce value */ + len -= TRANSOP_TF_NONCE_SIZE; /* size of ethernet packet */ + + memcpy(outbuf, assembly + TRANSOP_TF_NONCE_SIZE, len); + } else { + traceEvent(TRACE_ERROR, "decode_twofish decryption failed."); + } + + } else { + /* Wrong security association; drop the packet as it is undecodable. */ + traceEvent(TRACE_ERROR, "decode_twofish SA number %lu not found.", sa_rx); + + /* REVISIT: should be able to load a new SA at this point to complete the decoding. */ + } + } else { + /* Wrong security association; drop the packet as it is undecodable. */ + traceEvent(TRACE_ERROR,"decode_twofish unsupported twofish version %u.", tf_enc_ver); + + /* REVISIT: should be able to load a new SA at this point to complete the decoding. */ + } + } else { + traceEvent(TRACE_ERROR, "decode_twofish inbuf wrong size (%ul) to decrypt.", in_len); + } + + return len; +} + +static int transop_addspec_twofish(n2n_trans_op_t * arg, + const n2n_cipherspec_t * cspec) +{ + int retval = 1; + ssize_t pstat = -1; + transop_tf_t * priv = (transop_tf_t *) arg->priv; + uint8_t keybuf[N2N_MAX_KEYSIZE]; + + if (priv->num_sa < N2N_TWOFISH_NUM_SA) { + const char * op = (const char *) cspec->opaque; + const char * sep = index(op, '_'); + + if (sep) { + char tmp[256]; + size_t s; + + s = sep - op; + memcpy(tmp, cspec->opaque, s); + tmp[s] = 0; + + s = strlen(sep + 1); /* sep is the _ which might be immediately followed by NULL */ + + priv->sa[priv->num_sa].spec = *cspec; + priv->sa[priv->num_sa].sa_id = strtoul(tmp, NULL, 10); + + pstat = n2n_parse_hex(keybuf, N2N_MAX_KEYSIZE, sep + 1, s); + if (pstat > 0) { + priv->sa[priv->num_sa].enc_tf = TwoFishInit(keybuf, pstat); + priv->sa[priv->num_sa].dec_tf = TwoFishInit(keybuf, pstat); + + traceEvent(TRACE_DEBUG, + "transop_addspec_twofish sa_id=%u data=%s.\n", + priv->sa[priv->num_sa].sa_id, sep+1); + + ++(priv->num_sa); + retval = 0; + } + } else { + traceEvent(TRACE_ERROR, + "transop_addspec_twofish : bad key data - missing '_'.\n"); + } + } else { + traceEvent(TRACE_ERROR, "transop_addspec_twofish : full.\n"); + } + + return retval; +} + +static n2n_tostat_t transop_tick_twofish(n2n_trans_op_t * arg, time_t now) +{ + transop_tf_t * priv = (transop_tf_t *) arg->priv; + size_t i; + int found = 0; + n2n_tostat_t r; + + memset(&r, 0, sizeof(r)); + + traceEvent(TRACE_DEBUG, "transop_tf tick num_sa=%u", priv->num_sa); + + for (i = 0; i < priv->num_sa; ++i) { + if (0 == validCipherSpec(&(priv->sa[i].spec), now)) { + time_t remaining = priv->sa[i].spec.valid_until - now; + + traceEvent(TRACE_INFO, + "transop_tf choosing tx_sa=%u (valid for %lu sec)", + priv->sa[i].sa_id, remaining); + priv->tx_sa = i; + found = 1; + break; + } else { + traceEvent(TRACE_DEBUG, + "transop_tf tick rejecting sa=%u %lu -> %lu", + priv->sa[i].sa_id, priv->sa[i].spec.valid_from, priv->sa[i].spec.valid_until); + } + } + + if (found == 0) { + traceEvent(TRACE_INFO, + "transop_tf no keys are currently valid. Keeping tx_sa=%u", priv->tx_sa); + } else { + r.can_tx = 1; + r.tx_spec.t = N2N_TRANSFORM_ID_TWOFISH; + r.tx_spec = priv->sa[priv->tx_sa].spec; + } + + return r; +} + +int transop_twofish_setup(n2n_trans_op_t * ttt, n2n_sa_t sa_num, + uint8_t * encrypt_pwd, uint32_t encrypt_pwd_len) +{ + int retval = 1; + transop_tf_t * priv = NULL; + + if (ttt->priv) { + transop_deinit_twofish(ttt); + } + + memset(ttt, 0, sizeof(n2n_trans_op_t)); + + priv = (transop_tf_t *) malloc(sizeof(transop_tf_t)); + + if (NULL != priv) { + size_t i; + sa_twofish_t * sa = NULL; + + /* install the private structure. */ + ttt->priv = priv; + + for (i = 0; i < N2N_TWOFISH_NUM_SA; ++i) { + sa = &(priv->sa[i]); + sa->sa_id = 0; + memset(&(sa->spec), 0, sizeof(n2n_cipherspec_t)); + sa->enc_tf = NULL; + sa->dec_tf = NULL; + } + + priv->num_sa = 1; /* There is one SA in the array. */ + priv->tx_sa = 0; + sa = &(priv->sa[priv->tx_sa]); + sa->sa_id = sa_num; + sa->spec.valid_until = 0x7fffffff; + + /* This is a preshared key setup. Both Tx and Rx are using the same security association. */ + + sa->enc_tf = TwoFishInit(encrypt_pwd, encrypt_pwd_len); + sa->dec_tf = TwoFishInit(encrypt_pwd, encrypt_pwd_len); + + if ((sa->enc_tf) && (sa->dec_tf)) { + ttt->transform_id = N2N_TRANSFORM_ID_TWOFISH; + ttt->deinit = transop_deinit_twofish; + ttt->addspec = transop_addspec_twofish; + ttt->tick = transop_tick_twofish; /* chooses a new tx_sa */ + ttt->fwd = transop_encode_twofish; + ttt->rev = transop_decode_twofish; + + retval = 0; + } else { + traceEvent(TRACE_ERROR, "TwoFishInit failed"); + } + } else { + memset(ttt, 0, sizeof(n2n_trans_op_t)); + traceEvent(TRACE_ERROR, "Failed to allocate priv for twofish"); + } + + return retval; +} + +int transop_twofish_init(n2n_trans_op_t * ttt) +{ + int retval = 1; + transop_tf_t * priv = NULL; + + if (ttt->priv) { + transop_deinit_twofish(ttt); + } + + memset(ttt, 0, sizeof(n2n_trans_op_t)); + + priv = (transop_tf_t *) malloc(sizeof(transop_tf_t)); + + if (NULL != priv) { + size_t i; + sa_twofish_t * sa = NULL; + + /* install the private structure. */ + ttt->priv = priv; + priv->num_sa = 0; + priv->tx_sa = 0; /* We will use this sa index for encoding. */ + + ttt->transform_id = N2N_TRANSFORM_ID_TWOFISH; + ttt->addspec = transop_addspec_twofish; + ttt->tick = transop_tick_twofish; /* chooses a new tx_sa */ + ttt->deinit = transop_deinit_twofish; + ttt->fwd = transop_encode_twofish; + ttt->rev = transop_decode_twofish; + + for (i = 0; i < N2N_TWOFISH_NUM_SA; ++i) { + sa = &(priv->sa[i]); + sa->sa_id = 0; + memset(&(sa->spec), 0, sizeof(n2n_cipherspec_t)); + sa->enc_tf = NULL; + sa->dec_tf = NULL; + } + + retval = 0; + } else { + memset(ttt, 0, sizeof(n2n_trans_op_t)); + traceEvent(TRACE_ERROR, "Failed to allocate priv for twofish"); + } + + return retval; +} + diff --git a/tuntap_freebsd.c b/tuntap_freebsd.c new file mode 100644 index 0000000..da79b5f --- /dev/null +++ b/tuntap_freebsd.c @@ -0,0 +1,135 @@ +/* + * (C) 2007-09 - Luca Deri + * + * 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" + +#ifdef __FreeBSD__ + +void tun_close(tuntap_dev *device); + +/* ********************************** */ + +#define N2N_FREEBSD_TAPDEVICE_SIZE 32 +int tuntap_open(tuntap_dev *device /* ignored */, + char *dev, + const char *address_mode, /* static or dhcp */ + char *device_ip, + char *device_mask, + const char * device_mac, + int mtu) +{ + int i; + char tap_device[N2N_FREEBSD_TAPDEVICE_SIZE]; + + for (i = 0; i < 255; i++) { + snprintf(tap_device, sizeof(tap_device), "/dev/tap%d", i); + + device->fd = open(tap_device, O_RDWR); + if(device->fd > 0) { + traceEvent(TRACE_NORMAL, "Succesfully open %s", tap_device); + break; + } + } + + if(device->fd < 0) { + traceEvent(TRACE_ERROR, "Unable to open tap device"); + return(-1); + } else { + char buf[256]; + FILE *fd; + + device->ip_addr = inet_addr(device_ip); + + if ( device_mac && device_mac[0] != '\0' ) { + /* FIXME - This is not tested. Might be wrong syntax for OS X */ + + /* Set the hw address before bringing the if up. */ + snprintf(buf, sizeof(buf), "ifconfig tap%d ether %s", + i, device_mac); + system(buf); + } + + snprintf(buf, sizeof(buf), "ifconfig tap%d %s netmask %s mtu %d up", + i, device_ip, device_mask, mtu); + system(buf); + + traceEvent(TRACE_NORMAL, "Interface tap%d up and running (%s/%s)", + i, device_ip, device_mask); + + /* Read MAC address */ + + snprintf(buf, sizeof(buf), "ifconfig tap%d |grep ether|cut -c 8-24", i); + /* traceEvent(TRACE_INFO, "%s", buf); */ + + fd = popen(buf, "r"); + if(fd < 0) { + tun_close(device); + return(-1); + } else { + int a, b, c, d, e, f; + + buf[0] = 0; + fgets(buf, sizeof(buf), fd); + pclose(fd); + + if(buf[0] == '\0') { + traceEvent(TRACE_ERROR, "Unable to read tap%d interface MAC address"); + exit(0); + } + + traceEvent(TRACE_NORMAL, "Interface tap%d mac %s", i, buf); + if(sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", &a, &b, &c, &d, &e, &f) == 6) { + device->mac_addr[0] = a, device->mac_addr[1] = b; + device->mac_addr[2] = c, device->mac_addr[3] = d; + device->mac_addr[4] = e, device->mac_addr[5] = f; + } + } + } + + /* read_mac(dev, device->mac_addr); */ + 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) +{ +} + +#endif /* #ifdef __FreeBSD__ */ + diff --git a/tuntap_linux.c b/tuntap_linux.c new file mode 100644 index 0000000..2835195 --- /dev/null +++ b/tuntap_linux.c @@ -0,0 +1,158 @@ +/* + * (C) 2007-09 - Luca Deri + * + * 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.h" + +#ifdef __linux__ + +static void read_mac(char *ifname, n2n_mac_t mac_addr) { + int _sock, res; + struct ifreq ifr; + macstr_t mac_addr_buf; + + memset(&ifr, 0, sizeof(struct ifreq)); + + /* Dummy socket, just to make ioctls with */ + _sock = socket(PF_INET, SOCK_DGRAM, 0); + strcpy(ifr.ifr_name, ifname); + res = ioctl(_sock, SIOCGIFHWADDR, &ifr); + if (res < 0) { + perror("Get hw addr"); + } else + memcpy(mac_addr, ifr.ifr_ifru.ifru_hwaddr.sa_data, 6); + + traceEvent(TRACE_NORMAL, "Interface %s has MAC %s", ifname, macaddr_str(mac_addr_buf, mac_addr)); + close(_sock); +} + +/* ********************************** */ + +/** @brief Open and configure the TAP device for packet read/write. + * + * This routine creates the interface via the tuntap driver then uses ifconfig + * to configure address/mask and MTU. + * + * @param device - [inout] a device info holder object + * @param dev - user-defined name for the new iface, + * if NULL system will assign a name + * @param device_ip - address of iface + * @param device_mask - netmask for device_ip + * @param mtu - MTU for device_ip + * + * @return - negative value on error + * - non-negative file-descriptor on success + */ +int tuntap_open(tuntap_dev *device, char *dev, /* user-definable interface name, eg. edge0 */ +const char *address_mode, /* static or dhcp */ +char *device_ip, char *device_mask, const char * device_mac, int mtu) +{ + char *tuntap_device = "/dev/net/tun"; +#define N2N_LINUX_SYSTEMCMD_SIZE 128 + char buf[N2N_LINUX_SYSTEMCMD_SIZE]; + struct ifreq ifr; + int rc; + + device->fd = open(tuntap_device, O_RDWR); + if (device->fd < 0) { + printf("ERROR: ioctl() [%s][%d]\n", strerror(errno), errno); + return -1; + } + + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; /* Want a TAP device for layer 2 frames. */ + strncpy(ifr.ifr_name, dev, IFNAMSIZ); + rc = ioctl(device->fd, TUNSETIFF, (void *) &ifr); + + if (rc < 0) { + traceEvent(TRACE_ERROR, "ioctl() [%s][%d]\n", strerror(errno), rc); + close(device->fd); + return -1; + } + + /* Store the device name for later reuse */ + 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); + + device->ip_addr = inet_addr(device_ip); + device->device_mask = inet_addr(device_mask); + read_mac(dev, device->mac_addr); + 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; + 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. */ + + /* 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. */ + fread(buf, 1, 15, fp); + fclose(fp); + fp = NULL; + + traceEvent(TRACE_INFO, "ifconfig address = %s", buf); + + tuntap->ip_addr = inet_addr(buf); + } +} + +#endif /* #ifdef __linux__ */ + diff --git a/tuntap_netbsd.c b/tuntap_netbsd.c new file mode 100644 index 0000000..93a9f41 --- /dev/null +++ b/tuntap_netbsd.c @@ -0,0 +1,147 @@ +/* + * (C) 2007-09 - Luca Deri + * (C) 2009 - Alaric Snell-Pym + * + * 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" + +#ifdef __NetBSD__ + +#include +#include +#include + +void tun_close(tuntap_dev *device); + +/* ********************************** */ + +#define N2N_NETBSD_TAPDEVICE_SIZE 32 +int tuntap_open(tuntap_dev *device /* ignored */, + char *dev, + const char *address_mode, /* static or dhcp */ + char *device_ip, + char *device_mask, + const char * device_mac, + int mtu) +{ + char tap_device[N2N_NETBSD_TAPDEVICE_SIZE]; + struct ifreq req; + + 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); + } else { + device->fd = open("/dev/tap", O_RDWR); + if(device->fd >= 0) { + 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); + } else { + snprintf(tap_device, sizeof(tap_device), req.ifr_name); + } + } + } + + if(device->fd < 0) { + traceEvent(TRACE_ERROR, "Unable to open tap device (%s)", strerror(errno)); + return(-1); + } else { + char buf[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' ) { + /* Set the hw address before bringing the if up. */ + snprintf(buf, sizeof(buf), "ifconfig %s link %s active", + tap_device, device_mac); + system(buf); + } + + snprintf(buf, sizeof(buf), "ifconfig %s %s netmask %s mtu %d up", + tap_device, device_ip, device_mask, mtu); + system(buf); + + traceEvent(TRACE_NORMAL, "Interface %s up and running (%s/%s)", + tap_device, device_ip, device_mask); + + /* Read MAC address */ + + snprintf(buf, sizeof(buf), "ifconfig %s |grep address|cut -c 11-28", tap_device); + /* traceEvent(TRACE_INFO, "%s", buf); */ + + fd = popen(buf, "r"); + if(fd < 0) { + tun_close(device); + return(-1); + } else { + int a, b, c, d, e, f; + + 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); + exit(0); + } + + traceEvent(TRACE_NORMAL, "Interface %s mac %s", tap_device, buf); + if(sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", &a, &b, &c, &d, &e, &f) == 6) { + device->mac_addr[0] = a, device->mac_addr[1] = b; + device->mac_addr[2] = c, device->mac_addr[3] = d; + device->mac_addr[4] = e, device->mac_addr[5] = f; + } + } + } + + /* read_mac(dev, device->mac_addr); */ + 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) +{ +} + +#endif /* #ifdef __NetBSD__ */ + diff --git a/tuntap_osx.c b/tuntap_osx.c new file mode 100644 index 0000000..88587ed --- /dev/null +++ b/tuntap_osx.c @@ -0,0 +1,135 @@ +/* + * (C) 2007-09 - Luca Deri + * + * 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" + +#ifdef _DARWIN_ + +void tun_close(tuntap_dev *device); + +/* ********************************** */ + +#define N2N_OSX_TAPDEVICE_SIZE 32 +int tuntap_open(tuntap_dev *device /* ignored */, + char *dev, + const char *address_mode, /* static or dhcp */ + char *device_ip, + char *device_mask, + const char * device_mac, + int mtu) +{ + int i; + char tap_device[N2N_OSX_TAPDEVICE_SIZE]; + + for (i = 0; i < 255; i++) { + snprintf(tap_device, sizeof(tap_device), "/dev/tap%d", i); + + device->fd = open(tap_device, O_RDWR); + if(device->fd > 0) { + traceEvent(TRACE_NORMAL, "Succesfully open %s", tap_device); + break; + } + } + + if(device->fd < 0) { + traceEvent(TRACE_ERROR, "Unable to open tap device"); + return(-1); + } else { + char buf[256]; + FILE *fd; + + device->ip_addr = inet_addr(device_ip); + + if ( device_mac && device_mac[0] != '\0' ) { + /* FIXME - This is not tested. Might be wrong syntax for OS X */ + + /* Set the hw address before bringing the if up. */ + snprintf(buf, sizeof(buf), "ifconfig tap%d ether %s", + i, device_mac); + system(buf); + } + + snprintf(buf, sizeof(buf), "ifconfig tap%d %s netmask %s mtu %d up", + i, device_ip, device_mask, mtu); + system(buf); + + traceEvent(TRACE_NORMAL, "Interface tap%d up and running (%s/%s)", + i, device_ip, device_mask); + + /* Read MAC address */ + + snprintf(buf, sizeof(buf), "ifconfig tap%d |grep ether|cut -c 8-24", i); + /* traceEvent(TRACE_INFO, "%s", buf); */ + + fd = popen(buf, "r"); + if(fd < 0) { + tun_close(device); + return(-1); + } else { + int a, b, c, d, e, f; + + buf[0] = 0; + fgets(buf, sizeof(buf), fd); + pclose(fd); + + if(buf[0] == '\0') { + traceEvent(TRACE_ERROR, "Unable to read tap%d interface MAC address"); + exit(0); + } + + traceEvent(TRACE_NORMAL, "Interface tap%d [MTU %d] mac %s", i, mtu, buf); + if(sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", &a, &b, &c, &d, &e, &f) == 6) { + device->mac_addr[0] = a, device->mac_addr[1] = b; + device->mac_addr[2] = c, device->mac_addr[3] = d; + device->mac_addr[4] = e, device->mac_addr[5] = f; + } + } + } + + /* read_mac(dev, device->mac_addr); */ + 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) +{ +} + +#endif /* _DARWIN_ */ + diff --git a/n2n_v2/twofish.c b/twofish.c similarity index 100% rename from n2n_v2/twofish.c rename to twofish.c diff --git a/n2n_v2/twofish.h b/twofish.h similarity index 100% rename from n2n_v2/twofish.h rename to twofish.h diff --git a/version.c b/version.c new file mode 100644 index 0000000..36c88d7 --- /dev/null +++ b/version.c @@ -0,0 +1,3 @@ +const char * n2n_sw_version = N2N_VERSION; +const char * n2n_sw_osName = N2N_OSNAME; +const char * n2n_sw_buildDate = __DATE__ " " __TIME__; diff --git a/n2n_v2/win32/CMakeLists.txt b/win32/CMakeLists.txt similarity index 83% rename from n2n_v2/win32/CMakeLists.txt rename to win32/CMakeLists.txt index 8fb7511..ae2becc 100644 --- a/n2n_v2/win32/CMakeLists.txt +++ b/win32/CMakeLists.txt @@ -2,5 +2,5 @@ add_library(n2n_win32 getopt1.c getopt.c wintap.c - n2n_win32.c) + n2n_win32.c) target_link_libraries(n2n_win32 ws2_32) diff --git a/n2n_v2/win32/DotNet/n2n.sln b/win32/DotNet/n2n.sln similarity index 100% rename from n2n_v2/win32/DotNet/n2n.sln rename to win32/DotNet/n2n.sln diff --git a/n2n_v1/win32/DotNet/n2n.suo b/win32/DotNet/n2n.suo similarity index 100% rename from n2n_v1/win32/DotNet/n2n.suo rename to win32/DotNet/n2n.suo diff --git a/n2n_v2/win32/DotNet/n2n.vcproj b/win32/DotNet/n2n.vcproj similarity index 100% rename from n2n_v2/win32/DotNet/n2n.vcproj rename to win32/DotNet/n2n.vcproj diff --git a/n2n_v2/win32/DotNet/supernode.vcproj b/win32/DotNet/supernode.vcproj similarity index 100% rename from n2n_v2/win32/DotNet/supernode.vcproj rename to win32/DotNet/supernode.vcproj diff --git a/n2n_v1/win32/getopt.c b/win32/getopt.c similarity index 96% rename from n2n_v1/win32/getopt.c rename to win32/getopt.c index c938ea3..5b7bc1f 100644 --- a/n2n_v1/win32/getopt.c +++ b/win32/getopt.c @@ -20,7 +20,7 @@ License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - + /* This tells Alpha OSF/1 not to define a getopt prototype in . Ditto for AIX 3.2 and . */ #ifndef _NO_PROTO @@ -203,7 +203,7 @@ static enum /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; - + #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. @@ -255,7 +255,7 @@ extern int strlen (const char *); #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ - + /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have @@ -468,7 +468,7 @@ _getopt_initialize (argc, argv, optstring) return optstring; } - + /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. @@ -999,7 +999,7 @@ getopt____ (argc, argv, optstring) } #endif /* Not ELIDE_CODE. */ - + #ifdef TEST /* Compile with -DTEST to make an executable for use in testing diff --git a/n2n_v1/win32/getopt.h b/win32/getopt.h similarity index 100% rename from n2n_v1/win32/getopt.h rename to win32/getopt.h diff --git a/n2n_v1/win32/getopt1.c b/win32/getopt1.c similarity index 100% rename from n2n_v1/win32/getopt1.c rename to win32/getopt1.c diff --git a/win32/n2n_win32.c b/win32/n2n_win32.c new file mode 100644 index 0000000..16445a6 --- /dev/null +++ b/win32/n2n_win32.c @@ -0,0 +1,18 @@ +/* + * win32 compile fix 05/01/2011 Dominik Meyer + */ + +#include "n2n_win32.h" + +int gettimeofday (struct timeval *tv, void* tz) +{ + union { + long long ns100; /*time since 1 Jan 1601 in 100ns units */ + FILETIME ft; + } now; + + GetSystemTimeAsFileTime (&now.ft); + tv->tv_usec = (long) ((now.ns100 / 10LL) % 1000000LL); + tv->tv_sec = (long) ((now.ns100 - 116444736000000000LL) / 10000000LL); + return (0); +}; diff --git a/n2n_v2/win32/n2n_win32.h b/win32/n2n_win32.h similarity index 62% rename from n2n_v2/win32/n2n_win32.h rename to win32/n2n_win32.h index 5423a6d..2bbccef 100644 --- a/n2n_v2/win32/n2n_win32.h +++ b/win32/n2n_win32.h @@ -1,8 +1,8 @@ /* - (C) 2007-09 - Luca Deri + (C) 2007-09 - Luca Deri -*/ + */ #ifndef _N2N_WIN32_H_ #define _N2N_WIN32_H_ @@ -21,7 +21,6 @@ #include #include - #include "wintap.h" #ifdef _MSC_VER @@ -49,7 +48,6 @@ typedef int ssize_t; typedef unsigned long in_addr_t; - //#define EAFNOSUPPORT WSAEAFNOSUPPORT #define MAX(a,b) (a > b ? a : b) #define MIN(a,b) (a < b ? a : b) @@ -63,11 +61,10 @@ typedef unsigned long in_addr_t; /* * Structure of a 10Mb/s Ethernet header. */ -struct ether_hdr -{ - uint8_t dhost[ETH_ADDR_LEN]; - uint8_t shost[ETH_ADDR_LEN]; - uint16_t type; /* higher layer protocol encapsulated */ +struct ether_hdr { + uint8_t dhost[ETH_ADDR_LEN]; + uint8_t shost[ETH_ADDR_LEN]; + uint16_t type; /* higher layer protocol encapsulated */ }; typedef struct ether_hdr ether_hdr_t; @@ -76,40 +73,39 @@ typedef struct ether_hdr ether_hdr_t; struct ip { #if BYTE_ORDER == LITTLE_ENDIAN - u_char ip_hl:4, /* header length */ - ip_v:4; /* version */ + u_char ip_hl :4, /* header length */ + ip_v :4; /* version */ #else - u_char ip_v:4, /* version */ - ip_hl:4; /* header length */ + u_char ip_v:4, /* version */ + ip_hl:4; /* header length */ #endif - u_char ip_tos; /* type of service */ - short ip_len; /* total length */ - u_short ip_id; /* identification */ - short ip_off; /* fragment offset field */ + u_char ip_tos; /* type of service */ + short ip_len; /* total length */ + u_short ip_id; /* identification */ + short ip_off; /* fragment offset field */ #define IP_DF 0x4000 /* dont fragment flag */ #define IP_MF 0x2000 /* more fragments flag */ #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ - u_char ip_ttl; /* time to live */ - u_char ip_p; /* protocol */ - u_short ip_sum; /* checksum */ - struct in_addr ip_src,ip_dst; /* source and dest address */ + u_char ip_ttl; /* time to live */ + u_char ip_p; /* protocol */ + u_short ip_sum; /* checksum */ + struct in_addr ip_src, ip_dst; /* source and dest address */ }; - /* ************************************* */ typedef struct tuntap_dev { - HANDLE device_handle; - char *device_name; - char *ifName; - OVERLAPPED overlap_read, overlap_write; - uint8_t mac_addr[6]; - uint32_t ip_addr, device_mask; - unsigned int mtu; + HANDLE device_handle; + char *device_name; + char *ifName; + OVERLAPPED overlap_read, overlap_write; + uint8_t mac_addr[6]; + uint32_t ip_addr, device_mask; + unsigned int mtu; } tuntap_dev; #define index(a, b) strchr(a, b) -int gettimeofday (struct timeval *tv, void* tz); +int gettimeofday(struct timeval *tv, void* tz); #endif diff --git a/n2n_v2/win32/version-msvc.c b/win32/version-msvc.c similarity index 100% rename from n2n_v2/win32/version-msvc.c rename to win32/version-msvc.c diff --git a/win32/wintap.c b/win32/wintap.c new file mode 100644 index 0000000..ea48bab --- /dev/null +++ b/win32/wintap.c @@ -0,0 +1,307 @@ +/* + (C) 2007-09 - Luca Deri + */ + +#include "../n2n.h" +#include "n2n_win32.h" + +/* 1500 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */ +#define MTU 1518 + +void initWin32() { + WSADATA wsaData; + int err; + + err = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (err != 0) { + /* Tell the user that we could not find a usable */ + /* WinSock DLL. */ + printf("FATAL ERROR: unable to initialise Winsock 2.x."); + exit(-1); + } +} + +int open_wintap(struct tuntap_dev *device, const char * address_mode, /* "static" or "dhcp" */ +char *device_ip, char *device_mask, const char *device_mac, int mtu) +{ + HKEY key, key2; + LONG rc; + char regpath[1024], cmd[256]; + char adapterid[1024]; + char adaptername[1024]; + char tapname[1024]; + long len; + int found = 0; + int err, i; + ULONG status = TRUE; + + memset(device, 0, sizeof(struct tuntap_dev)); + device->device_handle = INVALID_HANDLE_VALUE; + device->device_name = NULL; + device->ifName = NULL; + device->ip_addr = inet_addr(device_ip); + + /* Open registry and look for network adapters */ + if ((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, + KEY_READ, &key))) { + printf("Unable to read registry: [rc=%d]\n", rc); + exit(-1); + /* MSVC Note: If you keep getting rc=2 errors, make sure you set: + Project -> Properties -> Configuration Properties -> General -> Character set + to: "Use Multi-Byte Character Set" + */ + } + + for (i = 0;; i++) { + len = sizeof(adapterid); + if (RegEnumKeyEx(key, i, (LPTSTR) adapterid, &len, 0, 0, 0, NULL)) + break; + + /* Find out more about this adapter */ + + _snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", + NETWORK_CONNECTIONS_KEY, adapterid); + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR) regpath, 0, KEY_READ, + &key2)) + continue; + + len = sizeof(adaptername); + err = RegQueryValueEx(key2, "Name", 0, 0, adaptername, &len); + + RegCloseKey(key2); + + if (err) + continue; + + if (device->device_name) { + if (!strcmp(device->device_name, adapterid)) { + found = 1; + break; + } else + continue; + } + + if (device->ifName) { + if (!strcmp(device->ifName, adaptername)) { + found = 1; + break; + } else + continue; + } + + _snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, + adapterid); + device->device_handle = CreateFile(tapname, + GENERIC_WRITE | GENERIC_READ, 0, /* Don't let other processes share or open + the resource until the handle's been closed */ + 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, + 0); + if (device->device_handle != INVALID_HANDLE_VALUE) { + found = 1; + break; + } + } + + RegCloseKey(key); + + if (!found) { + printf("No Windows tap device found!\n"); + exit(0); + } + + /* ************************************** */ + + if (!device->device_name) + device->device_name = _strdup(adapterid); + + if (!device->ifName) + device->ifName = _strdup(adaptername); + + /* Try to open the corresponding tap device->device_name */ + + if (device->device_handle == INVALID_HANDLE_VALUE) { + _snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, + device->device_name); + device->device_handle = CreateFile(tapname, + GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, + FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0); + } + + if (device->device_handle == INVALID_HANDLE_VALUE) { + printf("%s (%s) is not a usable Windows tap device\n", + device->device_name, device->ifName); + exit(-1); + } + + /* Get MAC address from tap device->device_name */ + + if (!DeviceIoControl(device->device_handle, TAP_IOCTL_GET_MAC, + device->mac_addr, sizeof(device->mac_addr), device->mac_addr, + sizeof(device->mac_addr), &len, 0)) { + printf("Could not get MAC address from Windows tap %s (%s)\n", + device->device_name, device->ifName); + return -1; + } + + device->mtu = mtu; + + printf( + "Open device [name=%s][ip=%s][ifName=%s][MTU=%d][mac=%02X:%02X:%02X:%02X:%02X:%02X]\n", + device->device_name, device_ip, device->ifName, device->mtu, + device->mac_addr[0] & 0xFF, device->mac_addr[1] & 0xFF, + device->mac_addr[2] & 0xFF, device->mac_addr[3] & 0xFF, + device->mac_addr[4] & 0xFF, device->mac_addr[5] & 0xFF); + + /* ****************** */ + + printf("Setting %s device address...\n", device->ifName); + + if (0 == strcmp("dhcp", address_mode)) { + _snprintf(cmd, sizeof(cmd), + "netsh interface ip set address \"%s\" dhcp", device->ifName); + } else { + _snprintf(cmd, sizeof(cmd), + "netsh interface ip set address \"%s\" static %s %s", + device->ifName, device_ip, device_mask); + } + + if (system(cmd) == 0) { + device->ip_addr = inet_addr(device_ip); + device->device_mask = inet_addr(device_mask); + printf("Device %s set to %s/%s\n", device->ifName, device_ip, + device_mask); + } else + printf("WARNING: Unable to set device %s IP address [%s]\n", + device->ifName, cmd); + + /* ****************** */ + + if (device->mtu != DEFAULT_MTU + ) + printf("WARNING: MTU set is not supported on Windows\n"); + + /* set driver media status to 'connected' (i.e. set the interface up) */ + if (!DeviceIoControl(device->device_handle, TAP_IOCTL_SET_MEDIA_STATUS, + &status, sizeof(status), &status, sizeof(status), &len, NULL)) + printf("WARNING: Unable to enable TAP adapter\n"); + + /* + * Initialize overlapped structures + */ + device->overlap_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + device->overlap_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!device->overlap_read.hEvent || !device->overlap_write.hEvent) { + return -1; + } + + return (0); +} + +/* ************************************************ */ + +int tuntap_read(struct tuntap_dev *tuntap, unsigned char *buf, int len) +{ + DWORD read_size, last_err; + + ResetEvent(tuntap->overlap_read.hEvent); + if (ReadFile(tuntap->device_handle, buf, len, &read_size, + &tuntap->overlap_read)) { + //printf("tun_read(len=%d)\n", read_size); + return read_size; + } + switch (last_err = GetLastError()) { + case ERROR_IO_PENDING: + WaitForSingleObject(tuntap->overlap_read.hEvent, INFINITE); + GetOverlappedResult(tuntap->device_handle, &tuntap->overlap_read, + &read_size, FALSE); + return read_size; + break; + default: + printf("GetLastError() returned %d\n", last_err); + break; + } + + return -1; +} +/* ************************************************ */ + +int tuntap_write(struct tuntap_dev *tuntap, unsigned char *buf, int len) +{ + DWORD write_size; + + //printf("tun_write(len=%d)\n", len); + + ResetEvent(tuntap->overlap_write.hEvent); + if (WriteFile(tuntap->device_handle, buf, len, &write_size, + &tuntap->overlap_write)) { + //printf("DONE tun_write(len=%d)\n", write_size); + return write_size; + } + switch (GetLastError()) { + case ERROR_IO_PENDING: + WaitForSingleObject(tuntap->overlap_write.hEvent, INFINITE); + GetOverlappedResult(tuntap->device_handle, &tuntap->overlap_write, + &write_size, FALSE); + return write_size; + break; + default: + break; + } + + return -1; +} + +/* ************************************************ */ + +int tuntap_open(struct tuntap_dev *device, char *dev, const char *address_mode, /* static or dhcp */ +char *device_ip, char *device_mask, const char * device_mac, int mtu) +{ + return (open_wintap(device, address_mode, device_ip, device_mask, + device_mac, mtu)); +} + +/* ************************************************ */ + +void tuntap_close(struct tuntap_dev *tuntap) +{ + CloseHandle(tuntap->device_handle); +} + +/* Fill out the ip_addr value from the interface. Called to pick up dynamic + * address changes. */ +void tuntap_get_address(struct tuntap_dev *tuntap) +{ +} + +/* ************************************************ */ + +#if 0 +int main(int argc, char* argv[]) +{ + struct tuntap_dev tuntap; + int i; + int mtu = 1400; + + printf("Welcome to n2n\n"); + initWin32(); + open_wintap(&tuntap, "static", "1.2.3.20", "255.255.255.0", mtu); + + for(i=0; i<10; i++) { + u_char buf[MTU]; + int rc; + + rc = tun_read(&tuntap, buf, sizeof(buf)); + buf[0]=2; + buf[1]=3; + buf[2]=4; + + printf("tun_read returned %d\n", rc); + rc = tun_write(&tuntap, buf, rc); + printf("tun_write returned %d\n", rc); + } + // rc = tun_open (device->device_name, IF_MODE_TUN); + WSACleanup (); + return(0); +} + +#endif diff --git a/n2n_v2/win32/wintap.h b/win32/wintap.h similarity index 94% rename from n2n_v2/win32/wintap.h rename to win32/wintap.h index 0eef8f0..20d5f71 100644 --- a/n2n_v2/win32/wintap.h +++ b/win32/wintap.h @@ -1,6 +1,6 @@ /* - (C) 2007 - Luca Deri -*/ + (C) 2007 - Luca Deri + */ #ifndef _WINTAP_H_ #define _WINTAP_H_ @@ -13,8 +13,6 @@ #include #include - - //=============================================== // This file is included both by OpenVPN and // the TAP-Win32 driver and contains definitions @@ -64,4 +62,4 @@ extern void initWin32(); -#endif \ No newline at end of file +#endif diff --git a/wire.c b/wire.c new file mode 100644 index 0000000..87e5c7a --- /dev/null +++ b/wire.c @@ -0,0 +1,265 @@ +/* (c) 2009 Richard Andrews */ + +/** Routines for encoding and decoding n2n packets on the wire. + * + * encode_X(base,idx,v) prototypes are inspired by the erlang internal + * encoding model. Passing the start of a buffer in base and a pointer to an + * integer (initially set to zero). Each encode routine increases idx by the + * amount written and returns the amount written. In this way complex sequences + * of encodings can be represented cleanly. See encode_register() for an + * example. + */ + +#include "n2n_wire.h" +#include + +int encode_uint8(uint8_t * base, size_t * idx, const uint8_t v) +{ + *(base + (*idx)) = (v & 0xff); + ++(*idx); + return 1; +} + +int decode_uint8(const uint8_t * base, size_t * idx, size_t * rem, + uint8_t * out) +{ + if (*rem < 1) { + return 0; + } + + *out = (base[*idx] & 0xff ); + ++(*idx); + --(*rem); + return 1; +} + +int encode_uint16(uint8_t * base, size_t * idx, const uint16_t v) +{ + *(base + (*idx)) = (v >> 8) & 0xff; + *(base + (1 + *idx)) = (v & 0xff ); + *idx += 2; + return 2; +} + +int decode_uint16(const uint8_t * base, size_t * idx, size_t * rem, + uint16_t * out) +{ + if (*rem < 2) { + return 0; + } + + *out = (base[*idx] & 0xff) << 8; + *out |= (base[1 + *idx] & 0xff ); + *idx += 2; + *rem -= 2; + return 2; +} + +int encode_uint32(uint8_t * base, size_t * idx, const uint32_t v) +{ + *(base + (0 + *idx)) = (v >> 24) & 0xff; + *(base + (1 + *idx)) = (v >> 16) & 0xff; + *(base + (2 + *idx)) = (v >> 8) & 0xff; + *(base + (3 + *idx)) = (v & 0xff ); + *idx += 4; + return 4; +} + +int decode_uint32(const uint8_t * base, size_t * idx, size_t * rem, + uint32_t * out) +{ + if (*rem < 4) { + return 0; + } + + *out = (base[0 + *idx] & 0xff) << 24; + *out |= (base[1 + *idx] & 0xff) << 16; + *out |= (base[2 + *idx] & 0xff) << 8; + *out |= (base[3 + *idx] & 0xff ); + *idx += 4; + *rem -= 4; + return 4; +} + +int encode_buf(uint8_t * base, size_t * idx, const void * p, size_t s) +{ + memcpy((base + (*idx)), p, s ); + *idx += s; + return s; +} + +/* Copy from base to out of size bufsize */ +int decode_buf(const uint8_t * base, size_t * idx, size_t * rem, + uint8_t * out, size_t bufsize) +{ + if (*rem < bufsize) { + return 0; + } + + memcpy(out, (base + *idx), bufsize ); + *idx += bufsize; + *rem -= bufsize; + return bufsize; +} + +int encode_mac(uint8_t * base, size_t * idx, const n2n_mac_t m) +{ + return encode_buf(base, idx, m, N2N_MAC_SIZE); +} + +int decode_mac(const uint8_t * base, size_t * idx, size_t * rem, + uint8_t * out /* of size N2N_MAC_SIZE. This clearer than passing a + n2n_mac_t */ ) +{ + return decode_buf(base, idx, rem, out, N2N_MAC_SIZE); +} + +int encode_ip(uint8_t * base, size_t * idx, const n2n_ip_t ip) +{ + /* TODO: IPV6 */ + return encode_buf(base, idx, ip, IPV4_SIZE); +} + +int decode_ip(const uint8_t * base, size_t * idx, size_t * rem, + n2n_ip_t ip) +{ + /* TODO: IPV6 */ + return decode_buf(base, idx, rem, ip, IPV4_SIZE); +} + +int encode_sock(uint8_t * base, size_t * idx, const n2n_sock_t * sock) +{ + int retval = 0; + uint16_t f; + + switch (sock->family) { + case AF_INET: + { + f = 0; + retval += encode_uint16(base, idx, f); + retval += encode_uint16(base, idx, sock->port); + retval += encode_buf(base, idx, sock->addr.v4, IPV4_SIZE); + break; + } + case AF_INET6: + { + f = 0x8000; + retval += encode_uint16(base, idx, f); + retval += encode_uint16(base, idx, sock->port); + retval += encode_buf(base, idx, sock->addr.v6, IPV6_SIZE); + break; + } + default: + retval = -1; + } + + return retval; +} + +int decode_sock(const uint8_t * base, size_t * idx, size_t * rem, + n2n_sock_t * sock) +{ + size_t * idx0 = idx; + uint16_t f; + + decode_uint16(base, idx, rem, &f); + + if (f & 0x8000) { + /* IPv6 */ + sock->family = AF_INET6; + decode_uint16(base, idx, rem, &(sock->port)); + decode_buf(base, idx, rem, sock->addr.v6, IPV6_SIZE); + } else { + /* IPv4 */ + sock->family = AF_INET; + decode_uint16(base, idx, rem, &(sock->port)); + memset(sock->addr.v6, 0, IPV6_SIZE); /* so memcmp() works for equality. */ + decode_buf(base, idx, rem, sock->addr.v4, IPV4_SIZE); + } + + return (idx - idx0); +} + +int encode_supernode_register(uint8_t * base, size_t * idx, + int ack, const n2n_supernode_register_t * reg) +{ + int retval = 0; + if (!ack) { + retval += encode_mac(base, idx, reg->syn.a_mac); + retval += encode_ip(base, idx, reg->syn.a_n2n_ip); + } else { + retval += encode_sock(base, idx, ®->ack.a_pub_sock); + } + return retval; +} + +int decode_supernode_register(const uint8_t * base, size_t * idx, size_t * rem, + int ack, n2n_supernode_register_t * reg) +{ + int retval = 0; + if(!ack) { + retval += decode_mac(base, idx, rem, reg->syn.a_mac); + retval += decode_ip(base, idx, rem, reg->syn.a_n2n_ip); + } else { + retval += decode_sock(base, idx, rem, ®->ack.a_pub_sock); + } + return retval; +} + +int fill_sockaddr(struct sockaddr * addr, size_t addrlen, + const n2n_sock_t * sock) +{ + int retval = -1; + + if (AF_INET == sock->family) { + if (addrlen >= sizeof(struct sockaddr_in)) { + struct sockaddr_in * si = (struct sockaddr_in *) addr; + si->sin_family = sock->family; + si->sin_port = htons(sock->port); + memcpy(&(si->sin_addr.s_addr), sock->addr.v4, IPV4_SIZE); + retval = 0; + } + } + + return retval; +} + +int encode_HEADER(uint8_t * base, size_t * idx, const n2n_HEADER_t *hdr) +{ + encode_uint8(base, idx, N2N_MAJOR_VERSION); + encode_uint8(base, idx, N2N_MINOR_VERSION); + encode_uint8(base, idx, hdr->pc); + encode_uint8(base, idx, hdr->flags); + return 0; +} + +int decode_HEADER(const uint8_t * base, size_t * idx, size_t * rem, + n2n_HEADER_t * hdr) +{ + uint8_t major_version, minor_version; + decode_uint8(base, idx, rem, &major_version); + decode_uint8(base, idx, rem, &minor_version); + if(major_version != N2N_MAJOR_VERSION || + minor_version != N2N_MINOR_VERSION) { + /* error: version missmatch */ + return 1; + } + decode_uint8(base, idx, rem, (uint8_t *) &hdr->pc); + decode_uint8(base, idx, rem, (uint8_t *) &hdr->flags); + return 0; +} + + +void decode_ETHFRAMEHDR(const uint8_t * base, n2n_ETHFRAMEHDR_t * eth) +{ + memcpy(eth->dstMac, base, N2N_MAC_SIZE); + base += N2N_MAC_SIZE; + memcpy(eth->srcMac, base, N2N_MAC_SIZE); +} + +int copy_ETHFRAMEHDR(uint8_t * base, uint8_t * pkt) +{ + memcpy(base, pkt, ETH_FRAMEHDRSIZE); + return ETH_FRAMEHDRSIZE; +} +