Browse files

IpTunnel set IP addresses automatically.

  • Loading branch information...
1 parent 1d026b0 commit c8d2024fa7a36187b80414c417794e4981537e0a Caleb James DeLisle committed Feb 5, 2013
View
10 admin/Admin.c
@@ -417,9 +417,13 @@ static void handleMessage(struct Message* message,
struct Allocator* alloc,
struct Admin* admin)
{
- message->bytes[message->length] = '\0';
- Log_keys(admin->logger, "Got message from [%s] [%s]",
- Sockaddr_print(src, alloc), message->bytes);
+ #ifdef Log_KEYS
+ uint8_t lastChar = message->bytes[message->length - 1];
+ message->bytes[message->length - 1] = '\0';
+ Log_keys(admin->logger, "Got message from [%s] [%s]",
+ Sockaddr_print(src, alloc), message->bytes);
+ message->bytes[message->length - 1] = lastChar;
+ #endif
// handle non empty message data
if (message->length > Admin_MAX_REQUEST_SIZE) {
View
66 admin/angel/Angel.c
@@ -14,8 +14,11 @@
*/
#include "admin/Admin.h"
#include "admin/angel/Angel.h"
+#include "benc/Int.h"
#include "benc/String.h"
+#include "exception/Jmp.h"
#include "memory/Allocator.h"
+#include "interface/TUNConfigurator.h"
#include "interface/Interface.h"
#include "interface/addressable/AddrInterfaceAdapter.h"
#include "util/events/EventBase.h"
@@ -41,6 +44,63 @@ static void adminExit(Dict* args, void* vcontext, String* txid)
exit(0);
}
+static void adminAddIp2(char* interfaceName,
+ struct Sockaddr* addr,
+ int prefixLen,
+ String* txid,
+ struct Allocator* tempAlloc,
+ struct AngelContext* ctx)
+{
+ struct Jmp j;
+ Jmp_try(j) {
+ uint8_t* addrBytes = NULL;
+ Sockaddr_getAddress(addr, &addrBytes);
+ if (Sockaddr_getFamily(addr) == Sockaddr_AF_INET6) {
+ TUNConfigurator_addIp6Address(interfaceName, addrBytes, prefixLen, NULL, &j.handler);
+ } else if (Sockaddr_getFamily(addr) == Sockaddr_AF_INET) {
+ TUNConfigurator_addIp4Address(interfaceName, addrBytes, prefixLen, NULL, &j.handler);
+ } else {
+ Dict d = Dict_CONST(
+ String_CONST("error"), String_OBJ(String_CONST("Address not IPv4 or IPv6")), NULL
+ );
+ Admin_sendMessage(&d, txid, ctx->admin);
+ return;
+ }
+ } Jmp_catch {
+ Dict d = Dict_CONST(
+ String_CONST("error"), String_OBJ(String_CONST(j.message)), NULL
+ );
+ Admin_sendMessage(&d, txid, ctx->admin);
+ return;
+ }
+
+ Dict d = Dict_CONST(
+ String_CONST("error"), String_OBJ(String_CONST("none")), NULL
+ );
+ Admin_sendMessage(&d, txid, ctx->admin);
+}
+
+static void adminAddIp(Dict* args, void* vcontext, String* txid)
+{
+ struct AngelContext* ctx = Identity_cast((struct AngelContext*) vcontext);
+ String* interfaceName = Dict_getString(args, String_CONST("interfaceName"));
+ String* address = Dict_getString(args, String_CONST("address"));
+ int64_t* prefixLenP = Dict_getInt(args, String_CONST("prefixLen"));
+ int prefixLen = *prefixLenP;
+
+ struct Sockaddr_storage ss;
+ if (Sockaddr_parse(address->bytes, &ss)) {
+ Dict d = Dict_CONST(
+ String_CONST("error"), String_OBJ(String_CONST("Failed to parse addesss")), NULL
+ );
+ Admin_sendMessage(&d, txid, ctx->admin);
+ } else {
+ struct Allocator* tempAlloc = Allocator_child(ctx->alloc);
+ adminAddIp2(interfaceName->bytes, &ss.addr, prefixLen, txid, tempAlloc, ctx);
+ Allocator_free(tempAlloc);
+ }
+}
+
void Angel_start(struct Interface* coreIface,
struct EventBase* eventBase,
struct Log* logger,
@@ -61,5 +121,11 @@ void Angel_start(struct Interface* coreIface,
Admin_registerFunction("Angel_exit", adminExit, &ctx, false, NULL, ctx.admin);
+ Admin_registerFunction("Angel_addIp", adminAddIp, &ctx, false, ((struct Admin_FunctionArg[]) {
+ { .name = "interfaceName", .required = 1, .type = "String" },
+ { .name = "address", .required = 1, .type = "String" },
+ { .name = "prefixLen", .required = 1, .type = "Int" }
+ }), ctx.admin);
+
EventBase_beginLoop(eventBase);
}
View
7 admin/angel/CMakeLists.txt
@@ -38,15 +38,20 @@ target_link_libraries(cjdns-angel
cjdns-memory-canary
cjdns-util-platform-socket
cjdns-interface-addressable-adapter
+ cjdns-interface-tuntap
+)
+
+add_library(cjdns-admin-hermes
+ Hermes.c
)
add_library(cjdns-core
Core.c
Core_admin.c
- Hermes.c
)
target_link_libraries(cjdns-core
+ cjdns-admin-hermes
crypto
interface
switch
View
10 admin/angel/Core.c
@@ -175,6 +175,7 @@ void Core_initTunnel(String* desiredDeviceName,
uint8_t addressPrefix,
struct Ducttape* dt,
struct Log* logger,
+ struct IpTunnel* ipTunnel,
struct EventBase* eventBase,
struct Allocator* alloc,
struct Except* eh)
@@ -197,6 +198,7 @@ void Core_initTunnel(String* desiredDeviceName,
TUNConfigurator_addIp6Address(assignedTunName, ipAddr, addressPrefix, logger, eh);
TUNConfigurator_setMTU(assignedTunName, DEFAULT_MTU, logger, eh);
+ IpTunnel_setTunName(assignedTunName, ipTunnel);
}
/** This is a response from a call which is intended only to send information to the angel. */
@@ -247,9 +249,11 @@ int Core_main(int argc, char** argv)
// The first read inside of getInitialConfig() will begin it waiting.
struct PipeInterface* pi =
PipeInterface_new(fromAngel, toAngel, eventBase, logger, alloc, rand);
- struct Hermes* hermes = Hermes_new(&pi->generic, eventBase, logger, alloc);
Dict* config = getInitialConfig(&pi->generic, eventBase, tempAlloc, eh);
+
+ struct Hermes* hermes = Hermes_new(&pi->generic, eventBase, logger, alloc);
+
String* privateKeyHex = Dict_getString(config, String_CONST("privateKey"));
Dict* adminConf = Dict_getDict(config, String_CONST("admin"));
String* pass = Dict_getString(adminConf, String_CONST("pass"));
@@ -321,7 +325,7 @@ int Core_main(int argc, char** argv)
SerializationModule_register(registry, logger, alloc);
- struct IpTunnel* ipTun = IpTunnel_new(logger, eventBase, alloc, rand, admin);
+ struct IpTunnel* ipTun = IpTunnel_new(logger, eventBase, alloc, rand, hermes);
struct Ducttape* dt = Ducttape_register(privateKey,
registry,
@@ -357,7 +361,7 @@ int Core_main(int argc, char** argv)
RouterModule_admin_register(router, admin, alloc);
AuthorizedPasswords_init(admin, cryptoAuth, alloc);
Admin_registerFunction("ping", adminPing, admin, false, NULL, admin);
- Core_admin_register(addr.ip6.bytes, dt, logger, alloc, admin, eventBase);
+ Core_admin_register(addr.ip6.bytes, dt, logger, ipTun, alloc, admin, eventBase);
Security_admin_register(alloc, logger, admin);
IpTunnel_admin_register(ipTun, admin, alloc);
View
1 admin/angel/Core.h
@@ -26,6 +26,7 @@ void Core_initTunnel(String* desiredDeviceName,
uint8_t addressPrefix,
struct Ducttape* dt,
struct Log* logger,
+ struct IpTunnel* ipTunnel,
struct EventBase* eventBase,
struct Allocator* alloc,
struct Except* eh);
View
4 admin/angel/Core_admin.c
@@ -27,6 +27,7 @@ struct Context
struct Allocator* alloc;
struct Admin* admin;
struct EventBase* eventBase;
+ struct IpTunnel* ipTunnel;
};
static void sendResponse(String* error,
@@ -53,6 +54,7 @@ static void initTunnel(Dict* args, void* vcontext, String* txid)
8,
ctx->ducttape,
ctx->logger,
+ ctx->ipTunnel,
ctx->eventBase,
ctx->alloc,
&jmp.handler);
@@ -68,6 +70,7 @@ static void initTunnel(Dict* args, void* vcontext, String* txid)
void Core_admin_register(uint8_t ipAddr[16],
struct Ducttape* dt,
struct Log* logger,
+ struct IpTunnel* ipTunnel,
struct Allocator* alloc,
struct Admin* admin,
struct EventBase* eventBase)
@@ -79,6 +82,7 @@ void Core_admin_register(uint8_t ipAddr[16],
ctx->alloc = alloc;
ctx->admin = admin;
ctx->eventBase = eventBase;
+ ctx->ipTunnel = ipTunnel;
struct Admin_FunctionArg args[] = {
{ .name = "desiredTunName", .required = 0, .type = "String" }
View
1 admin/angel/Core_admin.h
@@ -26,6 +26,7 @@
void Core_admin_register(uint8_t ipAddr[16],
struct Ducttape* dt,
struct Log* logger,
+ struct IpTunnel* ipTunnel,
struct Allocator* alloc,
struct Admin* admin,
struct EventBase* eventBase);
View
11 admin/angel/Hermes.c
@@ -29,7 +29,7 @@
#include "util/Identity.h"
#include "util/Hex.h"
-#define REQ_TIMEOUT 2048
+#define REQ_TIMEOUT 10000
struct Request
{
@@ -80,8 +80,10 @@ static void timeout(void* vrequest)
static void receiveMessage2(struct Message* msg, struct Hermes* hermes, struct Allocator* tempAlloc)
{
#ifdef Log_KEYS
- msg->bytes[msg->length] = '\0';
- Log_keys(hermes->logger, "Got message from angel [%s]", msg->bytes);
+ char lastChr = msg->bytes[msg->length - 1];
+ msg->bytes[msg->length - 1] = '\0';
+ Log_keys(hermes->logger, "Got message from angel [%s%c]", msg->bytes, lastChr);
+ msg->bytes[msg->length - 1] = lastChr;
#else
Log_debug(hermes->logger, "Got message from angel");
#endif
@@ -95,7 +97,8 @@ static void receiveMessage2(struct Message* msg, struct Hermes* hermes, struct A
String* txid = Dict_getString(&d, String_CONST("txid"));
uint32_t handle;
- if (!txid || txid->len != 8 || Hex_decode((uint8_t*)&handle, 4, (uint8_t*)txid->bytes, 8)) {
+ if (!txid || txid->len != 8 || 4 != Hex_decode((uint8_t*)&handle, 4, (uint8_t*)txid->bytes, 8))
+ {
Log_warn(hermes->logger, "Message from angel; txid missing or unrecognized");
return;
}
View
6 admin/angel/Hermes.h
@@ -38,12 +38,14 @@ typedef void (* Hermes_onResponse)(Dict* responseMessage, void* context);
* @param message the message to send, the txid key is reserved and will
* be overwritten.
* @param onResponse a callback which will be called with the response
- * from the angel.
+ * from the angel. This callback will also be called if
+ * there is no response and the request times out.
* @param onResponseContext a pointer which will be provided to onResponse.
* @param alloc an allocator for the request, if this allocator is freed
* before the response happens, the onResponse will not be
* called, this prevents a race condition when the structure
- * pointed to be context is freed after a call.
+ * pointed to be context is freed after a call. The allocator
+ * need not be freed after the request is complete.
* @param eh an exception handler which might raise:
* Hermes_callAngel_ESERIALIZE if serializing the message failed.
* Hermes_callAngel_ESEND if sending the message failed.
View
15 admin/angel/cjdroute2.c
@@ -322,7 +322,16 @@ static int genconf(struct Random* rand)
" \"nofiles\",\n"
"\n"
" // Change the user id to this user after starting up and getting resources.\n"
- " {\"setuser\": \"nobody\"}\n"
+ " {\n"
+ " \"setuser\": \"nobody\"\n"
+ "\n"
+ " // Exempt the Angel process from setting userId, the Angel is a small\n"
+ " // isolated piece of code which exists outside of the core's strict\n"
+ " // sandbox but does not handle network traffic.\n"
+ " // This must be enabled for IpTunnel to automatically set IP addresses\n"
+ " // for the TUN device.\n"
+ " \"exemptAngel\": 1\n"
+ " }\n"
" ],\n"
"\n"
" // Version of the config file, used internally for migration.\n"
@@ -474,6 +483,10 @@ int main(int argc, char** argv)
for (int i = 0; i < List_size(securityConf); i++) {
securityUser = Dict_getString(List_getDict(securityConf, i), String_CONST("setuser"));
if (securityUser) {
+ int64_t* ea = Dict_getInt(List_getDict(securityConf, i), String_CONST("exemptAngel"));
+ if (ea && *ea) {
+ securityUser = NULL;
+ }
break;
}
}
View
10 interface/CMakeLists.txt
@@ -22,20 +22,24 @@ if(HAS_ETH_INTERFACE)
set(ethif ETHInterface_${SYSTEM}.c ETHInterface_admin.c)
endif()
+add_library(cjdns-interface-tuntap
+ TUNConfigurator_${SYSTEM}.c
+ TUNMessageType.c
+ ${tunif}
+)
+
add_library(interface
UDPInterface.c
UDPInterface_admin.c
${ethif}
- ${tunif}
- TUNConfigurator_${SYSTEM}.c
- TUNMessageType.c
InterfaceConnector.c
SessionManager.c
ICMP6Generator.c
MultiInterface.c
)
target_link_libraries(interface
+ cjdns-interface-tuntap
util
cjdns-crypto-key
cjdns-util-platform-socket
View
10 interface/PipeInterface.c
@@ -23,6 +23,7 @@
#include "util/log/Log.h"
#include <unistd.h>
+#include <inttypes.h>
#define PING_FREQUENCY_MILLISECONDS 3000
#define LAG_MAX_BEFORE_DISCONNECT 10000
@@ -156,6 +157,8 @@ static bool tryReestablish(struct PipeInterface_pvt* context)
Log_debug(context->logger, "Reestablished synchronization, off by [%u] bytes",
(uint32_t) (nextFrame - context->message.as.bytes));
return true;
+ } else {
+ Log_debug(context->logger, "Failed to reestablish connection");
}
return false;
}
@@ -224,6 +227,7 @@ static bool handleMessage(struct PipeInterface_pvt* context)
}
} else {
Log_debug(context->logger, "Lost synchronization");
+
context->pub.state = PipeInterface_State_LOST;
bool ret = tryReestablish(context);
sendPing(context);
@@ -232,7 +236,8 @@ static bool handleMessage(struct PipeInterface_pvt* context)
}
}
} else if (context->pub.state == PipeInterface_State_INITIALIZING) {
- Log_debug(context->logger, "[%p] Established Synchronization", (void*) context);
+ Log_debug(context->logger, "[%p] Established Synchronization with magic [%" PRIX64 "]",
+ (void*) context, Endian_bigEndianToHost64(context->syncMagic));
context->pub.state = PipeInterface_State_ESTABLISHED;
} else if (context->isWaiting) {
context->isWaiting = false;
@@ -366,6 +371,9 @@ struct PipeInterface* PipeInterface_new(int inPipe,
Log_info(logger, "Creating new PipeInterface [%p]", (void*)context);
+ Socket_makeNonBlocking(inPipe);
+ Socket_makeNonBlocking(outPipe);
+
context->pingInterval = Timeout_setInterval(handleTimeout,
context,
PING_FREQUENCY_MILLISECONDS,
View
1 tunnel/CMakeLists.txt
@@ -18,6 +18,7 @@ add_library(cjdns-tunnel-iptunnel
target_link_libraries(cjdns-tunnel-iptunnel
cjdbenc
interface
+ cjdns-admin-hermes
)
enable_testing()
View
88 tunnel/IpTunnel.c
@@ -12,13 +12,15 @@
* 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 "admin/Admin.h"
+#include "admin/angel/Hermes.h"
#include "benc/String.h"
#include "benc/Dict.h"
#include "benc/List.h"
+#include "benc/Int.h"
#include "benc/serialization/standard/StandardBencSerializer.h"
#include "benc/serialization/BencSerializer.h"
#include "crypto/random/Random.h"
+#include "exception/Jmp.h"
#include "io/ArrayWriter.h"
#include "io/ArrayReader.h"
#include "interface/TUNMessageType.h"
@@ -50,14 +52,18 @@ struct IpTunnel_pvt
/** An always incrementing number which represents the connections. */
uint32_t nextConnectionNumber;
+ /** The name of the TUN interface so that ip addresses can be added. */
+ String* ifName;
+
/**
* Every 10 seconds check for connections which the other end has
* not provided ip addresses and send more requests.
*/
struct Timeout* timeout;
struct Random* rand;
- struct Admin* admin;
+ /** The angel connector for setting IP addresses. */
+ struct Hermes* hermes;
/** For verifying the integrity of the structure. */
Identity
@@ -345,6 +351,42 @@ static uint8_t requestForAddresses(Dict* request,
return sendControlMessage(msg, conn, context);
}
+static void addAddressCallback(Dict* responseMessage, void* vcontext)
+{
+ struct IpTunnel_pvt* ctx = Identity_cast((struct IpTunnel_pvt*) vcontext);
+ char* err = "invalid response";
+ String* error = Dict_getString(responseMessage, String_CONST("error"));
+ if (error) {
+ err = error->bytes;
+ }
+ if (!error || !String_equals(error, String_CONST("none"))) {
+ Log_error(ctx->logger, "Error setting ip address on TUN [%s]", err);
+ }
+}
+
+static void addAddress(char* printedAddr, struct IpTunnel_pvt* ctx)
+{
+ if (!ctx->ifName) {
+ Log_error(ctx->logger, "Failed to set IP address because TUN interface is not setup");
+ return;
+ }
+ struct Jmp j;
+ Jmp_try(j) {
+ Dict args = Dict_CONST(
+ String_CONST("address"), String_OBJ(String_CONST(printedAddr)), Dict_CONST(
+ String_CONST("interfaceName"), String_OBJ(ctx->ifName), Dict_CONST(
+ String_CONST("prefixLen"), Int_OBJ(0), NULL
+ )));
+ Dict msg = Dict_CONST(
+ String_CONST("args"), Dict_OBJ(&args), Dict_CONST(
+ String_CONST("q"), String_OBJ(String_CONST("Angel_addIp")), NULL
+ ));
+ Hermes_callAngel(&msg, addAddressCallback, ctx, ctx->allocator, &j.handler, ctx->hermes);
+ } Jmp_catch {
+ Log_error(ctx->logger, "Error setting ip address on TUN [%s]", j.message);
+ }
+}
+
static int incomingAddresses(Dict* d,
struct IpTunnel_Connection* conn,
struct Allocator* alloc,
@@ -389,21 +431,33 @@ static int incomingAddresses(Dict* d,
String* ip4 = Dict_getString(addresses, String_CONST("ip4"));
if (ip4 && ip4->len == 4) {
Bits_memcpyConst(conn->connectionIp4, ip4->bytes, 4);
- #ifdef Log_INFO
- Log_info(context->logger, "Got issued address [%u.%u.%u.%u] for connection [%d]",
- ip4->bytes[0], ip4->bytes[1], ip4->bytes[2], ip4->bytes[3], conn->number);
- #endif
+
+ struct Sockaddr* sa = Sockaddr_clone(Sockaddr_LOOPBACK, alloc);
+ uint8_t* addrBytes = NULL;
+ Sockaddr_getAddress(sa, &addrBytes);
+ Bits_memcpy(addrBytes, ip4->bytes, 4);
+ char* printedAddr = Sockaddr_print(sa, alloc);
+
+ Log_info(context->logger, "Got issued address [%s] for connection [%d]",
+ printedAddr, conn->number);
+
+ addAddress(printedAddr, context);
}
String* ip6 = Dict_getString(addresses, String_CONST("ip6"));
if (ip6 && ip6->len == 16) {
Bits_memcpyConst(conn->connectionIp6, ip6->bytes, 16);
- #ifdef Log_INFO
- uint8_t addr[40];
- AddrTools_printIp(addr, (uint8_t*)ip6->bytes);
- Log_info(context->logger, "Got issued address [%s] for connection [%d]",
- addr, conn->number);
- #endif
+
+ struct Sockaddr* sa = Sockaddr_clone(Sockaddr_LOOPBACK6, alloc);
+ uint8_t* addrBytes = NULL;
+ Sockaddr_getAddress(sa, &addrBytes);
+ Bits_memcpy(addrBytes, ip6->bytes, 16);
+ char* printedAddr = Sockaddr_print(sa, alloc);
+
+ Log_info(context->logger, "Got issued address [%s] for connection [%d]",
+ printedAddr, conn->number);
+
+ addAddress(printedAddr, context);
}
return 0;
}
@@ -654,11 +708,17 @@ static void timeout(void* vcontext)
} while ((++i % (int32_t)context->pub.connectionList.count) != beginning);
}
+void IpTunnel_setTunName(char* interfaceName, struct IpTunnel* ipTun)
+{
+ struct IpTunnel_pvt* ctx = Identity_cast((struct IpTunnel_pvt*) ipTun);
+ ctx->ifName = String_new(interfaceName, ctx->allocator);
+}
+
struct IpTunnel* IpTunnel_new(struct Log* logger,
struct EventBase* eventBase,
struct Allocator* alloc,
struct Random* rand,
- struct Admin* admin)
+ struct Hermes* hermes)
{
struct IpTunnel_pvt* context =
alloc->clone(sizeof(struct IpTunnel_pvt), alloc, &(struct IpTunnel_pvt) {
@@ -669,7 +729,7 @@ struct IpTunnel* IpTunnel_new(struct Log* logger,
.allocator = alloc,
.logger = logger,
.rand = rand,
- .admin = admin
+ .hermes = hermes
});
context->timeout = Timeout_setInterval(timeout, context, 10000, eventBase, alloc);
Identity_set(context);
View
9 tunnel/IpTunnel.h
@@ -15,7 +15,7 @@
#ifndef IpTunnel_H
#define IpTunnel_H
-#include "admin/Admin.h"
+#include "admin/angel/Hermes.h"
#include "crypto/random/Random.h"
#include "interface/Interface.h"
#include "memory/Allocator.h"
@@ -86,12 +86,14 @@ struct IpTunnel
* @param logger a logger or NULL.
* @param eventBase the event base.
* @param alloc an allocator.
+ * @param rand a random generator.
+ * @param hermes the Hermes admin connector.
*/
struct IpTunnel* IpTunnel_new(struct Log* logger,
struct EventBase* eventBase,
struct Allocator* alloc,
struct Random* rand,
- struct Admin* admin);
+ struct Hermes* hermes);
/**
* Allow another node to tunnel IPv4 and/or ICANN IPv6 through this node.
@@ -128,4 +130,7 @@ int IpTunnel_connectTo(uint8_t publicKeyOfNodeToConnectTo[32], struct IpTunnel*
int IpTunnel_removeConnection(int connectionNumber, struct IpTunnel* tunnel);
+void IpTunnel_setTunName(char* interfaceName, struct IpTunnel* ipTun);
+
+
#endif

0 comments on commit c8d2024

Please sign in to comment.