Browse Source

Moved ControlHandler up above UpperDistributor in order to make CTRL frames tappable and also updated schematic

Caleb James DeLisle 7 years ago
parent
commit
016fac012c

BIN
doc/CjdnsModules.odg


BIN
doc/CjdnsModules.png


+ 3 - 2
net/Benchmark.c

@@ -179,8 +179,9 @@ static void switching(struct Context* ctx)
                                                 alloc);
     Assert_true(!ret);
 
-    Iface_unplumb(alice->switchAdapter->controlIf.connectedIf, &alice->switchAdapter->controlIf);
-    Iface_plumb(&alice->switchAdapter->controlIf, &sc->aliceCtrlIf);
+    Iface_unplumb(alice->upper->controlHandlerIf.connectedIf,
+                  &alice->upper->controlHandlerIf);
+    Iface_plumb(&alice->upper->controlHandlerIf, &sc->aliceCtrlIf);
 
     struct Message* msg = Message_new(Control_Ping_MIN_SIZE + Control_Header_SIZE, 256, alloc);
     struct Control_Header* ch = (struct Control_Header*) msg->bytes;

+ 11 - 13
net/ControlHandler.c

@@ -116,14 +116,13 @@ static Iface_DEFUN handlePing(struct Message* msg,
     ctrl->header.checksum_be = 0;
     ctrl->header.checksum_be = Checksum_engine(msg->bytes, msg->length);
 
-    Message_push32(msg, 0xffffffff, NULL);
-
-    Message_shift(msg, SwitchHeader_SIZE, NULL);
+    Message_shift(msg, RouteHeader_SIZE, NULL);
 
-    struct SwitchHeader* switchHeader = (struct SwitchHeader*) msg->bytes;
-    Bits_memset(switchHeader, 0, SwitchHeader_SIZE);
-    SwitchHeader_setVersion(switchHeader, SwitchHeader_CURRENT_VERSION);
-    switchHeader->label_be = Endian_hostToBigEndian64(label);
+    struct RouteHeader* routeHeader = (struct RouteHeader*) msg->bytes;
+    Bits_memset(routeHeader, 0, RouteHeader_SIZE);
+    SwitchHeader_setVersion(&routeHeader->sh, SwitchHeader_CURRENT_VERSION);
+    routeHeader->sh.label_be = Endian_hostToBigEndian64(label);
+    routeHeader->flags |= RouteHeader_flags_CTRLMSG;
 
     return Iface_next(&ch->pub.coreIf, msg);
 }
@@ -142,10 +141,10 @@ static Iface_DEFUN incomingFromCore(struct Message* msg, struct Iface* coreIf)
 {
     struct ControlHandler_pvt* ch = Identity_check((struct ControlHandler_pvt*) coreIf);
 
-    struct SwitchHeader switchHeader;
-    Message_pop(msg, &switchHeader, SwitchHeader_SIZE, NULL);
+    struct RouteHeader routeHdr;
+    Message_pop(msg, &routeHdr, RouteHeader_SIZE, NULL);
     uint8_t labelStr[20];
-    uint64_t label = Endian_bigEndianToHost64(switchHeader.label_be);
+    uint64_t label = Endian_bigEndianToHost64(routeHdr.sh.label_be);
     AddrTools_printPath(labelStr, label);
     Log_debug(ch->log, "ctrl packet from [%s]", labelStr);
 
@@ -154,7 +153,7 @@ static Iface_DEFUN incomingFromCore(struct Message* msg, struct Iface* coreIf)
         return NULL;
     }
 
-    Assert_true(Message_pop32(msg, NULL) == 0xffffffff);
+    Assert_true(routeHdr.flags & RouteHeader_flags_CTRLMSG);
 
     if (Checksum_engine(msg->bytes, msg->length)) {
         Log_info(ch->log, "DROP ctrl packet from [%s] with invalid checksum", labelStr);
@@ -175,8 +174,7 @@ static Iface_DEFUN incomingFromCore(struct Message* msg, struct Iface* coreIf)
             || ctrl->header.type_be == Control_PONG_be)
     {
         Log_debug(ch->log, "got switch pong from [%s]", labelStr);
-        // Shift back over the header
-        Message_shift(msg, 4 + SwitchHeader_SIZE, NULL);
+        Message_push(msg, &routeHdr, RouteHeader_SIZE, NULL);
         return Iface_next(&ch->pub.switchPingerIf, msg);
     }
 

+ 6 - 16
net/NetCore.c

@@ -26,7 +26,6 @@
 #include "tunnel/IpTunnel.h"
 #include "net/EventEmitter.h"
 #include "net/SessionManager.h"
-#include "net/SwitchAdapter.h"
 #include "net/UpperDistributor.h"
 #include "net/TUNAdapter.h"
 #include "util/version/Version.h"
@@ -53,32 +52,23 @@ struct NetCore* NetCore_new(uint8_t* privateKey,
     myAddress->protocolVersion = Version_CURRENT_PROTOCOL;
     myAddress->path = 1;
 
-    // lower half
-
     struct SwitchCore* switchCore = nc->switchCore = SwitchCore_new(log, alloc, base);
 
-    struct SwitchAdapter* switchAdapter = nc->switchAdapter = SwitchAdapter_new(alloc, log);
-    Iface_plumb(&switchAdapter->switchIf, switchCore->routerIf);
+    struct SessionManager* sm = nc->sm = SessionManager_new(alloc, base, ca, rand, log, ee);
+    Iface_plumb(switchCore->routerIf, &sm->switchIf);
+
+    struct UpperDistributor* upper = nc->upper = UpperDistributor_new(alloc, log, ee, myAddress);
+    Iface_plumb(&sm->insideIf, &upper->sessionManagerIf);
 
     struct ControlHandler* controlHandler = nc->controlHandler =
         ControlHandler_new(alloc, log, ee, ca->publicKey);
-    Iface_plumb(&controlHandler->coreIf, &switchAdapter->controlIf);
+    Iface_plumb(&controlHandler->coreIf, &upper->controlHandlerIf);
 
     struct SwitchPinger* sp = nc->sp = SwitchPinger_new(base, rand, log, myAddress, alloc);
     Iface_plumb(&controlHandler->switchPingerIf, &sp->controlHandlerIf);
 
     nc->ifController = InterfaceController_new(ca, switchCore, log, base, sp, rand, alloc, ee);
 
-    // session manager
-
-    struct SessionManager* sm = nc->sm = SessionManager_new(alloc, base, ca, rand, log, ee);
-    Iface_plumb(&switchAdapter->sessionManagerIf, &sm->switchIf);
-
-    // upper half
-
-    struct UpperDistributor* upper = nc->upper = UpperDistributor_new(alloc, log, ee, myAddress);
-    Iface_plumb(&sm->insideIf, &upper->sessionManagerIf);
-
     struct TUNAdapter* tunAdapt = nc->tunAdapt = TUNAdapter_new(alloc, log, myAddress->ip6.bytes);
     Iface_plumb(&tunAdapt->upperDistributorIf, &upper->tunAdapterIf);
 

+ 0 - 2
net/NetCore.h

@@ -28,7 +28,6 @@
 #include "tunnel/IpTunnel.h"
 #include "net/EventEmitter.h"
 #include "net/SessionManager.h"
-#include "net/SwitchAdapter.h"
 #include "net/UpperDistributor.h"
 #include "net/TUNAdapter.h"
 #include "util/Linker.h"
@@ -44,7 +43,6 @@ struct NetCore
     struct EventEmitter* ee;
     struct Address* myAddress;
     struct SwitchCore* switchCore;
-    struct SwitchAdapter* switchAdapter;
     struct ControlHandler* controlHandler;
     struct SwitchPinger* sp;
     struct InterfaceController* ifController;

+ 45 - 1
net/SessionManager.c

@@ -226,6 +226,17 @@ static struct SessionManager_Session_pvt* getSession(struct SessionManager_pvt*
     return sess;
 }
 
+static Iface_DEFUN ctrlFrame(struct Message* msg, struct SessionManager_pvt* sm)
+{
+    struct RouteHeader rh;
+    Bits_memset(&rh, 0, RouteHeader_SIZE);
+    Message_pop(msg, &rh.sh, SwitchHeader_SIZE, NULL);
+    Message_pop(msg, NULL, 4, NULL);
+    rh.flags = RouteHeader_flags_INCOMING | RouteHeader_flags_CTRLMSG;
+    Message_push(msg, &rh, RouteHeader_SIZE, NULL);
+    return Iface_next(&sm->pub.insideIf, msg);
+}
+
 static Iface_DEFUN incomingFromSwitchIf(struct Message* msg, struct Iface* iface)
 {
     struct SessionManager_pvt* sm =
@@ -241,8 +252,17 @@ static Iface_DEFUN incomingFromSwitchIf(struct Message* msg, struct Iface* iface
     struct SwitchHeader* switchHeader = (struct SwitchHeader*) msg->bytes;
     Message_shift(msg, -SwitchHeader_SIZE, NULL);
 
+    // The label comes in reversed from the switch because the switch doesn't know that we aren't
+    // another switch ready to parse more bits, bit reversing the label yields the source address.
+    // (the field is still big endian!)
+    switchHeader->label_be = Bits_bitReverse64(switchHeader->label_be);
+
     struct SessionManager_Session_pvt* session;
     uint32_t nonceOrHandle = Endian_bigEndianToHost32(((uint32_t*)msg->bytes)[0]);
+    if (nonceOrHandle == 0xffffffff) {
+        Message_shift(msg, SwitchHeader_SIZE, NULL);
+        return ctrlFrame(msg, sm);
+    }
     if (nonceOrHandle > 3) {
         // > 3 it's a handle.
         session = sessionForHandle(nonceOrHandle, sm);
@@ -493,12 +513,36 @@ static Iface_DEFUN readyToSend(struct Message* msg,
     return Iface_next(&sm->pub.switchIf, msg);
 }
 
+static Iface_DEFUN outgoingCtrlFrame(struct Message* msg, struct SessionManager_pvt* sm)
+{
+    Assert_true(msg->length >= RouteHeader_SIZE);
+    struct RouteHeader* header = (struct RouteHeader*) msg->bytes;
+    if (!Bits_isZero(header->publicKey, 32) || !Bits_isZero(header->ip6, 16)) {
+        Log_debug(sm->log, "DROP Ctrl frame with non-zero destination key or IP");
+        return NULL;
+    }
+    if (!(header->flags & RouteHeader_flags_CTRLMSG)) {
+        Log_debug(sm->log, "DROP Ctrl frame w/o RouteHeader_flags_CTRLMSG flag");
+        return NULL;
+    }
+    struct SwitchHeader sh;
+    Bits_memcpy(&sh, &header->sh, SwitchHeader_SIZE);
+    Message_pop(msg, NULL, RouteHeader_SIZE, NULL);
+    Message_push32(msg, 0xffffffff, NULL);
+    Message_push(msg, &sh, SwitchHeader_SIZE, NULL);
+    return Iface_next(&sm->pub.switchIf, msg);
+}
+
 static Iface_DEFUN incomingFromInsideIf(struct Message* msg, struct Iface* iface)
 {
     struct SessionManager_pvt* sm =
         Identity_containerOf(iface, struct SessionManager_pvt, pub.insideIf);
-    Assert_true(msg->length >= RouteHeader_SIZE + DataHeader_SIZE);
+    Assert_true(msg->length >= RouteHeader_SIZE);
     struct RouteHeader* header = (struct RouteHeader*) msg->bytes;
+    if (header->flags & RouteHeader_flags_CTRLMSG) {
+        return outgoingCtrlFrame(msg, sm);
+    }
+    Assert_true(msg->length >= RouteHeader_SIZE + DataHeader_SIZE);
     struct DataHeader* dataHeader = (struct DataHeader*) &header[1];
 
     struct SessionManager_Session_pvt* sess = sessionForIp6(header->ip6, sm);

+ 0 - 81
net/SwitchAdapter.c

@@ -1,81 +0,0 @@
-/* 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 "memory/Allocator.h"
-#include "net/SwitchAdapter.h"
-#include "util/Identity.h"
-#include "wire/SwitchHeader.h"
-#include "util/Linker.h"
-
-struct SwitchAdapter_pvt
-{
-    struct SwitchAdapter pub;
-    struct Log* log;
-    Identity
-};
-
-struct Header {
-     struct SwitchHeader sh;
-     uint32_t handle_be;
-};
-#define Header_SIZE 16
-Assert_compileTime(sizeof(struct Header) == Header_SIZE);
-
-static Iface_DEFUN incomingFromControlIf(struct Message* msg, struct Iface* controlIf)
-{
-    struct SwitchAdapter_pvt* sa =
-        Identity_containerOf(controlIf, struct SwitchAdapter_pvt, pub.controlIf);
-    return Iface_next(&sa->pub.switchIf, msg);
-}
-
-static Iface_DEFUN incomingFromSessionManagerIf(struct Message* msg, struct Iface* sessionManagerIf)
-{
-    struct SwitchAdapter_pvt* sa =
-        Identity_containerOf(sessionManagerIf, struct SwitchAdapter_pvt, pub.sessionManagerIf);
-    return Iface_next(&sa->pub.switchIf, msg);
-}
-
-static Iface_DEFUN incomingFromSwitchIf(struct Message* msg, struct Iface* switchIf)
-{
-    struct SwitchAdapter_pvt* sa =
-        Identity_containerOf(switchIf, struct SwitchAdapter_pvt, pub.switchIf);
-    if (msg->length < Header_SIZE) {
-        Log_debug(sa->log, "DROP runt");
-        return 0;
-    }
-    Assert_true(!(((uintptr_t)msg->bytes) % 4) && "alignment");
-    struct Header* hdr = (struct Header*) msg->bytes;
-
-    // The label comes in reversed from the switch because the switch doesn't know that we aren't
-    // another switch ready to parse more bits, bit reversing the label yields the source address.
-    // (the field is still big endian!)
-    hdr->sh.label_be = Bits_bitReverse64(hdr->sh.label_be);
-
-    if (hdr->handle_be == 0xffffffff) {
-        return Iface_next(&sa->pub.controlIf, msg);
-    }
-    return Iface_next(&sa->pub.sessionManagerIf, msg);
-}
-
-struct SwitchAdapter* SwitchAdapter_new(struct Allocator* allocator, struct Log* log)
-{
-    struct Allocator* alloc = Allocator_child(allocator);
-    struct SwitchAdapter_pvt* out = Allocator_calloc(alloc, sizeof(struct SwitchAdapter_pvt), 1);
-    out->pub.controlIf.send = incomingFromControlIf;
-    out->pub.sessionManagerIf.send = incomingFromSessionManagerIf;
-    out->pub.switchIf.send = incomingFromSwitchIf;
-    out->log = log;
-    Identity_set(out);
-    return &out->pub;
-}

+ 0 - 47
net/SwitchAdapter.h

@@ -1,47 +0,0 @@
-/* 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 SwitchAdapter_H
-#define SwitchAdapter_H
-
-#include "interface/Iface.h"
-#include "memory/Allocator.h"
-#include "util/log/Log.h"
-#include "util/Linker.h"
-Linker_require("net/SwitchAdapter.c");
-
-/**
- * Connects the actual switch interface to the SessionManager and the ControlHandler.
- */
-struct SwitchAdapter
-{
-    /** Sends and handles packets to/from switch. */
-    struct Iface switchIf;
-
-    /**
-     * Sends forth the packets with control headers (0xffffffff) under the switch header.
-     * Directs all input to the switch.
-     */
-    struct Iface controlIf;
-
-    /**
-     * Sends all packets which are not control frames.
-     * Directs all input to the switch.
-     */
-    struct Iface sessionManagerIf;
-};
-
-struct SwitchAdapter* SwitchAdapter_new(struct Allocator* alloc, struct Log* log);
-
-#endif

+ 11 - 34
net/SwitchPinger.c

@@ -21,7 +21,7 @@
 #include "util/Pinger.h"
 #include "util/version/Version.h"
 #include "util/Identity.h"
-#include "wire/SwitchHeader.h"
+#include "wire/RouteHeader.h"
 #include "wire/Control.h"
 #include "wire/Error.h"
 
@@ -79,20 +79,10 @@ struct Ping
 static Iface_DEFUN messageFromControlHandler(struct Message* msg, struct Iface* iface)
 {
     struct SwitchPinger_pvt* ctx = Identity_check((struct SwitchPinger_pvt*) iface);
-    struct SwitchHeader* switchHeader = (struct SwitchHeader*) msg->bytes;
-    ctx->incomingLabel = Endian_bigEndianToHost64(switchHeader->label_be);
+    struct RouteHeader rh;
+    Message_pop(msg, &rh, RouteHeader_SIZE, NULL);
+    ctx->incomingLabel = Endian_bigEndianToHost64(rh.sh.label_be);
     ctx->incomingVersion = 0;
-    Message_shift(msg, -SwitchHeader_SIZE, NULL);
-
-    uint32_t handle = Message_pop32(msg, NULL);
-    #ifdef Version_7_COMPAT
-    if (handle != 0xffffffff) {
-        Message_push32(msg, handle, NULL);
-        handle = 0xffffffff;
-        Assert_true(SwitchHeader_isV7Ctrl(switchHeader));
-    }
-    #endif
-    Assert_true(handle == 0xffffffff);
 
     struct Control* ctrl = (struct Control*) msg->bytes;
     if (ctrl->header.type_be == Control_PONG_be) {
@@ -240,26 +230,13 @@ static void sendPing(String* data, void* sendPingContext)
     ctrl->header.type_be = (p->pub.keyPing) ? Control_KEYPING_be : Control_PING_be;
     ctrl->header.checksum_be = Checksum_engine(msg->bytes, msg->length);
 
-    #ifdef Version_7_COMPAT
-        if (0) {
-    #endif
-    Message_push32(msg, 0xffffffff, NULL);
-    #ifdef Version_7_COMPAT
-        }
-    #endif
-
-    Message_shift(msg, SwitchHeader_SIZE, NULL);
-    struct SwitchHeader* switchHeader = (struct SwitchHeader*) msg->bytes;
-    Bits_memset(switchHeader, 0, SwitchHeader_SIZE);
-    switchHeader->label_be = Endian_hostToBigEndian64(p->label);
-    SwitchHeader_setVersion(switchHeader, SwitchHeader_CURRENT_VERSION);
-
-    #ifdef Version_7_COMPAT
-        // v7 detects ctrl packets by the bit which has been
-        // re-appropriated for suppression of errors.
-        switchHeader->congestAndSuppressErrors = 1;
-        SwitchHeader_setVersion(switchHeader, 0);
-    #endif
+    struct RouteHeader rh;
+    Bits_memset(&rh, 0, RouteHeader_SIZE);
+    rh.flags |= RouteHeader_flags_CTRLMSG;
+    rh.sh.label_be = Endian_hostToBigEndian64(p->label);
+    SwitchHeader_setVersion(&rh.sh, SwitchHeader_CURRENT_VERSION);
+
+    Message_push(msg, &rh, RouteHeader_SIZE, NULL);
 
     Iface_send(&p->context->pub.controlHandlerIf, msg);
 }

+ 20 - 1
net/UpperDistributor.c

@@ -165,12 +165,30 @@ static Iface_DEFUN incomingFromIpTunnelIf(struct Message* msg, struct Iface* ipT
     return toSessionManagerIf(msg, ud);
 }
 
+static Iface_DEFUN incomingFromControlHandlerIf(struct Message* msg, struct Iface* iface)
+{
+    struct UpperDistributor_pvt* ud =
+        Identity_containerOf(iface, struct UpperDistributor_pvt, pub.controlHandlerIf);
+    Assert_true(msg->length >= RouteHeader_SIZE);
+    struct RouteHeader* hdr = (struct RouteHeader*) msg->bytes;
+    Assert_true(hdr->flags & RouteHeader_flags_CTRLMSG);
+    Assert_true(!(hdr->flags & RouteHeader_flags_INCOMING));
+    sendToHandlers(msg, ContentType_CTRL, ud);
+    return Iface_next(&ud->pub.sessionManagerIf, msg);
+}
+
 static Iface_DEFUN incomingFromSessionManagerIf(struct Message* msg, struct Iface* sessionManagerIf)
 {
     struct UpperDistributor_pvt* ud =
         Identity_containerOf(sessionManagerIf, struct UpperDistributor_pvt, pub.sessionManagerIf);
-    Assert_true(msg->length >= RouteHeader_SIZE + DataHeader_SIZE);
+    Assert_true(msg->length >= RouteHeader_SIZE);
     struct RouteHeader* hdr = (struct RouteHeader*) msg->bytes;
+    if (hdr->flags & RouteHeader_flags_CTRLMSG) {
+        sendToHandlers(msg, ContentType_CTRL, ud);
+        return Iface_next(&ud->pub.controlHandlerIf, msg);
+    }
+    Assert_true(msg->length >= RouteHeader_SIZE + DataHeader_SIZE);
+
     struct DataHeader* dh = (struct DataHeader*) &hdr[1];
     enum ContentType type = DataHeader_getContentType(dh);
     sendToHandlers(msg, type, ud);
@@ -255,6 +273,7 @@ struct UpperDistributor* UpperDistributor_new(struct Allocator* allocator,
     out->pub.tunAdapterIf.send = incomingFromTunAdapterIf;
     out->pub.ipTunnelIf.send = incomingFromIpTunnelIf;
     out->pub.sessionManagerIf.send = incomingFromSessionManagerIf;
+    out->pub.controlHandlerIf.send = incomingFromControlHandlerIf;
     out->log = log;
     out->alloc = alloc;
     out->myAddress = myAddress;

+ 2 - 0
net/UpperDistributor.h

@@ -33,6 +33,8 @@ struct UpperDistributor
     struct Iface tunAdapterIf;
 
     struct Iface ipTunnelIf;
+
+    struct Iface controlHandlerIf;
 };
 
 struct UpperDistributor_Handler

+ 0 - 1
test/TestFramework.c

@@ -33,7 +33,6 @@
 #include "tunnel/IpTunnel.h"
 #include "net/EventEmitter.h"
 #include "net/SessionManager.h"
-#include "net/SwitchAdapter.h"
 #include "net/UpperDistributor.h"
 #include "net/TUNAdapter.h"
 #include "wire/Headers.h"

+ 4 - 1
wire/ContentType.h

@@ -63,7 +63,10 @@ enum ContentType
      * CTRL messages.
      */
     ContentType_AVAILABLE =     0x8000,
-    ContentType_MAX = 0xffff
+    ContentType_MAX = 0xffff,
+
+    // This contentType will never appear in the wild, it represents unencrypted control frames.
+    ContentType_CTRL = 0xffff + 1
 };
 
 #endif

+ 1 - 0
wire/RouteHeader.h

@@ -53,6 +53,7 @@ struct RouteHeader
      * switch label are of the *source* of the packet, not the destination.
      */
     #define RouteHeader_flags_INCOMING 1
+    #define RouteHeader_flags_CTRLMSG (1<<1)
     uint8_t flags;
 
     uint8_t unused;