void NetDev_addAddress(const char* ifName, struct Sockaddr* sa, int prefixLen, struct Log* logger, struct Except* eh) { int addrFam = Sockaddr_getFamily(sa); struct Allocator* alloc; BufferAllocator_STACK(alloc, 4096); char* printedAddr = Sockaddr_print(sa, alloc); if (addrFam != Sockaddr_AF_INET && addrFam != Sockaddr_AF_INET6) { Except_throw(eh, "Unknown address type for address [%s]", printedAddr); } int prefixMax = (addrFam == Sockaddr_AF_INET6) ? 128 : 32; if (prefixLen < 0 || prefixLen > prefixMax) { Except_throw(eh, "prefixLen [%d] must be greater than 0 and less than %d", prefixLen, prefixMax); } void* addr; int len = Sockaddr_getAddress(sa, &addr); if (len < 0 || len != prefixMax / 8) { Except_throw(eh, "Invalid sockaddr [%s]", printedAddr); } Log_info(logger, "Setting IP address [%s/%d] on interface [%s]", printedAddr, prefixLen, ifName); NetPlatform_addAddress(ifName, addr, prefixLen, addrFam, logger, eh); }
struct Message* InterfaceWaiter_waitForData(struct Interface* iface, struct event_base* eventBase, struct Allocator* alloc, struct Except* eh) { struct Context ctx = { .eventBase = eventBase, .exceptionHandler = eh, .alloc = alloc }; struct Allocator* tempAlloc; BufferAllocator_STACK(tempAlloc, 512); iface->receiverContext = &ctx; iface->receiveMessage = receiveMessage; ctx.timeout = Timeout_setTimeout(timeout, &ctx, 2000, eventBase, tempAlloc); event_base_dispatch(eventBase); iface->receiveMessage = NULL; Assert_true(ctx.message); return ctx.message; }
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; }
struct Message* InterfaceWaiter_waitForData(struct Interface* iface, struct EventBase* eventBase, struct Allocator* alloc, struct Except* eh) { struct Context ctx = { .eventBase = eventBase, .alloc = alloc }; struct Allocator* tempAlloc; BufferAllocator_STACK(tempAlloc, 512); iface->receiverContext = &ctx; iface->receiveMessage = receiveMessage; ctx.timeout = Timeout_setTimeout(timeout, &ctx, 2000, eventBase, tempAlloc); EventBase_beginLoop(eventBase); iface->receiveMessage = NULL; Allocator_free(tempAlloc); if (ctx.timedOut) { Except_raise(eh, InterfaceWaiter_waitForData_TIMEOUT, "InterfaceWaiter Timed out waiting for data."); } Assert_true(ctx.message); return ctx.message; }
static void listConnections(Dict* args, void* vcontext, String* txid) { struct Context* context = vcontext; struct Allocator* alloc; BufferAllocator_STACK(alloc, 1024); List* l = NULL; for (int i = 0; i < (int)context->ipTun->connectionList.count; i++) { l = List_addInt(l, context->ipTun->connectionList.connections[i].number, alloc); } Dict resp = Dict_CONST( String_CONST("connections"), List_OBJ(l), Dict_CONST( String_CONST("error"), String_OBJ(String_CONST("none")), NULL )); Admin_sendMessage(&resp, txid, context->admin); }
void NetDev_addAddress(const char* ifName, struct Sockaddr* sa, struct Log* logger, struct Except* eh) { int addrFam; char* printedAddr; void* addr; struct Allocator* alloc; BufferAllocator_STACK(alloc, 4096); checkAddressAndPrefix(sa, &addrFam, &printedAddr, &addr, alloc, eh); Log_info(logger, "Setting IP address [%s/%d] on interface [%s]", printedAddr, sa->prefix, ifName); NetPlatform_addAddress(ifName, addr, sa->prefix, addrFam, logger, alloc, eh); }
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); } }
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); }
static void showConn(struct IpTunnel_Connection* conn, String* txid, struct Admin* admin) { struct Allocator* alloc; BufferAllocator_STACK(alloc, 1024); Dict* d = Dict_new(alloc); char ip6[40]; if (!Bits_isZero(conn->connectionIp6, 16)) { Assert_always(evutil_inet_ntop(AF_INET6, conn->connectionIp6, ip6, 40)); Dict_putString(d, String_CONST("ip6Address"), String_CONST(ip6), alloc); } char ip4[16]; if (!Bits_isZero(conn->connectionIp4, 4)) { Assert_always(evutil_inet_ntop(AF_INET, conn->connectionIp4, ip4, 16)); Dict_putString(d, String_CONST("ip4Address"), String_CONST(ip4), alloc); } Dict_putString(d, String_CONST("key"), Key_stringify(conn->header.nodeKey, alloc), alloc); Dict_putInt(d, String_CONST("outgoing"), conn->isOutgoing, alloc); Admin_sendMessage(d, txid, admin); }
/** @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 }); }