mirror of
https://github.com/cjdelisle/cjdns
synced 2025-10-06 00:32:50 +02:00
265 lines
9.6 KiB
C
265 lines
9.6 KiB
C
/* 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 <https://www.gnu.org/licenses/>.
|
|
*/
|
|
#include "crypto/random/Random.h"
|
|
#include "crypto/Ca.h"
|
|
#ifndef SUBNODE
|
|
#include "dht/Pathfinder.h"
|
|
#endif
|
|
#include "io/Writer.h"
|
|
#include "io/FileWriter.h"
|
|
#include "util/log/Log.h"
|
|
#include "memory/Allocator.h"
|
|
#include "subnode/SubnodePathfinder.h"
|
|
#include "test/TestFramework.h"
|
|
#include "util/log/WriterLog.h"
|
|
#include "util/events/EventBase.h"
|
|
#include "net/InterfaceController.h"
|
|
#include "net/SessionManager.h"
|
|
#include "interface/Iface.h"
|
|
#include "tunnel/IpTunnel.h"
|
|
#include "net/EventEmitter.h"
|
|
#include "net/SessionManager.h"
|
|
#include "net/UpperDistributor.h"
|
|
#include "net/TUNAdapter.h"
|
|
#include "wire/Headers.h"
|
|
|
|
// Needed just to get the encoding scheme that we're using
|
|
#define NumberCompress_OLD_CODE
|
|
#include "switch/NumberCompress.h"
|
|
|
|
struct TestFramework_Link
|
|
{
|
|
struct Iface clientIf;
|
|
struct Iface serverIf;
|
|
struct TestFramework* client;
|
|
struct TestFramework* server;
|
|
int serverIfNum;
|
|
int clientIfNum;
|
|
Identity
|
|
};
|
|
|
|
static Iface_DEFUN sendTo(Message_t* msg,
|
|
struct Iface* dest,
|
|
struct TestFramework* srcTf,
|
|
struct TestFramework* destTf)
|
|
{
|
|
Assert_true(!((uintptr_t)Message_bytes(msg) % 4) || !"alignment fault");
|
|
Assert_true(!(Message_getCapacity(msg) % 4) || !"length fault");
|
|
Assert_true(((int)Message_getCapacity(msg) >= Message_getLength(msg)) || !"length fault0");
|
|
|
|
Log_debug(srcTf->logger, "Transferring message to [%p] - message length [%d]\n",
|
|
(void*)dest, Message_getLength(msg));
|
|
|
|
// Store the original message and a copy of the original so they can be compared later.
|
|
srcTf->lastMsgBackup = Message_clone(msg, srcTf->alloc);
|
|
srcTf->lastMsg = msg;
|
|
if (Message_getAlloc(msg)) {
|
|
// If it's a message which was buffered inside of CryptoAuth then it will be freed
|
|
// so by adopting the allocator we can hold it in memory.
|
|
Allocator_adopt(srcTf->alloc, Message_getAlloc(msg));
|
|
}
|
|
|
|
// Copy the original and send that to the other end.
|
|
// Can't use Iface_next() when not sending the original msg.
|
|
Message_t* sendMsg = Message_clone(msg, destTf->alloc);
|
|
return Iface_send(dest, sendMsg);
|
|
}
|
|
|
|
static Iface_DEFUN sendClient(Message_t* msg, struct Iface* clientIf)
|
|
{
|
|
struct TestFramework_Link* link =
|
|
Identity_containerOf(clientIf, struct TestFramework_Link, clientIf);
|
|
return sendTo(msg, &link->serverIf, link->client, link->server);
|
|
}
|
|
|
|
static Iface_DEFUN sendServer(Message_t* msg, struct Iface* serverIf)
|
|
{
|
|
struct TestFramework_Link* link =
|
|
Identity_containerOf(serverIf, struct TestFramework_Link, serverIf);
|
|
return sendTo(msg, &link->clientIf, link->server, link->client);
|
|
}
|
|
|
|
struct TestFramework* TestFramework_setUp(char* privateKey,
|
|
struct Allocator* allocator,
|
|
EventBase_t* base,
|
|
struct Random* rand,
|
|
struct Log* logger,
|
|
bool enableNoise)
|
|
{
|
|
if (!logger) {
|
|
struct Writer* logwriter = FileWriter_new(stdout, allocator);
|
|
logger = WriterLog_new(logwriter, allocator);
|
|
}
|
|
|
|
if (!rand) {
|
|
Err_assert(Random_new(&rand, allocator, logger));
|
|
}
|
|
|
|
if (!base) {
|
|
base = EventBase_new(allocator);
|
|
}
|
|
|
|
uint64_t pks[4];
|
|
if (!privateKey) {
|
|
Random_longs(rand, pks, 4);
|
|
privateKey = (char*)pks;
|
|
}
|
|
|
|
struct EncodingScheme* scheme = NumberCompress_defineScheme(allocator);
|
|
|
|
struct NetCore* nc =
|
|
NetCore_new(privateKey, allocator, base, rand, logger, enableNoise);
|
|
|
|
struct RouteGen* rg = RouteGen_new(allocator, logger);
|
|
|
|
struct GlobalConfig* globalConf = GlobalConfig_new(allocator);
|
|
struct IpTunnel* ipTunnel =
|
|
IpTunnel_new(logger, base, allocator, rand, rg, globalConf);
|
|
Iface_plumb(&nc->tunAdapt->ipTunnelIf, &ipTunnel->tunInterface);
|
|
Iface_plumb(&nc->upper->ipTunnelIf, &ipTunnel->nodeInterface);
|
|
|
|
struct SubnodePathfinder* spf = SubnodePathfinder_new(
|
|
allocator, logger, base, rand, nc->myAddress, privateKey, scheme, nc->ca);
|
|
EventEmitter_regPathfinderIface(nc->ee, &spf->eventIf);
|
|
|
|
#ifndef SUBNODE
|
|
struct Pathfinder* pf = Pathfinder_register(allocator, logger, base, rand, NULL);
|
|
pf->fullVerify = true;
|
|
EventEmitter_regPathfinderIface(nc->ee, &pf->eventIf);
|
|
#endif
|
|
|
|
SubnodePathfinder_start(spf);
|
|
|
|
struct TestFramework* tf = Allocator_calloc(allocator, sizeof(struct TestFramework), 1);
|
|
Identity_set(tf);
|
|
tf->alloc = allocator;
|
|
tf->rand = rand;
|
|
tf->eventBase = base;
|
|
tf->logger = logger;
|
|
tf->nc = nc;
|
|
tf->tunIf = &nc->tunAdapt->tunIf;
|
|
tf->publicKey = nc->myAddress->key;
|
|
tf->ip = nc->myAddress->ip6.bytes;
|
|
#ifndef SUBNODE
|
|
tf->pathfinder = pf;
|
|
#endif
|
|
tf->subnodePathfinder = spf;
|
|
tf->scheme = scheme;
|
|
|
|
return tf;
|
|
}
|
|
|
|
void TestFramework_assertLastMessageUnaltered(struct TestFramework* tf)
|
|
{
|
|
if (!tf->lastMsg) {
|
|
return;
|
|
}
|
|
Message_t* a = tf->lastMsg;
|
|
Message_t* b = tf->lastMsgBackup;
|
|
Assert_true(Message_getLength(a) == Message_getLength(b));
|
|
Assert_true(Message_getPadding(a) == Message_getPadding(b));
|
|
Assert_true(!Bits_memcmp(Message_bytes(a), Message_bytes(b), Message_getLength(a)));
|
|
}
|
|
|
|
void TestFramework_linkNodes(struct TestFramework* client,
|
|
struct TestFramework* server,
|
|
bool beacon)
|
|
{
|
|
// ifaceA is the client, ifaceB is the server
|
|
struct TestFramework_Link* link =
|
|
Allocator_calloc(client->alloc, sizeof(struct TestFramework_Link), 1);
|
|
Identity_set(link);
|
|
link->clientIf.send = sendClient;
|
|
link->serverIf.send = sendServer;
|
|
link->client = client;
|
|
link->server = server;
|
|
|
|
struct InterfaceController_Iface* clientIci = InterfaceController_newIface(
|
|
client->nc->ifController, String_CONST("client"), client->alloc);
|
|
link->clientIfNum = clientIci->ifNum;
|
|
Iface_plumb(&link->clientIf, &clientIci->addrIf);
|
|
|
|
struct InterfaceController_Iface* serverIci = InterfaceController_newIface(
|
|
server->nc->ifController, String_CONST("server"), server->alloc);
|
|
link->serverIfNum = serverIci->ifNum;
|
|
Iface_plumb(&link->serverIf, &serverIci->addrIf);
|
|
|
|
if (beacon) {
|
|
int ret = InterfaceController_beaconState(client->nc->ifController,
|
|
link->clientIfNum,
|
|
InterfaceController_beaconState_newState_ACCEPT);
|
|
Assert_true(!ret);
|
|
|
|
ret = InterfaceController_beaconState(server->nc->ifController,
|
|
link->serverIfNum,
|
|
InterfaceController_beaconState_newState_SEND);
|
|
Assert_true(!ret);
|
|
} else {
|
|
// Except that it has an authorizedPassword added.
|
|
Ca_addUser(String_CONST("abcdefg123"), String_CONST("TEST"), server->nc->ca);
|
|
|
|
// Client has pubKey and passwd for the server.
|
|
InterfaceController_bootstrapPeer(client->nc->ifController,
|
|
link->clientIfNum,
|
|
server->publicKey,
|
|
Sockaddr_LOOPBACK,
|
|
String_CONST("abcdefg123"),
|
|
NULL,
|
|
NULL,
|
|
Version_CURRENT_PROTOCOL);
|
|
}
|
|
}
|
|
|
|
void TestFramework_craftIPHeader(Message_t* msg, uint8_t srcAddr[16], uint8_t destAddr[16])
|
|
{
|
|
Err_assert(Message_eshift(msg, Headers_IP6Header_SIZE));
|
|
struct Headers_IP6Header* ip = (struct Headers_IP6Header*) Message_bytes(msg);
|
|
|
|
ip->versionClassAndFlowLabel = 0;
|
|
ip->flowLabelLow_be = 0;
|
|
ip->payloadLength_be = Endian_hostToBigEndian16(Message_getLength(msg) - Headers_IP6Header_SIZE);
|
|
ip->nextHeader = 123; // made up number
|
|
ip->hopLimit = 255;
|
|
Bits_memcpy(ip->sourceAddr, srcAddr, 16);
|
|
Bits_memcpy(ip->destinationAddr, destAddr, 16);
|
|
Headers_setIpVersion(ip);
|
|
}
|
|
|
|
int TestFramework_peerCount(struct TestFramework* node)
|
|
{
|
|
struct Allocator* alloc = Allocator_child(node->alloc);
|
|
struct InterfaceController_PeerStats* statsOut = NULL;
|
|
int len = InterfaceController_getPeerStats(node->nc->ifController, alloc, &statsOut);
|
|
int out = 0;
|
|
for (int i = 0; i < len; i++) {
|
|
out += (statsOut[i].state == InterfaceController_PeerState_ESTABLISHED);
|
|
}
|
|
Allocator_free(alloc);
|
|
return out;
|
|
}
|
|
|
|
int TestFramework_sessionCount(struct TestFramework* node)
|
|
{
|
|
struct Allocator* alloc = Allocator_child(node->alloc);
|
|
struct SessionManager_HandleList* list = SessionManager_getHandleList(node->nc->sm, alloc);
|
|
int count = 0;
|
|
for (int i = 0; i < list->length; i++) {
|
|
struct SessionManager_Session* sess =
|
|
SessionManager_sessionForHandle(list->handles[i], node->nc->sm);
|
|
count += (Ca_getState(sess->caSession) == Ca_State_ESTABLISHED);
|
|
}
|
|
Allocator_free(alloc);
|
|
return count;
|
|
} |