Exemplo n.º 1
0
Arquivo: Core.c Projeto: AdUser/cjdns
static void adminExit(Dict* input, void* vcontext, String* txid, struct Allocator* requestAlloc)
{
    struct Context* context = vcontext;
    Log_info(context->logger, "Got request to exit");
    Log_info(context->logger, "Stopping angel");
    context->exitTxid = String_clone(txid, context->allocator);
    Dict angelExit = Dict_CONST(String_CONST("q"), String_OBJ(String_CONST("Angel_exit")), NULL);
    Hermes_callAngel(&angelExit,
                     onAngelExitResponse,
                     context,
                     context->allocator,
                     NULL,
                     context->hermes);
}
Exemplo n.º 2
0
static void newInterface(Dict* args, void* vcontext, String* txid)
{
    struct Context* ctx = vcontext;
    String* bindAddress = Dict_getString(args, String_CONST("bindAddress"));
    struct Sockaddr_storage addr;
    if (Sockaddr_parse((bindAddress) ? bindAddress->bytes : "0.0.0.0", &addr)) {
        Dict out = Dict_CONST(
            String_CONST("error"), String_OBJ(String_CONST("Failed to parse address")), NULL
        );
        Admin_sendMessage(&out, txid, ctx->admin);
        return;
    }
    newInterface2(ctx, &addr.addr, txid);
}
Exemplo n.º 3
0
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"));
        if (!user) {
          user = String_printf(child, "password [%d]", i);
        }

        Log_info(ctx->logger, "Adding authorized password #[%d] for user [%s].", i, user->bytes);

        Dict args = Dict_CONST(
            String_CONST("authType"), Int_OBJ(1), Dict_CONST(
            String_CONST("password"), String_OBJ(passwd), Dict_CONST(
            String_CONST("user"), String_OBJ(user), NULL
        )));
        rpcCall(String_CONST("AuthorizedPasswords_add"), &args, ctx, child);
        Allocator_free(child);
    }
}
Exemplo n.º 4
0
static void listConnections(Dict* args, void* vcontext, String* txid)
{
    struct Context* context = vcontext;
    struct Allocator* alloc;
    BufferAllocator_STACK(alloc, 1024);
    List* l = NULL;
    for (int i = 0; i < (int)context->ipTun->connectionList.count; i++) {
        l = List_addInt(l, context->ipTun->connectionList.connections[i].number, alloc);
    }
    Dict resp = Dict_CONST(
        String_CONST("connections"), List_OBJ(l), Dict_CONST(
        String_CONST("error"), String_OBJ(String_CONST("none")), NULL
    ));
    Admin_sendMessage(&resp, txid, context->admin);
}
Exemplo n.º 5
0
static void beginConnection(Dict* args, void* vcontext, String* txid)
{
    struct Context* ctx = vcontext;

    String* password = Dict_getString(args, String_CONST("password"));
    String* publicKey = Dict_getString(args, String_CONST("publicKey"));
    String* address = Dict_getString(args, String_CONST("address"));
    int64_t* interfaceNumber = Dict_getInt(args, String_CONST("interfaceNumber"));
    uint32_t ifNum = (interfaceNumber) ? ((uint32_t) *interfaceNumber) : 0;
    String* error = NULL;

    uint8_t pkBytes[32];
    int ret;
    if (ctx->ifCount == 0) {
        error = String_CONST("no interfaces are setup, call UDPInterface_new() first");

    } else if (interfaceNumber && (*interfaceNumber >= ctx->ifCount || *interfaceNumber < 0)) {
        error = String_CONST("invalid interfaceNumber");

    } else if ((ret = Key_parse(publicKey, pkBytes, NULL))) {
        error = String_CONST(Key_parse_strerror(ret));

    } else {
        struct UDPInterface* udpif = ctx->ifaces[ifNum];
        switch (UDPInterface_beginConnection(address->bytes, pkBytes, password, udpif)) {
            case UDPInterface_beginConnection_OUT_OF_SPACE:
                error = String_CONST("no more space to register with the switch.");
                break;
            case UDPInterface_beginConnection_BAD_KEY:
                error = String_CONST("invalid cjdns public key.");
                break;
            case UDPInterface_beginConnection_BAD_ADDRESS:
                error = String_CONST("unable to parse ip address and port.");
                break;
            case UDPInterface_beginConnection_ADDRESS_MISMATCH:
                error = String_CONST("different address type than this socket is bound to.");
                break;
            case 0:
                error = String_CONST("none");
                break;
            default:
                error = String_CONST("unknown error");
        }
    }

    Dict out = Dict_CONST(String_CONST("error"), String_OBJ(error), NULL);
    Admin_sendMessage(&out, txid, ctx->admin);
}
Exemplo n.º 6
0
static void supernodes(List* supernodes, struct Allocator* tempAlloc, struct Context* ctx)
{
    if (!supernodes) {
        return;
    }
    String* s;
    for (int i = 0; (s = List_getString(supernodes, i)) != NULL; i++) {
        Log_debug(ctx->logger, "Loading supernode connection to [%s]", s->bytes);
        Dict reqDict = Dict_CONST(String_CONST("key"), String_OBJ(s), NULL);
        if (!Defined(SUBNODE)) {
            Log_debug(ctx->logger, "Skipping because SUBNODE is not enabled");
            continue;
        }
        rpcCall0(String_CONST("SupernodeHunter_addSnode"), &reqDict, ctx, tempAlloc, NULL, true);
    }
}
Exemplo n.º 7
0
static void security(List* securityConf, struct Allocator* tempAlloc, struct Context* ctx)
{
    bool noFiles = false;
    for (int i = 0; i < List_size(securityConf); i++) {
        if (String_equals(String_CONST("nofiles"), List_getString(securityConf, i))) {
            noFiles = true;
        } else {
            Dict* userDict = List_getDict(securityConf, i);
            String* userName = Dict_getString(userDict, String_CONST("setuser"));
            if (userName) {
                Dict d = Dict_CONST(String_CONST("user"), String_OBJ(userName), NULL);
                // If this call returns an error, it is ok.
                rpcCall0(String_CONST("Security_setUser"), &d, ctx, tempAlloc, false);
            }
        }
    }
    if (noFiles) {
        Dict d = NULL;
        rpcCall(String_CONST("Security_noFiles"), &d, ctx, tempAlloc);
    }
}
Exemplo n.º 8
0
static void unsubscribe(Dict* args, void* vcontext, String* txid)
{
    struct AdminLog* log = (struct AdminLog*) vcontext;
    String* streamIdHex = Dict_getString(args, String_CONST("streamId"));
    uint8_t streamId[8];
    char* error = NULL;
    if (streamIdHex->len != 16 || Hex_decode(streamId, 8, (uint8_t*)streamIdHex->bytes, 16) != 8) {
        error = "Invalid streamId.";
    } else {
        error = "No such subscription.";
        for (int i = 0; i < (int)log->subscriptionCount; i++) {
            if (!Bits_memcmp(streamId, log->subscriptions[i].streamId, 8)) {
                removeSubscription(log, &log->subscriptions[i]);
                error = "none";
                break;
            }
        }
    }

    Dict response = Dict_CONST(
        String_CONST("error"), String_OBJ(String_CONST(error)), NULL
    );
    Admin_sendMessage(&response, txid, log->admin);
}
Exemplo n.º 9
0
static struct Address* getNode(String* pathStr,
                               struct Context* ctx,
                               char** errOut,
                               struct Allocator* alloc)
{
    struct Address addr = {.path=0};

    if (pathStr->len == 19 && !AddrTools_parsePath(&addr.path, pathStr->bytes)) {
        struct Node_Link* nl = Router_linkForPath(ctx->router, addr.path);
        if (!nl) {
            *errOut = "not_found";
            return NULL;
        } else {
            Bits_memcpyConst(&addr, &nl->child->address, sizeof(struct Address));
        }
    } else if (pathStr->len == 39 && !AddrTools_parseIp(addr.ip6.bytes, pathStr->bytes)) {
        struct Node_Two* n = Router_lookup(ctx->router, addr.ip6.bytes);
        if (!n || Bits_memcmp(addr.ip6.bytes, n->address.ip6.bytes, 16)) {
            *errOut = "not_found";
            return NULL;
        } else {
            Bits_memcpyConst(&addr, &n->address, sizeof(struct Address));
        }
    } else {
        struct Address* a = Address_fromString(pathStr, alloc);
        if (a) { return a; }
        *errOut = "parse_path";
        return NULL;
    }

    return Allocator_clone(alloc, &addr);
}

static void pingNode(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
{
    struct Context* ctx = Identity_check((struct Context*) vctx);
    String* pathStr = Dict_getString(args, String_CONST("path"));
    int64_t* timeoutPtr = Dict_getInt(args, String_CONST("timeout"));
    uint32_t timeout = (timeoutPtr && *timeoutPtr > 0) ? *timeoutPtr : 0;

    char* err = NULL;
    struct Address* addr = getNode(pathStr, ctx, &err, requestAlloc);

    if (err) {
        Dict errDict = Dict_CONST(String_CONST("error"), String_OBJ(String_CONST(err)), NULL);
        Admin_sendMessage(&errDict, txid, ctx->admin);
        return;
    }

    struct RouterModule_Promise* rp =
        RouterModule_pingNode(addr, timeout, ctx->module, ctx->allocator);
    struct Ping* ping = Allocator_calloc(rp->alloc, sizeof(struct Ping), 1);
    Identity_set(ping);
    ping->txid = String_clone(txid, rp->alloc);
    ping->rp = rp;
    ping->ctx = ctx;
    rp->userData = ping;
    rp->callback = pingResponse;
}

static void getPeers(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
{
    struct Context* ctx = Identity_check((struct Context*) vctx);
    String* nearbyLabelStr = Dict_getString(args, String_CONST("nearbyPath"));
    String* pathStr = Dict_getString(args, String_CONST("path"));
    int64_t* timeoutPtr = Dict_getInt(args, String_CONST("timeout"));
    uint32_t timeout = (timeoutPtr && *timeoutPtr > 0) ? *timeoutPtr : 0;

    char* err = NULL;
    struct Address* addr = getNode(pathStr, ctx, &err, requestAlloc);

    uint64_t nearbyLabel = 0;
    if (!err && nearbyLabelStr) {
        if (nearbyLabelStr->len != 19 || AddrTools_parsePath(&nearbyLabel, nearbyLabelStr->bytes)) {
            err = "parse_nearbyLabel";
        }
    }

    if (err) {
        Dict errDict = Dict_CONST(String_CONST("error"), String_OBJ(String_CONST(err)), NULL);
        Admin_sendMessage(&errDict, txid, ctx->admin);
        return;
    }

    struct RouterModule_Promise* rp =
        RouterModule_getPeers(addr, nearbyLabel, timeout, ctx->module, ctx->allocator);

    struct Ping* ping = Allocator_calloc(rp->alloc, sizeof(struct Ping), 1);
    Identity_set(ping);
    ping->txid = String_clone(txid, rp->alloc);
    ping->rp = rp;
    ping->ctx = ctx;
    rp->userData = ping;
    rp->callback = getPeersResponse;
}

static void findNode(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
{
    struct Context* ctx = Identity_check((struct Context*) vctx);
    String* nodeToQueryStr = Dict_getString(args, String_CONST("nodeToQuery"));
    String* targetStr = Dict_getString(args, String_CONST("target"));
    int64_t* timeoutPtr = Dict_getInt(args, String_CONST("timeout"));
    uint32_t timeout = (timeoutPtr && *timeoutPtr > 0) ? *timeoutPtr : 0;

    char* err = NULL;
    struct Address* nodeToQuery = getNode(nodeToQueryStr, ctx, &err, requestAlloc);
    uint8_t target[16];

    if (!err) {
        if (targetStr->len != 39 || AddrTools_parseIp(target, targetStr->bytes)) {
            err = "parse_target";
        }
    }

    if (err) {
        Dict errDict = Dict_CONST(String_CONST("error"), String_OBJ(String_CONST(err)), NULL);
        Admin_sendMessage(&errDict, txid, ctx->admin);
        return;
    }

    struct RouterModule_Promise* rp =
        RouterModule_findNode(nodeToQuery, target, timeout, ctx->module, ctx->allocator);

    struct Ping* ping = Allocator_calloc(rp->alloc, sizeof(struct Ping), 1);
    Identity_set(ping);
    ping->txid = String_clone(txid, rp->alloc);
    ping->rp = rp;
    ping->ctx = ctx;
    rp->userData = ping;
    rp->callback = findNodeResponse;
}

void RouterModule_admin_register(struct RouterModule* module,
                                 struct Router* router,
                                 struct Admin* admin,
                                 struct Allocator* alloc)
{
    // for improved reporting
    alloc = Allocator_child(alloc);
    struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
        .admin = admin,
        .allocator = alloc,
        .module = module,
        .router = router
    }));
Exemplo n.º 10
0
/** @return a string representing the address and port to connect to. */
static String* initAngel(int fromAngel,
                         int toAngel,
                         int corePipes[2][2],
                         struct PipeInterface** piOut,
                         struct EventBase* eventBase,
                         struct Log* logger,
                         struct Allocator* alloc,
                         struct Random* rand)
{
    #define TO_CORE (corePipes[0][1])
    #define FROM_CORE (corePipes[1][0])
    #define TO_ANGEL_AS_CORE (corePipes[1][1])
    #define FROM_ANGEL_AS_CORE (corePipes[0][0])

    Dict core = Dict_CONST(
        String_CONST("fromCore"), Int_OBJ(FROM_CORE), Dict_CONST(
        String_CONST("toCore"), Int_OBJ(TO_CORE), NULL
    ));
    Dict admin = Dict_CONST(
        String_CONST("bind"), String_OBJ(String_CONST("127.0.0.1")), Dict_CONST(
        String_CONST("core"), Dict_OBJ(&core), Dict_CONST(
        String_CONST("pass"), String_OBJ(String_CONST("abcd")), NULL
    )));
    Dict message = Dict_CONST(
        String_CONST("admin"), Dict_OBJ(&admin), NULL
    );

    struct Allocator* tempAlloc;
    BufferAllocator_STACK(tempAlloc, 1024);

    #define BUFFER_SZ 1023
    uint8_t buff[BUFFER_SZ + 1] = {0};
    struct Writer* w = ArrayWriter_new(buff, BUFFER_SZ, tempAlloc);
    StandardBencSerializer_get()->serializeDictionary(w, &message);

    Log_info(logger, "Writing intial configuration to angel on [%d] config: [%s]", toAngel, buff);
    write(toAngel, buff, w->bytesWritten(w));

    // This is angel->core data, we can throw this away.
    //Waiter_getData(buff, BUFFER_SZ, fromAngel, eventBase, NULL);
    //Log_info(logger, "Init message from angel to core: [%s]", buff);
    Bits_memset(buff, 0, BUFFER_SZ);

    struct PipeInterface* pi =
        PipeInterface_new(FROM_ANGEL_AS_CORE, TO_ANGEL_AS_CORE, eventBase, logger, alloc, rand);
    *piOut = pi;

    Log_info(logger, "PipeInterface [%p] is now ready.", (void*)pi);

    // Make sure the angel sends data to the core.
    InterfaceWaiter_waitForData(&pi->generic, eventBase, alloc, NULL);

    // Send response on behalf of core.
    char coreToAngelResponse[128] = "           PADDING              "
        "\xff\xff\xff\xff"
        "d"
          "5:error" "4:none"
        "e";

    char* start = strchr(coreToAngelResponse, '\xff');
    struct Message m = {
        .bytes = (uint8_t*) start,
        .length = strlen(start),
        .padding = start - coreToAngelResponse
    };
    pi->generic.sendMessage(&m, &pi->generic);

    // This is angel->client data, it will tell us which port was bound.
    Waiter_getData(buff, BUFFER_SZ, fromAngel, eventBase, NULL);

    printf("Response from angel to client: [%s]\n", buff);

    struct Reader* reader = ArrayReader_new(buff, BUFFER_SZ, tempAlloc);
    Dict configStore;
    Dict* config = &configStore;
    Assert_true(!StandardBencSerializer_get()->parseDictionary(reader, tempAlloc, config));

    Dict* responseAdmin = Dict_getDict(config, String_CONST("admin"));
    String* bind = Dict_getString(responseAdmin, String_CONST("bind"));
    Assert_true(bind);

    return String_clone(bind, alloc);
}

/**
 * This spawns itself as the Angel process which spawns itself again as the core process.
 * The "core process" pipes all of its inputs back to the originating process
 */

struct AdminTestFramework* AdminTestFramework_setUp(int argc, char** argv)
{
    if (argc > 1 && !strcmp("angel", argv[1])) {
        exit(AngelInit_main(argc, argv));
    }

    struct Allocator* alloc = CanaryAllocator_new(MallocAllocator_new(1<<20), NULL);

    struct Writer* logwriter = FileWriter_new(stdout, alloc);
    Assert_always(logwriter);
    struct Log* logger = WriterLog_new(logwriter, alloc);

    struct EventBase* eventBase = EventBase_new(alloc);
    struct Random* rand = Random_new(alloc, NULL);

    int fromAngel;
    int toAngel;
    int corePipes[2][2];
    if (Pipe_createUniPipe(corePipes[0]) || Pipe_createUniPipe(corePipes[1])) {
        Except_raise(NULL, -1, "Failed to create pipes [%s]", Errno_getString());
    }
    spawnAngel(&fromAngel, &toAngel);

    struct PipeInterface* pi;
    String* addrStr =
        initAngel(fromAngel, toAngel, corePipes, &pi, eventBase, logger, alloc, rand);

    Log_info(logger, "Angel initialized.");

    String* password = String_new("abcd", alloc);
    struct Admin* admin =
        Admin_new(&pi->generic, alloc, logger, eventBase, password);


    // Now setup the client.

    struct sockaddr_storage addr;
    int addrLen = sizeof(struct sockaddr_storage);
    Bits_memset(&addr, 0, sizeof(struct sockaddr_storage));
    Assert_true(!evutil_parse_sockaddr_port(addrStr->bytes, (struct sockaddr*) &addr, &addrLen));

    struct AdminClient* client =
        AdminClient_new((uint8_t*) &addr, addrLen, password, eventBase, logger, alloc);

    Assert_always(client);

    return alloc->clone(sizeof(struct AdminTestFramework), alloc, &(struct AdminTestFramework) {
        .admin = admin,
        .client = client,
        .alloc = alloc,
        .eventBase = eventBase,
        .logger = logger,
        .addr = alloc->clone(addrLen, alloc, &addr),
        .addrLen = addrLen,
        .angelInterface = &pi->generic
    });
}
Exemplo n.º 11
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);
        }
    }
}
Exemplo n.º 12
0
static void sendError(char* errorMessage, String* txid, struct Admin* admin)
{
    Dict error = Dict_CONST(String_CONST("error"), String_OBJ(String_CONST(errorMessage)), NULL);
    Admin_sendMessage(&error, txid, admin);
}
Exemplo n.º 13
0
static void adminPing(Dict* input, void* vadmin, String* txid)
{
    Dict d = Dict_CONST(String_CONST("q"), String_OBJ(String_CONST("pong")), NULL);
    Admin_sendMessage(&d, txid, (struct Admin*) vadmin);
}
Exemplo n.º 14
0
static void pingNode(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
{
    struct Context* ctx = Identity_cast((struct Context*) vctx);
    String* pathStr = Dict_getString(args, String_CONST("path"));
    int64_t* timeoutPtr = Dict_getInt(args, String_CONST("timeout"));
    uint32_t timeout = (timeoutPtr && *timeoutPtr > 0) ? *timeoutPtr : 0;

    char* err = NULL;

    struct Address addr = {.path=0};
    struct Node* n = NULL;

    if (pathStr->len == 19 && !AddrTools_parsePath(&addr.path, (uint8_t*) pathStr->bytes)) {
        n = RouterModule_getNode(addr.path, ctx->router);
    } else if (!AddrTools_parseIp(addr.ip6.bytes, (uint8_t*) pathStr->bytes)) {
        n = RouterModule_lookup(addr.ip6.bytes, ctx->router);
        if (n && Bits_memcmp(addr.ip6.bytes, n->address.ip6.bytes, 16)) {
            n = NULL;
        }
    } else {
        err = "Unexpected address, must be either an ipv6 address "
              "eg: 'fc4f:d:e499:8f5b:c49f:6e6b:1ae:3120', 19 char path eg: '0123.4567.89ab.cdef'";
    }

    if (!err) {
        if (!n) {
            err = "could not find node to ping";
        } else {
            struct RouterModule_Promise* rp =
                RouterModule_pingNode(n, timeout, ctx->router, ctx->allocator);
            struct Ping* ping = Allocator_calloc(rp->alloc, sizeof(struct Ping), 1);
            Identity_set(ping);
            ping->txid = String_clone(txid, rp->alloc);
            ping->rp = rp;
            ping->ctx = ctx;
            rp->userData = ping;
            rp->callback = pingResponse;
        }
    }

    if (err) {
        Dict errDict = Dict_CONST(String_CONST("error"), String_OBJ(String_CONST(err)), NULL);
        Admin_sendMessage(&errDict, txid, ctx->admin);
    }
}

void RouterModule_admin_register(struct RouterModule* module,
                                 struct Admin* admin,
                                 struct Allocator* alloc)
{
    struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
        .admin = admin,
        .allocator = alloc,
        .router = module
    }));
    Identity_set(ctx);

    Admin_registerFunction("RouterModule_lookup", lookup, ctx, true,
        ((struct Admin_FunctionArg[]) {
            { .name = "address", .required = 1, .type = "String" }
        }), admin);
Exemplo n.º 15
0
/** @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);

    #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);

    struct Message* toAngel = Allocator_malloc(tempAlloc, sizeof(struct Message) + w->bytesWritten);
    toAngel->bytes = (uint8_t*) (&toAngel[1]);
    toAngel->length = toAngel->capacity = w->bytesWritten;
    toAngel->padding = 0;
    toAngel->alloc = tempAlloc;
    Bits_memcpy(toAngel->bytes, buff, toAngel->length);

    Log_info(logger, "Writing intial configuration to angel on [%s] config: [%s]",
             asClientPipe->name, buff);
    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.
    char* coreToAngelResponse = "        PADDING         "
        "d"
          "5:error" "4:none"
        "e";

    struct Message* m = &(struct Message) {
        .bytes = (uint8_t*) coreToAngelResponse,
        .length = strlen(coreToAngelResponse),
        .padding = 0,
        .capacity = strlen(coreToAngelResponse)
    };
    Message_shift(m, -24, NULL);
    m = Message_clone(m, tempAlloc);

    Interface_sendMessage(asCoreIface, m);

    // This is angel->client data, it will tell us which port was bound.
    struct Message* angelToClient =
        InterfaceWaiter_waitForData(&asClientPipe->iface, eventBase, tempAlloc, NULL);

    printf("Response from angel to client: [%s]\n", angelToClient->bytes);

    Allocator_free(tempAlloc);

    return;
}
Exemplo n.º 16
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;

    if (argc != 3) {
        Except_raise(eh, -1, "This is internal to cjdns and shouldn't started manually.");
    }

    struct Allocator* alloc = MallocAllocator_new(ALLOCATOR_FAILSAFE);
    struct Log* preLogger = FileWriterLog_new(stderr, alloc);
    struct EventBase* eventBase = EventBase_new(alloc);

    // -------------------- Setup the Pre-Logger ---------------------- //
    struct Log* logger = IndirectLog_new(alloc);
    IndirectLog_set(logger, preLogger);

    // -------------------- Setup the PRNG ---------------------- //
    struct Random* rand = LibuvEntropyProvider_newDefaultRandom(eventBase, logger, eh, alloc);

    // -------------------- Change Canary Value ---------------------- //
    MallocAllocator_setCanary(alloc, (long)Random_int64(rand));
    struct Allocator* tempAlloc = Allocator_child(alloc);


    // The first read inside of getInitialConfig() will begin it waiting.
    struct Pipe* angelPipe = Pipe_named(argv[2], eventBase, eh, alloc);
    angelPipe->logger = logger;
    angelPipe->onClose = angelDied;

    struct Interface* angelIface = FramingInterface_new(65535, &angelPipe->iface, alloc);

    Dict* config = getInitialConfig(angelIface, eventBase, tempAlloc, eh);

    struct Hermes* hermes = Hermes_new(angelIface, eventBase, logger, alloc);

    String* privateKeyHex = Dict_getString(config, String_CONST("privateKey"));
    Dict* adminConf = Dict_getDict(config, String_CONST("admin"));
    String* pass = Dict_getString(adminConf, String_CONST("pass"));
    String* bind = Dict_getString(adminConf, String_CONST("bind"));
    if (!(pass && privateKeyHex && bind)) {
        if (!pass) {
            Except_raise(eh, -1, "Expected 'pass'");
        }
        if (!bind) {
            Except_raise(eh, -1, "Expected 'bind'");
        }
        if (!privateKeyHex) {
            Except_raise(eh, -1, "Expected 'privateKey'");
        }
        Except_raise(eh, -1, "Expected 'pass', 'privateKey' and 'bind' 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 Sockaddr_storage bindAddr;
    if (Sockaddr_parse(bind->bytes, &bindAddr)) {
        Except_raise(eh, -1, "bind address [%s] unparsable", bind->bytes);
    }

    struct AddrInterface* udpAdmin =
        UDPAddrInterface_new(eventBase, &bindAddr.addr, alloc, eh, logger);

    struct Admin* admin = Admin_new(udpAdmin, alloc, logger, eventBase, pass);

    char* boundAddr = Sockaddr_print(udpAdmin->addr, tempAlloc);
    Dict adminResponse = Dict_CONST(
        String_CONST("bind"), String_OBJ(String_CONST(boundAddr)), NULL
    );
    Dict response = Dict_CONST(
        String_CONST("error"), String_OBJ(String_CONST("none")), Dict_CONST(
        String_CONST("admin"), Dict_OBJ(&adminResponse), NULL
    ));
    // This always times out because the angel doesn't respond.
    Hermes_callAngel(&response, angelResponse, NULL, alloc, eh, hermes);

    // --------------------- Setup the Logger --------------------- //
    Dict* logging = Dict_getDict(config, String_CONST("logging"));
    String* logTo = Dict_getString(logging, String_CONST("logTo"));
    if (logTo && String_equals(logTo, String_CONST("stdout"))) {
        // do nothing, continue logging to stdout.
    } else {
        struct Log* adminLogger = AdminLog_registerNew(admin, alloc, rand);
        IndirectLog_set(logger, adminLogger);
        logger = adminLogger;
    }

    // CryptoAuth
    struct Address addr;
    parsePrivateKey(privateKey, &addr, eh);
    struct CryptoAuth* cryptoAuth = CryptoAuth_new(alloc, privateKey, eventBase, logger, rand);

    struct Sockaddr* myAddr = Sockaddr_fromBytes(addr.ip6.bytes, Sockaddr_AF_INET6, alloc);

    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, hermes);

    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,
                                       rand,
                                       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);
    Core_admin_register(myAddr, dt, logger, ipTun, alloc, admin, eventBase);
    Security_admin_register(alloc, logger, admin);
    IpTunnel_admin_register(ipTun, admin, alloc);

    struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
        .allocator = alloc,
        .admin = admin,
        .logger = logger,
        .hermes = hermes
    }));
Exemplo n.º 17
0
static void dumpTable_addEntries(struct Context* ctx,
                                 int i,
                                 int j,
                                 struct List_Item* last,
                                 String* txid)
{
    uint8_t path[20];
    uint8_t ip[40];
    String* pathStr = &(String) { .len = 19, .bytes = (char*)path };
    String* ipStr = &(String) { .len = 39, .bytes = (char*)ip };
    Object* link = Int_OBJ(0xFFFFFFFF);
    Object* version = Int_OBJ(Version_DEFAULT_ASSUMPTION);
    Dict entry = Dict_CONST(
        String_CONST("ip"), String_OBJ(ipStr), Dict_CONST(
        String_CONST("link"), link, Dict_CONST(
        String_CONST("path"), String_OBJ(pathStr), Dict_CONST(
        String_CONST("version"), version, NULL
    ))));

    struct List_Item next = { .next = last, .elem = Dict_OBJ(&entry) };

    if (i >= ctx->store->size || j >= ENTRIES_PER_PAGE) {
        if (i > j) {
            dumpTable_send(ctx, last, (j >= ENTRIES_PER_PAGE), txid);
            return;
        }

        Address_printIp(ip, ctx->store->selfAddress);
        strcpy((char*)path, "0000.0000.0000.0001");
        version->as.number = Version_CURRENT_PROTOCOL;
        dumpTable_send(ctx, &next, (j >= ENTRIES_PER_PAGE), txid);
        return;
    }

    struct Node* n = NodeStore_dumpTable(ctx->store, i);
    link->as.number = n->reach;
    version->as.number = n->version;
    Address_printIp(ip, &n->address);
    AddrTools_printPath(path, n->address.path);

    dumpTable_addEntries(ctx, i + 1, j + 1, &next, txid);
}

static void dumpTable(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
{
    struct Context* ctx = Identity_cast((struct Context*) vcontext);
    int64_t* page = Dict_getInt(args, String_CONST("page"));
    int i = (page) ? *page * ENTRIES_PER_PAGE : 0;
    dumpTable_addEntries(ctx, i, 0, NULL, txid);
}

static bool isOneHop(struct Node_Link* link)
{
    struct EncodingScheme* ps = link->parent->encodingScheme;
    int num = EncodingScheme_getFormNum(ps, link->cannonicalLabel);
    Assert_always(num > -1 && num < ps->count);
    return EncodingScheme_formSize(&ps->forms[num]) == Bits_log2x64(link->cannonicalLabel);
}

static void getLink(Dict* args, void* vcontext, String* txid, struct Allocator* alloc)
{
    struct Context* ctx = Identity_cast((struct Context*) vcontext);

    Dict* ret = Dict_new(alloc);
    Dict* result = Dict_new(alloc);
    Dict_putDict(ret, String_new("result", alloc), result, alloc);
    Dict_putString(ret, String_new("error", alloc), String_new("none", alloc), alloc);

    struct Node_Link* link;

    String* ipStr = Dict_getString(args, String_new("parent", alloc));
    int64_t* linkNum = Dict_getInt(args, String_new("linkNum", alloc));
    uint8_t ip[16];
    if (ipStr->len != 39 || AddrTools_parseIp(ip, ipStr->bytes)) {
        Dict_remove(ret, String_CONST("result"));
        Dict_putString(ret,
                       String_new("error", alloc),
                       String_new("Could not parse ip", alloc),
                       alloc);

    } else if ((link = NodeStore_getLink(ctx->store, ip, *linkNum))) {
        Dict_putInt(result,
                    String_new("inverseLinkEncodingFormNumber", alloc),
                    link->inverseLinkEncodingFormNumber,
                    alloc);
        Dict_putInt(result, String_new("linkState", alloc), link->linkState, alloc);

        Dict_putInt(result, String_new("isOneHop", alloc), isOneHop(link), alloc);

        String* cannonicalLabel = String_newBinary(NULL, 19, alloc);
        AddrTools_printPath(cannonicalLabel->bytes, link->cannonicalLabel);
        Dict_putString(result, String_new("cannonicalLabel", alloc), cannonicalLabel, alloc);

        String* parent = String_newBinary(NULL, 39, alloc);
        AddrTools_printIp(parent->bytes, link->parent->address.ip6.bytes);
        Dict_putString(result, String_new("parent", alloc), parent, alloc);

        String* child = String_newBinary(NULL, 39, alloc);
        AddrTools_printIp(child->bytes, link->child->address.ip6.bytes);
        Dict_putString(result, String_new("child", alloc), child, alloc);
    }

    Admin_sendMessage(ret, txid, ctx->admin);
}
static void getNode(Dict* args, void* vcontext, String* txid, struct Allocator* alloc)
{
    struct Context* ctx = Identity_cast((struct Context*) vcontext);

    Dict* ret = Dict_new(alloc);
    Dict* result = Dict_new(alloc);
    Dict_putDict(ret, String_new("result", alloc), result, alloc);
    Dict_putString(ret, String_new("error", alloc), String_new("none", alloc), alloc);

    // no ipStr specified --> return self-node
    struct Node_Two* node = ctx->store->selfNode;

    String* ipStr = Dict_getString(args, String_new("ip", alloc));
    uint8_t ip[16];
    while (ipStr) {
        if (ipStr->len != 39 || AddrTools_parseIp(ip, ipStr->bytes)) {
            Dict_remove(ret, String_CONST("result"));
            Dict_putString(ret,
                           String_new("error", alloc),
                           String_new("Could not parse ip", alloc),
                           alloc);

        } else if (!(node = NodeStore_getNode2(ctx->store, ip))) {
            // not found
        } else {
            break;
        }

        Admin_sendMessage(ret, txid, ctx->admin);
        return;
    }

    Dict_putInt(result, String_new("protocolVersion", alloc), node->version, alloc);

    String* key = Key_stringify(node->address.key, alloc);
    Dict_putString(result, String_new("key", alloc), key, alloc);

    uint32_t linkCount = NodeStore_linkCount(node);
    Dict_putInt(result, String_new("linkCount", alloc), linkCount, alloc);

    List* encScheme = EncodingScheme_asList(node->encodingScheme, alloc);
    Dict_putList(result, String_new("encodingScheme", alloc), encScheme, alloc);

    Admin_sendMessage(ret, txid, ctx->admin);
}

static void getRouteLabel(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
{
    struct Context* ctx = Identity_cast((struct Context*) vcontext);

    char* err = NULL;

    String* pathToParentS = Dict_getString(args, String_CONST("pathToParent"));
    uint64_t pathToParent;
    if (pathToParentS->len != 19) {
        err = "pathToParent incorrect length";
    } else if (AddrTools_parsePath(&pathToParent, pathToParentS->bytes)) {
        err = "Failed to parse pathToParent";
    }

    String* childAddressS = Dict_getString(args, String_CONST("childAddress"));
    uint8_t childAddress[16];
    if (childAddressS->len != 39) {
        err = "childAddress of incorrect length, must be a 39 character full ipv6 address";
    } else if (AddrTools_parseIp(childAddress, childAddressS->bytes)) {
        err = "Failed to parse childAddress";
    }

    uint64_t label = UINT64_MAX;
    if (!err) {
        label = NodeStore_getRouteLabel(ctx->store, pathToParent, childAddress);
        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);
    }
}

void NodeStore_admin_register(struct NodeStore* nodeStore,
                              struct Admin* admin,
                              struct Allocator* alloc)
{
    struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
        .admin = admin,
        .alloc = alloc,
        .store = nodeStore
    }));
    Identity_set(ctx);

    Admin_registerFunction("NodeStore_dumpTable", dumpTable, ctx, false,
        ((struct Admin_FunctionArg[]) {
            { .name = "page", .required = 1, .type = "Int" },
        }), admin);

    Admin_registerFunction("NodeStore_getLink", getLink, ctx, true,
        ((struct Admin_FunctionArg[]) {
            { .name = "parent", .required = 1, .type = "String" },
            { .name = "linkNum", .required = 1, .type = "Int" },
        }), admin);
Exemplo n.º 18
0
static void beginConnection(Dict* args,
                            void* vcontext,
                            String* txid,
                            struct Allocator* requestAlloc)
{
    struct Context* ctx = vcontext;

    String* password = Dict_getString(args, String_CONST("password"));
    String* publicKey = Dict_getString(args, String_CONST("publicKey"));
    String* address = Dict_getString(args, String_CONST("address"));
    int64_t* interfaceNumber = Dict_getInt(args, String_CONST("interfaceNumber"));
    uint32_t ifNum = (interfaceNumber) ? ((uint32_t) *interfaceNumber) : 0;
    String* peerName = Dict_getString(args, String_CONST("peerName"));
    String* error = NULL;

    Log_debug(ctx->logger, "Peering with [%s]", publicKey->bytes);

    struct Sockaddr_storage ss;
    uint8_t pkBytes[32];
    int ret;
    if (interfaceNumber && *interfaceNumber < 0) {
        error = String_CONST("negative interfaceNumber");

    } else if ((ret = Key_parse(publicKey, pkBytes, NULL))) {
        error = String_CONST(Key_parse_strerror(ret));

    } else if (Sockaddr_parse(address->bytes, &ss)) {
        error = String_CONST("unable to parse ip address and port.");

    } else if (Sockaddr_getFamily(&ss.addr) != Sockaddr_getFamily(ctx->udpIf->addr)) {
        error = String_CONST("different address type than this socket is bound to.");

    } else {

        struct Sockaddr* addr = &ss.addr;
        char* addrPtr = NULL;
        int addrLen = Sockaddr_getAddress(&ss.addr, &addrPtr);
        Assert_true(addrLen > 0);
        struct Allocator* tempAlloc = Allocator_child(ctx->alloc);
        if (Bits_isZero(addrPtr, addrLen)) {
            // unspec'd address, convert to loopback
            if (Sockaddr_getFamily(addr) == Sockaddr_AF_INET) {
                addr = Sockaddr_clone(Sockaddr_LOOPBACK, tempAlloc);
            } else if (Sockaddr_getFamily(addr) == Sockaddr_AF_INET6) {
                addr = Sockaddr_clone(Sockaddr_LOOPBACK6, tempAlloc);
            } else {
                Assert_failure("Sockaddr which is not AF_INET nor AF_INET6");
            }
            Sockaddr_setPort(addr, Sockaddr_getPort(&ss.addr));
        }

        int ret = InterfaceController_bootstrapPeer(
            ctx->ic, ifNum, pkBytes, addr, password, peerName, ctx->alloc);

        Allocator_free(tempAlloc);

        if (ret) {
            switch(ret) {
                case InterfaceController_bootstrapPeer_BAD_IFNUM:
                    error = String_CONST("no such interface for interfaceNumber");
                    break;

                case InterfaceController_bootstrapPeer_BAD_KEY:
                    error = String_CONST("invalid cjdns public key.");
                    break;

                case InterfaceController_bootstrapPeer_OUT_OF_SPACE:
                    error = String_CONST("no more space to register with the switch.");
                    break;

                default:
                    error = String_CONST("unknown error");
                    break;
            }
        } else {
            error = String_CONST("none");
        }
    }

    Dict out = Dict_CONST(String_CONST("error"), String_OBJ(error), NULL);
    Admin_sendMessage(&out, txid, ctx->admin);
}
Exemplo n.º 19
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
            });
Exemplo n.º 20
0
static void dumpTable_addEntries(struct Context* ctx,
                                 int i,
                                 int j,
                                 struct List_Item* last,
                                 String* txid)
{
    uint8_t path[20];
    uint8_t ip[40];
    String* pathStr = &(String) { .len = 19, .bytes = (char*)path };
    String* ipStr = &(String) { .len = 39, .bytes = (char*)ip };
    Object* link = Int_OBJ(0xFFFFFFFF);
    Object* version = Int_OBJ(Version_DEFAULT_ASSUMPTION);
    Dict entry = Dict_CONST(
        String_CONST("ip"), String_OBJ(ipStr), Dict_CONST(
        String_CONST("link"), link, Dict_CONST(
        String_CONST("path"), String_OBJ(pathStr), Dict_CONST(
        String_CONST("version"), version, NULL
    ))));

    struct List_Item next = { .next = last, .elem = Dict_OBJ(&entry) };

    if (i >= ctx->store->size || j >= ENTRIES_PER_PAGE) {
        if (i > j) {
            dumpTable_send(ctx, last, (j >= ENTRIES_PER_PAGE), txid);
            return;
        }

        Address_printIp(ip, ctx->store->selfAddress);
        strcpy((char*)path, "0000.0000.0000.0001");
        dumpTable_send(ctx, &next, (j >= ENTRIES_PER_PAGE), txid);
        return;
    }

    struct Node* n = NodeStore_dumpTable(ctx->store, i);
    link->as.number = n->reach;
    version->as.number = n->version;
    Address_printIp(ip, &n->address);
    AddrTools_printPath(path, n->address.path);

    dumpTable_addEntries(ctx, i + 1, j + 1, &next, txid);
}

static void dumpTable(Dict* args, void* vcontext, String* txid)
{
    struct Context* ctx = Identity_cast((struct Context*) vcontext);
    int64_t* page = Dict_getInt(args, String_CONST("page"));
    int i = (page) ? *page * ENTRIES_PER_PAGE : 0;
    dumpTable_addEntries(ctx, i, 0, NULL, txid);
}

void NodeStore_admin_register(struct NodeStore* nodeStore,
                              struct Admin* admin,
                              struct Allocator* alloc)
{
    struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
        .admin = admin,
        .alloc = alloc,
        .store = nodeStore
    }));
    Identity_set(ctx);

    Admin_registerFunction("NodeStore_dumpTable", dumpTable, ctx, false,
        ((struct Admin_FunctionArg[]) {
            { .name = "page", .required = 1, .type = "Int" },
        }), admin);
}