Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Refactoring and added root tests to check TUN device functionality.

  • Loading branch information...
commit be0561f9a15f1c548c62771ddecac83d1cdcedcd 1 parent 53df63c
Caleb James DeLisle authored
Showing with 1,477 additions and 577 deletions.
  1. +1 −1  admin/angel/Core.c
  2. +56 −0 cmake/modules/HasRoot.cmake
  3. +48 −9 cmake/modules/RemoteTest.cmake
  4. +12 −5 cmake/modules/Test.cmake
  5. +3 −1 interface/CMakeLists.txt
  6. +1 −1  interface/ETHInterface.h
  7. +50 −99 interface/ETHInterface_Linux.c
  8. +1 −1  interface/ETHInterface_admin.c
  9. +1 −1  interface/ETHInterface_admin.h
  10. +15 −29 {net → interface}/InterfaceController.h
  11. +199 −0 interface/MultiInterface.c
  12. +45 −0 interface/MultiInterface.h
  13. +28 −6 interface/TUNConfigurator.h
  14. +17 −8 interface/TUNConfigurator_FreeBSD.c
  15. +18 −9 interface/TUNConfigurator_Illumos.c
  16. +67 −9 interface/TUNConfigurator_Linux.c
  17. +17 −8 interface/TUNConfigurator_OSX.c
  18. +17 −8 interface/TUNConfigurator_OpenBSD.c
  19. +14 −5 interface/TUNConfigurator_W32.c
  20. +46 −79 interface/TUNInterface.c
  21. +17 −2 interface/TUNInterface.h
  22. +31 −87 interface/UDPInterface.c
  23. +3 −4 interface/UDPInterface.h
  24. +1 −1  interface/UDPInterface_admin.c
  25. +1 −1  interface/UDPInterface_admin.h
  26. +11 −6 interface/UDPInterface_pvt.h
  27. +5 −0 interface/test/CMakeLists.txt
  28. +117 −0 interface/test/MultiInterface_test.c
  29. +134 −0 interface/test/TUNInterface_ipv4_root_test.c
  30. +133 −0 interface/test/TUNInterface_ipv6_root_test.c
  31. +8 −4 interface/test/UDPInterface_communication_test.c
  32. +7 −20 interface/test/UDPInterface_test.c
  33. +38 −130 net/DefaultInterfaceController.c
  34. +2 −1  net/DefaultInterfaceController.h
  35. +17 −4 net/Ducttape.c
  36. +2 −9 net/test/DefaultInterfaceController_test.c
  37. +9 −11 test/TestFramework.c
  38. +2 −0  test/TestFramework.h
  39. +6 −1 test/threeNodes_test.c
  40. +6 −0 test/twoNodes_test.c
  41. +8 −0 tunnel/IpTunnel.c
  42. +3 −0  tunnel/test/IpTunnel_test.c
  43. +1 −0  util/CMakeLists.txt
  44. +38 −17 util/Map.h
  45. +39 −0 util/events/Event.h
  46. +1 −0  util/events/libevent/CMakeLists.txt
  47. +77 −0 util/events/libevent/Event.c
  48. +17 −0 util/platform/CMakeLists.txt
  49. +21 −0 util/platform/Socket.c
  50. +26 −0 util/platform/Socket.h
  51. +24 −0 wire/Ethernet.h
  52. +16 −0 wire/Message.h
View
2  admin/angel/Core.c
@@ -169,7 +169,7 @@ void Core_initTunnel(String* desiredDeviceName,
//Ducttape_setUserInterface(dt, &icmp->internal);
Ducttape_setUserInterface(dt, &tun->iface);
- TUNConfigurator_setIpAddress(assignedTunName, ipAddr, addressPrefix, logger, eh);
+ TUNConfigurator_addIp6Address(assignedTunName, ipAddr, addressPrefix, logger, eh);
TUNConfigurator_setMTU(assignedTunName, DEFAULT_MTU, logger, eh);
}
View
56 cmake/modules/HasRoot.cmake
@@ -0,0 +1,56 @@
+# You may redistribute this program 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 <http://www.gnu.org/licenses/>.
+if (NOT HasRoot_CMAKE)
+
+set(content "
+ #ifdef WIN32
+ #include <windows.h>
+ #include <string.h>
+ int main()
+ {
+ char buff[32] = {0};
+ DWORD length = 32;
+ GetUserNameA(buff, &length);
+ printf(\"%s\\n\", buff);
+ return strcmp(\"Administrator\", buff);
+ }
+ #else
+ #include <unistd.h>
+ int main()
+ {
+ return getuid();
+ }
+ #endif
+")
+
+file(WRITE ${CMAKE_BINARY_DIR}/HasRoot.c "${content}")
+RemoteTest_tryRun(runRes compRes ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/HasRoot.c
+ COMPILE_OUTPUT_VARIABLE compileOut
+ RUN_OUTPUT_VARIABLE output
+)
+if (NOT compRes)
+ message("${compileOut}")
+ message(FATAL_ERROR "Compilation failed")
+endif()
+if ("${runRes}" STREQUAL "PLEASE_FILL_OUT-FAILED_TO_RUN")
+ message(FATAL_ERROR "RunFailed")
+endif()
+if (NOT runRes)
+ set(HasRoot TRUE CACHE INTERNAL "")
+ message("Testing with root access, root tests enabled")
+else()
+ set(HasRoot FALSE CACHE INTERNAL "")
+ message("Testing without root access, root tests disabled")
+endif()
+
+set(HasRoot_CMAKE TRUE CACHE INTERNAL "")
+endif()
View
57 cmake/modules/RemoteTest.cmake
@@ -9,15 +9,40 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-if (NOT REMOTE_TEST)
-set(REMOTE_TEST TRUE)
-file(READ ${CMAKE_SOURCE_DIR}/cmake/modules/RemoteTestTemplate.bash template)
-string(REPLACE "__REMOTE_TEST_IP_PORT__" "${REMOTE_TEST_IP_PORT}" FILE_CONTENT "${template}")
-set(template FALSE)
+if (CMAKE_CROSSCOMPILING AND REMOTE_TEST_IP_PORT)
+ file(READ ${CMAKE_SOURCE_DIR}/cmake/modules/RemoteTestTemplate.bash template)
+ string(REPLACE "__REMOTE_TEST_IP_PORT__" "${REMOTE_TEST_IP_PORT}" FILE_CONTENT "${template}")
+ # try_run(RUN_RESULT_VAR COMPILE_RESULT_VAR
+ # bindir srcfile [CMAKE_FLAGS <Flags>]
+ # [COMPILE_DEFINITIONS <flags>]
+ # [COMPILE_OUTPUT_VARIABLE comp]
+ # [RUN_OUTPUT_VARIABLE run]
+ # [OUTPUT_VARIABLE var]
+ # [ARGS <arg1> <arg2>...])
+ function(RemoteTest_tryRun RUN_RESULT COMPILE_RESULT bindir srcfile)
+ set(params "")
+ foreach(i RANGE ${ARGC})
+ list(APPEND params ${ARGV${i}})
+ endforeach()
+ string(RANDOM rand)
+ set(execFile ${CMAKE_CURRENT_BINARY_DIR}/${rand}_remote_executable)
+ try_compile(${COMPILE_RESULT} ${bindir} ${srcfile} COPY_FILE ${execFile})
+
+ message("Running remote test: ${execFile}_remote.sh")
+ string(REPLACE "__TEST_FILE__" "${execFile}" fileContent "${FILE_CONTENT}")
+ file(WRITE "${execFile}_remote.sh" "${fileContent}")
+ execute_process(COMMAND chmod "a+x" ${execFile}_remote.sh)
+ execute_process(COMMAND ${execFile}_remote.sh
+ RESULT_VARIABLE runResult
+ OUTPUT_VARIABLE output
+ )
+ set(${RUN_RESULT} ${runResult} PARENT_SCOPE)
+ set(${RUN_OUTPUT_VARIABLE} ${output} PARENT_SCOPE)
+
+ endfunction()
-if (REMOTE_TEST_IP_PORT)
function(remoteTest executable)
string(REPLACE "__TEST_FILE__" "${CMAKE_CURRENT_BINARY_DIR}/${executable}${CMAKE_EXECUTABLE_SUFFIX}" fileContent "${FILE_CONTENT}")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${executable}_remote.sh "${fileContent}")
@@ -27,10 +52,24 @@ if (REMOTE_TEST_IP_PORT)
add_test(${executable} ${CMAKE_CURRENT_BINARY_DIR}/${executable}_remote.sh)
message(" Running test remotely")
endFunction()
-else()
- function(remoteTest executable)
+elseif(CMAKE_CROSSCOMPILING)
+ function(RemoteTest_addTest executable)
message(" REMOTE_TEST_IP_PORT unspecified, skipping test.")
endfunction()
-endif()
+ function(RemoteTest_tryRun)
+ message(FATAL_ERROR "REMOTE_TEST_IP_PORT unspecified.")
+ endfunction()
+else()
+ function(RemoteTest_addTest executable)
+ add_test(${executable} ${executable})
+ endfunction()
+
+ function(RemoteTest_tryRun)
+ set(params "")
+ foreach(i RANGE ${ARGC})
+ list(APPEND params ${ARGV${i}})
+ endforeach()
+ try_run(${params})
+ endfunction()
endif()
View
17 cmake/modules/Test.cmake
@@ -10,21 +10,28 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
include(${CMAKE_SOURCE_DIR}/cmake/modules/RemoteTest.cmake)
+include(${CMAKE_SOURCE_DIR}/cmake/modules/HasRoot.cmake)
string(REGEX REPLACE "^.*/" "" main_dir_name ${CMAKE_SOURCE_DIR})
string(REPLACE ${CMAKE_SOURCE_DIR} ${main_dir_name} this_dir ${CMAKE_CURRENT_SOURCE_DIR})
message("-- Tests to run for " ${this_dir})
add_definitions(-g -DTEST)
-foreach(test_source ${Test_FILES})
+function(Test_process test_source isRootTest)
string(REPLACE "test.c" "test" test_bin ${test_source})
message(" " ${test_source})
add_executable(${test_bin} ${test_source})
target_link_libraries(${test_bin} ${Test_LIBRARIES})
- if (CMAKE_CROSSCOMPILING)
- remoteTest(${test_bin})
- else()
- add_test(${test_bin} ${test_bin})
+ if (NOT isRootTest OR HasRoot)
+ RemoteTest_addTest(${test_bin})
endif()
+endfunction()
+
+foreach(test_source ${Test_FILES})
+ Test_process(${test_source} FALSE)
endforeach()
+foreach(test_source ${Test_ROOT_FILES})
+ Test_process(${test_source} TRUE)
+endforeach()
+
message("")
View
4 interface/CMakeLists.txt
@@ -32,12 +32,14 @@ add_library(interface
InterfaceConnector.c
SessionManager.c
ICMP6Generator.c
+ MultiInterface.c
)
target_link_libraries(interface
util
cjdns-crypto-key
- ${LIBEVENT2_LIBRARIES}
+ cjdns-util-events-libevent
+ cjdns-util-platform-socket
)
add_library(cjdns-interface-pipeinterface
View
2  interface/ETHInterface.h
@@ -17,7 +17,7 @@
#include "util/events/EventBase.h"
#include "interface/Interface.h"
-#include "net/InterfaceController.h"
+#include "interface/InterfaceController.h"
#include "util/log/Log.h"
#include "memory/Allocator.h"
View
149 interface/ETHInterface_Linux.c
@@ -17,24 +17,24 @@
#include "interface/Interface.h"
#include "interface/ETHInterface.h"
#include "memory/Allocator.h"
-#include "net/InterfaceController.h"
+#include "interface/InterfaceController.h"
+#include "interface/MultiInterface.h"
#include "wire/Headers.h"
#include "wire/Message.h"
#include "wire/Error.h"
+#include "wire/Ethernet.h"
#include "util/Assert.h"
#include "util/Errno.h"
#include "util/platform/libc/string.h"
-
-#ifdef WIN32
- #include <winsock.h>
- #undef interface
-#else
- #include <sys/socket.h>
- #include <linux/if_packet.h>
- #include <linux/if_ether.h>
- #include <linux/if_arp.h>
-#endif
-
+#include "util/platform/Socket.h"
+#include "util/events/Event.h"
+#include "util/Identity.h"
+#include "util/AddrTools.h"
+
+#include <sys/socket.h>
+#include <linux/if_packet.h>
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
#include <event2/event.h>
#include <sys/types.h>
#include <sys/ioctl.h>
@@ -44,10 +44,6 @@
#define PADDING 512
-#define MAX_INTERFACES 256
-
-#define ETH_P_CJDNS 0xFC00
-
// 2 last 0x00 of .sll_addr are removed from original size (20)
#define SOCKADDR_LL_LEN 18
@@ -55,13 +51,7 @@ struct ETHInterface
{
struct Interface interface;
- evutil_socket_t socket;
-
- /**
- * The event registered with libevent.
- * Needed only so it can be freed.
- */
- struct event* incomingMessageEvent;
+ Socket socket;
uint8_t messageBuff[PADDING + MAX_PACKET_SIZE];
@@ -72,37 +62,19 @@ struct ETHInterface
struct InterfaceController* ic;
- /** A base sockaddr_ll which is used to build the address to send packets to. */
- struct sockaddr_ll addrBase;
-};
+ struct MultiInterface* multiIface;
-static inline void sockaddrForKey(struct sockaddr_ll* sockaddr,
- uint8_t key[InterfaceController_KEY_SIZE],
- struct ETHInterface* ethIf)
-{
- Assert_true(key[6] == 'e' && key[7] == 'n');
- Bits_memcpyConst(sockaddr, &ethIf->addrBase, sizeof(struct sockaddr_ll));
- Bits_memcpyConst(sockaddr->sll_addr, key, 6);
-}
+ struct sockaddr_ll addrBase;
-static inline void keyForSockaddr(uint8_t key[InterfaceController_KEY_SIZE],
- struct sockaddr_ll* sockaddr,
- struct ETHInterface* ethIf)
-{
- Bits_memcpyConst(key, sockaddr->sll_addr, 6);
- key[6] = 'e';
- key[7] = 'n';
-}
+ Identity
+};
static uint8_t sendMessage(struct Message* message, struct Interface* ethIf)
{
- struct ETHInterface* context = ethIf->senderContext;
- Assert_true(&context->interface == ethIf);
+ struct ETHInterface* context = Identity_cast((struct ETHInterface*) ethIf);
struct sockaddr_ll addr;
-
- sockaddrForKey(&addr, message->bytes, context);
- Message_shift(message, -InterfaceController_KEY_SIZE);
+ Message_pop(message, &addr, sizeof(struct sockaddr_ll));
if (sendto(context->socket,
message->bytes,
@@ -127,32 +99,21 @@ static uint8_t sendMessage(struct Message* message, struct Interface* ethIf)
return 0;
}
-/**
- * Release the event used by this module.
- *
- * @param vevent a void pointer cast of the event structure.
- */
-static void freeEvent(void* vevent)
-{
- event_del((struct event*) vevent);
- event_free((struct event*) vevent);
-}
-
-static void handleEvent(evutil_socket_t socket, short eventType, void* vcontext)
+static void handleEvent(void* vcontext)
{
- struct ETHInterface* context = (struct ETHInterface*) vcontext;
+ struct ETHInterface* context = Identity_cast((struct ETHInterface*) vcontext);
struct Message message =
{ .bytes = context->messageBuff + PADDING, .padding = PADDING, .length = MAX_PACKET_SIZE };
struct sockaddr_ll addr = { .sll_family = 0 };
- ev_socklen_t addrLen = sizeof(struct sockaddr_ll);
+ uint32_t addrLen = sizeof(struct sockaddr_ll);
// Start writing InterfaceController_KEY_SIZE after the beginning,
// keyForSockaddr() will write the key there.
- int rc = recvfrom(socket,
- message.bytes + InterfaceController_KEY_SIZE,
- message.length - InterfaceController_KEY_SIZE,
+ int rc = recvfrom(context->socket,
+ message.bytes,
+ message.length,
0,
(struct sockaddr*) &addr,
&addrLen);
@@ -176,9 +137,8 @@ static void handleEvent(evutil_socket_t socket, short eventType, void* vcontext)
return;
}
- message.length = rc + InterfaceController_KEY_SIZE;
-
- keyForSockaddr(message.bytes, &addr, context);
+ message.length = rc;
+ Message_push(&message, &addr, sizeof(struct sockaddr_ll));
context->interface.receiveMessage(&message, &context->interface);
}
@@ -188,50 +148,50 @@ int ETHInterface_beginConnection(const char* macAddress,
String* password,
struct ETHInterface* ethIf)
{
- struct sockaddr_ll addr = { .sll_family = 0 };
+ Identity_check(ethIf);
+ struct sockaddr_ll addr;
+ Bits_memcpyConst(&addr, &ethIf->addrBase, sizeof(struct sockaddr_ll));
if (AddrTools_parseMac(addr.sll_addr, (const uint8_t*)macAddress)) {
return ETHInterface_beginConnection_BAD_MAC;
}
- uint8_t key[InterfaceController_KEY_SIZE];
- keyForSockaddr(key, &addr, ethIf);
- int ret = ethIf->ic->insertEndpoint(key, cryptoKey, password, &ethIf->interface, ethIf->ic);
- switch(ret) {
- case 0:
- return 0;
+ struct Interface* iface = MultiInterface_ifaceForKey(ethIf->multiIface, &addr);
+ int ret = InterfaceController_registerPeer(ethIf->ic, cryptoKey, password, false, iface);
+ if (ret) {
+ Allocator_free(iface->allocator);
+ switch(ret) {
+ case InterfaceController_registerPeer_BAD_KEY:
+ return ETHInterface_beginConnection_BAD_KEY;
- case InterfaceController_registerInterface_BAD_KEY:
- return ETHInterface_beginConnection_BAD_KEY;
+ case InterfaceController_registerPeer_OUT_OF_SPACE:
+ return ETHInterface_beginConnection_OUT_OF_SPACE;
- case InterfaceController_registerInterface_OUT_OF_SPACE:
- return ETHInterface_beginConnection_OUT_OF_SPACE;
-
- default:
- return ETHInterface_beginConnection_UNKNOWN_ERROR;
+ default:
+ return ETHInterface_beginConnection_UNKNOWN_ERROR;
+ }
}
+ return 0;
}
-struct ETHInterface* ETHInterface_new(struct event_base* base,
+struct ETHInterface* ETHInterface_new(struct EventBase* base,
const char* bindDevice,
struct Allocator* allocator,
struct Except* exHandler,
struct Log* logger,
struct InterfaceController* ic)
{
- struct ETHInterface* context = allocator->malloc(sizeof(struct ETHInterface), allocator);
- Bits_memcpyConst(context, (&(struct ETHInterface) {
+ struct ETHInterface* context = Allocator_clone(allocator, (&(struct ETHInterface) {
.interface = {
.sendMessage = sendMessage,
- .senderContext = context,
.allocator = allocator
},
.logger = logger,
.ic = ic
- }), sizeof(struct ETHInterface));
+ }));
struct ifreq ifr = { .ifr_ifindex = 0 };
- context->socket = socket(AF_PACKET, SOCK_DGRAM, Endian_hostToBigEndian16(ETH_P_CJDNS));
+ context->socket = socket(AF_PACKET, SOCK_DGRAM, Ethernet_TYPE_CJDNS);
if (context->socket == -1) {
Except_raise(exHandler, ETHInterface_new_SOCKET_FAILED,
"call to socket() failed. [%s]", Errno_getString());
@@ -259,14 +219,13 @@ struct ETHInterface* ETHInterface_new(struct event_base* base,
context->addrBase = (struct sockaddr_ll) {
.sll_family = AF_PACKET,
- .sll_protocol = Endian_hostToBigEndian16(ETH_P_CJDNS),
+ .sll_protocol = Ethernet_TYPE_CJDNS,
.sll_ifindex = context->ifindex,
.sll_hatype = ARPHRD_ETHER,
.sll_pkttype = PACKET_OTHERHOST,
.sll_halen = ETH_ALEN
};
-
if (bind(context->socket, (struct sockaddr*) &context->addrBase, sizeof(struct sockaddr_ll))) {
Except_raise(exHandler, ETHInterface_new_BIND_FAILED,
"call to bind() failed [%s]", Errno_getString());
@@ -274,17 +233,9 @@ struct ETHInterface* ETHInterface_new(struct event_base* base,
evutil_make_socket_nonblocking(context->socket);
- context->incomingMessageEvent =
- event_new(base, context->socket, EV_READ | EV_PERSIST, handleEvent, context);
-
- if (!context->incomingMessageEvent || event_add(context->incomingMessageEvent, NULL)) {
- Except_raise(exHandler, ETHInterface_new_FAILED_CREATING_EVENT,
- "failed to create ETHInterface event [%s]", Errno_getString());
- }
-
- allocator->onFree(freeEvent, context->incomingMessageEvent, allocator);
+ Event_socketRead(handleEvent, context, context->socket, base, allocator, exHandler);
- ic->registerInterface(&context->interface, ic);
+ context->multiIface = MultiInterface_new(sizeof(struct sockaddr_ll), &context->interface, ic);
return context;
}
View
2  interface/ETHInterface_admin.c
@@ -17,7 +17,7 @@
#include "exception/Jmp.h"
#include "interface/ETHInterface.h"
#include "memory/Allocator.h"
-#include "net/InterfaceController.h"
+#include "interface/InterfaceController.h"
#include "util/Base32.h"
#include "util/Errno.h"
View
2  interface/ETHInterface_admin.h
@@ -17,7 +17,7 @@
#include "admin/Admin.h"
#include "memory/Allocator.h"
-#include "net/InterfaceController.h"
+#include "interface/InterfaceController.h"
#include "util/log/Log.h"
#include "util/events/EventBase.h"
View
44 net/InterfaceController.h → interface/InterfaceController.h
@@ -15,30 +15,22 @@
#ifndef InterfaceController_H
#define InterfaceController_H
-#include "crypto/CryptoAuth.h"
-#include "dht/dhtcore/RouterModule.h"
+#include "benc/String.h"
#include "interface/Interface.h"
-#include "memory/Allocator.h"
-#include "switch/SwitchCore.h"
-#include "net/SwitchPinger.h"
-#include "util/log/Log.h"
#include <stdint.h>
#include <stdbool.h>
-/** The number of bytes used to discriminate between endpoints. */
-#define InterfaceController_KEY_SIZE 8
-
struct InterfaceController
{
/**
- * Add a new endpoint.
+ * Add a new peer.
* Called from the network interface when it is asked to make a connection or it autoconnects.
*
- * @param key the ip/mac address to use for discriminating this endpoint.
* @param herPublicKey the public key of the foreign node, NULL if unknown.
* @param password the password for authenticating with the other node if specified.
- * @param externalInterface the network interface which is used to connect to this node.
+ * @param requireAuth true if the other node must authenticate (incoming connection).
+ * @param iface an interface which pipes messages to this peer.
* @param ic the interface controller, a child of the memory allocator for this controller
* will be used for the endpoint because we want to be able to free a single
* endpoint without freeing the whole network interface but if the network interface
@@ -47,22 +39,16 @@ struct InterfaceController
* InterfaceController_registerInterface_BAD_KEY if the key is not a valid cjdns key.
* InterfaceController_registerInterface_OUT_OF_SPACE if no space to store the entry.
*/
- #define InterfaceController_registerInterface_OUT_OF_SPACE -1
- #define InterfaceController_registerInterface_BAD_KEY -2
- int (* const insertEndpoint)(uint8_t key[InterfaceController_KEY_SIZE],
- uint8_t herPublicKey[32],
- String* password,
- struct Interface* externalInterface,
- struct InterfaceController* ic);
-
- /**
- * Setup an external interface to forward to this InterfaceController.
- * This always succeeds.
- *
- * @param externalInterface the network facing interface to register.
- * @param ic the InterfaceController.
- */
- void (* const registerInterface)(struct Interface* externalInterface,
- struct InterfaceController* ic);
+ #define InterfaceController_registerPeer_OUT_OF_SPACE -1
+ #define InterfaceController_registerPeer_BAD_KEY -2
+ int (* const registerPeer)(struct InterfaceController* ic,
+ uint8_t herPublicKey[32],
+ String* password,
+ bool requireAuth,
+ struct Interface* iface);
};
+
+#define InterfaceController_registerPeer(ic, herPublicKey, password, requireAuth, iface) \
+ (ic)->registerPeer((ic), (herPublicKey), (password), (requireAuth), (iface))
+
#endif
View
199 interface/MultiInterface.c
@@ -0,0 +1,199 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program 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 <http://www.gnu.org/licenses/>.
+ */
+#include "interface/MultiInterface.h"
+#include "interface/Interface.h"
+#include "interface/InterfaceController.h"
+#include "memory/Allocator.h"
+#include "util/Identity.h"
+
+/*
+ * An Interface such as Ethernet or UDP which may connect to multiple peers
+ * through the same socket, Interfaces are MultiInterface must send and expect
+ * a configurable length key to be sent in front of the message, this key
+ * indicates which peer the message is from/to.
+ */
+
+// if no key size is specified.
+#define DEFAULT_KEYSIZE 4
+
+
+struct MapKey
+{
+ int keySize;
+
+ /** Variable size. */
+ uint8_t bytes[DEFAULT_KEYSIZE];
+};
+
+struct Peer
+{
+ /** The InterfaceController facing iface. */
+ struct Interface internalIf;
+
+ /** The multi-iface containing this peer. */
+ struct MultiInterface* multiIface;
+
+ Identity
+
+ /** Variable size. */
+ struct MapKey key;
+};
+
+#define Map_USE_HASH
+#define Map_USE_COMPARATOR
+#define Map_NAME OfPeersByKey
+#define Map_KEY_TYPE struct MapKey*
+#define Map_VALUE_TYPE struct Peer*
+#include "util/Map.h"
+
+static inline uint32_t Map_OfPeersByKey_hash(struct MapKey** key)
+{
+ uint32_t* k = (uint32_t*) ((*key)->bytes);
+ return k[0];
+}
+
+static inline int Map_OfPeersByKey_compare(struct MapKey** keyA, struct MapKey** keyB)
+{
+ uint32_t* kA = (uint32_t*) (*keyA);
+ uint32_t* kB = (uint32_t*) (*keyB);
+ for (int i = 0; i <= ((*keyA)->keySize / 4); i++) {
+ if (kA[i] != kB[i]) {
+ return kA[i] < kB[i];
+ }
+ }
+ return 0;
+}
+
+struct MultiInterface_pvt
+{
+ struct MultiInterface pub;
+
+ /** Endpoints by their key. */
+ struct Map_OfPeersByKey peerMap;
+
+ struct InterfaceController* ic;
+
+ struct Allocator* allocator;
+
+ Identity
+};
+
+static uint8_t sendMessage(struct Message* msg, struct Interface* peerIface)
+{
+ struct Peer* p = Identity_cast((struct Peer*) peerIface);
+ Message_push(msg, p->key.bytes, p->key.keySize);
+ return p->multiIface->iface->sendMessage(msg, p->multiIface->iface);
+}
+
+static void removePeer(void* vpeer)
+{
+ struct Peer* p = Identity_cast((struct Peer*) vpeer);
+ struct MultiInterface_pvt* mif = Identity_cast((struct MultiInterface_pvt*) p->multiIface);
+ struct Map_OfPeersByKey* peerMap = &mif->peerMap;
+ for (int i = 0; i < (int)peerMap->count; i++) {
+ if (peerMap->values[i] == p) {
+ Map_OfPeersByKey_remove(i, peerMap);
+ }
+ }
+}
+
+static inline struct Peer* peerForKey(struct MultiInterface_pvt* mif,
+ struct MapKey* key,
+ bool regIfNew)
+{
+ int index = Map_OfPeersByKey_indexForKey(&key, &mif->peerMap);
+ if (index >= 0) {
+ return mif->peerMap.values[index];
+ }
+
+ // Per peer allocator.
+ struct Allocator* alloc = Allocator_child(mif->allocator);
+
+ size_t size = sizeof(struct Peer) + (mif->pub.keySize - DEFAULT_KEYSIZE);
+ struct Peer* peer = Allocator_malloc(mif->allocator, size);
+
+ Bits_memcpyConst(peer, (&(struct Peer) {
+ .internalIf = {
+ .sendMessage = sendMessage,
+ .allocator = alloc
+ },
+ .multiIface = &mif->pub,
+ .key = { .keySize = mif->pub.keySize }
+ }), sizeof(struct Peer));
+ Bits_memcpy(peer->key.bytes, key->bytes, mif->pub.keySize);
+
+ Identity_set(peer);
+
+ struct MapKey* kptr = &peer->key;
+ index = Map_OfPeersByKey_put(&kptr, &peer, &mif->peerMap);
+
+ // remove the peer from the map when the allocator is freed.
+ Allocator_onFree(alloc, removePeer, peer);
+
+ if (regIfNew) {
+ InterfaceController_registerPeer(mif->ic, NULL, NULL, true, &peer->internalIf);
+ }
+ return peer;
+}
+
+static uint8_t receiveMessage(struct Message* msg, struct Interface* external)
+{
+ struct MultiInterface_pvt* mif =
+ Identity_cast((struct MultiInterface_pvt*) external->receiverContext);
+
+ // push the key size to the message.
+ Message_push(msg, &mif->pub.keySize, 4);
+
+ struct Peer* p = peerForKey(mif, (struct MapKey*) msg->bytes, true);
+
+ // pop the key size and key
+ Message_shift(msg, -(mif->pub.keySize + 4));
+
+ return p->internalIf.receiveMessage(msg, &p->internalIf);
+}
+
+struct Interface* MultiInterface_ifaceForKey(struct MultiInterface* mIface, void* key)
+{
+ struct MultiInterface_pvt* mif = Identity_cast((struct MultiInterface_pvt*) mIface);
+ uint8_t buff[mif->pub.keySize + 4];
+ Bits_memcpyConst(buff, &mif->pub.keySize, 4);
+ Bits_memcpy(buff+4, key, mif->pub.keySize);
+ struct Peer* p = peerForKey(mif, (struct MapKey*) buff, false);
+ return &p->internalIf;
+}
+
+struct MultiInterface* MultiInterface_new(int keySize,
+ struct Interface* external,
+ struct InterfaceController* ic)
+{
+ Assert_true(!(keySize % 4));
+ Assert_true(keySize > 4);
+ struct MultiInterface_pvt* out =
+ Allocator_clone(external->allocator, (&(struct MultiInterface_pvt) {
+ .pub = {
+ .iface = external,
+ .keySize = keySize,
+ },
+ .peerMap = { .allocator = external->allocator },
+ .ic = ic,
+ .allocator = external->allocator
+ }));
+ Identity_set(out);
+
+ external->receiveMessage = receiveMessage;
+ external->receiverContext = out;
+
+ return &out->pub;
+}
View
45 interface/MultiInterface.h
@@ -0,0 +1,45 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program 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 <http://www.gnu.org/licenses/>.
+ */
+#ifndef MultiInterface_H
+#define MultiInterface_H
+
+#include "interface/Interface.h"
+#include "interface/InterfaceController.h"
+
+/*
+ * An Interface such as Ethernet or UDP which may connect to multiple peers
+ * through the same socket, Interfaces are MultiInterface must send and expect
+ * a configurable length key to be sent in front of the message, this key
+ * indicates which peer the message is from/to.
+ */
+
+struct MultiInterface
+{
+ /** The interface which is wrapped by this MultiInterface. */
+ struct Interface* const iface;
+
+ /**
+ * The number of bytes which this interface will send
+ * ahead of the message to signal it's origin.
+ */
+ const int keySize;
+};
+
+struct Interface* MultiInterface_ifaceForKey(struct MultiInterface* mIface, void* key);
+
+struct MultiInterface* MultiInterface_new(int keySize,
+ struct Interface* external,
+ struct InterfaceController* ic);
+#endif
View
34 interface/TUNConfigurator.h
@@ -34,6 +34,9 @@
/** If there is an error bringing the interface up. */
#define TUNConfigurator_ERROR_ENABLING_INTERFACE 2
+/** Invalid argument. */
+#define TUNConfigurator_BAD_INPUT 3
+
/**
* Open the TUN device.
*
@@ -68,12 +71,31 @@ void* TUNConfigurator_initTun(const char* interfaceName,
* TUNConfigurator_ERROR_GETTING_ADMIN_SOCKET Error getting admin socket for interface.
* TUNConfigurator_ERROR_ENABLING_INTERFACE If the interface cannot be brought up.
*/
-#define TUNConfigurator_setIpAddress_INTERNAL -1
-void TUNConfigurator_setIpAddress(const char* interfaceName,
- const uint8_t address[16],
- int prefixLen,
- struct Log* logger,
- struct Except* eh);
+#define TUNConfigurator_addIp4Address_INTERNAL -1
+void TUNConfigurator_addIp4Address(const char* interfaceName,
+ const uint8_t address[4],
+ int prefixLen,
+ struct Log* logger,
+ struct Except* eh);
+
+/**
+ * Set an IPv6 address on an interface, bring the interface up, and configure a route.
+ *
+ * @param interfaceName the name of the interface to alter.
+ * @param address the ip address to set.
+ * @param prefixLen the number of bits netmask to include in the route.
+ * @param logger
+ * @param eh if this function fails, it will raise one of the following.
+ * TUNConfigurator_setIpAddress_INTERNAL Catch all exception code for failures.
+ * TUNConfigurator_ERROR_GETTING_ADMIN_SOCKET Error getting admin socket for interface.
+ * TUNConfigurator_ERROR_ENABLING_INTERFACE If the interface cannot be brought up.
+ */
+#define TUNConfigurator_addIp6Address_INTERNAL -1
+void TUNConfigurator_addIp6Address(const char* interfaceName,
+ const uint8_t address[16],
+ int prefixLen,
+ struct Log* logger,
+ struct Except* eh);
/**
* Set the MTU of an interface.
View
25 interface/TUNConfigurator_FreeBSD.c
@@ -105,11 +105,20 @@ void* TUNConfigurator_initTun(const char* interfaceName,
return (void*) ret;
}
-void TUNConfigurator_setIpAddress(const char* interfaceName,
- const uint8_t address[16],
- int prefixLen,
- struct Log* logger,
- struct Except* eh)
+void TUNConfigurator_addIp4Address(const char* interfaceName,
+ const uint8_t address[4],
+ int prefixLen,
+ struct Log* logger,
+ struct Except* eh)
+{
+ Except_raise(eh, TUNConfigurator_addIp4Address_INTERNAL, "unimplemented");
+}
+
+void TUNConfigurator_addIp6Address(const char* interfaceName,
+ const uint8_t address[16],
+ int prefixLen,
+ struct Log* logger,
+ struct Except* eh)
{
/* stringify our IP address */
char myIp[40];
@@ -130,7 +139,7 @@ void TUNConfigurator_setIpAddress(const char* interfaceName,
if (err) {
// Should never happen since the address is specified as binary.
Except_raise(eh,
- TUNConfigurator_setIpAddress_INTERNAL,
+ TUNConfigurator_addIp6Address_INTERNAL,
"bad IPv6 address [%s]",
gai_strerror(err));
}
@@ -159,7 +168,7 @@ void TUNConfigurator_setIpAddress(const char* interfaceName,
int s = socket(AF_INET6, SOCK_DGRAM, 0);
if (s < 0) {
Except_raise(eh,
- TUNConfigurator_setIpAddress_INTERNAL,
+ TUNConfigurator_addIp6Address_INTERNAL,
"socket() failed [%s]",
Errno_getString());
}
@@ -168,7 +177,7 @@ void TUNConfigurator_setIpAddress(const char* interfaceName,
enum Errno err = Errno_get();
close(s);
Except_raise(eh,
- TUNConfigurator_setIpAddress_INTERNAL,
+ TUNConfigurator_addIp6Address_INTERNAL,
"ioctl(SIOCAIFADDR) failed [%s]",
Errno_strerror(err));
}
View
27 interface/TUNConfigurator_Illumos.c
@@ -85,25 +85,34 @@ static void setupRoute(const uint8_t address[16],
int sock = socket(PF_ROUTE, SOCK_RAW, 0);
if (sock == -1) {
- Except_raise(eh, TUNConfigurator_setIpAddress_INTERNAL,
+ Except_raise(eh, TUNConfigurator_addIp6Address_INTERNAL,
"open route socket [%s]", Errno_getString());
}
ssize_t returnLen = write(sock, (char*) &rm, rm.header.rtm_msglen);
if (returnLen < 0) {
- Except_raise(eh, TUNConfigurator_setIpAddress_INTERNAL,
+ Except_raise(eh, TUNConfigurator_addIp6Address_INTERNAL,
"insert route [%s]", Errno_getString());
} else if (returnLen < rm.header.rtm_msglen) {
- Except_raise(eh, TUNConfigurator_setIpAddress_INTERNAL,
+ Except_raise(eh, TUNConfigurator_addIp6Address_INTERNAL,
"insert route returned only [%d] of [%d]", returnLen, rm.header.rtm_msglen);
}
}
-void TUNConfigurator_setIpAddress(const char* interfaceName,
- const uint8_t address[16],
- int prefixLen,
- struct Log* logger,
- struct Except* eh)
+void TUNConfigurator_addIp4Address(const char* interfaceName,
+ const uint8_t address[4],
+ int prefixLen,
+ struct Log* logger,
+ struct Except* eh)
+{
+ Except_raise(eh, TUNConfigurator_addIp4Address_INTERNAL, "unimplemented");
+}
+
+void TUNConfigurator_addIp6Address(const char* interfaceName,
+ const uint8_t address[16],
+ int prefixLen,
+ struct Log* logger,
+ struct Except* eh)
{
struct lifreq ifr = {
.lifr_ppa = 0,
@@ -147,7 +156,7 @@ void TUNConfigurator_setIpAddress(const char* interfaceName,
if (error) {
enum Errno err = Errno_get();
close(udpSock);
- Except_raise(eh, TUNConfigurator_setIpAddress_INTERNAL, "%s [%s]",
+ Except_raise(eh, TUNConfigurator_addIp6Address_INTERNAL, "%s [%s]",
error, Errno_strerror(err));
}
close(udpSock);
View
76 interface/TUNConfigurator_Linux.c
@@ -101,18 +101,20 @@ void* TUNConfigurator_initTun(const char* interfaceName,
* Get a socket and ifRequest for a given interface by name.
*
* @param interfaceName the name of the interface, eg: tun0
+ * @param af either AF_INET or AF_INET6
* @param eg an exception handler in case something goes wrong.
* this will send a TUNConfigurator_ERROR_GETTING_ADMIN_SOCKET for all errors.
* @param ifRequestOut an ifreq which will be populated with the interface index of the interface.
* @return a socket for interacting with this interface.
*/
static int socketForIfName(const char* interfaceName,
+ int af,
struct Except* eh,
struct ifreq* ifRequestOut)
{
int s;
- if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ if ((s = socket(af, SOCK_DGRAM, 0)) < 0) {
Except_raise(eh, TUNConfigurator_ERROR_GETTING_ADMIN_SOCKET,
"socket() failed: [%s]", Errno_getString());
}
@@ -157,14 +159,66 @@ static void checkInterfaceUp(int socket,
}
}
-void TUNConfigurator_setIpAddress(const char* interfaceName,
- const uint8_t address[16],
- int prefixLen,
- struct Log* logger,
- struct Except* eh)
+void TUNConfigurator_addIp4Address(const char* interfaceName,
+ const uint8_t address[4],
+ int prefixLen,
+ struct Log* logger,
+ struct Except* eh)
{
+ if (prefixLen < 0 || prefixLen > 32) {
+ Except_raise(eh, TUNConfigurator_BAD_INPUT,
+ "for ipv4 addresses, prefixLen must be between 0 and 32");
+ }
+
+ struct ifreq ifRequest = { .ifr_ifindex = 0 };
+ int s = socketForIfName(interfaceName, AF_INET, eh, &ifRequest);
+
+ checkInterfaceUp(s, &ifRequest, logger, eh);
+
+ struct sockaddr_in sin = { .sin_family = AF_INET, .sin_port = 0 };
+ Bits_memcpyConst(&sin.sin_addr.s_addr, address, 4);
+ Bits_memcpyConst(&ifRequest.ifr_addr, &sin, sizeof(struct sockaddr));
+
+ uint8_t myIp[INET_ADDRSTRLEN];
+ inet_ntop(AF_INET, address, (char*)myIp, INET_ADDRSTRLEN);
+ Log_info(logger, "Setting IP4 address [%s] for device [%s]", myIp, interfaceName);
+
+ if (ioctl(s, SIOCSIFADDR, &ifRequest) < 0) {
+ enum Errno err = Errno_get();
+ close(s);
+ Except_raise(eh, TUNConfigurator_addIp4Address_INTERNAL,
+ "ioctl(SIOCSIFADDR) failed: [%s]", Errno_strerror(err));
+ }
+
+
+ uint32_t x = ~0 << (32 - prefixLen);
+ x = Endian_hostToBigEndian32(x);
+ Bits_memcpyConst(&sin.sin_addr, &x, 4);
+ Bits_memcpyConst(&ifRequest.ifr_addr, &sin, sizeof(struct sockaddr_in));
+
+ if (ioctl(s, SIOCSIFNETMASK, &ifRequest) < 0) {
+ enum Errno err = Errno_get();
+ close(s);
+ Except_raise(eh, TUNConfigurator_addIp4Address_INTERNAL,
+ "ioctl(SIOCSIFNETMASK) failed: [%s]", Errno_strerror(err));
+ }
+
+ close(s);
+}
+
+void TUNConfigurator_addIp6Address(const char* interfaceName,
+ const uint8_t address[16],
+ int prefixLen,
+ struct Log* logger,
+ struct Except* eh)
+{
+ if (prefixLen < 0 || prefixLen > 128) {
+ Except_raise(eh, TUNConfigurator_BAD_INPUT,
+ "for ipv6 addresses, prefixLen must be between 0 and 128");
+ }
+
struct ifreq ifRequest;
- int s = socketForIfName(interfaceName, eh, &ifRequest);
+ int s = socketForIfName(interfaceName, AF_INET6, eh, &ifRequest);
struct in6_ifreq ifr6;
Bits_memset(&ifr6, 0, sizeof(struct in6_ifreq));
@@ -183,9 +237,11 @@ void TUNConfigurator_setIpAddress(const char* interfaceName,
if (ioctl(s, SIOCSIFADDR, &ifr6) < 0) {
enum Errno err = Errno_get();
close(s);
- Except_raise(eh, TUNConfigurator_setIpAddress_INTERNAL,
+ Except_raise(eh, TUNConfigurator_addIp6Address_INTERNAL,
"ioctl(SIOCSIFADDR) failed: [%s]", Errno_strerror(err));
}
+
+ close(s);
}
void TUNConfigurator_setMTU(const char* interfaceName,
@@ -194,7 +250,7 @@ void TUNConfigurator_setMTU(const char* interfaceName,
struct Except* eh)
{
struct ifreq ifRequest;
- int s = socketForIfName(interfaceName, eh, &ifRequest);
+ int s = socketForIfName(interfaceName, AF_INET6, eh, &ifRequest);
Log_info(logger, "Setting MTU for device [%s] to [%u] bytes.", interfaceName, mtu);
@@ -205,4 +261,6 @@ void TUNConfigurator_setMTU(const char* interfaceName,
Except_raise(eh, TUNConfigurator_setMTU_INTERNAL,
"ioctl(SIOCSIFMTU) failed: [%s]", Errno_strerror(err));
}
+
+ close(s);
}
View
25 interface/TUNConfigurator_OSX.c
@@ -131,11 +131,20 @@ void* TUNConfigurator_initTun(const char* interfaceName,
return (void*) tunPtr;
}
-void TUNConfigurator_setIpAddress(const char* interfaceName,
- const uint8_t address[16],
- int prefixLen,
- struct Log* logger,
- struct Except* eh)
+void TUNConfigurator_addIp4Address(const char* interfaceName,
+ const uint8_t address[4],
+ int prefixLen,
+ struct Log* logger,
+ struct Except* eh)
+{
+ Except_raise(eh, TUNConfigurator_addIp4Address_INTERNAL, "unimplemented");
+}
+
+void TUNConfigurator_addIp6Address(const char* interfaceName,
+ const uint8_t address[16],
+ int prefixLen,
+ struct Log* logger,
+ struct Except* eh)
{
/* stringify our IP address */
char myIp[40];
@@ -156,7 +165,7 @@ void TUNConfigurator_setIpAddress(const char* interfaceName,
if (err) {
// Should never happen since the address is specified as binary.
Except_raise(eh,
- TUNConfigurator_setIpAddress_INTERNAL,
+ TUNConfigurator_addIp6Address_INTERNAL,
"bad IPv6 address [%s]",
gai_strerror(err));
}
@@ -185,7 +194,7 @@ void TUNConfigurator_setIpAddress(const char* interfaceName,
int s = socket(AF_INET6, SOCK_DGRAM, 0);
if (s < 0) {
Except_raise(eh,
- TUNConfigurator_setIpAddress_INTERNAL,
+ TUNConfigurator_addIp6Address_INTERNAL,
"socket() failed [%s]",
Errno_getString());
}
@@ -194,7 +203,7 @@ void TUNConfigurator_setIpAddress(const char* interfaceName,
enum Errno err = Errno_get();
close(s);
Except_raise(eh,
- TUNConfigurator_setIpAddress_INTERNAL,
+ TUNConfigurator_addIp6Address_INTERNAL,
"ioctl(SIOCAIFADDR) failed [%s]",
Errno_strerror(err));
}
View
25 interface/TUNConfigurator_OpenBSD.c
@@ -98,11 +98,20 @@ void* TUNConfigurator_initTun(const char* interfaceName,
return (void*) ret;
}
-void TUNConfigurator_setIpAddress(const char* interfaceName,
- const uint8_t address[16],
- int prefixLen,
- struct Log* logger,
- struct Except* eh)
+void TUNConfigurator_addIp4Address(const char* interfaceName,
+ const uint8_t address[4],
+ int prefixLen,
+ struct Log* logger,
+ struct Except* eh)
+{
+ Except_raise(eh, TUNConfigurator_addIp4Address_INTERNAL, "unimplemented");
+}
+
+void TUNConfigurator_addIp6Address(const char* interfaceName,
+ const uint8_t address[16],
+ int prefixLen,
+ struct Log* logger,
+ struct Except* eh)
{
/* stringify our IP address */
char myIp[40];
@@ -123,7 +132,7 @@ void TUNConfigurator_setIpAddress(const char* interfaceName,
if (err) {
// Should never happen since the address is specified as binary.
Except_raise(eh,
- TUNConfigurator_setIpAddress_INTERNAL,
+ TUNConfigurator_addIp6Address_INTERNAL,
"bad IPv6 address [%s]",
gai_strerror(err));
}
@@ -152,7 +161,7 @@ void TUNConfigurator_setIpAddress(const char* interfaceName,
int s = socket(AF_INET6, SOCK_DGRAM, 0);
if (s < 0) {
Except_raise(eh,
- TUNConfigurator_setIpAddress_INTERNAL,
+ TUNConfigurator_addIp6Address_INTERNAL,
"socket() failed [%s]",
Errno_getString());
}
@@ -161,7 +170,7 @@ void TUNConfigurator_setIpAddress(const char* interfaceName,
enum Errno err = Errno_get();
close(s);
Except_raise(eh,
- TUNConfigurator_setIpAddress_INTERNAL,
+ TUNConfigurator_addIp6Address_INTERNAL,
"ioctl(SIOCAIFADDR) failed [%s]",
Errno_strerror(err));
}
View
19 interface/TUNConfigurator_W32.c
@@ -23,11 +23,20 @@ void* TUNConfigurator_initTun(const char* interfaceName,
return NULL;
}
-void TUNConfigurator_setIpAddress(const char* interfaceName,
- const uint8_t address[16],
- int prefixLen,
- struct Log* logger,
- struct Except* eh)
+void TUNConfigurator_addIp4Address(const char* interfaceName,
+ const uint8_t address[4],
+ int prefixLen,
+ struct Log* logger,
+ struct Except* eh)
+{
+ Except_raise(eh, TUNConfigurator_addIp4Address_INTERNAL, "unimplemented");
+}
+
+void TUNConfigurator_addIp6Address(const char* interfaceName,
+ const uint8_t address[16],
+ int prefixLen,
+ struct Log* logger,
+ struct Except* eh)
{
}
View
125 interface/TUNInterface.c
@@ -14,12 +14,11 @@
*/
#include "interface/Interface.h"
#include "interface/TUNInterface.h"
-#include "benc/String.h"
-#include "util/Endian.h"
#include "util/Errno.h"
+#include "util/events/Event.h"
+#include "util/Identity.h"
+#include "util/platform/Socket.h"
-#include "util/platform/libc/string.h"
-#include <event2/event.h>
#include <net/if.h>
#include <fcntl.h>
#include <sys/ioctl.h>
@@ -27,84 +26,59 @@
#ifdef Linux
#include <linux/if_ether.h>
- #define INET6_ETHERTYPE ETH_P_IPV6
#else
#include <netinet/in.h>
#include <netinet/if_ether.h>
- #define INET6_ETHERTYPE PF_INET6
#endif
// Defined extra large so large MTU can be taken advantage of later.
#define MAX_PACKET_SIZE 8192
#define PADDING_SPACE (10240 - MAX_PACKET_SIZE)
-// The number of bytes at the beginning of the message which is used
-// to contain the type of packet.
-#ifdef Illumos
- #define PACKET_INFO_SIZE 0
-#else
- #define PACKET_INFO_SIZE 4
-
- static void setPacketInfo(uint8_t* toLocation)
- {
- ((uint16_t*) toLocation)[0] = 0;
- ((uint16_t*) toLocation)[1] = Endian_bigEndianToHost16(INET6_ETHERTYPE);
- }
-#endif
-
-
-struct Context
+struct TUNInterface_pvt
{
struct TUNInterface pub;
- struct event* incomingEvent;
- int fileDescriptor;
+ Socket tunSocket;
+ Identity
};
-static void closeInterface(void* vcontext)
+static void handleEvent(void* vcontext)
{
- struct Context* tun = vcontext;
- close(tun->fileDescriptor);
- event_del(tun->incomingEvent);
- event_free(tun->incomingEvent);
-}
+ struct TUNInterface_pvt* tun = Identity_cast((struct TUNInterface_pvt*) vcontext);
-static void handleEvent(evutil_socket_t socket, short eventType, void* vcontext)
-{
- // 292 bytes of extra padding to build headers back from for better efficiency.
- uint8_t messageBuffer[MAX_PACKET_SIZE + PADDING_SPACE];
+ struct Message* msg;
+ Message_STACK(msg, MAX_PACKET_SIZE, PADDING_SPACE);
- struct Message message = {
- .bytes = messageBuffer + PADDING_SPACE,
- .padding = PADDING_SPACE,
- .length = MAX_PACKET_SIZE
- };
+ ssize_t length = read(tun->tunSocket, msg->bytes, msg->length);
- ssize_t length =
- read(socket, messageBuffer + PADDING_SPACE - PACKET_INFO_SIZE, MAX_PACKET_SIZE);
-
- if (length < 0) {
+ if (length < 4) {
printf("Error reading from TUN device %d\n", (int) length);
return;
}
- message.length = length - PACKET_INFO_SIZE;
+ msg->length = length;
+
+ #ifdef Illumos
+ // Illumos does not send packet info, it only supports ip4 and ip6 over tun.
+ uint16_t ethertype = ((msg->bytes[0] >> 4) == 6) ? Ethernet_TYPE_IP6 : Ethernet_TYPE_IP4;
+ TUNInterface_pushMessageType(msg, ethertype);
+ #endif
- struct Interface* iface = &((struct Context*) vcontext)->pub.iface;
+ struct Interface* iface = &tun->pub.iface;
if (iface->receiveMessage) {
- iface->receiveMessage(&message, iface);
+ iface->receiveMessage(msg, iface);
}
}
static uint8_t sendMessage(struct Message* message, struct Interface* iface)
{
- #if PACKET_INFO_SIZE > 0
- // The type of packet we send,
- // older linux kernels need this hint otherwise they assume it's ipv4.
- Message_shift(message, PACKET_INFO_SIZE);
- setPacketInfo(message->bytes);
+ #ifdef Illumos
+ // Illumos does not support packet info.
+ Message_shift(message, -4);
#endif
- struct Context* tun = iface->senderContext;
- ssize_t ret = write(tun->fileDescriptor, message->bytes, message->length);
+ struct TUNInterface_pvt* tun = Identity_cast((struct TUNInterface_pvt*) iface);
+
+ ssize_t ret = write(tun->tunSocket, message->bytes, message->length);
if (ret < 0) {
printf("Error writing to TUN device %d\n", Errno_get());
}
@@ -113,34 +87,27 @@ static uint8_t sendMessage(struct Message* message, struct Interface* iface)
}
struct TUNInterface* TUNInterface_new(void* tunSocket,
- struct event_base* base,
+ struct EventBase* base,
struct Allocator* allocator)
{
- int tunFileDesc = (int) ((intptr_t) tunSocket);
-
- evutil_make_socket_nonblocking(tunFileDesc);
-
- struct Context* tun = allocator->malloc(sizeof(struct Context), allocator);
- tun->incomingEvent = event_new(base, tunFileDesc, EV_READ | EV_PERSIST, handleEvent, tun);
- tun->fileDescriptor = tunFileDesc;
-
- if (tun->incomingEvent == NULL) {
- abort();
- }
-
- struct Interface iface = {
- .senderContext = tun,
- .sendMessage = sendMessage,
- .allocator = allocator,
- .requiredPadding = 0,
- .maxMessageLength = MAX_PACKET_SIZE
- };
-
- Bits_memcpyConst(&tun->pub.iface, &iface, sizeof(struct Interface));
-
- event_add(tun->incomingEvent, NULL);
-
- allocator->onFree(closeInterface, tun, allocator);
+ Socket tunSock = (Socket) ((intptr_t) tunSocket);
+
+ Socket_makeNonBlocking(tunSock);
+
+ struct TUNInterface_pvt* tun = Allocator_clone(allocator, (&(struct TUNInterface_pvt) {
+ .pub = {
+ .iface = {
+ .sendMessage = sendMessage,
+ .allocator = allocator,
+ .requiredPadding = 0,
+ .maxMessageLength = MAX_PACKET_SIZE
+ }
+ },
+ .tunSocket = tunSock
+ }));
+ Identity_set(tun);
+
+ Event_socketRead(handleEvent, tun, tunSock, base, allocator, NULL);
return &tun->pub;
}
View
19 interface/TUNInterface.h
@@ -15,11 +15,11 @@
#ifndef TUNInterface_H
#define TUNInterface_H
-#include "interface/Interface.h"
#include "benc/String.h"
+#include "interface/Interface.h"
#include "memory/Allocator.h"
-
#include "util/events/EventBase.h"
+#include "wire/Message.h"
/**
* An interface which connects to the TUN/TAP device for
@@ -41,4 +41,19 @@ struct TUNInterface
struct TUNInterface* TUNInterface_new(void* tunSocket,
struct event_base* base,
struct Allocator* allocator);
+
+
+static inline void TUNInterface_pushMessageType(struct Message* message, uint16_t ethertype)
+{
+ Message_shift(message, 4);
+ ((uint16_t*) message->bytes)[0] = 0;
+ ((uint16_t*) message->bytes)[1] = ethertype;
+}
+
+static inline uint16_t TUNInterface_popMessageType(struct Message* message)
+{
+ Message_shift(message, -4);
+ return ((uint16_t*) message->bytes)[-1];
+}
+
#endif
View
118 interface/UDPInterface.c
@@ -14,10 +14,11 @@
*/
#include "exception/Except.h"
#include "interface/Interface.h"
+#include "interface/MultiInterface.h"
#include "interface/UDPInterface.h"
#include "interface/UDPInterface_pvt.h"
#include "memory/Allocator.h"
-#include "net/InterfaceController.h"
+#include "interface/InterfaceController.h"
#include "util/Assert.h"
#include "util/Errno.h"
#include "wire/Message.h"
@@ -34,49 +35,21 @@
#include <sys/types.h>
#include <event2/event.h>
-
#define MAX_INTERFACES 256
-
-#define EFFECTIVE_KEY_SIZE \
- ((InterfaceController_KEY_SIZE > sizeof(struct sockaddr_in)) \
- ? sizeof(struct sockaddr_in) : InterfaceController_KEY_SIZE)
-
-static inline void sockaddrForKey(struct sockaddr_in* sockaddr,
- uint8_t key[InterfaceController_KEY_SIZE],
- struct UDPInterface_pvt* udpif)
-{
- if (EFFECTIVE_KEY_SIZE < sizeof(struct sockaddr_in)) {
- Bits_memset(sockaddr, 0, sizeof(struct sockaddr_in));
- }
- Bits_memcpyConst(sockaddr, key, EFFECTIVE_KEY_SIZE);
-}
-
-static inline void keyForSockaddr(uint8_t key[InterfaceController_KEY_SIZE],
- struct sockaddr_in* sockaddr,
- struct UDPInterface_pvt* udpif)
-{
- if (EFFECTIVE_KEY_SIZE < InterfaceController_KEY_SIZE) {
- Bits_memset(key, 0, InterfaceController_KEY_SIZE);
- }
- Bits_memcpyConst(key, sockaddr, EFFECTIVE_KEY_SIZE);
-}
-
static uint8_t sendMessage(struct Message* message, struct Interface* iface)
{
struct UDPInterface_pvt* context = iface->senderContext;
Assert_true(&context->pub.generic == iface);
- struct sockaddr_in sin;
- sockaddrForKey(&sin, message->bytes, context);
- Bits_memcpyConst(&sin, message->bytes, InterfaceController_KEY_SIZE);
- Message_shift(message, -InterfaceController_KEY_SIZE);
+ struct sockaddr_storage addrStore;
+ Message_pop(message, &addrStore, context->addrLen);
if (sendto(context->socket,
message->bytes,
message->length,
0,
- (struct sockaddr*) &sin,
+ (struct sockaddr*) &addrStore,
context->addrLen) < 0)
{
switch (Errno_get()) {
@@ -95,18 +68,7 @@ static uint8_t sendMessage(struct Message* message, struct Interface* iface)
return 0;
}
-/**
- * Release the event used by this module.
- *
- * @param vevent a void pointer cast of the event structure.
- */
-static void freeEvent(void* vevent)
-{
- event_del((struct event*) vevent);
- event_free((struct event*) vevent);
-}
-
-static void handleEvent(evutil_socket_t socket, short eventType, void* vcontext)
+static void handleEvent(void* vcontext)
{
struct UDPInterface_pvt* context = (struct UDPInterface_pvt*) vcontext;
@@ -116,15 +78,14 @@ static void handleEvent(evutil_socket_t socket, short eventType, void* vcontext)
.length = UDPInterface_MAX_PACKET_SIZE
};
- struct sockaddr_storage addrStore;
- Bits_memset(&addrStore, 0, sizeof(struct sockaddr_storage));
- ev_socklen_t addrLen = sizeof(struct sockaddr_storage);
+ struct sockaddr_storage addrStore = { .ss_family = 0 };
+ uint32_t addrLen = sizeof(struct sockaddr_storage);
// Start writing InterfaceController_KEY_SIZE after the beginning,
// keyForSockaddr() will write the key there.
- int rc = recvfrom(socket,
- message.bytes + InterfaceController_KEY_SIZE,
- message.length - InterfaceController_KEY_SIZE,
+ int rc = recvfrom(context->socket,
+ message.bytes,
+ message.length,
0,
(struct sockaddr*) &addrStore,
&addrLen);
@@ -135,9 +96,9 @@ static void handleEvent(evutil_socket_t socket, short eventType, void* vcontext)
if (rc < 0) {
return;
}
- message.length = rc + InterfaceController_KEY_SIZE;
+ message.length = rc;
- keyForSockaddr(message.bytes, (struct sockaddr_in*) &addrStore, context);
+ Message_push(&message, &addrStore, addrLen);
context->pub.generic.receiveMessage(&message, &context->pub.generic);
}
@@ -149,7 +110,7 @@ int UDPInterface_beginConnection(const char* address,
{
struct UDPInterface_pvt* udpif = (struct UDPInterface_pvt*) udp;
struct sockaddr_storage addr;
- ev_socklen_t addrLen = sizeof(struct sockaddr_storage);
+ uint32_t addrLen = sizeof(struct sockaddr_storage);
Bits_memset(&addr, 0, addrLen);
if (evutil_parse_sockaddr_port(address, (struct sockaddr*) &addr, (int*) &addrLen)) {
return UDPInterface_beginConnection_BAD_ADDRESS;
@@ -158,22 +119,22 @@ int UDPInterface_beginConnection(const char* address,
return UDPInterface_beginConnection_ADDRESS_MISMATCH;
}
- uint8_t key[InterfaceController_KEY_SIZE];
- keyForSockaddr(key, (struct sockaddr_in*) &addr, udpif);
- int ret = udpif->ic->insertEndpoint(key, cryptoKey, password, &udpif->pub.generic, udpif->ic);
- switch(ret) {
- case 0:
- return 0;
-
- case InterfaceController_registerInterface_BAD_KEY:
- return UDPInterface_beginConnection_BAD_KEY;
+ struct Interface* iface = MultiInterface_ifaceForKey(udpif->multiIface, &addr);
+ int ret = InterfaceController_registerPeer(udpif->ic, cryptoKey, password, false, iface);
+ if (ret) {
+ Allocator_free(iface->allocator);
+ switch(ret) {
+ case InterfaceController_registerPeer_BAD_KEY:
+ return UDPInterface_beginConnection_BAD_KEY;
- case InterfaceController_registerInterface_OUT_OF_SPACE:
- return UDPInterface_beginConnection_OUT_OF_SPACE;
+ case InterfaceController_registerPeer_OUT_OF_SPACE:
+ return UDPInterface_beginConnection_OUT_OF_SPACE;
- default:
- return UDPInterface_beginConnection_UNKNOWN_ERROR;
+ default:
+ return UDPInterface_beginConnection_UNKNOWN_ERROR;
+ }
}
+ return 0;
}
struct UDPInterface* UDPInterface_new(struct event_base* base,
@@ -207,20 +168,13 @@ struct UDPInterface* UDPInterface_new(struct event_base* base,
"failed to parse address");
}
addrFam = context->addr.ss_family;
-
- // This is because the key size is only 8 bytes.
- // Expanding the key size just for IPv6 doesn't make a lot of sense
- // when ethernet, 802.11 and ipv4 are ok with a shorter key size
- if (context->addr.ss_family != AF_INET || context->addrLen != sizeof(struct sockaddr_in)) {
- Except_raise(exHandler, UDPInterface_new_PROTOCOL_NOT_SUPPORTED,
- "only IPv4 is supported");
- }
-
} else {
addrFam = AF_INET;
- context->addrLen = sizeof(struct sockaddr);
+ context->addrLen = sizeof(struct sockaddr_in);
}
+ context->multiIface = MultiInterface_new(context->addrLen, &context->pub.generic, ic);
+
context->socket = socket(addrFam, SOCK_DGRAM, 0);
if (context->socket == -1) {
Except_raise(exHandler, UDPInterface_new_BIND_FAILED, "call to socket() failed.");
@@ -240,17 +194,7 @@ struct UDPInterface* UDPInterface_new(struct event_base* base,
evutil_make_socket_nonblocking(context->socket);
- context->incomingMessageEvent =
- event_new(base, context->socket, EV_READ | EV_PERSIST, handleEvent, context);
-
- if (!context->incomingMessageEvent || event_add(context->incomingMessageEvent, NULL)) {
- Except_raise(exHandler, UDPInterface_new_FAILED_CREATING_EVENT,
- "failed to create UDPInterface event");
- }
-
- allocator->onFree(freeEvent, context->incomingMessageEvent, allocator);
-
- ic->registerInterface(&context->pub.generic, ic);
+ Event_socketRead(handleEvent, context, context->socket, base, allocator, exHandler);
return &context->pub;
}
View
7 interface/UDPInterface.h
@@ -15,12 +15,11 @@
#ifndef UDPInterface_H
#define UDPInterface_H
-#include "util/events/EventBase.h"
-
#include "interface/Interface.h"
-#include "net/InterfaceController.h"
-#include "util/log/Log.h"
+#include "interface/InterfaceController.h"
#include "memory/Allocator.h"
+#include "util/events/EventBase.h"
+#include "util/log/Log.h"
struct UDPInterface
{
View
2  interface/UDPInterface_admin.c
@@ -17,7 +17,7 @@
#include "exception/Jmp.h"
#include "interface/UDPInterface.h"
#include "memory/Allocator.h"
-#include "net/InterfaceController.h"
+#include "interface/InterfaceController.h"
#include "util/Errno.h"
#include "crypto/Key.h"
View
2  interface/UDPInterface_admin.h
@@ -17,7 +17,7 @@
#include "admin/Admin.h"
#include "memory/Allocator.h"
-#include "net/InterfaceController.h"
+#include "interface/InterfaceController.h"
#include "util/log/Log.h"
#include "util/events/EventBase.h"
View
17 interface/UDPInterface_pvt.h
@@ -16,13 +16,16 @@
#define UDPInterface_pvt_H
#include "util/events/EventBase.h"
+#include "interface/MultiInterface.h"
#include "interface/UDPInterface.h"
-#include "net/InterfaceController.h"
-#include "util/log/Log.h"
+#include "interface/InterfaceController.h"
#include "memory/Allocator.h"
#include "util/Identity.h"
+#include "util/log/Log.h"
+#include "util/platform/Socket.h"
+#include "util/events/Event.h"
-#include <event2/event.h>
+#include <netinet/in.h> // sockaddr_storage
#define UDPInterface_MAX_PACKET_SIZE 8192
@@ -33,19 +36,19 @@ struct UDPInterface_pvt
{
struct UDPInterface pub;
- evutil_socket_t socket;
+ Socket socket;
/**
* The event registered with libevent.
* Needed only so it can be freed.
*/
- struct event* incomingMessageEvent;
+ struct Event* incomingMessageEvent;
/** Used for testing. */
struct sockaddr_storage addr;
/** Used to tell what address type is being used. */
- ev_socklen_t addrLen;
+ uint32_t addrLen;
uint8_t messageBuff[UDPInterface_PADDING + UDPInterface_MAX_PACKET_SIZE];
@@ -53,6 +56,8 @@ struct UDPInterface_pvt
struct InterfaceController* ic;
+ struct MultiInterface* multiIface;
+
Identity
};
View
5 interface/test/CMakeLists.txt
@@ -13,6 +13,11 @@ set(Test_FILES
UDPInterface_test.c
UDPInterface_communication_test.c
ICMP6Generator_test.c
+ MultiInterface_test.c
+)
+set(Test_ROOT_FILES
+ TUNInterface_ipv4_root_test.c
+ TUNInterface_ipv6_root_test.c
)
set(Test_LIBRARIES
cjdns-admin
View
117 interface/test/MultiInterface_test.c
@@ -0,0 +1,117 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program 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 <http://www.gnu.org/licenses/>.
+ */
+#include "crypto/Random.h"
+#include "interface/MultiInterface.h"
+#include "interface/Interface.h"
+#include "interface/InterfaceController.h"
+#include "memory/Allocator.h"
+#include "memory/MallocAllocator.h"
+#include "memory/CanaryAllocator.h"
+#include "wire/Message.h"
+#include "benc/String.h"
+
+
+#define KEY_SIZE 20
+#define ENTRY_COUNT 64
+#define CYCLES 128
+
+struct Entry {
+ uint8_t key[KEY_SIZE];
+};
+
+struct Context
+{
+ struct InterfaceController ic;
+ struct Interface* receivedOn;
+ struct Message* lastSent;
+};
+
+
+static uint8_t sendMessage(struct Message* msg, struct Interface* iface)
+{
+ return 0;
+}
+
+static uint8_t recieveInternal(struct Message* msg, struct Interface* iface)
+{
+ struct Context* ctx = iface->receiverContext;
+ ctx->receivedOn = iface;
+ return 0;
+}
+
+static int registerPeer(struct InterfaceController* ic,
+ uint8_t herPublicKey[32],
+ String* password,
+ bool requireAuth,
+ struct Interface* iface)
+{
+ iface->receiveMessage = recieveInternal;
+ iface->receiverContext = ic;
+ return 0;
+}
+
+
+int main()
+{
+ struct Allocator* alloc = CanaryAllocator_new(MallocAllocator_new(1<<20), NULL);
+ struct Random* rand = Random_new(alloc, NULL);
+
+ // mock interface controller.
+ struct Context ctx = {
+ .ic = {
+ .registerPeer = registerPeer
+ }
+ };
+
+ struct Interface externalIf = {
+ .sendMessage = sendMessage,
+ .allocator = alloc,
+ .senderContext = &ctx
+ };
+
+ /*struct MultiInterface* mif = */MultiInterface_new(KEY_SIZE, &externalIf, &ctx.ic);
+
+ struct Entry* entries = Allocator_malloc(alloc, sizeof(struct Entry) * ENTRY_COUNT);
+ Random_bytes(rand, (uint8_t*)entries, ENTRY_COUNT * sizeof(struct Entry));
+
+ struct Interface** ifaces = Allocator_calloc(alloc, sizeof(char*), ENTRY_COUNT);
+
+ // seed the list with some near collisions.
+ for (int i = 0; i < 10; i++) {
+ int rnd = (((uint32_t*)entries)[i] >> 1) % ENTRY_COUNT;
+ ((uint32_t*) (&entries[rnd]))[0] = ((uint32_t*) (&entries[i]))[0];
+ }
+
+ for (int i = 0; i < CYCLES; i++) {
+ int rnd = ((uint32_t*)entries)[i] % ENTRY_COUNT;
+ struct Entry* entry = &entries[rnd];
+ struct Interface* iface = ifaces[rnd];
+
+ struct Message* msg;
+ Message_STACK(msg, 0, 128);
+
+ Message_push(msg, "hello world", 12);
+ Message_push(msg, entry, 16);
+
+ externalIf.receiveMessage(msg, &externalIf);
+
+ //printf("Received message for iface [%u] from [%p]\n", rnd, (void*)ctx.receivedOn);
+ if (iface) {
+ Assert_always(ctx.receivedOn == iface);
+ } else {
+ ifaces[rnd] = ctx.receivedOn;
+ }
+ }
+}
View
134 interface/test/TUNInterface_ipv4_root_test.c
@@ -0,0 +1,134 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program 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 <http://www.gnu.org/licenses/>.
+ */
+#define string_strcmp
+#define string_strlen
+#include "admin/testframework/AdminTestFramework.h"
+#include "admin/Admin.h"
+#include "admin/AdminClient.h"
+#include "benc/Dict.h"
+#include "benc/String.h"
+#include "benc/Int.h"
+#include "interface/UDPInterface_pvt.h"
+#include "interface/TUNInterface.h"
+#include "interface/TUNConfigurator.h"
+#include "memory/Allocator.h"
+#include "memory/MallocAllocator.h"
+#include "memory/CanaryAllocator.h"
+#include "interface/InterfaceController.h"
+#include "io/FileWriter.h"
+#include "io/Writer.h"
+#include "util/Assert.h"
+#include "util/log/Log.h"
+#include "util/log/WriterLog.h"
+#include "util/platform/libc/string.h"
+#include "util/Timeout.h"
+#include "wire/Ethernet.h"
+#include "wire/Headers.h"
+
+#ifdef BSD
+ #include <netinet/in.h>
+#endif
+
+// On loan from the DoD, thanks guys.
+const uint8_t testAddrA[4] = {11, 0, 0, 1};
+const uint8_t testAddrB[4] = {11, 0, 0, 2};
+
+/*
+ * Setup a UDPInterface and a TUNInterface, test sending traffic between them.
+ */
+
+static int registerPeer(struct InterfaceController* ic,
+ uint8_t herPublicKey[32],
+ String* password,
+ bool requireAuth,
+ struct Interface* iface)
+{
+ return 0;
+}
+
+static int receivedMessageTUNCount = 0;
+static uint8_t receiveMessageTUN(struct Message* msg, struct Interface* iface)
+{
+ receivedMessageTUNCount++;
+ uint16_t ethertype = TUNInterface_popMessageType(msg);
+ Assert_always(ethertype == Ethernet_TYPE_IP4);
+
+ struct Headers_IP4Header* header = (struct Headers_IP4Header*) msg->bytes;
+
+ Assert_always(msg->length == Headers_IP4Header_SIZE + Headers_UDPHeader_SIZE + 12);
+
+ Assert_always(!Bits_memcmp(header->destAddr, testAddrB, 4));
+ Assert_always(!Bits_memcmp(header->sourceAddr, testAddrA, 4));
+
+ Bits_memcpyConst(header->destAddr, testAddrA, 4);
+ Bits_memcpyConst(header->sourceAddr, testAddrB, 4);
+
+ TUNInterface_pushMessageType(msg, ethertype);
+
+ return iface->sendMessage(msg, iface);
+}
+
+static uint8_t receiveMessageUDP(struct Message* msg, struct Interface* iface)
+{
+ if (!receivedMessageTUNCount) {
+ return 0;
+ }
+ // Got the message, test successful.
+ exit(0);
+ return 0;
+}
+
+static void fail(void* ignored)
+{
+ Assert_true(!"timeout");
+}
+
+int main(int argc, char** argv)
+{
+ struct Allocator* alloc = CanaryAllocator_new(MallocAllocator_new(1<<20), NULL);
+ struct EventBase* base = EventBase_new(alloc);
+ struct Writer* logWriter = FileWriter_new(stdout, alloc);
+ struct Log* logger = WriterLog_new(logWriter, alloc);
+
+ // mock interface controller.
+ struct InterfaceController ic = {
+ .registerPeer = registerPeer
+ };
+
+ char assignedInterfaceName[TUNConfigurator_IFNAMSIZ];
+ void* tunPtr = TUNConfigurator_initTun(NULL, assignedInterfaceName, logger, NULL);
+ TUNConfigurator_addIp4Address(assignedInterfaceName, testAddrA, 30, logger, NULL);
+ struct TUNInterface* tun = TUNInterface_new(tunPtr, base, alloc);
+
+ struct UDPInterface* udp = UDPInterface_new(base, "11.0.0.1:5000", alloc, NULL, logger, &ic);
+
+ struct sockaddr_in sin = { .sin_family = AF_INET };
+ sin.sin_port = Endian_hostToBigEndian16(5000);
+ Bits_memcpy(&sin.sin_addr, testAddrB, 4);
+
+ struct Message* msg;
+ Message_STACK(msg, 0, 64);
+ Message_push(msg, "Hello World", 12);
+ Message_push(msg, &sin, sizeof(struct sockaddr_in));
+
+ udp->generic.receiveMessage = receiveMessageUDP;
+ tun->iface.receiveMessage = receiveMessageTUN;
+
+ udp->generic.sendMessage(msg, &udp->generic);
+
+ Timeout_setTimeout(fail, NULL, 1000, base, alloc);
+
+ EventBase_beginLoop(base);
+}
View
133 interface/test/TUNInterface_ipv6_root_test.c
@@ -0,0 +1,133 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program 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 <http://www.gnu.org/licenses/>.
+ */
+#define string_strcmp
+#define string_strlen
+#include "admin/testframework/AdminTestFramework.h"
+#include "admin/Admin.h"
+#include "admin/AdminClient.h"
+#include "benc/Dict.h"
+#include "benc/String.h"
+#include "benc/Int.h"
+#include "interface/UDPInterface_pvt.h"
+#include "interface/TUNInterface.h"
+#include "interface/TUNConfigurator.h"
+#include "memory/Allocator.h"
+#include "memory/MallocAllocator.h"
+#include "memory/CanaryAllocator.h"
+#include "interface/InterfaceController.h"
+#include "io/FileWriter.h"
+#include "io/Writer.h"
+#include "util/Assert.h"
+#include "util/log/Log.h"
+#include "util/log/WriterLog.h"
+#include "util/platform/libc/string.h"
+#include "util/Timeout.h"
+#include "wire/Ethernet.h"
+#include "wire/Headers.h"
+
+#ifdef BSD
+ #include <netinet/in.h>
+#endif
+
+const uint8_t testAddrA[] = {0xfd,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
+const uint8_t testAddrB[] = {0xfd,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2};
+
+/*
+ * Setup a UDPInterface and a TUNInterface, test sending traffic between them.
+ */
+
+static int registerPeer(struct InterfaceController* ic,
+ uint8_t herPublicKey[32],
+ String* password,
+ bool requireAuth,
+ struct Interface* iface)
+{
+ return 0;
+}
+
+static int receivedMessageTUNCount = 0;
+static uint8_t receiveMessageTUN(struct Message* msg, struct Interface* iface)
+{
+ receivedMessageTUNCount++;
+ uint16_t ethertype = TUNInterface_popMessageType(msg);
+ Assert_always(ethertype == Ethernet_TYPE_IP6);
+
+ struct Headers_IP6Header* header = (struct Headers_IP6Header*) msg->bytes;
+
+ Assert_always(msg->length == Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE + 12);
+
+ Assert_always(!Bits_memcmp(header->destinationAddr, testAddrB, 16));
+ Assert_always(!Bits_memcmp(header->sourceAddr, testAddrA, 16));
+
+ Bits_memcpyConst(header->destinationAddr, testAddrA, 16);
+ Bits_memcpyConst(header->sourceAddr, testAddrB, 16);
+
+ TUNInterface_pushMessageType(msg, ethertype);
+
+ return iface->sendMessage(msg, iface);
+}
+
+static uint8_t receiveMessageUDP(struct Message* msg, struct Interface* iface)
+{
+ if (!receivedMessageTUNCount) {
+ // return 0;
+ }
+ // Got the message, test successful.
+ exit(0);
+ return 0;
+}
+
+static void fail(void* ignored)
+{
+ Assert_true(!"timeout");
+}
+
+int main(int argc, char** argv)
+{
+ struct Allocator* alloc = CanaryAllocator_new(MallocAllocator_new(1<<20), NULL);
+ struct EventBase* base = EventBase_new(alloc);
+ struct Writer* logWriter = FileWriter_new(stdout, alloc);
+ struct Log* logger = WriterLog_new(logWriter, alloc);
+
+ // mock interface controller.
+ struct InterfaceController ic = {
+ .registerPeer = registerPeer
+ };
+
+ char assignedInterfaceName[TUNConfigurator_IFNAMSIZ];
+ void* tunPtr = TUNConfigurator_initTun(NULL, assignedInterfaceName, logger, NULL);
+ TUNConfigurator_addIp6Address(assignedInterfaceName, testAddrA, 126, logger, NULL);
+ struct TUNInterface* tun = TUNInterface_new(tunPtr, base, alloc);
+
+ struct UDPInterface* udp = UDPInterface_new(base, "[fd00::1]:5000", alloc, NULL, logger, &ic);
+
+ struct sockaddr_in6 sin = { .sin6_family = AF_INET6 };
+ sin.sin6_port = Endian_hostToBigEndian16(5000);
+ Bits_memcpy(&sin.sin6_addr, testAddrB, 16);
+
+ struct Message* msg;
+ Message_STACK(msg, 0, 64);
+ Message_push(msg, "Hello World", 12);
+ Message_push(msg, &sin, sizeof(struct sockaddr_in6));