static uint8_t sendMessage(struct Message* message, struct Interface* iface) { struct UDPAddrInterface_pvt* context = Identity_cast((struct UDPAddrInterface_pvt*) iface->senderContext); struct Sockaddr_storage addrStore; Message_pop(message, &addrStore, context->pub.addr->addrLen); Assert_true(addrStore.addr.addrLen == context->pub.addr->addrLen); if (Socket_sendto(context->socket, message->bytes, message->length, 0, &addrStore.addr) < 0) { switch (Errno_get()) { case Errno_EMSGSIZE: return Error_OVERSIZE_MESSAGE; case Errno_ENOBUFS: case Errno_EAGAIN: return Error_LINK_LIMIT_EXCEEDED; default:; Log_info(context->logger, "Got error sending to socket [%s]", Errno_getString()); } } return 0; }
void TUNConfigurator_setMTU(const char* interfaceName, uint32_t mtu, struct Log* logger, struct Except* eh) { int s = socket(AF_INET6, SOCK_DGRAM, 0); if (s < 0) { Except_raise(eh, TUNConfigurator_ERROR_GETTING_ADMIN_SOCKET, "socket() failed [%s]", Errno_getString()); } struct ifreq ifRequest; strncpy(ifRequest.ifr_name, interfaceName, IFNAMSIZ); ifRequest.ifr_mtu = mtu; Log_info(logger, "Setting MTU for device [%s] to [%u] bytes.", interfaceName, mtu); if (ioctl(s, SIOCSIFMTU, &ifRequest) < 0) { enum Errno err = Errno_get(); close(s); Except_raise(eh, TUNConfigurator_setMTU_INTERNAL, "ioctl(SIOCSIFMTU) failed [%s]", Errno_strerror(err)); } }
static void newInterface2(struct Context* ctx, struct Sockaddr* addr, String* txid) { struct Allocator* const alloc = Allocator_child(ctx->allocator); struct UDPInterface* udpIf = NULL; struct Jmp jmp; Jmp_try(jmp) { udpIf = UDPInterface_new(ctx->eventBase, addr, alloc, &jmp.handler, ctx->logger, ctx->ic); } Jmp_catch { String* errStr = String_CONST(jmp.message); Dict out = Dict_CONST(String_CONST("error"), String_OBJ(errStr), NULL); if (jmp.code == UDPInterface_new_SOCKET_FAILED || jmp.code == UDPInterface_new_BIND_FAILED) { char* err = Errno_getString(); Dict out2 = Dict_CONST(String_CONST("cause"), String_OBJ(String_CONST(err)), out); Admin_sendMessage(&out2, txid, ctx->admin); } else { Admin_sendMessage(&out, txid, ctx->admin); } Allocator_free(alloc); } // sizeof(struct UDPInterface*) the size of a pointer. ctx->ifaces = Allocator_realloc(ctx->allocator, ctx->ifaces, sizeof(struct UDPInterface*) * (ctx->ifCount + 1)); ctx->ifaces[ctx->ifCount] = udpIf; Dict out = Dict_CONST( String_CONST("error"), String_OBJ(String_CONST("none")), Dict_CONST( String_CONST("interfaceNumber"), Int_OBJ(ctx->ifCount), NULL )); Admin_sendMessage(&out, txid, ctx->admin); ctx->ifCount++; }
/** * Initialize the core. * * @param coreBinaryPath the path to the core binary. * @param toCore a pointer to an int which will be set to the * file descriptor for writing to the core. * @param fromCore a pointer to an int which will be set to the * file descriptor for reading from the core. * @param eh an exception handler in case something goes wrong. */ static void initCore(char* coreBinaryPath, int* toCore, int* fromCore, struct Except* eh) { int pipes[2][2]; if (Pipe_createUniPipe(pipes[0]) || Pipe_createUniPipe(pipes[1])) { Except_raise(eh, -1, "Failed to create pipes [%s]", Errno_getString()); } // Pipes used in the core process. #define TO_ANGEL (pipes[1][1]) #define FROM_ANGEL (pipes[0][0]) // Pipes used in the angel process (here). #define TO_CORE (pipes[0][1]) #define FROM_CORE (pipes[1][0]) char toAngel[32]; char fromAngel[32]; snprintf(toAngel, 32, "%u", TO_ANGEL); snprintf(fromAngel, 32, "%u", FROM_ANGEL); char* args[] = { "core", toAngel, fromAngel, NULL }; FILE* file; if ((file = fopen(coreBinaryPath, "r")) != NULL) { fclose(file); } else { Except_raise(eh, -1, "Can't open core executable [%s] for reading.", coreBinaryPath); } if (Process_spawn(coreBinaryPath, args)) { Except_raise(eh, -1, "Failed to spawn core process."); } *toCore = TO_CORE; *fromCore = FROM_CORE; }
/** @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; }
void TUNConfigurator_setIpAddress(const char* interfaceName, const uint8_t address[16], int prefixLen, struct Log* logger, struct Except* eh) { /* stringify our IP address */ char myIp[40]; AddrTools_printIp((uint8_t*)myIp, address); /* set up the interface ip assignment request */ struct in6_aliasreq in6_addreq; memset(&in6_addreq, 0, sizeof(in6_addreq)); in6_addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; in6_addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; /* parse the IPv6 address and add it to the request */ struct addrinfo hints, *result; bzero(&hints, sizeof(struct addrinfo)); hints.ai_family = AF_INET6; int err = getaddrinfo((const char *)myIp, NULL, &hints, &result); if (err) { // Should never happen since the address is specified as binary. Except_raise(eh, TUNConfigurator_setIpAddress_INTERNAL, "bad IPv6 address [%s]", gai_strerror(err)); } Bits_memcpy(&in6_addreq.ifra_addr, result->ai_addr, result->ai_addrlen); /* turn the prefixlen into a mask, and add it to the request */ struct sockaddr_in6* mask = &in6_addreq.ifra_prefixmask; u_char *cp; int len = prefixLen; mask->sin6_len = sizeof(*mask); if ((prefixLen == 0) || (prefixLen == 128)) { memset(&mask->sin6_addr, 0xff, sizeof(struct in6_addr)); } else { memset((void *)&mask->sin6_addr, 0x00, sizeof(mask->sin6_addr)); for (cp = (u_char *)&mask->sin6_addr; len > 7; len -= 8) { *cp++ = 0xff; } *cp = 0xff << (8 - len); } strncpy(in6_addreq.ifra_name, interfaceName, sizeof(in6_addreq.ifra_name)); /* do the actual assignment ioctl */ int s = socket(AF_INET6, SOCK_DGRAM, 0); if (s < 0) { Except_raise(eh, TUNConfigurator_setIpAddress_INTERNAL, "socket() failed [%s]", Errno_getString()); } if (ioctl(s, SIOCAIFADDR_IN6, &in6_addreq) < 0) { enum Errno err = Errno_get(); close(s); Except_raise(eh, TUNConfigurator_setIpAddress_INTERNAL, "ioctl(SIOCAIFADDR) failed [%s]", Errno_strerror(err)); } Log_info(logger, "Configured IPv6 [%s/%i] for [%s]", myIp, prefixLen, interfaceName); close(s); }