mirror of
https://github.com/cjdelisle/cjdns
synced 2025-10-05 16:22:54 +02:00
Deleted sybilsim and FakeNetwork which are nolonger being meaningfully maintained
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -17,7 +17,6 @@
|
||||
/cleanconfig*
|
||||
/privatetopublic*
|
||||
/publictoip6*
|
||||
/sybilsim*
|
||||
/makekeys*
|
||||
/mkpasswd*
|
||||
/node_build/node_modules/jshint
|
||||
|
49
HACKING.md
49
HACKING.md
@@ -143,51 +143,4 @@ You can do this on Linux using the `perf` utility.
|
||||
<ctrl+c>
|
||||
sudo perf script | ../FlameGraph/stackcollapse-perf.pl > ./cjdns-stackcollapse.out
|
||||
../FlameGraph/flamegraph.pl < ./cjdns-stackcollapse.out > ./cjdns-stackcollapse.svg
|
||||
chromium ./cjdns-stackcollapse.svg
|
||||
|
||||
|
||||
Simulating
|
||||
----------
|
||||
|
||||
Cjdns comes with it's own simulator, it will create *n* nodes and link them together
|
||||
however you wish. It's like having many cjdns processes all running together but they're
|
||||
all in the same process so it is much more efficient. You can set admin credentials on
|
||||
one node and then use the admin tools to access it as you would an ordinary router.
|
||||
You will however need private keys whose public keys hash to ip addresses beginning with
|
||||
fc. To make these keys, use the `makekeys` utility.
|
||||
|
||||
./makekeys | head -n 32 > keys.txt
|
||||
|
||||
To convert the list of keys into a simulator configuration, use `makesim.js`, note there
|
||||
are interesting constants inside of `makesim.js` which you might want to alter.
|
||||
|
||||
node ./tools/lib/makesim.js keys.txt > ~/my-cjdns-simulation.json
|
||||
|
||||
Once you have a simulation setup, you may want to add your admin credentials to one of
|
||||
the nodes so you can inspect it, dump the table, etc...
|
||||
|
||||
Example simulation config entry with added admin block:
|
||||
|
||||
```javascript
|
||||
"fc5c:0537:606a:3d7e:c9f0:2103:4dcd:6bc8": {
|
||||
"privateKey": "0dc3d33bbffc2d16c175df463110c6d164714a40d23db2f83539664b7365a5b6",
|
||||
"peers": [
|
||||
"fc1c:84bf:9557:1ce4:4862:fd82:5105:9984",
|
||||
"fc1c:90e4:2953:938b:47cc:65c3:6540:dff6",
|
||||
"fc1b:7ea7:911f:f2d5:7685:ac22:6c4f:8b15"
|
||||
],
|
||||
"admin":
|
||||
{
|
||||
"bind": "127.0.0.1:11234",
|
||||
"password": "the_password_you_will_use_to_connect"
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
And to start it up (in the debugger):
|
||||
|
||||
gdb ./sybilsim -ex 'r < ~/my-cjdns-simulation.json'
|
||||
|
||||
BUG: Sometimes the simulator doesn't really start up correctly! If you could figure out
|
||||
what is going wrong, your help would be most appreciated, if not, you can just quit and
|
||||
then restart it again and it should start up ok.
|
||||
chromium ./cjdns-stackcollapse.svg
|
@@ -335,7 +335,6 @@ void Core_init(struct Allocator* alloc,
|
||||
struct Admin* admin,
|
||||
struct Random* rand,
|
||||
struct Except* eh,
|
||||
struct FakeNetwork* fakeNet,
|
||||
bool noSec)
|
||||
{
|
||||
struct Security* sec = NULL;
|
||||
@@ -376,7 +375,7 @@ void Core_init(struct Allocator* alloc,
|
||||
InterfaceController_admin_register(nc->ifController, admin, alloc);
|
||||
SwitchPinger_admin_register(nc->sp, admin, alloc);
|
||||
UDPInterface_admin_register(
|
||||
eventBase, alloc, logger, admin, nc->ifController, fakeNet, globalConf);
|
||||
eventBase, alloc, logger, admin, nc->ifController, globalConf);
|
||||
#ifdef HAS_ETH_INTERFACE
|
||||
ETHInterface_admin_register(eventBase, alloc, logger, admin, nc->ifController);
|
||||
#endif
|
||||
@@ -535,7 +534,7 @@ int Core_main(int argc, char** argv)
|
||||
|
||||
Allocator_free(tempAlloc);
|
||||
|
||||
Core_init(alloc, logger, eventBase, privateKey, admin, rand, eh, NULL, false);
|
||||
Core_init(alloc, logger, eventBase, privateKey, admin, rand, eh, false);
|
||||
EventBase_beginLoop(eventBase);
|
||||
return 0;
|
||||
}
|
||||
|
@@ -20,7 +20,6 @@
|
||||
#include "exception/Except.h"
|
||||
#include "memory/Allocator.h"
|
||||
#include "tunnel/IpTunnel.h"
|
||||
#include "util/events/FakeNetwork.h"
|
||||
#include "util/Linker.h"
|
||||
Linker_require("admin/angel/Core.c")
|
||||
|
||||
@@ -40,7 +39,6 @@ void Core_init(struct Allocator* alloc,
|
||||
struct Admin* admin,
|
||||
struct Random* rand,
|
||||
struct Except* eh,
|
||||
struct FakeNetwork* fakeNet,
|
||||
bool noSec);
|
||||
|
||||
int Core_main(int argc, char** argv);
|
||||
|
@@ -48,7 +48,6 @@
|
||||
#include "util/events/EventBase.h"
|
||||
#include "util/events/Pipe.h"
|
||||
#include "util/events/Process.h"
|
||||
#include "util/events/FakeNetwork.h"
|
||||
#include "util/events/libuv/Glock.h"
|
||||
#include "util/Hex.h"
|
||||
#include "util/log/Log.h"
|
||||
|
@@ -1,457 +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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "benc/serialization/standard/BencMessageReader.h"
|
||||
#include "benc/serialization/standard/BencMessageWriter.h"
|
||||
#include "benc/serialization/json/JsonBencSerializer.h"
|
||||
#include "benc/serialization/BencSerializer.h"
|
||||
#include "benc/List.h"
|
||||
#include "io/ArrayReader.h"
|
||||
#include "admin/angel/Core.h"
|
||||
#include "client/AdminClient.h"
|
||||
#include "interface/ASynchronizer.h"
|
||||
#include "interface/addressable/AddrIfaceAdapter.h"
|
||||
#include "memory/Allocator.h"
|
||||
#include "util/log/FileWriterLog.h"
|
||||
#include "wire/Message.h"
|
||||
#include "util/events/EventBase.h"
|
||||
#include "crypto/random/Random.h"
|
||||
#include "crypto/random/nanotime/NanotimeEntropyProvider.h"
|
||||
#include "exception/Except.h"
|
||||
#include "util/events/Timeout.h"
|
||||
#include "crypto/Key.h"
|
||||
#include "util/log/Log_impl.h"
|
||||
#include "io/FileReader.h"
|
||||
#include "io/ArrayWriter.h"
|
||||
#include "util/Hex.h"
|
||||
#include "util/events/FakeNetwork.h"
|
||||
#include "util/Hash.h"
|
||||
|
||||
#include <sodium/crypto_scalarmult_curve25519.h>
|
||||
|
||||
#include <unistd.h> // isatty()
|
||||
|
||||
struct NodeContext {
|
||||
struct Sockaddr* boundAddr;
|
||||
struct Allocator* alloc;
|
||||
struct EventBase* base;
|
||||
uint8_t privateKey[32];
|
||||
String* publicKey;
|
||||
struct AdminClient* adminClient;
|
||||
struct Admin* admin;
|
||||
|
||||
char* nodeName;
|
||||
|
||||
/** Admin socket to bind */
|
||||
String* bind;
|
||||
|
||||
/** Admin password */
|
||||
String* pass;
|
||||
|
||||
/** UDPInterface */
|
||||
int ifNum;
|
||||
struct Sockaddr* udpAddr;
|
||||
|
||||
struct Log nodeLog;
|
||||
struct Log* parentLogger;
|
||||
|
||||
List* peers;
|
||||
|
||||
Identity
|
||||
};
|
||||
|
||||
struct RPCCall;
|
||||
|
||||
typedef void (* RPCCallback)(struct RPCCall* call, struct AdminClient_Result* res);
|
||||
|
||||
struct RPCCall
|
||||
{
|
||||
String* func;
|
||||
Dict* args;
|
||||
struct NodeContext* node;
|
||||
RPCCallback callback;
|
||||
};
|
||||
|
||||
#define Map_KEY_TYPE String*
|
||||
#define Map_VALUE_TYPE struct NodeContext*
|
||||
#define Map_NAME OfNodes
|
||||
#define Map_USE_COMPARATOR
|
||||
#define Map_USE_HASH
|
||||
#include "util/Map.h"
|
||||
static inline int Map_OfNodes_compare(String** a, String** b)
|
||||
{
|
||||
return String_compare(*a, *b);
|
||||
}
|
||||
static inline uint32_t Map_OfNodes_hash(String** a)
|
||||
{
|
||||
return Hash_compute(a[0]->bytes, a[0]->len);
|
||||
}
|
||||
|
||||
struct Context
|
||||
{
|
||||
struct RPCCall* rpcCalls;
|
||||
int rpcCallCount;
|
||||
int nextCall;
|
||||
struct Allocator* rpcAlloc;
|
||||
|
||||
struct Random* rand;
|
||||
struct EventBase* base;
|
||||
struct Log* logger;
|
||||
struct Allocator* alloc;
|
||||
|
||||
struct Map_OfNodes nodeMap;
|
||||
Dict* confNodes;
|
||||
|
||||
Identity
|
||||
};
|
||||
|
||||
static String* pubKeyForPriv(uint8_t* privateKey, struct Allocator* alloc)
|
||||
{
|
||||
uint8_t publicKey[32];
|
||||
crypto_scalarmult_curve25519_base(publicKey, privateKey);
|
||||
return Key_stringify(publicKey, alloc);
|
||||
}
|
||||
|
||||
static void printLog(struct Log* log,
|
||||
enum Log_Level logLevel,
|
||||
const char* file,
|
||||
int line,
|
||||
const char* format,
|
||||
va_list args)
|
||||
{
|
||||
struct NodeContext* ctx = Identity_check(
|
||||
(struct NodeContext*) (((char*)log) - offsetof(struct NodeContext, nodeLog))
|
||||
);
|
||||
struct Allocator* alloc = Allocator_child(ctx->alloc);
|
||||
String* str = String_printf(alloc, "[%s] %s", ctx->nodeName, file);
|
||||
ctx->parentLogger->print(ctx->parentLogger, logLevel, str->bytes, line, format, args);
|
||||
Allocator_free(alloc);
|
||||
}
|
||||
|
||||
static struct RPCCall* pushCall(struct Context* ctx)
|
||||
{
|
||||
ctx->rpcCalls = Allocator_realloc(ctx->rpcAlloc,
|
||||
ctx->rpcCalls,
|
||||
sizeof(struct RPCCall) * (ctx->rpcCallCount+1));
|
||||
Bits_memset(&ctx->rpcCalls[ctx->rpcCallCount], 0, sizeof(struct RPCCall));
|
||||
return &ctx->rpcCalls[ctx->rpcCallCount++];
|
||||
}
|
||||
|
||||
static void bindUDPCallback(struct RPCCall* call, struct AdminClient_Result* res)
|
||||
{
|
||||
Assert_true(!res->err);
|
||||
// Indirection to shutup clang warning
|
||||
struct Log* logger = &call->node->nodeLog;
|
||||
Log_debug(logger, "UDPInterface_new() -> [%s]", res->messageBytes);
|
||||
String* addr = Dict_getStringC(res->responseDict, "bindAddress");
|
||||
int64_t* ifNum = Dict_getIntC(res->responseDict, "interfaceNumber");
|
||||
struct Sockaddr_storage ss;
|
||||
Assert_true(!Sockaddr_parse(addr->bytes, &ss));
|
||||
call->node->ifNum = *ifNum;
|
||||
call->node->udpAddr = Sockaddr_clone(&ss.addr, call->node->alloc);
|
||||
}
|
||||
|
||||
static void bindUDP(struct Context* ctx, struct NodeContext* node)
|
||||
{
|
||||
struct RPCCall* call = pushCall(ctx);
|
||||
call->func = String_new("UDPInterface_new", ctx->rpcAlloc);
|
||||
call->args = Dict_new(ctx->rpcAlloc);
|
||||
call->node = node;
|
||||
call->callback = bindUDPCallback;
|
||||
}
|
||||
|
||||
static void securitySetupComplete(struct Context* ctx, struct NodeContext* node)
|
||||
{
|
||||
struct RPCCall* call = pushCall(ctx);
|
||||
call->func = String_new("Security_setupComplete", ctx->rpcAlloc);
|
||||
call->args = Dict_new(ctx->rpcAlloc);
|
||||
call->node = node;
|
||||
}
|
||||
|
||||
static struct NodeContext* startNode(char* nodeName,
|
||||
char* privateKeyHex,
|
||||
Dict* admin,
|
||||
struct Context* ctx,
|
||||
struct Except* eh,
|
||||
struct FakeNetwork* fakeNet)
|
||||
{
|
||||
struct Allocator* alloc = Allocator_child(ctx->alloc);
|
||||
struct NodeContext* node = Allocator_clone(alloc, (&(struct NodeContext) {
|
||||
.alloc = alloc,
|
||||
.base = ctx->base,
|
||||
.nodeLog = {
|
||||
.print = printLog
|
||||
},
|
||||
.parentLogger = ctx->logger,
|
||||
.nodeName = nodeName
|
||||
}));
|
||||
Identity_set(node);
|
||||
|
||||
node->bind = Dict_getStringC(admin, "bind");
|
||||
if (!node->bind) {
|
||||
node->bind = String_new("127.0.0.1:0", alloc);
|
||||
}
|
||||
node->pass = Dict_getStringC(admin, "password");
|
||||
if (!node->pass) {
|
||||
node->pass = String_new("x", alloc);
|
||||
}
|
||||
|
||||
Assert_true(Hex_decode(node->privateKey, 32, privateKeyHex, 64) == 32);
|
||||
|
||||
struct AddrIfaceAdapter* adminClientIface = AddrIfaceAdapter_new(node->alloc);
|
||||
struct AddrIfaceAdapter* adminIface = AddrIfaceAdapter_new(node->alloc);
|
||||
struct ASynchronizer* asyncer = ASynchronizer_new(node->alloc, ctx->base, ctx->logger);
|
||||
Iface_plumb(&asyncer->ifA, &adminClientIface->inputIf);
|
||||
Iface_plumb(&asyncer->ifB, &adminIface->inputIf);
|
||||
|
||||
String* pass = String_new("12345", node->alloc);
|
||||
node->adminClient = AdminClient_new(&adminClientIface->generic,
|
||||
Sockaddr_clone(Sockaddr_LOOPBACK, node->alloc),
|
||||
pass,
|
||||
ctx->base,
|
||||
&node->nodeLog,
|
||||
node->alloc);
|
||||
|
||||
node->admin = Admin_new(&adminIface->generic, &node->nodeLog, ctx->base, pass);
|
||||
|
||||
Core_init(node->alloc,
|
||||
&node->nodeLog,
|
||||
ctx->base,
|
||||
node->privateKey,
|
||||
node->admin,
|
||||
ctx->rand,
|
||||
eh,
|
||||
fakeNet,
|
||||
true);
|
||||
|
||||
securitySetupComplete(ctx, node);
|
||||
bindUDP(ctx, node);
|
||||
node->publicKey = pubKeyForPriv(node->privateKey, node->alloc);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static void beginConnectionCallback(struct RPCCall* call, struct AdminClient_Result* res)
|
||||
{
|
||||
Assert_true(!res->err);
|
||||
// Indirection to shutup clang warning
|
||||
struct Log* logger = &call->node->nodeLog;
|
||||
Log_debug(logger, "UDPInterface_beginConnection() -> [%s]", res->messageBytes);
|
||||
}
|
||||
|
||||
static void linkNodes(struct Context* ctx, struct NodeContext* client, struct NodeContext* server)
|
||||
{
|
||||
Dict* addPasswordArgs = Dict_new(ctx->rpcAlloc);
|
||||
String* clientStr = String_printf(ctx->rpcAlloc, "%ld", (long) (uintptr_t) client);
|
||||
Dict_putString(addPasswordArgs,
|
||||
String_new("password", ctx->rpcAlloc),
|
||||
clientStr,
|
||||
ctx->rpcAlloc);
|
||||
Dict_putString(addPasswordArgs,
|
||||
String_new("user", ctx->rpcAlloc),
|
||||
clientStr,
|
||||
ctx->rpcAlloc);
|
||||
struct RPCCall* addPasswordCall = pushCall(ctx);
|
||||
addPasswordCall->func = String_new("AuthorizedPasswords_add", ctx->rpcAlloc);
|
||||
addPasswordCall->args = addPasswordArgs;
|
||||
addPasswordCall->node = server;
|
||||
|
||||
// client
|
||||
Dict* beginConnectionArgs = Dict_new(ctx->rpcAlloc);
|
||||
Dict_putInt(beginConnectionArgs,
|
||||
String_new("interfaceNumber", ctx->rpcAlloc),
|
||||
client->ifNum,
|
||||
ctx->rpcAlloc);
|
||||
Dict_putString(beginConnectionArgs,
|
||||
String_new("password", ctx->rpcAlloc),
|
||||
clientStr,
|
||||
ctx->rpcAlloc);
|
||||
Dict_putString(beginConnectionArgs,
|
||||
String_new("publicKey", ctx->rpcAlloc),
|
||||
server->publicKey,
|
||||
ctx->rpcAlloc);
|
||||
char* udpAddr = Sockaddr_print(server->udpAddr, ctx->rpcAlloc);
|
||||
Dict_putString(beginConnectionArgs,
|
||||
String_new("address", ctx->rpcAlloc),
|
||||
String_new(udpAddr, ctx->rpcAlloc),
|
||||
ctx->rpcAlloc);
|
||||
|
||||
Log_info(ctx->logger, "Linking [%s] with [%s/%s]",
|
||||
client->nodeName, server->nodeName, udpAddr);
|
||||
|
||||
struct RPCCall* connectCall = pushCall(ctx);
|
||||
connectCall->func = String_new("UDPInterface_beginConnection", ctx->rpcAlloc);
|
||||
connectCall->args = beginConnectionArgs;
|
||||
connectCall->node = client;
|
||||
connectCall->callback = beginConnectionCallback;
|
||||
}
|
||||
|
||||
static void linkAllNodes(struct Context* ctx)
|
||||
{
|
||||
int i = 0;
|
||||
String* key = NULL;
|
||||
Dict_forEach(ctx->confNodes, key) {
|
||||
int nodeIdx = Map_OfNodes_indexForKey(&key, &ctx->nodeMap);
|
||||
Assert_true(nodeIdx >= 0);
|
||||
struct NodeContext* nc = ctx->nodeMap.values[nodeIdx];
|
||||
List* connectTo = nc->peers;
|
||||
for (int j = 0; j < List_size(connectTo); j++) {
|
||||
String* server = List_getString(connectTo, j);
|
||||
Assert_true(server);
|
||||
int nodeIdxB = Map_OfNodes_indexForKey(&server, &ctx->nodeMap);
|
||||
Assert_true(nodeIdxB >= 0);
|
||||
struct NodeContext* ncB = ctx->nodeMap.values[nodeIdxB];
|
||||
linkNodes(ctx, nc, ncB);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
ctx->confNodes = NULL;
|
||||
}
|
||||
|
||||
static void startRpc(void* vcontext);
|
||||
|
||||
static void rpcCallback(struct AdminClient_Promise* promise, struct AdminClient_Result* res)
|
||||
{
|
||||
struct Context* ctx = promise->userData;
|
||||
Identity_check(ctx);
|
||||
|
||||
struct RPCCall* thisCall = &ctx->rpcCalls[ctx->nextCall];
|
||||
if (thisCall->callback) {
|
||||
thisCall->callback(thisCall, res);
|
||||
}
|
||||
|
||||
ctx->nextCall++;
|
||||
startRpc(ctx);
|
||||
}
|
||||
|
||||
static void startRpc(void* vcontext)
|
||||
{
|
||||
struct Context* ctx = vcontext;
|
||||
Identity_check(ctx);
|
||||
|
||||
if (ctx->nextCall >= ctx->rpcCallCount) {
|
||||
if (ctx->confNodes) {
|
||||
linkAllNodes(ctx);
|
||||
}
|
||||
}
|
||||
if (ctx->nextCall >= ctx->rpcCallCount) {
|
||||
Log_info(ctx->logger, "\n\nCompleted setting up simulation\n\n");
|
||||
Allocator_free(ctx->rpcAlloc);
|
||||
ctx->rpcAlloc = NULL;
|
||||
ctx->rpcCalls = NULL;
|
||||
ctx->rpcCallCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
struct RPCCall* nextCall = &ctx->rpcCalls[ctx->nextCall];
|
||||
struct AdminClient_Promise* promise = AdminClient_rpcCall(nextCall->func,
|
||||
nextCall->args,
|
||||
nextCall->node->adminClient,
|
||||
ctx->rpcAlloc);
|
||||
promise->callback = rpcCallback;
|
||||
promise->userData = ctx;
|
||||
}
|
||||
|
||||
static void letErRip(Dict* config, struct Allocator* alloc)
|
||||
{
|
||||
struct Except* eh = NULL;
|
||||
struct Log* logger = FileWriterLog_new(stdout, alloc);
|
||||
struct EventBase* base = EventBase_new(alloc);
|
||||
struct Random* rand = NanotimeEntropyProvider_newDefaultRandom(base, logger, eh, alloc);
|
||||
Allocator_setCanary(alloc, (uintptr_t)Random_uint64(rand));
|
||||
|
||||
struct Context sctx = {
|
||||
.rpcAlloc = Allocator_child(alloc),
|
||||
|
||||
.logger = logger,
|
||||
.base = base,
|
||||
.rand = rand,
|
||||
.alloc = alloc,
|
||||
.nodeMap = {
|
||||
.allocator = alloc
|
||||
}
|
||||
};
|
||||
struct Context* ctx = &sctx;
|
||||
Identity_set(ctx);
|
||||
|
||||
ctx->confNodes = Dict_getDictC(config, "nodes");
|
||||
|
||||
struct FakeNetwork* fakeNet = FakeNetwork_new(base, alloc, logger);
|
||||
|
||||
String* key = NULL;
|
||||
Dict_forEach(ctx->confNodes, key) {
|
||||
Dict* val = Dict_getDict(ctx->confNodes, key);
|
||||
String* privateKeyHex = Dict_getStringC(val, "privateKey");
|
||||
Dict* admin = Dict_getDictC(val, "admin");
|
||||
struct NodeContext* nc =
|
||||
startNode(key->bytes, privateKeyHex->bytes, admin, ctx, eh, fakeNet);
|
||||
nc->peers = Dict_getListC(val, "peers");
|
||||
Map_OfNodes_put(&key, &nc, &ctx->nodeMap);
|
||||
}
|
||||
|
||||
Log_info(ctx->logger, "\n\nAll nodes initialized\n\n");
|
||||
|
||||
// begin the chain of RPC calls which sets up the net
|
||||
Timeout_setTimeout(startRpc, ctx, 0, base, ctx->rpcAlloc);
|
||||
|
||||
EventBase_beginLoop(base);
|
||||
|
||||
Allocator_free(alloc);
|
||||
}
|
||||
|
||||
static int usage(char* appName)
|
||||
{
|
||||
printf("Example usage: %s < config.json\n"
|
||||
"Example config:\n"
|
||||
"{\n"
|
||||
" \"nodes\": {\n"
|
||||
" \"alice\": {\n"
|
||||
" \"privateKey\": "
|
||||
"\"5e2295679394e5e1db67c238abbc10292ad9b127904394c52cc5fff39383e920\",\n"
|
||||
" \"peers\": []\n"
|
||||
" },\n"
|
||||
" \"bob\": {\n"
|
||||
" \"privateKey\": "
|
||||
"\"6569bf3f0d168faa6dfb2912f8ee5ee9b938319e97618fdf06caed73b1aad1cc\",\n"
|
||||
" \"peers\": [\n"
|
||||
" \"alice\"\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n", appName);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This is invoked from sybilsim.rs
|
||||
int sybilsim_main(int argc, char** argv);
|
||||
int sybilsim_main(int argc, char** argv)
|
||||
{
|
||||
Assert_true(argc > 0);
|
||||
if (isatty(STDIN_FILENO)) {
|
||||
return usage(argv[0]);
|
||||
}
|
||||
|
||||
struct Allocator* alloc = Allocator_new(1LL<<31);
|
||||
|
||||
struct Reader* stdinReader = FileReader_new(stdin, alloc);
|
||||
Dict config;
|
||||
if (JsonBencSerializer_get()->parseDictionary(stdinReader, alloc, &config)) {
|
||||
fprintf(stderr, "Failed to parse configuration.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
letErRip(&config, alloc);
|
||||
return 0;
|
||||
}
|
@@ -1,43 +0,0 @@
|
||||
sybilsim(8) -- Cjdns packet switch
|
||||
=============================================
|
||||
|
||||
## SYNOPSIS
|
||||
|
||||
`/usr/libexec/cjdns/sybilsim < config.json`
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
Sybilsim reads a list of nodes and peers from stdin and simulates the
|
||||
corresponding mesh without any actual networking using the same code
|
||||
as cjdroute. This is useful for testing and optimizing cjdroute.
|
||||
Every node must have a valid cjdns private key. The makekeys(1) utility can be
|
||||
useful for scripts that generate the config.
|
||||
|
||||
## USAGE
|
||||
|
||||
Example config:
|
||||
|
||||
{
|
||||
"nodes": {
|
||||
"alice": {
|
||||
"privateKey":
|
||||
"5e2295679394e5e1db67c238abbc10292ad9b127904394c52cc5fff39383e920",
|
||||
"peers": []
|
||||
},
|
||||
"bob": {
|
||||
"privateKey":
|
||||
"6569bf3f0d168faa6dfb2912f8ee5ee9b938319e97618fdf06caed73b1aad1cc",
|
||||
"peers": [ "alice" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Example use:
|
||||
|
||||
makekeys | head -20 >keys.txt
|
||||
node /usr/libexec/cjdns/tools/lib/makesim.js keys.txt |
|
||||
/usr/libexec/cjdns/sybilsim
|
||||
|
||||
## SEE ALSO
|
||||
|
||||
makekeys(1), cjdroute(1)
|
@@ -11,12 +11,6 @@ RUN adduser -D -h /etc/cjdns -u 1000 cjdns \
|
||||
&& rm -rf build_* && ./do \
|
||||
&& cp cjdroute /usr/bin \
|
||||
&& cp -r tools/* /usr/bin \
|
||||
&& cp makekeys \
|
||||
mkpasswd \
|
||||
privatetopublic \
|
||||
publictoip6 \
|
||||
randombytes \
|
||||
sybilsim /usr/bin \
|
||||
&& cp contrib/docker/entrypoint.sh / \
|
||||
&& rm -rf /src /var/cache/apk/* \
|
||||
&& apk del --purge python build-base linux-headers
|
||||
|
@@ -121,8 +121,6 @@ ln contrib/selinux/cjdns.{te,fc} . # for doc dir
|
||||
|
||||
# install c and nodejs tools
|
||||
mkdir -p %{buildroot}%{_prefix}/lib/cjdns/{node_build,contrib}
|
||||
cp -p publictoip6 privatetopublic makekeys randombytes sybilsim \
|
||||
$RPM_BUILD_ROOT%{_prefix}/lib/cjdns
|
||||
cp -pr tools $RPM_BUILD_ROOT%{_prefix}/lib/cjdns
|
||||
cp -p node_build/Semaphore.js $RPM_BUILD_ROOT%{_prefix}/lib/cjdns/node_build
|
||||
cp -pr contrib/nodejs $RPM_BUILD_ROOT%{_prefix}/lib/cjdns/contrib
|
||||
|
@@ -5,7 +5,6 @@ cp mkpasswd /usr/bin/
|
||||
cp privatetopublic /usr/bin/
|
||||
cp publictoip6 /usr/bin/
|
||||
cp randombytes /usr/bin/
|
||||
cp sybilsim /usr/bin/
|
||||
cp contrib/systemd/cjdns.service /etc/systemd/system/
|
||||
cp contrib/systemd/cjdns-resume.service /etc/systemd/system
|
||||
systemctl enable --now cjdns.service
|
||||
|
@@ -17,7 +17,6 @@
|
||||
#include "memory/Allocator.h"
|
||||
#include "net/InterfaceController.h"
|
||||
#include "util/events/EventBase.h"
|
||||
#include "util/events/FakeNetwork.h"
|
||||
#include "util/platform/Sockaddr.h"
|
||||
#include "crypto/Key.h"
|
||||
#include "interface/UDPInterface_admin.h"
|
||||
@@ -36,7 +35,6 @@ struct Context
|
||||
struct Admin* admin;
|
||||
struct ArrayList_UDPInterface* ifaces;
|
||||
struct InterfaceController* ic;
|
||||
struct FakeNetwork* fakeNet;
|
||||
struct GlobalConfig* globalConf;
|
||||
Identity
|
||||
};
|
||||
@@ -333,7 +331,6 @@ void UDPInterface_admin_register(struct EventBase* base,
|
||||
struct Log* logger,
|
||||
struct Admin* admin,
|
||||
struct InterfaceController* ic,
|
||||
struct FakeNetwork* fakeNet,
|
||||
struct GlobalConfig* globalConf)
|
||||
{
|
||||
struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
|
||||
@@ -342,7 +339,6 @@ void UDPInterface_admin_register(struct EventBase* base,
|
||||
.logger = logger,
|
||||
.admin = admin,
|
||||
.ic = ic,
|
||||
.fakeNet = fakeNet,
|
||||
.globalConf = globalConf
|
||||
}));
|
||||
Identity_set(ctx);
|
||||
|
@@ -20,7 +20,6 @@
|
||||
#include "net/InterfaceController.h"
|
||||
#include "util/log/Log.h"
|
||||
#include "util/events/EventBase.h"
|
||||
#include "util/events/FakeNetwork.h"
|
||||
#include "util/GlobalConfig.h"
|
||||
#include "util/Linker.h"
|
||||
Linker_require("interface/UDPInterface_admin.c")
|
||||
@@ -30,7 +29,6 @@ void UDPInterface_admin_register(struct EventBase* base,
|
||||
struct Log* logger,
|
||||
struct Admin* admin,
|
||||
struct InterfaceController* ic,
|
||||
struct FakeNetwork* fakeNet,
|
||||
struct GlobalConfig* globalConf);
|
||||
|
||||
#endif
|
||||
|
@@ -294,7 +294,6 @@ Builder.configure({
|
||||
|
||||
builder.buildLibrary('contrib/c/publictoip6.c');
|
||||
builder.buildLibrary('contrib/c/privatetopublic.c');
|
||||
builder.buildLibrary('contrib/c/sybilsim.c');
|
||||
builder.buildLibrary('contrib/c/makekeys.c');
|
||||
builder.buildLibrary('contrib/c/mkpasswd.c');
|
||||
builder.buildLibrary('crypto/random/randombytes.c');
|
||||
|
@@ -1,44 +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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef FakeNetwork_H
|
||||
#define FakeNetwork_H
|
||||
|
||||
#include "exception/Except.h"
|
||||
#include "interface/Iface.h"
|
||||
#include "interface/addressable/AddrIface.h"
|
||||
#include "memory/Allocator.h"
|
||||
#include "util/events/EventBase.h"
|
||||
#include "util/log/Log.h"
|
||||
#include "util/Linker.h"
|
||||
Linker_require("util/events/libuv/FakeNetwork.c")
|
||||
|
||||
struct FakeNetwork
|
||||
{
|
||||
int unused;
|
||||
};
|
||||
|
||||
struct FakeNetwork_UDPIface
|
||||
{
|
||||
struct AddrIface generic;
|
||||
};
|
||||
|
||||
struct FakeNetwork* FakeNetwork_new(struct EventBase* base,
|
||||
struct Allocator* allocator,
|
||||
struct Log* logger);
|
||||
|
||||
struct FakeNetwork_UDPIface* FakeNetwork_iface(struct FakeNetwork* net,
|
||||
struct Sockaddr* bindAddress,
|
||||
struct Allocator* alloc);
|
||||
#endif
|
@@ -1,166 +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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "util/events/FakeNetwork.h"
|
||||
#include "exception/Except.h"
|
||||
#include "interface/Iface.h"
|
||||
#include "interface/addressable/AddrIface.h"
|
||||
#include "memory/Allocator.h"
|
||||
#include "util/events/EventBase.h"
|
||||
#include "util/log/Log.h"
|
||||
#include "interface/ASynchronizer.h"
|
||||
#include "wire/Error.h"
|
||||
|
||||
#define Map_USE_HASH
|
||||
#define Map_USE_COMPARATOR
|
||||
#define Map_NAME OfIfaces
|
||||
#define Map_KEY_TYPE struct Sockaddr*
|
||||
#define Map_VALUE_TYPE struct FakeNetwork_UDPIface_pvt*
|
||||
#include "util/Map.h"
|
||||
static inline uint32_t Map_OfIfaces_hash(struct Sockaddr** key)
|
||||
{
|
||||
return Sockaddr_hash(*key);
|
||||
}
|
||||
static inline int Map_OfIfaces_compare(struct Sockaddr** keyA, struct Sockaddr** keyB)
|
||||
{
|
||||
return Sockaddr_compare(*keyA, *keyB);
|
||||
}
|
||||
|
||||
struct FakeNetwork_pvt
|
||||
{
|
||||
struct FakeNetwork pub;
|
||||
struct Allocator* alloc;
|
||||
struct Log* log;
|
||||
struct EventBase* base;
|
||||
struct ASynchronizer* async;
|
||||
struct Iface fromAsync;
|
||||
struct Iface toAsync;
|
||||
uint16_t lastPort;
|
||||
|
||||
struct Map_OfIfaces map;
|
||||
Identity
|
||||
};
|
||||
|
||||
struct FakeNetwork_UDPIface_pvt
|
||||
{
|
||||
struct FakeNetwork_UDPIface pub;
|
||||
struct FakeNetwork_pvt* fnp;
|
||||
Identity
|
||||
};
|
||||
|
||||
static void popSockaddr(struct Message* msg, struct Sockaddr_storage* ss)
|
||||
{
|
||||
uint64_t length = 0;
|
||||
Er_assert(Message_epop(msg, &length, 8));
|
||||
Er_assert(Message_eshift(msg, 8));
|
||||
Assert_true(length >= Sockaddr_OVERHEAD);
|
||||
Assert_true(length <= sizeof(struct Sockaddr_storage));
|
||||
Er_assert(Message_epop(msg, ss, length));
|
||||
}
|
||||
|
||||
static void pushSockaddr(struct Message* msg, struct Sockaddr* sa)
|
||||
{
|
||||
Er_assert(Message_epush(msg, sa, sa->addrLen));
|
||||
}
|
||||
|
||||
static Iface_DEFUN fromAsync(struct Message* msg, struct Iface* fnpFromAsync)
|
||||
{
|
||||
struct FakeNetwork_pvt* fnp =
|
||||
Identity_containerOf(fnpFromAsync, struct FakeNetwork_pvt, fromAsync);
|
||||
|
||||
struct Sockaddr_storage dest;
|
||||
struct Sockaddr* dp = &dest.addr;
|
||||
popSockaddr(msg, &dest);
|
||||
int idx = Map_OfIfaces_indexForKey(&dp, &fnp->map);
|
||||
if (idx == -1) {
|
||||
char* destAddr = Sockaddr_print(dp, Message_getAlloc(msg));
|
||||
|
||||
// hack, the 'dest' becomes the source.
|
||||
popSockaddr(msg, &dest);
|
||||
char* srcAddr = Sockaddr_print(dp, Message_getAlloc(msg));
|
||||
|
||||
Log_debug(fnp->log, "Message with unknown dest address [%s] from [%s]", destAddr, srcAddr);
|
||||
return Error(msg, "INVALID");
|
||||
}
|
||||
|
||||
struct FakeNetwork_UDPIface_pvt* fnip = Identity_check(fnp->map.values[idx]);
|
||||
return Iface_next(&fnip->pub.generic.iface, msg);
|
||||
}
|
||||
|
||||
static Iface_DEFUN incoming(struct Message* msg, struct Iface* iface)
|
||||
{
|
||||
struct FakeNetwork_UDPIface_pvt* fnip =
|
||||
Identity_check((struct FakeNetwork_UDPIface_pvt*) iface);
|
||||
struct FakeNetwork_pvt* fnp = Identity_check(fnip->fnp);
|
||||
|
||||
// Swap so that the message contains [dest][src][content]
|
||||
struct Sockaddr_storage dest;
|
||||
popSockaddr(msg, &dest);
|
||||
pushSockaddr(msg, fnip->pub.generic.addr);
|
||||
pushSockaddr(msg, &dest.addr);
|
||||
|
||||
return Iface_next(&fnp->toAsync, msg);
|
||||
}
|
||||
|
||||
struct FakeNetwork_UDPIface* FakeNetwork_iface(struct FakeNetwork* net,
|
||||
struct Sockaddr* bindAddress,
|
||||
struct Allocator* allocator)
|
||||
{
|
||||
struct FakeNetwork_pvt* fnp = Identity_check((struct FakeNetwork_pvt*) net);
|
||||
struct Allocator* alloc = Allocator_child(allocator);
|
||||
struct Sockaddr* addr = Sockaddr_clone(bindAddress, alloc);
|
||||
|
||||
uint8_t* addrBytes;
|
||||
int addrLen = Sockaddr_getAddress(addr, &addrBytes);
|
||||
if (Sockaddr_getPort(addr) == 0) {
|
||||
Sockaddr_setPort(addr, ++fnp->lastPort);
|
||||
// Check for wrapping.
|
||||
Assert_true(fnp->lastPort != 0);
|
||||
Assert_true(addrLen == 4);
|
||||
Bits_memcpy(addrBytes, ((uint8_t[]){127, 0, 0, 1}), 4);
|
||||
} else if (addrLen == 4 && !Bits_memcmp(addrBytes, "\0\0\0\0", 4)) {
|
||||
Assert_failure("Address 0 with port specified is not allowed");
|
||||
}
|
||||
|
||||
if (Map_OfIfaces_indexForKey(&addr, &fnp->map) != -1) {
|
||||
return NULL;
|
||||
}
|
||||
struct FakeNetwork_UDPIface_pvt* fnip =
|
||||
Allocator_calloc(alloc, sizeof(struct FakeNetwork_UDPIface_pvt), 1);
|
||||
Map_OfIfaces_put(&addr, &fnip, &fnp->map);
|
||||
fnip->fnp = fnp;
|
||||
fnip->pub.generic.alloc = alloc;
|
||||
fnip->pub.generic.addr = addr;
|
||||
fnip->pub.generic.iface.send = incoming;
|
||||
Identity_set(fnip);
|
||||
return &fnip->pub;
|
||||
}
|
||||
|
||||
struct FakeNetwork* FakeNetwork_new(struct EventBase* base,
|
||||
struct Allocator* allocator,
|
||||
struct Log* logger)
|
||||
{
|
||||
struct Allocator* alloc = Allocator_child(allocator);
|
||||
struct FakeNetwork_pvt* fnp = Allocator_calloc(alloc, sizeof(struct FakeNetwork_pvt), 1);
|
||||
fnp->alloc = alloc;
|
||||
fnp->log = logger;
|
||||
fnp->base = base;
|
||||
fnp->map.allocator = alloc;
|
||||
fnp->async = ASynchronizer_new(alloc, base, logger);
|
||||
fnp->fromAsync.send = fromAsync;
|
||||
Iface_plumb(&fnp->fromAsync, &fnp->async->ifB);
|
||||
Iface_plumb(&fnp->toAsync, &fnp->async->ifA);
|
||||
Identity_set(fnp);
|
||||
return &fnp->pub;
|
||||
}
|
Reference in New Issue
Block a user