/** * Send a search request to the next node in this search. * This is called whenever a response comes in or after the global mean response time passes. */ static void searchStep(struct SearchRunner_Search* search) { struct SearchRunner_pvt* ctx = Identity_check((struct SearchRunner_pvt*)search->runner); struct Node_Two* node; struct SearchStore_Node* nextSearchNode; for (;;) { nextSearchNode = SearchStore_getNextNode(search->search); // If the number of requests sent has exceeded the max search requests, let's stop there. if (search->totalRequests >= MAX_REQUESTS_PER_SEARCH || nextSearchNode == NULL) { if (search->pub.callback) { search->pub.callback(&search->pub, 0, NULL, NULL); } Allocator_free(search->pub.alloc); return; } node = NodeStore_getBest(&nextSearchNode->address, ctx->nodeStore); if (!node) { continue; } if (node == ctx->nodeStore->selfNode) { continue; } if (Bits_memcmp(node->address.ip6.bytes, nextSearchNode->address.ip6.bytes, 16)) { continue; } break; } Assert_true(node != ctx->nodeStore->selfNode); Bits_memcpyConst(&search->lastNodeAsked, &node->address, sizeof(struct Address)); struct RouterModule_Promise* rp = RouterModule_newMessage(&node->address, 0, ctx->router, search->pub.alloc); Dict* message = Dict_new(rp->alloc); Dict_putString(message, CJDHTConstants_QUERY, CJDHTConstants_QUERY_FN, rp->alloc); Dict_putString(message, CJDHTConstants_TARGET, search->targetStr, rp->alloc); rp->userData = search; rp->callback = searchCallback; RouterModule_sendMessage(rp, message); search->totalRequests++; }
static void authorizedPasswords(List* list, struct Context* ctx) { uint32_t count = List_size(list); for (uint32_t i = 0; i < count; i++) { Dict* d = List_getDict(list, i); Log_info(ctx->logger, "Checking authorized password %d.", i); if (!d) { Log_critical(ctx->logger, "Not a dictionary type %d.", i); exit(-1); } String* passwd = Dict_getString(d, String_CONST("password")); if (!passwd) { Log_critical(ctx->logger, "Must specify a password %d.", i); exit(-1); } } for (uint32_t i = 0; i < count; i++) { struct Allocator* child = Allocator_child(ctx->alloc); Dict* d = List_getDict(list, i); String* passwd = Dict_getString(d, String_CONST("password")); String* user = Dict_getString(d, String_CONST("user")); String* displayName = user; if (!displayName) { displayName = String_printf(child, "password [%d]", i); } //String* publicKey = Dict_getString(d, String_CONST("publicKey")); String* ipv6 = Dict_getString(d, String_CONST("ipv6")); Log_info(ctx->logger, "Adding authorized password #[%d] for user [%s].", i, displayName->bytes); Dict *args = Dict_new(child); uint32_t i = 1; Dict_putInt(args, String_CONST("authType"), i, child); Dict_putString(args, String_CONST("password"), passwd, child); if (user) { Dict_putString(args, String_CONST("user"), user, child); } Dict_putString(args, String_CONST("displayName"), displayName, child); if (ipv6) { Log_info(ctx->logger, " This connection password restricted to [%s] only.", ipv6->bytes); Dict_putString(args, String_CONST("ipv6"), ipv6, child); } rpcCall(String_CONST("AuthorizedPasswords_add"), args, ctx, child); Allocator_free(child); } }
/** * Send a search request to the next node in this search. * This is called whenever a response comes in or after the global mean response time passes. */ static void searchStep(struct SearchRunner_Search* search) { struct SearchRunner_pvt* ctx = Identity_check((struct SearchRunner_pvt*)search->runner); struct SearchStore_Node* nextSearchNode; for (;;) { nextSearchNode = SearchStore_getNextNode(search->search); // If the number of requests sent has exceeded the max search requests, let's stop there. if (search->totalRequests >= search->maxRequests) { // fallthrough } else if (search->numFinds > 0 && search->totalRequests >= search->maxRequestsIfFound) { // fallthrough } else if (nextSearchNode == NULL) { // fallthrough } else { break; } if (search->pub.callback) { search->pub.callback(&search->pub, 0, NULL, NULL); } Allocator_free(search->pub.alloc); return; } Bits_memcpyConst(&search->lastNodeAsked, &nextSearchNode->address, sizeof(struct Address)); struct RouterModule_Promise* rp = RouterModule_newMessage(&nextSearchNode->address, 0, ctx->router, search->pub.alloc); Dict* message = Dict_new(rp->alloc); if (!Bits_memcmp(nextSearchNode->address.ip6.bytes, search->target.ip6.bytes, 16)) { Dict_putString(message, CJDHTConstants_QUERY, CJDHTConstants_QUERY_GP, rp->alloc); } else { Dict_putString(message, CJDHTConstants_QUERY, CJDHTConstants_QUERY_FN, rp->alloc); } Dict_putString(message, CJDHTConstants_TARGET, search->targetStr, rp->alloc); rp->userData = search; rp->callback = searchCallback; RouterModule_sendMessage(rp, message); search->totalRequests++; }
static Dict* serialize(void* vcontext) { char* buffer = calloc(2048, 1); struct Allocator* allocator = BufferAllocator_new(buffer, 2048); Dict* out = Dict_new(allocator); Dict_putString(out, &hi, String_new((char*) vcontext, allocator), allocator); return out; }
Dict* Security_getUser(char* userName, struct Allocator* retAlloc) { Dict* ret = Dict_new(retAlloc); Dict_putString(ret, String_new("error", retAlloc), String_new("Not supported on windows", retAlloc), retAlloc); return ret; }
static void sendMsg(struct MsgCore_pvt* mcp, Dict* msgDict, struct Address* addr, struct Allocator* allocator) { struct Allocator* alloc = Allocator_child(allocator); // Send the encoding scheme definition Dict_putString(msgDict, CJDHTConstants_ENC_SCHEME, mcp->schemeDefinition, allocator); // And tell the asker which interface the message came from int encIdx = EncodingScheme_getFormNum(mcp->scheme, addr->path); Assert_true(encIdx != EncodingScheme_getFormNum_INVALID); Dict_putInt(msgDict, CJDHTConstants_ENC_INDEX, encIdx, allocator); // send the protocol version Dict_putInt(msgDict, CJDHTConstants_PROTOCOL, Version_CURRENT_PROTOCOL, allocator); if (!Defined(SUBNODE)) { String* q = Dict_getStringC(msgDict, "q"); String* sq = Dict_getStringC(msgDict, "sq"); if (q || sq) { Log_debug(mcp->log, "Send query [%s] to [%s]", ((q) ? q->bytes : sq->bytes), Address_toString(addr, alloc)->bytes); String* txid = Dict_getStringC(msgDict, "txid"); Assert_true(txid); String* newTxid = String_newBinary(NULL, txid->len + 1, alloc); Bits_memcpy(&newTxid->bytes[1], txid->bytes, txid->len); newTxid->bytes[0] = '1'; Dict_putStringC(msgDict, "txid", newTxid, alloc); } } struct Message* msg = Message_new(0, 2048, alloc); BencMessageWriter_write(msgDict, msg, NULL); //Log_debug(mcp->log, "Sending msg [%s]", Escape_getEscaped(msg->bytes, msg->length, alloc)); // Sanity check (make sure the addr was actually calculated) Assert_true(addr->ip6.bytes[0] == 0xfc); struct DataHeader data; Bits_memset(&data, 0, sizeof(struct DataHeader)); DataHeader_setVersion(&data, DataHeader_CURRENT_VERSION); DataHeader_setContentType(&data, ContentType_CJDHT); Message_push(msg, &data, sizeof(struct DataHeader), NULL); struct RouteHeader route; Bits_memset(&route, 0, sizeof(struct RouteHeader)); Bits_memcpy(route.ip6, addr->ip6.bytes, 16); route.version_be = Endian_hostToBigEndian32(addr->protocolVersion); route.sh.label_be = Endian_hostToBigEndian64(addr->path); Bits_memcpy(route.publicKey, addr->key, 32); Message_push(msg, &route, sizeof(struct RouteHeader), NULL); Iface_send(&mcp->pub.interRouterIf, msg); }
static void sendResponse(String* error, struct Admin* admin, String* txid, struct Allocator* tempAlloc) { Dict* output = Dict_new(tempAlloc); Dict_putString(output, String_CONST("error"), error, tempAlloc); Admin_sendMessage(output, txid, admin); }
static void sendResponse(String* msg, struct Admin* admin, String* txid) { #define BUFFERSZ 1024 uint8_t buffer[BUFFERSZ]; struct Allocator* alloc = BufferAllocator_new(buffer, BUFFERSZ); Dict* output = Dict_new(alloc); Dict_putString(output, String_CONST("error"), msg, alloc); Admin_sendMessage(output, txid, admin); }
static void getRouteLabel(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct Context* ctx = Identity_check((struct Context*) vcontext); char* err = NULL; String* pathToParentS = Dict_getString(args, String_CONST("pathToParent")); uint64_t pathToParent = 0; if (pathToParentS->len != 19 || AddrTools_parsePath(&pathToParent, pathToParentS->bytes)) { err = "parse_pathToParent"; } String* pathParentToChildS = Dict_getString(args, String_CONST("pathParentToChild")); uint64_t pathParentToChild = 0; if (pathParentToChildS->len != 19 || AddrTools_parsePath(&pathParentToChild, pathParentToChildS->bytes)) { err = "parse_pathParentToChild"; } uint64_t label = UINT64_MAX; if (!err) { label = NodeStore_getRouteLabel(ctx->store, pathToParent, pathParentToChild); err = NodeStore_getRouteLabel_strerror(label); } Dict* response = Dict_new(requestAlloc); if (!err) { String* printedPath = String_newBinary(NULL, 19, requestAlloc); AddrTools_printPath(printedPath->bytes, label); Dict_putString(response, String_new("result", requestAlloc), printedPath, requestAlloc); Dict_putString(response, String_new("error", requestAlloc), String_new("none", requestAlloc), requestAlloc); Admin_sendMessage(response, txid, ctx->admin); } else { Dict_putString(response, String_new("error", requestAlloc), String_new(err, requestAlloc), requestAlloc); Admin_sendMessage(response, txid, ctx->admin); } }
static void addRemoveSomething(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc, enum addRemoveSomething_What what) { struct RouteGen_admin_Ctx* ctx = Identity_check((struct RouteGen_admin_Ctx*) vcontext); String* route = Dict_getString(args, String_CONST("route")); char* error = NULL; struct Sockaddr_storage ss; if (route->len > 63) { error = "parse_failed"; } if (!error) { if (Sockaddr_parse(route->bytes, &ss)) { error = "parse_failed"; } else { int family = Sockaddr_getFamily(&ss.addr); if (family != Sockaddr_AF_INET && family != Sockaddr_AF_INET6) { error = "unexpected_af"; } } } int retVal = -1; Dict* out = Dict_new(requestAlloc); if (!error) { switch (what) { case addRemoveSomething_What_ADD_EXCEPTION: RouteGen_addException(ctx->rg, &ss.addr); break; case addRemoveSomething_What_ADD_PREFIX: RouteGen_addPrefix(ctx->rg, &ss.addr); break; case addRemoveSomething_What_ADD_LOCALPREFIX: RouteGen_addLocalPrefix(ctx->rg, &ss.addr); break; case addRemoveSomething_What_RM_EXCEPTION: retVal = RouteGen_removeException(ctx->rg, &ss.addr); break; case addRemoveSomething_What_RM_PREFIX: retVal = RouteGen_removePrefix(ctx->rg, &ss.addr); break; case addRemoveSomething_What_RM_LOCALPREFIX: retVal = RouteGen_removeLocalPrefix(ctx->rg, &ss.addr); break; default: Assert_failure("invalid op"); } if (!retVal) { error = "no_such_route"; } else { error = "none"; } } Dict_putString(out, String_new("error", requestAlloc), String_new(error, requestAlloc), requestAlloc); Admin_sendMessage(out, txid, ctx->admin); }
static void adminPing(Dict* input, void* vadmin, String* txid) { uint8_t buffer[256]; struct Allocator* alloc = BufferAllocator_new(buffer, 256); String* pong = BSTR("pong"); Dict* d = Dict_new(alloc); Dict_putString(d, CJDHTConstants_QUERY, pong, alloc); Admin_sendMessage(d, txid, (struct Admin*) vadmin); }
/** @return a string representing the address and port to connect to. */ static void initAngel(struct Pipe* asClientPipe, struct Interface* asCoreIface, char* asCorePipeName, struct EventBase* eventBase, struct Log* logger, struct Allocator* alloc, struct Random* rand) { Dict admin = Dict_CONST( String_CONST("bind"), String_OBJ(String_CONST("127.0.0.1")), Dict_CONST( String_CONST("corePipeName"), String_OBJ(String_CONST(asCorePipeName)), 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 = Allocator_child(alloc); struct Message* toAngel = Message_new(0, 1024, tempAlloc); BencMessageWriter_write(&message, toAngel, NULL); Log_info(logger, "Writing intial configuration to angel on [%s]", asClientPipe->name); Interface_sendMessage(&asClientPipe->iface, toAngel); // This is client->angel->core data, we can throw this away. //struct Message* angelToCore = InterfaceWaiter_waitForData(asCoreIface, eventBase, tempAlloc, NULL); // unterminated string //Log_info(logger, "Init message from angel to core: [%s]", angelToCore->bytes); // Send response on behalf of core. Dict* coreToAngelResp = Dict_new(tempAlloc); Dict_putString(coreToAngelResp, String_CONST("error"), String_CONST("none"), tempAlloc); struct Message* coreToAngelMsg = Message_new(0, 256, tempAlloc); BencMessageWriter_write(coreToAngelResp, coreToAngelMsg, NULL); Interface_sendMessage(asCoreIface, coreToAngelMsg); // This is angel->client data, it will tell us which port was bound. struct Message* angelToClient = InterfaceWaiter_waitForData(&asClientPipe->iface, eventBase, tempAlloc, NULL); uint8_t lastByte = angelToClient->bytes[angelToClient->length-1]; angelToClient->bytes[angelToClient->length-1] = '\0'; printf("Response from angel to client: [%s%c]\n", angelToClient->bytes, (char)lastByte); Allocator_free(tempAlloc); return; }
static void udpInterface(Dict* config, struct Context* ctx) { Dict* udp = Dict_getDict(config, String_CONST("UDPInterface")); if (udp) { // Setup the interface. String* bindStr = Dict_getString(udp, String_CONST("bind")); Dict* d = Dict_new(ctx->alloc); if (bindStr) { Dict_putString(d, String_CONST("bindAddress"), bindStr, ctx->alloc); } rpcCall(String_CONST("UDPInterface_new"), d, ctx, ctx->alloc); // Make the connections. Dict* connectTo = Dict_getDict(udp, String_CONST("connectTo")); if (connectTo) { struct Dict_Entry* entry = *connectTo; while (entry != NULL) { String* key = (String*) entry->key; if (entry->val->type != Object_DICT) { Log_critical(ctx->logger, "interfaces.UDPInterface.connectTo: entry [%s] " "is not a dictionary type.", key->bytes); exit(-1); } Dict* value = entry->val->as.dictionary; Log_keys(ctx->logger, "Attempting to connect to node [%s].", key->bytes); struct Allocator* perCallAlloc = ctx->alloc->child(ctx->alloc); Dict_putString(value, String_CONST("address"), key, perCallAlloc); rpcCall(String_CONST("UDPInterface_beginConnection"), value, ctx, perCallAlloc); perCallAlloc->free(perCallAlloc); entry = entry->next; } } } }
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); }
static void checkPermissionsB(struct Except* eh, String* txid, struct Admin* admin, struct Allocator* requestAlloc) { struct Security_Permissions* sp = Security_checkPermissions(requestAlloc, eh); Dict* out = Dict_new(requestAlloc); Dict_putInt(out, String_CONST("noOpenFiles"), sp->noOpenFiles, requestAlloc); Dict_putInt(out, String_CONST("seccompExists"), sp->seccompExists, requestAlloc); Dict_putInt(out, String_CONST("seccompEnforcing"), sp->seccompEnforcing, requestAlloc); Dict_putInt(out, String_CONST("userId"), sp->uid, requestAlloc); Dict_putString(out, String_CONST("error"), String_CONST("none"), requestAlloc); Admin_sendMessage(out, txid, admin); }
void Admin_registerFunctionWithArgCount(char* name, Admin_FUNCTION(callback), void* callbackContext, bool needsAuth, struct Admin_FunctionArg* arguments, int argCount, struct Admin* admin) { if (!admin) { return; } String* str = String_new(name, admin->allocator); if (!admin->functionCount) { admin->functions = admin->allocator->malloc(sizeof(struct Function), admin->allocator); } else { admin->functions = admin->allocator->realloc(admin->functions, sizeof(struct Function) * (admin->functionCount + 1), admin->allocator); } struct Function* fu = &admin->functions[admin->functionCount]; admin->functionCount++; fu->name = str; fu->call = callback; fu->context = callbackContext; fu->needsAuth = needsAuth; fu->args = Dict_new(admin->allocator); for (int i = 0; arguments && i < argCount; i++) { // "type" must be one of: [ "String", "Int", "Dict", "List" ] String* type = NULL; if (!strcmp(arguments[i].type, STRING->bytes)) { type = STRING; } else if (!strcmp(arguments[i].type, INT->bytes)) { type = INT; } else if (!strcmp(arguments[i].type, DICT->bytes)) { type = DICT; } else if (!strcmp(arguments[i].type, LIST->bytes)) { type = LIST; } else { abort(); } Dict* arg = Dict_new(admin->allocator); Dict_putString(arg, TYPE, type, admin->allocator); Dict_putInt(arg, REQUIRED, arguments[i].required, admin->allocator); String* name = String_new(arguments[i].name, admin->allocator); Dict_putDict(fu->args, name, arg, admin->allocator); } }
static void pingResponse(struct RouterModule_Promise* promise, uint32_t lag, struct Address* from, Dict* responseDict) { struct Ping* ping = Identity_check((struct Ping*)promise->userData); struct Allocator* tempAlloc = promise->alloc; Dict* resp = Dict_new(tempAlloc); String* versionBin = Dict_getString(responseDict, CJDHTConstants_VERSION); if (versionBin && versionBin->len == 20) { String* versionStr = String_newBinary(NULL, 40, tempAlloc); Hex_encode(versionStr->bytes, 40, versionBin->bytes, 20); Dict_putString(resp, String_CONST("version"), versionStr, tempAlloc); } else { Dict_putString(resp, String_CONST("version"), String_CONST("unknown"), tempAlloc); } String* result = (responseDict) ? String_CONST("pong") : String_CONST("timeout"); Dict_putString(resp, String_CONST("result"), result, tempAlloc); int64_t* protocolVersion = Dict_getInt(responseDict, CJDHTConstants_PROTOCOL); if (protocolVersion) { Dict_putInt(resp, String_CONST("protocol"), *protocolVersion, tempAlloc); } Dict_putInt(resp, String_CONST("ms"), lag, tempAlloc); if (from) { uint8_t fromStr[60] = ""; Address_print(fromStr, from); Dict_putString(resp, String_CONST("from"), String_new(fromStr, tempAlloc), tempAlloc); } Admin_sendMessage(resp, ping->txid, ping->ctx->admin); }
static void listConnections(Dict* args, void* vcontext, String* txid, struct Allocator* alloc) { struct Context* context = vcontext; List* l = List_new(alloc); for (int i = 0; i < (int)context->ipTun->connectionList.count; i++) { List_addInt(l, context->ipTun->connectionList.connections[i].number, alloc); } Dict* resp = Dict_new(alloc); Dict_putList(resp, String_CONST("connections"), l, alloc); Dict_putString(resp, String_CONST("error"), String_CONST("none"), alloc); Admin_sendMessage(resp, txid, context->admin); }
static void tunInterface(Dict* ifaceConf, struct Allocator* tempAlloc, struct Context* ctx) { String* ifaceType = Dict_getString(ifaceConf, String_CONST("type")); if (!String_equals(ifaceType, String_CONST("TUNInterface"))) { return; } // Setup the interface. String* device = Dict_getString(ifaceConf, String_CONST("tunDevice")); Dict* args = Dict_new(tempAlloc); if (device) { Dict_putString(args, String_CONST("desiredTunName"), device, tempAlloc); } rpcCall0(String_CONST("Core_initTunnel"), args, ctx, tempAlloc, false); }
static void sessionStats(Dict* args, void* vcontext, String* txid, struct Allocator* alloc) { struct Context* context = Identity_check((struct Context*) vcontext); int64_t* handleP = Dict_getInt(args, String_CONST("handle")); uint32_t handle = *handleP; struct SessionManager_Session* session = SessionManager_sessionForHandle(handle, context->sm); Dict* r = Dict_new(alloc); if (!session) { Dict_putString(r, String_CONST("error"), String_CONST("no such session"), alloc); Admin_sendMessage(r, txid, context->admin); return; } uint8_t printedAddr[40]; AddrTools_printIp(printedAddr, session->caSession->herIp6); Dict_putString(r, String_CONST("ip6"), String_new(printedAddr, alloc), alloc); String* state = String_new(CryptoAuth_stateString(CryptoAuth_getState(session->caSession)), alloc); Dict_putString(r, String_CONST("state"), state, alloc); struct ReplayProtector* rp = &session->caSession->replayProtector; Dict_putInt(r, String_CONST("duplicates"), rp->duplicates, alloc); Dict_putInt(r, String_CONST("lostPackets"), rp->lostPackets, alloc); Dict_putInt(r, String_CONST("receivedOutOfRange"), rp->receivedOutOfRange, alloc); struct Address addr; Bits_memcpyConst(addr.key, session->caSession->herPublicKey, 32); addr.path = session->sendSwitchLabel; addr.protocolVersion = session->version; Dict_putString(r, String_CONST("addr"), Address_toString(&addr, alloc), alloc); Dict_putString(r, String_CONST("publicKey"), Key_stringify(session->caSession->herPublicKey, alloc), alloc); Dict_putInt(r, String_CONST("version"), session->version, alloc); Dict_putInt(r, String_CONST("handle"), session->receiveHandle, alloc); Dict_putInt(r, String_CONST("sendHandle"), session->sendHandle, alloc); Dict_putInt(r, String_CONST("timeOfLastIn"), session->timeOfLastIn, alloc); Dict_putInt(r, String_CONST("timeOfLastOut"), session->timeOfLastOut, alloc); Dict_putString(r, String_CONST("deprecation"), String_CONST("publicKey,version will soon be removed"), alloc); Admin_sendMessage(r, txid, context->admin); return; }
static void minSinatures(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct Context* context = vcontext; struct Allocator* alloc = Allocator_child(context->alloc); int64_t* count = Dict_getInt(args, String_CONST("count")); char* err = "none"; if (*count < 0 || *count > INT32_MAX) { err = "count cannot be less than zero or more than INT32_MAX"; } else { context->rainfly->minSignatures = *count; } Dict* response = Dict_new(alloc); Dict_putString(response, String_CONST("error"), String_CONST(err), alloc); Admin_sendMessage(response, txid, context->admin); Allocator_free(alloc); }
List* EncodingScheme_asList(struct EncodingScheme* list, struct Allocator* alloc) { Assert_true(EncodingScheme_isSane(list)); String* prefixLen = String_new("prefixLen", alloc); String* bitCount = String_new("bitCount", alloc); String* prefix = String_new("prefix", alloc); List* scheme = NULL; for (int i = 0; i < (int)list->count; i++) { Dict* form = Dict_new(alloc); Dict_putInt(form, prefixLen, list->forms[i].prefixLen, alloc); Dict_putInt(form, bitCount, list->forms[i].bitCount, alloc); String* pfx = String_newBinary(NULL, 8, alloc); uint32_t prefix_be = Endian_hostToBigEndian32(list->forms[i].prefix); Hex_encode(pfx->bytes, 8, (uint8_t*)&prefix_be, 4); Dict_putString(form, prefix, pfx, alloc); scheme = List_addDict(scheme, form, alloc); } return scheme; }
static void commit(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct RouteGen_admin_Ctx* const ctx = Identity_check((struct RouteGen_admin_Ctx*) vcontext); String* const tunName = Dict_getString(args, String_CONST("tunName")); Dict* const ret = Dict_new(requestAlloc); char* error = "none"; struct Jmp j; Jmp_try(j) { RouteGen_commit(ctx->rg, tunName->bytes, requestAlloc, &j.handler); } Jmp_catch { error = j.message; } Dict_putString(ret, String_new("error", requestAlloc), String_new(error, requestAlloc), requestAlloc); Admin_sendMessage(ret, txid, ctx->admin); }
static void udpInterface(Dict* config, struct Context* ctx) { List* ifaces = Dict_getList(config, String_CONST("UDPInterface")); if (!ifaces) { ifaces = List_new(ctx->alloc); List_addDict(ifaces, Dict_getDict(config, String_CONST("UDPInterface")), ctx->alloc); } uint32_t count = List_size(ifaces); for (uint32_t i = 0; i < count; i++) { Dict *udp = List_getDict(ifaces, i); if (!udp) { continue; } // Setup the interface. String* bindStr = Dict_getString(udp, String_CONST("bind")); Dict* d = Dict_new(ctx->alloc); if (bindStr) { Dict_putString(d, String_CONST("bindAddress"), bindStr, ctx->alloc); } Dict* resp = NULL; rpcCall0(String_CONST("UDPInterface_new"), d, ctx, ctx->alloc, &resp, true); int ifNum = *(Dict_getInt(resp, String_CONST("interfaceNumber"))); // Make the connections. Dict* connectTo = Dict_getDict(udp, String_CONST("connectTo")); if (connectTo) { struct Dict_Entry* entry = *connectTo; struct Allocator* perCallAlloc = Allocator_child(ctx->alloc); while (entry != NULL) { String* key = (String*) entry->key; if (entry->val->type != Object_DICT) { Log_critical(ctx->logger, "interfaces.UDPInterface.connectTo: entry [%s] " "is not a dictionary type.", key->bytes); exit(-1); } Dict* all = entry->val->as.dictionary; Dict* value = Dict_new(perCallAlloc); String* pub_d = Dict_getString(all, String_CONST("publicKey")); String* pss_d = Dict_getString(all, String_CONST("password")); String* peerName_d = Dict_getString(all, String_CONST("peerName")); String* login_d = Dict_getString(all, String_CONST("login")); if ( !pub_d || !pss_d ) { const char * error_name = "(unknown)"; if ( !pub_d ) { error_name = "publicKey"; } if ( !pss_d ) { error_name = "password"; } Log_warn(ctx->logger, "Skipping peer: missing %s for peer [%s]", error_name, key->bytes); if (abort_if_invalid_ref) { Assert_failure("Invalid peer reference"); } else { entry = entry->next; continue; } } Dict_putString(value, String_CONST("publicKey"), pub_d, perCallAlloc); Dict_putString(value, String_CONST("password"), pss_d, perCallAlloc); Dict_putString(value, String_CONST("peerName"), peerName_d, perCallAlloc); Dict_putString(value, String_CONST("login"), login_d, perCallAlloc); Log_keys(ctx->logger, "Attempting to connect to node [%s].", key->bytes); key = String_clone(key, perCallAlloc); char* lastColon = CString_strrchr(key->bytes, ':'); if (!Sockaddr_parse(key->bytes, NULL)) { // it's a sockaddr, fall through } else if (lastColon) { // try it as a hostname. int port = atoi(lastColon+1); if (!port) { Log_critical(ctx->logger, "Couldn't get port number from [%s]", key->bytes); exit(-1); } *lastColon = '\0'; struct Sockaddr* adr = Sockaddr_fromName(key->bytes, perCallAlloc); if (adr != NULL) { Sockaddr_setPort(adr, port); key = String_new(Sockaddr_print(adr, perCallAlloc), perCallAlloc); } else { Log_warn(ctx->logger, "Failed to lookup hostname [%s]", key->bytes); entry = entry->next; continue; } } struct Allocator* child = Allocator_child(ctx->alloc); struct Message* msg = Message_new(0, AdminClient_MAX_MESSAGE_SIZE + 256, child); int r = BencMessageWriter_writeDictTry(value, msg, NULL); const int max_reference_size = 298; if (r != 0 || msg->length > max_reference_size) { Log_warn(ctx->logger, "Peer skipped:"); Log_warn(ctx->logger, "Too long peer reference for [%s]", key->bytes); if (abort_if_invalid_ref) { Assert_failure("Invalid peer reference"); } else { entry = entry->next; continue; } } Dict_putInt(value, String_CONST("interfaceNumber"), ifNum, perCallAlloc); Dict_putString(value, String_CONST("address"), key, perCallAlloc); rpcCall(String_CONST("UDPInterface_beginConnection"), value, ctx, perCallAlloc); entry = entry->next; } Allocator_free(perCallAlloc); } } }
static void adminPeerStats(Dict* args, void* vcontext, String* txid, struct Allocator* alloc) { struct Context* context = Identity_check((struct Context*)vcontext); struct InterfaceController_PeerStats* stats = NULL; int64_t* page = Dict_getInt(args, String_CONST("page")); int i = (page) ? *page * ENTRIES_PER_PAGE : 0; int count = InterfaceController_getPeerStats(context->ic, alloc, &stats); String* bytesIn = String_CONST("bytesIn"); String* bytesOut = String_CONST("bytesOut"); String* pubKey = String_CONST("publicKey"); String* addr = String_CONST("addr"); String* state = String_CONST("state"); String* last = String_CONST("last"); String* switchLabel = String_CONST("switchLabel"); String* isIncoming = String_CONST("isIncoming"); String* user = String_CONST("user"); String* version = String_CONST("version"); String* duplicates = String_CONST("duplicates"); String* lostPackets = String_CONST("lostPackets"); String* receivedOutOfRange = String_CONST("receivedOutOfRange"); List* list = List_new(alloc); for (int counter=0; i < count && counter++ < ENTRIES_PER_PAGE; i++) { Dict* d = Dict_new(alloc); Dict_putInt(d, bytesIn, stats[i].bytesIn, alloc); Dict_putInt(d, bytesOut, stats[i].bytesOut, alloc); Dict_putString(d, addr, Address_toString(&stats[i].addr, alloc), alloc); Dict_putString(d, pubKey, Key_stringify(stats[i].addr.key, alloc), alloc); String* stateString = String_new(InterfaceController_stateString(stats[i].state), alloc); Dict_putString(d, state, stateString, alloc); Dict_putInt(d, last, stats[i].timeOfLastMessage, alloc); uint8_t labelStack[20]; AddrTools_printPath(labelStack, stats[i].addr.path); Dict_putString(d, switchLabel, String_new((char*)labelStack, alloc), alloc); Dict_putInt(d, isIncoming, stats[i].isIncomingConnection, alloc); Dict_putInt(d, duplicates, stats[i].duplicates, alloc); Dict_putInt(d, lostPackets, stats[i].lostPackets, alloc); Dict_putInt(d, receivedOutOfRange, stats[i].receivedOutOfRange, alloc); if (stats[i].user) { Dict_putString(d, user, stats[i].user, alloc); } uint8_t address[16]; AddressCalc_addressForPublicKey(address, stats[i].addr.key); Dict_putInt(d, version, stats[i].addr.protocolVersion, alloc); List_addDict(list, d, alloc); } Dict* resp = Dict_new(alloc); Dict_putList(resp, String_CONST("peers"), list, alloc); Dict_putInt(resp, String_CONST("total"), count, alloc); if (i < count) { Dict_putInt(resp, String_CONST("more"), 1, alloc); } Dict_putString(resp, String_CONST("deprecation"), String_CONST("publicKey,switchLabel,version will soon be removed"), alloc); Admin_sendMessage(resp, txid, context->admin); }
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(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; }
static void ipTunnel(Dict* ifaceConf, struct Allocator* tempAlloc, struct Context* ctx) { List* incoming = Dict_getList(ifaceConf, String_CONST("allowedConnections")); if (incoming) { Dict* d; for (int i = 0; (d = List_getDict(incoming, i)) != NULL; i++) { String* key = Dict_getString(d, String_CONST("publicKey")); String* ip4 = Dict_getString(d, String_CONST("ip4Address")); // Note that the prefix length has to be a proper int in the config // (not quoted!) int64_t* ip4Prefix = Dict_getInt(d, String_CONST("ip4Prefix")); String* ip6 = Dict_getString(d, String_CONST("ip6Address")); int64_t* ip6Prefix = Dict_getInt(d, String_CONST("ip6Prefix")); if (!key) { Log_critical(ctx->logger, "In router.ipTunnel.allowedConnections[%d]" "'publicKey' required.", i); exit(1); } if (!ip4 && !ip6) { Log_critical(ctx->logger, "In router.ipTunnel.allowedConnections[%d]" "either 'ip4Address' or 'ip6Address' required.", i); exit(1); } else if (ip4Prefix && !ip4) { Log_critical(ctx->logger, "In router.ipTunnel.allowedConnections[%d]" "'ip4Address' required with 'ip4Prefix'.", i); exit(1); } else if (ip6Prefix && !ip6) { Log_critical(ctx->logger, "In router.ipTunnel.allowedConnections[%d]" "'ip6Address' required with 'ip6Prefix'.", i); exit(1); } Log_debug(ctx->logger, "Allowing IpTunnel connections from [%s]", key->bytes); if (ip4) { Log_debug(ctx->logger, "Issue IPv4 address %s", ip4->bytes); if (ip4Prefix) { Log_debug(ctx->logger, "Issue IPv4 netmask/prefix length /%d", (int) *ip4Prefix); } else { Log_debug(ctx->logger, "Use default netmask/prefix length /0"); } } if (ip6) { Log_debug(ctx->logger, "Issue IPv6 address [%s]", ip6->bytes); if (ip6Prefix) { Log_debug(ctx->logger, "Issue IPv6 netmask/prefix length /%d", (int) *ip6Prefix); } else { Log_debug(ctx->logger, "Use default netmask/prefix length /0"); } } Dict_putString(d, String_CONST("publicKeyOfAuthorizedNode"), key, tempAlloc); rpcCall0(String_CONST("IpTunnel_allowConnection"), d, ctx, tempAlloc, NULL, true); } } List* outgoing = Dict_getList(ifaceConf, String_CONST("outgoingConnections")); if (outgoing) { String* s; for (int i = 0; (s = List_getString(outgoing, i)) != NULL; i++) { Log_debug(ctx->logger, "Initiating IpTunnel connection to [%s]", s->bytes); Dict requestDict = Dict_CONST(String_CONST("publicKeyOfNodeToConnectTo"), String_OBJ(s), NULL); rpcCall0(String_CONST("IpTunnel_connectTo"), &requestDict, ctx, tempAlloc, NULL, true); } } }
static void ethInterface(Dict* config, struct Context* ctx) { List* ifaces = Dict_getList(config, String_CONST("ETHInterface")); if (!ifaces) { ifaces = List_new(ctx->alloc); List_addDict(ifaces, Dict_getDict(config, String_CONST("ETHInterface")), ctx->alloc); } uint32_t count = List_size(ifaces); for (uint32_t i = 0; i < count; i++) { Dict *eth = List_getDict(ifaces, i); if (!eth) { continue; } String* deviceStr = Dict_getString(eth, String_CONST("bind")); if (!deviceStr || !String_equals(String_CONST("all"), deviceStr)) { continue; } Log_info(ctx->logger, "Setting up all ETHInterfaces..."); Dict* res = NULL; Dict* d = Dict_new(ctx->alloc); if (rpcCall0(String_CONST("ETHInterface_listDevices"), d, ctx, ctx->alloc, &res, false)) { Log_info(ctx->logger, "Getting device list failed"); break; } List* devs = Dict_getList(res, String_CONST("devices")); uint32_t devCount = List_size(devs); for (uint32_t j = 0; j < devCount; j++) { Dict* d = Dict_new(ctx->alloc); String* deviceName = List_getString(devs, j); // skip loopback... if (String_equals(String_CONST("lo"), deviceName)) { continue; } Dict_putString(d, String_CONST("bindDevice"), deviceName, ctx->alloc); Dict* resp; Log_info(ctx->logger, "Creating new ETHInterface [%s]", deviceName->bytes); if (rpcCall0(String_CONST("ETHInterface_new"), d, ctx, ctx->alloc, &resp, false)) { Log_warn(ctx->logger, "Failed to create ETHInterface."); continue; } int ifNum = *(Dict_getInt(resp, String_CONST("interfaceNumber"))); ethInterfaceSetBeacon(ifNum, eth, ctx); } return; } for (uint32_t i = 0; i < count; i++) { Dict *eth = List_getDict(ifaces, i); if (!eth) { continue; } // Setup the interface. String* deviceStr = Dict_getString(eth, String_CONST("bind")); Log_info(ctx->logger, "Setting up ETHInterface [%d].", i); Dict* d = Dict_new(ctx->alloc); if (deviceStr) { Log_info(ctx->logger, "Binding to device [%s].", deviceStr->bytes); Dict_putString(d, String_CONST("bindDevice"), deviceStr, ctx->alloc); } Dict* resp = NULL; if (rpcCall0(String_CONST("ETHInterface_new"), d, ctx, ctx->alloc, &resp, false)) { Log_warn(ctx->logger, "Failed to create ETHInterface."); continue; } int ifNum = *(Dict_getInt(resp, String_CONST("interfaceNumber"))); ethInterfaceSetBeacon(ifNum, eth, ctx); // Make the connections. Dict* connectTo = Dict_getDict(eth, String_CONST("connectTo")); if (connectTo) { Log_info(ctx->logger, "ETHInterface should connect to a specific node."); struct Dict_Entry* entry = *connectTo; while (entry != NULL) { String* key = (String*) entry->key; if (entry->val->type != Object_DICT) { Log_critical(ctx->logger, "interfaces.ETHInterface.connectTo: entry [%s] " "is not a dictionary type.", key->bytes); exit(-1); } Dict* value = entry->val->as.dictionary; Log_keys(ctx->logger, "Attempting to connect to node [%s].", key->bytes); struct Allocator* perCallAlloc = Allocator_child(ctx->alloc); // Turn the dict from the config into our RPC args dict by filling in all // the arguments, Dict_putString(value, String_CONST("macAddress"), key, perCallAlloc); Dict_putInt(value, String_CONST("interfaceNumber"), ifNum, perCallAlloc); rpcCall(String_CONST("ETHInterface_beginConnection"), value, ctx, perCallAlloc); Allocator_free(perCallAlloc); entry = entry->next; } } } }
static void security(struct Allocator* tempAlloc, List* conf, struct Log* log, struct Context* ctx) { int seccomp = 1; int nofiles = 0; int noforks = 1; int chroot = 1; int setupComplete = 1; int setuser = 1; if (Defined(win32)) { setuser = 0; } int uid = -1; int64_t* group = NULL; int keepNetAdmin = 1; do { Dict* d = Dict_new(tempAlloc); Dict_putString(d, String_CONST("user"), String_CONST("nobody"), tempAlloc); if (!Defined(win32)) { Dict* ret = NULL; rpcCall0(String_CONST("Security_getUser"), d, ctx, tempAlloc, &ret, true); uid = *Dict_getInt(ret, String_CONST("uid")); group = Dict_getInt(ret, String_CONST("gid")); } } while (0); for (int i = 0; conf && i < List_size(conf); i++) { Dict* elem = List_getDict(conf, i); String* s; if (elem && (s = Dict_getString(elem, String_CONST("setuser")))) { if (setuser == 0) { continue; } Dict* d = Dict_new(tempAlloc); Dict_putString(d, String_CONST("user"), s, tempAlloc); Dict* ret = NULL; rpcCall0(String_CONST("Security_getUser"), d, ctx, tempAlloc, &ret, true); uid = *Dict_getInt(ret, String_CONST("uid")); group = Dict_getInt(ret, String_CONST("gid")); int64_t* nka = Dict_getInt(elem, String_CONST("keepNetAdmin")); int64_t* exemptAngel = Dict_getInt(elem, String_CONST("exemptAngel")); keepNetAdmin = ((nka) ? *nka : ((exemptAngel) ? *exemptAngel : 0)); continue; } if (elem && (s = Dict_getString(elem, String_CONST("chroot")))) { Log_debug(log, "Security_chroot(%s)", s->bytes); Dict* d = Dict_new(tempAlloc); Dict_putString(d, String_CONST("root"), s, tempAlloc); rpcCall0(String_CONST("Security_chroot"), d, ctx, tempAlloc, NULL, false); chroot = 0; continue; } uint64_t* x; if (elem && (x = Dict_getInt(elem, String_CONST("nofiles")))) { if (!*x) { continue; } nofiles = 1; continue; } if (elem && (x = Dict_getInt(elem, String_CONST("setuser")))) { if (!*x) { setuser = 0; } continue; } if (elem && (x = Dict_getInt(elem, String_CONST("seccomp")))) { if (!*x) { seccomp = 0; } continue; } if (elem && (x = Dict_getInt(elem, String_CONST("noforks")))) { if (!*x) { noforks = 0; } continue; } if (elem && (x = Dict_getInt(elem, String_CONST("chroot")))) { if (!*x) { chroot = 0; } continue; } if (elem && (x = Dict_getInt(elem, String_CONST("setupComplete")))) { if (!*x) { setupComplete = 0; } continue; } Log_info(ctx->logger, "Unrecognized entry in security at index [%d]", i); } if (chroot) { Log_debug(log, "Security_chroot(/var/run)"); Dict* d = Dict_new(tempAlloc); Dict_putString(d, String_CONST("root"), String_CONST("/var/run/"), tempAlloc); rpcCall0(String_CONST("Security_chroot"), d, ctx, tempAlloc, NULL, false); } /* FIXME(sdg): moving noforks after setuser might make nproc <- 0,0 work on older kernels, where doing it before causes setuid to fail w EAGAIN. */ if (noforks) { Log_debug(log, "Security_noforks()"); Dict* d = Dict_new(tempAlloc); rpcCall(String_CONST("Security_noforks"), d, ctx, tempAlloc); } if (setuser) { Log_debug(log, "Security_setUser(uid:%d, keepNetAdmin:%d)", uid, keepNetAdmin); Dict* d = Dict_new(tempAlloc); Dict_putInt(d, String_CONST("uid"), uid, tempAlloc); if (group) { Dict_putInt(d, String_CONST("gid"), (int)*group, tempAlloc); } Dict_putInt(d, String_CONST("keepNetAdmin"), keepNetAdmin, tempAlloc); rpcCall0(String_CONST("Security_setUser"), d, ctx, tempAlloc, NULL, false); } if (nofiles) { Log_debug(log, "Security_nofiles()"); Dict* d = Dict_new(tempAlloc); rpcCall(String_CONST("Security_nofiles"), d, ctx, tempAlloc); } if (seccomp) { Log_debug(log, "Security_seccomp()"); Dict* d = Dict_new(tempAlloc); rpcCall(String_CONST("Security_seccomp"), d, ctx, tempAlloc); } if (setupComplete) { Log_debug(log, "Security_setupComplete()"); Dict* d = Dict_new(tempAlloc); rpcCall(String_CONST("Security_setupComplete"), d, ctx, tempAlloc); } }