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 checkRunningInstance(struct Allocator* allocator, struct EventBase* base, String* addr, String* password, struct Log* logger, struct Except* eh) { struct Allocator* alloc = Allocator_child(allocator); struct Sockaddr_storage pingAddrStorage; if (Sockaddr_parse(addr->bytes, &pingAddrStorage)) { Except_raise(eh, -1, "Unable to parse [%s] as an ip address port, eg: 127.0.0.1:11234", addr->bytes); } struct AdminClient* adminClient = AdminClient_new(&pingAddrStorage.addr, password, base, logger, alloc); // 100 milliseconds is plenty to wait for a process to respond on the same machine. adminClient->millisecondsToWait = 100; Dict* pingArgs = Dict_new(alloc); struct AdminClient_Result* pingResult = AdminClient_rpcCall(String_new("ping", alloc), pingArgs, adminClient, alloc); if (pingResult->err == AdminClient_Error_NONE) { Except_raise(eh, -1, "Startup failed: cjdroute is already running."); } Allocator_free(alloc); }
static void sendConfToCore(struct Interface* toCoreInterface, struct Allocator* tempAlloc, 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, tempAlloc); if (StandardBencSerializer_get()->serializeDictionary(writer, config)) { Except_raise(eh, -1, "Failed to serialize pre-configuration for core."); } struct Message* m = &(struct Message) { .bytes = start, .length = writer->bytesWritten, .padding = 32 }; m = Message_clone(m, tempAlloc); 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); } } static struct Pipe* getClientPipe(int argc, char** argv, struct EventBase* base, struct Except* eh, struct Allocator* alloc) { int inFromClientNo; int outToClientNo; if (argc < 4 || (inFromClientNo = atoi(argv[2])) == 0) { inFromClientNo = STDIN_FILENO; } if (argc < 4 || (outToClientNo = atoi(argv[3])) == 0) { outToClientNo = STDOUT_FILENO; } // named pipe. if (argc > 2 && inFromClientNo == STDIN_FILENO) { return Pipe_named(argv[2], base, eh, alloc); } return Pipe_forFiles(inFromClientNo, outToClientNo, base, eh, alloc); }
struct Interface* TUNInterface_new(const char* interfaceName, char assignedInterfaceName[TUNInterface_IFNAMSIZ], int isTapMode, struct EventBase* base, struct Log* logger, struct Except* eh, struct Allocator* alloc) { if (isTapMode) { Except_throw(eh, "tap mode not supported on this platform"); } // to store the tunnel device index int ppa = 0; // Open the descriptor int tunFd = open("/dev/tun0", O_RDWR); if (tunFd == -1) { tunFd = open("/dev/tun1", O_RDWR); ppa = 1; } if (tunFd == -1) { tunFd = open("/dev/tun2", O_RDWR); ppa = 2; } if (tunFd == -1) { tunFd = open("/dev/tun3", O_RDWR); ppa = 3; } if (tunFd < 0 ) { int err = errno; close(tunFd); char* error = NULL; if (tunFd < 0) { error = "open(\"/dev/tunX\")"; } Except_raise(eh, TUNConfigurator_initTun_INTERNAL, error, strerror(err)); } // Since devices are numbered rather than named, it's not possible to have tun0 and cjdns0 // so we'll skip the pretty names and call everything tunX if (assignedInterfaceName) { snprintf(assignedInterfaceName, TUNConfigurator_IFNAMSIZ, "tun%d", ppa); } char* error = NULL; if (error) { int err = errno; close(tunFd); Except_raise(eh, TUNConfigurator_initTun_INTERNAL, "%s [%s]", error, strerror(err)); } struct Pipe* p = Pipe_forFiles(tunFd, tunFd, base, eh, alloc); return BSDMessageTypeWrapper_new(&p->iface, logger); }
/** * Open the tun device. * * @param interfaceName the interface name you *want* to use or NULL to let the kernel decide. * @param assignedInterfaceName the interface name you get. * @param log * @param eh * @return a file descriptor for the tunnel. */ void* TUNConfigurator_initTun(const char* interfaceName, char assignedInterfaceName[TUNConfigurator_IFNAMSIZ], struct Log* logger, struct Except* eh) { // Open the descriptor int tunFd = open("/dev/tun", O_RDWR); //Get the resulting device name const char* assignedDevname; assignedDevname = fdevname(tunFd); // Extract the number eg: 0 from tun0 int ppa = 0; for (uint32_t i = 0; i < strlen(assignedDevname); i++) { if (isdigit(assignedDevname[i])) { ppa = atoi(assignedDevname); } } if (tunFd < 0 || ppa < 0 ) { enum Errno err = Errno_get(); close(tunFd); char* error = NULL; if (tunFd < 0) { error = "open(\"/dev/tun\")"; } else if (ppa < 0) { error = "fdevname/getting number from fdevname"; } Except_raise(eh, TUNConfigurator_initTun_INTERNAL, error, Errno_strerror(err)); } // Since devices are numbered rather than named, it's not possible to have tun0 and cjdns0 // so we'll skip the pretty names and call everything tunX snprintf(assignedInterfaceName, TUNConfigurator_IFNAMSIZ, "tun%d", ppa); char* error = NULL; // We want to send IPv6 through our tun device, so we need to be able to specify "ethertype" int tunhead = 1; if (ioctl(tunFd,TUNSIFHEAD,&tunhead) == -1) { error = "TUNSIFHEAD"; } if (error) { enum Errno err = Errno_get(); close(tunFd); Except_raise(eh, TUNConfigurator_initTun_INTERNAL, "%s [%s]", error, Errno_strerror(err)); } intptr_t ret = (intptr_t) tunFd; return (void*) ret; }
void *Mem_alloc(long nbytes,const char *file,int line) { struct descriptor *bp; void *ptr; assert(nbytes>0); //对nbytes做字节对齐扩充到合适字节,避免空间浪费 nbytes=((nbytes+sizeof(union align)-1)/(sizeof(union align)))*(sizeof(union align)); //从空闲块的首地址的下一块开始寻找合适的空间,freelist是一个循环链表,这里所谓的空闲块 //并不是真正都是空闲的,其实是所有当前已经申请过的块,每一块都有至少(NALLOC)大。经过多次分别后 //块中有的是空闲的,而有的可能已经被用满。 for(bp=freelist.free;bp;bp=bp->free) { if(bp->size>nbytes) //如果找到合适的空闲块 { bp->size-=nbytes; ptr=(char *)bp->ptr+bp->size; //得到分配空间的首地址 if((bp=dalloc(ptr,nbytes,file,line))!=NULL) //申请一个存储新ptr的结构体bp { unsigned h=hash(ptr,htab); //然后将这个结构体加入到hash表中 bp->link=htab[h]; //表明这块内存已经被占用了。 htab[h]=bp; return ptr; } else { if(file==NULL) RAISE(Mem_Failed); else Except_raise(&Mem_Failed,file,line); } } if(bp==&freelist) //没有合适的空闲块,那么分配一个新块 { struct descriptor *newptr; if((ptr=malloc(nbytes+NALLOC))==NULL //新块大小由固定宏和nbytes共同决定,意味着所有的块都将有大小上的一些差异 ||(newptr=dalloc(ptr,nbytes+NALLOC,__FILE__,__LINE__))==NULL) { if(file==NULL) RAISE(Mem_Failed); else Except_raise(&Mem_Failed,file,line); } newptr->free=freelist.free; freelist.free=newptr; } } assert(0); return NULL; }
void* Mem_alloc(long nbytes, const char* file, int line) { struct descriptor *bp; void* ptr; assert(nbytes > 0); nbytes = (nbytes + sizeof(union align) - 1)/(sizeof(union align)) * (sizeof(union align)); for (bp = freelist.free; bp; bp = bp->free) { if (bp->size > nbytes) { bp->size -= nbytes; ptr = (char*)bp->ptr + bp->size; if ( (bp = dalloc(ptr, nbytes, file, line)) != NULL) { unsigned h = hash(ptr, htab); bp->link = htab[h]; htab[h] = bp; return ptr; } else { Except_raise(&Assert_Failed, file, line); } } if (bp == &freelist) { struct descriptor *newptr; if ( (ptr = malloc(nbytes + NALLOC) ) == NULL || ( newptr = dalloc(ptr, nbytes + NALLOC, __FILE__, __LINE__)) == NULL ) { Except_raise(&Assert_Failed, file, line); } newptr->free = freelist.free; freelist.free= newptr; } } assert(0); return NULL; }
void QExc_free(void *ptr, int line, const char* file) { MemorySuite *suite; if(ptr == NULL) Except_raise(&Mem_FreeFailed, line, file); suite = RemoveMemorySuite(ptr); if(suite == NULL) Except_raise(&Mem_FreeFailed, line, file); free(ptr); free(suite); }
void *Arena_alloc(T arena, long nbytes, const char *file, int line) { assert(arena); assert(nbytes > 0); nbytes = ((nbytes + sizeof (union align) - 1)/ (sizeof (union align)))*(sizeof (union align)); while (nbytes > arena->limit - arena->avail) { T ptr; char *limit; if ((ptr = freechunks) != NULL) { freechunks = freechunks->prev; nfree--; limit = ptr->limit; } else { long m = sizeof (union header) + nbytes + 10*1024; ptr = malloc(m); if (ptr == NULL) { if (file == NULL) RAISE(Arena_Failed); else Except_raise(&Arena_Failed, file, line); } limit = (char *)ptr + m; } *ptr = *arena; arena->avail = (char *)((union header *)ptr + 1); arena->limit = limit; arena->prev = ptr; } arena->avail += nbytes; return arena->avail - nbytes; }
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 = Allocator_child(alloc); 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; }
void* QExc_malloc(unsigned int size, int line, const char *file) { _MemoryPtr newBlock; MemorySuite *newSuite; newSuite = (MemorySuite*)malloc(sizeof(MemorySuite)); if(newSuite == NULL) //program routine will jump to setjmp Except_raise(&Mem_AllocFailed, line, file); newBlock = (_MemoryPtr)malloc(size); if(newBlock == NULL) { free(newSuite); Except_raise(&Mem_AllocFailed, line, file); } SetMemorySuite(newSuite, newBlock, size, line, file); return newBlock; }
static void initCore(char* coreBinaryPath, String* corePipeName, struct EventBase* base, struct Allocator* alloc, struct Except* eh) { char* args[] = { "core", corePipeName->bytes, 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, base, alloc)) { Except_raise(eh, -1, "Failed to spawn core process."); } }
void * Mem_alloc(long nbytes, const char *file, int line) { assert(nbytes > 0); nbytes = ((nbytes + sizeof(union align) - 1) / (sizeof(union align))) * (sizeof(union align)); for (struct descriptor *bp = freelist.free; bp; bp = bp->free) { if (bp->size > nbytes) { bp->size -= nbytes; void *ptr = (char *)bp->ptr + bp->size; if ((bp = dalloc(ptr, nbytes, file, line)) != NULL) { unsigned h = hash(ptr, htab); bp->link = htab[h]; htab[h] = bp; return ptr; } else { if (file == NULL) RAISE(Mem_Failed); else Except_raise(&Mem_Failed, file, line); } } if (bp == &freelist) { void *ptr = malloc(nbytes + NALLOC); struct descriptor *newptr = dalloc(ptr, nbytes + NALLOC, __FILE__, __LINE__); if (ptr == NULL || newptr == NULL) { if (file == NULL) RAISE(Mem_Failed); else Except_raise(&Mem_Failed, file, line); } newptr->free = freelist.free; freelist.free = newptr; } // exercise 5.2 if (bp->free->size == sizeof(union align)) { struct descriptor *temp = bp->free; bp->free = temp->free; temp->free = NULL; } } assert(0); return NULL; }
void *Mem_alloc(long nbytes, const char *file, int line){ void *ptr; assert(nbytes > 0); ptr = malloc(nbytes); if (ptr == NULL) { if (file == NULL) RAISE(Mem_Failed); else Except_raise(&Mem_Failed, file, line); } return ptr; }
void Mem_free(void* ptr,const char *file,int line) { if(ptr) { struct descriptor *bp; if(((unsigned long)ptr)%(sizeof(union align))!=0||(bp=find(ptr))==NULL||bp->free) Except_raise(&Assert_Failed,file,line); bp->free=freelist.free; freelist.free=bp; } }
void *Mem_alloc(long nbytes, const char *file, int line) { void *ptr; if (nbytes <= 0) { if (file == NULL) RAISE(Mem_Failed); else Except_raise(&Mem_Failed, file, line); } ptr = malloc(nbytes); if (ptr == NULL) { if (file == NULL) { RAISE(Mem_Failed); } else { Except_raise(&Mem_Failed, file, line); } } alt++; return ptr; }
/** * 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; }
void *Mem_copy( void* destination, void* source, long nbytes, const char *file, int line ) { assert(nbytes > 0); void *ptr; ptr = memcpy( destination, source, nbytes ); if (ptr == NULL) { if (file == NULL) RAISE(Mem_Failed); else Except_raise(&Mem_Failed, file, line); } return ptr; }
void *Mem_resize(void *ptr, long nbytes, const char *file, int line) { assert( ptr ); assert( nbytes > 0 ); ptr = realloc( ptr, nbytes ); if( ptr == NULL ) { if (file == NULL) RAISE(Mem_Failed); else Except_raise(&Mem_Failed, file, line); } return ptr; }
void *Mem_resize(void *ptr,long nbytes,const char *file,int line) { struct descriptor *bp; void *newptr; assert(ptr); assert(nbytes>0); if(((unsigned long)ptr)%(sizeof(union align))!=0||(bp=find(ptr))==NULL||bp->free) Except_raise(&Assert_Failed,file,line); newptr=Mem_alloc(nbytes,file,line); memcpy(newptr,ptr,nbytes<bp->size? nbytes:bp->size); Mem_free(ptr,file,line); return newptr; }
static Dict* getInitialConfig(struct Interface* iface, struct EventBase* eventBase, struct Allocator* alloc, struct Except* eh) { struct Message* m = InterfaceWaiter_waitForData(iface, eventBase, alloc, eh); struct Reader* reader = ArrayReader_new(m->bytes, m->length, alloc); Dict* config = Dict_new(alloc); if (StandardBencSerializer_get()->parseDictionary(reader, alloc, config)) { Except_raise(eh, -1, "Failed to parse initial configuration."); } return config; }
//<functions 54> void *Mem_alloc(long nbytes, const char *file, int line) { void *ptr; assert(nbytes > 0); ptr = malloc(nbytes); if (ptr == NULL) { //<raise Mem_Failed 54> if (file == NULL) { RAISE(Mem_Failed); } else { Except_raise(&Mem_Failed, file, line); } } }
void *Mem_calloc( long count, long nbytes, const char *file, int line ) { assert(count > 0); assert(nbytes > 0); void *ptr; ptr = calloc(count, nbytes); if (ptr == NULL) { if (file == NULL) RAISE(Mem_Failed); else Except_raise(&Mem_Failed, file, line); } return ptr; }
static void *align_alloc(size_t nbytes, const char *file, int line){ void *ptr; assert(nbytes > 0); ptr = Aligned_malloc(nbytes, ALIGNMENT); if (ptr == NULL) { if (file == NULL) RAISE(Mem_Failed); else Except_raise(&Mem_Failed, file, line); } return ptr; }
static void *align_realloc(void *ptr, size_t nbytes, const char *file, int line) { assert(ptr); assert(nbytes > 0); ptr = Aligned_realloc(ptr, nbytes, ALIGNMENT); if (ptr == NULL) { if (file == NULL) RAISE(Mem_Failed); else Except_raise(&Mem_Failed, file, line); } log_dbg("%p realloc %lu bytes", ptr, (unsigned long) nbytes); return ptr; }
void Mem_free(void *ptr, const char *file, int line) { if (ptr) { struct descriptor *bp = find(ptr); if (((unsigned long long)ptr) % (sizeof(union align)) != 0 || bp == NULL || bp->free) { if (log_file) { fprintf(log_file, "** freeing free memory\n" "Mem_free(0x%p) called from %s:%d\n" "This block is %d bytes long and was allocated from %s:%d\n", \ ptr, file, line, bp->size, bp->file, bp->line); } else Except_raise(&Assert_Failed, file, line); } bp->free = freelist.free; freelist.free = bp; } }
void * Mem_resize(void *ptr, long nbytes, const char *file, int line) { assert(ptr); assert(nbytes > 0); struct descriptor *bp = find(ptr); if (((unsigned long long)ptr) % (sizeof(union align)) != 0 || bp == NULL || bp->free) { if (log_file) { fprintf(log_file, "** resizing unallocated memory\n" "Mem_resize(0x%p, %ld) called from %s:%d\n", \ ptr, nbytes, file, line); } else Except_raise(&Assert_Failed, file, line); } void *newptr = Mem_alloc(nbytes, file, line); memcpy(newptr, ptr, nbytes < bp->size ? nbytes : bp->size); Mem_free(ptr, file, line); return newptr; }
LONG(CALLBACK win_exception_handler)(LPEXCEPTION_POINTERS ep) { HMODULE hm; MODULEINFO mi; WCHAR fn[MAX_PATH]; char message[512]; unsigned int code; code = ep->ExceptionRecord->ExceptionCode; GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)(ep->ExceptionRecord->ExceptionAddress), &hm ); GetModuleInformation(GetCurrentProcess(), hm, &mi, sizeof(mi) ); GetModuleFileNameEx(GetCurrentProcess(), hm, fn, MAX_PATH ); sprintf(message, "SE %s at address %p inside %s loaded at base address %p\n", seDescription(code), ep->ExceptionRecord->ExceptionAddress, fn, mi.lpBaseOfDll); if(code == EXCEPTION_ACCESS_VIOLATION || code == EXCEPTION_IN_PAGE_ERROR ) { sprintf("%sInvalid operation: %s at address %p\n", message, opDescription(ep->ExceptionRecord->ExceptionInformation[0]), ep->ExceptionRecord->ExceptionInformation[1]); } if(code == EXCEPTION_IN_PAGE_ERROR) { sprintf("%sUnderlying NTSTATUS code that resulted in the exception %i", message, ep->ExceptionRecord->ExceptionInformation[2]); } Native_Exception.reason = message; SetUnhandledExceptionFilter(win_exception_handler); Except_raise(&Native_Exception, "", 0); return 0; }
/* * 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 });
/** @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 }); }