/** https://github.com/cjdelisle/cjdns/issues/179 */ static void test179(struct Allocator* alloc, struct Log* logger) { uint8_t buff[32] = {0}; uint8_t buff2[32] = {0}; struct Random* rand = Random_new(alloc, logger, NULL); struct Random* rand2 = Random_new(alloc, logger, NULL); Random_bytes(rand, buff, 32); Random_bytes(rand2, buff, 32); Assert_true(Bits_memcmp(buff, buff2, 32)); }
int main() { struct Allocator* alloc = MallocAllocator_new(1<<22); struct Random* rand = Random_new(alloc, NULL, NULL); struct Log* log = FileWriterLog_new(stdout, alloc); uint8_t ip[16]; uint8_t printedIp[40]; uint8_t printedShortIp[40]; uint8_t ipFromFull[16]; uint8_t ipFromShort[16]; for (int i = 0; i < 1024; ++i) { Random_bytes(rand, ip, 16); for (int j = 0; j < 16; j++) { // make the random result have lots of zeros since that's what we're looking for. ip[j] = (ip[j] % 2) ? 0 : ip[j]; } AddrTools_printIp(printedIp, ip); AddrTools_printShortIp(printedShortIp, ip); //printf("%s\n%s\n\n", printedIp, printedShortIp); AddrTools_parseIp(ipFromFull, printedIp); AddrTools_parseIp(ipFromShort, printedShortIp); Log_debug(log, "print/parse %s", printedIp); Assert_true(0 == Bits_memcmp(ip, ipFromFull, 16)); Assert_true(0 == Bits_memcmp(ipFromFull, ipFromShort, 16)); } Allocator_free(alloc); return 0; }
static void testDuplicates(struct Random* rand) { uint16_t randomShorts[8192]; uint16_t out[8192]; struct ReplayProtector rp = {.bitfield = 0}; Random_bytes(rand, (uint8_t*)randomShorts, sizeof(randomShorts)); uint32_t outIdx = 0; for (uint32_t i = 0; i < 1024; i++) { if (ReplayProtector_checkNonce((randomShorts[i] % (i + 20)), &rp)) { out[outIdx] = (randomShorts[i] % (i + 20)); outIdx++; } } for (uint32_t i = 0; i < outIdx; i++) { for (uint32_t j = i + 1; j < outIdx; j++) { Assert_always(out[i] != out[j]); } } } int main() { struct Allocator* alloc = MallocAllocator_new(4096); struct Random* rand = Random_new(alloc, NULL, NULL); for (int i = 0; i < CYCLES; i++) { testDuplicates(rand); } return 0; }
int main() { uint16_t randomShorts[8192]; uint16_t out[8192]; struct ReplayProtector rp = {0,0}; struct Allocator* alloc; BufferAllocator_STACK(alloc, 1024); struct Random* rand = Random_new(alloc, NULL, NULL); Random_bytes(rand, (uint8_t*)randomShorts, sizeof(randomShorts)); uint32_t outIdx = 0; for (uint32_t i = 0; i < 1024; i++) { if (ReplayProtector_checkNonce((randomShorts[i] % (i + 20)), &rp)) { out[outIdx] = (randomShorts[i] % (i + 20)); outIdx++; } } for (uint32_t i = 0; i < outIdx; i++) { for (uint32_t j = i + 1; j < outIdx; j++) { Assert_always(out[i] != out[j]); } } return 0; }
int main() { struct Allocator* alloc = MallocAllocator_new(1048576); struct Log* logger = FileWriterLog_new(stdout, alloc); struct Random* rand = Random_new(alloc, logger, NULL); uint8_t curve25519private[32]; Random_bytes(rand, curve25519private, 32); uint8_t curve25519public[32]; crypto_scalarmult_curve25519_base(curve25519public, curve25519private); uint8_t signingKeyPair[64]; Sign_signingKeyPairFromCurve25519(signingKeyPair, curve25519private); struct Message* msg = Message_new(0, 512, alloc); Message_push(msg, "hello world", 12, NULL); Sign_signMsg(signingKeyPair, msg, rand); uint8_t curve25519publicB[32]; Assert_true(!Sign_verifyMsg(&signingKeyPair[32], msg)); Assert_true(!Sign_publicSigningKeyToCurve25519(curve25519publicB, &signingKeyPair[32])); Assert_true(!Bits_memcmp(curve25519publicB, curve25519public, 32)); Allocator_free(alloc); return 0; }
int main() { struct Allocator* alloc = MallocAllocator_new(1<<22); struct Random* rand = Random_new(alloc, NULL, NULL); uint8_t ip[16]; uint8_t printedIp[40]; uint8_t printedShortIp[40]; uint8_t ipFromFull[16]; uint8_t ipFromShort[16]; for (int i = 0; i < 1024; ++i) { Random_bytes(rand, ip, 16); AddrTools_printIp(printedIp, ip); AddrTools_printShortIp(printedShortIp, ip); printf("%s\n%s\n\n", printedIp, printedShortIp); AddrTools_parseIp(ipFromFull, printedIp); AddrTools_parseIp(ipFromShort, printedShortIp); Assert_true(0 == Bits_memcmp(ip, ipFromFull, 16)); Assert_true(0 == Bits_memcmp(ipFromFull, ipFromShort, 16)); } return 0; }
struct AdminTestFramework* AdminTestFramework_setUp(int argc, char** argv, char* testName) { if (argc > 2 && !strcmp(testName, argv[1]) && !strcmp("angel", argv[2])) { exit(AngelInit_main(argc-1, &argv[1])); } struct Allocator* alloc = MallocAllocator_new(1<<20); struct Writer* logwriter = FileWriter_new(stdout, alloc); Assert_true(logwriter); struct Log* logger = WriterLog_new(logwriter, alloc); struct EventBase* eventBase = EventBase_new(alloc); struct Random* rand = Random_new(alloc, logger, NULL); char asClientPipeName[32] = {0}; Random_base32(rand, (uint8_t*)asClientPipeName, 31); struct Pipe* asClientPipe = Pipe_named(asClientPipeName, eventBase, NULL, alloc); asClientPipe->logger = logger; char asCorePipeName[32] = {0}; Random_base32(rand, (uint8_t*)asCorePipeName, 31); struct Pipe* asCorePipe = Pipe_named(asCorePipeName, eventBase, NULL, alloc); asCorePipe->logger = logger; struct Interface* asCoreIface = FramingInterface_new(65535, &asCorePipe->iface, alloc); spawnAngel(testName, asClientPipeName, eventBase, alloc); Log_info(logger, "Initializing Angel"); initAngel(asClientPipe, asCoreIface, (char*)asCorePipe->name, eventBase, logger, alloc, rand); struct Sockaddr_storage addr; Assert_true(!Sockaddr_parse("127.0.0.1", &addr)); Log_info(logger, "Binding UDP admin socket"); struct AddrInterface* udpAdmin = UDPAddrInterface_new(eventBase, &addr.addr, alloc, NULL, logger); String* password = String_new("abcd", alloc); struct Admin* admin = Admin_new(udpAdmin, alloc, logger, eventBase, password); // Now setup the client. struct AdminClient* client = AdminClient_new(udpAdmin->addr, password, eventBase, logger, alloc); Assert_true(client); return Allocator_clone(alloc, (&(struct AdminTestFramework) { .admin = admin, .client = client, .alloc = alloc, .eventBase = eventBase, .logger = logger, .addr = Sockaddr_clone(udpAdmin->addr, alloc), .angelInterface = asCoreIface }));
int main() { struct Allocator* alloc = MallocAllocator_new(20000000); struct Random* rand = Random_new(alloc, NULL, NULL); packUnpack(rand); return 0; }
int main() { struct Allocator* alloc = MallocAllocator_new(1<<20); struct Random* rand = Random_new(alloc, NULL, NULL); // mock interface controller. struct Context ctx = { .ic = { .registerPeer = registerPeer, .getPeerState = getPeerState } }; struct Interface externalIf = { .sendMessage = sendMessage, .allocator = alloc, .senderContext = &ctx }; /*struct MultiInterface* mif = */MultiInterface_new(KEY_SIZE, &externalIf, &ctx.ic); struct Entry* entries = Allocator_malloc(alloc, sizeof(struct Entry) * ENTRY_COUNT); Random_bytes(rand, (uint8_t*)entries, ENTRY_COUNT * sizeof(struct Entry)); struct Interface** ifaces = Allocator_calloc(alloc, sizeof(char*), ENTRY_COUNT); // seed the list with some near collisions. for (int i = 0; i < 10; i++) { int rnd = (((uint32_t*)entries)[i] >> 1) % ENTRY_COUNT; ((uint32_t*) (&entries[rnd]))[0] = ((uint32_t*) (&entries[i]))[0]; } for (int i = 0; i < CYCLES; i++) { int rnd = ((uint32_t*)entries)[i] % ENTRY_COUNT; struct Entry* entry = &entries[rnd]; struct Interface* iface = ifaces[rnd]; struct Message* msg; Message_STACK(msg, 0, 128); Message_push(msg, "hello world", 12); Message_push(msg, entry, 16); externalIf.receiveMessage(msg, &externalIf); //printf("Received message for iface [%u] from [%p]\n", rnd, (void*)ctx.receivedOn); if (iface) { Assert_always(ctx.receivedOn == iface); } else { ifaces[rnd] = ctx.receivedOn; } } Allocator_free(alloc); }
/** Check if nodes A and C can communicate via B without A knowing that C exists. */ void Benchmark_runAll() { struct Allocator* alloc = MallocAllocator_new(1<<22); struct Context* ctx = Allocator_calloc(alloc, sizeof(struct Context), 1); Identity_set(ctx); ctx->alloc = alloc; ctx->base = EventBase_new(alloc); struct Log* log = ctx->log = FileWriterLog_new(stdout, alloc); ctx->rand = Random_new(alloc, log, NULL); cryptoAuth(ctx); switching(ctx); }
/** Check if nodes A and C can communicate via B without A knowing that C exists. */ int main() { struct Allocator* alloc = MallocAllocator_new(1<<22); struct Writer* logwriter = FileWriter_new(stdout, alloc); struct Log* logger = WriterLog_new(logwriter, alloc); struct Random* rand = Random_new(alloc, logger, NULL); struct EventBase* base = EventBase_new(alloc); start(alloc, logger, base, rand, runTest); EventBase_beginLoop(base); Allocator_free(alloc); return 0; }
int main() { struct Allocator* alloc = MallocAllocator_new(1024); struct Random* rand = Random_new(alloc, NULL, NULL); FILE* tmp = tmpfile(); uint8_t buffer1[2048]; size_t checkSize; Random_bytes(rand, buffer1, 2048); checkSize = fwrite(buffer1, 1, 2048, tmp); if (checkSize != 2048) { return 1; } uint8_t buffer2[1024]; rewind(tmp); struct Reader* r = FileReader_new(tmp, alloc); Reader_read(r, buffer2, 128); Reader_skip(r, 128); Reader_read(r, buffer2+128, 128); Reader_skip(r, 512); Reader_read(r, buffer2+128+128, 256); Reader_skip(r, 300); Reader_read(r, buffer2+128+128+256, 128); Assert_true(r->bytesRead == 128+128+128+512+256+300+128); uint8_t* ptr1 = buffer1; uint8_t* ptr2 = buffer2; #define SKIP(x) ptr1 += x #define CMP(x) Assert_true(!Bits_memcmp(ptr1, ptr2, x)); ptr1 += x; ptr2 += x CMP(128); SKIP(128); CMP(128); SKIP(512); CMP(256); SKIP(300); CMP(128); Allocator_free(alloc); return 0; }
struct TestFramework* TestFramework_setUp(char* privateKey, struct Allocator* allocator, struct EventBase* base, struct Random* rand, struct Log* logger) { if (!logger) { struct Writer* logwriter = FileWriter_new(stdout, allocator); logger = WriterLog_new(logwriter, allocator); } if (!rand) { rand = Random_new(allocator, logger, NULL); } if (!base) { base = EventBase_new(allocator); } uint64_t pks[4]; if (!privateKey) { Random_longs(rand, pks, 4); privateKey = (char*)pks; } struct NetCore* nc = NetCore_new(privateKey, allocator, base, rand, logger); struct Pathfinder* pf = Pathfinder_register(allocator, logger, base, rand, NULL); struct ASynchronizer* pfAsync = ASynchronizer_new(allocator, base, logger); Iface_plumb(&pfAsync->ifA, &pf->eventIf); EventEmitter_regPathfinderIface(nc->ee, &pfAsync->ifB); 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; tf->pathfinder = pf; return tf; }
int main() { struct Allocator* stackAlloc; BufferAllocator_STACK(stackAlloc, 2048); struct Random* rand = Random_new(stackAlloc, NULL, NULL); for (int cycles = 0; cycles < CYCLES; cycles++) { struct Allocator* alloc = MallocAllocator_new(1<<18); struct Map_OfLongsByInteger* map = Map_OfLongsByInteger_new(alloc); uint32_t size; Random_bytes(rand, (uint8_t*) &size, 4); size = (size % 4096) + 101; uint32_t key = 3; uint64_t val = 4; for (uint32_t i = 0; i < size; i++) { Map_OfLongsByInteger_put(&key, &val, map); key += val >> 13 ^ size << 19; val += key >> 19 ^ i << 13; } // If a key is duplicated, the entry will br replaced. size = map->count; for (uint32_t i = size - 1; i > size - 100; i--) { int index = map->keys[i] % size; uint32_t handle = map->handles[index]; if (index != Map_OfLongsByInteger_indexForHandle(handle, map)) { uint32_t num = 0; for (int i = 0; i < (int)map->count; i++) { if (num > map->handles[i]) { Assert_true(!"map out of order"); } num = map->handles[i]; } printf("failed to find the correct index for the handle " "handle[%u], index[%u], indexForHandle[%u]\n", handle, index, Map_OfLongsByInteger_indexForHandle(handle, map)); Assert_true(false); } } Allocator_free(alloc); } }
void CryptoAuth_benchmark(struct EventBase* base, struct Log* logger, struct Allocator* alloc) { struct Random* rand = Random_new(alloc, logger, NULL); struct Context ctx = { .ca1 = CryptoAuth_new(alloc, NULL, base, NULL, rand), .ca2 = CryptoAuth_new(alloc, privateKey, base, NULL, rand), .if1 = { .sendMessage = transferMessage, .senderContext = &ctx.if2, .allocator = alloc }, .if2 = { .sendMessage = transferMessage, .senderContext = &ctx.if1, .allocator = alloc }, .base = base
static int init(const uint8_t* privateKey, uint8_t* publicKey, const uint8_t* password) { printf("\nSetting up:\n"); struct Allocator* allocator = MallocAllocator_new(1048576); textBuff = Allocator_malloc(allocator, BUFFER_SIZE); struct Writer* logwriter = FileWriter_new(stdout, allocator); struct Log* logger = WriterLog_new(logwriter, allocator); struct Random* rand = Random_new(allocator, logger, NULL); struct EventBase* base = EventBase_new(allocator); ca1 = CryptoAuth_new(allocator, NULL, base, logger, rand); if1 = Allocator_clone(allocator, (&(struct Interface) { .sendMessage = sendMessageToIf2, .receiveMessage = recvMessageOnIf2, .allocator = allocator }));
int main() { struct Allocator* alloc; BufferAllocator_STACK(alloc, 512); struct Random* rand = Random_new(alloc, NULL); uint8_t bytes[32]; Random_bytes(rand, bytes, 32); uint8_t base32[64]; Bits_memset(base32, 0, 64); Assert_always(Base32_encode(base32, 64, bytes, 32) == 52); //printf("base32 encoded: %s\n", base32); uint8_t bytes2[32]; Assert_always(Base32_decode(bytes2, 32, base32, 52) == 32); Assert_always(Bits_memcmp(bytes, bytes2, 32) == 0); }
int main(int argc, char** argv) { struct Allocator* alloc = MallocAllocator_new(1<<22); struct Random* rand = Random_new(alloc, NULL, NULL); uint8_t privateKey[32]; uint8_t publicKey[32]; uint8_t ip[16]; uint8_t hexPrivateKey[65]; uint8_t printedIp[40]; for (;;) { Random_bytes(rand, privateKey, 32); crypto_scalarmult_curve25519_base(publicKey, privateKey); if (AddressCalc_addressForPublicKey(ip, publicKey)) { Hex_encode(hexPrivateKey, 65, privateKey, 32); AddrTools_printIp(printedIp, ip); printf("%s %s\n", hexPrivateKey, printedIp); } } return 0; }
int main() { struct Allocator* alloc = MallocAllocator_new(20000); struct Random* rand = Random_new(alloc, NULL, NULL); uint8_t bytes[32]; Random_bytes(rand, bytes, 32); uint8_t hex[65] = {0}; Assert_true(Hex_encode(hex, 65, bytes, 32) == 64); //printf("hex encoded: %s\n", hex); uint8_t bytes2[32]; Assert_true(Hex_decode(bytes2, 32, hex, 64) == 32); Assert_true(Bits_memcmp(bytes, bytes2, 32) == 0); Allocator_free(alloc); return 0; }
int main() { struct Allocator* alloc = MallocAllocator_new(20000); struct Random* rand = Random_new(alloc, NULL, NULL); uint8_t bytes[32]; Random_bytes(rand, bytes, 32); uint8_t base32[64]; Bits_memset(base32, 0, 64); Assert_always(Base32_encode(base32, 64, bytes, 32) == 52); //printf("base32 encoded: %s\n", base32); uint8_t bytes2[32]; Assert_always(Base32_decode(bytes2, 32, base32, 52) == 32); Assert_always(Bits_memcmp(bytes, bytes2, 32) == 0); Allocator_free(alloc); return 0; }
/** @return a string representing the address and port to connect to. */ static String* initAngel(int fromAngel, int toAngel, int corePipes[2][2], struct PipeInterface** piOut, struct EventBase* eventBase, struct Log* logger, struct Allocator* alloc, struct Random* rand) { #define TO_CORE (corePipes[0][1]) #define FROM_CORE (corePipes[1][0]) #define TO_ANGEL_AS_CORE (corePipes[1][1]) #define FROM_ANGEL_AS_CORE (corePipes[0][0]) Dict core = Dict_CONST( String_CONST("fromCore"), Int_OBJ(FROM_CORE), Dict_CONST( String_CONST("toCore"), Int_OBJ(TO_CORE), NULL )); Dict admin = Dict_CONST( String_CONST("bind"), String_OBJ(String_CONST("127.0.0.1")), Dict_CONST( String_CONST("core"), Dict_OBJ(&core), Dict_CONST( String_CONST("pass"), String_OBJ(String_CONST("abcd")), NULL ))); Dict message = Dict_CONST( String_CONST("admin"), Dict_OBJ(&admin), NULL ); struct Allocator* tempAlloc; BufferAllocator_STACK(tempAlloc, 1024); #define BUFFER_SZ 1023 uint8_t buff[BUFFER_SZ + 1] = {0}; struct Writer* w = ArrayWriter_new(buff, BUFFER_SZ, tempAlloc); StandardBencSerializer_get()->serializeDictionary(w, &message); Log_info(logger, "Writing intial configuration to angel on [%d] config: [%s]", toAngel, buff); write(toAngel, buff, w->bytesWritten(w)); // This is angel->core data, we can throw this away. //Waiter_getData(buff, BUFFER_SZ, fromAngel, eventBase, NULL); //Log_info(logger, "Init message from angel to core: [%s]", buff); Bits_memset(buff, 0, BUFFER_SZ); struct PipeInterface* pi = PipeInterface_new(FROM_ANGEL_AS_CORE, TO_ANGEL_AS_CORE, eventBase, logger, alloc, rand); *piOut = pi; Log_info(logger, "PipeInterface [%p] is now ready.", (void*)pi); // Make sure the angel sends data to the core. InterfaceWaiter_waitForData(&pi->generic, eventBase, alloc, NULL); // Send response on behalf of core. char coreToAngelResponse[128] = " PADDING " "\xff\xff\xff\xff" "d" "5:error" "4:none" "e"; char* start = strchr(coreToAngelResponse, '\xff'); struct Message m = { .bytes = (uint8_t*) start, .length = strlen(start), .padding = start - coreToAngelResponse }; pi->generic.sendMessage(&m, &pi->generic); // This is angel->client data, it will tell us which port was bound. Waiter_getData(buff, BUFFER_SZ, fromAngel, eventBase, NULL); printf("Response from angel to client: [%s]\n", buff); struct Reader* reader = ArrayReader_new(buff, BUFFER_SZ, tempAlloc); Dict configStore; Dict* config = &configStore; Assert_true(!StandardBencSerializer_get()->parseDictionary(reader, tempAlloc, config)); Dict* responseAdmin = Dict_getDict(config, String_CONST("admin")); String* bind = Dict_getString(responseAdmin, String_CONST("bind")); Assert_true(bind); return String_clone(bind, alloc); } /** * This spawns itself as the Angel process which spawns itself again as the core process. * The "core process" pipes all of its inputs back to the originating process */ struct AdminTestFramework* AdminTestFramework_setUp(int argc, char** argv) { if (argc > 1 && !strcmp("angel", argv[1])) { exit(AngelInit_main(argc, argv)); } struct Allocator* alloc = CanaryAllocator_new(MallocAllocator_new(1<<20), NULL); struct Writer* logwriter = FileWriter_new(stdout, alloc); Assert_always(logwriter); struct Log* logger = WriterLog_new(logwriter, alloc); struct EventBase* eventBase = EventBase_new(alloc); struct Random* rand = Random_new(alloc, NULL); int fromAngel; int toAngel; int corePipes[2][2]; if (Pipe_createUniPipe(corePipes[0]) || Pipe_createUniPipe(corePipes[1])) { Except_raise(NULL, -1, "Failed to create pipes [%s]", Errno_getString()); } spawnAngel(&fromAngel, &toAngel); struct PipeInterface* pi; String* addrStr = initAngel(fromAngel, toAngel, corePipes, &pi, eventBase, logger, alloc, rand); Log_info(logger, "Angel initialized."); String* password = String_new("abcd", alloc); struct Admin* admin = Admin_new(&pi->generic, alloc, logger, eventBase, password); // Now setup the client. struct sockaddr_storage addr; int addrLen = sizeof(struct sockaddr_storage); Bits_memset(&addr, 0, sizeof(struct sockaddr_storage)); Assert_true(!evutil_parse_sockaddr_port(addrStr->bytes, (struct sockaddr*) &addr, &addrLen)); struct AdminClient* client = AdminClient_new((uint8_t*) &addr, addrLen, password, eventBase, logger, alloc); Assert_always(client); return alloc->clone(sizeof(struct AdminTestFramework), alloc, &(struct AdminTestFramework) { .admin = admin, .client = client, .alloc = alloc, .eventBase = eventBase, .logger = logger, .addr = alloc->clone(addrLen, alloc, &addr), .addrLen = addrLen, .angelInterface = &pi->generic }); }
int main(int argc, char** argv) { #ifdef Log_KEYS fprintf(stderr, "Log_LEVEL = KEYS, EXPECT TO SEE PRIVATE KEYS IN YOUR LOGS!\n"); #endif Assert_true(argc > 0); struct Except* eh = NULL; // Allow it to allocate 4MB struct Allocator* allocator = MallocAllocator_new(1<<22); struct Random* rand = Random_new(allocator, NULL, eh); struct EventBase* eventBase = EventBase_new(allocator); if (argc == 2) { // one argument if (strcmp(argv[1], "--help") == 0) { return usage(argv[0]); } else if (strcmp(argv[1], "--genconf") == 0) { return genconf(rand); } else if (strcmp(argv[1], "--pidfile") == 0) { // Performed after reading the configuration } else if (strcmp(argv[1], "--reconf") == 0) { // Performed after reading the configuration } else if (strcmp(argv[1], "--bench") == 0) { return benchmark(); } else if (strcmp(argv[1], "--version") == 0) { //printf("Version ID: %s\n", RouterModule_gitVersion()); return 0; } else { fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], argv[1]); fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]); return -1; } } else if (argc > 2) { // more than one argument? fprintf(stderr, "%s: too many arguments\n", argv[0]); fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]); return -1; } if (isatty(STDIN_FILENO)) { // We were started from a terminal // The chances an user wants to type in a configuration // bij hand are pretty slim so we show him the usage return usage(argv[0]); } else { // We assume stdin is a configuration file and that we should // start routing } struct Reader* stdinReader = FileReader_new(stdin, allocator); Dict config; if (JsonBencSerializer_get()->parseDictionary(stdinReader, allocator, &config)) { fprintf(stderr, "Failed to parse configuration.\n"); return -1; } struct Writer* logWriter = FileWriter_new(stdout, allocator); struct Log* logger = WriterLog_new(logWriter, allocator); // --------------------- Setup Pipes to Angel --------------------- // int pipeToAngel[2]; int pipeFromAngel[2]; if (Pipe_createUniPipe(pipeToAngel) || Pipe_createUniPipe(pipeFromAngel)) { Except_raise(eh, -1, "Failed to create pipes to angel [%s]", Errno_getString()); } char pipeToAngelStr[8]; snprintf(pipeToAngelStr, 8, "%d", pipeToAngel[0]); char pipeFromAngelStr[8]; snprintf(pipeFromAngelStr, 8, "%d", pipeFromAngel[1]); char* args[] = { "angel", pipeToAngelStr, pipeFromAngelStr, NULL }; // --------------------- Spawn Angel --------------------- // String* privateKey = Dict_getString(&config, String_CONST("privateKey")); String* corePath = getCorePath(allocator); if (!corePath) { Except_raise(eh, -1, "Can't find a usable cjdns core executable, " "make sure it is in the same directory as cjdroute"); } if (!privateKey) { Except_raise(eh, -1, "Need to specify privateKey."); } Log_info(logger, "Forking angel to background."); Process_spawn(corePath->bytes, args); // --------------------- Get Admin --------------------- // Dict* configAdmin = Dict_getDict(&config, String_CONST("admin")); String* adminPass = Dict_getString(configAdmin, String_CONST("password")); String* adminBind = Dict_getString(configAdmin, String_CONST("bind")); if (!adminPass) { adminPass = String_newBinary(NULL, 32, allocator); Random_base32(rand, (uint8_t*) adminPass->bytes, 32); adminPass->len = strlen(adminPass->bytes); } if (!adminBind) { adminBind = String_new("127.0.0.1:0", allocator); } // --------------------- Get user for angel to setuid() ---------------------- // String* securityUser = NULL; List* securityConf = Dict_getList(&config, String_CONST("security")); for (int i = 0; i < List_size(securityConf); i++) { securityUser = Dict_getString(List_getDict(securityConf, i), String_CONST("setuser")); if (securityUser) { int64_t* ea = Dict_getInt(List_getDict(securityConf, i), String_CONST("exemptAngel")); if (ea && *ea) { securityUser = NULL; } break; } } // --------------------- Pre-Configure Angel ------------------------- // Dict* preConf = Dict_new(allocator); Dict* adminPreConf = Dict_new(allocator); Dict_putDict(preConf, String_CONST("admin"), adminPreConf, allocator); Dict_putString(adminPreConf, String_CONST("core"), corePath, allocator); Dict_putString(preConf, String_CONST("privateKey"), privateKey, allocator); Dict_putString(adminPreConf, String_CONST("bind"), adminBind, allocator); Dict_putString(adminPreConf, String_CONST("pass"), adminPass, allocator); if (securityUser) { Dict_putString(adminPreConf, String_CONST("user"), securityUser, allocator); } #define CONFIG_BUFF_SIZE 1024 uint8_t buff[CONFIG_BUFF_SIZE] = {0}; struct Writer* toAngelWriter = ArrayWriter_new(buff, CONFIG_BUFF_SIZE - 1, allocator); if (StandardBencSerializer_get()->serializeDictionary(toAngelWriter, preConf)) { Except_raise(eh, -1, "Failed to serialize pre-configuration"); } write(pipeToAngel[1], buff, toAngelWriter->bytesWritten(toAngelWriter)); Log_keys(logger, "Sent [%s] to angel process.", buff); // --------------------- Get Response from Angel --------------------- // uint32_t amount = Waiter_getData(buff, CONFIG_BUFF_SIZE, pipeFromAngel[0], eventBase, eh); Dict responseFromAngel; struct Reader* responseFromAngelReader = ArrayReader_new(buff, amount, allocator); if (StandardBencSerializer_get()->parseDictionary(responseFromAngelReader, allocator, &responseFromAngel)) { Except_raise(eh, -1, "Failed to parse pre-configuration response [%s]", buff); } // --------------------- Get Admin Addr/Port/Passwd --------------------- // Dict* responseFromAngelAdmin = Dict_getDict(&responseFromAngel, String_CONST("admin")); adminBind = Dict_getString(responseFromAngelAdmin, String_CONST("bind")); if (!adminBind) { Except_raise(eh, -1, "didn't get address and port back from angel"); } struct Sockaddr_storage adminAddr; if (Sockaddr_parse(adminBind->bytes, &adminAddr)) { Except_raise(eh, -1, "Unable to parse [%s] as an ip address port, eg: 127.0.0.1:11234", adminBind->bytes); } // sanity check Assert_true(EventBase_eventCount(eventBase) == 0); // --------------------- Configuration ------------------------- // Configurator_config(&config, &adminAddr.addr, adminPass, eventBase, logger, allocator); return 0; }
int main(int argc, char** argv) { #ifdef Log_KEYS fprintf(stderr, "Log_LEVEL = KEYS, EXPECT TO SEE PRIVATE KEYS IN YOUR LOGS!\n"); #endif if (argc < 2) { // Fall through. } else if (!CString_strcmp("angel", argv[1])) { return AngelInit_main(argc, argv); } else if (!CString_strcmp("core", argv[1])) { return Core_main(argc, argv); } Assert_ifParanoid(argc > 0); struct Except* eh = NULL; // Allow it to allocate 8MB struct Allocator* allocator = MallocAllocator_new(1<<23); struct Random* rand = Random_new(allocator, NULL, eh); struct EventBase* eventBase = EventBase_new(allocator); if (argc == 2) { // one argument if ((CString_strcmp(argv[1], "--help") == 0) || (CString_strcmp(argv[1], "-h") == 0)) { return usage(allocator, argv[0]); } else if (CString_strcmp(argv[1], "--genconf") == 0) { return genconf(rand); } else if (CString_strcmp(argv[1], "--pidfile") == 0) { // deprecated fprintf(stderr, "'--pidfile' option is deprecated.\n"); return 0; } else if (CString_strcmp(argv[1], "--reconf") == 0) { // Performed after reading the configuration } else if (CString_strcmp(argv[1], "--bench") == 0) { return benchmark(); } else if ((CString_strcmp(argv[1], "--version") == 0) || (CString_strcmp(argv[1], "-v") == 0)) { printf("Cjdns protocol version: %d\n", Version_CURRENT_PROTOCOL); return 0; } else if (CString_strcmp(argv[1], "--cleanconf") == 0) { // Performed after reading configuration } else if (CString_strcmp(argv[1], "--nobg") == 0) { // Performed while reading configuration } else { fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], argv[1]); fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]); return -1; } } else if (argc > 2) { // more than one argument? fprintf(stderr, "%s: too many arguments [%s]\n", argv[0], argv[1]); fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]); // because of '--pidfile $filename'? if (CString_strcmp(argv[1], "--pidfile") == 0) { fprintf(stderr, "\n'--pidfile' option is deprecated.\n"); } return -1; } if (isatty(STDIN_FILENO)) { // We were started from a terminal // The chances an user wants to type in a configuration // bij hand are pretty slim so we show him the usage return usage(allocator, argv[0]); } else { // We assume stdin is a configuration file and that we should // start routing } struct Reader* stdinReader = FileReader_new(stdin, allocator); Dict config; if (JsonBencSerializer_get()->parseDictionary(stdinReader, allocator, &config)) { fprintf(stderr, "Failed to parse configuration.\n"); return -1; } if (argc == 2 && CString_strcmp(argv[1], "--cleanconf") == 0) { struct Writer* stdoutWriter = FileWriter_new(stdout, allocator); JsonBencSerializer_get()->serializeDictionary(stdoutWriter, &config); printf("\n"); return 0; } int forceNoBackground = 0; if (argc == 2 && CString_strcmp(argv[1], "--nobg") == 0) { forceNoBackground = 1; } struct Writer* logWriter = FileWriter_new(stdout, allocator); struct Log* logger = WriterLog_new(logWriter, allocator); // --------------------- Get Admin --------------------- // Dict* configAdmin = Dict_getDict(&config, String_CONST("admin")); String* adminPass = Dict_getString(configAdmin, String_CONST("password")); String* adminBind = Dict_getString(configAdmin, String_CONST("bind")); if (!adminPass) { adminPass = String_newBinary(NULL, 32, allocator); Random_base32(rand, (uint8_t*) adminPass->bytes, 32); adminPass->len = CString_strlen(adminPass->bytes); } if (!adminBind) { Except_throw(eh, "You must specify admin.bind in the cjdroute.conf file."); } // --------------------- Welcome to cjdns ---------------------- // char* archInfo = ArchInfo_describe(ArchInfo_detect(), allocator); char* sysInfo = SysInfo_describe(SysInfo_detect(), allocator); Log_info(logger, "Cjdns %s %s", archInfo, sysInfo); // --------------------- Check for running instance --------------------- // Log_info(logger, "Checking for running instance..."); checkRunningInstance(allocator, eventBase, adminBind, adminPass, logger, eh); // --------------------- Setup Pipes to Angel --------------------- // char angelPipeName[64] = "client-angel-"; Random_base32(rand, (uint8_t*)angelPipeName+13, 31); Assert_ifParanoid(EventBase_eventCount(eventBase) == 0); struct Pipe* angelPipe = Pipe_named(angelPipeName, eventBase, eh, allocator); Assert_ifParanoid(EventBase_eventCount(eventBase) == 2); angelPipe->logger = logger; char* args[] = { "angel", angelPipeName, NULL }; // --------------------- Spawn Angel --------------------- // String* privateKey = Dict_getString(&config, String_CONST("privateKey")); char* corePath = Process_getPath(allocator); if (!corePath) { Except_throw(eh, "Can't find a usable cjdns core executable, " "make sure it is in the same directory as cjdroute"); } if (!privateKey) { Except_throw(eh, "Need to specify privateKey."); } Log_info(logger, "Forking angel to background."); Process_spawn(corePath, args, eventBase, allocator); // --------------------- Get user for angel to setuid() ---------------------- // String* securityUser = NULL; List* securityConf = Dict_getList(&config, String_CONST("security")); for (int i = 0; securityConf && i < List_size(securityConf); i++) { securityUser = Dict_getString(List_getDict(securityConf, i), String_CONST("setuser")); if (securityUser) { int64_t* ea = Dict_getInt(List_getDict(securityConf, i), String_CONST("exemptAngel")); if (ea && *ea) { securityUser = NULL; } break; } } // --------------------- Pre-Configure Angel ------------------------- // Dict* preConf = Dict_new(allocator); Dict* adminPreConf = Dict_new(allocator); Dict_putDict(preConf, String_CONST("admin"), adminPreConf, allocator); Dict_putString(adminPreConf, String_CONST("core"), String_new(corePath, allocator), allocator); Dict_putString(preConf, String_CONST("privateKey"), privateKey, allocator); Dict_putString(adminPreConf, String_CONST("bind"), adminBind, allocator); Dict_putString(adminPreConf, String_CONST("pass"), adminPass, allocator); if (securityUser) { Dict_putString(adminPreConf, String_CONST("user"), securityUser, allocator); } Dict* logging = Dict_getDict(&config, String_CONST("logging")); if (logging) { Dict_putDict(preConf, String_CONST("logging"), logging, allocator); } struct Message* toAngelMsg = Message_new(0, 1024, allocator); BencMessageWriter_write(preConf, toAngelMsg, eh); Interface_sendMessage(&angelPipe->iface, toAngelMsg); Log_debug(logger, "Sent [%d] bytes to angel process", toAngelMsg->length); // --------------------- Get Response from Angel --------------------- // struct Message* fromAngelMsg = InterfaceWaiter_waitForData(&angelPipe->iface, eventBase, allocator, eh); Dict* responseFromAngel = BencMessageReader_read(fromAngelMsg, allocator, eh); // --------------------- Get Admin Addr/Port/Passwd --------------------- // Dict* responseFromAngelAdmin = Dict_getDict(responseFromAngel, String_CONST("admin")); adminBind = Dict_getString(responseFromAngelAdmin, String_CONST("bind")); if (!adminBind) { Except_throw(eh, "didn't get address and port back from angel"); } struct Sockaddr_storage adminAddr; if (Sockaddr_parse(adminBind->bytes, &adminAddr)) { Except_throw(eh, "Unable to parse [%s] as an ip address port, eg: 127.0.0.1:11234", adminBind->bytes); } // sanity check, Pipe_named() creates 2 events, see above. Assert_ifParanoid(EventBase_eventCount(eventBase) == 2); // --------------------- Configuration ------------------------- // Configurator_config(&config, &adminAddr.addr, adminPass, eventBase, logger, allocator); // --------------------- noBackground ------------------------ // int64_t* noBackground = Dict_getInt(&config, String_CONST("noBackground")); if (forceNoBackground || (noBackground && *noBackground)) { EventBase_beginLoop(eventBase); } //Allocator_free(allocator); return 0; }
int main() { struct Allocator* mainAlloc = MallocAllocator_new(1<<20); struct Log* log = FileWriterLog_new(stdout, mainAlloc); struct Random* rand = Random_new(mainAlloc, log, NULL); struct Context* ctx = Allocator_malloc(mainAlloc, sizeof(struct Context)); Identity_set(ctx); struct Interface iface = { .sendMessage = NULL }; struct Interface* fi = FramingInterface_new(4096, &iface, mainAlloc); fi->receiveMessage = messageOut; fi->receiverContext = ctx; for (int i = 0; i < CYCLES; i++) { struct Allocator* alloc = Allocator_child(mainAlloc); // max frame size must be at least 5 so that at least 1 byte of data is sent. int maxFrameSize = ( Random_uint32(rand) % (MAX_FRAME_SZ - 1) ) + 1; int maxMessageSize = ( Random_uint32(rand) % (MAX_MSG_SZ - MIN_MSG_SZ) ) + MIN_MSG_SZ; Log_debug(log, "maxFrameSize[%d] maxMessageSize[%d]", maxFrameSize, maxMessageSize); ctx->alloc = alloc; ctx->messages = NULL; ctx->messageCount = 0; ctx->currentMessage = 0; // Create one huge message, then create lots of little frames inside of it // then split it up in random places and send the sections to the framing // interface. struct Message* msg = Message_new(WORK_BUFF_SZ, 0, alloc); Assert_true(WORK_BUFF_SZ == msg->length); Random_bytes(rand, msg->bytes, msg->length); Message_shift(msg, -WORK_BUFF_SZ, NULL); for (;;) { int len = Random_uint32(rand) % maxFrameSize; if (!len) { len++; } if (msg->padding < len + 4) { break; } Message_shift(msg, len, NULL); ctx->messageCount++; ctx->messages = Allocator_realloc(alloc, ctx->messages, ctx->messageCount * sizeof(char*)); struct Message* om = ctx->messages[ctx->messageCount-1] = Message_new(len, 0, alloc); Bits_memcpy(om->bytes, msg->bytes, len); Message_push32(msg, len, NULL); } do { int nextMessageSize = Random_uint32(rand) % maxMessageSize; if (!nextMessageSize) { nextMessageSize++; } if (nextMessageSize > msg->length) { nextMessageSize = msg->length; } struct Allocator* msgAlloc = Allocator_child(alloc); struct Message* m = Message_new(nextMessageSize, 0, msgAlloc); Message_pop(msg, m->bytes, nextMessageSize, NULL); Interface_receiveMessage(&iface, m); Allocator_free(msgAlloc); } while (msg->length); Assert_true(ctx->messageCount == ctx->currentMessage); Allocator_free(alloc); } return 0; }
int main() { AddressCalc_addressForPublicKey(nodeCjdnsIp6, fakePubKey); struct Allocator* alloc = MallocAllocator_new(1<<20); struct Log* logger = FileWriterLog_new(stdout, alloc); struct Random* rand = Random_new(alloc, logger, NULL); struct EventBase* eb = EventBase_new(alloc); struct IpTunnel* ipTun = IpTunnel_new(logger, eb, alloc, rand); struct Sockaddr_storage ip6ToGive; Sockaddr_parse("fd01:0101:0101:0101:0101:0101:0101:0101", &ip6ToGive); IpTunnel_allowConnection(fakePubKey, &ip6ToGive.addr, 0, NULL, 0, ipTun); struct Message* message; Message_STACK(message, 64, 512); message->alloc = alloc; const char* requestForAddresses = "d" "1:q" "21:IpTunnel_getAddresses" "4:txid" "4:abcd" "e"; CString_strcpy((char*)message->bytes, requestForAddresses); message->length = CString_strlen(requestForAddresses); Message_shift(message, Headers_UDPHeader_SIZE, NULL); struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message->bytes; uh->srcPort_be = 0; uh->destPort_be = 0; uh->length_be = Endian_hostToBigEndian16(message->length - Headers_UDPHeader_SIZE); uint16_t* checksum = &uh->checksum_be; *checksum = 0; uint32_t length = message->length; Message_shift(message, Headers_IP6Header_SIZE, NULL); struct Headers_IP6Header* ip = (struct Headers_IP6Header*) message->bytes; ip->versionClassAndFlowLabel = 0; ip->flowLabelLow_be = 0; ip->payloadLength_be = Endian_hostToBigEndian16(length); ip->nextHeader = 17; ip->hopLimit = 255; Bits_memset(ip->sourceAddr, 0, 32); Headers_setIpVersion(ip); Message_shift(message, RouteHeader_SIZE + DataHeader_SIZE, NULL); struct RouteHeader* rh = (struct RouteHeader*) message->bytes; struct DataHeader* dh = (struct DataHeader*) &rh[1]; Bits_memset(rh, 0, RouteHeader_SIZE + DataHeader_SIZE); Bits_memcpy(rh->ip6, nodeCjdnsIp6, 16); Bits_memcpy(rh->publicKey, fakePubKey, 32); DataHeader_setContentType(dh, ContentType_IPTUN); *checksum = Checksum_udpIp6(ip->sourceAddr, (uint8_t*) uh, length); int origCap = message->capacity; int origLen = message->length; struct Iface nodeIface = { .send = responseWithIpCallback }; Iface_plumb(&nodeIface, &ipTun->nodeInterface); struct Iface tunIface = { .send = messageToTun }; Iface_plumb(&tunIface, &ipTun->tunInterface); Iface_send(&nodeIface, message); Assert_true(called == 2); called = 0; // This is a hack, reusing the message will cause breakage if IpTunnel is refactored. Message_reset(message); Message_shift(message, origCap, NULL); message->length = origLen; Bits_memcpy(ip->sourceAddr, fakeIp6ToGive, 16); // This can't be zero. Bits_memset(ip->destinationAddr, 1, 16); Iface_send(&nodeIface, message); Assert_true(called == 1); Allocator_free(alloc); return 0; }
struct TestFramework* TestFramework_setUp(char* privateKey, struct Allocator* allocator, struct Log* logger) { if (!logger) { struct Writer* logwriter = FileWriter_new(stdout, allocator); logger = WriterLog_new(logwriter, allocator); } struct Random* rand = Random_new(allocator, logger, NULL); struct EventBase* base = EventBase_new(allocator); uint64_t pks[4]; if (!privateKey) { Random_longs(rand, pks, 4); privateKey = (char*)pks; } uint8_t* publicKey = Allocator_malloc(allocator, 32); crypto_scalarmult_curve25519_base(publicKey, (uint8_t*)privateKey); struct Address* myAddress = Allocator_calloc(allocator, sizeof(struct Address), 1); Bits_memcpyConst(myAddress->key, publicKey, 32); AddressCalc_addressForPublicKey(myAddress->ip6.bytes, publicKey); struct SwitchCore* switchCore = SwitchCore_new(logger, allocator); struct CryptoAuth* ca = CryptoAuth_new(allocator, (uint8_t*)privateKey, base, logger, rand); struct DHTModuleRegistry* registry = DHTModuleRegistry_new(allocator); ReplyModule_register(registry, allocator); struct NodeStore* nodeStore = NodeStore_new(myAddress, 128, allocator, logger, rand); struct RouterModule* routerModule = RouterModule_register(registry, allocator, publicKey, base, logger, rand, nodeStore); struct SearchRunner* searchRunner = SearchRunner_new(nodeStore, logger, base, routerModule, myAddress->ip6.bytes, allocator); SerializationModule_register(registry, logger, allocator); struct IpTunnel* ipTun = IpTunnel_new(logger, base, allocator, rand, NULL); struct Ducttape* dt = Ducttape_register((uint8_t*)privateKey, registry, routerModule, searchRunner, switchCore, base, allocator, logger, ipTun, rand); struct SwitchPinger* sp = SwitchPinger_new(&dt->switchPingerIf, base, rand, logger, allocator); // Interfaces. struct InterfaceController* ifController = DefaultInterfaceController_new(ca, switchCore, routerModule, logger, base, sp, rand, allocator); struct TestFramework* tf = Allocator_clone(allocator, (&(struct TestFramework) { .alloc = allocator, .rand = rand, .eventBase = base, .logger = logger, .switchCore = switchCore, .ducttape = dt, .cryptoAuth = ca, .router = routerModule, .switchPinger = sp, .ifController = ifController, .publicKey = publicKey, .ip = myAddress->ip6.bytes }));
int main() { AddressCalc_addressForPublicKey(nodeCjdnsIp6, fakePubKey); struct Allocator* alloc = MallocAllocator_new(1<<20); struct Writer* w = FileWriter_new(stdout, alloc); struct Log* logger = WriterLog_new(w, alloc); struct Random* rand = Random_new(alloc, logger, NULL); struct EventBase* eb = EventBase_new(alloc); struct IpTunnel* ipTun = IpTunnel_new(logger, eb, alloc, rand, NULL); struct Sockaddr_storage ip6ToGive; Sockaddr_parse("fd01:0101:0101:0101:0101:0101:0101:0101", &ip6ToGive); IpTunnel_allowConnection(fakePubKey, &ip6ToGive.addr, NULL, ipTun); struct Message* message; Message_STACK(message, 64, 512); message->alloc = alloc; const char* requestForAddresses = "d" "1:q" "21:IpTunnel_getAddresses" "4:txid" "4:abcd" "e"; CString_strcpy((char*)message->bytes, requestForAddresses); message->length = CString_strlen(requestForAddresses); Message_shift(message, Headers_UDPHeader_SIZE, NULL); struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message->bytes; uh->srcPort_be = 0; uh->destPort_be = 0; uh->length_be = Endian_hostToBigEndian16(message->length - Headers_UDPHeader_SIZE); uint16_t* checksum = &uh->checksum_be; *checksum = 0; uint32_t length = message->length; Message_shift(message, Headers_IP6Header_SIZE, NULL); struct Headers_IP6Header* ip = (struct Headers_IP6Header*) message->bytes; ip->versionClassAndFlowLabel = 0; ip->flowLabelLow_be = 0; ip->payloadLength_be = Endian_hostToBigEndian16(length); ip->nextHeader = 17; ip->hopLimit = 255; Bits_memset(ip->sourceAddr, 0, 32); Headers_setIpVersion(ip); Message_shift(message, IpTunnel_PacketInfoHeader_SIZE, NULL); struct IpTunnel_PacketInfoHeader* pi = (struct IpTunnel_PacketInfoHeader*) message->bytes; Bits_memcpyConst(pi->nodeIp6Addr, nodeCjdnsIp6, 16); Bits_memcpyConst(pi->nodeKey, fakePubKey, 32); *checksum = Checksum_udpIp6(ip->sourceAddr, (uint8_t*) uh, length); ipTun->nodeInterface.receiveMessage = responseWithIpCallback; ipTun->nodeInterface.sendMessage(message, &ipTun->nodeInterface); Assert_true(called); called = 0; // Now create a message for someone else. Message_shift(message, Headers_UDPHeader_SIZE + Headers_IP6Header_SIZE + IpTunnel_PacketInfoHeader_SIZE, NULL); Bits_memcpyConst(ip->sourceAddr, fakeIp6ToGive, 16); // This can't be zero. Bits_memset(ip->destinationAddr, 1, 16); ipTun->tunInterface.receiveMessage = messageToTun; ipTun->nodeInterface.sendMessage(message, &ipTun->nodeInterface); Assert_true(called); Allocator_free(alloc); return 0; }
int main(int argc, char** argv) { if (argc > 1 && !strcmp("--genconf", argv[argc-1])) { genconf(); return 0; } struct Allocator* alloc = MallocAllocator_new(1<<22); struct EventBase* base = EventBase_new(alloc); struct Writer* logWriter = FileWriter_new(stdout, alloc); struct Log* logger = WriterLog_new(logWriter, alloc); struct Random* rand = Random_new(alloc, logger, NULL); struct Reader* stdinReader = FileReader_new(stdin, alloc); Dict config; if (JsonBencSerializer_get()->parseDictionary(stdinReader, alloc, &config)) { Log_critical(logger, "Failed to parse configuration"); return -1; } Dict* dns = Dict_getDict(&config, String_CONST("dns")); if (!dns) { Log_critical(logger, "No DNS in configuration"); return -1; } struct Sockaddr_storage addr; Assert_true(!Sockaddr_parse("::", &addr)); struct AddrInterface* ifaceB = UDPAddrInterface_new(base, &addr.addr, alloc, NULL, logger); struct RainflyClient* client = RainflyClient_new(ifaceB, base, rand, logger); String* bind = Dict_getString(dns, String_CONST("bind")); Assert_true(!Sockaddr_parse(bind ? bind->bytes : "[::]:5353", &addr)); struct AddrInterface* iface = UDPAddrInterface_new(base, &addr.addr, alloc, NULL, logger); struct DNSServer* dnsServer = DNSServer_new(iface, logger, client); List* auth = Dict_getList(dns, String_CONST("authorities")); for (int i = 0; i < (int)List_size(auth); i++) { String* str = List_getString(auth, i); if (!str) { Log_warn(logger, "Element [%d] in [dns.authorities] list of wrong type", i); continue; } uint8_t key[32] = {0}; if (str->len < 52 || Base32_decode(key, 32, str->bytes, 52) != 32) { Log_warn(logger, "Failed to parse key [%s]", str->bytes); continue; } if (RainflyClient_addKey(client, key)) { Log_warn(logger, "Failed to add key to RainflyClient [%s]", str->bytes); } } List* servers = Dict_getList(dns, String_CONST("servers")); for (int i = 0; i < (int)List_size(servers); i++) { String* str = List_getString(servers, i); if (!str) { Log_warn(logger, "Element [%d] in [dns.servers] list of wrong type", i); continue; } struct Sockaddr_storage node; if (Sockaddr_parse(str->bytes, &node)) { Log_warn(logger, "Failed to parse server name [%s]", str->bytes); continue; } if (RainflyClient_addServer(client, &node.addr)) { Log_warn(logger, "Failed to add server to RainflyClient [%s]", str->bytes); } } List* legacy = Dict_getList(dns, String_CONST("legacy")); for (int i = 0; i < (int)List_size(legacy); i++) { String* str = List_getString(legacy, i); if (!str) { Log_warn(logger, "Element [%d] in [dns.legacy] list of wrong type", i); continue; } struct Sockaddr_storage node; if (Sockaddr_parse(str->bytes, &node)) { Log_warn(logger, "Failed to parse legacy server name [%s]", str->bytes); continue; } if (DNSServer_addServer(dnsServer, &node.addr)) { Log_warn(logger, "Failed to add server to DNSServer [%s]", str->bytes); } } EventBase_beginLoop(base); }
/* * This process is started with 2 parameters, they must all be numeric in base 10. * toAngel the pipe which is used to send data back to the angel process. * fromAngel the pipe which is used to read incoming data from the angel. * * Upon initialization, this process will wait for an initial configuration to be sent to * it and then it will send an initial response. */ int Core_main(int argc, char** argv) { struct Except* eh = NULL; int toAngel; int fromAngel; if (argc != 4 || !(toAngel = atoi(argv[2])) || !(fromAngel = atoi(argv[3]))) { Except_raise(eh, -1, "This is internal to cjdns and shouldn't started manually."); } struct Allocator* alloc = MallocAllocator_new(ALLOCATOR_FAILSAFE); struct EventBase* eventBase = EventBase_new(alloc); struct Random* rand = Random_new(alloc, eh); // -------------------- Setup the Pre-Logger ---------------------- // struct Writer* logWriter = FileWriter_new(stdout, alloc); struct Log* preLogger = WriterLog_new(logWriter, alloc); struct IndirectLog* indirectLogger = IndirectLog_new(alloc); indirectLogger->wrappedLog = preLogger; struct Log* logger = &indirectLogger->pub; // The first read inside of getInitialConfig() will begin it waiting. struct PipeInterface* pi = PipeInterface_new(fromAngel, toAngel, eventBase, logger, alloc, rand); Dict* config = getInitialConfig(&pi->generic, eventBase, alloc, eh); String* privateKeyHex = Dict_getString(config, String_CONST("privateKey")); Dict* adminConf = Dict_getDict(config, String_CONST("admin")); String* pass = Dict_getString(adminConf, String_CONST("pass")); if (!pass || !privateKeyHex) { Except_raise(eh, -1, "Expected 'pass' and 'privateKey' in configuration."); } Log_keys(logger, "Starting core with admin password [%s]", pass->bytes); uint8_t privateKey[32]; if (privateKeyHex->len != 64 || Hex_decode(privateKey, 32, (uint8_t*) privateKeyHex->bytes, 64) != 32) { Except_raise(eh, -1, "privateKey must be 64 bytes of hex."); } struct Admin* admin = Admin_new(&pi->generic, alloc, logger, eventBase, pass); Dict adminResponse = Dict_CONST(String_CONST("error"), String_OBJ(String_CONST("none")), NULL); Admin_sendMessageToAngel(&adminResponse, admin); // --------------------- Setup the Logger --------------------- // // the prelogger will nolonger be used. struct Log* adminLogger = AdminLog_registerNew(admin, alloc, rand); indirectLogger->wrappedLog = adminLogger; logger = adminLogger; // CryptoAuth struct Address addr; parsePrivateKey(privateKey, &addr, eh); struct CryptoAuth* cryptoAuth = CryptoAuth_new(alloc, privateKey, eventBase, logger, rand); struct SwitchCore* switchCore = SwitchCore_new(logger, alloc); struct DHTModuleRegistry* registry = DHTModuleRegistry_new(alloc); ReplyModule_register(registry, alloc); // Router struct RouterModule* router = RouterModule_register(registry, alloc, addr.key, eventBase, logger, admin, rand); SerializationModule_register(registry, logger, alloc); struct IpTunnel* ipTun = IpTunnel_new(logger, eventBase, alloc, rand); struct Ducttape* dt = Ducttape_register(privateKey, registry, router, switchCore, eventBase, alloc, logger, admin, ipTun, rand); struct SwitchPinger* sp = SwitchPinger_new(&dt->switchPingerIf, eventBase, logger, alloc); // Interfaces. struct InterfaceController* ifController = DefaultInterfaceController_new(cryptoAuth, switchCore, router, logger, eventBase, sp, alloc); // ------------------- Register RPC functions ----------------------- // SwitchPinger_admin_register(sp, admin, alloc); UDPInterface_admin_register(eventBase, alloc, logger, admin, ifController); #ifdef HAS_ETH_INTERFACE ETHInterface_admin_register(eventBase, alloc, logger, admin, ifController); #endif RouterModule_admin_register(router, admin, alloc); AuthorizedPasswords_init(admin, cryptoAuth, alloc); Admin_registerFunction("ping", adminPing, admin, false, NULL, admin); Admin_registerFunction("Core_exit", adminExit, logger, true, NULL, admin); Core_admin_register(addr.ip6.bytes, dt, logger, alloc, admin, eventBase); Security_admin_register(alloc, logger, admin); IpTunnel_admin_register(ipTun, admin, alloc); struct MemoryContext* mc = alloc->clone(sizeof(struct MemoryContext), alloc, &(struct MemoryContext) { .allocator = alloc, .admin = admin });
static void sendConfToCore(struct Interface* toCoreInterface, struct Allocator* alloc, Dict* config, struct Except* eh, struct Log* logger) { #define CONFIG_BUFF_SIZE 1024 uint8_t buff[CONFIG_BUFF_SIZE + 32] = {0}; uint8_t* start = buff + 32; struct Writer* writer = ArrayWriter_new(start, CONFIG_BUFF_SIZE - 33, alloc); if (StandardBencSerializer_get()->serializeDictionary(writer, config)) { Except_raise(eh, -1, "Failed to serialize pre-configuration for core."); } struct Message m = { .bytes = start, .length = writer->bytesWritten(writer), .padding = 32 }; Log_keys(logger, "Sent [%d] bytes to core [%s].", m.length, m.bytes); toCoreInterface->sendMessage(&m, toCoreInterface); } static void setUser(char* user, struct Log* logger, struct Except* eh) { struct Jmp jmp; Jmp_try(jmp) { Security_setUser(user, logger, &jmp.handler); } Jmp_catch { if (jmp.code == Security_setUser_PERMISSION) { return; } Except_raise(eh, jmp.code, "%s", jmp.message); } } /** * Input: * { * "admin": { * "core": "/path/to/core/binary", * "bind": "127.0.0.1:12345", * "pass": "******", * "user": "******" * } * } * for example: * d5:admind4:core30:./build/admin/angel/cjdns-core4:bind15:127.0.0.1:123454:pass4:abcdee * * Pre-existing core mode: * { * "admin": { * "core": { * "fromCore": 12, * "toCore": 14 * }, * "bind": "127.0.0.1:12345", * "pass": "******", * "user": "******" * } * } * * If "core" is a dictionary, the angel will behave as though the core is already spawned and * it will read from the core on the file descriptor given by "fromCore" and write to the file * given by "toCore". * * "user" is optional, if set the angel will setuid() that user's uid. */ int AngelInit_main(int argc, char** argv) { struct Except* eh = NULL; int inFromClientNo; int outToClientNo; if (argc < 3 || (inFromClientNo = atoi(argv[2])) == 0) { inFromClientNo = STDIN_FILENO; } if (argc < 4 || (outToClientNo = atoi(argv[3])) == 0) { outToClientNo = STDOUT_FILENO; } struct Allocator* alloc = MallocAllocator_new(1<<21); struct Writer* logWriter = FileWriter_new(stdout, alloc); struct Log* logger = WriterLog_new(logWriter, alloc); struct Random* rand = Random_new(alloc, logger, eh); alloc = CanaryAllocator_new(alloc, rand); struct Allocator* tempAlloc = Allocator_child(alloc); struct EventBase* eventBase = EventBase_new(alloc); Log_debug(logger, "Initializing angel with input [%d] and output [%d]", inFromClientNo, outToClientNo); Log_debug(logger, "Getting pre-configuration from client"); #define CONFIG_BUFF_SIZE 1024 uint8_t buff[CONFIG_BUFF_SIZE] = {0}; Waiter_getData(buff, CONFIG_BUFF_SIZE, inFromClientNo, eventBase, eh); Log_debug(logger, "Finished getting pre-configuration from client"); struct Reader* reader = ArrayReader_new(buff, CONFIG_BUFF_SIZE, tempAlloc); Dict config; if (StandardBencSerializer_get()->parseDictionary(reader, tempAlloc, &config)) { Except_raise(eh, -1, "Failed to parse configuration."); } Dict* admin = Dict_getDict(&config, String_CONST("admin")); String* core = Dict_getString(admin, String_CONST("core")); String* bind = Dict_getString(admin, String_CONST("bind")); String* pass = Dict_getString(admin, String_CONST("pass")); String* user = Dict_getString(admin, String_CONST("user")); int toCore = -1; int fromCore = -1; if (!core) { Dict* coreDict = Dict_getDict(admin, String_CONST("core")); int64_t* toCorePtr = Dict_getInt(coreDict, String_CONST("toCore")); int64_t* fromCorePtr = Dict_getInt(coreDict, String_CONST("fromCore")); toCore = (toCorePtr) ? *toCorePtr : -1; fromCore = (fromCorePtr) ? *fromCorePtr : -1; } if (!bind || !pass || (!core && (toCore == -1 || fromCore == -1))) { Except_raise(eh, -1, "missing configuration params in preconfig. [%s]", buff); } if (core) { Log_info(logger, "Initializing core [%s]", core->bytes); initCore(core->bytes, &toCore, &fromCore, eh); } Log_debug(logger, "Sending pre-configuration to core."); struct PipeInterface* pif = PipeInterface_new(fromCore, toCore, eventBase, logger, alloc, rand); struct Interface* coreIface = &pif->generic; PipeInterface_waitUntilReady(pif); sendConfToCore(coreIface, tempAlloc, &config, eh, logger); struct Message* coreResponse = InterfaceWaiter_waitForData(coreIface, eventBase, tempAlloc, eh); if (write(outToClientNo, coreResponse->bytes, coreResponse->length)) { // Ignore the result of write() without the compiler complaining. } #ifdef Log_KEYS uint8_t lastChar = coreResponse->bytes[coreResponse->length-1]; coreResponse->bytes[coreResponse->length-1] = 0; Log_keys(logger, "Sent [%s%c] to client.", coreResponse->bytes, lastChar); coreResponse->bytes[coreResponse->length-1] = lastChar; #endif if (user) { setUser(user->bytes, logger, eh); } Allocator_free(tempAlloc); Angel_start(coreIface, eventBase, logger, alloc); return 0; }