Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Major refactoring, use at your own risk

  • Loading branch information...
commit 9a30efed891e384f67fb8c7783886155d30db4cd 1 parent 806792a
Caleb James DeLisle authored
View
14 admin/Admin.c
@@ -59,6 +59,8 @@ struct Admin
struct Function* functions;
int functionCount;
struct Allocator* allocator;
+ struct sockaddr_storage address;
+ int addressLength;
String* password;
/** Becomes true after the admin process has sent it's first message. */
@@ -478,6 +480,8 @@ struct Admin* Admin_new(struct sockaddr_storage* addr,
admin->functionCount = 0;
admin->eventBase = eventBase;
admin->password = password;
+ memcpy(&admin->address, addr, sizeof(struct sockaddr_storage));
+ admin->addressLength = addrLen;
admin->pipeEv = event_new(eventBase, inFd, EV_READ | EV_PERSIST, inFromChild, admin);
event_add(admin->pipeEv, NULL);
@@ -485,3 +489,13 @@ struct Admin* Admin_new(struct sockaddr_storage* addr,
return admin;
}
+
+void Admin_getConnectInfo(struct sockaddr_storage** addrPtr,
+ int* addrLenPtr,
+ String** passwordPtr,
+ struct Admin* admin)
+{
+ *addrPtr = &admin->address;
+ *addrLenPtr = admin->addressLength;
+ *passwordPtr = admin->password;
+}
View
5 admin/Admin.h
@@ -39,4 +39,9 @@ struct Admin* Admin_new(struct sockaddr_storage* addr,
struct event_base* eventBase,
struct ExceptionHandler* eh,
struct Allocator* allocator);
+
+void Admin_getConnectInfo(struct sockaddr_storage** addrPtr,
+ int* addrLenPtr,
+ String** passwordPtr,
+ struct Admin* admin);
#endif
View
122 admin/Configurator.c
@@ -132,46 +132,6 @@ static void sendMessage(Dict* message, struct Context* ctx)
evtimer_del(timeoutEvent);
}
-static void authorizedPasswords(List* list, struct Context* ctx)
-{
- uint32_t count = List_size(list);
- for (uint32_t i = 0; i < count; i++) {
- Dict* d = List_getDict(list, i);
- Log_info1(ctx->logger, "Checking authorized password %d.", i);
- if (!d) {
- Log_critical1(ctx->logger, "Not a dictionary type.", i);
- exit(-1);
- }
- String* passwd = Dict_getString(d, String_CONST("password"));
- if (!passwd) {
- Log_critical1(ctx->logger, "Must specify a password.", i);
- exit(-1);
- }
- }
-
- Log_info(ctx->logger, "Flushing existing authorized passwords");
- Dict message = Dict_CONST(
- String_CONST("q"), String_OBJ(String_CONST("auth")), Dict_CONST(
- String_CONST("aq"), String_OBJ(String_CONST("AuthorizedPasswords_flush")), NULL
- ));
- sendMessage(&message, ctx);
-
- for (uint32_t i = 0; i < count; i++) {
- Dict* d = List_getDict(list, i);
- String* passwd = Dict_getString(d, String_CONST("password"));
- Log_info1(ctx->logger, "Adding authorized password %d.", i);
-
- Dict message = Dict_CONST(
- String_CONST("q"), String_OBJ(String_CONST("auth")), Dict_CONST(
- String_CONST("aq"), String_OBJ(String_CONST("AuthorizedPasswords_add")), Dict_CONST(
- String_CONST("authType"), Int_OBJ(1), Dict_CONST(
- String_CONST("password"), String_OBJ(passwd), NULL
- ))));
-
- sendMessage(&message, ctx);
- }
-}
-
static void incoming(evutil_socket_t socket, short eventType, void* vcontext)
{
struct Context* ctx = (struct Context*) vcontext;
@@ -224,6 +184,81 @@ static void incoming(evutil_socket_t socket, short eventType, void* vcontext)
event_base_loopexit(ctx->eventBase, NULL);
}
+static void rpcCall(String* function, Dict* args, struct Context* ctx)
+{
+ Dict message = Dict_CONST(
+ String_CONST("q"), String_OBJ(String_CONST("auth")), Dict_CONST(
+ String_CONST("aq"), String_OBJ(function), Dict_CONST(
+ String_CONST("args"), Dict_OBJ(args), NULL
+ )));
+ sendMessage(&message, ctx);
+}
+
+static void authorizedPasswords(List* list, struct Context* ctx)
+{
+ uint32_t count = List_size(list);
+ for (uint32_t i = 0; i < count; i++) {
+ Dict* d = List_getDict(list, i);
+ Log_info1(ctx->logger, "Checking authorized password %d.", i);
+ if (!d) {
+ Log_critical1(ctx->logger, "Not a dictionary type.", i);
+ exit(-1);
+ }
+ String* passwd = Dict_getString(d, String_CONST("password"));
+ if (!passwd) {
+ Log_critical1(ctx->logger, "Must specify a password.", i);
+ exit(-1);
+ }
+ }
+
+ Log_info(ctx->logger, "Flushing existing authorized passwords");
+ Dict message = Dict_CONST(
+ String_CONST("q"), String_OBJ(String_CONST("auth")), Dict_CONST(
+ String_CONST("aq"), String_OBJ(String_CONST("AuthorizedPasswords_flush")), NULL
+ ));
+ sendMessage(&message, ctx);
+
+ for (uint32_t i = 0; i < count; i++) {
+ Dict* d = List_getDict(list, i);
+ String* passwd = Dict_getString(d, String_CONST("password"));
+ Log_info1(ctx->logger, "Adding authorized password %d.", i);
+
+ Dict message = Dict_CONST(
+ String_CONST("q"), String_OBJ(String_CONST("auth")), Dict_CONST(
+ String_CONST("aq"), String_OBJ(String_CONST("AuthorizedPasswords_add")), Dict_CONST(
+ String_CONST("authType"), Int_OBJ(1), Dict_CONST(
+ String_CONST("password"), String_OBJ(passwd), NULL
+ ))));
+
+ sendMessage(&message, ctx);
+ }
+}
+
+static void udpInterface(Dict* config, struct Allocator* tempAlloc, struct Context* ctx)
+{
+ Dict* udp = Dict_getDict(config, String_CONST("UDPInterface"));
+ Dict* connectTo = Dict_getDict(udp, String_CONST("connectTo"));
+ if (connectTo) {
+ struct Dict_Entry* entry = *connectTo;
+ while (entry != NULL) {
+ String* key = (String*) entry->key;
+ if (entry->val->type != Object_DICT) {
+ fprintf(stderr,
+ "interfaces.UDPInterface.connectTo: entry [%s] is not a dictionary type.\n",
+ key->bytes);
+ abort();
+ }
+ Dict* value = entry->val->as.dictionary;
+
+ Log_info1(ctx->logger, "Attempting to connect to node [%s].", key->bytes);
+ Dict_putString(value, String_CONST("address"), key, tempAlloc);
+ rpcCall(String_CONST("UDPInterface_beginConnection"), value, ctx);
+
+ entry = entry->next;
+ }
+ }
+}
+
void Configurator_config(Dict* config,
struct sockaddr_storage* addr,
int addrLen,
@@ -251,11 +286,18 @@ void Configurator_config(Dict* config,
event_new(context.eventBase, context.socket, EV_READ | EV_PERSIST, incoming, &context);
event_add(context.socketEvent, NULL);
+ uint8_t buffer[256];
+ struct Allocator* tmpAlloc = BufferAllocator_new(buffer, 256);
+
List* authedPasswords = Dict_getList(config, String_CONST("authorizedPasswords"));
if (authedPasswords) {
authorizedPasswords(authedPasswords, &context);
}
+ Dict* ifaces = Dict_getDict(config, String_CONST("interfaces"));
+
+ udpInterface(ifaces, tmpAlloc, &context);
+
close(context.socket);
event_del(context.socketEvent);
}
View
1  benc/Dict.h
@@ -175,5 +175,6 @@ Dict* Dict_new(const struct Allocator* allocator);
.next = nextDict \
})
+#define Dict_OBJ(x) (&(Object) { .type = Object_DICT, .as.dictionary = x })
#endif
View
168 cjdroute.c
@@ -360,136 +360,6 @@ static void reconf(struct Context* ctx, Dict* mainConf)
Configurator_config(mainConf, &addr, addrLen, password, ctx->base, ctx->logger, ctx->allocator);
}
-static uint8_t serverFirstIncoming(struct Message* msg, struct Interface* iface)
-{
- struct UDPInterfaceContext* uictx = (struct UDPInterfaceContext*) iface->receiverContext;
-
- struct Interface* udpDefault = UDPInterface_getDefaultInterface(uictx->udpContext);
- assert(udpDefault);
- UDPInterface_bindToCurrentEndpoint(udpDefault);
-
- struct User* u = CryptoAuth_getUser(iface);
- assert(u);
- // Add it to the switch, this will change the receiveMessage for this interface.
- struct Address addr;
- memset(&addr, 0, sizeof(struct Address));
- SwitchCore_addInterface(iface, u->trust, &addr.networkAddress_be, uictx->context->switchCore);
-
- uint8_t* herKey = CryptoAuth_getHerPublicKey(iface);
- memcpy(addr.key, herKey, 32);
- uint8_t printedAddr[60];
- Address_print(printedAddr, &addr);
- Log_info1(uictx->context->logger,
- "Node %s has connected to us.\n",
- printedAddr);
-
- // Prepare for the next connection.
- struct Interface* newUdpDefault = UDPInterface_getDefaultInterface(uictx->udpContext);
- struct Interface* newAuthedUdpDefault =
- CryptoAuth_wrapInterface(newUdpDefault, NULL, true, true, uictx->context->ca);
- newAuthedUdpDefault->receiveMessage = serverFirstIncoming;
- newAuthedUdpDefault->receiverContext = uictx;
-
- // Send the message on to the switch so the first message isn't lost.
- return iface->receiveMessage(msg, iface);
-}
-
-static void udpConnectTo(String* connectToAddress,
- Dict* config,
- struct UDPInterface* udpContext,
- struct Context* ctx)
-{
- String* password = Dict_getString(config, BSTR("password"));
- String* publicKey = Dict_getString(config, BSTR("publicKey"));
-
- #define FAIL_IF_NULL(cannotBeNull, fieldName) \
- if (!cannotBeNull) { \
- fprintf(stderr, \
- "interfaces.UDPInterface['%s']." fieldName " is not set, " \
- "this field is mandatory.\n", \
- connectToAddress->bytes); \
- exit(-1); \
- }
-
- FAIL_IF_NULL(password, "password")
- FAIL_IF_NULL(publicKey, "publicKey")
-
- #undef FAIL_IF_NULL
-
-
- uint8_t pkBytes[32];
- if (publicKey->len < 52 || Base32_decode(pkBytes, 32, (uint8_t*)publicKey->bytes, 52) != 32) {
- fprintf(stderr,
- "interfaces.UDPInterface['%s'].publicKey could not be parsed.\n",
- connectToAddress->bytes);
- exit(-1);
- }
- uint8_t addressBytes[16];
- AddressCalc_addressForPublicKey(addressBytes, pkBytes);
- if (addressBytes[0] != 0xFC) {
- fprintf(stderr,
- "interfaces.UDPInterface['%s'].publicKey\n( %s )\nis not in FC00/8 range, "
- "it was probably mistranscribed.\n",
- connectToAddress->bytes,
- publicKey->bytes);
- exit(-1);
- }
-
- struct Interface* udp =
- UDPInterface_addEndpoint(udpContext, connectToAddress->bytes, ctx->eHandler);
- struct Interface* authedUdp = CryptoAuth_wrapInterface(udp, pkBytes, false, true, ctx->ca);
- CryptoAuth_setAuth(password, 1, authedUdp);
-
- uint64_t switchAddr_be;
- SwitchCore_addInterface(authedUdp, 0, &switchAddr_be, ctx->switchCore);
- struct Address addr;
- memset(&addr, 0, sizeof(struct Address));
- memcpy(addr.key, pkBytes, 32);
- addr.networkAddress_be = switchAddr_be;
- RouterModule_addNode(&addr, ctx->routerModule);
-}
-
-static void configureUDP(Dict* config, struct Context* ctx)
-{
- String* bindStr = Dict_getString(config, BSTR("bind"));
- char* bindAddress = bindStr ? bindStr->bytes : NULL;
-
- struct UDPInterface* udpContext =
- UDPInterface_new(ctx->base, bindAddress, ctx->allocator, ctx->eHandler, ctx->logger);
-
- if (bindStr) {
- struct Interface* udpDefault = UDPInterface_getDefaultInterface(udpContext);
- struct Interface* authedDef =
- CryptoAuth_wrapInterface(udpDefault, NULL, true, true, ctx->ca);
-
- struct UDPInterfaceContext* uictx =
- ctx->allocator->malloc(sizeof(struct UDPInterfaceContext), ctx->allocator);
- uictx->context = ctx;
- uictx->udpContext = udpContext;
- authedDef->receiveMessage = serverFirstIncoming;
- authedDef->receiverContext = uictx;
- }
-
- Dict* connectTo = Dict_getDict(config, BSTR("connectTo"));
- if (connectTo) {
- struct Dict_Entry* entry = *connectTo;
- while (entry != NULL) {
- String* key = (String*) entry->key;
- if (entry->val->type != Object_DICT) {
- fprintf(stderr,
- "interfaces.UDPInterface.connectTo: entry %s is not a dictionary type.\n",
- key->bytes);
- abort();
- }
- Dict* value = entry->val->as.dictionary;
-
- udpConnectTo(key, value, udpContext, ctx);
-
- entry = entry->next;
- }
- }
-}
-
static void registerRouter(Dict* config, struct Address *addr, struct Context* context)
{
Dict* iface = Dict_getDict(config, BSTR("interface"));
@@ -612,14 +482,6 @@ static void admin(Dict* mainConf, char* user, struct Log* logger, struct Context
AuthorizedPasswords_init(context->admin, context->ca, context->allocator);
Admin_registerFunction("ping", adminPing, context->admin, false, context->admin);
Admin_registerFunction("memory", adminMemory, context, false, context->admin);
-
- Configurator_config(mainConf,
- &addr,
- addrLen,
- password,
- context->base,
- logger,
- context->allocator);
}
static void pidfile(Dict* config)
@@ -724,11 +586,25 @@ int main(int argc, char** argv)
SerializationModule_register(context.registry, context.allocator);
// Interfaces.
+ struct InterfaceController* ifController =
+ InterfaceController_new(context.ca,
+ context.switchCore,
+ context.routerModule,
+ context.logger,
+ context.allocator);
+
Dict* interfaces = Dict_getDict(&config, BSTR("interfaces"));
- Dict* udpConf = Dict_getDict(interfaces, BSTR("UDPInterface"));
+ Dict* udpConf = Dict_getDict(interfaces, BSTR("UDPInterface"));
if (udpConf) {
- configureUDP(udpConf, &context);
+ String* bindStr = Dict_getString(udpConf, BSTR("bind"));
+ UDPInterface_new(context.base,
+ (bindStr) ? bindStr->bytes : NULL,
+ context.allocator,
+ context.eHandler,
+ context.logger,
+ ifController,
+ context.admin);
}
if (udpConf == NULL) {
@@ -752,6 +628,18 @@ int main(int argc, char** argv)
fclose(pf);
}
+ struct sockaddr_storage* adminAddr;
+ int adminAddrLen;
+ String* adminPassword;
+ Admin_getConnectInfo(&adminAddr, &adminAddrLen, &adminPassword, context.admin);
+ Configurator_config(&config,
+ adminAddr,
+ adminAddrLen,
+ adminPassword,
+ context.base,
+ &logger,
+ context.allocator);
+
Ducttape_register(&config,
privateKey,
context.registry,
View
14 crypto/test/CryptoAuth_unit_test.c
@@ -94,7 +94,7 @@ void randombytes(unsigned char* buffer,unsigned long long size)
memset(buffer, 0xFF, size);
}
-struct Wrapper* setUp(uint8_t* myPrivateKey,
+struct CryptoAuth_Wrapper* setUp(uint8_t* myPrivateKey,
uint8_t* herPublicKey,
uint8_t* authPassword,
struct Message** resultMessage)
@@ -110,8 +110,8 @@ struct Wrapper* setUp(uint8_t* myPrivateKey,
.senderContext = resultMessage
});
- struct Wrapper* wrapper =
- allocator->clone(sizeof(struct Wrapper), allocator, &(struct Wrapper) {
+ struct CryptoAuth_Wrapper* wrapper =
+ allocator->clone(sizeof(struct CryptoAuth_Wrapper), allocator, &(struct CryptoAuth_Wrapper) {
.context = ca,
.wrappedInterface = iface
});
@@ -136,7 +136,7 @@ void testHello(uint8_t* password, uint8_t* expectedOutput)
{
assert(strlen((char*)expectedOutput) == 264);
struct Message* outMessage;
- struct Wrapper* wrapper =
+ struct CryptoAuth_Wrapper* wrapper =
setUp(NULL, (uint8_t*) "wxyzabcdefghijklmnopqrstuv987654", password, &outMessage);
uint8_t msgBuff[Headers_CryptoAuth_SIZE + 12];
@@ -200,7 +200,7 @@ void receiveHelloWithNoAuth()
.bytes = message
};
- struct Wrapper* wrapper = setUp(privateKey, NULL, NULL, NULL);
+ struct CryptoAuth_Wrapper* wrapper = setUp(privateKey, NULL, NULL, NULL);
struct Message* finalOut = NULL;
wrapper->externalInterface.receiveMessage = receiveMessage;
@@ -228,7 +228,7 @@ void repeatHello()
.senderContext = &out
};
- struct Wrapper wrapper = {
+ struct CryptoAuth_Wrapper wrapper = {
.context = ca,
.wrappedInterface = &iface
};
@@ -255,7 +255,7 @@ void repeatHello()
ca = CryptoAuth_new(NULL, allocator, privateKey, eventBase, &logger);
struct Message* finalOut = NULL;
- struct Wrapper wrapper2 = {
+ struct CryptoAuth_Wrapper wrapper2 = {
.context = ca,
.externalInterface = {
.receiveMessage = receiveMessage,
View
2  crypto/test/Exports.c
@@ -41,7 +41,7 @@ int Exports_decryptRndNonce(uint8_t nonce[24], struct Message* msg, uint8_t secr
return decryptRndNonce(nonce, msg, secret);
}
-uint8_t Exports_encryptHandshake(struct Message* message, struct Wrapper* wrapper)
+uint8_t Exports_encryptHandshake(struct Message* message, struct CryptoAuth_Wrapper* wrapper)
{
return encryptHandshake(message, wrapper);
}
View
2  crypto/test/Exports.h
@@ -23,7 +23,7 @@ void Exports_encryptRndNonce(uint8_t nonce[24], struct Message* msg, uint8_t sec
int Exports_decryptRndNonce(uint8_t nonce[24], struct Message* msg, uint8_t secret[32]);
-uint8_t Exports_encryptHandshake(struct Message* message, struct Wrapper* wrapper);
+uint8_t Exports_encryptHandshake(struct Message* message, struct CryptoAuth_Wrapper* wrapper);
void Exports_receiveMessage(struct Message* received, struct Interface* interface);
View
3  interface/CMakeLists.txt
@@ -16,9 +16,10 @@ add_library(interface
TUNInterface.c
TUNConfigurator.c
InterfaceConnector.c
+ InterfaceController.c
SessionManager.c
)
-target_link_libraries(interface ${LIBEVENT2_LIBRARIES})
+target_link_libraries(interface util ${LIBEVENT2_LIBRARIES})
enable_testing()
#add_subdirectory(test)
View
356 interface/InterfaceController.c
@@ -0,0 +1,356 @@
+/*
+ * 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/CryptoAuth_struct.h"
+#include "interface/InterfaceController.h"
+#include "interface/InterfaceMap.h"
+#include "memory/Allocator.h"
+#include "util/Time.h"
+#include "wire/Error.h"
+#include "wire/Message.h"
+
+
+/** Maximum number of interfaces (should be same as number of switch slots). */
+#define MAX_INTERFACES 255
+
+
+/*--------------------Structs--------------------*/
+
+struct Endpoint
+{
+ /**
+ * The internal interface, this is on the external side of the CryptoAuth.
+ * This is wrapped by CryptoAuth and incoming packets from the CryptoAuth go to
+ * receivedAfterCryptoAuth() then to the switch.
+ */
+ struct Interface internal;
+
+ /** The switch's receiverMessage callback, needed for adding receivedAfterCryptoAuth(). */
+ Interface_CALLBACK(switchReceiveMessage);
+
+ /** The switch's receiverContext, needed for adding receivedAfterCryptoAuth(). */
+ void* switchReceiverContext;
+
+ struct Interface* cryptoAuthIf;
+
+ /**
+ * The external (network side) interface,
+ * this is the same for all endpoints using this network module.
+ */
+ struct Interface* external;
+
+ /** The lookup key for this endpoint (ip/mac address) */
+ uint8_t key[InterfaceController_KEY_SIZE];
+
+ /**
+ * True after the CryptoAuth handshake is completed.
+ * This is used to check for a registeration of a node which is already registered in a
+ * different switch slot, if there is one and the handshake completes, it will be moved.
+ */
+ bool authenticated : 1;
+
+ /** If true then the entry will be removed if it sits too long with no incoming message. */
+ bool removeIfExpires : 1;
+
+ /**
+ * The time of the last incoming message, used to clear out endpoints
+ * if they are not responsive. Only updated if removeIfExpires == true.
+ */
+ uint32_t timeOfLastMessage;
+};
+
+struct InterfaceController
+{
+ /** Used to get an endpoint by it's lookup key, endpoint.internal is entered into the map. */
+ struct InterfaceMap* imap;
+
+ struct Endpoint endpoints[MAX_INTERFACES];
+
+ struct Allocator* allocator;
+
+ struct CryptoAuth* ca;
+
+ /** Switch for adding nodes when they are discovered. */
+ struct SwitchCore* switchCore;
+
+ /** Router needed to inject newly added nodes to bootstrap the system. */
+ struct RouterModule* routerModule;
+
+ struct Log* logger;
+
+ struct event_base* eventBase;
+};
+
+struct InterfaceController* InterfaceController_new(struct CryptoAuth* ca,
+ struct SwitchCore* switchCore,
+ struct RouterModule* routerModule,
+ struct Log* logger,
+ struct Allocator* allocator)
+{
+ struct InterfaceController* ic =
+ allocator->calloc(sizeof(struct InterfaceController), 1, allocator);
+ ic->imap = InterfaceMap_new(InterfaceController_KEY_SIZE, allocator);
+ ic->allocator = allocator;
+ ic->ca = ca;
+ ic->switchCore = switchCore;
+ ic->routerModule = routerModule;
+ ic->logger = logger;
+ return ic;
+}
+
+static inline struct Endpoint* endpointForInternalInterface(struct Interface* iface)
+{
+ return (struct Endpoint*) (((char*)iface) - offsetof(struct Endpoint, internal));
+}
+
+/** If there's already an endpoint with the same public key, merge the new one with the old one. */
+static inline void moveEndpointIfNeeded(struct Endpoint** epPtr,
+ struct InterfaceController* ic)
+{
+ struct Endpoint* ep = *epPtr;
+ uint8_t* key = CryptoAuth_getHerPublicKey(ep->cryptoAuthIf);
+ for (int i = 0; i < MAX_INTERFACES; i++) {
+ struct Endpoint* thisEp = &ic->endpoints[i];
+ if (thisEp != ep
+ && thisEp->authenticated
+ && !memcmp(CryptoAuth_getHerPublicKey(thisEp->cryptoAuthIf), key, 32))
+ {
+ memcpy(thisEp->key, ep->key, InterfaceController_KEY_SIZE);
+
+ // This is a mess.
+ // We copy the CryptoAuth session over so the user is able to `hijack'
+ // their old session seamlessly.
+ memcpy(thisEp->cryptoAuthIf->receiverContext,
+ ep->cryptoAuthIf->receiverContext,
+ sizeof(struct CryptoAuth_Wrapper));
+
+ *epPtr = thisEp;
+ ep->cryptoAuthIf->allocator->free(ep->cryptoAuthIf->allocator);
+ }
+ }
+}
+
+// Incoming message which has passed through the cryptoauth and needs to be forwarded to the switch.
+static uint8_t receivedAfterCryptoAuth(struct Message* msg, struct Interface* cryptoAuthIf)
+{
+ struct Endpoint* ep = cryptoAuthIf->receiverContext;
+ struct InterfaceController* ic = ep->internal.senderContext;
+
+ if (ep->removeIfExpires) {
+ ep->timeOfLastMessage = Time_currentTimeSeconds(ic->eventBase);
+ }
+ if (!ep->authenticated) {
+ if (CryptoAuth_getState(cryptoAuthIf) == CryptoAuth_ESTABLISHED) {
+ moveEndpointIfNeeded(&ep, ic);
+ ep->authenticated = true;
+ }
+ }
+
+ // yet another hack to make this asymmetric flow thing work.
+ return ep->switchReceiveMessage(msg, &(struct Interface) {
+ .receiverContext = ep->switchReceiverContext
+ });
+}
+
+static void closeInterface(void* vendpoint)
+{
+ struct Endpoint* toClose = (struct Endpoint*) vendpoint;
+ struct InterfaceController* ic = toClose->internal.senderContext;
+
+ int index = InterfaceMap_indexOf(toClose->key, ic->imap);
+ InterfaceMap_remove(index, ic->imap);
+
+ // make sure not to reorder the entries because InterfaceMap points to them.
+ memset(toClose, 0, sizeof(struct Endpoint));
+}
+
+/**
+ * Take a message from the switch (which has already been encrypted) and prepend the key.
+ * Send the result on to the actual network level interface.
+ */
+static uint8_t sendMessage(struct Message* message, struct Interface* iface)
+{
+ struct Endpoint* ep = endpointForInternalInterface(iface);
+
+ Message_shift(message, InterfaceController_KEY_SIZE);
+ memcpy(message->bytes, ep->key, InterfaceController_KEY_SIZE);
+
+ return ep->external->sendMessage(message, ep->external);
+}
+
+static inline struct Endpoint* getEndpoint(uint8_t key[InterfaceController_KEY_SIZE],
+ struct InterfaceController* ic)
+{
+ int index = InterfaceMap_indexOf(key, ic->imap);
+ if (index > -1) {
+ struct Endpoint* ep = endpointForInternalInterface(ic->imap->interfaces[index]);
+ #ifdef Log_DEBUG
+ assert(ep->external || !"Entry was not removed from the map but was null.");
+ assert(!memcmp(key, ep->key, InterfaceController_KEY_SIZE));
+ #endif
+ return ep;
+ }
+ return NULL;
+}
+
+/**
+ * Allow for a configurable which makes different network interfaces require or not require auth.
+ * An IPv4 interface might require auth to connect while an 802.11 interface
+ * allows anyone to connect.
+ */
+static inline bool requiresAuth(struct Interface* networkInterface, struct InterfaceController* ic)
+{
+ // TODO: add configuration.
+ return true;
+}
+
+static uint8_t receiveMessage(struct Message* msg, struct Interface* iface);
+
+/**
+ * Add a new endpoint.
+ * 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 requireAuth if true then the other end must supply a valid password on connect.
+ * @param password the password for authenticating to the other node or null if none.
+ * @param externalInterface the network interface which is used to connect to this node.
+ * @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
+ * is freed, we would expect all of it's children to deregister.
+ * @return the newly inserted endpoint, NULL if there is no space to add one.
+ */
+static struct Endpoint* insertEndpoint(uint8_t key[InterfaceController_KEY_SIZE],
+ uint8_t herPublicKey[32],
+ bool requireAuth,
+ String* password,
+ struct Interface* externalInterface,
+ struct InterfaceController* ic)
+{
+ // scan for an unused endpoint slot.
+ struct Endpoint* ep = NULL;
+ for (int i = 0; i < MAX_INTERFACES; i++) {
+ if (ic->endpoints[i].external == NULL) {
+ ep = &ic->endpoints[i];
+ break;
+ }
+ }
+ if (!ep) {
+ return NULL;
+ }
+
+ struct Allocator* epAllocator =
+ externalInterface->allocator->child(externalInterface->allocator);
+ epAllocator->onFree(closeInterface, &ep, epAllocator);
+
+ externalInterface->receiverContext = ic;
+ externalInterface->receiveMessage = receiveMessage;
+
+ ep->external = externalInterface;
+ memcpy(&ep->key, key, InterfaceController_KEY_SIZE);
+ InterfaceMap_put(key, &ep->internal, 0, ic->imap);
+
+ // Outgoing: switch -> cryptoAuth -> sendMessage() -> external
+ // Incoming: external -> receiveMessage() -> cryptoAuth -> postCryptoAuth() -> switch
+
+ memcpy(&ep->internal, (&(struct Interface) {
+ .senderContext = ep,
+ .sendMessage = sendMessage,
+ .allocator = epAllocator,
+ .maxMessageLength = externalInterface->maxMessageLength,
+ .requiredPadding = InterfaceController_KEY_SIZE + externalInterface->requiredPadding
+ }), sizeof(struct Interface));
+
+ struct Interface* authedIf =
+ CryptoAuth_wrapInterface(&ep->internal, herPublicKey, requireAuth, true, ic->ca);
+
+ // Always use authType 1 until something else comes along, then we'll have to refactor.
+ if (password) {
+ CryptoAuth_setAuth(password, 1, authedIf);
+ }
+ ep->cryptoAuthIf = authedIf;
+
+ struct Address addr;
+ memset(&addr, 0, sizeof(struct Address));
+ if (SwitchCore_addInterface(authedIf, 0, &addr.networkAddress_be, ic->switchCore)) {
+ return NULL;
+ }
+
+
+ // Hack:
+ // Store switchReceiverContext and switchReceiveMessage in the ep and change them to add
+ // another level of indirection on the incoming side but not on the outgoing side.
+ ep->switchReceiveMessage = authedIf->receiveMessage;
+ ep->switchReceiverContext = authedIf->receiverContext;
+ authedIf->receiveMessage = receivedAfterCryptoAuth;
+ authedIf->receiverContext = ep;
+
+
+ if (herPublicKey) {
+ memcpy(addr.key, herPublicKey, 32);
+ RouterModule_addNode(&addr, ic->routerModule);
+ #ifdef Log_INFO
+ uint8_t printAddr[60];
+ Address_print(printAddr, &addr);
+ Log_info1(ic->logger, "Adding direct peer %s.", printAddr);
+ #endif
+ #ifdef Log_KEYS
+ uint8_t keyHex[2 * InterfaceController_KEY_SIZE + 1];
+ Hex_encode(keyHex, sizeof(keyHex), key, InterfaceController_KEY_SIZE);
+ Log_keys1(ic->logger, "With connection identifier [%s]", keyHex);
+ #endif
+ }
+
+ return ep;
+}
+
+static uint8_t receiveMessage(struct Message* msg, struct Interface* iface)
+{
+ struct InterfaceController* ic = iface->receiverContext;
+ struct Endpoint* ep = getEndpoint(msg->bytes, ic);
+ if (ep) {
+ Message_shift(msg, -InterfaceController_KEY_SIZE);
+ return ep->internal.receiveMessage(msg, &ep->internal);
+ }
+
+ // Not a known peer, add them.
+ ep = insertEndpoint(msg->bytes, NULL, requiresAuth(iface, ic), NULL, iface, ic);
+
+ if (!ep) {
+ Log_warn(ic->logger, "Could not insert endpoint, out of space in switch.");
+ return Error_NONE;
+ } else {
+ #ifdef Log_KEYS
+ uint8_t keyHex[2 * InterfaceController_KEY_SIZE + 1];
+ Hex_encode(keyHex, sizeof(keyHex), msg->bytes, InterfaceController_KEY_SIZE);
+ Log_keys1(ic->logger, "Got incoming connection request from [%s]", keyHex);
+ #else
+ Log_info(ic->logger, "Got incoming connection request.");
+ #endif
+ }
+
+ // Send the message on to the switch so the first message isn't lost.
+ Message_shift(msg, -InterfaceController_KEY_SIZE);
+ return ep->internal.receiveMessage(msg, &ep->internal);
+}
+
+int InterfaceController_insertEndpoint(uint8_t key[InterfaceController_KEY_SIZE],
+ uint8_t herPublicKey[32],
+ String* password,
+ struct Interface* externalInterface,
+ struct InterfaceController* ic)
+{
+ return (insertEndpoint(key, herPublicKey, false, password, externalInterface, ic)) ? 0 : -1;
+}
View
58 interface/InterfaceController.h
@@ -0,0 +1,58 @@
+/*
+ * 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 InterfaceController_H
+#define InterfaceController_H
+
+#include "crypto/CryptoAuth.h"
+#include "dht/dhtcore/RouterModule.h"
+#include "interface/Interface.h"
+#include "memory/Allocator.h"
+#include "switch/SwitchCore.h"
+#include "util/Log.h"
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/** The number of bytes used to discriminate between endpoints. */
+#define InterfaceController_KEY_SIZE 8
+
+struct InterfaceController;
+
+struct InterfaceController* InterfaceController_new(struct CryptoAuth* ca,
+ struct SwitchCore* switchCore,
+ struct RouterModule* routerModule,
+ struct Log* logger,
+ struct Allocator* allocator);
+
+/**
+ * Add a new endpoint.
+ * 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 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
+ * is freed, we would expect all of it's children to deregister.
+ * @return -1 if there are no more slots to insert a node, otherwise zero.
+ */
+int InterfaceController_insertEndpoint(uint8_t key[InterfaceController_KEY_SIZE],
+ uint8_t herPublicKey[32],
+ String* password,
+ struct Interface* externalInterface,
+ struct InterfaceController* ic);
+
+#endif
View
377 interface/UDPInterface.c
@@ -11,12 +11,16 @@
* 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 "exception/ExceptionHandler.h"
#include "interface/Interface.h"
+#include "interface/InterfaceController.h"
#include "interface/UDPInterface.h"
#include "memory/Allocator.h"
#include "memory/BufferAllocator.h"
#include "util/Endian.h"
+#include "util/Base32.h"
#include "wire/Message.h"
#include "wire/Error.h"
@@ -43,17 +47,10 @@ static void handleEvent(evutil_socket_t socket, short eventType, void* vcontext)
/*--------------------Structs--------------------*/
-struct Endpoint
+struct UDPInterface
{
- /** The ip address where messages to this endpoint should go. */
- struct sockaddr_storage addr;
-
- /** the public api. */
struct Interface interface;
-};
-struct UDPInterface
-{
evutil_socket_t socket;
/**
@@ -65,62 +62,29 @@ struct UDPInterface
/** Used to tell what address type is being used. */
int addrLen;
- /**
- * The ip address / interface mapping.
- * Although this is 4 bytes, it compares the full sockaddr so this will work with ip6.
- */
- uint32_t addresses[MAX_INTERFACES];
- struct Endpoint endpoints[MAX_INTERFACES];
- uint32_t endpointCount;
-
- struct Allocator* allocator;
-
- /** The interface which will get all traffic for which there is no endpoint. */
- struct Interface* defaultInterface;
+ uint8_t messageBuff[MAX_PACKET_SIZE];
- /**
- * This will be set while receiveMessage() is being called by the default interface.
- * It is used by UDPInterface_bindToCurrentEndpoint(), the rest of the time it is NULL.
- */
- struct sockaddr_storage* defaultInterfaceSender;
+ struct Log* logger;
- uint8_t* messageBuff;
+ struct InterfaceController* ic;
- struct Log* logger;
+ struct Admin* admin;
};
-static void closeInterface(void* vcontext)
-{
- struct Interface* toClose = (struct Interface*) vcontext;
- struct UDPInterface* context = toClose->senderContext;
- for (uint32_t i = 0; i < context->endpointCount; i++) {
- if (&context->endpoints[i].interface == toClose)
- {
- context->addresses[i] = context->addresses[context->endpointCount - 1];
- memcpy(&context->endpoints[i],
- &context->endpoints[context->endpointCount - 1],
- sizeof(struct Endpoint));
- context->endpointCount--;
- return;
- }
- }
- assert(!"Tried to close an interface which wasn't found.");
-}
-
static uint8_t sendMessage(struct Message* message, struct Interface* iface)
{
- struct UDPInterface* context = (struct UDPInterface*) iface->senderContext;
- assert(context->defaultInterface != iface
- || !"Error: can't send traffic to the default interface");
+ struct UDPInterface* context = iface->senderContext;
+ assert(&context->interface == iface);
- struct Endpoint* ep =
- (struct Endpoint*) (((char*)iface) - offsetof(struct Endpoint, interface));
+ struct sockaddr_in sin;
+ memcpy(&sin, message->bytes, InterfaceController_KEY_SIZE);
+ Message_shift(message, -InterfaceController_KEY_SIZE);
if (sendto(context->socket,
message->bytes,
message->length,
0,
- (struct sockaddr*) &ep->addr,
+ (struct sockaddr*) &sin,
context->addrLen) < 0)
{
switch (errno) {
@@ -135,23 +99,143 @@ static uint8_t sendMessage(struct Message* message, struct Interface* iface)
return Error_LINK_LIMIT_EXCEEDED;
default:;
- Log_debug1(context->logger, "Got error sending to socket errno=%d", errno);
- };
+ Log_info1(context->logger, "Got error sending to socket errno=%d", errno);
+ }
}
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)
+{
+ struct UDPInterface* context = (struct UDPInterface*) vcontext;
+
+ struct Message message =
+ { .bytes = context->messageBuff + PADDING, .padding = PADDING, .length = MAX_PACKET_SIZE };
+
+ struct sockaddr_storage addrStore;
+ memset(&addrStore, 0, sizeof(struct sockaddr_storage));
+ int addrLen = sizeof(struct sockaddr_storage);
+ int rc = recvfrom(socket,
+ message.bytes + InterfaceController_KEY_SIZE,
+ MAX_PACKET_SIZE - InterfaceController_KEY_SIZE,
+ 0,
+ (struct sockaddr*) &addrStore,
+ (socklen_t*) &addrLen);
+ /*
+ Log_debug1(context->logger,
+ "Got message from peer on port %u\n",
+ Endian_bigEndianToHost16(((struct sockaddr_in*) &addrStore)->sin_port));
+ */
+ if (addrLen != context->addrLen) {
+ return;
+ }
+ if (rc < 0) {
+ return;
+ }
+ message.length = rc + InterfaceController_KEY_SIZE;
+
+ memcpy(message.bytes, &addrStore, InterfaceController_KEY_SIZE);
+
+ context->interface.receiveMessage(&message, &context->interface);
+}
+
+int UDPInterface_beginConnection(const char* address,
+ uint8_t cryptoKey[32],
+ String* password,
+ struct UDPInterface* udpif)
+{
+ struct sockaddr_storage addr;
+ int addrLen = sizeof(struct sockaddr_storage);
+ memset(&addr, 0, addrLen);
+ if (evutil_parse_sockaddr_port(address, (struct sockaddr*) &addr, &addrLen)) {
+ return -2;
+ }
+ if (addrLen != udpif->addrLen) {
+ return -3;
+ }
+
+ uint8_t key[InterfaceController_KEY_SIZE];
+ memcpy(key, &addr, InterfaceController_KEY_SIZE);
+ return InterfaceController_insertEndpoint(key, cryptoKey, password, &udpif->interface, udpif->ic);
+}
+
+static void beginConnectionAdmin(Dict* ap, void* vcontext, String* txid)
+{
+ struct UDPInterface* udpif = (struct UDPInterface*) vcontext;
+
+ Dict* args = Dict_getDict(ap, String_CONST("args"));
+ String* password = Dict_getString(args, String_CONST("password"));
+ String* publicKey = Dict_getString(args, String_CONST("publicKey"));
+ String* address = Dict_getString(args, String_CONST("address"));
+ String* error = NULL;
+
+ uint8_t pkBytes[32];
+
+ if (!address) {
+ error = String_CONST("address unspecified or not a string.");
+
+ } else if (!publicKey) {
+ error = String_CONST("publicKey unspecified or not a string.");
+
+ } else if (publicKey->len < 52) {
+ error = String_CONST("publicKey is too short, must be 52 characters long.");
+
+ } else if (Base32_decode(pkBytes, 32, (uint8_t*)publicKey->bytes, 52) != 32) {
+ error = String_CONST("failed to parse publicKey.");
+
+ } else {
+ switch (UDPInterface_beginConnection(address->bytes, pkBytes, password, udpif)) {
+ case -1:
+ error = String_CONST("no more space to register with the switch.");
+ break;
+ case -2:
+ error = String_CONST("unable to parse ip address and port.");
+ break;
+ case -3:
+ error = String_CONST("different address type than this socket is bound to.");
+ break;
+ case 0:
+ error = String_CONST("none");
+ break;
+ default:
+ error = String_CONST("unknown error");
+ }
+ }
+
+ Dict out = Dict_CONST(String_CONST("error"), String_OBJ(error), NULL);
+ Admin_sendMessage(&out, txid, udpif->admin);
+}
+
struct UDPInterface* UDPInterface_new(struct event_base* base,
const char* bindAddr,
struct Allocator* allocator,
struct ExceptionHandler* exHandler,
- struct Log* logger)
+ struct Log* logger,
+ struct InterfaceController* ic,
+ struct Admin* admin)
{
- struct UDPInterface* context = allocator->calloc(sizeof(struct UDPInterface), 1, allocator);
-
- context->messageBuff = allocator->calloc(MAX_PACKET_SIZE + PADDING, 1, allocator);
- context->logger = logger;
- context->allocator = allocator;
+ struct UDPInterface* context = allocator->malloc(sizeof(struct UDPInterface), allocator);
+ memcpy(context, (&(struct UDPInterface) {
+ .interface = {
+ .sendMessage = sendMessage,
+ .senderContext = context,
+ .allocator = allocator
+ },
+ .logger = logger,
+ .ic = ic,
+ .admin = admin
+ }), sizeof(struct UDPInterface));
sa_family_t addrFam;
struct sockaddr_storage addr;
@@ -163,6 +247,16 @@ struct UDPInterface* UDPInterface_new(struct event_base* base,
return NULL;
}
addrFam = 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 (addr.ss_family == AF_INET6) {
+ exHandler->exception(__FILE__ " UDPInterface_new() IPv6 transport not supported.",
+ -4,
+ exHandler);
+ }
+
} else {
addrFam = AF_INET;
context->addrLen = sizeof(struct sockaddr);
@@ -197,164 +291,11 @@ struct UDPInterface* UDPInterface_new(struct event_base* base,
allocator->onFree(freeEvent, context->incomingMessageEvent, allocator);
- return context;
-}
-
-/**
- * This is a trick to speed up lookup of addresses.
- * For ipv4 addresses it will match the whole address
- * For ipv6 and other addresses, it will be a match but the user must check that the whole
- * sockaddr matches before using it.
- */
-static inline uint32_t getAddr(struct sockaddr_storage* addr)
-{
- uint32_t out;
- memcpy(&out, ((uint8_t*)addr) + 4, 4);
- return out;
-}
-
-static struct Interface* insertEndpoint(struct sockaddr_storage* addr,
- struct UDPInterface* context)
-{
- if (context->endpointCount >= MAX_INTERFACES) {
- return NULL;
- }
-
- struct Allocator* epAllocator = context->allocator->child(context->allocator);
- struct Endpoint* ep = &context->endpoints[context->endpointCount];
- memcpy(&ep->addr, addr, sizeof(struct sockaddr_storage));
-
- struct Interface iface = {
- .senderContext = context,
- .sendMessage = sendMessage,
- .allocator = epAllocator,
- .maxMessageLength = MAX_PACKET_SIZE,
- .requiredPadding = 0
- };
- memcpy(&ep->interface, &iface, sizeof(struct Interface));
-
- epAllocator->onFree(closeInterface, &ep->interface, epAllocator);
-
- context->addresses[context->endpointCount] = getAddr(addr);
- context->endpointCount++;
-
- return &ep->interface;
-}
-
-struct Interface* UDPInterface_addEndpoint(struct UDPInterface* context,
- const char* endpointSockAddr,
- struct ExceptionHandler* exHandler)
-{
- struct sockaddr_storage addr;
- int addrLen = sizeof(struct sockaddr_storage);
- if (0 != evutil_parse_sockaddr_port(endpointSockAddr, (struct sockaddr*) &addr, &addrLen)) {
- exHandler->exception(__FILE__ " UDPInterface_addEndpoint() failed to parse address.",
- -1, exHandler);
- return NULL;
- }
- if (addrLen != context->addrLen) {
- // You can't just bind to an ip4 address then start sending ip6 traffic
- exHandler->exception(__FILE__ " UDPInterface_addEndpoint() address of different type "
- "then interface.", -1, exHandler);
- return NULL;
- }
-
- return insertEndpoint(&addr, context);
-}
-
-struct Interface* UDPInterface_getDefaultInterface(struct UDPInterface* context)
-{
- if (context->defaultInterface == NULL) {
- struct sockaddr_storage sockaddrZero;
- memset(&sockaddrZero, 0, sizeof(struct sockaddr_storage));
- context->defaultInterface = insertEndpoint(&sockaddrZero, context);
- }
- return context->defaultInterface;
-}
-
-int UDPInterface_bindToCurrentEndpoint(struct Interface* defaultInterface)
-{
- struct UDPInterface* context = (struct UDPInterface*) defaultInterface->senderContext;
- if (context->defaultInterface != defaultInterface
- || context->defaultInterfaceSender == NULL)
- {
- return -1;
- }
- for (uint32_t i = 0; i < context->endpointCount; i++) {
- // TODO this can be faster
- if (defaultInterface == &context->endpoints[i].interface) {
- struct Endpoint* ep = &context->endpoints[i];
- memcpy(&ep->addr, context->defaultInterfaceSender, sizeof(struct sockaddr_storage));
- context->addresses[i] = getAddr(&ep->addr);
- context->defaultInterface = NULL;
- return 0;
- }
- }
- assert(!"Couldn't find the interface in the list");
- return -1;
-}
-
-/*--------------------Internals--------------------*/
-
-/**
- * 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)
-{
- struct UDPInterface* context = (struct UDPInterface*) vcontext;
-
- struct Message message =
- { .bytes = context->messageBuff + PADDING, .padding = PADDING, .length = MAX_PACKET_SIZE };
-
- struct sockaddr_storage addrStore;
- memset(&addrStore, 0, sizeof(struct sockaddr_storage));
- int addrLen = sizeof(struct sockaddr_storage);
- int rc = recvfrom(socket,
- message.bytes,
- MAX_PACKET_SIZE,
- 0,
- (struct sockaddr*) &addrStore,
- (socklen_t*) &addrLen);
- /*
- Log_debug1(context->logger,
- "Got message from peer on port %u\n",
- Endian_bigEndianToHost16(((struct sockaddr_in*) &addrStore)->sin_port));
- */
- if (addrLen != context->addrLen) {
- return;
- }
- if (rc < 0) {
- return;
- }
- message.length = rc;
-
- uint32_t addr = getAddr(&addrStore);
- for (uint32_t i = 0; i < context->endpointCount; i++) {
- if (addr == context->addresses[i]
- && memcmp(&context->endpoints[i].addr,
- &addrStore,
- sizeof(struct sockaddr_storage)) == 0)
- {
- struct Interface* iface = &context->endpoints[i].interface;
- if (iface->receiveMessage != NULL) {
- iface->receiveMessage(&message, iface);
- }
- return;
- }
- }
+ Admin_registerFunction("UDPInterface_beginConnection",
+ beginConnectionAdmin,
+ context,
+ true,
+ admin);
- // Otherwise just send it to the default interface.
- if (context->defaultInterface != NULL && context->defaultInterface->receiveMessage != NULL) {
- context->defaultInterfaceSender = &addrStore;
- context->defaultInterface->receiveMessage(&message, context->defaultInterface);
- context->defaultInterfaceSender = NULL;
- }
+ return context;
}
View
51 interface/UDPInterface.h
@@ -17,6 +17,7 @@
#include <event2/event.h>
#include "interface/Interface.h"
+#include "interface/InterfaceController.h"
#include "util/Log.h"
#include "memory/Allocator.h"
@@ -28,48 +29,32 @@ struct UDPInterface;
* @param allocator the memory allocator for this message.
* @param exHandler the handler to deal with whatever exception arises.
* @param logger
+ * @param admin the administration module which will have UDPInterface_beginConnection()
+ * registered with it.
+ * @param ic the controller which this interface should register with
+ * and use when starting connections.
* @return a new UDPInterface.
*/
struct UDPInterface* UDPInterface_new(struct event_base* base,
const char* bindAddr,
struct Allocator* allocator,
struct ExceptionHandler* exHandler,
- struct Log* logger);
+ struct Log* logger,
+ struct InterfaceController* ic,
+ struct Admin* admin);
/**
- * Add an endpoint.
+ * Begin an outgoing connection.
*
- * @param context the tunnel context.
- * @param endpointSockAddr a string representation of the endpoint address EG: 1.2.3.4:56789
- * @param exHandler the handler to handle whatever exception may arise.
- * @return the interface object or null if error.
+ * @param address the ipv4 address and udp port to connect to, expressed as address:port.
+ * @param cryptoKey the node's public key, this is required to send it traffic.
+ * @param password if specified, the password for authenticating with the other node.
+ * @param udpif the UDP interface.
+ * @return 0 on success and -1 if there is no free switch slot.
*/
-struct Interface* UDPInterface_addEndpoint(struct UDPInterface* context,
- const char* endpointSockAddr,
- struct ExceptionHandler* exHandler);
-
-/**
- * Get an interface which will return all packets for which there is no interface.
- * This interface has no send functions and there is only one default interface per tunnel
- * so calling this function multiple times will yield the same object.
- * If a successful call is made to UDPInterface_bindToCurrentEndpoint(), this will no longer be
- * the default interface and you will need to call getDefaultInterface again.
- *
- * @param context the tunnel context.
- * @return the default interface.
- */
-struct Interface* UDPInterface_getDefaultInterface(struct UDPInterface* context);
-
-/**
- * Bind the default endpoint to whatever node just sent us data.
- * If called from inside of recieveMessage() which is handling incoming data from the
- * default endpoint, this will make the default endpoint nolonger default and bind it to the
- * ip address which last sent data and return 0, if called at any other time or with any
- * other interface, it will return -1.
- *
- * @param defaultInterface the interface returned by UDPInterface_getDefaultEndpoint()
- * @return 0 if all goes well, -1 if improperly used.
- */
-int UDPInterface_bindToCurrentEndpoint(struct Interface* defaultInterface);
+int UDPInterface_beginConnection(const char* address,
+ uint8_t cryptoKey[32],
+ String* password,
+ struct UDPInterface* udpif);
#endif
View
19 switch/SwitchCore.c
@@ -166,7 +166,7 @@ static uint8_t receiveMessage(struct Message* message, struct Interface* iface)
}
}
- if (destIndex >= core->interfaceCount) {
+ if (destIndex >= core->interfaceCount || core->interfaces[destIndex].iface == NULL) {
Log_debug(sourceIf->core->logger, "Dropped packet because there is no interface "
"where the bits specify.\n");
sendError(sourceIf, message, Error_MALFORMED_ADDRESS, sourceIf->core->logger);
@@ -211,10 +211,11 @@ static void removeInterface(void* vcontext)
{
struct SwitchInterface* si =
(struct SwitchInterface*) ((struct Interface*)vcontext)->receiverContext;
- struct SwitchCore* core = si->core;
- core->interfaceCount--;
- memcpy(si, &core->interfaces[core->interfaceCount], sizeof(struct SwitchInterface));
- si->iface->receiverContext = si;
+
+ // This will not be true if the interface has been swapped for another one.
+ if (si) {
+ memset(si, 0, sizeof(struct SwitchInterface));
+ }
}
/**
@@ -237,6 +238,14 @@ int SwitchCore_addInterface(struct Interface* iface,
ifIndex--;
}
+ // If there's a vacent spot where another iface was before it was removed, use that.
+ for (uint32_t i = 0; i < ifIndex; i++) {
+ if (core->interfaces[i].iface == NULL && i != 1) {
+ ifIndex = i;
+ break;
+ }
+ }
+
if (ifIndex == SwitchCore_MAX_INTERFACES) {
return -1;
}
View
16 util/Base32.h
@@ -40,10 +40,10 @@
* is not valid base32, or Base32_TOO_BIG if the output buffer is not large
* enough to handle the output.
*/
-int Base32_decode(uint8_t* output,
- const uint32_t outLength,
- const uint8_t *in,
- const uint32_t inputLength)
+static inline int Base32_decode(uint8_t* output,
+ const uint32_t outLength,
+ const uint8_t *in,
+ const uint32_t inputLength)
{
// Maps ascii character inputs to the numbers
// Invalid characters are represented by 99
@@ -105,10 +105,10 @@ int Base32_decode(uint8_t* output,
* @return the length of the output if all goes well,
* or Base32_TOO_BIG if the output buffer is not large enough to handle the output.
*/
-int Base32_encode(uint8_t *output,
- const uint32_t outputLength,
- const uint8_t *in,
- const uint32_t inputLength)
+static inline int Base32_encode(uint8_t *output,
+ const uint32_t outputLength,
+ const uint8_t *in,
+ const uint32_t inputLength)
{
uint32_t outIndex = 0;
uint32_t inIndex = 0;
Please sign in to comment.
Something went wrong with that request. Please try again.